diff --git a/packages/db/src/seed.ts b/packages/db/src/seed.ts index 79164fa..d2d274b 100644 --- a/packages/db/src/seed.ts +++ b/packages/db/src/seed.ts @@ -20,6 +20,7 @@ import postgres from "postgres"; import { drizzle } from "drizzle-orm/postgres-js"; import { eq, and, sql } from "drizzle-orm"; import * as schema from "./schema.js"; +import type { MedicalAlert } from "@groombook/types"; // ── Seed profile configuration ───────────────────────────────────────────── @@ -243,6 +244,55 @@ const groomingNotes = [ "Previous clipper burn — be gentle on belly", ]; +// ── Extended pet profile pools ───────────────────────────────────────────────── + +const temperamentFlagPool: string[] = [ + "friendly", + "anxious-with-strangers", + "good-with-kids", + "leash-reactive", + "vocal", + "high-energy", + "calm-on-table", + "treat-motivated", +]; + +const medicalAlertPool: MedicalAlert[] = [ + { id: "", type: "allergies", description: "Seasonal allergies — monitor skin", severity: "low" }, + { id: "", type: "allergies", description: "Chicken allergy — avoid poultry-based treats", severity: "high" }, + { id: "", type: "joint", description: "Hip dysplasia — handle with care", severity: "medium" }, + { id: "", type: "joint", description: "Arthritis — anti-inflammatory medication on file", severity: "medium" }, + { id: "", type: "dental", description: "Dental disease — extractions in history", severity: "medium" }, + { id: "", type: "dental", description: "Baby teeth retained — vet monitor", severity: "low" }, + { id: "", type: "heart", description: "Heart murmur grade II — avoid stress", severity: "high" }, + { id: "", type: "heart", description: "Murmur cleared by vet last year", severity: "low" }, + { id: "", type: "other", description: "Eye ulcer history — be careful around face", severity: "medium" }, + { id: "", type: "other", description: "Seizure history — avoid flashing lights", severity: "high" }, + { id: "", type: "other", description: "Luxating patella — short walks only", severity: "medium" }, + { id: "", type: "other", description: "Ear infections — dry thoroughly after bath", severity: "low" }, +]; + +const preferredCutPool: string[] = [ + "Puppy Cut", + "Teddy Bear Cut", + "Lion Cut", + "Breed Standard", + "Summer Shave", + "Kennel Cut", + "Lamb Cut", + "Continental Clip", + "Sporting Clip", + "Sanitary Trim", + "Face & Feet Trim", + "Full Groom", +]; + +type CoatType = schema.coatTypeEnum.enumValues[number]; +type PetSizeCategory = schema.petSizeCategoryEnum.enumValues[number]; + +const coatTypePool: CoatType[] = ["short", "medium", "long", "double", "wire", "silky", "curly", "hairless"]; +const petSizeCategoryPool: PetSizeCategory[] = ["small", "medium", "large", "extra_large"]; + const appointmentNotes = [ null, null, null, null, "Client requested extra brushing", @@ -853,6 +903,18 @@ async function seed() { specialCareNotes: rand() < 0.1 ? "Vet clearance required before grooming" : null, customFields: {}, image: petIndex < 250 ? pick(puggleImages) : pick(demoPetImages), + temperamentScore: randInt(1, 5), + temperamentFlags: pickN(temperamentFlagPool, randInt(1, 3)), + medicalAlerts: (() => { + if (rand() < 0.3) { + const count = rand() < 0.7 ? 1 : 2; + return pickN(medicalAlertPool, count).map((a) => ({ ...a, id: uuid() })); + } + return []; + })(), + preferredCuts: pickN(preferredCutPool, randInt(1, 2)), + coatType: pick(coatTypePool), + petSizeCategory: pick(petSizeCategoryPool), }); petRecords.push({ id: petId, clientId }); @@ -888,6 +950,12 @@ async function seed() { specialCareNotes: pet.specialCareNotes, customFields: pet.customFields, image: pet.image, + temperamentScore: pet.temperamentScore, + temperamentFlags: pet.temperamentFlags, + medicalAlerts: pet.medicalAlerts, + preferredCuts: pet.preferredCuts, + coatType: pet.coatType, + petSizeCategory: pet.petSizeCategory, }, }); } @@ -922,8 +990,52 @@ async function seed() { .values({ id: uc.id, name: uc.name, email: uc.email, phone: uc.phone, address: uc.address }) .onConflictDoUpdate({ target: schema.clients.id, set: { name: uc.name, email: uc.email, phone: uc.phone, address: uc.address } }); await db.insert(schema.pets) - .values({ id: uc.petId, clientId: uc.id, name: uc.petName, species: "Dog", breed: uc.petBreed, weightKg: "25.00", dateOfBirth: new Date("2021-03-15T00:00:00Z"), image: pick(demoPetImages) }) - .onConflictDoUpdate({ target: schema.pets.id, set: { clientId: uc.id, name: uc.petName, species: "Dog", breed: uc.petBreed, weightKg: "25.00", dateOfBirth: new Date("2021-03-15T00:00:00Z"), image: pick(demoPetImages) } }); + .values({ + id: uc.petId, + clientId: uc.id, + name: uc.petName, + species: "Dog", + breed: uc.petBreed, + weightKg: "25.00", + dateOfBirth: new Date("2021-03-15T00:00:00Z"), + image: pick(demoPetImages), + temperamentScore: randInt(1, 5), + temperamentFlags: pickN(temperamentFlagPool, randInt(1, 3)), + medicalAlerts: (() => { + if (rand() < 0.3) { + const count = rand() < 0.7 ? 1 : 2; + return pickN(medicalAlertPool, count).map((a) => ({ ...a, id: uuid() })); + } + return []; + })(), + preferredCuts: pickN(preferredCutPool, randInt(1, 2)), + coatType: pick(coatTypePool), + petSizeCategory: pick(petSizeCategoryPool), + }) + .onConflictDoUpdate({ + target: schema.pets.id, + set: { + clientId: uc.id, + name: uc.petName, + species: "Dog", + breed: uc.petBreed, + weightKg: "25.00", + dateOfBirth: new Date("2021-03-15T00:00:00Z"), + image: pick(demoPetImages), + temperamentScore: randInt(1, 5), + temperamentFlags: pickN(temperamentFlagPool, randInt(1, 3)), + medicalAlerts: (() => { + if (rand() < 0.3) { + const count = rand() < 0.7 ? 1 : 2; + return pickN(medicalAlertPool, count).map((a) => ({ ...a, id: uuid() })); + } + return []; + })(), + preferredCuts: pickN(preferredCutPool, randInt(1, 2)), + coatType: pick(coatTypePool), + petSizeCategory: pick(petSizeCategoryPool), + }, + }); // Create one completed appointment for this client const apptId = uuid(); const svcIdx = 0;