Macht aus dem digitalen Kroki ein echtes taktisches Lagebild: Karte: - Nordpfeil-Overlay (dreht mit dem Karten-Bearing mit) - Windrichtung in 8 Richtungen setzbar (Windrose mit Drift-Pfeil + Label "Wind aus NW"), pro Einsatz gespeichert (Project.windDirection) Export (PNG & PDF): - Nordpfeil, Massstabsbalken und Windanzeige werden in die Karte eingebrannt - PDF zusätzlich: Symbol-Legende (Namen aus /api/icons) + bestehende Kopfzeile (Einsatz/Ort/Zeit/Nr) → fertiges, weitergebbares Krokier-Dokument Technik: - windDirection: Schema + idempotente Migration + Zod-Validierung + Typ - Neue Komponente MapCompass (Nordpfeil/Windrose/Wind-Setzer) - MapView verfolgt Bearing über 'rotate'-Event Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
46 lines
1.5 KiB
TypeScript
46 lines
1.5 KiB
TypeScript
import { z } from 'zod'
|
|
|
|
export const loginSchema = z.object({
|
|
email: z.string().email('Ungültige E-Mail-Adresse'),
|
|
password: z.string().min(1, 'Passwort erforderlich'),
|
|
})
|
|
|
|
export const PROJECT_MODES = ['EINSATZ', 'UEBUNG'] as const
|
|
export type ProjectMode = (typeof PROJECT_MODES)[number]
|
|
|
|
export const projectSchema = z.object({
|
|
title: z.string().min(1, 'Titel erforderlich').max(200, 'Titel zu lang'),
|
|
mode: z.enum(PROJECT_MODES).optional(),
|
|
exerciseEvaluation: z.string().max(10000).optional(),
|
|
location: z.string().optional(),
|
|
description: z.string().optional(),
|
|
einsatzleiter: z.string().optional(),
|
|
journalfuehrer: z.string().optional(),
|
|
// Windrichtung in Grad (0=N, 90=O …), meteorologisch „Wind aus"; null = nicht gesetzt
|
|
windDirection: z.number().int().min(0).max(359).nullable().optional(),
|
|
mapCenter: z.object({
|
|
lng: z.number(),
|
|
lat: z.number(),
|
|
}).optional(),
|
|
mapZoom: z.number().min(1).max(22).optional(),
|
|
})
|
|
|
|
export const featureSchema = z.object({
|
|
type: z.string(),
|
|
geometry: z.object({
|
|
type: z.string(),
|
|
coordinates: z.any(),
|
|
}),
|
|
properties: z.record(z.any()).optional(),
|
|
})
|
|
|
|
export const iconUploadSchema = z.object({
|
|
name: z.string().min(1, 'Name erforderlich').max(100, 'Name zu lang'),
|
|
categoryId: z.string().uuid('Ungültige Kategorie'),
|
|
})
|
|
|
|
export type LoginInput = z.infer<typeof loginSchema>
|
|
export type ProjectInput = z.infer<typeof projectSchema>
|
|
export type FeatureInput = z.infer<typeof featureSchema>
|
|
export type IconUploadInput = z.infer<typeof iconUploadSchema>
|