diff --git a/frontend/src/pages/Checklisten.tsx b/frontend/src/pages/Checklisten.tsx
index bf76b52..b1cce3c 100644
--- a/frontend/src/pages/Checklisten.tsx
+++ b/frontend/src/pages/Checklisten.tsx
@@ -110,18 +110,20 @@ function getAssignmentLabel(v: ChecklistVorlage): string {
return 'Global';
}
-function getDueColor(nextDue?: string | null, intervall?: string | null): 'error' | 'warning' | 'success' | 'default' {
+function getDueColor(nextDue?: string | null, intervall?: string | null, istFaellig?: boolean): 'error' | 'warning' | 'success' | 'default' {
if (!nextDue) return intervall ? 'warning' : 'default'; // has recurrence but never run → warn; no recurrence → neutral
const daysUntil = Math.ceil((new Date(nextDue).getTime() - Date.now()) / 86400000);
- if (daysUntil < 0) return 'error';
+ if (daysUntil < 0) return 'error'; // overdue
+ if (!istFaellig) return 'success'; // done for current period
if (daysUntil <= 3) return 'warning';
- return 'success';
+ return 'default';
}
-function getDueLabel(nextDue?: string | null, intervall?: string | null): string {
+function getDueLabel(nextDue?: string | null, intervall?: string | null, istFaellig?: boolean): string {
if (!nextDue) return intervall ? 'Noch nie ausgeführt' : 'Manuell';
const daysUntil = Math.ceil((new Date(nextDue).getTime() - Date.now()) / 86400000);
if (daysUntil < 0) return `${Math.abs(daysUntil)}d überfällig`;
+ if (!istFaellig) return `Erledigt — nächste in ${daysUntil}d`;
if (daysUntil === 0) return 'Heute fällig';
return `in ${daysUntil}d fällig`;
}
@@ -257,73 +259,9 @@ function OverviewTab({ overview, loading, canExecute, navigate }: OverviewTabPro
return Keine Checklisten zugewiesen;
}
- // Flatten all checklists and detect open checks
- const allChecklists = [
- ...vehicles.flatMap((v) => v.checklists.map((cl) => ({ ...cl, targetName: v.name, targetId: v.id, targetType: 'fahrzeug' as const }))),
- ...equipment.flatMap((e) => e.checklists.map((cl) => ({ ...cl, targetName: e.name, targetId: e.id, targetType: 'ausruestung' as const }))),
- ];
- const openChecks = allChecklists.filter((cl) => cl.ist_faellig);
- const hasOpenChecks = openChecks.length > 0;
-
- // ── Open checks flat list ──
- if (hasOpenChecks) {
- return (
-
-
- Offene Prüfungen ({openChecks.length})
-
-
- {openChecks.map((cl, idx) => {
- const color = getDueColor(cl.next_due, cl.intervall);
- const label = getDueLabel(cl.next_due, cl.intervall);
- const param = cl.ausruestung_id
- ? `ausruestung=${cl.ausruestung_id}`
- : cl.targetType === 'ausruestung'
- ? `ausruestung=${cl.targetId}`
- : `fahrzeug=${cl.targetId}`;
- const primaryText = cl.targetName + ' — ' + cl.vorlage_name + (cl.ausruestung_name ? ` (${cl.ausruestung_name})` : '');
- const secondaryText = cl.letzte_ausfuehrung_am
- ? `Letzte Prüfung: ${formatDate(cl.letzte_ausfuehrung_am)}`
- : 'Noch nie geprüft';
- return (
- canExecute && navigate(`/checklisten/ausfuehrung/new?${param}&vorlage=${cl.vorlage_id}`)}
- sx={{
- py: 1,
- px: 2,
- bgcolor: idx % 2 === 0 ? 'action.hover' : 'transparent',
- cursor: canExecute ? 'pointer' : 'default',
- '&:hover': canExecute ? undefined : { bgcolor: idx % 2 === 0 ? 'action.hover' : 'transparent' },
- }}
- >
-
-
- {canExecute && }
-
- );
- })}
-
-
- );
- }
-
- // ── Normal accordion view (no open checks) ──
-
const renderChecklistRow = (cl: ChecklistOverviewChecklist, itemId: string, type: 'fahrzeug' | 'ausruestung', index: number) => {
- const color = getDueColor(cl.next_due, cl.intervall);
- const label = getDueLabel(cl.next_due, cl.intervall);
+ const color = getDueColor(cl.next_due, cl.intervall, cl.ist_faellig);
+ const label = getDueLabel(cl.next_due, cl.intervall, cl.ist_faellig);
const param = cl.ausruestung_id
? `ausruestung=${cl.ausruestung_id}`
: type === 'fahrzeug'
@@ -358,7 +296,7 @@ function OverviewTab({ overview, loading, canExecute, navigate }: OverviewTabPro
variant="outlined"
sx={{ ml: 1, pointerEvents: 'none' }}
/>
- {canExecute && }
+ {canExecute && cl.ist_faellig && }
);
};
@@ -376,16 +314,16 @@ function OverviewTab({ overview, loading, canExecute, navigate }: OverviewTabPro
{icon} {title}
{items.map((item) => {
- const totalDue = item.checklists.length;
- const hasOverdue = item.checklists.some((cl) => getDueColor(cl.next_due, cl.intervall) === 'error');
- const badgeColor = hasOverdue ? 'error' : item.checklists.some((cl) => getDueColor(cl.next_due, cl.intervall) === 'warning') ? 'warning' : 'default';
+ const openCount = item.checklists.filter((cl) => cl.ist_faellig).length;
+ const hasOverdue = item.checklists.some((cl) => getDueColor(cl.next_due, cl.intervall, cl.ist_faellig) === 'error');
+ const badgeColor = hasOverdue ? 'error' : openCount > 0 ? 'warning' : 'success';
return (
}>
{item.name}
0 ? openCount : undefined}
color={badgeColor as any}
sx={{ ml: 'auto', mr: 2 }}
/>