admin views fixes

This commit is contained in:
ValueOn AG 2026-02-08 13:28:35 +01:00
parent fcb8500104
commit 2fdb09df01
3 changed files with 20 additions and 7 deletions

View file

@ -61,6 +61,7 @@ export const PAGE_ICONS: Record<string, React.ReactNode> = {
'page.admin.user-mandates': <FaUserTag />, 'page.admin.user-mandates': <FaUserTag />,
'page.admin.feature-roles': <FaCube />, 'page.admin.feature-roles': <FaCube />,
'page.admin.feature-instances': <FaCubes />, 'page.admin.feature-instances': <FaCubes />,
'page.admin.featureInstances': <FaCubes />,
'page.admin.feature-users': <FaUsersCog />, 'page.admin.feature-users': <FaUsersCog />,
'page.admin.user-access-overview': <FaUserShield />, 'page.admin.user-access-overview': <FaUserShield />,
'page.admin.billing': <FaMoneyBillAlt />, 'page.admin.billing': <FaMoneyBillAlt />,

View file

@ -7,7 +7,7 @@
* - Konten übersicht * - Konten übersicht
*/ */
import React, { useState, useEffect, useCallback } from 'react'; import React, { useState, useEffect, useCallback, useMemo } from 'react';
import { useBillingAdmin, type BillingSettings, type AccountSummary, type MandateUserSummary } from '../../hooks/useBilling'; import { useBillingAdmin, type BillingSettings, type AccountSummary, type MandateUserSummary } from '../../hooks/useBilling';
import { useAdminMandates } from '../../hooks/useMandates'; import { useAdminMandates } from '../../hooks/useMandates';
import styles from './Billing.module.css'; import styles from './Billing.module.css';
@ -321,16 +321,30 @@ const CreditAdder: React.FC<CreditAdderProps> = ({ settings, accounts, users, on
interface AccountsOverviewProps { interface AccountsOverviewProps {
accounts: AccountSummary[]; accounts: AccountSummary[];
users: MandateUserSummary[];
loading: boolean; loading: boolean;
} }
const AccountsOverview: React.FC<AccountsOverviewProps> = ({ accounts, loading }) => { const AccountsOverview: React.FC<AccountsOverviewProps> = ({ accounts, users, loading }) => {
const formatCurrency = (amount: number) => { const formatCurrency = (amount: number) => {
return new Intl.NumberFormat('de-CH', { return new Intl.NumberFormat('de-CH', {
style: 'currency', style: 'currency',
currency: 'CHF' currency: 'CHF'
}).format(amount); }).format(amount);
}; };
// Build a lookup map: userId -> display name
const _userNameMap = useMemo(() => {
const map = new Map<string, string>();
for (const user of users) {
const displayName = user.displayName
|| [user.firstName, user.lastName].filter(Boolean).join(' ')
|| user.email
|| user.id;
map.set(user.id, displayName);
}
return map;
}, [users]);
if (loading) { if (loading) {
return <div className={styles.loadingPlaceholder}>Lade Konten...</div>; return <div className={styles.loadingPlaceholder}>Lade Konten...</div>;
@ -348,7 +362,7 @@ const AccountsOverview: React.FC<AccountsOverviewProps> = ({ accounts, loading }
<div key={account.id} className={styles.accountCard}> <div key={account.id} className={styles.accountCard}>
<h4>{account.accountType === 'MANDATE' ? 'Mandanten-Konto' : 'Benutzer-Konto'}</h4> <h4>{account.accountType === 'MANDATE' ? 'Mandanten-Konto' : 'Benutzer-Konto'}</h4>
<div className={styles.accountInfo}> <div className={styles.accountInfo}>
{account.userId && <span>User: {account.userId}</span>} {account.userId && <span>User: {_userNameMap.get(account.userId) || account.userId}</span>}
<span>Guthaben: <strong>{formatCurrency(account.balance)}</strong></span> <span>Guthaben: <strong>{formatCurrency(account.balance)}</strong></span>
{account.creditLimit && <span>Limit: {formatCurrency(account.creditLimit)}</span>} {account.creditLimit && <span>Limit: {formatCurrency(account.creditLimit)}</span>}
<span>Status: {account.enabled ? 'Aktiv' : 'Deaktiviert'}</span> <span>Status: {account.enabled ? 'Aktiv' : 'Deaktiviert'}</span>
@ -414,6 +428,7 @@ export const BillingAdmin: React.FC = () => {
<AccountsOverview <AccountsOverview
accounts={accounts} accounts={accounts}
users={users}
loading={loading} loading={loading}
/> />
</> </>

View file

@ -273,7 +273,6 @@ export const BillingDataView: React.FC = () => {
params.month = month; params.month = month;
} }
const response = await api.get('/api/billing/view/statistics', { params }); const response = await api.get('/api/billing/view/statistics', { params });
console.log('📊 View statistics response:', response.data);
setViewStats(response.data); setViewStats(response.data);
} catch (err: any) { } catch (err: any) {
console.error('Failed to load statistics:', err); console.error('Failed to load statistics:', err);
@ -409,12 +408,10 @@ export const BillingDataView: React.FC = () => {
)} )}
</section> </section>
{/* Usage Statistics via FormGeneratorReport */} {/* Usage Statistics via FormGeneratorReport (no period selector - always full year) */}
<section className={styles.section}> <section className={styles.section}>
<FormGeneratorReport <FormGeneratorReport
title="Nutzungsübersicht" title="Nutzungsübersicht"
periodSelector={periodSelectorConfig}
onFilterChange={_handleStatsFilterChange}
loading={statsLoading} loading={statsLoading}
sections={overviewSections} sections={overviewSections}
noDataMessage="Keine Statistiken verfügbar" noDataMessage="Keine Statistiken verfügbar"