// ===================================================== // API.js โ€” Mekanisme Fetch Data Beasiswa (terpusat) // ----------------------------------------------------- // Alur: coba API remote (Directus publik) โ†’ jika gagal, // fallback ke berkas lokal `data/beasiswa.json`. // // Data remote dinormalisasi ke skema UI yang sama dengan // data lokal agar filter.js dan popup.js tidak perlu berubah. // ===================================================== (function (global) { 'use strict'; const CONFIG = { baseUrl: 'https://api.ifuntanhub.dev', collection: '/items/beasiswa', localSource: 'data/beasiswa.json', }; // Normalise status remote โ†’ nilai yang dipakai UI function normalizeStatus(s) { if (!s) return 'Ditutup'; const lower = s.toLowerCase(); if (lower === 'dibuka' || lower === 'buka') return 'Buka'; if (lower === 'ditutup') return 'Ditutup'; return s; // "Segera Dibuka" atau nilai lain: tampilkan apa adanya } // Petakan satu item (API remote maupun lokal) ke skema yang diharapkan filter.js / popup.js function normalizeItem(item) { const parts = [item.jenjang, item.negara, item.tipe_pendanaan].filter(Boolean); return { id: String(item.id), nama: item.nama || '', status: normalizeStatus(item.status), kategori: item.tipe_pendanaan || '', thumbnail: item.thumbnail || '', deskripsi_singkat: item.deskripsi_singkat || parts.join(' ยท ') || 'Info beasiswa tersedia di sumber resmi.', deskripsi_singkat_en: item.deskripsi_singkat_en || '', tanggal_buka: item.tanggal_buka || '', tanggal_tutup: item.tenggat_waktu || '', url_sumber: item.url || '', syarat_umum: item.syarat_umum || [], syarat_umum_en: item.syarat_umum_en || [], kontak: item.kontak || '', tags: item.tags || parts, }; } async function fetchRemote() { const res = await fetch(CONFIG.baseUrl + CONFIG.collection); if (!res.ok) throw new Error(`API merespons HTTP ${res.status}`); const json = await res.json(); return (json.data || []).map(normalizeItem); } async function fetchLocal() { const res = await fetch(CONFIG.localSource); if (!res.ok) throw new Error(`Gagal memuat data lokal (HTTP ${res.status})`); const json = await res.json(); const raw = Array.isArray(json) ? json : json.data || []; return raw.map(normalizeItem); } async function getBeasiswa() { try { const data = await fetchRemote(); return { data, source: 'remote' }; } catch (err) { console.warn('[BeasiswaAPI] API remote gagal, fallback ke data lokal:', err.message); try { const data = await fetchLocal(); return { data, source: 'local' }; } catch (localErr) { console.error('[BeasiswaAPI] Semua sumber gagal:', localErr.message); throw localErr; } } } global.BeasiswaAPI = { config: CONFIG, getBeasiswa, fetchRemote, fetchLocal }; })(window);