Fitness
Endpoints para seguimiento de medidas corporales y fotos.
Modelos de Datos
Section titled “Modelos de Datos”El siguiente modelo de Prisma pertenece al schema fitness:
BodyMeasurement
Section titled “BodyMeasurement”model BodyMeasurement { id String @id @default(cuid()) userProfileId String @map("user_profile_id")
measurementDate DateTime @default(now()) @map("measurement_date")
weight Float height Float imc Float
bodyFatPercentage Float? @map("body_fat_percentage") muscleMassPercentage Float? @map("muscle_mass_percentage")
notes String? photoUrl String? @map("photo_url")
userProfile UserProfile @relation(fields: [userProfileId], references: [id], onDelete: Cascade)
updatedAt DateTime @updatedAt @map("updated_at")
@@index([userProfileId, measurementDate]) @@map("body_measurements") @@schema("fitness")}Endpoints
Section titled “Endpoints”Obtener Medidas
Section titled “Obtener Medidas”Obtener medidas corporales con filtrado y paginación.
- URL:
/api/v1/fitness/measurements - Método:
GET - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint obtiene medidas corporales con filtrado avanzado:
-
Filtros disponibles:
userProfileId: Filtrar por usuario específicodateFrom/dateTo: Rango de fechas de mediciónsortBy: Ordenar por ‘date’, ‘weight’, o ‘imc’sortOrder: ‘asc’ o ‘desc’
-
Incluye relación con userProfile (id, name)
-
Añade clasificación IMC a cada medida:
- Bajo peso (< 18.5)
- Peso normal (18.5 - 24.9)
- Sobrepeso (25 - 29.9)
- Obesidad grado I, II, III (30+)
-
Paginación estándar con page/limit
Parámetros de Consulta de Solicitud
Section titled “Parámetros de Consulta de Solicitud”userProfileId: Filtrar por usuariodateFrom: Fecha de inicio (cadena ISO)dateTo: Fecha de fin (cadena ISO)sortBy: Campo de ordenamiento (date, weight, imc)sortOrder: Dirección de ordenamiento (asc, desc)page: Número de página (por defecto: 1)limit: Resultados por página (por defecto: 10)
Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.fitness.measurements.$get({ query: { dateFrom: '2023-01-01', sortBy: 'date', sortOrder: 'desc' }})Crear Medida
Section titled “Crear Medida”Registrar una nueva medida corporal.
- URL:
/api/v1/fitness/measurements - Método:
POST - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint registra una nueva medida corporal:
-
Obtiene userProfileId del contexto de autenticación
-
Calcula IMC automáticamente:
peso / (altura_metros)² -
Crea la medida con:
- Fecha (proporcionada o actual)
- Peso, altura, IMC calculado
- Campos opcionales: bodyFatPercentage, muscleMassPercentage, notes, photoUrl
-
Busca medida anterior para calcular comparación:
weightChange: Diferencia de pesoweightChangePercentage: Cambio porcentualimcChange: Diferencia de IMCdaysBetween: Días desde la última medida
-
Retorna medida con clasificación IMC y comparación
Cuerpo de Solicitud
Section titled “Cuerpo de Solicitud”{ "weight": 75.5, "height": 180, "bodyFatPercentage": 15.5, "muscleMassPercentage": 42.0, "measurementDate": "2023-10-27", "notes": "Morning measurement", "photoUrl": "https://..."}Respuesta
Section titled “Respuesta”{ "data": { "id": "...", "weight": 75.5, "height": 180, "imc": 23.3, "imcClassification": "Peso normal", "comparison": { "weightChange": -0.5, "weightChangePercentage": -0.66, "imcChange": -0.15, "daysBetween": 7 } }}Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.fitness.measurements.$post({ json: { weight: 75.5, height: 180, measurementDate: '2023-10-27' }})Obtener Última Medida
Section titled “Obtener Última Medida”Obtener la medida más reciente del usuario autenticado.
- URL:
/api/v1/fitness/measurements/latest - Método:
GET - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint obtiene la última medida del usuario:
- Busca la medida más reciente ordenando por
measurementDatedescendente - Incluye userProfile (id, name)
- Añade clasificación IMC
- Lanza 404 si no hay medidas registradas
Respuesta
Section titled “Respuesta”{ "data": { "id": "...", "weight": 75.5, "height": 180, "imc": 23.3, "imcClassification": "Peso normal", "measurementDate": "2023-10-27T00:00:00.000Z", "bodyFatPercentage": 15.5, "muscleMassPercentage": 42.0 }}Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.fitness.measurements.latest.$get()Obtener Estadísticas de Progreso
Section titled “Obtener Estadísticas de Progreso”Obtener estadísticas de progreso para un período específico.
- URL:
/api/v1/fitness/measurements/stats - Método:
GET - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint calcula estadísticas de progreso:
-
Determina fecha de inicio según período:
week: 7 días atrásmonth: 1 mes atrásquarter: 3 meses atrásyear: 1 año atrásall: Desde el año 2000
-
Obtiene todas las medidas del período ordenadas por fecha
-
Calcula estadísticas de peso:
- Actual, inicial, cambio, cambio porcentual
- Mínimo, máximo, promedio
-
Calcula estadísticas de IMC:
- Actual, inicial, cambio, clasificación
- Mínimo, máximo, promedio
-
Composición corporal (si hay datos):
- Cambio en grasa corporal
- Cambio en masa muscular
-
Historial para gráficas: Últimas 30 medidas
Parámetros de Consulta de Solicitud
Section titled “Parámetros de Consulta de Solicitud”period: Período de tiempo (week, month, quarter, year, all)
Respuesta
Section titled “Respuesta”{ "data": { "totalMeasurements": 15, "period": "month", "dateRange": { "from": "...", "to": "..." }, "weight": { "current": 75.5, "initial": 78.0, "change": -2.5, "changePercentage": -3.2, "min": 75.0, "max": 78.0, "average": 76.5 }, "imc": { "current": 23.3, "classification": "Peso normal" }, "history": [...] }}Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.fitness.measurements.stats.$get({ query: { period: 'month' }})Subir Foto de Medida
Section titled “Subir Foto de Medida”Subir una foto para una medida corporal.
- URL:
/api/v1/fitness/measurements/photo - Método:
POST - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint sube una foto de progreso:
- Crea ruta del archivo:
{UPLOAD_DIR}/measurements/{userId}/{timestamp}.{extension} - Guarda el archivo usando Bun.write con el buffer de la imagen
- Retorna URL pública:
{BACKEND_URL}/uploads/measurements/{userId}/{filename}
Cuerpo de Solicitud
Section titled “Cuerpo de Solicitud”- Content-Type:
multipart/form-data - Campo:
photo(Archivo)
Respuesta
Section titled “Respuesta”{ "data": { "photoUrl": "https://api.example.com/uploads/measurements/user123/2023-10-27.jpg" }}Comparar Medidas
Section titled “Comparar Medidas”Comparar dos medidas del mismo usuario.
- URL:
/api/v1/fitness/measurements/compare - Método:
POST - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint compara dos medidas corporales:
- Obtiene ambas medidas por ID
- Verifica que pertenezcan al mismo usuario
- Identifica cuál es más antigua y cuál más reciente
- Calcula diferencias:
daysBetween: Días entre medidasweightChangey porcentajeimcChangey porcentajebodyFatChange(si disponible)muscleMassChange(si disponible)
Cuerpo de Solicitud
Section titled “Cuerpo de Solicitud”{ "measurementId1": "measurement_id_1", "measurementId2": "measurement_id_2"}Respuesta
Section titled “Respuesta”{ "data": { "older": { "...": "..." }, "newer": { "...": "..." }, "comparison": { "daysBetween": 30, "weightChange": -2.5, "weightChangePercentage": -3.2, "imcChange": -0.8, "bodyFatChange": -1.5, "muscleMassChange": 0.8 } }}Obtener Resumen de Medidas
Section titled “Obtener Resumen de Medidas”Obtener un resumen rápido de medidas para el usuario.
- URL:
/api/v1/fitness/measurements/summary - Método:
GET - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint obtiene un resumen rápido:
-
Ejecuta consultas en paralelo:
- Última medida
- Total de medidas
- Primera medida
-
Calcula datos generales:
totalMeasurementshasData: boolean indicando si hay medidaslatest: Última medida con clasificación IMCoverall: Cambio total de peso e IMC desde la primera medidadaysSinceFirst: Días desde la primera medida
Respuesta
Section titled “Respuesta”{ "data": { "totalMeasurements": 15, "hasData": true, "latest": { "weight": 75.5, "imc": 23.3, "imcClassification": "Peso normal" }, "overall": { "weightChange": -5.0, "imcChange": -1.5, "daysSinceFirst": 90 } }}