fix: five dashboard improvements across booking, vehicles, profile, and UI
- fix(auth): guard extractNames() against Authentik sending full name in given_name field (e.g. "Matthias Hochmeister" + family_name "Hochmeister"); detect by checking given_name ends with family_name suffix, fall through to name-splitting so Vorname/Nachname display correctly in Profile - fix(db): add migration 018 to repair broken BEFORE UPDATE triggers on veranstaltungen and veranstaltung_kategorien; old triggers called update_updated_at_column() which references NEW.updated_at, but both tables use aktualisiert_am, causing every category/event edit to fail - feat(booking): open vehicle booking creation to all authenticated users; only dashboard_admin / dashboard_moderator can change the Buchungsart (type select disabled for regular members); edit and cancel still restricted to WRITE_GROUPS - feat(vehicles): VehicleDashboardCard now fetches equipment warnings via equipmentApi.getVehicleWarnings() in parallel and shows an alert when any vehicle equipment is not einsatzbereit - fix(ui): add MuiTextField defaultProps (InputLabelProps.shrink=true) and MuiOutlinedInput notch legend font-size override to theme to eliminate floating-label / border conflict on click Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,9 @@ import {
|
||||
} from '@mui/material';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
import { vehiclesApi } from '../../services/vehicles';
|
||||
import { equipmentApi } from '../../services/equipment';
|
||||
import type { VehicleStats, InspectionAlert } from '../../types/vehicle.types';
|
||||
import type { VehicleEquipmentWarning } from '../../types/equipment.types';
|
||||
|
||||
interface VehicleDashboardCardProps {
|
||||
hideWhenEmpty?: boolean;
|
||||
@@ -22,6 +24,7 @@ const VehicleDashboardCard: React.FC<VehicleDashboardCardProps> = ({
|
||||
}) => {
|
||||
const [stats, setStats] = useState<VehicleStats | null>(null);
|
||||
const [alerts, setAlerts] = useState<InspectionAlert[]>([]);
|
||||
const [equipmentWarnings, setEquipmentWarnings] = useState<VehicleEquipmentWarning[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
@@ -31,13 +34,15 @@ const VehicleDashboardCard: React.FC<VehicleDashboardCardProps> = ({
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const [statsData, alertsData] = await Promise.all([
|
||||
const [statsData, alertsData, warningsData] = await Promise.all([
|
||||
vehiclesApi.getStats(),
|
||||
vehiclesApi.getAlerts(30),
|
||||
equipmentApi.getVehicleWarnings(),
|
||||
]);
|
||||
if (mounted) {
|
||||
setStats(statsData);
|
||||
setAlerts(alertsData);
|
||||
setEquipmentWarnings(warningsData);
|
||||
}
|
||||
} catch {
|
||||
if (mounted) setError('Fahrzeugstatus konnte nicht geladen werden.');
|
||||
@@ -84,7 +89,8 @@ const VehicleDashboardCard: React.FC<VehicleDashboardCardProps> = ({
|
||||
const hasConcerns =
|
||||
overdueAlerts.length > 0 ||
|
||||
upcomingAlerts.length > 0 ||
|
||||
stats.ausserDienst > 0;
|
||||
stats.ausserDienst > 0 ||
|
||||
equipmentWarnings.length > 0;
|
||||
|
||||
const allGood = stats.einsatzbereit === stats.total && !hasConcerns;
|
||||
|
||||
@@ -133,6 +139,14 @@ const VehicleDashboardCard: React.FC<VehicleDashboardCardProps> = ({
|
||||
</Typography>
|
||||
</Alert>
|
||||
)}
|
||||
{equipmentWarnings.length > 0 && (
|
||||
<Alert severity="warning" variant="outlined" sx={{ py: 0.5 }}>
|
||||
<AlertTitle sx={{ fontWeight: 600, mb: 0.5 }}>Ausrüstung nicht verfügbar</AlertTitle>
|
||||
<Typography variant="body2">
|
||||
{equipmentWarnings.length} Ausrüstungsgegenstand{equipmentWarnings.length !== 1 ? 'stände' : 'stand'} nicht einsatzbereit
|
||||
</Typography>
|
||||
</Alert>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user