import { z } from "zod"; import { ACTIVITY_LEVELS, ALLERGENS, CONSENT_KINDS, CUISINES, DIET_PATTERNS, EQUIPMENT, GOAL_TYPES, PRECISION_MODES, RELIGIOUS_RULES, SEXES, } from "@app/shared-types"; /** Hälsoprofil – hanteras separat från hushållsdata (spec §7, §56). */ export const updateHealthProfileInputSchema = z.object({ birthYear: z.number().int().min(1900).max(2030).optional(), sex: z.enum(SEXES).optional(), heightCm: z.number().min(80).max(250).optional(), weightKg: z.number().min(20).max(400).optional(), targetWeightKg: z.number().min(20).max(400).optional(), activityLevel: z.enum(ACTIVITY_LEVELS).optional(), trainingSessionsPerWeek: z.number().int().min(0).max(21).optional(), trainingTypes: z.array(z.string().max(50)).max(10).optional(), }); export type UpdateHealthProfileInput = z.infer; export const updatePreferencesInputSchema = z.object({ primaryGoal: z.enum(GOAL_TYPES).optional(), goals: z.array(z.enum(GOAL_TYPES)).max(11).optional(), dietPattern: z.enum(DIET_PATTERNS).optional(), religiousRule: z.enum(RELIGIOUS_RULES).optional(), allergens: z.array(z.enum(ALLERGENS)).optional(), intolerances: z.array(z.string().max(60)).max(30).optional(), avoidIngredientIds: z.array(z.string().max(80)).max(100).optional(), favoriteCuisines: z.array(z.enum(CUISINES)).max(19).optional(), dislikedDishes: z.array(z.string().max(80)).max(50).optional(), spiceLevelMax: z.number().int().min(0).max(5).optional(), weeklyBudgetMinor: z.number().int().min(0).max(10_000_000).nullable().optional(), maxCookingMinutesWeekday: z.number().int().min(5).max(360).nullable().optional(), equipment: z.array(z.enum(EQUIPMENT)).optional(), defaultPortions: z.number().int().min(1).max(20).optional(), }); export type UpdatePreferencesInput = z.infer; export const updateMeInputSchema = z.object({ displayName: z.string().min(1).max(80).trim().optional(), locale: z.string().min(2).max(10).optional(), precisionMode: z.enum(PRECISION_MODES).optional(), }); export type UpdateMeInput = z.infer; export const consentInputSchema = z.object({ kind: z.enum(CONSENT_KINDS), granted: z.boolean(), }); export type ConsentInput = z.infer; /** Onboarding i ett svep (spec §6): allt är valfritt utom visningsnamnet som redan finns. */ export const onboardingInputSchema = z.object({ healthProfile: updateHealthProfileInputSchema.optional(), preferences: updatePreferencesInputSchema.optional(), precisionMode: z.enum(PRECISION_MODES).default("simple"), householdChoice: z .discriminatedUnion("kind", [ z.object({ kind: z.literal("create"), name: z.string().min(1).max(80) }), z.object({ kind: z.literal("join"), inviteCode: z.string().min(4).max(20) }), z.object({ kind: z.literal("skip") }), ]) .default({ kind: "skip" }), }); export type OnboardingInput = z.infer; /** Progressive onboarding Step A – minimal info for immediate value (FAS 1b). */ export const quickStartInputSchema = z.object({ // Backwards-compatible single goal; if `goals` is omitted we fall back to this. primaryGoal: z.enum(GOAL_TYPES).optional(), // Multi-select goals (new UI). First goal is considered primary. goals: z.array(z.enum(GOAL_TYPES)).max(11).optional(), // Household size for the auto-created household (default 1 if omitted). persons: z.coerce.number().int().min(1).max(50).optional(), precisionMode: z.enum(PRECISION_MODES).default("simple"), }); export type QuickStartInput = z.infer; /** Progressive onboarding status response (FAS 1b). */ export const onboardingStatusSchema = z.object({ step: z.enum(["a", "b", "c"]), onboardingCompleted: z.boolean(), hasHousehold: z.boolean(), hasHealthProfile: z.boolean(), hasPreferences: z.boolean(), }); export type OnboardingStatus = z.infer;