rework vehicle handling

This commit is contained in:
Matthias Hochmeister
2026-02-28 13:34:16 +01:00
parent 84cf505511
commit 41fc41bee4
13 changed files with 931 additions and 1228 deletions

View File

@@ -4,15 +4,12 @@ import {
AlertTitle,
Box,
CircularProgress,
Collapse,
Link,
Typography,
} from '@mui/material';
import { Link as RouterLink } from 'react-router-dom';
import { vehiclesApi } from '../../services/vehicles';
import { InspectionAlert, PruefungArtLabel, PruefungArt } from '../../types/vehicle.types';
// ── Helpers ───────────────────────────────────────────────────────────────────
import { InspectionAlert, InspectionAlertType } from '../../types/vehicle.types';
function formatDate(iso: string): string {
return new Date(iso).toLocaleDateString('de-DE', {
@@ -22,6 +19,10 @@ function formatDate(iso: string): string {
});
}
function alertTypeLabel(type: InspectionAlertType): string {
return type === '57a' ? '§57a Periodische Prüfung' : 'Nächste Wartung / Service';
}
type Urgency = 'overdue' | 'urgent' | 'warning';
function getUrgency(tage: number): Urgency {
@@ -36,12 +37,8 @@ const URGENCY_CONFIG: Record<Urgency, { severity: 'error' | 'warning'; label: st
warning: { severity: 'warning', label: 'Fällig in Kürze (≤ 30 Tage)' },
};
// ── Component ─────────────────────────────────────────────────────────────────
interface InspectionAlertsProps {
/** How many days ahead to fetch — default 30 */
daysAhead?: number;
/** Collapse into a single banner if no alerts */
hideWhenEmpty?: boolean;
}
@@ -55,7 +52,6 @@ const InspectionAlerts: React.FC<InspectionAlertsProps> = ({
useEffect(() => {
let mounted = true;
const fetchAlerts = async () => {
try {
setLoading(true);
@@ -68,7 +64,6 @@ const InspectionAlerts: React.FC<InspectionAlertsProps> = ({
if (mounted) setLoading(false);
}
};
fetchAlerts();
return () => { mounted = false; };
}, [daysAhead]);
@@ -92,12 +87,11 @@ const InspectionAlerts: React.FC<InspectionAlertsProps> = ({
if (hideWhenEmpty) return null;
return (
<Alert severity="success">
Alle Prüfungsfristen sind aktuell. Keine Fälligkeiten in den nächsten {daysAhead} Tagen.
Alle Fristen sind aktuell. Keine Fälligkeiten in den nächsten {daysAhead} Tagen.
</Alert>
);
}
// Group by urgency
const overdue = alerts.filter((a) => a.tage < 0);
const urgent = alerts.filter((a) => a.tage >= 0 && a.tage <= 14);
const warning = alerts.filter((a) => a.tage > 14);
@@ -117,35 +111,37 @@ const InspectionAlerts: React.FC<InspectionAlertsProps> = ({
<AlertTitle sx={{ fontWeight: 600 }}>{label}</AlertTitle>
<Box component="ul" sx={{ m: 0, pl: 2 }}>
{items.map((alert) => {
const artLabel = PruefungArtLabel[alert.pruefungArt as PruefungArt] ?? alert.pruefungArt;
const dateStr = formatDate(alert.faelligAm);
const tageText = alert.tage < 0
const typeLabel = alertTypeLabel(alert.type);
const dateStr = formatDate(alert.faelligAm);
const tageText = alert.tage < 0
? `seit ${Math.abs(alert.tage)} Tag${Math.abs(alert.tage) === 1 ? '' : 'en'} überfällig`
: alert.tage === 0
? 'heute fällig'
: `fällig in ${alert.tage} Tag${alert.tage === 1 ? '' : 'en'}`;
return (
<Collapse key={alert.pruefungId} in timeout="auto">
<Box component="li" sx={{ mb: 0.5 }}>
<Link
component={RouterLink}
to={`/fahrzeuge/${alert.fahrzeugId}`}
color="inherit"
underline="hover"
sx={{ fontWeight: 500 }}
>
{alert.bezeichnung}
{alert.kurzname ? ` (${alert.kurzname})` : ''}
</Link>
{' — '}
<strong>{artLabel}</strong>
{' '}
<Typography component="span" variant="body2">
{tageText} ({dateStr})
</Typography>
</Box>
</Collapse>
<Box
key={`${alert.fahrzeugId}-${alert.type}`}
component="li"
sx={{ mb: 0.5 }}
>
<Link
component={RouterLink}
to={`/fahrzeuge/${alert.fahrzeugId}`}
color="inherit"
underline="hover"
sx={{ fontWeight: 500 }}
>
{alert.bezeichnung}
{alert.kurzname ? ` (${alert.kurzname})` : ''}
</Link>
{' — '}
<strong>{typeLabel}</strong>
{' '}
<Typography component="span" variant="body2">
{tageText} ({dateStr})
</Typography>
</Box>
);
})}
</Box>