Files
WearPartTracker/app/components/BikeCard.tsx
Denis Urs Rudolph d37676f3c0 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
2025-12-05 22:37:10 +01:00

108 lines
3.2 KiB
TypeScript

'use client'
import { BikeWithParts } from '@/types'
import { useState } from 'react'
import Link from 'next/link'
import { calculateServiceStatus } from '@/lib/utils'
import AlertBadge from './AlertBadge'
interface BikeCardProps {
bike: BikeWithParts
onDelete: () => void
}
export default function BikeCard({ bike, onDelete }: BikeCardProps) {
const [isDeleting, setIsDeleting] = useState(false)
const handleDelete = async () => {
if (!confirm('Möchten Sie dieses Fahrrad wirklich löschen?')) {
return
}
setIsDeleting(true)
try {
const response = await fetch(`/api/bikes/${bike.id}`, {
method: 'DELETE',
})
if (response.ok) {
onDelete()
} else {
alert('Fehler beim Löschen des Fahrrads')
}
} catch (error) {
console.error('Error deleting bike:', error)
alert('Fehler beim Löschen des Fahrrads')
} finally {
setIsDeleting(false)
}
}
const activeParts = bike.wearParts.filter((p) => p.status === 'ACTIVE')
const needsServiceParts = activeParts.filter((part) => {
const serviceStatus = calculateServiceStatus(part, bike.currentMileage)
return serviceStatus.status !== 'OK' || serviceStatus.isOverdue
})
const overdueParts = activeParts.filter((part) => {
const serviceStatus = calculateServiceStatus(part, bike.currentMileage)
return serviceStatus.isOverdue
})
return (
<div className="bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow">
<div className="flex justify-between items-start mb-4">
<div>
<h2 className="text-2xl font-semibold text-gray-900">{bike.name}</h2>
{bike.brand && bike.model && (
<p className="text-gray-600 mt-1">
{bike.brand} {bike.model}
</p>
)}
</div>
{needsServiceParts.length > 0 && (
<AlertBadge
count={needsServiceParts.length}
variant={overdueParts.length > 0 ? 'critical' : 'warning'}
/>
)}
</div>
<div className="mb-4">
<p className="text-sm text-gray-500">
{activeParts.length} aktive Verschleißteile
</p>
<p className="text-sm text-gray-500">
{bike.currentMileage.toLocaleString('de-DE')} km
</p>
{overdueParts.length > 0 && (
<p className="text-sm text-red-600 font-medium mt-1">
{overdueParts.length} überfällig!
</p>
)}
{needsServiceParts.length > 0 && overdueParts.length === 0 && (
<p className="text-sm text-orange-600 font-medium mt-1">
{needsServiceParts.length} benötigen Wartung
</p>
)}
</div>
<div className="flex gap-2 mt-4">
<Link
href={`/bikes/${bike.id}`}
className="flex-1 px-4 py-2 bg-blue-600 text-white text-center rounded-lg hover:bg-blue-700 transition-colors"
>
Details
</Link>
<button
onClick={handleDelete}
disabled={isDeleting}
className="px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 transition-colors disabled:opacity-50"
>
{isDeleting ? 'Löschen...' : 'Löschen'}
</button>
</div>
</div>
)
}