Feature: Musicando Ideias profissional com gerador de 3 versoes, sintese de audio MiniMax music-2.0, player com loop/equalizer, mapeamento BNCC e exportacao PDF/TXT/MP3

This commit is contained in:
2026-08-31 11:17:02 +00:00
parent 1ef002ff1a
commit 88d7163b9f
4 changed files with 1016 additions and 188 deletions
+465 -79
View File
@@ -6722,7 +6722,7 @@ window.toggleCustomAudio = (btn) => {
};
};
// ============================================================
// MUSICANDO IDEIAS
// MUSICANDO IDEIAS (ESTÚDIO PROFISSIONAL)
// ============================================================
const barBtnMusica = document.getElementById('barBtnMusica');
const musicaModal = document.getElementById('musicaModal');
@@ -6731,123 +6731,445 @@ window.toggleCustomAudio = (btn) => {
const musicaHistoryModal = document.getElementById('musicaHistoryModal');
const btnCloseMusicaHistory = document.getElementById('btnCloseMusicaHistory');
const musicaTemplateSelect = document.getElementById('musicaTemplateSelect');
const musicaTemaInput = document.getElementById('musicaTemaInput');
const musicaTurmaSelect = document.getElementById('musicaTurmaSelect');
const musicaFaixaEtaria = document.getElementById('musicaFaixaEtaria');
const musicaRitmo = document.getElementById('musicaRitmo');
const musicaTemaInput = document.getElementById('musicaTemaInput');
const musicaIntensidade = document.getElementById('musicaIntensidade');
const musicaVozSelect = document.getElementById('musicaVozSelect');
const musicaDuracaoSelect = document.getElementById('musicaDuracaoSelect');
const btnGenerateMusica = document.getElementById('btnGenerateMusica');
const musicaGenerateLoader = document.getElementById('musicaGenerateLoader');
const musicaResultArea = document.getElementById('musicaResultArea');
const musicaTextOutput = document.getElementById('musicaTextOutput');
const btnCopyMusica = document.getElementById('btnCopyMusica');
const btnDownloadMusicaPdf = document.getElementById('btnDownloadMusicaPdf');
let currentMusicaEstrofes = 3;
let currentMusica = '';
// Elementos do Lado Direito
const musicaBnccBadge = document.getElementById('musicaBnccBadge');
const musicaAudioPlayerBox = document.getElementById('musicaAudioPlayerBox');
const musicaAudioPlayer = document.getElementById('musicaAudioPlayer');
const musicaPlayerTitle = document.getElementById('musicaPlayerTitle');
const btnToggleMusicLoop = document.getElementById('btnToggleMusicLoop');
const btnDownloadMusicaAudio = document.getElementById('btnDownloadMusicaAudio');
const musicaWaveformVisualizer = document.getElementById('musicaWaveformVisualizer');
document.querySelectorAll('.btn-musica-estrofes').forEach(btn => {
btn.addEventListener('click', (e) => {
document.querySelectorAll('.btn-musica-estrofes').forEach(b => b.classList.remove('active'));
e.target.classList.add('active');
currentMusicaEstrofes = parseInt(e.target.dataset.estrofes);
});
});
const musicaVersionsTabs = document.getElementById('musicaVersionsTabs');
const btnTabVersaoPrincipal = document.getElementById('btnTabVersaoPrincipal');
const btnTabVersaoCurta = document.getElementById('btnTabVersaoCurta');
const btnTabVersaoDancante = document.getElementById('btnTabVersaoDancante');
const musicaPlaceholderText = document.getElementById('musicaPlaceholderText');
const musicaActiveContentBox = document.getElementById('musicaActiveContentBox');
const musicaActiveTitle = document.getElementById('musicaActiveTitle');
const musicaActiveBadge = document.getElementById('musicaActiveBadge');
const musicaActiveLyrics = document.getElementById('musicaActiveLyrics');
const musicaPedagogicalTipBox = document.getElementById('musicaPedagogicalTipBox');
const musicaPedagogicalTipText = document.getElementById('musicaPedagogicalTipText');
const btnCopyActiveLyrics = document.getElementById('btnCopyActiveLyrics');
const btnDownloadActiveTxt = document.getElementById('btnDownloadActiveTxt');
const btnExportActivePdf = document.getElementById('btnExportActivePdf');
// TEMPLATES PRÉ-CONFIGURADOS DO MUSICANDO IDEIAS
const MUSICA_TEMPLATES = {
horta: {
tema: "Plantar sementinhas na horta da escola, regar a terra com carinho, ver os brotinhos crescerem e colher vegetais coloridos e saudáveis.",
faixa: "Crianças pequenas (4 anos a 5 anos e 11 meses)",
ritmo: "Cantiga de Roda",
intensidade: "moderada",
voz: "mulher",
duracao: "1min",
instrumentos: ["Violão acústico", "Flauta doce", "Pandeiro e percussão", "Xilofone infantil"]
},
familia: {
tema: "O amor e o carinho da família, os abraços acolhedores na chegada e na saída da escola, gratidão e respeito aos pais e avós.",
faixa: "Crianças bem pequenas (1 ano e 7 meses a 3 anos e 11 meses)",
ritmo: "Canção de Ninar",
intensidade: "calma",
voz: "mulher",
duracao: "1min",
instrumentos: ["Violão acústico", "Metalofone e sinos", "Flauta doce"]
},
higiene: {
tema: "Lavar as mãozinhas com água e sabão antes do lanche, escovar os dentinhos após comer e cuidar do corpinho limpinho e cheiroso.",
faixa: "Crianças pequenas (4 anos a 5 anos e 11 meses)",
ritmo: "Pop Infantil Alegre",
intensidade: "dancante",
voz: "crianca",
duracao: "1min",
instrumentos: ["Teclado e sintetizador", "Pandeiro e percussão", "Palmas e coro de crianças"]
},
mindlab: {
tema: "Pensar antes de jogar, esperar a sua vez com calma, cooperar com os colegas de equipe e comemorar as jogadas inteligentes.",
faixa: "Crianças pequenas (4 anos a 5 anos e 11 meses)",
ritmo: "Cantiga de Roda",
intensidade: "moderada",
voz: "homem",
duracao: "1min",
instrumentos: ["Violão acústico", "Pandeiro e percussão", "Xilofone infantil"]
},
verao: {
tema: "O sol brilhando no céu, brincadeiras com água e areia no parque, beber água fresca e sentir a brisa da natureza.",
faixa: "Crianças pequenas (4 anos a 5 anos e 11 meses)",
ritmo: "Forrózinho Lúdico",
intensidade: "dancante",
voz: "mulher",
duracao: "1min",
instrumentos: ["Acordeon", "Pandeiro e percussão", "Violão acústico", "Palmas e coro de crianças"]
},
alfabeto: {
tema: "As letrinhas do alfabeto dançando, descobrindo os sons das vogais A E I O U e escrevendo o próprio nome com alegria.",
faixa: "Crianças pequenas (4 anos a 5 anos e 11 meses)",
ritmo: "Marchinha Escolar",
intensidade: "dancante",
voz: "mulher",
duracao: "1min",
instrumentos: ["Pandeiro e percussão", "Metalofone e sinos", "Palmas e coro de crianças"]
},
emocoes: {
tema: "Reconhecer quando estamos felizes, com medo, bravos ou tranquilos, respirar fundo e receber um abraço amigo na roda.",
faixa: "Crianças bem pequenas (1 ano e 7 meses a 3 anos e 11 meses)",
ritmo: "Canção de Ninar",
intensidade: "calma",
voz: "mulher",
duracao: "1min",
instrumentos: ["Violão acústico", "Flauta doce", "Metalofone e sinos"]
}
};
// Estado atual da música gerada
let activeMusicaData = {
titulo: '',
versaoPrincipal: '',
versaoCurta: '',
versaoDancante: '',
bnccCampos: '',
instrumentos: '',
dicas: '',
audioUrl: '',
tema: '',
ritmo: '',
faixaEtaria: ''
};
let activeMusicaTab = 'principal';
let isLoopActive = false;
// Carregar turmas no seletor
const loadTurmasForMusica = async () => {
if (!musicaTurmaSelect) return;
try {
const res = await fetch('/api/turmas');
if (res.ok) {
const turmas = await res.json();
musicaTurmaSelect.innerHTML = '<option value="">-- Selecionar Turma --</option>';
turmas.forEach(t => {
const opt = document.createElement('option');
opt.value = t.id;
opt.textContent = `${t.nome} (${t.ano || '2026'})`;
opt.dataset.nome = t.nome;
musicaTurmaSelect.appendChild(opt);
});
}
} catch (err) {
console.warn('Erro ao carregar turmas para música:', err);
}
};
// Abrir Modal
if (barBtnMusica) {
barBtnMusica.addEventListener('click', () => {
musicaModal.style.display = 'flex';
musicaTemaInput.value = '';
musicaResultArea.style.display = 'none';
musicaGenerateLoader.style.display = 'none';
btnGenerateMusica.disabled = false;
currentMusica = '';
loadTurmasForMusica();
if (!musicaTemaInput.value) {
applyMusicaTemplate('horta');
}
});
}
if (btnCloseMusicaModal) musicaModal.addEventListener('click', (e) => { if(e.target === musicaModal) musicaModal.style.display = 'none'; });
if (btnCloseMusicaModal) btnCloseMusicaModal.addEventListener('click', () => musicaModal.style.display = 'none');
if (btnOpenMusicaHistory) {
btnOpenMusicaHistory.addEventListener('click', () => {
musicaHistoryModal.style.display = 'flex';
loadMusicaHistory();
if (btnCloseMusicaModal) {
btnCloseMusicaModal.addEventListener('click', () => {
musicaModal.style.display = 'none';
if (musicaAudioPlayer) musicaAudioPlayer.pause();
});
}
if (btnCloseMusicaHistory) btnCloseMusicaHistory.addEventListener('click', () => musicaHistoryModal.style.display = 'none');
musicaHistoryModal.addEventListener('click', (e) => { if(e.target === musicaHistoryModal) musicaHistoryModal.style.display = 'none'; });
musicaModal.addEventListener('click', (e) => {
if (e.target === musicaModal) {
musicaModal.style.display = 'none';
if (musicaAudioPlayer) musicaAudioPlayer.pause();
}
});
// Aplicar Template
const applyMusicaTemplate = (key) => {
const tmpl = MUSICA_TEMPLATES[key];
if (!tmpl) return;
if (musicaTemaInput) musicaTemaInput.value = tmpl.tema;
if (musicaFaixaEtaria) musicaFaixaEtaria.value = tmpl.faixa;
if (musicaRitmo) musicaRitmo.value = tmpl.ritmo;
if (musicaIntensidade) musicaIntensidade.value = tmpl.intensidade;
if (musicaVozSelect) musicaVozSelect.value = tmpl.voz;
if (musicaDuracaoSelect) musicaDuracaoSelect.value = tmpl.duracao;
// Ajustar checkboxes de instrumentos
const checkboxes = document.querySelectorAll('#musicaInstrumentsContainer input[type="checkbox"]');
checkboxes.forEach(cb => {
cb.checked = tmpl.instrumentos.includes(cb.value);
});
};
if (musicaTemplateSelect) {
musicaTemplateSelect.addEventListener('change', (e) => {
if (e.target.value) {
applyMusicaTemplate(e.target.value);
}
});
}
// Alternar Versões no Painel Direito
const switchMusicaVersionTab = (tab) => {
activeMusicaTab = tab;
[btnTabVersaoPrincipal, btnTabVersaoCurta, btnTabVersaoDancante].forEach(b => {
if (b) {
b.classList.remove('active');
b.style.background = 'transparent';
b.style.color = 'var(--text-secondary)';
}
});
let currentLyrics = '';
let badgeText = '';
if (tab === 'principal') {
if (btnTabVersaoPrincipal) {
btnTabVersaoPrincipal.classList.add('active');
btnTabVersaoPrincipal.style.background = 'rgba(168,85,247,0.15)';
btnTabVersaoPrincipal.style.color = '#c084fc';
}
currentLyrics = activeMusicaData.versaoPrincipal;
badgeText = '🌟 Versão Completa (com gestos)';
} else if (tab === 'curta') {
if (btnTabVersaoCurta) {
btnTabVersaoCurta.classList.add('active');
btnTabVersaoCurta.style.background = 'rgba(168,85,247,0.15)';
btnTabVersaoCurta.style.color = '#c084fc';
}
currentLyrics = activeMusicaData.versaoCurta;
badgeText = '⚡ Rascunho / Memorização Rápida';
} else if (tab === 'dancante') {
if (btnTabVersaoDancante) {
btnTabVersaoDancante.classList.add('active');
btnTabVersaoDancante.style.background = 'rgba(168,85,247,0.15)';
btnTabVersaoDancante.style.color = '#c084fc';
}
currentLyrics = activeMusicaData.versaoDancante;
badgeText = '🎉 Versão Dançante / Roda';
}
if (musicaActiveBadge) musicaActiveBadge.textContent = badgeText;
if (musicaActiveLyrics) musicaActiveLyrics.textContent = currentLyrics || 'Nenhuma letra para esta versão.';
};
if (btnTabVersaoPrincipal) btnTabVersaoPrincipal.addEventListener('click', () => switchMusicaVersionTab('principal'));
if (btnTabVersaoCurta) btnTabVersaoCurta.addEventListener('click', () => switchMusicaVersionTab('curta'));
if (btnTabVersaoDancante) btnTabVersaoDancante.addEventListener('click', () => switchMusicaVersionTab('dancante'));
// Controle de Loop de Áudio
if (btnToggleMusicLoop) {
btnToggleMusicLoop.addEventListener('click', () => {
isLoopActive = !isLoopActive;
if (musicaAudioPlayer) musicaAudioPlayer.loop = isLoopActive;
btnToggleMusicLoop.textContent = isLoopActive ? '🔁 Loop: LIGADO' : '🔁 Loop: Desligado';
btnToggleMusicLoop.style.background = isLoopActive ? 'rgba(16, 185, 129, 0.2)' : 'rgba(255,255,255,0.05)';
btnToggleMusicLoop.style.color = isLoopActive ? '#34d399' : 'var(--text-secondary)';
});
}
// Equalizer / Waveform Animation quando toca
if (musicaAudioPlayer) {
musicaAudioPlayer.addEventListener('play', () => {
const bars = document.querySelectorAll('#musicaWaveformVisualizer .wave-bar');
bars.forEach(b => b.classList.add('wave-active'));
});
musicaAudioPlayer.addEventListener('pause', () => {
const bars = document.querySelectorAll('#musicaWaveformVisualizer .wave-bar');
bars.forEach(b => b.classList.remove('wave-active'));
});
}
// --- GERAR MÚSICA (COMPOR 3 VERSÕES + ÁUDIO) ---
if (btnGenerateMusica) {
btnGenerateMusica.addEventListener('click', async () => {
const tema = musicaTemaInput.value.trim();
const tema = (musicaTemaInput?.value || '').trim();
if (!tema) {
showToast('Por favor, informe o tema da música.', 'error');
await showCustomAlert('Aviso', 'Por favor, informe a ideia ou tema da música.');
return;
}
// Coletar instrumentos selecionados
const selectedInstruments = Array.from(
document.querySelectorAll('#musicaInstrumentsContainer input[type="checkbox"]:checked')
).map(cb => cb.value).join(', ');
btnGenerateMusica.disabled = true;
musicaResultArea.style.display = 'none';
musicaGenerateLoader.style.display = 'flex';
if (musicaGenerateLoader) musicaGenerateLoader.style.display = 'flex';
try {
const response = await fetch('/api/musicas/generate', {
const res = await fetch('/api/musicas/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
faixaEtaria: musicaFaixaEtaria.value,
estrofes: currentMusicaEstrofes,
ritmo: musicaRitmo.value,
tema: tema
tema,
faixaEtaria: musicaFaixaEtaria?.value,
ritmo: musicaRitmo?.value,
instrumentos: selectedInstruments || 'Violão acústico, Pandeiro e Flauta',
intensidade: musicaIntensidade?.value || 'moderada',
duracao: musicaDuracaoSelect?.value || '1min',
voz: musicaVozSelect?.value || 'mulher',
turmaId: musicaTurmaSelect?.value || null,
gerarAudio: true
})
});
const data = await response.json();
if (response.ok) {
currentMusica = data.musica;
musicaTextOutput.innerHTML = window.marked ? marked.parse(currentMusica) : currentMusica;
musicaResultArea.style.display = 'flex';
const data = await res.json();
if (res.ok && data.success) {
activeMusicaData = {
titulo: data.titulo || `Música: ${tema}`,
versaoPrincipal: data.versaoPrincipal,
versaoCurta: data.versaoCurta,
versaoDancante: data.versaoDancante,
bnccCampos: data.bnccCampos,
instrumentos: data.instrumentosSugeridos || selectedInstruments,
dicas: data.dicasPedagogicas,
audioUrl: data.audioUrl,
tema: tema,
ritmo: data.ritmo || musicaRitmo?.value,
faixaEtaria: data.faixaEtaria || musicaFaixaEtaria?.value
};
// Atualizar UI
if (musicaPlaceholderText) musicaPlaceholderText.style.display = 'none';
if (musicaVersionsTabs) musicaVersionsTabs.style.display = 'flex';
if (musicaActiveContentBox) musicaActiveContentBox.style.display = 'flex';
if (musicaActiveTitle) musicaActiveTitle.textContent = activeMusicaData.titulo;
if (musicaBnccBadge) {
musicaBnccBadge.textContent = `BNCC: ${activeMusicaData.bnccCampos.split('•')[0].trim()}`;
musicaBnccBadge.style.display = 'inline-block';
}
if (musicaPedagogicalTipText && activeMusicaData.dicas) {
musicaPedagogicalTipText.textContent = activeMusicaData.dicas;
musicaPedagogicalTipBox.style.display = 'block';
}
// Se gerou áudio com MiniMax
if (data.audioUrl) {
musicaAudioPlayer.src = data.audioUrl;
if (musicaPlayerTitle) musicaPlayerTitle.textContent = activeMusicaData.titulo;
if (btnDownloadMusicaAudio) btnDownloadMusicaAudio.href = data.audioUrl;
if (musicaAudioPlayerBox) musicaAudioPlayerBox.style.display = 'flex';
} else {
if (musicaAudioPlayerBox) musicaAudioPlayerBox.style.display = 'none';
}
switchMusicaVersionTab('principal');
showToast('3 versões de música pedagógica compostas com sucesso!', 'success');
} else {
showToast(data.error || 'Erro ao gerar música.', 'error');
await showCustomAlert('Erro', data.error || 'Erro ao compor música.');
}
} catch (err) {
showToast('Erro de conexão.', 'error');
console.error('Erro ao compor música:', err);
await showCustomAlert('Erro', 'Não foi possível conectar ao servidor: ' + err.message);
} finally {
musicaGenerateLoader.style.display = 'none';
btnGenerateMusica.disabled = false;
if (musicaGenerateLoader) musicaGenerateLoader.style.display = 'none';
}
});
}
if (btnCopyMusica) {
btnCopyMusica.addEventListener('click', () => {
if (currentMusica) {
navigator.clipboard.writeText(currentMusica);
showToast('Música copiada para a área de transferência!', 'success');
// Copiar Letra Ativa
if (btnCopyActiveLyrics) {
btnCopyActiveLyrics.addEventListener('click', () => {
const text = musicaActiveLyrics?.textContent || '';
if (text) {
navigator.clipboard.writeText(`${activeMusicaData.titulo}\n\n${text}`);
showToast('Letra copiada para a área de transferência!', 'success');
}
});
}
if (btnDownloadMusicaPdf) {
btnDownloadMusicaPdf.addEventListener('click', () => {
if (!currentMusica) return;
// Baixar Letra TXT
if (btnDownloadActiveTxt) {
btnDownloadActiveTxt.addEventListener('click', () => {
const text = musicaActiveLyrics?.textContent || '';
if (!text) return;
const content = `MÚSICA PEDAGÓGICA - PEDAGOGIA\n========================================\nTítulo: ${activeMusicaData.titulo}\nFaixa Etária: ${activeMusicaData.faixaEtaria}\nRitmo: ${activeMusicaData.ritmo}\nBNCC: ${activeMusicaData.bnccCampos}\nInstrumentos: ${activeMusicaData.instrumentos}\n========================================\n\n${text}\n\n----------------------------------------\nOrientação Pedagógica:\n${activeMusicaData.dicas}\n`;
const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = `musica_${(activeMusicaData.titulo || 'pedagogica').replace(/[^a-zA-Z0-9_-]/g, '_').toLowerCase()}.txt`;
document.body.appendChild(link);
link.click();
link.remove();
});
}
// Exportar PDF Formatado
if (btnExportActivePdf) {
btnExportActivePdf.addEventListener('click', () => {
const lyrics = musicaActiveLyrics?.textContent || '';
if (!lyrics) return;
const printWindow = window.open('', '_blank');
printWindow.document.write(`
<html>
<head>
<title>Música - Assistente PedaGog</title>
<title>${activeMusicaData.titulo} - PedaGog</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;600;700&family=Outfit:wght@400;600;700&display=swap" rel="stylesheet">
<style>
body { font-family: 'Outfit', 'Inter', sans-serif; padding: 40px; color: #333; line-height: 1.6; }
h1, h2, h3 { color: #10b981; margin-top: 24px; margin-bottom: 12px; }
@media print { body { padding: 0; } button { display: none; } }
body { font-family: 'Fredoka', 'Outfit', sans-serif; padding: 40px; color: #1e293b; background: #fffdfa; line-height: 1.7; }
.header-box { border-bottom: 3px dashed #a855f7; padding-bottom: 16px; margin-bottom: 24px; }
h1 { color: #7c3aed; margin: 0 0 8px 0; font-size: 2rem; }
.meta-tags { display: flex; gap: 12px; font-size: 0.9rem; color: #64748b; font-weight: 600; margin-bottom: 8px; flex-wrap: wrap; }
.meta-tag { background: #f3e8ff; color: #7e22ce; padding: 4px 10px; border-radius: 6px; }
.lyrics-box { font-size: 1.15rem; background: #f8fafc; padding: 24px; border-radius: 12px; border: 1px solid #e2e8f0; white-space: pre-wrap; margin-bottom: 24px; box-shadow: 0 2px 4px rgba(0,0,0,0.02); }
.tip-box { background: #f0fdf4; border: 1px solid #bbf7d0; color: #166534; padding: 14px 18px; border-radius: 8px; font-size: 0.92rem; }
@media print { body { padding: 20px; } button { display: none; } }
</style>
</head>
<body>
<div style="max-width: 800px; margin: 0 auto;">
<div style="display: flex; justify-content: space-between; align-items: center; border-bottom: 2px solid #e2e8f0; padding-bottom: 10px; margin-bottom: 20px;">
<h1 style="margin: 0;">🎵 Música Pedagógica</h1>
<button onclick="window.print()" style="background: #10b981; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-weight: bold;">Imprimir / PDF</button>
<div style="max-width: 750px; margin: 0 auto;">
<div class="header-box">
<div style="display: flex; justify-content: space-between; align-items: flex-start;">
<div>
<h1>🎵 ${activeMusicaData.titulo}</h1>
<div class="meta-tags">
<span class="meta-tag">👶 ${activeMusicaData.faixaEtaria}</span>
<span class="meta-tag">🥁 ${activeMusicaData.ritmo}</span>
<span class="meta-tag">📚 ${activeMusicaData.bnccCampos.split('•')[0]}</span>
</div>
<div style="font-size: 0.85rem; color: #64748b;">🎸 Instrumentos: ${activeMusicaData.instrumentos}</div>
</div>
<button onclick="window.print()" style="background: #a855f7; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-weight: bold; font-family: sans-serif;">🖨 Imprimir / Salvar PDF</button>
</div>
</div>
<div class="lyrics-box">${lyrics}</div>
${activeMusicaData.dicas ? `
<div class="tip-box">
💡 <strong>Vivência Pedagógica Sugerida:</strong><br>
${activeMusicaData.dicas}
</div>` : ''}
<div style="margin-top: 30px; text-align: center; font-size: 0.8rem; color: #94a3b8; border-top: 1px solid #e2e8f0; padding-top: 10px;">
Gerado por PedagogIA Assistente Pedagógica da Professora Camila
</div>
<div>${window.marked ? marked.parse(currentMusica) : currentMusica}</div>
</div>
</body>
</html>
@@ -6856,10 +7178,31 @@ window.toggleCustomAudio = (btn) => {
});
}
// --- HISTÓRICO DE MÚSICAS ---
if (btnOpenMusicaHistory) {
btnOpenMusicaHistory.addEventListener('click', () => {
musicaHistoryModal.style.display = 'flex';
loadMusicaHistory();
});
}
if (btnCloseMusicaHistory) {
btnCloseMusicaHistory.addEventListener('click', () => {
musicaHistoryModal.style.display = 'none';
});
}
musicaHistoryModal.addEventListener('click', (e) => {
if (e.target === musicaHistoryModal) {
musicaHistoryModal.style.display = 'none';
}
});
async function loadMusicaHistory() {
const listContainer = document.getElementById('musicaHistoryList');
if (!listContainer) return;
listContainer.innerHTML = '<p style="text-align:center; color:var(--text-secondary);">Carregando...</p>';
listContainer.innerHTML = '<p style="text-align:center; color:var(--text-secondary);">Carregando histórico...</p>';
try {
const response = await fetch('/api/musicas/list');
const data = await response.json();
@@ -6869,43 +7212,86 @@ window.toggleCustomAudio = (btn) => {
const date = new Date(item.created_at).toLocaleString('pt-BR');
const div = document.createElement('div');
div.className = 'history-item-card';
div.style.cssText = 'background: rgba(255,255,255,0.02); padding: 14px; border-radius: 8px; border: 1px solid var(--border-light); display: flex; flex-direction: column; gap: 8px; cursor: pointer; position: relative;';
div.style.cssText = 'background: rgba(255,255,255,0.03); padding: 14px; border-radius: 10px; border: 1px solid var(--border-light); display: flex; flex-direction: column; gap: 8px; cursor: pointer; position: relative; transition: all 0.2s;';
div.innerHTML = `
<div style="display: flex; justify-content: space-between; align-items: flex-start; padding-right: 30px;">
<strong style="color: var(--brand-green); font-size: 0.95rem;">${item.faixa_etaria} - ${item.ritmo}</strong>
<span style="font-size: 0.75rem; color: var(--text-secondary);">${date}</span>
<strong style="color: #c084fc; font-size: 0.95rem;">${item.faixa_etaria} ${item.ritmo}</strong>
<span style="font-size: 0.72rem; color: var(--text-secondary);">${date}</span>
</div>
<p style="margin: 0; font-size: 0.85rem; color: var(--text-primary); opacity: 0.9;">Tema: ${item.tema}</p>
<p style="margin: 0; font-size: 0.85rem; color: var(--text-primary); opacity: 0.9;"><strong>Tema:</strong> ${item.tema}</p>
${item.audio_url ? `
<div style="display: flex; align-items: center; gap: 8px; margin-top: 4px;">
<span style="font-size: 0.75rem; color: #10b981; font-weight: 600;">🎧 Áudio Disponível</span>
</div>
` : ''}
<button class="btn-delete-musica" data-id="${item.id}" style="position: absolute; top: 12px; right: 12px; background: transparent; border: none; color: #ef4444; cursor: pointer; font-size: 1.1rem; padding: 4px; border-radius: 4px;" title="Excluir">🗑</button>
`;
div.addEventListener('click', async (e) => {
if (e.target.closest('.btn-delete-musica')) {
e.stopPropagation();
if (confirm('Tem certeza que deseja excluir?')) {
if (confirm('Tem certeza que deseja excluir esta música do histórico?')) {
try {
const delRes = await fetch(`/api/musicas/${item.id}`, { method: 'DELETE' });
if (delRes.ok) { showToast('Música excluída.', 'success'); loadMusicaHistory(); }
} catch (err) { showToast('Erro ao excluir.', 'error'); }
if (delRes.ok) {
showToast('Música excluída do histórico.', 'success');
loadMusicaHistory();
}
} catch (err) {
showToast('Erro ao excluir música.', 'error');
}
}
return;
}
// Carregar música clicada
try {
const res = await fetch(`/api/musicas/${item.id}`);
const detail = await res.json();
if (res.ok) {
currentMusica = detail.musica;
musicaTextOutput.innerHTML = window.marked ? marked.parse(currentMusica) : currentMusica;
musicaResultArea.style.display = 'flex';
activeMusicaData = {
titulo: `Música: ${detail.tema}`,
versaoPrincipal: detail.versao_longa || detail.musica,
versaoCurta: detail.versao_curta || detail.musica,
versaoDancante: detail.versao_dancante || detail.musica,
bnccCampos: detail.bncc || 'EI02TS02 • Traços, Sons, Cores e Formas',
instrumentos: detail.instrumentos || 'Violão e Percussão',
dicas: '',
audioUrl: detail.audio_url,
tema: detail.tema,
ritmo: detail.ritmo,
faixaEtaria: detail.faixa_etaria
};
if (musicaPlaceholderText) musicaPlaceholderText.style.display = 'none';
if (musicaVersionsTabs) musicaVersionsTabs.style.display = 'flex';
if (musicaActiveContentBox) musicaActiveContentBox.style.display = 'flex';
if (musicaActiveTitle) musicaActiveTitle.textContent = activeMusicaData.titulo;
if (detail.audio_url) {
musicaAudioPlayer.src = detail.audio_url;
if (btnDownloadMusicaAudio) btnDownloadMusicaAudio.href = detail.audio_url;
if (musicaAudioPlayerBox) musicaAudioPlayerBox.style.display = 'flex';
} else {
if (musicaAudioPlayerBox) musicaAudioPlayerBox.style.display = 'none';
}
switchMusicaVersionTab('principal');
musicaHistoryModal.style.display = 'none';
}
} catch (err) { showToast('Erro ao carregar.', 'error'); }
} catch (err) {
showToast('Erro ao carregar detalhes da música.', 'error');
}
});
listContainer.appendChild(div);
});
} else {
listContainer.innerHTML = '<p style="text-align:center; color:var(--text-secondary);">Nenhum histórico.</p>';
listContainer.innerHTML = '<p style="text-align:center; color:var(--text-secondary); padding: 20px;">Nenhuma música gerada até o momento.</p>';
}
} catch (err) { listContainer.innerHTML = '<p style="text-align:center; color:#ef4444;">Erro ao carregar.</p>'; }
} catch (err) {
listContainer.innerHTML = '<p style="text-align:center; color:#ef4444;">Erro ao carregar histórico de músicas.</p>';
}
}