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 Medida por ID
Section titled “Obtener Medida por ID”Obtener una medida específica por su ID.
- URL:
/api/v1/fitness/measurements/:id - Método:
GET - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint retorna los detalles de la medida indicada si pertenece al usuario.
Respuesta
Section titled “Respuesta”{ "data": { "id": "...", "weight": 75.5, "height": 180, "imc": 23.3, "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[':id'].$get({ param: { id: 'measurement_id_here' }})Actualizar Medida
Section titled “Actualizar Medida”Actualizar una medida corporal existente.
- URL:
/api/v1/fitness/measurements/:id - Método:
PATCH - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint permite editar los datos de la medida especificada por ID, validando que el usuario logueado sea el dueño.
Cuerpo de Solicitud (Parcial)
Section titled “Cuerpo de Solicitud (Parcial)”{ "notes": "Updated notes"}Respuesta
Section titled “Respuesta”{ "message": "Medida actualizada correctamente", "data": { "id": "...", "notes": "Updated notes" }}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[':id'].$patch({ param: { id: 'measurement_id_here' }, json: { notes: 'Updated notes' }})Eliminar Medida
Section titled “Eliminar Medida”Eliminar una medida corporal existente.
- URL:
/api/v1/fitness/measurements/:id - Método:
DELETE - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint permite eliminar la medida indicada, asegurándose de que el usuario logueado tenga los permisos.
Respuesta
Section titled “Respuesta”{ "message": "Medida eliminada correctamente"}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[':id'].$delete({ param: { id: 'measurement_id_here' }})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 Medidas de un Usuario (Admin/Staff)
Section titled “Obtener Medidas de un Usuario (Admin/Staff)”Obtener las medidas de un usuario específico.
- URL:
/api/v1/fitness/users/:userProfileId/measurements - Método:
GET - Autenticación Requerida: Sí (Admin/Staff)
Descripción Interna
Section titled “Descripción Interna”Este endpoint funciona igual que el endpoint principal de obtención, pero permite especificar el ID del perfil de usuario y solo es accesible para administradores o staff.
Obtener Última Medida de un Usuario (Admin/Staff)
Section titled “Obtener Última Medida de un Usuario (Admin/Staff)”Obtener la última medida de un usuario específico.
- URL:
/api/v1/fitness/users/:userProfileId/measurements/latest - Método:
GET - Autenticación Requerida: Sí (Admin/Staff)
Descripción Interna
Section titled “Descripción Interna”Este endpoint obtiene la medida más reciente de un perfil de usuario específico, incluyendo clasificación de IMC. Solo para administradores o staff.
Obtener Resumen de Medidas de un Usuario (Admin/Staff)
Section titled “Obtener Resumen de Medidas de un Usuario (Admin/Staff)”Obtener el resumen de medidas de un usuario específico.
- URL:
/api/v1/fitness/users/:userProfileId/measurements/summary - Método:
GET - Autenticación Requerida: Sí (Admin/Staff)
Descripción Interna
Section titled “Descripción Interna”Muestra el resumen general (total medidas, progreso general) de un usuario específico. Solo para administradores o staff.
Obtener Estadísticas de Progreso de un Usuario (Admin/Staff)
Section titled “Obtener Estadísticas de Progreso de un Usuario (Admin/Staff)”Obtener el historial de progreso de medidas de un usuario específico.
- URL:
/api/v1/fitness/users/:userProfileId/measurements/stats - Método:
GET - Autenticación Requerida: Sí (Admin/Staff)
Descripción Interna
Section titled “Descripción Interna”Devuelve las estadísticas de progreso y comparaciones para un rango de tiempo especificado de un perfil de usuario específico. Solo para administradores o staff.
Crear Medida para un Usuario (Admin/Staff)
Section titled “Crear Medida para un Usuario (Admin/Staff)”Registrar una nueva medida corporal para otro usuario.
- URL:
/api/v1/fitness/users/:userProfileId/measurements - Método:
POST - Autenticación Requerida: Sí (Admin/Staff)
Descripción Interna
Section titled “Descripción Interna”Registra una medida a nombre del usuario especificado. Solo accesible para administradores o staff.
Obtener Todas las Medidas (Admin/Staff)
Section titled “Obtener Todas las Medidas (Admin/Staff)”Obtener todas las medidas en el sistema.
- URL:
/api/v1/fitness/admin/measurements/all - Método:
GET - Autenticación Requerida: Sí (Admin/Staff)
Descripción Interna
Section titled “Descripción Interna”Retorna una lista completa de las medidas con filtros opcionales. Útil para revisión global o métricas. Solo administradores o staff.
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 } }}