// This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { provider = "prisma-client-js" } datasource db { provider = "sqlite" url = env("DATABASE_URL") } model User { id String @id @default(cuid()) email String @unique passwordHash String name String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations sessions Session[] exercises Exercise[] workouts Workout[] programs Program[] equipment Equipment[] contentItems ContentItem[] aiSuggestions AISuggestion[] userPreferences UserPreferences? @@index([email]) } model Session { id String @id @default(cuid()) userId String token String @unique expiresAt DateTime createdAt DateTime @default(now()) // Relations user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([userId]) @@index([token]) } model Exercise { id String @id @default(cuid()) userId String name String description String? muscleGroups String // JSON array stored as text: ["chest", "triceps"] type String // barbell, dumbbell, machine, cable, bodyweight, cardio, kettlebell, other inputFields String @default("[\"sets\",\"reps\",\"weight\"]") // JSON array: sets, reps, weight, duration, distance, calories defaultWeightUnit String? // null = use user pref; "kg" for kettlebells, etc. isCustom Boolean @default(false) createdAt DateTime @default(now()) // Relations user User @relation(fields: [userId], references: [id], onDelete: Cascade) setLogs SetLog[] programExercises ProgramExercise[] @@unique([userId, name]) @@index([userId]) @@index([type]) } model Workout { id String @id @default(cuid()) userId String date DateTime name String? notes String? durationMinutes Int? difficulty Int? // 1-10 scale caloriesBurned Int? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations user User @relation(fields: [userId], references: [id], onDelete: Cascade) setLogs SetLog[] @@index([userId]) @@index([date]) } model SetLog { id String @id @default(cuid()) workoutId String exerciseId String setNumber Int reps Int? weight Float? weightUnit String @default("lbs") rpe Int? // Rate of Perceived Exertion (1-10) durationSeconds Int? // for timed exercises (assault bike, jump rope, planks) distance Float? // for distance-based exercises distanceUnit String? // "mi", "km", "m" calories Int? // for cardio machines that report calories notes String? createdAt DateTime @default(now()) // Relations workout Workout @relation(fields: [workoutId], references: [id], onDelete: Cascade) exercise Exercise @relation(fields: [exerciseId], references: [id], onDelete: Cascade) @@index([workoutId]) @@index([exerciseId]) } model Program { id String @id @default(cuid()) userId String name String description String? type String // hypertrophy, strength, power, endurance, recovery durationWeeks Int startDate DateTime endDate DateTime? isActive Boolean @default(false) aiGenerated Boolean @default(false) aiNotes String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations user User @relation(fields: [userId], references: [id], onDelete: Cascade) weeks ProgramWeek[] aiSuggestions AISuggestion[] @@index([userId]) @@index([isActive]) } model ProgramWeek { id String @id @default(cuid()) programId String weekNumber Int phase String? description String? createdAt DateTime @default(now()) // Relations program Program @relation(fields: [programId], references: [id], onDelete: Cascade) days ProgramDay[] @@unique([programId, weekNumber]) @@index([programId]) } model ProgramDay { id String @id @default(cuid()) weekId String dayOfWeek Int // 0-6 (Sunday-Saturday) name String? description String? createdAt DateTime @default(now()) // Relations week ProgramWeek @relation(fields: [weekId], references: [id], onDelete: Cascade) exercises ProgramExercise[] @@unique([weekId, dayOfWeek]) @@index([weekId]) } model ProgramExercise { id String @id @default(cuid()) dayId String exerciseId String order Int sets Int? repsMin Int? repsMax Int? rpe Int? restSeconds Int? notes String? createdAt DateTime @default(now()) // Relations day ProgramDay @relation(fields: [dayId], references: [id], onDelete: Cascade) exercise Exercise @relation(fields: [exerciseId], references: [id], onDelete: Cascade) @@unique([dayId, order]) @@index([dayId]) @@index([exerciseId]) } model Equipment { id String @id @default(cuid()) userId String name String type String // rack, barbell, dumbbell, plate, bench, etc. quantity Int weight Float? // for plates, dumbbells, etc. weightUnit String @default("lbs") notes String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@unique([userId, name]) @@index([userId]) } model ContentItem { id String @id @default(cuid()) userId String title String source String // pdf_upload, youtube, manual_entry sourceUrl String? content String? fullText String? // Full searchable text createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations user User @relation(fields: [userId], references: [id], onDelete: Cascade) chunks ContentChunk[] @@index([userId]) @@index([source]) } model ContentChunk { id String @id @default(cuid()) contentItemId String chunkNumber Int text String pageNumber Int? timestamp Float? // For video timestamps createdAt DateTime @default(now()) // Relations contentItem ContentItem @relation(fields: [contentItemId], references: [id], onDelete: Cascade) @@index([contentItemId]) } model AISuggestion { id String @id @default(cuid()) userId String programId String? type String // exercise_recommendation, workout_adjustment, program_optimization, etc. suggestion String priority Int // 1-5 scale accepted Boolean? source String // rules, claude metadata String? // JSON metadata createdAt DateTime @default(now()) // Relations user User @relation(fields: [userId], references: [id], onDelete: Cascade) program Program? @relation(fields: [programId], references: [id], onDelete: SetNull) @@index([userId]) @@index([programId]) @@index([type]) } model UserPreferences { id String @id @default(cuid()) userId String @unique theme String @default("system") // light, dark, system defaultWeightUnit String @default("lbs") defaultRestSeconds Int @default(90) enableClaudeAI Boolean @default(false) claudeApiKey String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([userId]) }