Files
Lageplan/src/lib/validations.ts
Pepe Ziberi 6b6bae9ce1 feat(krokier): Nordpfeil + Windrichtung + Export-Dokument (v1.6.0)
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>
2026-07-22 20:56:11 +02:00

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>