generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id String @id @default(uuid()) email String @unique passwordHash String name String screenName String? avatarUrl String? unitPreference UnitPreference @default(METRIC) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt games Game[] @relation("GameMaster") teams TeamMember[] captainOf Team? @relation("TeamCaptain") chatMessages ChatMessage[] locationHistory LocationHistory[] } enum UnitPreference { METRIC IMPERIAL } model Game { id String @id @default(uuid()) name String description String? prizeDetails String? visibility Visibility @default(PUBLIC) startDate DateTime? locationLat Float? locationLng Float? searchRadius Float? rules String? randomizeRoutes Boolean @default(false) status GameStatus @default(DRAFT) inviteCode String? @unique createdAt DateTime @default(now()) updatedAt DateTime @updatedAt gameMasterId String gameMaster User @relation("GameMaster", fields: [gameMasterId], references: [id]) routes Route[] teams Team[] chatMessages ChatMessage[] locationHistory LocationHistory[] } model Route { id String @id @default(uuid()) gameId String game Game @relation(fields: [gameId], references: [id], onDelete: Cascade) name String description String? color String @default("#3498db") createdAt DateTime @default(now()) updatedAt DateTime @updatedAt routeLegs RouteLeg[] teamRoutes TeamRoute[] } model RouteLeg { id String @id @default(uuid()) routeId String route Route @relation(fields: [routeId], references: [id], onDelete: Cascade) sequenceNumber Int description String conditionType String @default("photo") conditionDetails String? locationLat Float? locationLng Float? timeLimit Int? } model Team { id String @id @default(uuid()) gameId String game Game @relation(fields: [gameId], references: [id], onDelete: Cascade) name String captainId String? @unique captain User? @relation("TeamCaptain", fields: [captainId], references: [id]) currentLegIndex Int @default(0) status TeamStatus @default(ACTIVE) totalTimeDeduction Int @default(0) lat Float? lng Float? rank Int? createdAt DateTime @default(now()) members TeamMember[] photoSubmissions PhotoSubmission[] chatMessages ChatMessage[] teamRoutes TeamRoute[] } model TeamRoute { id String @id @default(uuid()) teamId String team Team @relation(fields: [teamId], references: [id], onDelete: Cascade) routeId String route Route @relation(fields: [routeId], references: [id]) assignedAt DateTime @default(now()) @@unique([teamId]) } model TeamMember { id String @id @default(uuid()) teamId String team Team @relation(fields: [teamId], references: [id], onDelete: Cascade) userId String user User @relation(fields: [userId], references: [id]) joinedAt DateTime @default(now()) @@unique([teamId, userId]) } model PhotoSubmission { id String @id @default(uuid()) teamId String team Team @relation(fields: [teamId], references: [id], onDelete: Cascade) routeId String routeLegId String photoUrl String approved Boolean @default(false) submittedAt DateTime @default(now()) } model ChatMessage { id String @id @default(uuid()) gameId String game Game @relation(fields: [gameId], references: [id], onDelete: Cascade) teamId String? team Team? @relation(fields: [teamId], references: [id]) userId String user User @relation(fields: [userId], references: [id]) message String sentAt DateTime @default(now()) } model LocationHistory { id String @id @default(uuid()) userId String user User @relation(fields: [userId], references: [id], onDelete: Cascade) gameId String game Game @relation(fields: [gameId], references: [id], onDelete: Cascade) teamId String lat Float lng Float accuracy Float? recordedAt DateTime @default(now()) } enum Visibility { PUBLIC PRIVATE } enum GameStatus { DRAFT LIVE ENDED ARCHIVED } enum TeamStatus { ACTIVE DISQUALIFIED FINISHED }