ui-nyla/src/pages/Dashboard.tsx
2026-01-24 09:58:04 +01:00

139 lines
4.8 KiB
TypeScript

/**
* Dashboard Page
*
* System-Übersicht für den User.
* Zeigt alle verfügbaren Feature-Instanzen als Karten an.
*/
import React from 'react';
import { Link } from 'react-router-dom';
import { useMandates, useFeatureStore } from '../stores/featureStore';
import { getLabel, FEATURE_REGISTRY } from '../types/mandate';
import type { FeatureInstance } from '../types/mandate';
import { FaBriefcase, FaRobot, FaPlay, FaArrowRight } from 'react-icons/fa';
import styles from './Dashboard.module.css';
// =============================================================================
// FEATURE ICONS
// =============================================================================
const FEATURE_ICONS: Record<string, React.ReactNode> = {
trustee: <FaBriefcase size={24} />,
chatbot: <FaRobot size={24} />,
chatworkflow: <FaPlay size={24} />,
};
// =============================================================================
// INSTANCE CARD
// =============================================================================
interface InstanceCardProps {
instance: FeatureInstance;
featureLabel: string;
}
const InstanceCard: React.FC<InstanceCardProps> = ({ instance, featureLabel }) => {
const basePath = `/mandates/${instance.mandateId}/${instance.featureCode}/${instance.id}`;
// Ersten verfügbaren View finden
const featureConfig = FEATURE_REGISTRY[instance.featureCode];
const firstView = featureConfig?.views?.[0];
const targetPath = firstView ? `${basePath}/${firstView.path}` : basePath;
return (
<Link to={targetPath} className={styles.instanceCard}>
<div className={styles.cardIcon}>
{FEATURE_ICONS[instance.featureCode] || <FaBriefcase size={24} />}
</div>
<div className={styles.cardContent}>
<div className={styles.cardHeader}>
<span className={styles.featureLabel}>{featureLabel}</span>
<span className={styles.roleBadge}>{instance.userRoles?.join(', ') || '-'}</span>
</div>
<h3 className={styles.instanceLabel}>{instance.instanceLabel}</h3>
<p className={styles.mandateName}>{instance.mandateName}</p>
</div>
<div className={styles.cardArrow}>
<FaArrowRight />
</div>
</Link>
);
};
// =============================================================================
// EMPTY STATE
// =============================================================================
const EmptyState: React.FC = () => (
<div className={styles.emptyState}>
<div className={styles.emptyIcon}>📋</div>
<h2>Willkommen bei PowerOn</h2>
<p>Du hast aktuell Zugriff auf keine Feature-Instanzen.</p>
<p>Kontaktiere einen Administrator, um Zugriff zu erhalten.</p>
</div>
);
// =============================================================================
// DASHBOARD PAGE
// =============================================================================
export const DashboardPage: React.FC = () => {
const mandates = useMandates();
const { hasAnyInstance, getAllInstances } = useFeatureStore();
// Alle Instanzen sammeln für Übersicht
const allInstances = getAllInstances();
// Gruppiere nach Feature
const instancesByFeature = allInstances.reduce((acc, instance) => {
const featureCode = instance.featureCode;
if (!acc[featureCode]) {
acc[featureCode] = [];
}
acc[featureCode].push(instance);
return acc;
}, {} as Record<string, FeatureInstance[]>);
if (!hasAnyInstance()) {
return <EmptyState />;
}
return (
<div className={styles.dashboard}>
<header className={styles.header}>
<h1>Übersicht</h1>
<p className={styles.subtitle}>
Du hast Zugriff auf {allInstances.length} Feature-Instanz{allInstances.length !== 1 ? 'en' : ''}
in {mandates.length} Mandant{mandates.length !== 1 ? 'en' : ''}.
</p>
</header>
<main className={styles.content}>
{Object.entries(instancesByFeature).map(([featureCode, instances]) => {
const featureConfig = FEATURE_REGISTRY[featureCode];
const featureLabel = featureConfig ? getLabel(featureConfig.label) : featureCode;
return (
<section key={featureCode} className={styles.featureSection}>
<h2 className={styles.sectionTitle}>
{FEATURE_ICONS[featureCode]}
<span>{featureLabel}</span>
</h2>
<div className={styles.instanceGrid}>
{instances.map(instance => (
<InstanceCard
key={instance.id}
instance={instance}
featureLabel={featureLabel}
/>
))}
</div>
</section>
);
})}
</main>
</div>
);
};
export default DashboardPage;