Phases 6-7

This commit is contained in:
Aerilyn Weber 2026-05-14 14:47:23 +09:00
parent 76a516a417
commit 029940b079
111 changed files with 17247 additions and 447 deletions

View file

@ -0,0 +1,75 @@
import { z } from 'zod/v4';
import { ProductCategory, ServingUnit, ProductSource } from '../enums/product.enums.js';
export const NutritionInfoSchema = z.object({
calories: z.number().min(0),
protein: z.number().min(0),
carbs: z.number().min(0),
fat: z.number().min(0),
fiber: z.number().min(0).optional(),
sugar: z.number().min(0).optional(),
sodium: z.number().min(0).optional(),
saturatedFat: z.number().min(0).optional(),
cholesterol: z.number().min(0).optional(),
});
export const CreateProductSchema = z.object({
name: z.string().min(1).max(200).trim(),
brand: z.string().max(200).trim().optional(),
barcode: z
.string()
.regex(/^\d{8,14}$/, 'Barcode must be 8-14 digits')
.optional(),
category: z.nativeEnum(ProductCategory),
servingSize: z.number().positive(),
servingUnit: z.nativeEnum(ServingUnit),
densityGPerMl: z.number().positive().optional(),
nutrition: NutritionInfoSchema,
tags: z.array(z.string().min(1).max(50).trim()).max(20).default([]),
imageUrl: z.url().optional(),
source: z.nativeEnum(ProductSource).default(ProductSource.MANUAL),
});
export const UpdateProductSchema = CreateProductSchema.partial();
export const ProductQuerySchema = z.object({
q: z.string().optional(),
category: z.nativeEnum(ProductCategory).optional(),
tags: z.string().optional(),
barcode: z.string().optional(),
cursor: z.string().optional(),
limit: z.coerce.number().int().min(1).max(100).default(20),
});
export const ProductResponseSchema = z.object({
_id: z.string(),
householdId: z.string(),
name: z.string(),
brand: z.string().optional(),
barcode: z.string().optional(),
category: z.string(),
servingSize: z.number(),
servingUnit: z.string(),
densityGPerMl: z.number().optional(),
nutrition: NutritionInfoSchema,
tags: z.array(z.string()),
imageUrl: z.string().optional(),
source: z.string(),
createdBy: z.string(),
createdAt: z.string(),
updatedAt: z.string(),
deletedAt: z.string().optional(),
});
export const ProductListResponseSchema = z.object({
data: z.array(ProductResponseSchema),
pagination: z.object({
cursor: z.string().nullable(),
hasMore: z.boolean(),
total: z.number().optional(),
}),
});
export type CreateProductInput = z.infer<typeof CreateProductSchema>;
export type UpdateProductInput = z.infer<typeof UpdateProductSchema>;
export type ProductQueryInput = z.infer<typeof ProductQuerySchema>;