document.addEventListener('DOMContentLoaded', async () => {
const rutinaId = new URLSearchParams(window.location.search).get('routineId');
if (!rutinaId) return alert('No se proporcionó ID de rutina.');
const select = document.getElementById('selectAtleta');
const tituloRutina = document.getElementById('tituloRutina');
const tipoRutina = document.getElementById('tipoRutina');
const modalidadRutina = document.getElementById('modalidadRutina');
const inputFigura = document.getElementById('figura');
const btnEditarFormacion = document.getElementById('btnEditarFormacion');
const btnGuardarFormacion = document.getElementById('btnGuardarFormacion');
let editIndex = null;
let indexSeleccionado = null;
let modoDireccion = false;
let indexAtletaDireccion = null;
const rutina = await fetch(`/api/rutinas/${rutinaId}`).then(res => res.json());
const modalidad = rutina.modalidad;
const audioPlayer = document.getElementById('audioPlayer');
if (rutina.musicUrl) {
audioPlayer.src = rutina.musicUrl;
}
tituloRutina.textContent = rutina.title || rutina.nombreCompetencia;
tipoRutina.textContent = rutina.tipoCompetencia;
modalidadRutina.textContent = modalidad;
const atletas = await fetch('/api/users/athletes').then(res => res.json());
atletas.forEach(a => {
const opt = document.createElement('option');
opt.value = JSON.stringify({ id: a._id, nombre: a.name, idPers: a.idPersonalizado });
opt.textContent = `${a.name} (${a.idPersonalizado || 'sin ID'})`;
select.appendChild(opt);
});
select.addEventListener('change', () => {
const datos = JSON.parse(select.value || '{}');
select.dataset.id = datos.id; // << GUARDAS el ObjectId real
if (datos.idPers) {
document.getElementById('idPersonalizado').value = datos.idPers;
document.getElementById('idPersonalizado').disabled = true;
} else {
document.getElementById('idPersonalizado').value = '';
document.getElementById('idPersonalizado').disabled = false;
}
});
let figurasFINA = [];
try {
const res = await fetch('/catalog/figurasFINA.json');
figurasFINA = await res.json();
const sugerenciasBox = document.getElementById('sugerenciasFigura');
inputFigura.addEventListener('input', () => {
const val = inputFigura.value.trim().toLowerCase();
sugerenciasBox.innerHTML = '';
if (val.length < 1) return;
const matches = figurasFINA.filter(f => f.nombre.toLowerCase().includes(val));
matches.forEach(figura => {
const item = document.createElement('button');
item.type = 'button';
item.textContent = figura.nombre;
item.onclick = () => {
inputFigura.value = figura.nombre;
inputFigura.title = `${figura.descripcion} (${figura.categoria})`;
sugerenciasBox.innerHTML = '';
mostrarPreview(figura);
const codigoInput = document.getElementById("codigoElemento");
if (codigoInput && figura.codigoElemento) {
codigoInput.value = figura.codigoElemento;
}
};
sugerenciasBox.appendChild(item);
});
});
inputFigura.addEventListener('blur', () => {
setTimeout(() => sugerenciasBox.innerHTML = '', 200);
});
function mostrarPreview(figura) {
document.getElementById('previewFigura').innerHTML = `
${figura.descripcion} ${figura.categoria}
`; const codigoInput = document.getElementById("codigoElemento"); if (codigoInput && figura.codigoElemento) { codigoInput.value = figura.codigoElemento; } } } catch (err) { console.warn('❌ No se pudo cargar el catálogo FINA:', err); } const tipoPiscinaSelect = document.getElementById('tipoPiscina'); const medidasPiscina = { olimpica: { width: 1000, height: 500 }, semiolimpica: { width: 750, height: 375 }, fosa: { width: 600, height: 600 } }; let tipoSeleccionado = rutina.tipoPiscina || 'olimpica'; tipoPiscinaSelect.value = tipoSeleccionado; let piscinaWidth = medidasPiscina[tipoSeleccionado].width; let piscinaHeight = medidasPiscina[tipoSeleccionado].height; tipoPiscinaSelect.addEventListener('change', async () => { tipoSeleccionado = tipoPiscinaSelect.value; piscinaWidth = medidasPiscina[tipoSeleccionado].width; piscinaHeight = medidasPiscina[tipoSeleccionado].height; // Actualiza dimensiones visuales stage.width(piscinaWidth); stage.height(piscinaHeight); document.getElementById('piscina').style.width = `${piscinaWidth}px`; document.getElementById('piscina').style.height = `${piscinaHeight}px`; document.getElementById('piscinaContainer').style.width = `${piscinaWidth + 20}px`; // Redibujar cuadrícula layer.destroyChildren(); dibujarCuadricula(layer, piscinaWidth, piscinaHeight); formacionActual.forEach(a => dibujarAtleta(a)); // Guardar en BD try { await fetch(`/api/rutinas/${rutinaId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ tipoPiscina: tipoSeleccionado }) }); } catch (err) { console.error('Error al actualizar tipoPiscina:', err); } }); // Escalas de conversión a metros const escalaX = 25 / piscinaWidth; const escalaY = 20 / piscinaHeight; function convertirAMetros(pxX, pxY) { return { metrosX: (pxX * escalaX).toFixed(2), metrosY: (pxY * escalaY).toFixed(2) }; } const stage = new Konva.Stage({ container: 'piscina', width: piscinaWidth, height: piscinaHeight }); const layer = new Konva.Layer(); stage.add(layer); const divPiscina = document.getElementById('piscina'); divPiscina.style.width = `${piscinaWidth}px`; divPiscina.style.height = `${piscinaHeight}px`; document.getElementById('piscinaContainer').style.width = `${piscinaWidth + 20}px`; dibujarCuadricula(layer, piscinaWidth, piscinaHeight); function dibujarCuadricula(layer, ancho, alto, tamano = 45) { for (let x = 0; x <= ancho; x += tamano) { layer.add(new Konva.Line({ points: [x, 0, x, alto], stroke: '#cceeff', strokeWidth: 1 })); } for (let y = 0; y <= alto; y += tamano) { layer.add(new Konva.Line({ points: [0, y, ancho, y], stroke: '#cceeff', strokeWidth: 1 })); } } let formacionActual = []; let atletasKonva = {}; let currentAtleta = null; const maxAtletas = modalidad === 'solo' ? 1 : modalidad === 'duo' ? 2 : 8; document.getElementById('btnAgregarAtleta').addEventListener('click', () => { if (formacionActual.length >= maxAtletas) { alert(`Modalidad "${modalidad}" permite un máximo de ${maxAtletas} atletas.`); return; } const idAtleta = select.dataset.id; const rol = document.getElementById('rolAtleta').value.trim().toLowerCase(); const idPersonalizado = document.getElementById('idPersonalizado').value.trim(); const figura = inputFigura?.value.trim(); const tipoElemento = document.getElementById('tipoElemento').value; const codigoElemento = document.getElementById('codigoElemento').value.trim(); if (!idAtleta || !rol || !idPersonalizado) { alert('Faltan datos del atleta'); return; } currentAtleta = { atletaId: idAtleta, rol, idPersonalizado, figura, tipoElemento, codigoElemento }; alert('Haz clic en la piscina para colocarlo'); }); stage.on('click', () => { if (!currentAtleta || modoDireccion) return; const pos = stage.getPointerPosition(); const metros = convertirAMetros(pos.x, pos.y); console.log(`📏 Posición en metros: (${metros.metrosX}m, ${metros.metrosY}m)`); const atletaObj = { ...currentAtleta, x: pos.x, y: pos.y, grupo: '', direccion: null }; formacionActual.push(atletaObj); dibujarAtleta(atletaObj); currentAtleta = null; document.getElementById('rolAtleta').value = ''; document.getElementById('idPersonalizado').value = ''; inputFigura.value = ''; inputFigura.title = ''; document.getElementById('previewFigura').innerHTML = ''; }); function dibujarAtleta(atleta) { const color = atleta.rol === 'volador' ? 'purple' : atleta.rol === 'pilar' ? 'blue' : 'red'; const metros = convertirAMetros(atleta.x, atleta.y); const circle = new Konva.Circle({ x: atleta.x, y: atleta.y, radius: 15, fill: color, stroke: 'white', strokeWidth: 2, draggable: !modoDireccion }); const text = new Konva.Text({ x: atleta.x, y: atleta.y, text: atleta.idPersonalizado, fontSize: 12, fill: 'white', fontStyle: 'bold', align: 'center' }); text.offsetX(text.width() / 2); text.offsetY(text.height() / 2); const figuraText = new Konva.Text({ x: atleta.x - 25, y: atleta.y + 18, text: atleta.figura || '', fontSize: 10, fill: '#333', fontStyle: 'italic' }); figuraText.listening(false); const coordText = new Konva.Text({ x: atleta.x - 35, y: atleta.y + 30, text: `${metros.metrosX}m, ${metros.metrosY}m`, fontSize: 9, fill: '#666' }); coordText.listening(false); let flecha = null; if (atleta.direccion) { flecha = new Konva.Arrow({ points: [atleta.direccion.x1, atleta.direccion.y1, atleta.direccion.x2, atleta.direccion.y2], stroke: 'black', fill: 'black', strokeWidth: 2, pointerLength: 10, pointerWidth: 10, dash: [4, 4] }); layer.add(flecha); } circle.on('dblclick', () => { const i = formacionActual.findIndex(a => a.idPersonalizado === atleta.idPersonalizado); const html = `