admin views fixes
This commit is contained in:
parent
fcb8500104
commit
2fdb09df01
3 changed files with 20 additions and 7 deletions
|
|
@ -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 />,
|
||||||
|
|
|
||||||
|
|
@ -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}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue