135 lines
4.5 KiB
TypeScript
135 lines
4.5 KiB
TypeScript
/**
|
|
* Dashboard Page
|
|
*
|
|
* System-Übersicht für den User.
|
|
* Zeigt alle verfügbaren Feature-Instanzen pro Mandant als Karten an.
|
|
* Daten kommen vom Backend via GET /api/navigation.
|
|
*/
|
|
|
|
import React from 'react';
|
|
import { Link } from 'react-router-dom';
|
|
import useNavigation from '../hooks/useNavigation';
|
|
import type { NavigationMandate, MandateFeature, FeatureInstance as NavFeatureInstance } from '../hooks/useNavigation';
|
|
import { getPageIcon } from '../config/pageRegistry';
|
|
import { FaArrowRight, FaBuilding } from 'react-icons/fa';
|
|
import OnboardingAssistant from '../components/OnboardingAssistant';
|
|
import styles from './Dashboard.module.css';
|
|
|
|
import { useLanguage } from '../providers/language/LanguageContext';
|
|
|
|
// =============================================================================
|
|
// INSTANCE CARD
|
|
// =============================================================================
|
|
|
|
interface InstanceCardProps {
|
|
instance: NavFeatureInstance;
|
|
feature: MandateFeature;
|
|
}
|
|
|
|
const InstanceCard: React.FC<InstanceCardProps> = ({ instance, feature }) => {
|
|
// Ersten verfügbaren View-Pfad vom Backend nehmen
|
|
const targetPath = instance.views.length > 0 ? instance.views[0].uiPath : undefined;
|
|
|
|
if (!targetPath) return null;
|
|
|
|
return (
|
|
<Link to={targetPath} className={styles.instanceCard}>
|
|
<div className={styles.cardIcon}>
|
|
{getPageIcon(feature.uiComponent)}
|
|
</div>
|
|
<div className={styles.cardContent}>
|
|
<div className={styles.cardHeader}>
|
|
<span className={styles.featureLabel}>{feature.uiLabel}</span>
|
|
</div>
|
|
<h3 className={styles.instanceLabel}>{instance.uiLabel}</h3>
|
|
</div>
|
|
<div className={styles.cardArrow}>
|
|
<FaArrowRight />
|
|
</div>
|
|
</Link>
|
|
);
|
|
};
|
|
|
|
// =============================================================================
|
|
// DASHBOARD PAGE
|
|
// =============================================================================
|
|
|
|
export const DashboardPage: React.FC = () => {
|
|
const { t } = useLanguage();
|
|
const { dynamicBlock, loading } = useNavigation();
|
|
|
|
// Alle Mandate und deren Features/Instanzen aus der Navigation
|
|
const mandates: NavigationMandate[] = dynamicBlock?.mandates || [];
|
|
|
|
// Gesamtzahl Instanzen und Mandate berechnen
|
|
let totalInstances = 0;
|
|
const totalMandates = mandates.length;
|
|
mandates.forEach(m => m.features.forEach(f => {
|
|
totalInstances += f.instances.length;
|
|
}));
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className={styles.dashboard}>
|
|
<header className={styles.header}>
|
|
<h1>{t('Übersicht')}</h1>
|
|
<p className={styles.subtitle}>{t('Lade')}</p>
|
|
</header>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className={styles.dashboard}>
|
|
<header className={styles.header}>
|
|
<h1>{t('Übersicht')}</h1>
|
|
{totalInstances > 0 && (
|
|
<p className={styles.subtitle}>
|
|
{t('Du hast Zugriff auf {instanceCount} {instanceWord} in {mandateCount} {mandateWord}.', {
|
|
instanceCount: totalInstances,
|
|
instanceWord: totalInstances === 1 ? t('Feature-Instanz') : t('Feature-Instanzen'),
|
|
mandateCount: totalMandates,
|
|
mandateWord: totalMandates === 1 ? t('Mandant') : t('Mandanten'),
|
|
})}
|
|
</p>
|
|
)}
|
|
</header>
|
|
|
|
<OnboardingAssistant />
|
|
|
|
<main className={styles.content}>
|
|
{mandates
|
|
.filter(mandate => mandate.features.some(f => f.instances.length > 0))
|
|
.map(mandate => {
|
|
// Alle Instanzen dieses Mandats sammeln (flach, ohne Feature-Gruppierung)
|
|
const mandateInstances: { instance: NavFeatureInstance; feature: MandateFeature }[] = [];
|
|
for (const feature of mandate.features) {
|
|
for (const instance of feature.instances) {
|
|
mandateInstances.push({ instance, feature });
|
|
}
|
|
}
|
|
|
|
return (
|
|
<section key={mandate.id} className={styles.featureSection}>
|
|
<h2 className={styles.sectionTitle}>
|
|
<FaBuilding />
|
|
<span>{mandate.uiLabel}</span>
|
|
</h2>
|
|
<div className={styles.instanceGrid}>
|
|
{mandateInstances.map(({ instance, feature }) => (
|
|
<InstanceCard
|
|
key={instance.id}
|
|
instance={instance}
|
|
feature={feature}
|
|
/>
|
|
))}
|
|
</div>
|
|
</section>
|
|
);
|
|
})}
|
|
</main>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default DashboardPage;
|