import { sqliteTable, text, integer, real } from "drizzle-orm/sqlite-core"; export const users = sqliteTable("users", { id: text("id").primaryKey(), email: text("email").notNull().unique(), firstName: text("first_name").notNull(), lastName: text("last_name").notNull(), password: text("password"), // Optional - Clerk handles authentication role: text("role", { enum: ["superAdmin", "admin", "trainer", "client"] }) .notNull() .default("client"), phone: text("phone"), createdAt: integer("created_at", { mode: "timestamp" }) .notNull() .$defaultFn(() => new Date()), updatedAt: integer("updated_at", { mode: "timestamp" }) .notNull() .$defaultFn(() => new Date()), }); export const clients = sqliteTable("clients", { id: text("id").primaryKey(), userId: text("user_id") .notNull() .references(() => users.id, { onDelete: "cascade" }), membershipType: text("membership_type", { enum: ["basic", "premium", "vip"] }) .notNull() .default("basic"), membershipStatus: text("membership_status", { enum: ["active", "inactive", "suspended"], }) .notNull() .default("active"), joinDate: integer("join_date", { mode: "timestamp" }) .notNull() .$defaultFn(() => new Date()), lastVisit: integer("last_visit", { mode: "timestamp" }), emergencyContactName: text("emergency_contact_name"), emergencyContactPhone: text("emergency_contact_phone"), emergencyContactRelationship: text("emergency_contact_relationship"), createdAt: integer("created_at", { mode: "timestamp" }) .notNull() .$defaultFn(() => new Date()), updatedAt: integer("updated_at", { mode: "timestamp" }) .notNull() .$defaultFn(() => new Date()), }); export const payments = sqliteTable("payments", { id: text("id").primaryKey(), clientId: text("client_id") .notNull() .references(() => clients.id, { onDelete: "cascade" }), amount: real("amount").notNull(), currency: text("currency").notNull().default("USD"), status: text("status", { enum: ["pending", "completed", "failed", "refunded"], }) .notNull() .default("pending"), paymentMethod: text("payment_method", { enum: ["cash", "card", "bank_transfer"], }).notNull(), dueDate: integer("due_date", { mode: "timestamp" }).notNull(), paidAt: integer("paid_at", { mode: "timestamp" }), description: text("description").notNull(), createdAt: integer("created_at", { mode: "timestamp" }) .notNull() .$defaultFn(() => new Date()), updatedAt: integer("updated_at", { mode: "timestamp" }) .notNull() .$defaultFn(() => new Date()), }); export const attendance = sqliteTable("attendance", { id: text("id").primaryKey(), clientId: text("client_id") .notNull() .references(() => clients.id, { onDelete: "cascade" }), checkInTime: integer("check_in_time", { mode: "timestamp" }).notNull(), checkOutTime: integer("check_out_time", { mode: "timestamp" }), type: text("type", { enum: ["gym", "class", "personal_training"] }) .notNull() .default("gym"), notes: text("notes"), createdAt: integer("created_at", { mode: "timestamp" }) .notNull() .$defaultFn(() => new Date()), }); export const notifications = sqliteTable("notifications", { id: text("id").primaryKey(), userId: text("user_id") .notNull() .references(() => users.id, { onDelete: "cascade" }), title: text("title").notNull(), message: text("message").notNull(), type: text("type", { enum: ["payment_reminder", "attendance", "promotion", "system"], }).notNull(), read: integer("read", { mode: "boolean" }).notNull().default(false), createdAt: integer("created_at", { mode: "timestamp" }) .notNull() .$defaultFn(() => new Date()), }); export const fitnessProfiles = sqliteTable("fitness_profiles", { id: text("id").primaryKey(), userId: text("user_id") .notNull() .unique() .references(() => users.id, { onDelete: "cascade" }), height: real("height"), // in cm weight: real("weight"), // in kg age: integer("age"), gender: text("gender", { enum: ["male", "female", "other", "prefer_not_to_say"], }), fitnessGoal: text("fitness_goal", { enum: [ "weight_loss", "muscle_gain", "endurance", "flexibility", "general_fitness", ], }), activityLevel: text("activity_level", { enum: [ "sedentary", "lightly_active", "moderately_active", "very_active", "extremely_active", ], }), medicalConditions: text("medical_conditions"), allergies: text("allergies"), injuries: text("injuries"), createdAt: integer("created_at", { mode: "timestamp" }) .notNull() .$defaultFn(() => new Date()), updatedAt: integer("updated_at", { mode: "timestamp" }) .notNull() .$defaultFn(() => new Date()), }); export const fitnessGoals = sqliteTable("fitness_goals", { id: text("id").primaryKey(), userId: text("user_id") .notNull() .references(() => users.id, { onDelete: "cascade" }), fitnessProfileId: text("fitness_profile_id").references( () => fitnessProfiles.id, { onDelete: "cascade" } ), // Goal details goalType: text("goal_type", { enum: [ "weight_target", "strength_milestone", "endurance_target", "flexibility_goal", "habit_building", "custom", ], }).notNull(), title: text("title").notNull(), description: text("description"), // Measurable targets targetValue: real("target_value"), // e.g., 70 (kg), 100 (kg bench press) currentValue: real("current_value"), // Current progress unit: text("unit"), // kg, km, reps, etc. // Timeline startDate: integer("start_date", { mode: "timestamp" }) .notNull() .$defaultFn(() => new Date()), targetDate: integer("target_date", { mode: "timestamp" }), completedDate: integer("completed_date", { mode: "timestamp" }), // Status tracking status: text("status", { enum: ["active", "completed", "abandoned", "paused"], }) .notNull() .default("active"), progress: real("progress").default(0), // 0-100 percentage // Metadata priority: text("priority", { enum: ["low", "medium", "high"], }).default("medium"), notes: text("notes"), createdAt: integer("created_at", { mode: "timestamp" }) .notNull() .$defaultFn(() => new Date()), updatedAt: integer("updated_at", { mode: "timestamp" }) .notNull() .$defaultFn(() => new Date()), }); export const recommendations = sqliteTable("recommendations", { id: text("id").primaryKey(), userId: text("user_id") .notNull() .references(() => users.id, { onDelete: "cascade" }), fitnessProfileId: text("fitness_profile_id") .notNull() .references(() => fitnessProfiles.id, { onDelete: "cascade" }), recommendationText: text("recommendation_text").notNull(), activityPlan: text("activity_plan").notNull(), dietPlan: text("diet_plan").notNull(), status: text("status", { enum: ["pending", "approved", "rejected"], }) .notNull() .default("pending"), generatedAt: integer("generated_at", { mode: "timestamp" }) .notNull() .$defaultFn(() => new Date()), approvedAt: integer("approved_at", { mode: "timestamp" }), approvedBy: text("approved_by"), // User ID of admin/trainer createdAt: integer("created_at", { mode: "timestamp" }) .notNull() .$defaultFn(() => new Date()), updatedAt: integer("updated_at", { mode: "timestamp" }) .notNull() .$defaultFn(() => new Date()), }); export type User = typeof users.$inferSelect; export type NewUser = typeof users.$inferInsert; export type Client = typeof clients.$inferSelect; export type NewClient = typeof clients.$inferInsert; export type Payment = typeof payments.$inferSelect; export type NewPayment = typeof payments.$inferInsert; export type Attendance = typeof attendance.$inferSelect; export type NewAttendance = typeof attendance.$inferInsert; export type Notification = typeof notifications.$inferSelect; export type NewNotification = typeof notifications.$inferInsert; export type FitnessProfile = typeof fitnessProfiles.$inferSelect; export type NewFitnessProfile = typeof fitnessProfiles.$inferInsert; export type FitnessGoal = typeof fitnessGoals.$inferSelect; export type NewFitnessGoal = typeof fitnessGoals.$inferInsert; export type Recommendation = typeof recommendations.$inferSelect; export type NewRecommendation = typeof recommendations.$inferInsert;