Schema (W0): - Add garments, garment_wears, outfits tables with Drizzle migrations - Drizzle migrations 0001 (garments/wears) and 0002 (outfits) auto-apply on deploy - RLS policies in drizzle/manual/06-wardrobe-rls.sql (apply via superuser in prod) API (W1–W9): - POST /api/garments/upload — direct upload to R2 garments/ prefix with sharp thumbnail - POST /api/garments/tag — vision tagging via LiteLLM, defensive parse, category validated - GET/POST /api/garments — list with composable filters, create - GET/PATCH/DELETE /api/garments/[id] — detail, edit, delete - POST /api/garments/[id]/wear — log worn date - GET /api/garments/outgrowth — pure SQL, explicit size ordering (no lexicographic sort) - GET /api/garments/packing — active garments grouped by category - GET /api/garments/outfit — Open-Meteo weather + deterministic outfit pairing, no LLM - GET/POST /api/garments/outfits + DELETE [id] — saved outfits Pages: - /wardrobe — grid with status/category/size/season filters + outgrowth nudge - /wardrobe/add — 3-step capture→vision→form, size required, batch-friendly - /wardrobe/[id] — detail/edit/status lifecycle + wear history - /wardrobe/packing — packing checklist by category - /wardrobe/outfit — weather-aware suggestions with shown basis - /wardrobe/saved-outfits — view/delete saved combinations Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
39 lines
No EOL
2.4 KiB
SQL
39 lines
No EOL
2.4 KiB
SQL
CREATE TABLE "garment_wears" (
|
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
"family_id" uuid NOT NULL,
|
|
"garment_id" uuid NOT NULL,
|
|
"worn_on" date NOT NULL,
|
|
"memory_id" uuid,
|
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE "garments" (
|
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
"family_id" uuid NOT NULL,
|
|
"child_id" uuid NOT NULL,
|
|
"name" text,
|
|
"category" text NOT NULL,
|
|
"size_label" text NOT NULL,
|
|
"colors" text[] DEFAULT '{}',
|
|
"seasons" text[] DEFAULT '{}',
|
|
"occasion_tags" text[] DEFAULT '{}',
|
|
"image_key" text NOT NULL,
|
|
"thumb_key" text NOT NULL,
|
|
"status" text DEFAULT 'active' NOT NULL,
|
|
"acquired_via" text,
|
|
"gift_from" text,
|
|
"vision_metadata" jsonb,
|
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
--> statement-breakpoint
|
|
ALTER TABLE "garment_wears" ADD CONSTRAINT "garment_wears_family_id_families_id_fk" FOREIGN KEY ("family_id") REFERENCES "public"."families"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
ALTER TABLE "garment_wears" ADD CONSTRAINT "garment_wears_garment_id_garments_id_fk" FOREIGN KEY ("garment_id") REFERENCES "public"."garments"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
ALTER TABLE "garment_wears" ADD CONSTRAINT "garment_wears_memory_id_memories_id_fk" FOREIGN KEY ("memory_id") REFERENCES "public"."memories"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
ALTER TABLE "garments" ADD CONSTRAINT "garments_family_id_families_id_fk" FOREIGN KEY ("family_id") REFERENCES "public"."families"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
ALTER TABLE "garments" ADD CONSTRAINT "garments_child_id_children_id_fk" FOREIGN KEY ("child_id") REFERENCES "public"."children"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
CREATE INDEX "garment_wears_garment_idx" ON "garment_wears" USING btree ("garment_id");--> statement-breakpoint
|
|
CREATE INDEX "garment_wears_family_idx" ON "garment_wears" USING btree ("family_id");--> statement-breakpoint
|
|
CREATE INDEX "garments_family_idx" ON "garments" USING btree ("family_id");--> statement-breakpoint
|
|
CREATE INDEX "garments_child_idx" ON "garments" USING btree ("child_id");--> statement-breakpoint
|
|
CREATE INDEX "garments_status_idx" ON "garments" USING btree ("status"); |