Files
Cibello-app/packages/validation/src/meals.ts
T
2026-08-05 19:21:11 +07:00

71 lines
2.6 KiB
TypeScript

import { z } from "zod";
import { MEAL_LOG_SOURCES, MEAL_TYPES } from "@app/shared-types";
import { dateStringSchema, quantitySchema, unitSchema, uuidSchema } from "./common.js";
const nutritionValuesInputSchema = z.object({
kcal: z.number().min(0).max(20000),
proteinG: z.number().min(0).max(1000).default(0),
carbsG: z.number().min(0).max(2000).default(0),
fatG: z.number().min(0).max(1000).default(0),
saturatedFatG: z.number().min(0).max(500).default(0),
fiberG: z.number().min(0).max(300).default(0),
sugarG: z.number().min(0).max(1000).default(0),
saltG: z.number().min(0).max(100).default(0),
});
/**
* Måltidsloggning (spec §23). Näringsvärden får ALDRIG hittas på av AI:
* de kommer från recept (deterministiskt), produkt/streckkod, eller
* användarens egen inmatning. Tallriksfoto ger intervall som användaren bekräftar.
*/
export const logMealInputSchema = z.object({
date: dateStringSchema,
mealType: z.enum(MEAL_TYPES),
source: z.enum(MEAL_LOG_SOURCES),
titleSv: z.string().min(1).max(150),
recipeId: uuidSchema.optional(),
mealBoxId: uuidSchema.optional(),
scanJobId: uuidSchema.optional(),
portionFraction: z.number().min(0.1).max(5).default(1),
/** Vid produkt/fritext: ange mängd + per-100-värden eller direkta värden. */
items: z
.array(
z.object({
displayName: z.string().min(1).max(120),
canonicalIngredientId: z.string().max(80).optional(),
productId: uuidSchema.optional(),
quantity: quantitySchema.optional(),
unit: unitSchema.optional(),
nutrition: nutritionValuesInputSchema.optional(),
}),
)
.max(30)
.default([]),
/** Direkta värden när användaren själv anger, eller bekräftat foto-intervall. */
nutritionOverride: nutritionValuesInputSchema.optional(),
});
export type LogMealInput = z.infer<typeof logMealInputSchema>;
export const dayQuerySchema = z.object({
date: dateStringSchema,
});
export const createMealBoxInputSchema = z.object({
recipeId: uuidSchema.optional(),
titleSv: z.string().min(1).max(150),
portions: z.number().int().min(1).max(24),
storageLocationId: uuidSchema,
frozen: z.boolean().default(false),
cookedAt: dateStringSchema.optional(),
reservedForUserId: uuidSchema.optional(),
});
export type CreateMealBoxInput = z.infer<typeof createMealBoxInputSchema>;
export const consumeMealBoxInputSchema = z.object({
portions: z.number().int().min(1).max(24).default(1),
logAsMeal: z.boolean().default(true),
mealType: z.enum(MEAL_TYPES).default("lunch"),
date: dateStringSchema.optional(),
});
export type ConsumeMealBoxInput = z.infer<typeof consumeMealBoxInputSchema>;