Skip to content

Rachas

Endpoints para seguimiento y gestión de rachas de actividad.

El siguiente modelo de Prisma pertenece al schema gamification:

model Streak {
id String @id @default(cuid())
userProfileId String @map("user_profile_id")
goalId String? @map("goal_id")
type StreakType
currentStreak Int @default(0) @map("current_streak")
longestStreak Int @default(0) @map("longest_streak")
totalDays Int @default(0) @map("total_days")
lastActivityDate DateTime? @map("last_activity_date")
streakStartDate DateTime? @map("streak_start_date")
freezesUsed Int @default(0) @map("freezes_used")
freezesAvailable Int @default(0) @map("freezes_available")
isActive Boolean @default(true) @map("is_active")
userProfile UserProfile @relation(fields: [userProfileId], references: [id], onDelete: Cascade)
goal Goal? @relation(fields: [goalId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@unique([userProfileId, type, goalId])
@@map("streaks")
@@schema("gamification")
}
enum StreakType {
WORKOUT_STREAK
GOAL_STREAK
ATTENDANCE_STREAK
CLASS_STREAK
@@schema("gamification")
}

Las rachas se actualizan automáticamente al registrar progreso en un objetivo:

  • Día consecutivo: currentStreak++
  • Día no consecutivo (1-3 días): Usa freeze si disponible
  • Más de 3 días: Reinicia a 1

Obtener rachas del usuario.

  • URL: /api/v1/gamification/streaks
  • Método: GET
  • Autenticación Requerida:

Este endpoint obtiene las rachas del usuario:

  1. Filtros disponibles:

    • type: Tipo de racha (GOAL_STREAK, WORKOUT_STREAK, etc.)
    • isActive: Solo rachas activas
    • goalId: Filtrar por objetivo específico
  2. Incluye información del goal asociado (id, title, type)

  3. Ordenado por currentStreak descendente

  • type: Tipo de racha
  • isActive: Filtrar rachas activas
  • goalId: Filtrar por objetivo
  • page: Número de página
  • limit: Resultados por página
{
"data": [
{
"id": "...",
"type": "WORKOUT_STREAK",
"currentStreak": 15,
"longestStreak": 30,
"totalDays": 120,
"lastActivityDate": "2023-10-27T00:00:00Z",
"streakStartDate": "2023-10-12T00:00:00Z",
"freezesUsed": 2,
"freezesAvailable": 3,
"isActive": true,
"goal": {
"id": "...",
"title": "Daily Workout",
"type": "GENERAL_FITNESS"
}
}
],
"pagination": {...}
}
import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.gamification.streaks.$get({
query: {
isActive: 'true'
}
})

Obtener una racha específica con historial.

  • URL: /api/v1/gamification/streaks/:id
  • Método: GET
  • Autenticación Requerida:

Obtener la racha de asistencia diaria del usuario actual (sin modificar).

  • URL: /api/v1/gamification/streaks/attendance/me
  • Método: GET
  • Autenticación Requerida:

Este endpoint obtiene la racha de asistencia del usuario sin realizar check-in:

  1. Busca o crea una racha de tipo ATTENDANCE_STREAK para el usuario
  2. No modifica la racha, solo la retorna
{
"data": {
"currentStreak": 15,
"longestStreak": 30,
"totalDays": 120,
"lastActivityDate": "2023-10-27T00:00:00Z",
"streakStartDate": "2023-10-12T00:00:00Z",
"isActive": true
}
}
const res = await client.api.v1.gamification.streaks.attendance.me.$get()
const { data } = await res.json()
console.log(`Racha actual: ${data.currentStreak} días`)

Registrar un check-in de asistencia y actualizar la racha.

  • URL: /api/v1/gamification/streaks/attendance/check-in
  • Método: POST
  • Autenticación Requerida:

Este endpoint registra el check-in diario del usuario:

  1. Obtiene o crea la racha de asistencia
  2. Verifica si ya hizo check-in hoy (no duplica)
  3. Calcula días desde el último check-in:
    • 0 días: Ya registró hoy, retorna estado actual
    • 1 día: Día consecutivo, incrementa racha
    • 2+ días: Racha rota, reinicia a 1
  4. Otorga XP: 5 XP base + bonus en milestones (7, 14, 30, 60, 90, 180, 365 días)
  5. Verifica logros de racha automáticamente
{
"message": "¡Excelente! Racha de 16 días",
"data": {
"currentStreak": 16,
"longestStreak": 30,
"totalDays": 121,
"xpEarned": 5,
"isNewCheckIn": true,
"streakIncreased": true,
"streakReset": false
}
}
EscenarioMensaje
Ya registrado hoy”Ya registraste tu asistencia hoy”
Día consecutivo”¡Excelente! Racha de X días”
Racha reiniciada”¡Bienvenido de nuevo! Tu racha se ha reiniciado”
Primer check-in”¡Primer check-in! Tu racha ha comenzado”
const res = await client.api.v1.gamification.streaks.attendance['check-in'].$post()
const { message, data } = await res.json()
if (data.isNewCheckIn) {
console.log(message)
console.log(`XP ganado: ${data.xpEarned}`)
}

Obtener la racha de entrenamiento del usuario actual.

  • URL: /api/v1/gamification/streaks/workout/me
  • Método: GET
  • Autenticación Requerida:

Esta racha se actualiza automáticamente cuando el usuario crea un WorkoutLog:

  1. Se incrementa si el usuario registra entrenamientos en días consecutivos
  2. Se reinicia a 1 si pasan 2+ días sin entrenar
  3. Otorga XP: 10 XP base + bonus en milestones (días 7, 14, 30, 60, 90, 180, 365)
{
"data": {
"currentStreak": 5,
"longestStreak": 15,
"totalDays": 45,
"lastActivityDate": "2023-10-27T00:00:00Z",
"streakStartDate": "2023-10-22T00:00:00Z",
"isActive": true
}
}
const res = await client.api.v1.gamification.streaks.workout.me.$get()
const { data } = await res.json()
console.log(`Racha de entrenamiento: ${data.currentStreak} días`)

Obtener las mejores rachas del usuario.

  • URL: /api/v1/gamification/streaks/best
  • Método: GET
  • Autenticación Requerida:
{
"data": {
"currentBest": {
"type": "WORKOUT_STREAK",
"currentStreak": 15
},
"allTimeBest": {
"type": "GOAL_STREAK",
"longestStreak": 45
},
"topStreaks": [...]
}
}

Usar una congelación para proteger una racha.

  • URL: /api/v1/gamification/streaks/:id/freeze
  • Método: POST
  • Autenticación Requerida:

Este endpoint usa un freeze para proteger una racha:

  1. Verifica que el streak tenga freezes disponibles
  2. Verifica que la racha esté activa
  3. Actualiza freezesUsed++ y freezesAvailable—
  4. Marca el día como wasFrozen
{
"data": {
"id": "...",
"freezesUsed": 3,
"freezesAvailable": 2,
"message": "Freeze used successfully"
}
}

Añadir congelaciones a la racha de un usuario.

  • URL: /api/v1/gamification/streaks/:id/add-freezes
  • Método: POST
  • Autenticación Requerida: Sí (Admin)
{
"amount": 3
}
TipoDescripción
WORKOUT_STREAKEntrenamientos consecutivos
GOAL_STREAKCumplimiento de objetivos diarios
ATTENDANCE_STREAKAsistencia al gimnasio
CLASS_STREAKAsistencia a clases