alopecia/js/main.js

69 lines
2.9 KiB
JavaScript

/* ============================================================
main.js — 오케스트레이터 (데이터 로드 · 탭 네비 · 지연 초기화)
============================================================ */
(function () {
'use strict';
// Chart.js 전역 폰트를 Pretendard로 (모든 차트 생성 전에 즉시 적용)
if (window.Chart) {
Chart.defaults.font.family = "'Pretendard Variable', Pretendard, system-ui, 'Malgun Gothic', sans-serif";
Chart.defaults.font.size = 13;
Chart.defaults.color = '#4a463d';
}
const inited = {};
function el(id) { return document.getElementById(id); }
function setHeader() {
const cat = Store.catalog || { proteins: [] };
el('stat-proteins').textContent = cat.n_proteins || cat.proteins.length;
el('stat-structures').textContent = (cat.proteins || []).filter(p => p.structure && p.structure.accession).length;
const gs = cat.grounding_stats;
if (gs) el('stat-grounding').textContent = `${gs.in_model_grounded}/${gs.in_model_total} 트윈·${gs.catalog_grounded}/${gs.catalog_total} 전체`;
el('last-updated').textContent = (cat.last_updated || '').replace('T', ' ').slice(0, 16) || '—';
const pa = (Store.extras && Store.extras.prior_art) || [];
const fw = (Store.extras && Store.extras.frameworks) || [];
el('prior-art-note').textContent = `선행연구 ${pa.length}건 · 권장 프레임워크 ${fw.length}종 · 에이전트 14기 마이닝`;
}
function initTab(name) {
if (inited[name]) {
if (name === 'graph') window.GraphTab.init();
if (name === 'atlas') window.AtlasTab.resize();
return;
}
inited[name] = true;
try {
if (name === 'twin') window.TwinTab.init();
else if (name === 'timeline') window.TimelineTab.init();
else if (name === 'network') window.NetworkTab.init();
else if (name === 'atlas') window.AtlasTab.init();
else if (name === 'graph') window.GraphTab.init();
else if (name === 'calibrate') window.CalibrateTab.init();
else if (name === 'validation') window.ValidationTab.init();
else if (name === 'stats') window.StatsTab.render();
else if (name === 'papers') window.LibraryTab.init();
} catch (e) { console.error('탭 초기화 오류', name, e); }
}
function bindTabs() {
document.querySelectorAll('.tab-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
btn.classList.add('active');
el('tab-' + btn.dataset.tab).classList.add('active');
initTab(btn.dataset.tab);
});
});
}
async function boot() {
await Store.loadAll();
setHeader();
bindTabs();
initTab('twin'); // 기본 탭
}
document.addEventListener('DOMContentLoaded', boot);
})();