# Perfil del Socio

Endpoints para la pantalla de **Perfil** en la app DeportesCam.
Todos requieren Bearer token (`auth:api_padel`).

---

## Flujo de la pantalla

```
1. Abrir pantalla Perfil
   └── GET /registro-padel/perfil
       ├── Datos del socio (nombre, membresía, username, contacto)
       ├── Lista de deportes activos  → pintar tabs (Pádel / Tenis / Otros)
       └── Horarios del primer deporte agrupados por día con seleccionado: true/false

2. Usuario cambia de tab (ej. toca "Tenis")
   └── GET /horario/lista?idDeporte=1
       └── Horarios del deporte agrupados por día con seleccionado: true/false

3. Usuario toca "Guardar cambios" (contacto/notificaciones)
   └── POST /registro-padel/actualizar-contacto

4. Usuario toca "Cambiar contraseña"
   └── POST /registro-padel/cambiar-password
```

---

## GET /deportescam/registro-padel/perfil

Carga inicial de la pantalla. Retorna todo lo necesario en una sola llamada.

**Autenticación:** Requerida  
**Middleware:** `auth:api_padel`, `seguridadFSG`, `throttle:60,1`

### Respuesta 200

```json
{
  "success": true,
  "message": "Perfil obtenido correctamente.",
  "data": {
    "perfil": {
      "nombre": "CENTRO ASTURIANO DE MÉXICO",
      "membresiaNo": "12345",
      "username": "GAMP230618",
      "noJugador": 3,
      "correo": "socio@email.com",
      "notificacionesCorreo": "Si",
      "whatsapp": "522481387936",
      "idCodigoPais": 1,
      "codigoPaisNumero": "52",
      "celular": "2481387936",
      "notificacionesWhatsApp": "Si"
    },
    "deportes": [
      { "idDeporte": "MQ==", "nombre": "Tenis" },
      { "idDeporte": "Mg==", "nombre": "Padel" },
      { "idDeporte": "Mw==", "nombre": "Otro" }
    ],
    "idDeporte": "MQ==",
    "horarios": {
      "Lunes": [
        { "idHorario": 1, "dia": "Lunes", "inicio": "06:30", "fin": "08:00", "seleccionado": true },
        { "idHorario": 2, "dia": "Lunes", "inicio": "08:00", "fin": "09:30", "seleccionado": false },
        { "idHorario": 3, "dia": "Lunes", "inicio": "09:30", "fin": "11:00", "seleccionado": false }
      ],
      "Martes": [
        { "idHorario": 4, "dia": "Martes", "inicio": "06:30", "fin": "08:00", "seleccionado": false },
        { "idHorario": 5, "dia": "Martes", "inicio": "08:00", "fin": "09:30", "seleccionado": true }
      ]
    }
  }
}
```

| Campo | Descripción |
|-------|-------------|
| `perfil` | Datos del socio autenticado |
| `deportes` | Lista de deportes activos para pintar los tabs |
| `idDeporte` | ID del deporte cuyo tab se muestra por defecto (el primero) |
| `horarios` | Objeto agrupado por día. Cada key es un día, el valor es el arreglo de horarios con `seleccionado` |

> **Nota:** Los horarios vienen agrupados por día para que el frontend solo itere `Object.entries(horarios)` sin necesidad de filtrar ni ordenar.

---

## GET /deportescam/horario/lista

Horarios al **cambiar de tab**. Retorna los horarios del deporte indicado
agrupados por día con `seleccionado: true/false` según las preferencias del socio.

**Autenticación:** Requerida  
**Middleware:** `auth:api_padel`, `seguridadFSG`, `throttle:60,1`

### Query params

| Param | Tipo | Requerido | Descripción | Ejemplo |
|-------|------|-----------|-------------|---------|
| `idDeporte` | string | No | ID del deporte en **Base64** | `Mg==` |
| `horarioDia` | string | No | Filtrar por día | `Lunes` |
| `horarioInicio` | string | No | Horarios desde esta hora | `06:30` |
| `horarioFin` | string | No | Horarios hasta esta hora | `10:00` |
| `typeData` | string | No | `all` para sin paginar | `all` |
| `perPage` | integer | No | Registros por página (default 10) | `20` |

```
GET /api/v1/deportescam/horario/lista?idDeporte=MQ==&typeData=all
```

### Respuesta 200

```json
{
  "success": true,
  "message": "Horarios obtenidos correctamente.",
  "data": {
    "Lunes": [
      { "idHorario": 10, "dia": "Lunes", "inicio": "06:30", "fin": "08:00", "seleccionado": false },
      { "idHorario": 11, "dia": "Lunes", "inicio": "08:00", "fin": "09:30", "seleccionado": true }
    ],
    "Martes": [
      { "idHorario": 12, "dia": "Martes", "inicio": "07:00", "fin": "08:30", "seleccionado": false }
    ]
  }
}
```

> **Nota:** Si se filtra por `horarioDia=Lunes` el objeto solo contendrá la key `"Lunes"`.

### Respuesta 401 — Token inválido o ausente

```json
{
  "message": "Unauthenticated."
}
```

### Respuesta 500 — Error interno

```json
{
  "success": false,
  "message": "Descripción del error interno."
}
```

---

## POST /deportescam/socio-preferencia/guardar

Sincroniza las preferencias de horario del socio para un deporte.
La lista enviada **reemplaza completamente** las preferencias existentes para ese deporte.
Si `horarios` viene vacío se eliminan todas las preferencias del deporte (solo si ya existían).

**Autenticación:** Requerida  
**Middleware:** `auth:api_padel`, `seguridadFSG`, `throttle:60,1`

### Body (JSON)

| Campo | Tipo | Requerido | Descripción | Ejemplo |
|-------|------|-----------|-------------|---------|
| `idDeporte` | string | Sí | ID del deporte en **Base64** (obtenido de `/perfil` o `/deporte/lista`) | `Mg==` |
| `horarios` | array | Sí | IDs de horarios seleccionados. Vacío = borrar todas las preferencias del deporte | `[1, 2, 3]` |

```json
{
  "idDeporte": "Mg==",
  "horarios": [1, 2, 3]
}
```

> **Nota:** Todos los `idHorario` deben pertenecer al `idDeporte` enviado y estar en estado `Activo`.

### Respuesta 200 — Preferencias guardadas

```json
{
  "success": true,
  "message": "Preferencias guardadas correctamente."
}
```

### Respuesta 200 — Preferencias eliminadas (horarios vacío)

```json
{
  "success": true,
  "message": "Preferencias eliminadas correctamente."
}
```

### Respuesta 422 — Sin preferencias que borrar

```json
{
  "success": false,
  "message": "No tienes preferencias registradas para este deporte."
}
```

### Respuesta 422 — Horario no pertenece al deporte

```json
{
  "success": false,
  "message": "El horario #5 no pertenece al deporte seleccionado o no está activo."
}
```

### Respuesta 422 — Errores de validación

```json
{
  "success": false,
  "status": 422,
  "message": "Tienes errores de validación",
  "errors": {
    "idDeporte": ["El deporte seleccionado no existe."],
    "horarios": ["El campo horarios debe ser un arreglo."]
  }
}
```

### Respuesta 401 — Token inválido o ausente

```json
{
  "message": "Unauthenticated."
}
```

---

## POST /deportescam/registro-padel/actualizar-contacto

Guarda los cambios de contacto y preferencias de notificación.  
Ver documentación completa en [registropadel.md](registropadel.md#post-deportescamregistro-padelactualizar-contacto).

---

## POST /deportescam/registro-padel/cambiar-password

Actualiza la contraseña del socio verificando la contraseña actual.  
Ver documentación completa en [registropadel.md](registropadel.md#post-deportescamregistro-padelcambiar-password).
