236 lines
7.1 KiB
JavaScript
236 lines
7.1 KiB
JavaScript
const express = require('express');
|
|
const mongoose = require('mongoose');
|
|
const router = express.Router();
|
|
const User = require('./user');
|
|
const multer = require('multer');
|
|
const path = require('path');
|
|
|
|
// Configuración de almacenamiento para música
|
|
const storage = multer.diskStorage({
|
|
destination: function (req, file, cb) {
|
|
cb(null, 'uploads/music');
|
|
},
|
|
filename: function (req, file, cb) {
|
|
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
|
|
cb(null, uniqueSuffix + path.extname(file.originalname));
|
|
}
|
|
});
|
|
|
|
const upload = multer({
|
|
storage: storage,
|
|
limits: { fileSize: 10 * 1024 * 1024 }, // máx 10MB
|
|
fileFilter: function (req, file, cb) {
|
|
if (!file.originalname.match(/\.(mp3)$/)) {
|
|
return cb(new Error('Solo se permiten archivos .mp3'));
|
|
}
|
|
cb(null, true);
|
|
}
|
|
});
|
|
|
|
const routineSchema = new mongoose.Schema({
|
|
title: String,
|
|
createdBy: { type: String, default: "coach-id-ejemplo" },
|
|
language: { type: String, enum: ['es', 'en', 'fr'], default: 'es' },
|
|
duration: Number,
|
|
musicUrl: { type: String, default: "" },
|
|
nombreCompetencia: String,
|
|
tipoCompetencia: { type: String, enum: ['libre', 'técnica'], default: 'libre' },
|
|
modalidad: { type: String, enum: ['solo', 'duo', 'equipo'], default: 'solo' },
|
|
participantes: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }],
|
|
elements: [],
|
|
formaciones: [
|
|
{
|
|
nombreColoquial: String,
|
|
notasTacticas: String,
|
|
duracion: Number,
|
|
atletas: [
|
|
{
|
|
atletaId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
|
|
idPersonalizado: String,
|
|
x: Number,
|
|
y: Number,
|
|
rol: String,
|
|
grupo: String,
|
|
direccion: {
|
|
x1: Number,
|
|
y1: Number,
|
|
x2: Number,
|
|
y2: Number
|
|
},
|
|
figura: String,
|
|
tipoElemento: { type: String, enum: ['TRE', 'híbrido', 'transición'], default: 'transición' },
|
|
codigoElemento: String
|
|
}
|
|
]
|
|
}
|
|
],
|
|
createdAt: { type: Date, default: Date.now }
|
|
});
|
|
|
|
const Routine = mongoose.model('Routine', routineSchema);
|
|
|
|
// GET todas las rutinas
|
|
router.get('/', async (req, res) => {
|
|
try {
|
|
const routines = await Routine.find()
|
|
.populate('participantes', 'name')
|
|
.populate('formaciones.atletas.atletaId', 'name');
|
|
res.json(routines);
|
|
} catch (error) {
|
|
res.status(500).json({ message: 'Error al obtener rutinas', error });
|
|
}
|
|
});
|
|
|
|
// POST nueva rutina
|
|
router.post('/', async (req, res) => {
|
|
try {
|
|
const newRoutine = new Routine(req.body);
|
|
await newRoutine.save();
|
|
res.status(201).json({ message: 'Rutina guardada exitosamente', routine: newRoutine });
|
|
} catch (error) {
|
|
res.status(500).json({ message: 'Error al guardar la rutina', error });
|
|
}
|
|
});
|
|
|
|
// GET rutina por ID
|
|
router.get('/:id', async (req, res) => {
|
|
try {
|
|
const routine = await Routine.findById(req.params.id)
|
|
.populate('participantes', 'name')
|
|
.populate('formaciones.atletas.atletaId', 'name');
|
|
if (!routine) return res.status(404).json({ error: 'Rutina no encontrada' });
|
|
res.json(routine);
|
|
} catch (error) {
|
|
res.status(500).json({ error: 'Error al cargar rutina', details: error });
|
|
}
|
|
});
|
|
|
|
// POST agregar formación
|
|
router.post('/:id/formations', async (req, res) => {
|
|
const { id } = req.params;
|
|
if (!mongoose.Types.ObjectId.isValid(id)) {
|
|
return res.status(400).json({ error: 'ID inválido para rutina' });
|
|
}
|
|
|
|
try {
|
|
const rutina = await Routine.findById(id);
|
|
if (!rutina) return res.status(404).json({ error: 'Rutina no encontrada' });
|
|
|
|
rutina.formaciones.push(req.body);
|
|
|
|
const nuevosAtletas = req.body.atletas.map(a => a.atletaId);
|
|
|
|
nuevosAtletas.forEach(idAtleta => {
|
|
if (!rutina.participantes.includes(idAtleta.toString())) {
|
|
rutina.participantes.push(idAtleta);
|
|
}
|
|
});
|
|
|
|
await rutina.save();
|
|
res.status(200).json({ message: 'Formación agregada exitosamente' });
|
|
} catch (error) {
|
|
console.error('Error al guardar formación:', error);
|
|
res.status(500).json({ error: 'Error al guardar formación', details: error });
|
|
}
|
|
});
|
|
|
|
|
|
// GET formaciones de rutina
|
|
router.get('/:id/formations', async (req, res) => {
|
|
try {
|
|
const rutina = await Routine.findById(req.params.id)
|
|
.populate('formaciones.atletas.atletaId', 'name');
|
|
if (!rutina) return res.status(404).json({ error: 'Rutina no encontrada' });
|
|
|
|
res.status(200).json(rutina.formaciones);
|
|
} catch (error) {
|
|
res.status(500).json({ error: 'Error al obtener formaciones', details: error });
|
|
}
|
|
});
|
|
|
|
// PUT editar formación por índice
|
|
router.put('/:id/formations/:index', async (req, res) => {
|
|
const { id, index } = req.params;
|
|
|
|
if (!mongoose.Types.ObjectId.isValid(id)) {
|
|
return res.status(400).json({ error: 'ID inválido' });
|
|
}
|
|
|
|
const i = parseInt(index);
|
|
if (isNaN(i) || i < 0) {
|
|
return res.status(400).json({ error: 'Índice de formación inválido' });
|
|
}
|
|
|
|
try {
|
|
const rutina = await Routine.findById(id);
|
|
if (!rutina) return res.status(404).json({ error: 'Rutina no encontrada' });
|
|
|
|
rutina.formaciones[i] = req.body;
|
|
await rutina.save();
|
|
res.status(200).json({ message: 'Formación actualizada correctamente' });
|
|
} catch (error) {
|
|
res.status(500).json({ error: 'Error al actualizar formación', details: error });
|
|
}
|
|
});
|
|
|
|
// POST para actualizar tamaño de piscina
|
|
router.post('/:id/piscina', async (req, res) => {
|
|
const { width, height } = req.body;
|
|
try {
|
|
const updated = await Routine.findByIdAndUpdate(
|
|
req.params.id,
|
|
{ $set: { 'piscina.width': width, 'piscina.height': height } },
|
|
{ new: true }
|
|
);
|
|
if (!updated) return res.status(404).json({ message: 'Rutina no encontrada' });
|
|
res.json({ message: 'Piscina actualizada', rutina: updated });
|
|
} catch (error) {
|
|
res.status(500).json({ message: 'Error al actualizar piscina', error });
|
|
}
|
|
});
|
|
|
|
// PUT actualizar todas las formaciones (reordenamiento)
|
|
router.put('/:id', async (req, res) => {
|
|
const { id } = req.params;
|
|
const { formaciones } = req.body;
|
|
|
|
try {
|
|
const rutina = await Routine.findById(id);
|
|
if (!rutina) return res.status(404).json({ error: 'Rutina no encontrada' });
|
|
|
|
rutina.formaciones = formaciones;
|
|
await rutina.save();
|
|
|
|
res.status(200).json({ message: 'Formaciones reordenadas correctamente' });
|
|
} catch (error) {
|
|
res.status(500).json({ message: 'Error al actualizar orden', error });
|
|
}
|
|
});
|
|
|
|
// POST subir música MP3
|
|
router.post('/upload/music', upload.single('music'), (req, res) => {
|
|
if (!req.file) {
|
|
return res.status(400).json({ error: 'No se subió ningún archivo' });
|
|
}
|
|
|
|
const fileUrl = `/uploads/music/${req.file.filename}`;
|
|
res.status(200).json({ url: fileUrl });
|
|
});
|
|
|
|
// GET rutinas asignadas a un atleta
|
|
router.get('/atleta/:id', async (req, res) => {
|
|
const atletaId = req.params.id;
|
|
try {
|
|
const rutinas = await Routine.find({ participantes: atletaId })
|
|
.populate('participantes', 'name')
|
|
.populate('formaciones.atletas.atletaId', 'name');
|
|
res.json(rutinas);
|
|
} catch (err) {
|
|
console.error(err);
|
|
res.status(500).json({ mensaje: "Error al obtener rutinas del atleta" });
|
|
}
|
|
});
|
|
|
|
|
|
module.exports = router;
|