import { setLang, tr } from './i18n.js'; const $ = (selector) => document.querySelector(selector); const tauriInvoke = window.__TAURI__?.core?.invoke; const connection = $('#connection'); const connectionText = $('#connectionText'); const version = $('#version'); const updateBtn = $('#updateBtn'); const datasetPath = $('#datasetPath'); const analyzeBtn = $('#analyzeBtn'); const refreshBtn = $('#refreshBtn'); const output = $('#output'); const alertList = $('#alertList'); const settingsDlg = $('#settingsDlg'); const settingsBtn = $('#settingsBtn'); const closeSettings = $('#closeSettings'); const doneSettings = $('#doneSettings'); const langSel = $('#langSel'); const themePick = $('#themePick'); let lastAlerts = []; let themePreference = localStorage.getItem('acaua-theme') || 'auto'; async function fetchJson(path, options = {}) { const response = await fetch(path, options); const body = await response.json().catch(() => ({})); if (!response.ok) throw new Error(body.error || response.statusText); return body; } async function call(command, args = {}) { if (tauriInvoke) return tauriInvoke(command, args); switch (command) { case 'app_info': return fetchJson('/api/status'); case 'analyze_dataset': return fetchJson('/api/analyze', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(args), }); case 'list_alerts': return fetchJson('/api/alerts'); case 'update_check': return fetchJson('/api/update'); case 'doctor_report': return fetchJson('/api/health'); default: throw new Error(`unsupported command: ${command}`); } } function message(template, ...values) { let index = 0; return tr(template).replace(/\{n\}/g, () => values[index++] ?? ''); } function renderAlerts(alerts) { lastAlerts = Array.isArray(alerts) ? alerts : []; alertList.replaceChildren(); if (!lastAlerts.length) { const empty = document.createElement('li'); empty.className = 'empty'; empty.textContent = tr('Nenhum alerta ainda.'); alertList.append(empty); return; } for (const alert of lastAlerts) { const item = document.createElement('li'); const meta = document.createElement('div'); meta.className = 'alert-meta'; const pillar = document.createElement('strong'); pillar.textContent = message('Pilar {n}', alert.pillar); const score = document.createElement('span'); score.className = 'mono'; score.textContent = Number(alert.score).toFixed(3); meta.append(pillar, score); const summary = document.createElement('div'); summary.className = 'alert-summary'; summary.setAttribute('data-i18n-skip', ''); summary.textContent = alert.summary; item.append(meta, summary); alertList.append(item); } } async function refreshStatus() { try { const info = await call('app_info'); version.textContent = `v${info.version}`; connectionText.textContent = tr('Serviço local ativo'); connection.classList.remove('offline'); } catch (error) { connectionText.textContent = tr('Serviço indisponível'); connection.classList.add('offline'); version.textContent = '—'; console.error(error); } } async function refreshAlerts() { try { renderAlerts(await call('list_alerts')); } catch (error) { console.error(error); } } async function analyzeDataset() { const path = datasetPath.value.trim(); if (!path) { output.textContent = tr('Nenhum dataset selecionado.'); return; } analyzeBtn.disabled = true; output.textContent = tr('Analisando…'); try { const report = await call('analyze_dataset', { path }); output.textContent = message( 'Análise concluída: {n} registros e {n} alertas.', report.records, report.alerts.length, ); await refreshAlerts(); } catch (error) { output.textContent = message('Falha na análise: {n}', error.message); } finally { analyzeBtn.disabled = false; } } async function checkUpdate() { updateBtn.disabled = true; updateBtn.textContent = tr('Verificando atualização…'); try { const status = await call('update_check'); updateBtn.textContent = status.update_available ? message('Atualização {n} disponível.', status.latest_version) : message('Versão {n} é a mais recente.', status.current_version); } catch (error) { updateBtn.title = message('Não foi possível verificar a atualização: {n}', error.message); updateBtn.textContent = tr('checar atualização'); } finally { updateBtn.disabled = false; window.setTimeout(() => { updateBtn.textContent = tr('checar atualização'); updateBtn.title = ''; }, 6000); } } function applyTheme(preference) { themePreference = preference; localStorage.setItem('acaua-theme', preference); const light = window.matchMedia('(prefers-color-scheme: light)').matches; const effective = preference === 'auto' ? (light ? 'light' : 'dark') : preference; document.documentElement.dataset.theme = effective; themePick.querySelectorAll('[data-theme-pick]').forEach((button) => { button.classList.toggle('active', button.dataset.themePick === preference); }); } function openSettings() { langSel.value = localStorage.getItem('acaua-lang') || 'auto'; settingsDlg.showModal(); } function closeDialog() { settingsDlg.close(); } function setActiveNav(target) { document.querySelectorAll('.nav-item').forEach((button) => { button.classList.toggle('active', button.dataset.target === target); }); } function init() { applyTheme(themePreference); langSel.value = localStorage.getItem('acaua-lang') || 'auto'; setLang(langSel.value); refreshStatus(); refreshAlerts(); analyzeBtn.addEventListener('click', analyzeDataset); datasetPath.addEventListener('keydown', (event) => { if (event.key === 'Enter') analyzeDataset(); }); refreshBtn.addEventListener('click', async () => { await refreshStatus(); await refreshAlerts(); }); updateBtn.addEventListener('click', checkUpdate); settingsBtn.addEventListener('click', openSettings); closeSettings.addEventListener('click', closeDialog); doneSettings.addEventListener('click', closeDialog); langSel.addEventListener('change', () => { localStorage.setItem('acaua-lang', langSel.value); setLang(langSel.value); refreshStatus(); renderAlerts(lastAlerts); updateBtn.textContent = tr('checar atualização'); }); themePick.addEventListener('click', (event) => { const button = event.target.closest('[data-theme-pick]'); if (button) applyTheme(button.dataset.themePick); }); window.matchMedia('(prefers-color-scheme: light)').addEventListener('change', () => { if (themePreference === 'auto') applyTheme('auto'); }); document.querySelectorAll('.nav-item').forEach((button) => { button.addEventListener('click', () => { const target = button.dataset.target; setActiveNav(target); if (target === 'settings') openSettings(); else document.getElementById(target)?.scrollIntoView({ behavior: 'smooth', block: 'start' }); }); }); } init();