working on onboarding flow

This commit is contained in:
dimitar committed 2025-12-13 06:26:23 +01:00
1 parent 868eaa5e3d
commit d3a36b6103
19 files changed
+2062 -393

No files matched your search

+42 -3
View File
@@ -6,10 +6,32 @@ export const users = sqliteTable("users", {
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"] })
role: text("role", {
enum: ["superAdmin", "admin", "trainer", "client", "generalUser"],
})
.notNull()
.default("client"),
phone: text("phone"),
// Remove direct foreign key reference to avoid circular dependency; validate at application level
gymId: text("gym_id"),
createdAt: integer("created_at", { mode: "timestamp" })
.notNull()
.$defaultFn(() => new Date()),
updatedAt: integer("updated_at", { mode: "timestamp" })
.notNull()
.$defaultFn(() => new Date()),
});
export const gyms = sqliteTable("gyms", {
id: text("id").primaryKey(),
name: text("name").notNull(),
location: text("location"),
status: text("status", { enum: ["active", "inactive"] })
.notNull()
.default("active"),
adminUserId: text("admin_user_id")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
createdAt: integer("created_at", { mode: "timestamp" })
.notNull()
.$defaultFn(() => new Date()),
@@ -144,7 +166,7 @@ export const fitnessGoals = sqliteTable("fitness_goals", {
.references(() => users.id, { onDelete: "cascade" }),
fitnessProfileId: text("fitness_profile_id").references(
() => fitnessProfiles.id,
{ onDelete: "cascade" }
{ onDelete: "cascade" },
),
// Goal details
@@ -198,6 +220,24 @@ export const fitnessGoals = sqliteTable("fitness_goals", {
.$defaultFn(() => new Date()),
});
// Removed local invitations table; Clerk invitations are the source of truth
export const trainerClients = sqliteTable("trainer_clients", {
id: text("id").primaryKey(),
trainerUserId: text("trainer_user_id")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
clientUserId: text("client_user_id")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
gymId: text("gym_id")
.notNull()
.references(() => gyms.id, { onDelete: "cascade" }),
createdAt: integer("created_at", { mode: "timestamp" })
.notNull()
.$defaultFn(() => new Date()),
});
export const recommendations = sqliteTable("recommendations", {
id: text("id").primaryKey(),
userId: text("user_id")
@@ -243,4 +283,3 @@ export type FitnessGoal = typeof fitnessGoals.$inferSelect;
export type NewFitnessGoal = typeof fitnessGoals.$inferInsert;
export type Recommendation = typeof recommendations.$inferSelect;
export type NewRecommendation = typeof recommendations.$inferInsert;
+132 -92
View File
@@ -1,115 +1,155 @@
export interface User {
id: string
email: string
firstName: string
lastName: string
password?: string
phone?: string
role: 'superAdmin' | 'admin' | 'trainer' | 'client'
imageUrl?: string
createdAt: Date
updatedAt: Date
id: string;
email: string;
firstName: string;
lastName: string;
password?: string;
phone?: string;
role: "superAdmin" | "admin" | "trainer" | "client" | "generalUser";
gymId?: string;
imageUrl?: string;
createdAt: Date;
updatedAt: Date;
}
export interface Client {
id: string
userId: string
user?: User
membershipType: 'basic' | 'premium' | 'vip'
membershipStatus: 'active' | 'inactive' | 'suspended' | 'expired'
joinDate: Date
lastVisit?: Date
id: string;
userId: string;
user?: User;
membershipType: "basic" | "premium" | "vip";
membershipStatus: "active" | "inactive" | "suspended" | "expired";
joinDate: Date;
lastVisit?: Date;
emergencyContact?: {
name: string
phone: string
relationship: string
}
name: string;
phone: string;
relationship: string;
};
}
export interface FitnessProfile {
id: string
userId: string
height: string
weight: string
age: string
gender: "male" | "female" | "other"
activityLevel: "sedentary" | "lightly_active" | "moderately_active" | "very_active" | "extremely_active"
fitnessGoals: string[]
exerciseHabits: string
dietHabits: string
medicalConditions: string
allergies?: string
injuries?: string
createdAt: Date
updatedAt: Date
id: string;
userId: string;
height: string;
weight: string;
age: string;
gender: "male" | "female" | "other";
activityLevel:
| "sedentary"
| "lightly_active"
| "moderately_active"
| "very_active"
| "extremely_active";
fitnessGoals: string[];
exerciseHabits: string;
dietHabits: string;
medicalConditions: string;
allergies?: string;
injuries?: string;
createdAt: Date;
updatedAt: Date;
}
export interface Attendance {
id: string
userId: string
clientId?: string
client?: Client
checkInTime: Date
checkOutTime?: Date
type: 'gym' | 'class' | 'personal_training'
notes?: string
createdAt?: Date
id: string;
userId: string;
clientId?: string;
client?: Client;
checkInTime: Date;
checkOutTime?: Date;
type: "gym" | "class" | "personal_training";
notes?: string;
createdAt?: Date;
}
export interface Recommendation {
id: string
userId: string
fitnessProfileId?: string
type: "short_term" | "medium_term" | "long_term" | "ai_plan"
recommendationText: string
activityPlan?: string
dietPlan?: string
status: "pending" | "approved" | "rejected" | "completed"
createdAt: Date
approvedAt?: Date
approvedBy?: string
id: string;
userId: string;
fitnessProfileId?: string;
type: "short_term" | "medium_term" | "long_term" | "ai_plan";
recommendationText: string;
activityPlan?: string;
dietPlan?: string;
status: "pending" | "approved" | "rejected" | "completed";
createdAt: Date;
approvedAt?: Date;
approvedBy?: string;
}
export interface FitnessGoal {
id: string
userId: string
fitnessProfileId?: string
goalType: "weight_target" | "strength_milestone" | "endurance_target" | "flexibility_goal" | "habit_building" | "custom"
title: string
description?: string
targetValue?: number
currentValue?: number
unit?: string
startDate: Date
targetDate?: Date
completedDate?: Date
status: "active" | "completed" | "abandoned" | "paused"
progress: number
priority: "low" | "medium" | "high"
notes?: string
createdAt: Date
updatedAt: Date
id: string;
userId: string;
fitnessProfileId?: string;
goalType:
| "weight_target"
| "strength_milestone"
| "endurance_target"
| "flexibility_goal"
| "habit_building"
| "custom";
title: string;
description?: string;
targetValue?: number;
currentValue?: number;
unit?: string;
startDate: Date;
targetDate?: Date;
completedDate?: Date;
status: "active" | "completed" | "abandoned" | "paused";
progress: number;
priority: "low" | "medium" | "high";
notes?: string;
createdAt: Date;
updatedAt: Date;
}
export interface Payment {
id: string
clientId: string
client: Client
amount: number
currency: string
status: 'pending' | 'completed' | 'failed' | 'refunded'
paymentMethod: 'cash' | 'card' | 'bank_transfer'
dueDate: Date
paidAt?: Date
description: string
id: string;
clientId: string;
client: Client;
amount: number;
currency: string;
status: "pending" | "completed" | "failed" | "refunded";
paymentMethod: "cash" | "card" | "bank_transfer";
dueDate: Date;
paidAt?: Date;
description: string;
}
export interface Notification {
id: string
userId: string
title: string
message: string
type: 'payment_reminder' | 'attendance' | 'promotion' | 'system'
read: boolean
createdAt: Date
}
id: string;
userId: string;
title: string;
message: string;
type: "payment_reminder" | "attendance" | "promotion" | "system";
read: boolean;
createdAt: Date;
}
export interface Gym {
id: string;
name: string;
location?: string;
status: "active" | "inactive";
adminUserId: string;
}
export interface Invitation {
id: string;
inviterUserId: string;
inviteeEmail: string;
roleAssigned: "trainer" | "client" | "admin";
gymId: string;
token: string;
status: "sent" | "accepted" | "expired";
expiresAt: Date;
createdAt: Date;
}
export interface TrainerClient {
id: string;
trainerUserId: string;
clientUserId: string;
gymId: string;
createdAt: Date;
}