# 🔌 Guía de Integración — Conectar el Campus al Backend

El archivo `campus.html` actualmente funciona con **datos de ejemplo** (arrays dentro del propio HTML). Esta guía explica cómo conectarlo al backend real, paso a paso.

> **No es obligatorio hacerlo todo de golpe.** Puedes migrar sección por sección. Mientras tanto, el campus sigue funcionando con sus datos de ejemplo.

---

## 📌 Concepto clave

Hoy el campus tiene esto dentro del `<script>`:

```javascript
let students = [ {id:1, nom:'Carlos', ...}, ... ];   // ← datos quemados
let courses  = [ ... ];
let asesores = [ ... ];
```

La meta es **reemplazar esos arrays** por datos que vienen del backend:

```javascript
let students = [];   // empieza vacío
let courses  = [];
let asesores = [];

// Al iniciar, los traemos del API
async function cargarDatos() {
  students = await API.students.list();
  courses  = await API.courses.list();
  asesores = await API.advisors.list();
}
```

---

## 🪜 Paso 1 — Incluir los scripts del API

En `campus.html`, justo antes de tu `<script>` principal (cerca del final, antes de `</body>`), agrega:

```html
<script src="js/config.js"></script>
<script src="js/api.js"></script>
<!-- ...aquí va tu <script> principal del campus... -->
```

---

## 🪜 Paso 2 — Cambiar el Login

**Busca** la función `doLogin()` en el campus. **Reemplázala** por:

```javascript
async function doLogin(){
  const role = V('l-role'), user = V('l-user').trim(), pass = V('l-pass');
  try {
    const res = await API.auth.login(user, pass, role);
    TokenStore.set(res.token);
    TokenStore.setUser(res.user);
    S('login-err').style.display = 'none';

    // Trae los datos del backend antes de entrar
    await cargarDatosIniciales();

    currentUser = { ...res.user, role: res.user.rol, name: res.user.nombre };
    showSplash(currentUser, role);
  } catch (err) {
    S('login-err').textContent = err.message;
    S('login-err').style.display = 'block';
  }
}

// Si el token expira, vuelve al login
function onSessionExpired(){
  showPage('pg-login');
  showToast('Tu sesión expiró. Vuelve a iniciar sesión.', 'warn');
}
```

---

## 🪜 Paso 3 — Cargar los datos al entrar

**Agrega** esta función nueva:

```javascript
async function cargarDatosIniciales(){
  try {
    const [sts, crs, pers, mats] = await Promise.all([
      API.students.list(),
      API.courses.list(),
      API.periods.list(),
      API.materials.list(),
    ]);
    // Mapea los nombres del backend (snake_case) a los del campus (camelCase)
    students = sts.map(mapStudentFromApi);
    courses  = crs.map(mapCourseFromApi);
    periodos = pers.map(p => p.nombre);
    materials = mats.map(mapMaterialFromApi);

    // Solo el admin trae la lista de asesores
    if (currentUser?.rol === 'admin') {
      asesores = (await API.advisors.list()).map(mapAdvisorFromApi);
    }
  } catch (err) {
    showToast('Error cargando datos: ' + err.message, 'error');
  }
}
```

---

## 🪜 Paso 4 — Funciones de mapeo

El backend usa nombres como `fecha_nac`, `es_regalo`; el campus usa `birth`, `esRegalo`.
**Agrega** estos traductores:

```javascript
function mapStudentFromApi(a){
  return {
    id: a.id, nom: a.nombre, ape: a.apellido, dni: a.dni, birth: a.fecha_nac,
    tel: a.telefono, email: a.email, addr: a.direccion, curso: a.curso,
    estado: a.estado, ingreso: a.fecha_ingreso, periodo: a.periodo,
    precio: +a.precio, cuota0: +a.cuota0, fecha0: a.fecha0,
    cuota1: +a.cuota1, fecha1: a.fecha1, cuota2: +a.cuota2, fecha2: a.fecha2,
    certificado: a.certificado, esRegalo: a.es_regalo, cursoRegalo: a.curso_regalo,
    user: a.username, pass: '', _financeRaw: a.finanzas,
  };
}
function mapCourseFromApi(c){
  return {
    id: c.id, nom: c.nombre, desc: c.descripcion, ins: c.instructor,
    mod: c.modalidad, lugar: c.lugar, cap: c.capacidad, periodo: c.periodo,
    portada: c.portada, portadaIco: c.portada_ico, portadaUrl: c.portada_url,
    esEnVivo: c.es_en_vivo, esRegalo: c.es_regalo, sesiones: c.sesiones, alumnos: 0,
  };
}
function mapMaterialFromApi(m){
  return { id: m.id, nom: m.nombre, tipo: m.tipo, curso: m.curso,
    size: m.tamano, fecha: m.fecha, sesion: m.sesion, url: m.url };
}
function mapAdvisorFromApi(a){
  return { id: a.id, nom: a.nombre, ape: a.apellido, email: a.email,
    tel: a.telefono, user: a.username };
}
```

---

## 🪜 Paso 5 — Guardar cambios en el backend

Cada vez que el campus **crea/edita/borra**, ahora debe avisar al backend.
Ejemplo con `saveStudent()`:

```javascript
async function saveStudent(){
  // ...validaciones que ya tienes...
  const payload = {
    nombre: nom, apellido: ape, dni: V('ms-dni'), fecha_nac: V('ms-birth'),
    telefono: V('ms-tel'), email: V('ms-email'), direccion: V('ms-addr'),
    curso: V('ms-curso'), estado: V('ms-estado'), periodo: periodo,
    precio: parseFloat(V('ms-precio'))||0,
    cuota0: ..., cuota1: ..., cuota2: ...,
    es_regalo: ..., curso_regalo: ...,
  };
  try {
    if (editingStudentId) {
      await API.students.update(editingStudentId, payload);
    } else {
      const res = await API.students.create(payload);
      // res.credenciales tiene el usuario y contraseña generados
    }
    await cargarDatosIniciales();   // recarga la lista
    renderStudentsTable(students);
  } catch (err) {
    showToast('Error: ' + err.message, 'error');
  }
}
```

Aplica el mismo patrón a:
- `saveCourse()` → `API.courses.create/update`
- `saveAsesor()` → `API.advisors.create/update`
- `addPeriod()` → `API.periods.create`
- `saveMat()` → `API.materials.create`
- `execDel()` → `API.{recurso}.remove(id)`

---

## ✅ Resultado final

Cuando termines:
- Los datos **persisten** en tu base de datos (no se pierden al recargar)
- Cada rol solo ve lo que le corresponde (lo valida el backend)
- Las contraseñas están **hasheadas y seguras**
- Nadie puede ver datos de otros aunque abra F12

---

## 💡 Recomendación de migración

Hazlo en este orden para no romper nada:
1. ✅ Login (Paso 2)
2. ✅ Cargar datos al entrar (Pasos 3-4)
3. ✅ Guardar alumnos
4. ✅ Guardar cursos y periodos
5. ✅ Guardar asesores y materiales
6. ✅ Eliminar (todos los recursos)

Prueba cada paso antes de seguir al siguiente.
