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

@@ -11,12 +11,14 @@ import { useState } from 'react'
interface WearPartListProps {
bikeId: string
parts: (WearPart & { maintenanceHistory: MaintenanceHistory[] })[]
bikeCurrentMileage?: number
onUpdate: () => void
}
export default function WearPartList({
bikeId,
parts,
bikeCurrentMileage,
onUpdate,
}: WearPartListProps) {
const [expandedPart, setExpandedPart] = useState<string | null>(null)
@@ -54,7 +56,7 @@ export default function WearPartList({
return (
<div className="space-y-4">
{parts.map((part) => {
const serviceStatus = calculateServiceStatus(part)
const serviceStatus = calculateServiceStatus(part, bikeCurrentMileage)
const isExpanded = expandedPart === part.id
return (
@@ -68,8 +70,11 @@ export default function WearPartList({
<h3 className="text-xl font-semibold text-gray-900">
{part.type}
</h3>
{serviceStatus.status !== 'OK' && (
<AlertBadge count={1} />
{(serviceStatus.status !== 'OK' || serviceStatus.isOverdue) && (
<AlertBadge
count={1}
variant={serviceStatus.status === 'OVERDUE' ? 'critical' : 'warning'}
/>
)}
<span
className={`px-2 py-1 rounded text-xs font-medium ${
@@ -122,16 +127,25 @@ export default function WearPartList({
? 'text-green-600'
: serviceStatus.status === 'WARNING'
? 'text-orange-600'
: 'text-red-600'
: serviceStatus.status === 'CRITICAL'
? 'text-red-600'
: 'text-red-800 font-bold'
}`}
>
{serviceStatus.status === 'OK'
? 'OK'
: serviceStatus.status === 'WARNING'
? 'Warnung'
: 'Kritisch'}
: serviceStatus.status === 'CRITICAL'
? 'Kritisch'
: 'Überfällig!'}
</span>
</div>
{serviceStatus.isOverdue && (
<div className="mb-2 p-2 bg-red-100 border border-red-300 rounded text-sm text-red-800">
Wartung ist um {Math.abs(serviceStatus.remainingKm).toFixed(0)} km überfällig!
</div>
)}
<div className="w-full bg-gray-200 rounded-full h-2">
<div
className={`h-2 rounded-full ${
@@ -139,13 +153,19 @@ export default function WearPartList({
? 'bg-green-500'
: serviceStatus.status === 'WARNING'
? 'bg-orange-500'
: 'bg-red-500'
: serviceStatus.status === 'CRITICAL'
? 'bg-red-500'
: 'bg-red-700'
}`}
style={{ width: `${serviceStatus.percentageUsed}%` }}
style={{
width: `${Math.min(100, Math.max(0, serviceStatus.percentageUsed))}%`,
}}
/>
</div>
<p className="text-xs text-gray-500 mt-1">
{serviceStatus.remainingKm.toFixed(0)} km bis zur Wartung
{serviceStatus.isOverdue
? `${Math.abs(serviceStatus.remainingKm).toFixed(0)} km überfällig`
: `${serviceStatus.remainingKm.toFixed(0)} km bis zur Wartung`}
</p>
</div>