Files
WearPartTracker/app/components/StatsCard.tsx
Denis Urs Rudolph de193bc783 Initial commit: Fahrrad Verschleißteile Tracker
- Next.js SPA mit Bun Runtime
- Prisma mit SQLite Datenbank
- Vollständige CRUD-Operationen für Fahrräder, Verschleißteile und Wartungshistorie
- Warnsystem für bevorstehende Wartungen
- Statistik-Features (Gesamtkosten, durchschnittliche Lebensdauer)
- Zod-Validierung für alle API-Requests
- Umfassende Test-Suite (41 Tests)
2025-12-05 22:17:50 +01:00

57 lines
1.7 KiB
TypeScript

'use client'
import { BikeWithParts } from '@/types'
import { calculateTotalCosts, calculateAverageLifespan } from '@/lib/utils'
import { formatCurrency } from '@/lib/utils'
interface StatsCardProps {
bikes: BikeWithParts[]
}
export default function StatsCard({ bikes }: StatsCardProps) {
const allParts = bikes.flatMap((bike) => bike.wearParts)
const totalCosts = calculateTotalCosts(allParts)
const avgLifespan = calculateAverageLifespan(allParts)
const totalBikes = bikes.length
const totalParts = allParts.length
return (
<div className="grid grid-cols-1 md:grid-cols-4 gap-4 mb-8">
<div className="bg-white rounded-lg shadow-md p-6">
<h3 className="text-sm font-medium text-gray-500 mb-2">
Fahrräder
</h3>
<p className="text-3xl font-bold text-gray-900">{totalBikes}</p>
</div>
<div className="bg-white rounded-lg shadow-md p-6">
<h3 className="text-sm font-medium text-gray-500 mb-2">
Verschleißteile
</h3>
<p className="text-3xl font-bold text-gray-900">{totalParts}</p>
</div>
<div className="bg-white rounded-lg shadow-md p-6">
<h3 className="text-sm font-medium text-gray-500 mb-2">
Gesamtkosten
</h3>
<p className="text-3xl font-bold text-gray-900">
{formatCurrency(totalCosts)}
</p>
</div>
<div className="bg-white rounded-lg shadow-md p-6">
<h3 className="text-sm font-medium text-gray-500 mb-2">
Ø Lebensdauer
</h3>
<p className="text-3xl font-bold text-gray-900">
{avgLifespan
? `${Math.round(avgLifespan)} km`
: 'N/A'}
</p>
</div>
</div>
)
}