139 lines
4.8 KiB
TypeScript
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;
|