/* ── Router + mount ── */ const PUBLIC_PAGES = NAV.map(n => n.key).concat(['register', 'login']); const KNOWN = PUBLIC_PAGES.concat(['admin', 'article']); function pageFromHash() { const h = (location.hash || '').replace(/^#\/?/, '').split('?')[0]; if (!h) return 'home'; return KNOWN.includes(h) ? h : 'notfound'; } function NotFound({ navigate }) { return (
404
لم نجد الصفحة

Halaman Tidak Ditemukan

Maaf, halaman yang Anda cari tidak ada atau telah dipindahkan.

); } function AdminHome({ user, navigate, onLogout }) { return (
Dashboard MQA
{user.name} · {user.role}
Selamat datang, {user.name.split(' ')[0]} 👋

Login berhasil melalui lapisan API (mode: {api.mode}). Modul dashboard lengkap akan di-port ke struktur no-build ini berikutnya.

{['Artikel', 'Pendaftar', 'Program', 'Donasi', 'Toko Buku', 'Pengaturan'].map(m => (
{m}
Segera
))}
); } function App() { const [page, setPage] = useState(pageFromHash); const [user, setUser] = useState(null); const [activeArticle, setActiveArticle] = useState(null); const [authorView, setAuthorView] = useState(null); useFadeUp(page + ':' + (activeArticle ? activeArticle.id : '')); const openArticle = (a) => { setActiveArticle(a); setPage('article'); location.hash = '#/article?id=' + a.id; window.scrollTo(0, 0); if (window.SEO) SEO.article(normArticle(a)); }; useEffect(() => { window.__openArticle = openArticle; }, []); // Saat refresh di #/article?id=… → pulihkan artikel yang sedang dibaca useEffect(() => { if (page === 'article' && !activeArticle) { const id = new URLSearchParams((location.hash.split('?')[1] || '')).get('id'); if (id) { const local = ((window.MQA || {}).articles || []).find(x => String(x.id) === String(id)); if (local) setActiveArticle(local); else api.get('articles.php?action=list').then(r => { const found = r.ok && r.articles && r.articles.find(x => String(x.id) === String(id)); if (found) setActiveArticle(found); }); } } }, [page]); const navigate = (p) => { setPage(p); const hash = '#/' + p; if (location.hash !== hash) location.hash = hash; window.scrollTo(0, 0); }; useEffect(() => { const onHash = () => setPage(pageFromHash()); window.addEventListener('hashchange', onHash); // cek sesi tersimpan api.get('auth.php?action=me').then(r => { if (r.ok) setUser(r.user); }); return () => window.removeEventListener('hashchange', onHash); }, []); // Update SEO (judul + meta) tiap halaman berubah useEffect(() => { if (!window.SEO) return; if (page === 'article') { if (activeArticle) SEO.article(normArticle(activeArticle)); } else if (!['admin', 'login'].includes(page)) SEO.page(page); }, [page, activeArticle]); const onLogin = (u) => { setUser(u); navigate('admin'); }; const onLogout = () => { api.post('auth.php?action=logout'); setUser(null); navigate('home'); }; // Halaman admin (butuh login) if (page === 'admin') { if (!user) return ; return ; } if (page === 'login') { if (user) return ; return ; } let content; if (page === 'home') content = ; else if (page === 'articles') content = ; else if (page === 'article') content = activeArticle ? : ; else if (page === 'programs') content = ; else if (page === 'teachers') content = ; else if (page === 'gallery') content = ; else if (page === 'kegiatan') content = ; else if (page === 'about') content = ; else if (page === 'contact') content = ; else if (page === 'donasi') content = ; else if (page === 'register') content = ; else if (page === 'toko') content = ; else content = ; return ( <>
{content}