Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/piratta/gymApp/llms.txt

Use this file to discover all available pages before exploring further.

All FocusFlow data structures are defined as TypeScript interfaces in src/types.ts. Every domain object — from user accounts and training routines to body-composition logs and in-app notifications — is fully typed so the compiler can catch shape mismatches at build time. This page documents every exported type in the order it appears in the source file.
All types are exported from src/types.ts and can be imported anywhere in the codebase with import type { ... } from '../types'.

UserRole

A union type alias that enumerates the three permission levels a FocusFlow account can hold.
export type UserRole = "coach" | "client" | "admin";
ValueDescription
"coach"Personal trainer / gym coach with athlete management access
"client"Athlete account linked to a specific coach
"admin"Platform administrator with global access

User

The root account object stored in Firestore. Represents every registered user regardless of role.
export interface User {
  id: string;
  username: string;
  passwordHash: string; // BCrypt simulator
  isTemporaryPassword: boolean;
  needsQuestionnaire: boolean;
  fullName: string;
  firstName: string;
  lastName: string;
  email: string;
  role: UserRole;
  avatarUrl?: string;
  coachId?: string; // Links client to specific coach
  isPaused?: boolean; // If true, the user (or their assigned clients) loses access
  biologicalSex?: "MALE" | "FEMALE";
  birthDate?: string; // YYYY-MM-DD
}
FieldTypeDescription
idstringFirestore document ID
usernamestringUnique login handle
passwordHashstringBCrypt-simulated password hash
isTemporaryPasswordbooleanForces password change on next login
needsQuestionnairebooleanWhether the onboarding questionnaire is still pending
fullNamestringConcatenated display name
firstNamestringGiven name
lastNamestringFamily name
emailstringAccount email address
roleUserRoleAccount permission level
coachIdstring?For clients: the ID of their assigned coach
isPausedboolean?Suspends access when true
biologicalSex"MALE" | "FEMALE"?Used by body-composition formulas
birthDatestring?Format: YYYY-MM-DD

ClientProfile

Extended metadata for client accounts, covering training plan settings, payment state, and plicometry configuration. Stored as a separate Firestore document keyed by clientId.
export interface ClientProfile {
  clientId: string;
  targetGoal: string;
  currentWeight: number;
  currentHeight: number;
  routineComplianceRate: number; // Percentage
  reviewPeriodDays: number; // 7, 14, 30
  progressionStrategy: string; // e.g., "Doble progresión", "Lineal"
  planType: string;
  lastPaymentDate: string; // ISO String
  requiredMeasurements?: string[];
  evaluationUnlocked?: boolean;
  nextExpirationDate?: string; // Edit-override format YYYY-MM-DD
  renewalMode?: "auto" | "manual";
  isPlicometriaEnabled?: boolean;
  plicometriaProtocolId?: "3-fold" | "4-fold" | "7-fold" | "yuhasz" | "jackson_pollock_3" | "jackson_pollock_4" | "jackson_pollock_7";
  biologicalSex?: "MALE" | "FEMALE";
  birthDate?: string; // YYYY-MM-DD
  coachNotes?: string;
  coachTasks?: { id: string; text: string; completed: boolean }[];
}
FieldTypeDescription
clientIdstringMatches the corresponding User.id
currentWeightnumberMost recent weight in kg
currentHeightnumberHeight in cm
routineComplianceRatenumberPercentage of sessions completed
reviewPeriodDaysnumberReview cadence: 7, 14, or 30 days
progressionStrategystringe.g. "Doble progresión", "Lineal"
nextExpirationDatestring?Coach-overridden plan expiry (YYYY-MM-DD)
renewalMode"auto" | "manual"?How the subscription renews
isPlicometriaEnabledboolean?Enables the body-composition tracking module
plicometriaProtocolIdstring?Which skinfold protocol to use
coachTasks{ id, text, completed }[]?Coach’s internal to-do list for this client

QuestionnaireData

The health intake form completed by new clients during onboarding.
export interface QuestionnaireData {
  weight: number;
  height: number;
  age: number;
  birthDate?: string;
  biologicalSex?: "MALE" | "FEMALE";
  sleepHours: number;
  stressLevel: number; // 1 to 5
  digestionStatus: string; // e.g. "Buena", "Lenta"
  additionalNotes?: string;
  completedAt: string;
}
FieldTypeDescription
weightnumberSelf-reported weight in kg
heightnumberHeight in cm
stressLevelnumberSubjective scale 1 (low) – 5 (high)
digestionStatusstringe.g. "Buena", "Lenta"
completedAtstringISO 8601 timestamp

Exercise

A reusable exercise definition in the coach’s exercise library.
export interface Exercise {
  id: string;
  name: string;
  category: string; // e.g., "Pecho", "Espalda", "Piernas", "Hombros", "Brazos", "Cardio"
  description?: string;
  coachId?: string; // Unique per coach
}
FieldTypeDescription
idstringFirestore document ID
namestringDisplay name of the exercise
categorystringMuscle group or modality (e.g. "Pecho", "Cardio")
descriptionstring?Optional coaching notes or technique cues
coachIdstring?Scopes the exercise to a specific coach’s library

ExerciseSet

Represents a single set within a workout, capturing both the prescription and the athlete’s actual performance.
export interface ExerciseSet {
  setIndex: number;
  targetReps: string; // e.g. "8-10" or "12"
  achievedReps?: number;
  weightUsed?: number;
  completed: boolean;
  skipped: boolean;
  targetRpe?: string; // e.g. "@6.0", "9", etc.
}
FieldTypeDescription
setIndexnumberZero-based position in the set list
targetRepsstringPrescribed rep range, e.g. "8-10"
achievedRepsnumber?Actual reps completed by the athlete
weightUsednumber?Load used in kg
completedbooleanWhether the set was finished
skippedbooleanWhether the set was deliberately skipped
targetRpestring?RPE/RIR target, e.g. "@6.0", "9"

RoutineExercise

An exercise entry inside a RoutineDay, combining the exercise definition reference with per-block prescriptions.
export interface RoutineExercise {
  id: string; // Unique within routine
  exerciseId: string;
  name: string;
  category: string;
  optional: boolean;
  setsCount: number;
  repsText: string;
  intensity: string; // e.g. "RPE 8", "RIR 2"
  expectedWeight: number; // expected starting weight in kg
  notes: string;
  sets: ExerciseSet[];
  customized?: boolean;
}
FieldTypeDescription
idstringUnique within the parent routine
exerciseIdstringReference to the Exercise library entry
optionalbooleanIf true, the athlete can skip this exercise
setsCountnumberPrescribed number of sets
repsTextstringPrescribed rep scheme, e.g. "3×10"
intensitystringLoad prescription, e.g. "RPE 8", "RIR 2"
expectedWeightnumberSuggested starting load in kg
setsExerciseSet[]One entry per prescribed set
customizedboolean?Marks athlete-modified prescriptions

RoutineDay

A single training day within a Routine, grouping exercises under a label such as "Lunes - Torso".
export interface RoutineDay {
  id: string;
  name: string; // e.g., "Lunes - Torso", "Martes - Pierna"
  notes?: string;
  exercises: RoutineExercise[];
  optional?: boolean;
}
FieldTypeDescription
idstringUnique within the parent routine
namestringLabel shown in the training schedule
notesstring?Coach instructions for the session
exercisesRoutineExercise[]Ordered list of exercises for the day
optionalboolean?If true, the whole day can be skipped

Routine

A complete training program assigned to a specific client, made up of multiple RoutineDay entries.
export interface Routine {
  id: string; // Client routine is usually unique per client
  clientId: string;
  name: string;
  isActive: boolean; // Current active routine vs "Siguiente Rutina"
  days: RoutineDay[];
  assignedAt: string;
  startDate?: string;
  endDate?: string;
  globalRestSeconds?: number;
}
FieldTypeDescription
idstringFirestore document ID
clientIdstringAthlete this routine belongs to
isActivebooleanDistinguishes current from upcoming routine
daysRoutineDay[]Ordered training days
assignedAtstringISO 8601 assignment timestamp
globalRestSecondsnumber?Default rest timer applied to all sets

ActiveWorkoutSession

Persists the in-progress state of a workout so sessions survive page refreshes or app restarts.
export interface ActiveWorkoutSession {
  clientId: string;
  routineId: string;
  dayId: string;
  dayName: string;
  startTime: string; // ISO 8601
  isStarted: boolean;
  isRestDay: boolean;
  isPaused?: boolean;
  elapsedSeconds?: number;
  retroDate?: string;
  exercises: {
    [routineExerciseId: string]: ExerciseSet[];
  };
  exerciseNotes?: {
    [routineExerciseId: string]: string;
  };
}
FieldTypeDescription
startTimestringISO 8601 — when the session clock began
isStartedbooleanWhether the athlete has tapped “Start”
isRestDaybooleanMarks passive recovery days
isPausedboolean?Session clock paused state
elapsedSecondsnumber?Accumulated session time in seconds
retroDatestring?Allows backdating a session to a past date
exercisesRecord<string, ExerciseSet[]>Live set data keyed by routineExerciseId
exerciseNotesRecord<string, string>?Per-exercise notes entered mid-session

WorkoutSummary

The immutable record created when a session is completed. Used for history, analytics, and coach review.
export interface WorkoutSummary {
  id: string;
  clientId: string;
  routineId: string;
  dayId: string;
  dayName: string;
  date: string; // YYYY-MM-DD
  timeSpentSeconds: number;
  totalVolume: number; // Sum of reps * weight
  completionRate: number; // Percentage
  isRestDay: boolean;
  notes?: string;
  loggedExercises?: {
    [routineExerciseId: string]: ExerciseSet[];
  };
  loggedExerciseDetails?: {
    [routineExerciseId: string]: {
      name: string;
      category: string;
      userNotes?: string;
    };
  };
}
FieldTypeDescription
datestringSession date (YYYY-MM-DD)
timeSpentSecondsnumberTotal elapsed workout time
totalVolumenumberSum of reps × weight across all sets
completionRatenumberPercentage of prescribed sets completed
loggedExercisesRecord<string, ExerciseSet[]>?Snapshot of all set data at completion
loggedExerciseDetailsRecord<string, { name, category, userNotes? }>?Exercise metadata at time of logging

DailyWeight

A single bodyweight measurement entry for tracking the athlete’s weight over time.
export interface DailyWeight {
  date: string; // YYYY-MM-DD
  value: number;
}
FieldTypeDescription
datestringMeasurement date (YYYY-MM-DD)
valuenumberBodyweight in kg

PlicometriaLog

A complete skinfold assessment record, storing both the raw measurements and the computed body-composition values.
export interface PlicometriaLog {
  id: string;
  clientId: string;
  date: string; // YYYY-MM-DD
  weight: number; // Peso actual (kg)
  protocolId: "3-fold" | "4-fold" | "7-fold" | "yuhasz";

  // Skinfolds in mm
  pectoral?: number;
  abdominal?: number;
  musloAnterior?: number;
  triceps?: number;
  suprailiaco?: number;
  biceps?: number;
  subescapular?: number;
  axilarMedio?: number;

  // Calculated properties
  sumaPliegues: number;
  densidadCorporal: number;
  porcentajeGrasa: number;
  masaGrasa: number; // kg
  masaMagra: number; // kg

  createdBy: "coach" | "client";
  createdAt: string; // ISO String
}
FieldTypeDescription
protocolIdstringSkinfold protocol used for this log
weightnumberBodyweight at time of assessment (kg)
pectoralaxilarMedionumber?Individual skinfold measurements in mm
sumaPlieguesnumberSum of all measured skinfolds (mm)
densidadCorporalnumberComputed body density (g/cm³)
porcentajeGrasanumberBody fat percentage (clamped 2–60%)
masaGrasanumberFat mass in kg
masaMagranumberLean mass in kg
createdBy"coach" | "client"Who entered the data
See the Plicometría Formulas reference for the exact mathematical derivation of densidadCorporal and porcentajeGrasa.

BodyMeasurements

A full-body tape-measure snapshot. Fields are optional so coaches can record only the measurements relevant to each athlete’s program.
export interface BodyMeasurements {
  date: string; // YYYY-MM-DD
  cuello?: number;
  hombros?: number;
  pecho?: number; // Pecho/Tórax
  bajoBusto?: number; // Contorno bajo el busto
  brazoRelajado?: number; // Brazo relajado
  brazoContraido?: number; // Brazo contraído
  antebraco?: number; // Antebrazo
  muneca?: number; // Muñeca
  cintura?: number; // Cintura
  cinturaUmbilical?: number; // Cintura umbilical
  cadera?: number; // Cadera
  gluteos?: number; // Glúteos
  musloSuperior?: number; // Muslo superior
  musloMedio?: number; // Muslo medio
  gemelo?: number; // Gemelo
  tobillo?: number; // Tobillo
  peso?: number; // Peso

  // Legacy fields for backwards compatibility
  biceps?: number;
  pierna?: number;
  espalda?: number;
}

Review

A periodic progress check-in submitted by the client and reviewed by the coach, combining measurements, photos, and bilateral feedback.
export interface Review {
  id: string;
  clientId: string;
  clientName: string;
  date: string; // YYYY-MM-DD
  measurements: BodyMeasurements;
  comment: string;
  photos: string[]; // Mock dataUrls or system images
  status: "pending" | "reviewed";
  coachFeedback?: string;
  feedbackPhotos?: string[]; // With annotated illustrations/arrows
  driveFolderUrl?: string; // Link to Google Drive folder containing original files
  reviewedAt?: string;
  acknowledgedByClient: boolean;
  workoutHistory?: WorkoutSummary[];
}
FieldTypeDescription
measurementsBodyMeasurementsTape measurements at time of review
photosstring[]Progress photo URLs
status"pending" | "reviewed"Coach action state
coachFeedbackstring?Coach’s written response
feedbackPhotosstring[]?Annotated images attached by the coach
driveFolderUrlstring?Link to the Google Drive folder with originals
acknowledgedByClientbooleanClient has seen the coach’s feedback
workoutHistoryWorkoutSummary[]?Sessions logged during the review period

Message

A single direct message exchanged between a coach and a client.
export interface Message {
  id: string;
  senderId: string;
  receiverId: string;
  content: string;
  timestamp: string; // ISO string
  isRead: boolean;
}
FieldTypeDescription
senderIdstringUser.id of the message author
receiverIdstringUser.id of the recipient
contentstringMessage body
timestampstringISO 8601 send time
isReadbooleanWhether the recipient has opened the message

WorkoutTemplate

A reusable routine skeleton that coaches can stamp out into client-specific Routine instances.
export interface WorkoutTemplate {
  id: string;
  name: string;
  description: string;
  days: RoutineDay[];
  globalRestSeconds?: number;
  coachId?: string; // Unique per coach
}
FieldTypeDescription
idstringFirestore document ID
namestringTemplate display name
descriptionstringBrief description of the program
daysRoutineDay[]Day-by-day training structure
globalRestSecondsnumber?Default rest timer for generated routines
coachIdstring?Scopes the template to a specific coach

AgendaEventType

A union type alias enumerating the six supported calendar event categories.
export type AgendaEventType =
  | "review"
  | "payment"
  | "videocall"
  | "call"
  | "presential_training"
  | "other";
ValueDescription
"review"Scheduled progress review session
"payment"Payment due or received
"videocall"Remote coaching call via video
"call"Voice or phone call
"presential_training"In-person training session
"other"Any other calendar note

AgendaEvent

A calendar entry on the coach’s agenda, representing any scheduled interaction with a client.
export interface AgendaEvent {
  id: string;
  clientId: string;
  clientName: string;
  coachId: string;
  type: AgendaEventType;
  title: string;
  date: string; // YYYY-MM-DD
  time?: string; // HH:MM
  notes?: string;
  notified: boolean;
  meetLink?: string;
}
FieldTypeDescription
clientIdstringAssociated client
coachIdstringOwning coach
typeAgendaEventTypeCategory of the event
datestringEvent date (YYYY-MM-DD)
timestring?Start time (HH:MM)
notifiedbooleanWhether a reminder was sent
meetLinkstring?Google Meet or video call URL

CoachProfile

Subscription and monetisation settings for a coach’s FocusFlow account.
export interface CoachProfile {
  coachId: string;
  planName: "Bronce" | "Plata" | "Oro" | "Elite";
  monthlyCost: number;
  maxAthletes: number;
  payoutRate: number;
  platformCommission: number;
  nextBillingDate: string;
}
FieldTypeDescription
planNamestringTier: "Bronce", "Plata", "Oro", or "Elite"
monthlyCostnumberMonthly charge in the platform’s currency unit
maxAthletesnumberMaximum concurrent active clients
payoutRatenumberCoach’s revenue share rate
platformCommissionnumberPlatform’s cut as a decimal or percentage
nextBillingDatestringISO 8601 next charge date

AppNotification

An in-app notification pushed to a user’s notification centre.
export interface AppNotification {
  id: string;
  userId: string;
  title: string;
  message: string;
  type: "workout" | "review" | "message" | "general";
  timestamp: string;
  isRead: boolean;
  linkTab?: "workout" | "calendar" | "progress" | "review" | "gallery" | "chat" | "profile" | "athletes" | "templates" | "messages" | "settings" | "reviews" | "agenda" | "billing" | "summary" | "exercises_menu";
}
FieldTypeDescription
userIdstringRecipient user ID
typestringNotification category
isReadbooleanWhether the user has dismissed it
linkTabstring?Deep-link target tab opened on tap

SubscriptionPlan

Describes a purchasable subscription plan available to clients.
export interface SubscriptionPlan {
  id: string;
  name: string;
  price: number;
  months: number;
  description: string;
}
FieldTypeDescription
idstringFirestore document ID
namestringPlan display name
pricenumberTotal price for the plan duration
monthsnumberPlan duration in months
descriptionstringMarketing copy shown to the client

Build docs developers (and LLMs) love