diff --git a/pages/projetos.md b/pages/projetos.md index 436c57e2..9c1cc426 100755 --- a/pages/projetos.md +++ b/pages/projetos.md @@ -342,10 +342,8 @@ document.addEventListener('DOMContentLoaded', () => { const filterContent = document.getElementById('filter-content'); const filterChevron = document.getElementById('filter-chevron'); - // Define estado inicial baseado na largura da tela let isFilterOpen = window.innerWidth > 1024; - // Função para aplicar o estado visual function updateFilterState() { if(isFilterOpen) { filterContent.style.display = 'block'; @@ -356,15 +354,12 @@ document.addEventListener('DOMContentLoaded', () => { } } - // Aplica estado inicial ao carregar - if (filterContent && filterChevron) { - updateFilterState(); - } + if (filterContent && filterChevron) updateFilterState(); if(filterBtn && filterContent) { filterBtn.addEventListener('click', () => { - isFilterOpen = !isFilterOpen; // Inverte o estado - updateFilterState(); // Aplica a mudança + isFilterOpen = !isFilterOpen; + updateFilterState(); }); } @@ -418,6 +413,7 @@ document.addEventListener('DOMContentLoaded', () => { const genreContainer = document.getElementById('genre-filters'); const sortSelect = document.getElementById('sort-select'); const starFilterSelect = document.getElementById('star-filter'); + const keyFilterSelect = document.getElementById('key-filter'); // CORREÇÃO 1: Pegar referência const projectsContainer = document.getElementById('projects-container'); let currentGenre = 'all'; @@ -431,39 +427,22 @@ document.addEventListener('DOMContentLoaded', () => { }) .catch(console.warn); - // Função atualizada para Badge de Dificuldade function renderizarDificuldade(num) { const n = Math.round(num) || 1; let label = "Básico"; - let icon = "fa-leaf"; // Ícone padrão - let colorClass = "is-success"; // Verde + let icon = "fa-leaf"; + let colorClass = "is-success"; - if (n >= 4.5) { - label = "Expert"; - icon = "fa-fire"; - colorClass = "is-danger"; // Vermelho - } else if (n >= 3.5) { - label = "Avançado"; - icon = "fa-bolt"; - colorClass = "is-warning"; // Amarelo/Laranja - } else if (n >= 2.5) { - label = "Intermediário"; - icon = "fa-layer-group"; - colorClass = "is-info"; // Azul - } + if (n >= 4.5) { label = "Expert"; icon = "fa-fire"; colorClass = "is-danger"; } + else if (n >= 3.5) { label = "Avançado"; icon = "fa-bolt"; colorClass = "is-warning"; } + else if (n >= 2.5) { label = "Intermediário"; icon = "fa-layer-group"; colorClass = "is-info"; } - // Retorna uma tag HTML bonita e visível - return ` - - ${label} - - `; + return ` ${label}`; } function enrichCards(data) { const mapDados = {}; - // Mapeamento dos dados data.forEach(item => { const k1 = normalizarChaveJS(item.arquivo.replace('.wav','').replace('.mp3','')); mapDados[k1] = item; @@ -473,66 +452,57 @@ document.addEventListener('DOMContentLoaded', () => { cards.forEach(card => { const info = mapDados[normalizarChaveJS(card.dataset.title)]; - // --- 1. Definição de Valores Padrão (Safety First) --- let genero = "Unknown"; + let subgenerosLista = []; // CORREÇÃO 2: Array para guardar subgêneros let estrelas = 0; let intensidade = -100; let bpm = 0; let tomHtml = ""; - let tomRaw = "all"; // Valor padrão para o filtro - let subTagsHTML = ""; // Para os subgêneros + let tomRaw = "all"; + let subTagsHTML = ""; - // --- 2. Só tenta extrair dados SE 'info' existir --- if (info) { - // Dados IA if (info.analise_ia) { genero = info.analise_ia.genero_macro || "Unknown"; - // Lógica de Subgêneros (Top 2) + // Captura subgêneros para o Filtro e Visual if (Array.isArray(info.analise_ia.nuvem_tags)) { + // Filtro: Pega todas as tags relevantes + info.analise_ia.nuvem_tags.forEach(t => { + if(t.tag) subgenerosLista.push(t.tag); + }); + + // Visual: Pega top 2 para mostrar const topTags = info.analise_ia.nuvem_tags.slice(0, 2); topTags.forEach(t => { - // Multiplica por 100 para porcentagem legível const scorePercent = Math.round((t.score || 0) * 100); - subTagsHTML += ` - - #${t.tag} - `; + subTagsHTML += `#${t.tag}`; }); } } - // Dados Técnicos if (info.analise_tecnica) { intensidade = parseFloat(info.analise_tecnica.intensidade_db || -100); bpm = parseFloat(info.analise_tecnica.bpm || 0); - // Correção: Usando Math.round para bater com o visual estrelas = Math.round(info.analise_tecnica.complexidade?.estrelas || 0); - // Lógica do Tom (Visual + Filtro) if (info.analise_tecnica.tom) { const t = info.analise_tecnica.tom; const e = info.analise_tecnica.escala === 'minor' ? 'm' : ''; - - // HTML visual (Badge) tomHtml = `🎹 ${t}${e}`; - - // Valor cru para o filtro (Ex: "C", "Cm", "Ab") tomRaw = t + e; } } } - // --- 3. Salva no Dataset para os Filtros --- card.dataset.genre = genero; + // CORREÇÃO 3: Salva subgêneros no dataset como string separada por vírgula + card.dataset.subgenres = subgenerosLista.join(',').toLowerCase(); card.dataset.stars = estrelas; card.dataset.intensity = intensidade; card.dataset.bpm_real = bpm; - card.dataset.key = tomRaw; // Novo dataset para o filtro de Tom + card.dataset.key = tomRaw; - // --- 4. Renderização no DOM --- const bpmContainer = card.querySelector('.bpm-container'); if (bpmContainer) { const iaDiv = document.createElement('div'); @@ -542,14 +512,12 @@ document.addEventListener('DOMContentLoaded', () => { iaDiv.style.gap = "6px"; iaDiv.className = "mt-3"; - // Dificuldade const diffDiv = document.createElement('div'); diffDiv.innerHTML = renderizarDificuldade(estrelas); iaDiv.appendChild(diffDiv); - // Tags (Gênero Macro + Tom) const tagsRow = document.createElement('div'); - tagsRow.className = "tags is-centered mb-1"; // mb-1 para dar espaço pros subgeneros + tagsRow.className = "tags is-centered mb-1"; tagsRow.style.gap = "4px"; if(genero !== "Unknown") { @@ -557,14 +525,12 @@ document.addEventListener('DOMContentLoaded', () => { if(genero === 'Electronic') color = 'is-info'; if(genero === 'Hip Hop') color = 'is-warning'; if(genero === 'Rock') color = 'is-danger'; - tagsRow.innerHTML += `🤖 ${genero}`; } tagsRow.innerHTML += tomHtml; iaDiv.appendChild(tagsRow); - // Nova Linha: Subgêneros if (subTagsHTML) { const subTagsRow = document.createElement('div'); subTagsRow.className = "tags is-centered mb-0"; @@ -573,7 +539,6 @@ document.addEventListener('DOMContentLoaded', () => { iaDiv.appendChild(subTagsRow); } - // Limpa e reinsere bpmContainer.innerHTML = ''; if(card.dataset.bpm_real > 0) { bpmContainer.innerHTML = `🎵 ${Math.round(card.dataset.bpm_real)} BPM`; @@ -586,14 +551,23 @@ document.addEventListener('DOMContentLoaded', () => { function createGenreButtons(data) { const genres = new Set(); data.forEach(i => { + // Macro Gênero if(i.analise_ia?.genero_macro && i.analise_ia.genero_macro !== "Unknown") genres.add(i.analise_ia.genero_macro); + + // CORREÇÃO 4: Adicionar Subgêneros aos filtros + if(Array.isArray(i.analise_ia?.nuvem_tags)) { + i.analise_ia.nuvem_tags.forEach(t => { + // Adiciona se tiver tag e um score razoável (opcional, aqui pegamos tudo) + if(t.tag) genres.add(t.tag); + }); + } }); Array.from(genres).sort().forEach(g => { const btn = document.createElement('button'); btn.className = 'button is-small is-rounded is-white'; - btn.textContent = g; + btn.textContent = g; // Exibe o nome do gênero btn.onclick = () => { document.querySelectorAll('#genre-filters .button').forEach(b => { b.classList.remove('is-active', 'is-info'); @@ -607,7 +581,6 @@ document.addEventListener('DOMContentLoaded', () => { genreContainer.appendChild(btn); }); - // Reset All Button const allBtn = genreContainer.querySelector('[data-genre="all"]'); allBtn.onclick = () => { document.querySelectorAll('#genre-filters .button').forEach(b => { @@ -623,13 +596,26 @@ document.addEventListener('DOMContentLoaded', () => { function applyFilters() { cards.forEach(c => { - const col = c.closest('.project-column'); - const g = c.dataset.genre; - const s = parseInt(c.dataset.stars || 0); - const k = c.dataset.key || 'all'; // Pega o tom salvo no card const currentKey = document.getElementById('key-filter')?.value || 'all'; + const col = c.closest('.project-column'); - const matchG = (currentGenre === 'all' || g === currentGenre); + const g = c.dataset.genre; // Gênero Macro + const sub = c.dataset.subgenres || ""; // Lista de subgêneros (string) + + const s = parseInt(c.dataset.stars || 0); + const k = c.dataset.key || 'all'; + + // CORREÇÃO 5: Lógica de Filtro Aprimorada + // Verifica se o gênero selecionado bate com o Macro OU se está contido nos subgêneros + let matchG = false; + if (currentGenre === 'all') { + matchG = true; + } else { + // Verifica match exato com Macro OU include na lista de subs + if (g === currentGenre) matchG = true; + if (sub.includes(currentGenre.toLowerCase())) matchG = true; + } + const matchS = (currentMinStars === 'all' || s === parseInt(currentMinStars)); const matchK = (currentKey === 'all' || k === currentKey); @@ -644,6 +630,13 @@ document.addEventListener('DOMContentLoaded', () => { }); } + // CORREÇÃO 6: Adicionando o Event Listener para o Tom + if(keyFilterSelect) { + keyFilterSelect.addEventListener('change', () => { + applyFilters(); + }); + } + sortSelect.addEventListener('change', (e) => { const crit = e.target.value; const cols = Array.from(projectsContainer.children);