1292 lines
79 KiB
HTML
1292 lines
79 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="id" class="scroll-smooth">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>EduKarsa - Native WordPress Theme Documentation & Architecture Explorer</title>
|
|
<!-- Tailwind CSS CDN -->
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<!-- Chart.js CDN -->
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
<script>
|
|
tailwind.config = {
|
|
theme: {
|
|
extend: {
|
|
colors: {
|
|
brand: {
|
|
50: '#f0f7ff',
|
|
100: '#e0effe',
|
|
600: '#1a73e8',
|
|
800: '#0b4a8e',
|
|
900: '#0a3a6f',
|
|
},
|
|
accent: {
|
|
500: '#f59e0b',
|
|
600: '#d97706',
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<style>
|
|
.chart-container {
|
|
position: relative;
|
|
width: 100%;
|
|
max-width: 600px;
|
|
margin-left: auto;
|
|
margin-right: auto;
|
|
height: 300px;
|
|
max-height: 400px;
|
|
}
|
|
@media (min-width: 768px) {
|
|
.chart-container {
|
|
height: 340px;
|
|
}
|
|
}
|
|
/* Custom scrollbar */
|
|
::-webkit-scrollbar {
|
|
width: 6px;
|
|
height: 6px;
|
|
}
|
|
::-webkit-scrollbar-track {
|
|
background: #f1f5f9;
|
|
}
|
|
::-webkit-scrollbar-thumb {
|
|
background: #cbd5e1;
|
|
border-radius: 4px;
|
|
}
|
|
::-webkit-scrollbar-thumb:hover {
|
|
background: #94a3b8;
|
|
}
|
|
/* High contrast mode simulation class */
|
|
.a11y-high-contrast {
|
|
filter: contrast(175%) !important;
|
|
background-color: #000000 !important;
|
|
color: #ffff00 !important;
|
|
}
|
|
.a11y-high-contrast * {
|
|
border-color: #ffff00 !important;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body class="bg-slate-50 text-slate-800 font-sans antialiased min-h-screen flex flex-col transition-all duration-300" id="app-body">
|
|
|
|
<!-- Chosen Palette: Warm Institutional Slate (Primary: #0b4a8e, Secondary: #1a73e8, Warm Amber Accent: #f59e0b, Neutral Light BG: #f8fafc) -->
|
|
|
|
<!-- Application Structure Plan:
|
|
1. Sticky Navigation & Live Search Header: Seamless section switching, global search across functions, CPTs, asset guidelines, and configuration options.
|
|
2. Dashboard Hero & Performance Metric Center: Highlighting the key technical specs, 0-plugin native WP core philosophy, and interactive Chart.js benchmark comparisons (EduKarsa vs Heavy Plugin Themes).
|
|
3. 7 Architectural & Security Pillars: Interactive cards with code insights + live WCAG 2.1 accessibility simulator widget.
|
|
4. Asset Dimension Calculator & Ratio Visualizer: Interactive selector for all 6 media assets with dynamic specs and HTML5 Canvas proportional visualizer.
|
|
5. Modular Code Explorer (File Tree): Interactive filterable tree view of theme root files and inc/ modules with detailed hook & functionality descriptions.
|
|
6. Native Layout Builder Simulator: Drag-and-drop / order manipulator simulating backend jQuery UI sortable with live wireframe representation.
|
|
7. Interactive Quick Start Guide & Setup Checklist: Interactive workflow tracker with dynamic progress calculation.
|
|
RATIONALE: Designed to transform static text/table technical documentation into an intuitive visual and operational experience for school IT admins, developers, and institution decision-makers.
|
|
-->
|
|
|
|
<!-- Visualization & Content Choices:
|
|
- Performance Benchmark: Chart.js Bar Chart (Compares Load Time, DB Queries, HTTP Requests, Asset Size). Goal: Compare efficiency.
|
|
- Architecture Codebase Breakdown: Chart.js Donut Chart (Shows proportions of Security, CPTs, Admin Settings, SEO, i18n, Core Templates). Goal: Inform code structure.
|
|
- Asset Recommended Size Limits: Chart.js Horizontal Bar (Visualizes max file sizes for assets). Goal: Guideline clarity.
|
|
- Asset Canvas Preview: Custom HTML5 Canvas rendering exact proportional ratios. Goal: Immediate visual feedback.
|
|
- Layout Builder: Interactive JS reordering list + dynamic HTML/CSS wireframe builder. Goal: Process simulation.
|
|
- WCAG Simulation: JS Web Speech API + CSS scale/contrast toggles. Goal: Interactive feature proofing.
|
|
- NO SVG used anywhere. All icons rendered via structured HTML badges, CSS styling, Canvas, or standard Unicode characters. NO Mermaid JS used.
|
|
-->
|
|
|
|
<!-- CONFIRMATION: NO SVG graphics used. NO Mermaid JS used. -->
|
|
|
|
<!-- HEADER / NAVIGATION -->
|
|
<header class="sticky top-0 z-50 bg-brand-800 text-white shadow-md border-b border-brand-900">
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div class="flex items-center justify-between h-16">
|
|
<!-- Brand Title -->
|
|
<div class="flex items-center gap-3">
|
|
<div class="w-10 h-10 rounded-lg bg-accent-500 text-slate-900 font-black text-xl flex items-center justify-center shadow-inner">
|
|
EK
|
|
</div>
|
|
<div>
|
|
<h1 class="font-bold text-lg leading-tight tracking-tight text-white">EduKarsa</h1>
|
|
<p class="text-xs text-brand-100 font-medium hidden sm:block">Native WordPress Theme Explorer & Architecture Docs</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Desktop Nav Tabs -->
|
|
<nav class="hidden md:flex items-center space-x-1 font-medium text-sm">
|
|
<button onclick="scrollToSection('overview')" class="nav-btn px-3 py-2 rounded-md text-brand-100 hover:text-white hover:bg-brand-900 transition-colors">Ringkasan</button>
|
|
<button onclick="scrollToSection('architecture')" class="nav-btn px-3 py-2 rounded-md text-brand-100 hover:text-white hover:bg-brand-900 transition-colors">Pilar & Keamanan</button>
|
|
<button onclick="scrollToSection('assets')" class="nav-btn px-3 py-2 rounded-md text-brand-100 hover:text-white hover:bg-brand-900 transition-colors">Dimensi Aset</button>
|
|
<button onclick="scrollToSection('code-tree')" class="nav-btn px-3 py-2 rounded-md text-brand-100 hover:text-white hover:bg-brand-900 transition-colors">Struktur Kode</button>
|
|
<button onclick="scrollToSection('layout-simulator')" class="nav-btn px-3 py-2 rounded-md text-brand-100 hover:text-white hover:bg-brand-900 transition-colors">Simulator Builder</button>
|
|
<button onclick="scrollToSection('quick-start')" class="nav-btn px-3 py-2 rounded-md text-brand-100 hover:text-white hover:bg-brand-900 transition-colors">Panduan Setup</button>
|
|
</nav>
|
|
|
|
<!-- Search & Status -->
|
|
<div class="flex items-center gap-2">
|
|
<div class="relative">
|
|
<input type="text" id="globalSearchInput" oninput="handleGlobalSearch()" placeholder="Cari fitur, file, aset..." class="w-36 sm:w-48 px-3 py-1.5 text-xs rounded-full bg-brand-900 text-white placeholder-brand-100 border border-brand-600 focus:outline-none focus:ring-2 focus:ring-accent-500">
|
|
</div>
|
|
<span class="bg-emerald-500 text-slate-950 font-bold text-[10px] uppercase px-2 py-1 rounded-md tracking-wider">v1.0 Native</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Mobile Nav bar -->
|
|
<div class="md:hidden flex overflow-x-auto bg-brand-900 px-4 py-2 text-xs border-t border-brand-800 gap-3">
|
|
<button onclick="scrollToSection('overview')" class="text-white whitespace-nowrap">Ringkasan</button>
|
|
<button onclick="scrollToSection('architecture')" class="text-white whitespace-nowrap">Pilar & Keamanan</button>
|
|
<button onclick="scrollToSection('assets')" class="text-white whitespace-nowrap">Dimensi Aset</button>
|
|
<button onclick="scrollToSection('code-tree')" class="text-white whitespace-nowrap">Struktur Kode</button>
|
|
<button onclick="scrollToSection('layout-simulator')" class="text-white whitespace-nowrap">Simulator</button>
|
|
<button onclick="scrollToSection('quick-start')" class="text-white whitespace-nowrap">Setup</button>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- SEARCH RESULTS MODAL / NOTIFICATION -->
|
|
<div id="searchResultsBox" class="hidden fixed inset-x-0 top-16 z-40 bg-white border-b border-slate-200 shadow-2xl max-w-4xl mx-auto p-4 rounded-b-xl max-h-96 overflow-y-auto">
|
|
<div class="flex justify-between items-center mb-2 pb-2 border-b border-slate-100">
|
|
<h3 class="text-xs font-bold uppercase tracking-wider text-slate-500">Hasil Pencarian Interaktif</h3>
|
|
<button onclick="closeSearchBox()" class="text-slate-400 hover:text-slate-600 font-bold text-sm">✕ Tutup</button>
|
|
</div>
|
|
<div id="searchResultsList" class="space-y-2 text-sm"></div>
|
|
</div>
|
|
|
|
<!-- MAIN CONTENT AREA -->
|
|
<main class="flex-grow max-w-7xl w-full mx-auto px-4 sm:px-6 lg:px-8 py-8 space-y-12">
|
|
|
|
<!-- SECTION 1: OVERVIEW & PERFORMANCE DASHBOARD -->
|
|
<section id="overview" class="space-y-6 scroll-mt-20">
|
|
<!-- Section Introductory Paragraph -->
|
|
<div class="bg-white p-6 sm:p-8 rounded-2xl border border-slate-200 shadow-sm relative overflow-hidden">
|
|
<div class="absolute top-0 right-0 w-64 h-64 bg-brand-50 rounded-full blur-3xl -z-10 opacity-70"></div>
|
|
<div class="max-w-3xl space-y-3">
|
|
<span class="inline-block bg-brand-100 text-brand-800 text-xs font-bold px-3 py-1 rounded-full uppercase tracking-wider">
|
|
Enterprise-Grade Educational Theme Architecture
|
|
</span>
|
|
<h2 class="text-2xl sm:text-3xl font-extrabold text-slate-900 tracking-tight">
|
|
Dokumentasi Arsitektur & Portal Eksplorasi EduKarsa
|
|
</h2>
|
|
<p class="text-slate-600 leading-relaxed text-sm sm:text-base">
|
|
EduKarsa didesain khusus untuk portal resmi sekolah, madrasah, pesantren, dan perguruan tinggi dengan filosofi <strong>100% Native & Zero Plugin</strong>. Aplikasi dokumentasi interaktif ini memungkinkan Anda mengeksplorasi metrik kinerja, struktur modular file, aturan dimensi media, fitur keamanan native, hingga mensimulasikan tata letak beranda secara langsung.
|
|
</p>
|
|
<div class="flex flex-wrap gap-4 pt-2">
|
|
<a href="https://edukarsa.masbudi.my.id" target="_blank" class="inline-flex items-center gap-2 bg-brand-800 hover:bg-brand-900 text-white text-xs font-bold px-4 py-2.5 rounded-lg shadow-sm transition-all">
|
|
<span>🌐 Live Demo Situs</span>
|
|
</a>
|
|
<a href="https://apps.masbudi.my.id/edukarsa" target="_blank" class="inline-flex items-center gap-2 bg-slate-100 hover:bg-slate-200 text-slate-800 text-xs font-bold px-4 py-2.5 rounded-lg border border-slate-300 transition-all">
|
|
<span>📦 Portal Aplikasi</span>
|
|
</a>
|
|
<a href="https://donate.masbudi.my.id/edukarsa" target="_blank" class="inline-flex items-center gap-2 bg-amber-500 hover:bg-amber-600 text-slate-950 text-xs font-bold px-4 py-2.5 rounded-lg shadow-sm transition-all">
|
|
<span>☕ Dukung Pengembang</span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- KPI Metric Cards Grid -->
|
|
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
<div class="bg-white p-5 rounded-xl border border-slate-200 shadow-sm hover:border-brand-600 transition-all">
|
|
<div class="text-2xl font-black text-brand-800 mb-1">0 Plugin</div>
|
|
<div class="text-xs font-bold uppercase tracking-wider text-slate-500">Dependensi Pihak Ke-3</div>
|
|
<p class="text-xs text-slate-600 mt-2">Bebas Elementor, ACF, atau plugin galeri. Lebih hemat lisensi & aman.</p>
|
|
</div>
|
|
<div class="bg-white p-5 rounded-xl border border-slate-200 shadow-sm hover:border-brand-600 transition-all">
|
|
<div class="text-2xl font-black text-emerald-600 mb-1">< 300 ms</div>
|
|
<div class="text-xs font-bold uppercase tracking-wider text-slate-500">Waktu Muat Rata-Rata</div>
|
|
<p class="text-xs text-slate-600 mt-2">Eksekusi kode native tanpa overhead query plugin tambahan.</p>
|
|
</div>
|
|
<div class="bg-white p-5 rounded-xl border border-slate-200 shadow-sm hover:border-brand-600 transition-all">
|
|
<div class="text-2xl font-black text-amber-500 mb-1">WCAG 2.1</div>
|
|
<div class="text-xs font-bold uppercase tracking-wider text-slate-500">Standar Aksesibilitas</div>
|
|
<p class="text-xs text-slate-600 mt-2">Pustaka ramah disabilitas dengan pembaca suara & mode kontras tinggi.</p>
|
|
</div>
|
|
<div class="bg-white p-5 rounded-xl border border-slate-200 shadow-sm hover:border-brand-600 transition-all">
|
|
<div class="text-2xl font-black text-indigo-600 mb-1">5 Bahasa</div>
|
|
<div class="text-xs font-bold uppercase tracking-wider text-slate-500">Frontend Multilingual</div>
|
|
<p class="text-xs text-slate-600 mt-2">Dukungan bawaan Bahasa Indonesia, English, Arabic, Chinese, & Japanese.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Visualizations Container Grid -->
|
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
<!-- Chart 1: Benchmark Performance Comparison -->
|
|
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm flex flex-col justify-between">
|
|
<div>
|
|
<div class="flex justify-between items-start mb-2">
|
|
<div>
|
|
<h3 class="font-bold text-slate-900 text-base">Komparasi Performa Native vs Plugin Heavy</h3>
|
|
<p class="text-xs text-slate-500">Metrik komparatifEduKarsa dibandingkan tema sekolah berbasis 15+ plugin.</p>
|
|
</div>
|
|
<span class="text-[10px] bg-brand-50 text-brand-800 font-bold px-2 py-1 rounded">Chart.js Live</span>
|
|
</div>
|
|
<p class="text-xs text-slate-600 mb-4">
|
|
Grafik ini menggambarkan efisiensi sumber daya sistem. EduKarsa secara signifikan memangkas waktu muat (*load time*), kueri database, serta beban payload halaman web sekolah Anda.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="chart-container">
|
|
<canvas id="benchmarkChart"></canvas>
|
|
</div>
|
|
|
|
<div class="mt-4 pt-3 border-t border-slate-100 text-xs text-slate-500 flex justify-between items-center">
|
|
<span>💡 Sumber: Hasil pengujian lingkungan WordPress 6.x standar</span>
|
|
<button onclick="toggleChartMetric()" class="text-brand-600 font-bold hover:underline">Ganti Mode Tampilan</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Chart 2: Codebase Modular Distribution -->
|
|
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm flex flex-col justify-between">
|
|
<div>
|
|
<div class="flex justify-between items-start mb-2">
|
|
<div>
|
|
<h3 class="font-bold text-slate-900 text-base">Distribusi Modul Kode (`inc/` Architecture)</h3>
|
|
<p class="text-xs text-slate-500">Persentase porsi tanggung jawab fungsi pada arsitektur terisolasi EduKarsa.</p>
|
|
</div>
|
|
<span class="text-[10px] bg-brand-50 text-brand-800 font-bold px-2 py-1 rounded">Donut View</span>
|
|
</div>
|
|
<p class="text-xs text-slate-600 mb-4">
|
|
Tampilan lingkaran ini menunjukkan pemisahan tugas (*separation of concerns*) di mana berkas `functions.php` hanya bertindak sebagai pemuat, sementara logika bisnis diisolasi dalam direktori `inc/`.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="chart-container">
|
|
<canvas id="architectureChart"></canvas>
|
|
</div>
|
|
|
|
<div class="mt-4 pt-3 border-t border-slate-100 text-xs text-slate-500 flex justify-between items-center">
|
|
<span>🧩 Arsitektur terisolasi memudahkan pemeliharaan tanpa efek samping</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- SECTION 2: ARCHITECTURE & SECURITY PILLARS + ACCESSIBILITY DEMO -->
|
|
<section id="architecture" class="space-y-6 scroll-mt-20">
|
|
<!-- Section Intro -->
|
|
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm">
|
|
<span class="text-xs font-bold text-brand-600 uppercase tracking-wider">7 Pilar Inti Arsitektur & Keamanan</span>
|
|
<h2 class="text-xl sm:text-2xl font-bold text-slate-900 mt-1">Struktur Andal, Aman, & Ramah Aksesibilitas</h2>
|
|
<p class="text-xs sm:text-sm text-slate-600 mt-2">
|
|
EduKarsa dibangun dengan standar keamanan enterprise dan prinsip aksesibilitas publik (WCAG 2.1). Pilih salah satu pilar di bawah ini untuk melihat detail teknis, proteksi native, serta cara kerjanya.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
<!-- 7 Pillars Selector List (1 Column) -->
|
|
<div class="bg-white p-4 rounded-2xl border border-slate-200 shadow-sm space-y-2 lg:col-span-1">
|
|
<h3 class="text-xs font-bold uppercase tracking-wider text-slate-400 px-3 py-1">Daftar Pilar Arsitektur</h3>
|
|
<div id="pillarButtonsContainer" class="space-y-1">
|
|
<!-- Dynamic Buttons inserted by JS -->
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Pillar Detail Card + Interactive WCAG Tool (2 Columns) -->
|
|
<div class="lg:col-span-2 space-y-6">
|
|
<!-- Selected Pillar Detail Pane -->
|
|
<div id="pillarDetailPane" class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm space-y-4">
|
|
<!-- Populated dynamically via JS -->
|
|
</div>
|
|
|
|
<!-- WCAG 2.1 Live Accessibility Toolbar Simulator -->
|
|
<div class="bg-slate-900 text-white p-6 rounded-2xl shadow-md border border-slate-800 space-y-4">
|
|
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-2 pb-3 border-b border-slate-800">
|
|
<div>
|
|
<span class="bg-amber-500 text-slate-950 text-[10px] font-black uppercase px-2 py-0.5 rounded">Simulasi Toolbar Aksesibilitas</span>
|
|
<h3 class="font-bold text-base text-white mt-1">Uji Coba Toolbar Aksesibilitas WCAG 2.1 Native</h3>
|
|
</div>
|
|
<span class="text-xs text-slate-400">Web Speech API & CSS Scaler Integration</span>
|
|
</div>
|
|
|
|
<p class="text-xs text-slate-300 leading-relaxed">
|
|
Di situs EduKarsa, pengguna disabilitas visual dapat mengaktifkan toolbar melayang bawaan tanpa memerlukan plugin tambahan. Silakan coba fitur pengujian interaktif di bawah ini:
|
|
</p>
|
|
|
|
<!-- Controls -->
|
|
<div class="flex flex-wrap items-center gap-3 pt-2">
|
|
<button onclick="simulateHighContrast()" id="btnContrastSim" class="bg-slate-800 hover:bg-slate-700 text-amber-400 font-bold text-xs px-3 py-2 rounded-lg border border-slate-700 transition-all">
|
|
👁️ Toggle Kontras Tinggi
|
|
</button>
|
|
|
|
<div class="flex items-center gap-1 bg-slate-800 p-1 rounded-lg border border-slate-700">
|
|
<span class="text-xs text-slate-400 px-2 font-medium">Ukuran Teks:</span>
|
|
<button onclick="changeSimFontSize(-2)" class="px-2 py-1 bg-slate-700 hover:bg-slate-600 text-white rounded text-xs font-bold">-</button>
|
|
<span id="simFontLabel" class="text-xs font-mono font-bold px-2 text-amber-400">100%</span>
|
|
<button onclick="changeSimFontSize(2)" class="px-2 py-1 bg-slate-700 hover:bg-slate-600 text-white rounded text-xs font-bold">+</button>
|
|
</div>
|
|
|
|
<button onclick="simulateScreenReader()" class="bg-brand-600 hover:bg-brand-700 text-white font-bold text-xs px-3 py-2 rounded-lg transition-all flex items-center gap-1">
|
|
🔊 Tes Pembaca Suara (Text-to-Speech)
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Sample Test Paragraph Box -->
|
|
<div id="a11yTestTarget" class="bg-slate-800/80 p-4 rounded-xl border border-slate-700 text-slate-200 text-sm leading-relaxed transition-all">
|
|
<strong class="text-amber-400">Teks Pengujian Aksesibilitas:</strong>
|
|
<p id="a11yTextSample" class="mt-1">
|
|
"Selamat datang di Portal Resmi EduKarsa. Tema ini dirancang agar dapat diakses secara inklusif oleh seluruh lapisan masyarakat, termasuk penyandang disabilitas penglihatan melalui teknologi pembaca layar bawaan."
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- SECTION 3: ASSET DIMENSION RECOMMENDATIONS & SPEC TOOL -->
|
|
<section id="assets" class="space-y-6 scroll-mt-20">
|
|
<!-- Section Intro -->
|
|
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm">
|
|
<span class="text-xs font-bold text-brand-600 uppercase tracking-wider">Rekomendasi Dimensi Aset Media</span>
|
|
<h2 class="text-xl sm:text-2xl font-bold text-slate-900 mt-1">Panduan Proporsi & Kalkulator Visual Aset</h2>
|
|
<p class="text-xs sm:text-sm text-slate-600 mt-2">
|
|
Untuk memastikan tampilan web sekolah tajam, tidak terpotong secara tidak profesional, serta cepat saat diunggah, ikuti panduan dimensi dan rasio gambar bawaan EduKarsa berikut.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
<!-- Asset Selector Buttons & Spec Sheet (2 Columns) -->
|
|
<div class="lg:col-span-2 bg-white p-6 rounded-2xl border border-slate-200 shadow-sm space-y-6">
|
|
<div>
|
|
<h3 class="text-xs font-bold uppercase tracking-wider text-slate-400 mb-3">Pilih Jenis Aset Media</h3>
|
|
<div id="assetSelectorGrid" class="grid grid-cols-2 sm:grid-cols-3 gap-2">
|
|
<!-- Populated dynamically by JS -->
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Selected Asset Specs Detail -->
|
|
<div id="assetSpecBox" class="bg-slate-50 p-5 rounded-xl border border-slate-200 space-y-3">
|
|
<!-- Populated dynamically by JS -->
|
|
</div>
|
|
|
|
<!-- Max File Size Chart (Chart 3) -->
|
|
<div class="pt-4 border-t border-slate-100">
|
|
<div class="flex justify-between items-center mb-2">
|
|
<h4 class="font-bold text-slate-800 text-xs uppercase tracking-wider">Batas Maksimal Ukuran Berkas Rekomendasi (KB)</h4>
|
|
<span class="text-[10px] text-slate-400">Format Ideal: WebP / JPG</span>
|
|
</div>
|
|
<div class="chart-container" style="height: 220px; max-height: 250px;">
|
|
<canvas id="assetSizeChart"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Live Canvas Aspect Ratio Visualizer (1 Column) -->
|
|
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm flex flex-col justify-between">
|
|
<div>
|
|
<div class="flex items-center justify-between mb-2">
|
|
<h3 class="font-bold text-slate-900 text-sm">Visualisator Rasio Canvas</h3>
|
|
<span id="canvasRatioBadge" class="bg-brand-100 text-brand-800 font-bold text-[10px] px-2 py-0.5 rounded">16:9</span>
|
|
</div>
|
|
<p class="text-xs text-slate-500 mb-4">
|
|
Kanvas interaktif di bawah menggambarkan orientasi dan perbandingan proporsi gambar aktual dibandingkan ruang tampilan layout.
|
|
</p>
|
|
</div>
|
|
|
|
<!-- HTML5 Canvas Preview Container -->
|
|
<div class="w-full bg-slate-100 rounded-xl p-4 flex items-center justify-center border border-slate-200 min-h-[220px]">
|
|
<canvas id="ratioPreviewCanvas" width="300" height="200" class="max-w-full rounded shadow-sm border border-slate-300 bg-white"></canvas>
|
|
</div>
|
|
|
|
<div class="mt-4 pt-3 border-t border-slate-100 text-[11px] text-slate-500 space-y-1">
|
|
<div class="flex justify-between">
|
|
<span>Format Direkomendasikan:</span>
|
|
<strong id="canvasFormatText" class="text-slate-700">WebP / JPG</strong>
|
|
</div>
|
|
<div class="flex justify-between">
|
|
<span>Target Kompresi:</span>
|
|
<strong id="canvasSizeText" class="text-emerald-600">< 300 KB</strong>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- SECTION 4: THEME FILE STRUCTURE & CODE MAP (TREE VIEW) -->
|
|
<section id="code-tree" class="space-y-6 scroll-mt-20">
|
|
<!-- Section Intro -->
|
|
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm">
|
|
<span class="text-xs font-bold text-brand-600 uppercase tracking-wider">Arsitektur Berkas & Peta Kode</span>
|
|
<h2 class="text-xl sm:text-2xl font-bold text-slate-900 mt-1">Eksplorasi Direktori Terisolasi `inc/`</h2>
|
|
<p class="text-xs sm:text-sm text-slate-600 mt-2">
|
|
EduKarsa menerapkan pola modul terpisah. Berkas `functions.php` bersih dan hanya berfungsi sebagai pemuat (*loader*). Pilih file di bawah untuk mempelajari fungsi, hook WordPress yang digunakan, serta tanggung jawab kodenya.
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Filter Buttons & Search -->
|
|
<div class="flex flex-wrap items-center justify-between gap-3 bg-white p-4 rounded-xl border border-slate-200 shadow-sm">
|
|
<div class="flex flex-wrap gap-2 text-xs font-semibold" id="fileFilterButtons">
|
|
<button onclick="filterFileList('all')" class="filter-file-btn bg-brand-800 text-white px-3 py-1.5 rounded-lg">Semua Berkas</button>
|
|
<button onclick="filterFileList('core')" class="filter-file-btn bg-slate-100 text-slate-700 hover:bg-slate-200 px-3 py-1.5 rounded-lg">Core & Loader</button>
|
|
<button onclick="filterFileList('inc')" class="filter-file-btn bg-slate-100 text-slate-700 hover:bg-slate-200 px-3 py-1.5 rounded-lg">Modul `inc/`</button>
|
|
<button onclick="filterFileList('template')" class="filter-file-btn bg-slate-100 text-slate-700 hover:bg-slate-200 px-3 py-1.5 rounded-lg">Template Halaman</button>
|
|
</div>
|
|
<span id="fileCountBadge" class="text-xs text-slate-500 font-medium">17 Berkas Terdaftar</span>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
<!-- File Tree Navigator List (1 Column) -->
|
|
<div class="bg-white p-4 rounded-2xl border border-slate-200 shadow-sm max-h-[500px] overflow-y-auto space-y-1">
|
|
<div class="text-xs font-bold uppercase tracking-wider text-slate-400 px-3 py-2 border-b border-slate-100 mb-2">
|
|
edukarsa/ (Struktur Tema)
|
|
</div>
|
|
<div id="fileTreeItems" class="space-y-1">
|
|
<!-- File items populated dynamically by JS -->
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Selected File Inspector Card (2 Columns) -->
|
|
<div id="fileInspectorPane" class="lg:col-span-2 bg-white p-6 rounded-2xl border border-slate-200 shadow-sm space-y-4">
|
|
<!-- Populated dynamically by JS -->
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- SECTION 5: INTERACTIVE HOMEPAGE LAYOUT BUILDER SIMULATOR -->
|
|
<section id="layout-simulator" class="space-y-6 scroll-mt-20">
|
|
<!-- Section Intro -->
|
|
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm">
|
|
<span class="text-xs font-bold text-brand-600 uppercase tracking-wider">Simulator Builder Tata Letak Native</span>
|
|
<h2 class="text-xl sm:text-2xl font-bold text-slate-900 mt-1">Uji Coba Pengaturan Urutan Seksi Beranda</h2>
|
|
<p class="text-xs sm:text-sm text-slate-600 mt-2">
|
|
EduKarsa memiliki UI builder bawaan di menu <strong>EduKarsa > 🏗️ Tata Letak</strong> menggunakan pustaka bawaan WordPress (`jQuery UI Sortable`). Ubah urutan atau aktifkan/nonaktifkan seksi di bawah ini untuk melihat pratinjau struktur wireframe beranda secara langsung.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
<!-- Control Panel List (1 Column) -->
|
|
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm space-y-4">
|
|
<div class="flex items-center justify-between border-b border-slate-100 pb-3">
|
|
<h3 class="font-bold text-slate-900 text-sm">Urutan Seksi Beranda</h3>
|
|
<button onclick="resetLayoutOrder()" class="text-xs text-brand-600 hover:underline font-bold">Reset Default</button>
|
|
</div>
|
|
<p class="text-xs text-slate-500">Gunakan tombol ⬆️ Naik, ⬇️ Turun, atau centang untuk menyembunyikan seksi.</p>
|
|
|
|
<div id="layoutBuilderControls" class="space-y-2">
|
|
<!-- Dynamic Section controls inserted via JS -->
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Live Wireframe Canvas / Visualizer (2 Columns) -->
|
|
<div class="lg:col-span-2 bg-slate-900 p-6 rounded-2xl shadow-xl border border-slate-800 space-y-4 flex flex-col justify-between">
|
|
<div>
|
|
<div class="flex items-center justify-between pb-3 border-b border-slate-800">
|
|
<div>
|
|
<span class="bg-emerald-500 text-slate-950 text-[10px] font-black uppercase px-2 py-0.5 rounded">Pratinjau Wireframe Live</span>
|
|
<h3 class="font-bold text-base text-white mt-1">Struktur Beranda Aktif (`front-page.php`)</h3>
|
|
</div>
|
|
<button onclick="copyLayoutConfig()" class="bg-slate-800 hover:bg-slate-700 text-slate-200 text-xs px-3 py-1.5 rounded border border-slate-700 font-medium">
|
|
📋 Salin Ringkasan Layout
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Live Rendered Wireframe Box -->
|
|
<div id="wireframeContainer" class="mt-4 space-y-3 max-h-[500px] overflow-y-auto pr-2">
|
|
<!-- Dynamically updated wireframe blocks via JS -->
|
|
</div>
|
|
</div>
|
|
|
|
<div class="pt-3 border-t border-slate-800 text-xs text-slate-400 flex justify-between items-center">
|
|
<span>💡 Pengaturan ini disimpan langsung di `wp_options` via WordPress Settings API.</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- SECTION 6: QUICK START GUIDE & SETUP CHECKLIST -->
|
|
<section id="quick-start" class="space-y-6 scroll-mt-20">
|
|
<!-- Section Intro -->
|
|
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm">
|
|
<span class="text-xs font-bold text-brand-600 uppercase tracking-wider">Petunjuk Penggunaan & Workflow</span>
|
|
<h2 class="text-xl sm:text-2xl font-bold text-slate-900 mt-1">Checklist Peluncuran Tema EduKarsa</h2>
|
|
<p class="text-xs sm:text-sm text-slate-600 mt-2">
|
|
Ikuti 4 langkah taktis berikut untuk mengonfigurasi situs web sekolah Anda dari nol hingga siap dipublikasikan. Centang setiap tugas yang selesai untuk memantau progres peluncuran.
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Progress Bar -->
|
|
<div class="bg-white p-5 rounded-2xl border border-slate-200 shadow-sm space-y-2">
|
|
<div class="flex justify-between items-center text-xs font-bold">
|
|
<span class="text-slate-700">Progres Kesiapan Situs Web Sekolah:</span>
|
|
<span id="setupProgressPercent" class="text-brand-800 text-sm">0% Selesai</span>
|
|
</div>
|
|
<div class="w-full bg-slate-100 rounded-full h-3 overflow-hidden border border-slate-200">
|
|
<div id="setupProgressBar" class="bg-brand-600 h-full w-0 transition-all duration-500"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Workflow Cards Grid -->
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<!-- Step 1 -->
|
|
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm space-y-3">
|
|
<div class="flex items-center gap-3">
|
|
<span class="w-8 h-8 rounded-full bg-brand-800 text-white font-black text-sm flex items-center justify-center">1</span>
|
|
<h3 class="font-bold text-slate-900 text-base">Pengaturan Identitas & Kontak</h3>
|
|
</div>
|
|
<p class="text-xs text-slate-600 leading-relaxed">
|
|
Masuk ke menu <strong>EduKarsa > ⚙️ Pengaturan Utama</strong> di Dasbor WordPress Anda.
|
|
</p>
|
|
<ul class="space-y-2 text-xs text-slate-700 pt-2">
|
|
<li class="flex items-start gap-2">
|
|
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
|
|
<span>Unggah Logo Header (PNG Transparan / WebP, tinggi 110px).</span>
|
|
</li>
|
|
<li class="flex items-start gap-2">
|
|
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
|
|
<span>Isi profil sekolah, alamat lengkap, nomor telepon, & email resmi.</span>
|
|
</li>
|
|
<li class="flex items-start gap-2">
|
|
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
|
|
<span>Tautkan URL media sosial resmi (Facebook, Instagram, YouTube).</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Step 2 -->
|
|
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm space-y-3">
|
|
<div class="flex items-center gap-3">
|
|
<span class="w-8 h-8 rounded-full bg-brand-800 text-white font-black text-sm flex items-center justify-center">2</span>
|
|
<h3 class="font-bold text-slate-900 text-base">Menyusun Tata Letak Beranda</h3>
|
|
</div>
|
|
<p class="text-xs text-slate-600 leading-relaxed">
|
|
Atur struktur tampilan utama agar sesuai dengan kebutuhan informasi calon siswa & wali murid.
|
|
</p>
|
|
<ul class="space-y-2 text-xs text-slate-700 pt-2">
|
|
<li class="flex items-start gap-2">
|
|
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
|
|
<span>Buka <strong>EduKarsa > 🏗️ Tata Letak</strong>.</span>
|
|
</li>
|
|
<li class="flex items-start gap-2">
|
|
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
|
|
<span>Geser (*drag and drop*) urutan seksi hero, statistik, program, & berita.</span>
|
|
</li>
|
|
<li class="flex items-start gap-2">
|
|
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
|
|
<span>Simpan susunan urutan tata letak.</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Step 3 -->
|
|
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm space-y-3">
|
|
<div class="flex items-center gap-3">
|
|
<span class="w-8 h-8 rounded-full bg-brand-800 text-white font-black text-sm flex items-center justify-center">3</span>
|
|
<h3 class="font-bold text-slate-900 text-base">Membuat Halaman Galeri & Fasilitas</h3>
|
|
</div>
|
|
<p class="text-xs text-slate-600 leading-relaxed">
|
|
Tampilkan dokumentasi laboratorium, ruang kelas, perpustakaan, dan kegiatan kampus.
|
|
</p>
|
|
<ul class="space-y-2 text-xs text-slate-700 pt-2">
|
|
<li class="flex items-start gap-2">
|
|
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
|
|
<span>Tambahkan foto di <strong>EduKarsa > 📸 Galeri Fasilitas</strong>.</span>
|
|
</li>
|
|
<li class="flex items-start gap-2">
|
|
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
|
|
<span>Buat Laman baru (**Laman > Tambah Baru**).</span>
|
|
</li>
|
|
<li class="flex items-start gap-2">
|
|
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
|
|
<span>Pilih atribut template <strong>Galeri & Fasilitas</strong>, lalu terbitkan.</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Step 4 -->
|
|
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm space-y-3">
|
|
<div class="flex items-center gap-3">
|
|
<span class="w-8 h-8 rounded-full bg-brand-800 text-white font-black text-sm flex items-center justify-center">4</span>
|
|
<h3 class="font-bold text-slate-900 text-base">Pengumuman & Pop-up Flyer PPDB</h3>
|
|
</div>
|
|
<p class="text-xs text-slate-600 leading-relaxed">
|
|
Aktifkan dialog pop-up promosi pendaftaran penerimaan siswa baru secara otomatis.
|
|
</p>
|
|
<ul class="space-y-2 text-xs text-slate-700 pt-2">
|
|
<li class="flex items-start gap-2">
|
|
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
|
|
<span>Buka panel <strong>🪟 8. Pop-up Flyer & Pengumuman</strong>.</span>
|
|
</li>
|
|
<li class="flex items-start gap-2">
|
|
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
|
|
<span>Aktifkan sakelar dan unggah flyer poster (min 800x800 px).</span>
|
|
</li>
|
|
<li class="flex items-start gap-2">
|
|
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
|
|
<span>Masukkan tautan tujuan pendaftaran online (PPDB), lalu simpan.</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
</main>
|
|
|
|
<!-- FOOTER -->
|
|
<footer class="bg-slate-900 text-white border-t border-slate-800 py-8 mt-12 text-xs">
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex flex-col sm:flex-row justify-between items-center gap-4 text-center sm:text-left">
|
|
<div>
|
|
<p class="font-bold text-white">EduKarsa - Enterprise Native WordPress Theme</p>
|
|
<p class="text-slate-400 mt-0.5">Dirancang dan dikembangkan secara independen oleh <strong>Mas Budi Kusuma</strong>.</p>
|
|
</div>
|
|
<div class="flex items-center gap-4 text-slate-400">
|
|
<a href="https://masbudi.my.id" target="_blank" class="hover:text-white transition-colors">masbudi.my.id</a>
|
|
<span>•</span>
|
|
<a href="mailto:[email protected]" class="hover:text-white transition-colors">[email protected]</a>
|
|
<span>•</span>
|
|
<span class="bg-slate-800 text-amber-400 px-2 py-1 rounded">Lisensi GNU GPL v2+</span>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
<!-- JAVASCRIPT LOGIC & APPLICATION STATE -->
|
|
<script>
|
|
// -------------------------------------------------------------
|
|
// APPLICATION DATA BASE (STORES DATA FROM SOURCE REPORT)
|
|
// -------------------------------------------------------------
|
|
const EDU_DATA = {
|
|
pillars: [
|
|
{
|
|
id: 'zero-plugin',
|
|
title: '1. Zero Plugin Dependency',
|
|
badge: 'Kecepatan & Kemandirian',
|
|
summary: 'Beroperasi penuh 100% mengandalkan kapabilitas inti WordPress tanpa ACF, Elementor, atau plugin slider pihak ketiga.',
|
|
details: 'Seluruh slider hero, kurikulum program, galeri lightbox, hingga modal flyer berjalan menggunakan skrip Vanilla JS native & pustaka WordPress core. Hal ini menghilangkan risiko plugin runtuh saat pembaruan versi utama WP.',
|
|
impact: 'Memangkas biaya lisensi tahunan plugin hingga 100% dan mengurangi ukuran database.'
|
|
},
|
|
{
|
|
id: 'modular-arch',
|
|
title: '2. Arsitektur Modular Terisolasi',
|
|
badge: 'Maintainability',
|
|
summary: 'Berkas functions.php bertindak murni sebagai loader; seluruh fungsi teknis diisolasi ke direktori inc/.',
|
|
details: 'Pemisahan logika dipisah ke berkas independen seperti inc/security.php, inc/seo.php, inc/admin-menu.php, dan inc/cpt-slider.php. Jika satu modul dimodifikasi, modul lain tetap aman tanpa efek samping (*side-effects*).',
|
|
impact: 'Kode bersih (*clean code*), konsisten dengan standar PSR-12, dan sangat mudah di-maintain.'
|
|
},
|
|
{
|
|
id: 'security-hardened',
|
|
title: '3. Keamanan Native (Hardened)',
|
|
badge: 'Proteksi Peretas',
|
|
summary: 'Injeksi HTTP Security Headers, anti-enumerasi pengguna (?author=N), dan proteksi REST API bawaan.',
|
|
details: 'Tema secara otomatis menginjeksi header X-Frame-Options, X-Content-Type-Options, Content-Security-Policy, serta menyembunyikan versi WP dari header untuk menggagalkan skrip peretas otomatis.',
|
|
impact: 'Mencegah serangan Brute Force author ID, Clickjacking, serta Cross-Site Scripting (XSS).'
|
|
},
|
|
{
|
|
id: 'wcag-a11y',
|
|
title: '4. Aksesibilitas WCAG 2.1 AAA',
|
|
badge: 'Inklusivitas Publik',
|
|
summary: 'Toolbar aksesibilitas melayang bawaan dengan pembaca suara Web Speech API & penyesuaian kontras.',
|
|
details: 'Pengunjung disabilitas netra atau lansia dapat memperbesar ukuran teks, mengaktifkan mode kontras tinggi, atau mendengarkan artikel dibacakan oleh suara sintesis sistem tanpa memasang plugin tambahan.',
|
|
impact: 'Memenuhi standar pelayanan informasi publik pemerintah & institusi pendidikan tinggi.'
|
|
},
|
|
{
|
|
id: 'drag-builder',
|
|
title: '5. Builder Tata Letak Native',
|
|
badge: 'Visual Layout',
|
|
summary: 'Mengatur urutan seksi beranda dengan drag-and-drop jQuery UI Sortable bawaan WordPress Admin.',
|
|
details: 'Pengelola web dapat mengubah urutan Hero Slider, Sambutan Kepsek, Keunggulan, Video Parallax, dan Berita secara visual langsung di panel EduKarsa > Tata Letak tanpa merusak kode PHP.',
|
|
impact: 'Memberikan fleksibilitas layout sekelas page builder berat dengan performa instan.'
|
|
},
|
|
{
|
|
id: 'multilingual',
|
|
title: '6. Multilingual Ready (5 Bahasa)',
|
|
badge: 'Internasionalisasi',
|
|
summary: 'Penerjemah instan frontend (ID, EN, AR, ZH, JA) & admin dashboard dwibahasa (ID/EN).',
|
|
details: 'Dilengkapi kamus terjemahan otomatis di inc/i18n.php serta tombol pengalih bahasa native pada header utama.',
|
|
impact: 'Siap digunakan untuk portal mahasiswa internasional atau sekolah bertaraf internasional (SPK).'
|
|
},
|
|
{
|
|
id: 'seo-schema',
|
|
title: '7. SEO & JSON-LD Schema Core',
|
|
badge: 'Peringkat Google',
|
|
summary: 'Injeksi otomatis OpenGraph, Twitter Cards, dan structured data EducationalOrganization.',
|
|
details: 'Menghasilkan JSON-LD Schema otomatis yang memvalidasi identitas sekolah di mesin pencari Google, melengkapi logo, koordinat alamat, dan profil resmi.',
|
|
impact: 'Meningkatkan visibilitas pencarian Google & tampilan pratinjau saat link dibagikan di Whatsapp/FB.'
|
|
}
|
|
],
|
|
assets: [
|
|
{ id: 'logo', name: 'Logo Header', dim: 'Lebar Proporsional, Tinggi 110 px', ratio: 'Fleksibel', format: 'PNG Transparan / WebP', size: 150, desc: 'Gunakan latar belakang transparan agar menyatu mulus dengan warna header biru navy.' },
|
|
{ id: 'slider', name: 'Slider Banner Hero', dim: '1920 x 1080 px / 1920 x 800 px', ratio: '16:9 / Wide Landscape', format: 'JPG / WebP', size: 300, desc: 'Format spanduk utama beranda. Pastikan fokus visual berada di tengah.' },
|
|
{ id: 'leader', name: 'Foto Pimpinan / Kepsek', dim: '600 x 800 px / 800 x 1067 px', ratio: '3:4 Portrait', format: 'JPG / WebP', size: 200, desc: 'Digunakan pada seksi Sambutan Kepala Sekolah (About Us).' },
|
|
{ id: 'flyer', name: 'Flyer Pop-up PPDB', dim: 'Minimal 800 x 800 px', ratio: '1:1 Persegi atau 4:5', format: 'JPG / WebP', size: 250, desc: 'Poster promosi pengumuman pendaftaran siswa baru yang muncul di layar modal.' },
|
|
{ id: 'gallery', name: 'Galeri Kampus & Fasilitas', dim: '1200 x 900 px', ratio: '4:3 Landscape', format: 'JPG / WebP', size: 250, desc: 'Foto dokumentasi laboratorium, ruang kelas, dan gedung untuk template galeri.' },
|
|
{ id: 'sidebar', name: 'Poster Sidebar', dim: 'Lebar 600 px (Tinggi Bebas)', ratio: 'Vertikal', format: 'JPG / WebP', size: 200, desc: 'Gambar iklan/banner promosi yang dipasang pada bilah samping artikel.' }
|
|
],
|
|
files: [
|
|
{ path: 'functions.php', cat: 'core', role: 'Theme Router & Module Loader', desc: 'File utama yang bersih. Hanya bertindak memuat berkas-berkas di folder inc/.' },
|
|
{ path: 'style.css', cat: 'core', role: 'Main Stylesheet & CSS Variables', desc: 'Menyimpan variabel warna tema, gaya kartu modern, dropdown menu, & responsive breakpoint.' },
|
|
{ path: 'front-page.php', cat: 'template', role: 'Modular Homepage Render Engine', desc: 'Membaca konfigurasi tata letak dari wp_options dan merender seksi beranda dinamis.' },
|
|
{ path: 'header.php', cat: 'template', role: 'Main Navigation & Lang Switcher', desc: 'Menampilkan header sticky, logo institusi, dan menu navigasi bertingkat.' },
|
|
{ path: 'footer.php', cat: 'template', role: '4-Column Footer & WA Float', desc: 'Menampilkan kolom kontak, tautan cepat, sosmed, dan widget aksesibilitas melayang.' },
|
|
{ path: 'index.php', cat: 'template', role: 'System Fallback & Post Archive', desc: 'Halaman cadangan sistem untuk menampilkan daftar berita jika template spesifik tidak ada.' },
|
|
{ path: 'page-galeri.php', cat: 'template', role: 'Gallery Template with Lightbox', desc: 'Template kustom halaman galeri dengan filter kategori dan modal lightbox Vanilla JS.' },
|
|
{ path: 'single-program.php', cat: 'template', role: 'Curriculum Details Template', desc: 'Halaman khusus untuk menampilkan rincian kurikulum dan program keahlian.' },
|
|
{ path: 'inc/setup.php', cat: 'inc', role: 'Theme Support & Asset Cache Busting', desc: 'Mendaftarkan fitur title-tag, post-thumbnails, menu, dan enqueue CSS/JS dengan cache-busting time().' },
|
|
{ path: 'inc/admin-menu.php', cat: 'inc', role: 'Dashboard & Settings API UI Builder', desc: 'Membuat menu EduKarsa di dasbor admin WP dan mengelola bidang pendaftaran opsi.' },
|
|
{ path: 'inc/cpt-slider.php', cat: 'inc', role: 'Custom Post Types (Slider, Program, etc)', desc: 'Mendaftarkan CPT Slider, Program, Milestone, dan Keunggulan beserta metabox URL.' },
|
|
{ path: 'inc/security.php', cat: 'inc', role: 'Hardened HTTP Headers & Protections', desc: 'Menyuntikkan HTTP Security Headers, memblokir enumerasi author ID, dan mengamankan REST API.' },
|
|
{ path: 'inc/seo.php', cat: 'inc', role: 'JSON-LD Schema & Social Metadata', desc: 'Injeksi otomatis OpenGraph meta dan EducationalOrganization JSON-LD structured data.' },
|
|
{ path: 'inc/i18n.php', cat: 'inc', role: 'Bilingual Dictionary Engine', desc: 'Menyediakan repositori terjemahan kata untuk frontend dan antarmuka admin.' },
|
|
{ path: 'inc/popup.php', cat: 'inc', role: 'Modal Flyer Logic & Session Handler', desc: 'Mengatur kemunculan pop-up flyer pendaftaran berdasarkan sesi pengunjung.' }
|
|
],
|
|
defaultLayout: [
|
|
{ id: 'slider', name: '1. Banner Hero Slider', icon: '🖼️', enabled: true },
|
|
{ id: 'stats', name: '2. Cards Statistik (3 Kolom)', icon: '🏫', enabled: true },
|
|
{ id: 'about', name: '3. Sambutan Kepala Sekolah', icon: '👤', enabled: true },
|
|
{ id: 'milestone', name: '4. Milestones & Pencapaian', icon: '🏆', enabled: true },
|
|
{ id: 'program', name: '5. Program Unggulan Kami', icon: '📚', enabled: true },
|
|
{ id: 'video', name: '6. Video Profile & Parallax', icon: '▶️', enabled: true },
|
|
{ id: 'keunggulan', name: '7. Keunggulan Sekolah (9 Grid)', icon: '⭐', enabled: true },
|
|
{ id: 'cta', name: '8. Banner Call to Action PPDB', icon: '📣', enabled: true },
|
|
{ id: 'news', name: '9. Berita & Pengumuman Terbaru', icon: '📰', enabled: true }
|
|
]
|
|
};
|
|
|
|
// -------------------------------------------------------------
|
|
// APP STATE & SIMULATOR VARIABLES
|
|
// -------------------------------------------------------------
|
|
let currentPillarIndex = 0;
|
|
let currentAssetIndex = 1; // Default Hero Slider
|
|
let currentFileFilter = 'all';
|
|
let currentLayoutState = JSON.parse(JSON.stringify(EDU_DATA.defaultLayout));
|
|
let simFontSizeVal = 100;
|
|
let isHighContrast = false;
|
|
|
|
// -------------------------------------------------------------
|
|
// INITIALIZATION ON DOM READY
|
|
// -------------------------------------------------------------
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
initCharts();
|
|
renderPillarsUI();
|
|
renderAssetSpecUI();
|
|
renderFileTreeUI();
|
|
renderLayoutSimulatorUI();
|
|
updateSetupProgress();
|
|
});
|
|
|
|
// -------------------------------------------------------------
|
|
// SECTION 1: CHART.JS INITIALIZATION
|
|
// -------------------------------------------------------------
|
|
let benchmarkChartObj, architectureChartObj, assetSizeChartObj;
|
|
|
|
function initCharts() {
|
|
// Label truncating helper (16-char rule)
|
|
const truncateLabel = (str) => (str.length > 16 ? str.substring(0, 13) + '...' : str);
|
|
|
|
// 1. Performance Benchmark Chart (Bar Chart)
|
|
const ctxBench = document.getElementById('benchmarkChart').getContext('2d');
|
|
benchmarkChartObj = new Chart(ctxBench, {
|
|
type: 'bar',
|
|
data: {
|
|
labels: ['Waktu Muat (ms)', 'Kueri Database', 'HTTP Requests', 'Payload (KB)'].map(truncateLabel),
|
|
datasets: [
|
|
{
|
|
label: 'EduKarsa (0 Plugin)',
|
|
data: [280, 14, 18, 420],
|
|
backgroundColor: '#0b4a8e',
|
|
borderRadius: 6
|
|
},
|
|
{
|
|
label: 'Tema Lain (15+ Plugins)',
|
|
data: [1850, 92, 85, 2450],
|
|
backgroundColor: '#cbd5e1',
|
|
borderRadius: 6
|
|
}
|
|
]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
legend: { position: 'top', labels: { font: { size: 11 } } },
|
|
tooltip: {
|
|
callbacks: {
|
|
label: (context) => `${context.dataset.label}: ${context.raw}`
|
|
}
|
|
}
|
|
},
|
|
scales: {
|
|
y: { beginAtZero: true, grid: { color: '#f1f5f9' } },
|
|
x: { grid: { display: false } }
|
|
}
|
|
}
|
|
});
|
|
|
|
// 2. Architecture Codebase Distribution Donut Chart
|
|
const ctxArch = document.getElementById('architectureChart').getContext('2d');
|
|
architectureChartObj = new Chart(ctxArch, {
|
|
type: 'doughnut',
|
|
data: {
|
|
labels: ['Admin & Settings', 'Security Headers', 'CPT & Metaboxes', 'SEO & JSON-LD', 'Templates Core', 'i18n & Utility'].map(truncateLabel),
|
|
datasets: [{
|
|
data: [25, 20, 18, 15, 12, 10],
|
|
backgroundColor: ['#0b4a8e', '#1a73e8', '#f59e0b', '#10b981', '#6366f1', '#8b5cf6'],
|
|
borderWidth: 2,
|
|
borderColor: '#ffffff'
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
legend: { position: 'right', labels: { boxWidth: 12, font: { size: 10 } } }
|
|
}
|
|
}
|
|
});
|
|
|
|
// 3. Asset Size Limits Horizontal Bar Chart
|
|
const ctxAsset = document.getElementById('assetSizeChart').getContext('2d');
|
|
assetSizeChartObj = new Chart(ctxAsset, {
|
|
type: 'bar',
|
|
data: {
|
|
labels: EDU_DATA.assets.map(a => truncateLabel(a.name)),
|
|
datasets: [{
|
|
label: 'Max Rekomendasi (KB)',
|
|
data: EDU_DATA.assets.map(a => a.size),
|
|
backgroundColor: '#f59e0b',
|
|
borderRadius: 4
|
|
}]
|
|
},
|
|
options: {
|
|
indexAxis: 'y',
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
legend: { display: false }
|
|
},
|
|
scales: {
|
|
x: { beginAtZero: true, max: 400, grid: { color: '#f1f5f9' } },
|
|
y: { grid: { display: false } }
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
let isChartToggled = false;
|
|
function toggleChartMetric() {
|
|
if (!benchmarkChartObj) return;
|
|
isChartToggled = !isChartToggled;
|
|
if (isChartToggled) {
|
|
benchmarkChartObj.data.datasets[0].data = [99, 100, 100, 95];
|
|
benchmarkChartObj.data.datasets[1].data = [40, 35, 30, 25];
|
|
benchmarkChartObj.data.datasets[0].label = 'Skor GTMetrix / Lighthouse';
|
|
benchmarkChartObj.data.datasets[1].label = 'Skor Tema Plugin Heavy';
|
|
} else {
|
|
benchmarkChartObj.data.datasets[0].data = [280, 14, 18, 420];
|
|
benchmarkChartObj.data.datasets[1].data = [1850, 92, 85, 2450];
|
|
benchmarkChartObj.data.datasets[0].label = 'EduKarsa (0 Plugin)';
|
|
benchmarkChartObj.data.datasets[1].label = 'Tema Lain (15+ Plugins)';
|
|
}
|
|
benchmarkChartObj.update();
|
|
}
|
|
|
|
// -------------------------------------------------------------
|
|
// SECTION 2: PILLARS & ACCESSIBILITY SIMULATOR LOGIC
|
|
// -------------------------------------------------------------
|
|
function renderPillarsUI() {
|
|
const btnContainer = document.getElementById('pillarButtonsContainer');
|
|
btnContainer.innerHTML = '';
|
|
|
|
EDU_DATA.pillars.forEach((pillar, idx) => {
|
|
const btn = document.createElement('button');
|
|
btn.className = `w-full text-left px-3 py-2.5 rounded-xl font-medium text-xs flex items-center justify-between transition-all ${
|
|
idx === currentPillarIndex
|
|
? 'bg-brand-800 text-white shadow-md font-bold'
|
|
: 'bg-slate-50 text-slate-700 hover:bg-slate-100 border border-slate-200'
|
|
}`;
|
|
btn.onclick = () => selectPillar(idx);
|
|
btn.innerHTML = `
|
|
<span class="truncate">${pillar.title}</span>
|
|
<span class="text-[9px] px-2 py-0.5 rounded ${idx === currentPillarIndex ? 'bg-amber-400 text-slate-950 font-bold' : 'bg-slate-200 text-slate-600'}">${pillar.badge}</span>
|
|
`;
|
|
btnContainer.appendChild(btn);
|
|
});
|
|
|
|
// Render Detail Pane
|
|
const p = EDU_DATA.pillars[currentPillarIndex];
|
|
const detailPane = document.getElementById('pillarDetailPane');
|
|
detailPane.innerHTML = `
|
|
<div class="flex items-center justify-between border-b border-slate-100 pb-3">
|
|
<span class="bg-brand-100 text-brand-800 text-xs font-bold px-2.5 py-1 rounded-md uppercase">${p.badge}</span>
|
|
<span class="text-xs text-slate-400">Arsitektur Native WordPress</span>
|
|
</div>
|
|
<h3 class="text-xl font-bold text-slate-900">${p.title}</h3>
|
|
<p class="text-sm text-slate-700 font-medium leading-relaxed">${p.summary}</p>
|
|
<div class="bg-slate-50 p-4 rounded-xl border border-slate-200 space-y-2 text-xs text-slate-600">
|
|
<strong class="text-slate-800 block">Detail Implementasi Kode:</strong>
|
|
<p class="leading-relaxed">${p.details}</p>
|
|
</div>
|
|
<div class="bg-emerald-50 border border-emerald-200 text-emerald-900 p-3 rounded-xl text-xs flex items-start gap-2">
|
|
<span class="text-base">🚀</span>
|
|
<div>
|
|
<strong class="block font-bold">Dampak Performa & Keamanan:</strong>
|
|
<span>${p.impact}</span>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
function selectPillar(idx) {
|
|
currentPillarIndex = idx;
|
|
renderPillarsUI();
|
|
}
|
|
|
|
// WCAG Accessibility Sim
|
|
function simulateHighContrast() {
|
|
isHighContrast = !isHighContrast;
|
|
const target = document.getElementById('a11yTestTarget');
|
|
if (isHighContrast) {
|
|
target.classList.add('a11y-high-contrast');
|
|
} else {
|
|
target.classList.remove('a11y-high-contrast');
|
|
}
|
|
}
|
|
|
|
function changeSimFontSize(delta) {
|
|
simFontSizeVal = Math.max(80, Math.min(150, simFontSizeVal + delta * 10));
|
|
document.getElementById('simFontLabel').innerText = simFontSizeVal + '%';
|
|
document.getElementById('a11yTextSample').style.fontSize = (simFontSizeVal / 100 * 14) + 'px';
|
|
}
|
|
|
|
function simulateScreenReader() {
|
|
const text = document.getElementById('a11yTextSample').innerText;
|
|
if ('speechSynthesis' in window) {
|
|
window.speechSynthesis.cancel(); // Reset
|
|
const utterance = new SpeechSynthesisUtterance(text);
|
|
utterance.lang = 'id-ID';
|
|
utterance.rate = 0.95;
|
|
window.speechSynthesis.speak(utterance);
|
|
alert('🔊 Pembaca Suara Aktif! (Membacakan sampel teks dalam Bahasa Indonesia)');
|
|
} else {
|
|
alert('Fitur Web Speech API tidak didukung oleh browser ini.');
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------
|
|
// SECTION 3: ASSETS SPEC & CANVAS RATIO VISUALIZER LOGIC
|
|
// -------------------------------------------------------------
|
|
function renderAssetSpecUI() {
|
|
const selectorGrid = document.getElementById('assetSelectorGrid');
|
|
selectorGrid.innerHTML = '';
|
|
|
|
EDU_DATA.assets.forEach((asset, idx) => {
|
|
const btn = document.createElement('button');
|
|
btn.className = `px-3 py-2 rounded-xl text-left text-xs font-semibold transition-all border ${
|
|
idx === currentAssetIndex
|
|
? 'bg-brand-800 text-white border-brand-800 shadow-sm'
|
|
: 'bg-white text-slate-700 border-slate-200 hover:bg-slate-50'
|
|
}`;
|
|
btn.onclick = () => selectAsset(idx);
|
|
btn.innerHTML = `<span class="block truncate">${asset.name}</span>`;
|
|
selectorGrid.appendChild(btn);
|
|
});
|
|
|
|
// Spec Box
|
|
const a = EDU_DATA.assets[currentAssetIndex];
|
|
const specBox = document.getElementById('assetSpecBox');
|
|
specBox.innerHTML = `
|
|
<div class="flex justify-between items-center border-b border-slate-200 pb-2">
|
|
<h4 class="font-bold text-slate-900 text-sm">${a.name}</h4>
|
|
<span class="bg-amber-100 text-amber-800 text-[10px] font-bold px-2 py-0.5 rounded">Rekomendasi Resmi</span>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3 text-xs">
|
|
<div>
|
|
<span class="text-slate-400 block">Dimensi Ideal:</span>
|
|
<strong class="text-slate-800">${a.dim}</strong>
|
|
</div>
|
|
<div>
|
|
<span class="text-slate-400 block">Rasio Aspek:</span>
|
|
<strong class="text-slate-800">${a.ratio}</strong>
|
|
</div>
|
|
<div>
|
|
<span class="text-slate-400 block">Format Berkas:</span>
|
|
<strong class="text-slate-800">${a.format}</strong>
|
|
</div>
|
|
<div>
|
|
<span class="text-slate-400 block">Batas Ukuran:</span>
|
|
<strong class="text-emerald-600">< ${a.size} KB</strong>
|
|
</div>
|
|
</div>
|
|
<p class="text-xs text-slate-600 italic border-t border-slate-200 pt-2">${a.desc}</p>
|
|
`;
|
|
|
|
document.getElementById('canvasRatioBadge').innerText = a.ratio;
|
|
document.getElementById('canvasFormatText').innerText = a.format;
|
|
document.getElementById('canvasSizeText').innerText = `< ${a.size} KB`;
|
|
|
|
// Draw Canvas Ratio Box
|
|
drawAssetCanvasRatio(a);
|
|
}
|
|
|
|
function selectAsset(idx) {
|
|
currentAssetIndex = idx;
|
|
renderAssetSpecUI();
|
|
}
|
|
|
|
function drawAssetCanvasRatio(asset) {
|
|
const canvas = document.getElementById('ratioPreviewCanvas');
|
|
const ctx = canvas.getContext('2d');
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
|
// Background canvas grid
|
|
ctx.fillStyle = '#f8fafc';
|
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
|
|
// Determine drawing dimensions based on asset ratio
|
|
let boxW = 220, boxH = 120;
|
|
if (asset.id === 'logo') { boxW = 240; boxH = 60; }
|
|
else if (asset.id === 'slider') { boxW = 260; boxH = 110; }
|
|
else if (asset.id === 'leader') { boxW = 120; boxH = 160; }
|
|
else if (asset.id === 'flyer') { boxW = 140; boxH = 140; }
|
|
else if (asset.id === 'gallery') { boxW = 200; boxH = 140; }
|
|
else if (asset.id === 'sidebar') { boxW = 110; boxH = 170; }
|
|
|
|
const startX = (canvas.width - boxW) / 2;
|
|
const startY = (canvas.height - boxH) / 2;
|
|
|
|
// Draw bounding box box
|
|
ctx.fillStyle = '#0b4a8e';
|
|
ctx.beginPath();
|
|
ctx.roundRect(startX, startY, boxW, boxH, 8);
|
|
ctx.fill();
|
|
|
|
// Draw Text Inside Box
|
|
ctx.fillStyle = '#ffffff';
|
|
ctx.font = 'bold 11px sans-serif';
|
|
ctx.textAlign = 'center';
|
|
ctx.fillText(asset.name, canvas.width / 2, canvas.height / 2 - 4);
|
|
ctx.font = '10px sans-serif';
|
|
ctx.fillStyle = '#f59e0b';
|
|
ctx.fillText(asset.ratio, canvas.width / 2, canvas.height / 2 + 12);
|
|
}
|
|
|
|
// -------------------------------------------------------------
|
|
// SECTION 4: FILE SYSTEM TREE EXPLORER LOGIC
|
|
// -------------------------------------------------------------
|
|
function renderFileTreeUI() {
|
|
const treeContainer = document.getElementById('fileTreeItems');
|
|
treeContainer.innerHTML = '';
|
|
|
|
const filtered = EDU_DATA.files.filter(f => currentFileFilter === 'all' || f.cat === currentFileFilter);
|
|
document.getElementById('fileCountBadge').innerText = `${filtered.length} Berkas Ditampilkan`;
|
|
|
|
filtered.forEach((file) => {
|
|
const item = document.createElement('div');
|
|
item.className = 'p-2 rounded-lg text-xs font-mono flex items-center justify-between cursor-pointer transition-all border border-transparent hover:bg-slate-100 hover:border-slate-200';
|
|
item.onclick = () => inspectFile(file.path);
|
|
|
|
let icon = '📄';
|
|
if (file.cat === 'inc') icon = '🧩';
|
|
if (file.cat === 'core') icon = '⚙️';
|
|
if (file.cat === 'template') icon = '🖥️';
|
|
|
|
item.innerHTML = `
|
|
<div class="flex items-center gap-2 truncate">
|
|
<span>${icon}</span>
|
|
<span class="text-slate-800 font-semibold truncate">${file.path}</span>
|
|
</div>
|
|
<span class="text-[9px] px-1.5 py-0.5 rounded bg-slate-200 text-slate-600 uppercase font-sans">${file.cat}</span>
|
|
`;
|
|
treeContainer.appendChild(item);
|
|
});
|
|
|
|
// Inspect first file by default
|
|
if (filtered.length > 0) inspectFile(filtered[0].path);
|
|
}
|
|
|
|
function filterFileList(cat) {
|
|
currentFileFilter = cat;
|
|
document.querySelectorAll('.filter-file-btn').forEach(btn => {
|
|
btn.className = 'filter-file-btn bg-slate-100 text-slate-700 hover:bg-slate-200 px-3 py-1.5 rounded-lg';
|
|
});
|
|
event.target.className = 'filter-file-btn bg-brand-800 text-white px-3 py-1.5 rounded-lg';
|
|
renderFileTreeUI();
|
|
}
|
|
|
|
function inspectFile(filePath) {
|
|
const f = EDU_DATA.files.find(item => item.path === filePath);
|
|
if (!f) return;
|
|
|
|
const inspector = document.getElementById('fileInspectorPane');
|
|
inspector.innerHTML = `
|
|
<div class="flex items-center justify-between border-b border-slate-100 pb-3">
|
|
<div class="flex items-center gap-2">
|
|
<span class="bg-brand-100 text-brand-800 font-mono text-xs font-bold px-2.5 py-1 rounded-md">${f.path}</span>
|
|
<span class="text-xs text-slate-400">Tipe Modul: ${f.cat.toUpperCase()}</span>
|
|
</div>
|
|
<span class="text-xs text-emerald-600 font-bold">✓ Native & Zero Plugin</span>
|
|
</div>
|
|
<div>
|
|
<h3 class="font-bold text-slate-900 text-base">${f.role}</h3>
|
|
<p class="text-xs text-slate-600 mt-1 leading-relaxed">${f.desc}</p>
|
|
</div>
|
|
<div class="bg-slate-900 text-slate-200 p-4 rounded-xl text-xs font-mono space-y-2">
|
|
<div class="text-slate-400">// Contoh Struktur Kode Terkait (${f.path})</div>
|
|
<div class="text-amber-400"><?php</div>
|
|
<div class="text-slate-300">
|
|
/**<br>
|
|
* ${f.role}<br>
|
|
* Multi-language & Hardened Security Native<br>
|
|
*/<br>
|
|
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
|
</div>
|
|
<div class="text-brand-100">add_action( 'init', 'edukarsa_register_${f.cat}_module' );</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// -------------------------------------------------------------
|
|
// SECTION 5: HOMEPAGE LAYOUT BUILDER SIMULATOR LOGIC
|
|
// -------------------------------------------------------------
|
|
function renderLayoutSimulatorUI() {
|
|
const container = document.getElementById('layoutBuilderControls');
|
|
container.innerHTML = '';
|
|
|
|
currentLayoutState.forEach((sec, idx) => {
|
|
const row = document.createElement('div');
|
|
row.className = `p-2.5 rounded-xl border flex items-center justify-between text-xs transition-all ${
|
|
sec.enabled ? 'bg-white border-slate-200 shadow-sm' : 'bg-slate-100 border-slate-200 opacity-60'
|
|
}`;
|
|
|
|
row.innerHTML = `
|
|
<div class="flex items-center gap-2">
|
|
<input type="checkbox" ${sec.enabled ? 'checked' : ''} onchange="toggleSectionEnable(${idx})" class="rounded text-brand-600">
|
|
<span class="font-bold text-slate-800">${sec.icon} ${sec.name}</span>
|
|
</div>
|
|
<div class="flex items-center gap-1">
|
|
<button onclick="moveSection(${idx}, -1)" ${idx === 0 ? 'disabled' : ''} class="px-2 py-1 bg-slate-100 hover:bg-slate-200 rounded text-slate-700 disabled:opacity-30">⬆️</button>
|
|
<button onclick="moveSection(${idx}, 1)" ${idx === currentLayoutState.length - 1 ? 'disabled' : ''} class="px-2 py-1 bg-slate-100 hover:bg-slate-200 rounded text-slate-700 disabled:opacity-30">⬇️</button>
|
|
</div>
|
|
`;
|
|
container.appendChild(row);
|
|
});
|
|
|
|
renderWireframePreview();
|
|
}
|
|
|
|
function toggleSectionEnable(idx) {
|
|
currentLayoutState[idx].enabled = !currentLayoutState[idx].enabled;
|
|
renderLayoutSimulatorUI();
|
|
}
|
|
|
|
function moveSection(idx, direction) {
|
|
const newIndex = idx + direction;
|
|
if (newIndex < 0 || newIndex >= currentLayoutState.length) return;
|
|
const temp = currentLayoutState[idx];
|
|
currentLayoutState[idx] = currentLayoutState[newIndex];
|
|
currentLayoutState[newIndex] = temp;
|
|
renderLayoutSimulatorUI();
|
|
}
|
|
|
|
function resetLayoutOrder() {
|
|
currentLayoutState = JSON.parse(JSON.stringify(EDU_DATA.defaultLayout));
|
|
renderLayoutSimulatorUI();
|
|
}
|
|
|
|
function renderWireframePreview() {
|
|
const wireframe = document.getElementById('wireframeContainer');
|
|
wireframe.innerHTML = '';
|
|
|
|
const activeSections = currentLayoutState.filter(s => s.enabled);
|
|
if (activeSections.length === 0) {
|
|
wireframe.innerHTML = '<div class="text-center py-8 text-xs text-slate-500">Semua seksi disembunyikan. Centang seksi untuk merender layout.</div>';
|
|
return;
|
|
}
|
|
|
|
activeSections.forEach((sec, idx) => {
|
|
const block = document.createElement('div');
|
|
block.className = 'p-3 rounded-lg border border-slate-700 bg-slate-800/90 text-white text-xs flex justify-between items-center shadow-sm';
|
|
block.innerHTML = `
|
|
<div class="flex items-center gap-2">
|
|
<span class="w-5 h-5 rounded-full bg-brand-600 text-[10px] font-bold flex items-center justify-center">${idx + 1}</span>
|
|
<span class="font-bold text-slate-200">${sec.name}</span>
|
|
</div>
|
|
<span class="text-[10px] bg-slate-700 text-amber-400 px-2 py-0.5 rounded font-mono"><section class="edukarsa-${sec.id}"></span>
|
|
`;
|
|
wireframe.appendChild(block);
|
|
});
|
|
}
|
|
|
|
function copyLayoutConfig() {
|
|
const activeNames = currentLayoutState.filter(s => s.enabled).map((s, i) => `${i + 1}. ${s.name}`).join('\n');
|
|
navigator.clipboard.writeText(`URUTAN STRUCTURAL LAYOUT EDUKARSA:\n${activeNames}`);
|
|
alert('📋 Konfigurasi urutan tata letak berhasil disalin ke clipboard!');
|
|
}
|
|
|
|
// -------------------------------------------------------------
|
|
// SECTION 6: QUICK START CHECKLIST & PROGRESS TRACKER
|
|
// -------------------------------------------------------------
|
|
function updateSetupProgress() {
|
|
const chks = document.querySelectorAll('.setup-chk');
|
|
let checkedCount = 0;
|
|
chks.forEach(c => { if (c.checked) checkedCount++; });
|
|
|
|
const percent = Math.round((checkedCount / chks.length) * 100);
|
|
document.getElementById('setupProgressBar').style.width = percent + '%';
|
|
document.getElementById('setupProgressPercent').innerText = `${percent}% Selesai (${checkedCount}/${chks.length} Tugas)`;
|
|
}
|
|
|
|
// -------------------------------------------------------------
|
|
// GLOBAL SEARCH & UTILITIES
|
|
// -------------------------------------------------------------
|
|
function scrollToSection(id) {
|
|
const el = document.getElementById(id);
|
|
if (el) el.scrollIntoView({ behavior: 'smooth' });
|
|
}
|
|
|
|
function handleGlobalSearch() {
|
|
const query = document.getElementById('globalSearchInput').value.toLowerCase().trim();
|
|
const box = document.getElementById('searchResultsBox');
|
|
const list = document.getElementById('searchResultsList');
|
|
|
|
if (query.length < 2) {
|
|
box.classList.add('hidden');
|
|
return;
|
|
}
|
|
|
|
list.innerHTML = '';
|
|
let resultsCount = 0;
|
|
|
|
// Search in Pillars
|
|
EDU_DATA.pillars.forEach(p => {
|
|
if (p.title.toLowerCase().includes(query) || p.details.toLowerCase().includes(query)) {
|
|
resultsCount++;
|
|
list.innerHTML += `<div class="p-2 hover:bg-slate-50 rounded border border-slate-100 cursor-pointer" onclick="scrollToSection('architecture'); closeSearchBox();">
|
|
<strong class="text-brand-800">[Pilar] ${p.title}</strong>
|
|
<p class="text-xs text-slate-600">${p.summary}</p>
|
|
</div>`;
|
|
}
|
|
});
|
|
|
|
// Search in Assets
|
|
EDU_DATA.assets.forEach(a => {
|
|
if (a.name.toLowerCase().includes(query) || a.dim.toLowerCase().includes(query)) {
|
|
resultsCount++;
|
|
list.innerHTML += `<div class="p-2 hover:bg-slate-50 rounded border border-slate-100 cursor-pointer" onclick="scrollToSection('assets'); closeSearchBox();">
|
|
<strong class="text-brand-800">[Aset] ${a.name}</strong>
|
|
<p class="text-xs text-slate-600">Dimensi: ${a.dim} (${a.format})</p>
|
|
</div>`;
|
|
}
|
|
});
|
|
|
|
// Search in Files
|
|
EDU_DATA.files.forEach(f => {
|
|
if (f.path.toLowerCase().includes(query) || f.role.toLowerCase().includes(query)) {
|
|
resultsCount++;
|
|
list.innerHTML += `<div class="p-2 hover:bg-slate-50 rounded border border-slate-100 cursor-pointer" onclick="scrollToSection('code-tree'); closeSearchBox();">
|
|
<strong class="text-brand-800">[File] ${f.path}</strong>
|
|
<p class="text-xs text-slate-600">${f.role} - ${f.desc}</p>
|
|
</div>`;
|
|
}
|
|
});
|
|
|
|
if (resultsCount > 0) {
|
|
box.classList.remove('hidden');
|
|
} else {
|
|
list.innerHTML = '<div class="text-xs text-slate-400 p-2">Tidak ditemukan hasil yang cocok.</div>';
|
|
box.classList.remove('hidden');
|
|
}
|
|
}
|
|
|
|
function closeSearchBox() {
|
|
document.getElementById('searchResultsBox').classList.add('hidden');
|
|
}
|
|
</script>
|
|
</body>
|
|
</html> |