Files
WearPartTracker/lib/validations.ts

98 lines
2.7 KiB
TypeScript
Raw Normal View History

import { z } from 'zod'
export const WearPartType = z.enum([
'CHAIN',
'BRAKE_PADS',
'TIRE',
'CASSETTE',
'CHAINRING',
'DERAILLEUR',
'BRAKE_CABLE',
'SHIFT_CABLE',
'BRAKE_ROTOR',
'PEDAL',
'CRANKSET',
'BOTTOM_BRACKET',
'HEADSET',
'WHEEL',
'HUB',
'SPOKE',
'OTHER',
])
export const WearPartStatus = z.enum([
'ACTIVE',
'NEEDS_SERVICE',
'REPLACED',
'INACTIVE',
])
export const MaintenanceAction = z.enum([
'INSTALL',
'REPLACE',
'SERVICE',
'CHECK',
'ADJUST',
])
export const bikeSchema = z.object({
name: z
.string()
.min(1, 'Name ist erforderlich')
.trim()
.min(1, 'Name darf nicht nur aus Leerzeichen bestehen'),
brand: z.string().optional().transform((val) => val?.trim() || undefined),
model: z.string().optional().transform((val) => val?.trim() || undefined),
purchaseDate: z
.union([z.date(), z.string()])
.optional()
.transform((val) => {
if (!val || val === undefined) return undefined
if (val instanceof Date) {
return isNaN(val.getTime()) ? undefined : val
}
if (typeof val === 'string') {
// Handle YYYY-MM-DD format (from HTML date input)
if (/^\d{4}-\d{2}-\d{2}$/.test(val)) {
const date = new Date(val + 'T00:00:00.000Z')
return isNaN(date.getTime()) ? undefined : date
}
// Handle ISO datetime format or any other parseable date string
const date = new Date(val)
return isNaN(date.getTime()) ? undefined : date
}
return undefined
})
.refine((val) => val === undefined || val instanceof Date, {
message: 'Ungültiges Datumsformat',
}),
notes: z.string().optional().transform((val) => val?.trim() || undefined),
})
export const wearPartSchema = z.object({
bikeId: z.string().min(1, 'Fahrrad-ID ist erforderlich'),
type: WearPartType,
brand: z.string().optional(),
model: z.string().optional(),
installDate: z.string().datetime().or(z.date()),
installMileage: z.number().int().min(0).default(0),
serviceInterval: z.number().int().min(1, 'Service-Intervall muss mindestens 1 km sein'),
status: WearPartStatus.default('ACTIVE'),
cost: z.number().positive().optional(),
notes: z.string().optional(),
})
export const maintenanceHistorySchema = z.object({
wearPartId: z.string().min(1, 'Verschleißteil-ID ist erforderlich'),
date: z.string().datetime().or(z.date()),
mileage: z.number().int().min(0),
action: MaintenanceAction,
notes: z.string().optional(),
cost: z.number().positive().optional(),
})
export type BikeInput = z.infer<typeof bikeSchema>
export type WearPartInput = z.infer<typeof wearPartSchema>
export type MaintenanceHistoryInput = z.infer<typeof maintenanceHistorySchema>