Feature: Kilometerstand-Feld für Fahrräder und verbesserte Warnungen

- currentMileage Feld zu Bike-Modell hinzugefügt
- calculateServiceStatus verwendet jetzt aktuellen Kilometerstand des Fahrrads
- Warnungen für überfällige Wartungen (OVERDUE Status)
- Rote Warnung bei überfälligen Teilen
- Kilometerstand wird in BikeDetail und BikeCard angezeigt
- AlertBadge unterstützt jetzt critical Variante
- Verbesserte Statusanzeige mit Überfällig-Hinweis
This commit is contained in:
Denis Urs Rudolph
2025-12-05 22:36:58 +01:00
parent 81edc206e0
commit d37676f3c0
10 changed files with 134 additions and 44 deletions

View File

@@ -1,20 +1,26 @@
import { WearPart, MaintenanceHistory } from '@prisma/client'
export function calculateServiceStatus(
part: WearPart & { maintenanceHistory: MaintenanceHistory[] }
part: WearPart & { maintenanceHistory: MaintenanceHistory[] },
bikeCurrentMileage?: number
): {
status: 'OK' | 'WARNING' | 'CRITICAL'
status: 'OK' | 'WARNING' | 'CRITICAL' | 'OVERDUE'
remainingKm: number
percentageUsed: number
isOverdue: boolean
} {
// Use bike's current mileage if provided, otherwise use latest maintenance mileage
const latestMaintenance = part.maintenanceHistory[0]
const currentMileage = latestMaintenance?.mileage ?? part.installMileage
const currentMileage = bikeCurrentMileage ?? (latestMaintenance?.mileage ?? part.installMileage)
const kmSinceInstall = currentMileage - part.installMileage
const remainingKm = part.serviceInterval - kmSinceInstall
const percentageUsed = (kmSinceInstall / part.serviceInterval) * 100
const isOverdue = remainingKm < 0
let status: 'OK' | 'WARNING' | 'CRITICAL' = 'OK'
if (percentageUsed >= 90) {
let status: 'OK' | 'WARNING' | 'CRITICAL' | 'OVERDUE' = 'OK'
if (isOverdue) {
status = 'OVERDUE'
} else if (percentageUsed >= 90) {
status = 'CRITICAL'
} else if (percentageUsed >= 75) {
status = 'WARNING'
@@ -23,7 +29,8 @@ export function calculateServiceStatus(
return {
status,
remainingKm: Math.max(0, remainingKm),
percentageUsed: Math.min(100, percentageUsed),
percentageUsed: Math.min(100, Math.max(0, percentageUsed)),
isOverdue,
}
}

View File

@@ -66,6 +66,7 @@ export const bikeSchema = z.object({
.refine((val) => val === undefined || val instanceof Date, {
message: 'Ungültiges Datumsformat',
}),
currentMileage: z.number().int().min(0).optional().default(0),
notes: z.string().optional().transform((val) => val?.trim() || undefined),
})