PageSourceSearch

https://next-level-study.com/theme.js

js next-level-study.com collected 2026-10-04 14:40:32 UTC 26,161 bytes, 586 lines download raw bytes

1// Immediate theme initialization to prevent flash & mobile viewport lock
2(function() {
3    try {
4        if (typeof document !== 'undefined' && document.documentElement) {
5            document.documentElement.style.overflowX = 'hidden';
6            document.documentElement.style.maxWidth = '100%';
7        }
8        const savedTheme = localStorage.getItem('nls_theme');
9        const systemPrefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
10        if (savedTheme === 'dark' || (!savedTheme && systemPrefersDark)) {
11            document.documentElement.classList.add('dark');
12        } else {
13            document.documentElement.classList.remove('dark');
14        }
15    } catch (e) {
16        console.error('Error initializing theme', e);
17    }
18})();
19
20function updateThemeIcons() {
21    const isDark = document.documentElement.classList.contains('dark');
22    document.querySelectorAll('.theme-toggle-dark-icon').forEach(function(icon) {
23        if (isDark) {
24            icon.classList.add('hidden');
25        } else {
26            icon.classList.remove('hidden');
27        }
28    });
29    document.querySelectorAll('.theme-toggle-light-icon').forEach(function(icon) {
30        if (isDark) {
31            icon.classList.remove('hidden');
32        } else {
33            icon.classList.add('hidden');
34        }
35    });
36    
37    // Update tooltips / titles
38    document.querySelectorAll('.theme-toggle-btn').forEach(function(btn) {
39        btn.setAttribute('title', isDark ? 'Beralih ke Mode Terang' : 'Beralih ke Mode Gelap');
40        btn.setAttribute('aria-label', isDark ? 'Beralih ke Mode Terang' : 'Beralih ke Mode Gelap');
41    });
42}
43
44function toggleTheme() {
45    const isDark = document.documentElement.classList.toggle('dark');
46    try {
47        localStorage.setItem('nls_theme', isDark ? 'dark' : 'light');
48    } catch (e) {}
49    updateThemeIcons();
50}
51
52// Attach event listeners when DOM is loaded
53if (document.readyState === 'loading') {
54    document.addEventListener('DOMContentLoaded', initThemeButtons);
55} else {
56    initThemeButtons();
57}
58
59function initThemeButtons() {
60    updateThemeIcons();
61    document.querySelectorAll('.theme-toggle-btn').forEach(function(btn) {
62        btn.removeEventListener('click', toggleTheme);
63        btn.addEventListener('click', toggleTheme);
64    });
65}
66
67// Global Alpine Store for Program Registration & Teacher Recruitment Modal
68function initAlpineStores() {
69    if (typeof window === 'undefined' || !window.Alpine) return;
70
71    // 1. Store: daftarPrivat
72    if (!window.Alpine.store('daftarPrivat')) {
73        const defaultForm = {
74            kebutuhan: 'Privat',
75            nama: '',
76            jenjang: 'SD / Sederajat',
77            subjek: '',
78            wa: '',
79            catatan: ''
80        };
81
82        let savedForm = defaultForm;
83        try {
84            const raw = localStorage.getItem('nls_program_registration_form') || localStorage.getItem('nls_priv_registration_form');
85            if (raw) {
86                savedForm = Object.assign({}, defaultForm, JSON.parse(raw));
87            }
88        } catch (e) {}
89
90        window.Alpine.store('daftarPrivat', {
91            showRegistrationModal: false,
92            modalOpen: false,
93            showToast: false,
94            toastMessage: 'Formulir berhasil diproses! Mengarahkan ke WhatsApp...',
95            form: savedForm,
96            submitForm: function() {
97                try {
98                    localStorage.setItem('nls_program_registration_form', JSON.stringify(this.form));
99                } catch (e) {}
100
101                const k = this.form.kebutuhan || 'Privat';
102                const n = this.form.nama || '-';
103                const j = this.form.jenjang || '-';
104                const s = this.form.subjek || '-';
105                const w = this.form.wa || '-';
106                const c = this.form.catatan || '-';
107
108                const lines = [
109                    'Halo Admin Next Level Study!',
110                    '',
111                    'Saya ingin mendaftar / konsultasi program:',
112                    `*Kebutuhan:* ${k}`,
113                    `*Nama / Instansi:* ${n}`,
114                    `*Jenjang Pendidikan:* ${j}`,
115                    `*Subjek yang Diminati:* ${s}`,
116                    `*Nomor WhatsApp:* ${w}`,
117                    `*Catatan Tambahan:* ${c}`,
118                    '',
119                    'Mohon informasi dan tindak lanjutnya. Terima kasih!'
120                ];
121
122                const waUrl = 'https://wa.me/6285163070002?text=' + encodeURIComponent(lines.join('\n'));
123                window.open(waUrl, '_blank');
124
125                this.showRegistrationModal = false;
126                this.modalOpen = false;
127                this.showToast = true;
128                const self = this;
129                setTimeout(function() {
130                    self.showToast = false;
131                }, 4000);
132            },
133            submit: function() {
134                this.submitForm();
135            }
136        });
137    }
138
139    // 1.5. Store: paketPrivat (Adaptive Package Registration Modal)
140            if (!window.Alpine.store('paketPrivat')) {
141        window.Alpine.store('paketPrivat', {
142            showModal: false,
143            activePackageKey: 'reguler',
144            packageDetails: {
145                reguler: {
146                    key: 'reguler',
147                    title: 'Paket Reguler',
148                    tagline: 'Pendampingan Kurikulum Nasional & Persiapan TKA (SD, SMP, SMA)',
149                    badge: 'Kurikulum Nasional & TKA',
150                    price: 'Rp 120.000',
151                    priceUnit: '/ Jam',
152                    sessions: 'Ideal 8 sesi per bulan',
153                    themeColor: '#0284c7'
154                },
155                intensif: {
156                    key: 'intensif',
157                    title: 'Paket Exclusive',
158                    tagline: 'OSN Kota/Provinsi, Siswa SD/SMP Internasional & SNBT/Mandiri',
159                    badge: 'OSN Kota/Provinsi & SNBT',
160                    price: 'Rp 160.000',
161                    priceUnit: '/ Jam',
162                    sessions: 'Ideal 10 sesi per bulan (Paling Diminati)',
163                    themeColor: '#f59e0b'
164                },
165                internasional: {
166                    key: 'internasional',
167                    title: 'Paket Juara',
168                    tagline: 'OSN Semifinal/Final, SMA Internasional & Kompetisi Global (AMO, SEAMO)',
169                    badge: 'OSN Final & Global (AMO, SEAMO)',
170                    price: 'Rp 200.000',
171                    priceUnit: '/ Jam',
172                    sessions: 'Bimbingan Champion Level Dunia',
173                    themeColor: '#7c3aed'
174                }
175            },
176            get activePackage() {
177                return this.packageDetails[this.activePackageKey] || this.packageDetails.reguler;
178            },
179            formData: {
180                namaSiswa: '',
181                namaOrtu: '',
182                noWa: '',
183                asalSekolah: '',
184                tingkatKelas: 'SMA Kelas 12',
185                metodeBelajar: 'Online (Zoom 1-on-1)',
186                mataPelajaran: '',
187                
188                // Reguler Specifics
189                regulerFocus: [],
190                regulerTargetKampus: '',
191
192                // Intensif (Exclusive) Specifics
193                intensifFocus: [],
194                intensifExperience: '',
195
196                // Internasional (Juara) Specifics
197                internasionalFocus: [],
198                internasionalTargetKampus: '',
199
200                // Scheduling
201                sesiPerBulan: '8 Sesi / Bulan (2x seminggu - Standar)',
202                waktuBelajar: 'Sore / Malam (18.30 - 21.00 WIB)',
203                hariPreferensi: ['Hari Kerja (Senin - Jumat)'],
204                catatanKhusus: ''
205            },
206            open: function(pkgKey) {
207                this.activePackageKey = pkgKey || 'reguler';
208                if (pkgKey === 'reguler') {
209                    this.formData.tingkatKelas = 'SMA Kelas 12';
210                } else if (pkgKey === 'intensif') {
211                    this.formData.tingkatKelas = 'SMP Kelas 8';
212                } else if (pkgKey === 'internasional') {
213                    this.formData.tingkatKelas = 'SMA Kelas 11';
214                }
215                this.showModal = true;
216                try { document.body.style.overflow = 'hidden'; } catch (e) {}
217            },
218            setPackage: function(pkgKey) {
219                this.activePackageKey = pkgKey;
220            },
221            close: function() {
222                this.showModal = false;
223                try { document.body.style.overflow = ''; } catch (e) {}
224            },
225            toggleArrayItem: function(arr, item) {
226                const idx = arr.indexOf(item);
227                if (idx > -1) {
228                    arr.splice(idx, 1);
229                } else {
230                    arr.push(item);
231                }
232            },
233            submitForm: function() {
234                if (!this.formData.namaSiswa.trim()) {
235                    alert('Mohon masukkan Nama Lengkap Siswa.');
236                    return;
237                }
238                if (!this.formData.noWa.trim()) {
239                    alert('Mohon masukkan Nomor WhatsApp aktif.');
240                    return;
241                }
242                if (!this.formData.mataPelajaran.trim()) {
243                    alert('Mohon tuliskan Mata Pelajaran yang ingin dipelajari.');
244                    return;
245                }
246
247                const pkg = this.activePackage;
248                let text = '*FORMULIR PENDAFTARAN LES PRIVAT NLS*\n';
249                text += '--------------------------------------------\n';
250                text += '📌 *PILIHAN PAKET:* ' + pkg.title.toUpperCase() + '\n';
251                text += '💰 *Tarif:* ' + pkg.price + ' ' + pkg.priceUnit + ' (' + pkg.tagline + ')\n\n';
252
253                text += '👤 *DATA SISWA & ORANG TUA:*\n';
254                text += '• Nama Siswa: ' + this.formData.namaSiswa + '\n';
255                if (this.formData.namaOrtu.trim()) {
256                    text += '• Nama Orang Tua/Wali: ' + this.formData.namaOrtu + '\n';
257                }
258                text += '• WhatsApp: ' + this.formData.noWa + '\n';
259                text += '• Asal Sekolah: ' + (this.formData.asalSekolah || '-') + '\n';
260                text += '• Tingkat/Kelas: ' + this.formData.tingkatKelas + '\n';
261                text += '• Metode Belajar: ' + this.formData.metodeBelajar;
262                if (this.formData.metodeBelajar.includes('Offline')) {
263                    text += ' (+ Transport Guru Rp 50.000/sesi)';
264                }
265                text += '\n\n';
266
267                text += '🎯 *PENYESUAIAN KEBUTUHAN (' + pkg.title + '):*\n';
268                text += '• Mata Pelajaran: ' + this.formData.mataPelajaran + '\n';
269                
270                if (this.activePackageKey === 'reguler') {
271                    text += '• Diperuntukkan Untuk: ' + (this.formData.regulerFocus.join(', ') || '-') + '\n';
272                    if (this.formData.regulerTargetKampus.trim()) {
273                        text += '• Target Kampus/Sekolah: ' + this.formData.regulerTargetKampus + '\n';
274                    }
275                } else if (this.activePackageKey === 'intensif') {
276                    text += '• Diperuntukkan Untuk: ' + (this.formData.intensifFocus.join(', ') || '-') + '\n';
277                    text += '• Pengalaman Olimpiade: ' + this.formData.intensifExperience + '\n';
278                } else if (this.activePackageKey === 'internasional') {
279                    text += '• Diperuntukkan Untuk: ' + (this.formData.internasionalFocus.join(', ') || '-') + '\n';
280                    if (this.formData.internasionalTargetKampus.trim()) {
281                        text += '• Target Kampus Dunia/PTN: ' + this.formData.internasionalTargetKampus + '\n';
282                    }
283                }
284
285                text += '\n⏰ *RENCANA JADWAL & FREKUENSI:*\n';
286                text += '• Estimasi Sesi: ' + this.formData.sesiPerBulan + '\n';
287                text += '• Waktu Luang: ' + this.formData.waktuBelajar + '\n';
288                text += '• Hari Belajar: ' + (this.formData.hariPreferensi.join(', ') || '-') + '\n';
289
290                if (this.formData.catatanKhusus.trim()) {
291                    text += '\n📝 *Catatan Khusus:*\n' + this.formData.catatanKhusus + '\n';
292                }
293
294                text += '\n--------------------------------------------\n';
295                text += 'Halo Admin Next Level Study, mohon info ketersediaan mentor dan jadwalnya. Terima kasih!';
296
297                const adminWa = '6285163070002';
298                const waUrl = 'https://wa.me/' + adminWa + '?text=' + encodeURIComponent(text);
299                window.open(waUrl, '_blank');
300
301                this.showModal = false;
302            }
303        });
304    }
305
306    // 2. Store: gabungPengajar
307    if (!window.Alpine.store('gabungPengajar')) {
308        window.Alpine.store('gabungPengajar', {
309            modalOpen: false,
310            showRegistrationModal: false,
311            showModal: false,
312            form: {
313                nama: '',
314                panggilan: '',
315                wa: '',
316                email: '',
317                pendidikan: '',
318                photo: '',
319                categories: [],
320                jenjang: [],
321                subject: '',
322                fokusPrivat: '',
323                filosofi: '',
324                prestasi1: '',
325                prestasi2: '',
326                prestasi3: '',
327                portfolio: ''
328            },
329            isPhotoUploading: false,
330            handlePhotoUpload: function(event) {
331                const file = event.target.files && event.target.files[0];
332                if (!file) return;
333
334                if (!file.type.startsWith('image/')) {
335                    alert('Mohon pilih file gambar yang valid (JPG, PNG, atau WEBP).');
336                    return;
337                }
338
339                if (file.size > 10 * 1024 * 1024) {
340                    alert('Ukuran foto maksimal adalah 10MB. Mohon gunakan foto yang lebih ringan.');
341                    return;
342                }
343
344                const self = this;
345                self.isPhotoUploading = true;
346                const reader = new FileReader();
347                reader.onload = function(e) {
348                    const img = new Image();
349                    img.onload = function() {
350                        try {
351                            const canvas = document.createElement('canvas');
352                            let width = img.width;
353                            let height = img.height;
354                            const maxDimension = 600;
355
356                            if (width > height) {
357                                if (width > maxDimension) {
358                                    height = Math.round((height * maxDimension) / width);
359                                    width = maxDimension;
360                                }
361                            } else {
362                                if (height > maxDimension) {
363                                    width = Math.round((width * maxDimension) / height);
364                                    height = maxDimension;
365                                }
366                            }
367
368                            canvas.width = width;
369                            canvas.height = height;
370                            const ctx = canvas.getContext('2d');
371                            ctx.drawImage(img, 0, 0, width, height);
372
373                            // Compress into light and crisp 600px JPEG (~35-60KB)
374                            const compressedDataUrl = canvas.toDataURL('image/jpeg', 0.85);
375                            self.form.photo = compressedDataUrl;
376                        } catch(err) {
377                            // Fallback if canvas context fails
378                            self.form.photo = e.target.result;
379                        } finally {
380                            self.isPhotoUploading = false;
381                        }
382                    };
383                    img.onerror = function() {
384                        self.isPhotoUploading = false;
385                        alert('Gagal memproses gambar. Mohon coba file gambar lain.');
386                    };
387                    img.src = e.target.result;
388                };
389                reader.readAsDataURL(file);
390            },
391            submit: function() {
392                // Strict validation for Section 1
393                if (!this.form.nama || !this.form.nama.trim()) {
394                    alert('Mohon isi Nama Lengkap & Gelar Anda pada Bagian 1.');
395                    return;
396                }
397                if (!this.form.panggilan || !this.form.panggilan.trim()) {
398                    alert('Mohon isi Nama Panggilan / Sapaan pada Bagian 1.');
399                    return;
400                }
401                if (!this.form.wa || !this.form.wa.trim()) {
402                    alert('Mohon isi Nomor WhatsApp Aktif pada Bagian 1.');
403                    return;
404                }
405                if (!this.form.email || !this.form.email.trim()) {
406                    alert('Mohon isi Alamat Email Aktif pada Bagian 1.');
407                    return;
408                }
409                if (!this.form.pendidikan || !this.form.pendidikan.trim()) {
410                    alert('Mohon isi Asal Universitas & Prestasi Akademik pada Bagian 1.');
411                    return;
412                }
413                if (!this.form.photo) {
414                    alert('Mohon unggah Foto Profil Pengajar pada Bagian 1.');
415                    return;
416                }
417
418                // Strict validation for Section 2
419                if (!Array.isArray(this.form.categories) || this.form.categories.length === 0) {
420                    alert('Mohon pilih minimal 1 Bidang Keahlian & Program pada Bagian 2.');
421                    return;
422                }
423                if (!Array.isArray(this.form.jenjang) || this.form.jenjang.length === 0) {
424                    alert('Mohon pilih minimal 1 Sasaran Jenjang Mengajar pada Bagian 2.');
425                    return;
426                }
427                if (!this.form.subject || !this.form.subject.trim()) {
428                    alert('Mohon isi Spesialisasi Mata Pelajaran Utama pada Bagian 2.');
429                    return;
430                }
431
432                // Strict validation for Section 3
433                if (!this.form.fokusPrivat || !this.form.fokusPrivat.trim()) {
434                    alert('Mohon isi Fokus Kebutuhan Les Privat pada Bagian 3.');
435                    return;
436                }
437                if (!this.form.filosofi || !this.form.filosofi.trim()) {
438                    alert('Mohon isi Kutipan / Filosofi Mengajar Anda pada Bagian 3.');
439                    return;
440                }
441
442                const catStr = this.form.categories.join(', ');
443                const jnjStr = this.form.jenjang.join(', ');
444                
445                // 1. Create teacher application record for admin Teacher Verification
446                const fullName = this.form.nama.trim();
447                const nickName = this.form.panggilan.trim();
448                const nowIso = new Date().toISOString();
449
450                const application = {
451                    id: 'app-' + Date.now(),
452                    submittedAt: nowIso,
453                    applied_at: nowIso,
454                    status: 'pending',
455                    nama: fullName,
456                    name: fullName,
457                    panggilan: nickName,
458                    shortName: nickName,
459                    wa: this.form.wa.trim(),
460                    phone: this.form.wa.trim(),
461                    email: this.form.email.trim(),
462                    pendidikan: this.form.pendidikan.trim(),
463                    education: this.form.pendidikan.trim(),
464                    photo: this.form.photo || '/images/pengajar/mentor-1-math.jpg',
465                    categories: [...this.form.categories],
466                    jenjang: [...this.form.jenjang],
467                    jenjangLabel: this.form.jenjang.join(' & '),
468                    subject: this.form.subject.trim(),
469                    subjects: [this.form.subject.trim()],
470                    kebutuhanPrivat: this.form.fokusPrivat.trim(),
471                    fokusPrivat: this.form.fokusPrivat.trim(),
472                    philosophy: this.form.filosofi.trim(),
473                    filosofi: this.form.filosofi.trim(),
474                    highlights: [this.form.prestasi1, this.form.prestasi2, this.form.prestasi3].filter(
474Boolean),
475                    portfolio: (this.form.portfolio || '').trim(),
476                    cv_link: (this.form.portfolio || '').trim(),
477                    notes: ''
478                };
479
480                // 2. Save into serverless database API, localStorage & sync cross-tab
481                try {
482                    // Send to backend API
483                    if (typeof fetch !== 'undefined') {
484                        fetch('/api/teacher-applications', {
485                            method: 'POST',
486                            headers: { 'Content-Type': 'application/json' },
487                            body: JSON.stringify(application)
488                        }).catch(function(err) {
489                            console.warn('[NLS] API save error:', err);
490                        });
491                    }
492
493                    let apps = [];
494                    const stored = localStorage.getItem("nls_teacher_applications_v1");
495                    if (stored) {
496                        const parsed = JSON.parse(stored);
497                        if (Array.isArray(parsed)) apps = parsed;
498                    }
499                    apps.unshift(application);
500                    localStorage.setItem("nls_teacher_applications_v1", JSON.stringify(apps));
501                    
502                    if (typeof window !== 'undefined' && window.PengajarDatabase && typeof window.PengajarDatabase.submitApplication === 'function') {
503                        try {
504                            window.PengajarDatabase.submitApplication(application);
505                        } catch (err) {}
506                    }
507
508                    if (typeof BroadcastChannel !== 'undefined') {
509                        const bc = new BroadcastChannel('nls_sync_channel');
510                        bc.postMessage({ type: 'SYNC_ALL' });
511                        bc.postMessage({ type: 'TEACHER_APPLICATION_ADDED', data: application });
512                        bc.postMessage({ type: 'TEACHER_APPLICATIONS_UPDATED', data: apps });
513                    }
514                    window.dispatchEvent(new CustomEvent('nls-teacher-application-added', { detail: application }));
515                    window.dispatchEvent(new CustomEvent('nls-teacher-applications-updated', { detail: apps }));
516                } catch (e) {
517                    console.error('Error saving teacher application:', e);
518                }
519
520                const lines = [
521                    '🌟 *PENDAFTARAN PENGAJAR & MENTOR - NEXT LEVEL STUDY* 🌟',
522                    '━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
523                    '',
524                    '👤 *1. DATA PRIBADI & PENDIDIKAN*',
525                    `• *Nama Lengkap & Gelar:* ${this.form.nama || '-'}`,
526                    `• *Nama Panggilan / Sapaan:* ${this.form.panggilan || '-'}`,
527                    `• *Nomor WhatsApp:* ${this.form.wa || '-'}`,
528                    `• *Alamat Email:* ${this.form.email || '-'}`,
529                    `• *Latar Belakang Pendidikan / Kampus:* ${this.form.pendidikan || '-'}`,
530                    '',
531                    '📚 *2. BIDANG KEAHLIAN & SASARAN PROGRAM*',
532                    `• *Bidang Keahlian:* ${catStr}`,
533                    `• *Sasaran Jenjang:* ${jnjStr}`,
534                    `• *Spesialisasi Mata Pelajaran:* ${this.form.subject || '-'}`,
535                    '',
536                    '🎯 *3. FOKUS KEBUTUHAN LES PRIVAT*',
537                    `${this.form.fokusPrivat || '-'}`,
538                    '',
539                    '💬 *4. FILOSOFI / QUOTE MENGAJAR*',
540                    `"${this.form.filosofi || '-'}"`,
541                    '',
542                    '🏆 *5. REKAM JEJAK & PRESTASI*',
543                    `1. ${this.form.prestasi1 || '-'}`,
544                    `2. ${this.form.prestasi2 || '-'}`,
545                    `3. ${this.form.prestasi3 || '-'}`,
546                    '',
547                    '🔗 *6. LINK CV / PORTOFOLIO*',
548                    `${this.form.portfolio || '-'}`,
549                    '',
550                    '━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
551                    '✅ *Komitmen:* Saya siap mengikuti rangkaian seleksi dan menjunjung tinggi kode etik & integritas pendidik Next Level Study.'
552                ];
553
554                const waUrl = 'https://wa.me/6285163070002?text=' + encodeURIComponent(lines.join('\n'));
555                window.open(waUrl, '_blank');
556                
557                alert('Pendaftaran berhasil dikirim! Formulir Anda telah masuk ke antrean Teacher Verification NLS dan diteruskan ke Tim Akademik.');
558
559                this.modalOpen = false;
560                this.showRegistrationModal = false;
561                this.showModal = false;
562
563                this.form = {
564                    nama: '', panggilan: '', wa: '', email: '', pendidikan: '',
565                    categories: [], jenjang: [], subject: '', fokusPrivat: '',
566                    filosofi: '', prestasi1: '', prestasi2: '', prestasi3: '', portfolio: ''
567                };
568            },
569            submitForm: function() {
570                this.submit();
571            }
572        });
573    }
574}
575
576if (typeof window !== 'undefined') {
577    window.initAlpineStores = initAlpineStores;
578    if (window.Alpine) {
579        initAlpineStores();
580    } else {
581        document.addEventListener('alpine:init', initAlpineStores);
582        document.addEventListener('DOMContentLoaded', function() {
583            if (window.Alpine) initAlpineStores();
584        });
585    }
586}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.