diff --git a/groups/C4A/README.md b/groups/C4A/README.md index a5f6721..abb90fa 100644 --- a/groups/C4A/README.md +++ b/groups/C4A/README.md @@ -12,11 +12,14 @@ Dokumentasi ini dibuat untuk memudahkan pengembang atau pengguna berikutnya dala - Data SOP: `groups/C4A/data/data-sop.json` - Data FAQ: `groups/C4A/data/data-faq.json` -2. **Ikon FontAwesome (v4)**: +2. **Dukungan Bilingual (ID/EN)**: + Semua teks konten yang ditampilkan ke pengguna mendukung dua bahasa. Anda perlu menggunakan objek dengan properti `id` (Bahasa Indonesia) dan `en` (Bahasa Inggris) pada setiap field teks. Jika properti `en` tidak diisi atau data masih berupa *string* biasa, sistem akan otomatis menggunakan Bahasa Indonesia sebagai *fallback*. + +3. **Ikon FontAwesome (v4)**: Jika ingin mengubah atau menambahkan logo/ikon pada data SOP, harap gunakan daftar ikon dari **FontAwesome v4** melalui tautan berikut: 👉 **[FontAwesome v4 Icons](https://fontawesome.com/v4/icons/)** (Contoh penggunaan: `fa-dot-circle-o`, `fa-graduation-cap`, `fa-flask`). -3. **Field Opsional**: +4. **Field Opsional**: Pada data SOP, properti **`staff_responsible`** (Staf Bertanggung Jawab) dan **`additional_info`** (Informasi Tambahan) bersifat **opsional**. Jika informasi tersebut tidak tersedia, kosongkan nilainya atau hapus propertinya dari JSON agar UI secara otomatis menyembunyikan bloknya. --- @@ -30,21 +33,39 @@ Silakan salin-tempel (copy-paste) format di bawah ini ke dalam array JSON yang s { "id": 3, "name": "Nama Staf Beserta Gelar", - "role": "Peran / Jabatan Staf", + "role": { + "id": "Peran / Jabatan Staf", + "en": "Staff Role / Title" + }, "image": "assets/images/nama-file-foto.png", - "location": "Lokasi Ruang Kerja / Kantor Staf", + "location": { + "id": "Lokasi Ruang Kerja / Kantor Staf", + "en": "Staff Workspace / Office Location" + }, "contact_consent": true, "phone": "628xxxxxxxxxx", "schedule": [ { - "day": "Hari Kerja (contoh: Senin – Jumat)", - "time": "Jam Kerja (contoh: 07.30–16.00 WIB)", - "break": "Jam Istirahat (contoh: istirahat 12.00–13.00 WIB)" + "day": { + "id": "Hari Kerja (contoh: Senin – Jumat)", + "en": "Work Days (e.g., Monday – Friday)" + }, + "time": "07.30–16.00 WIB", + "break": { + "id": "Jam Istirahat (contoh: istirahat 12.00–13.00 WIB)", + "en": "Break Time (e.g., break 12.00–13.00 WIB)" + } } ], "tasks": [ - "Tugas dan tanggung jawab utama 1", - "Tugas dan tanggung jawab utama 2" + { + "id": "Tugas dan tanggung jawab utama 1", + "en": "Main task and responsibility 1" + }, + { + "id": "Tugas dan tanggung jawab utama 2", + "en": "Main task and responsibility 2" + } ] } ``` @@ -57,21 +78,33 @@ Silakan salin-tempel (copy-paste) format di bawah ini ke dalam array JSON yang s "tab_number": 9, "category": "akademik", "icon": "fa-file-text", - "title": "Judul Lengkap SOP", - "description": "Deskripsi singkat mengenai SOP ini.", - "purpose": "Tujuan dibuatnya standar operasional prosedur ini.", + "title": { + "id": "Judul Lengkap SOP", + "en": "Full SOP Title" + }, + "description": { + "id": "Deskripsi singkat mengenai SOP ini.", + "en": "Brief description of this SOP." + }, + "purpose": { + "id": "Tujuan dibuatnya standar operasional prosedur ini.", + "en": "The purpose of creating this standard operating procedure." + }, "requirements": [ - "Persyaratan administratif/akademik 1", - "Persyaratan administratif/akademik 2" + { "id": "Persyaratan administratif/akademik 1", "en": "Administrative/academic requirement 1" }, + { "id": "Persyaratan administratif/akademik 2", "en": "Administrative/academic requirement 2" } ], "procedures": [ - "Langkah alur prosedur ke-1", - "Langkah alur prosedur ke-2" + { "id": "Langkah alur prosedur ke-1", "en": "Procedure flow step 1" }, + { "id": "Langkah alur prosedur ke-2", "en": "Procedure flow step 2" } ], "staff_responsible": [ - "👤 Staf Administrasi Informatika" + "👤 Staf Administrasi Informatika / Informatics Administrative Staff" ], - "additional_info": "Informasi tambahan penting." + "additional_info": { + "id": "Informasi tambahan penting.", + "en": "Important additional information." + } } ``` *Catatan: Properti `category` bernilai antara `"akademik"` atau `"praktikum"`. Properti `staff_responsible` dan `additional_info` bersifat opsional.* @@ -80,7 +113,13 @@ Silakan salin-tempel (copy-paste) format di bawah ini ke dalam array JSON yang s ```json { "id": 11, - "question": "Pertanyaan yang sering diajukan?", - "answer": "Jawaban dari pertanyaan tersebut. Boleh menggunakan tag HTML seperti tebal." + "question": { + "id": "Pertanyaan yang sering diajukan?", + "en": "Frequently asked question?" + }, + "answer": { + "id": "Jawaban dari pertanyaan tersebut. Boleh menggunakan tag HTML seperti tebal.", + "en": "Answer to the question. HTML tags like bold can be used." + } } ``` diff --git a/groups/C4A/index.html b/groups/C4A/index.html index 0092051..ac38de3 100644 --- a/groups/C4A/index.html +++ b/groups/C4A/index.html @@ -1,4 +1,4 @@ - + @@ -1163,7 +1163,7 @@
LAYANAN AKADEMIK • INFORMATIKA UNTAN

- Staf Pendukung &
+ Staf Pendukung &
Standar Operasional Prosedur (SOP)

Halaman ini menampilkan informasi petugas diff --git a/groups/C4A/js/ui.js b/groups/C4A/js/ui.js index 14ea1a2..8f9f26e 100644 --- a/groups/C4A/js/ui.js +++ b/groups/C4A/js/ui.js @@ -32,7 +32,7 @@ function loc(field) { const lang = getLang(); return field[lang] || field['id'] || ''; } - return field; + return String(field); } /** @@ -127,7 +127,7 @@ export function renderStaffCards(staffs) { const scheduleHTML = schedule.map(sched => `

` + `${loc(sched.day)}` + - `${sched.time} | ${loc(sched.break)}` + + `${loc(sched.time)} | ${loc(sched.break)}` + `
` ).join(''); @@ -149,7 +149,7 @@ export function renderStaffCards(staffs) { ${name}
-
${name}
+
${loc(name)}
${roleText}
@@ -283,14 +283,13 @@ function buildSopModalContent(sop) { const catLabel = getCatLabel(category); const catClass = CATEGORY_COLORS[category] || ''; - const reqsHTML = requirements.map(req => `
  • ${loc(req)}
  • `).join(''); const procsHTML = procedures.map(proc => `
  • ${loc(proc)}
  • `).join(''); // staffResponsible bersifat opsional — sembunyikan blok jika tidak ada const hasStaff = Array.isArray(staffResponsible) && staffResponsible.length > 0; const staffHTML = hasStaff - ? staffResponsible.map(staffName => `${staffName}`).join('') + ? staffResponsible.map(staffName => `${loc(staffName)}`).join('') : ''; const staffBlockHTML = hasStaff ? `
    @@ -353,15 +352,19 @@ export function renderSopCards(sops) { // simpan data global di element agar bisa diakses filter/search container._sopData = sops; + const emptyState = document.getElementById('sop-empty-state'); + // Tampilkan pesan jika data SOP kosong atau gagal dimuat if (!sops || sops.length === 0) { container.innerHTML = `

    ${t('grp_c4a_empty_sop', 'Data SOP tidak tersedia saat ini.')}

    `; updateResultInfo(0, 0); + if (emptyState) emptyState.style.display = 'none'; return; } container.innerHTML = sops.map(buildSopCard).join(''); updateResultInfo(sops.length, sops.length); + if (emptyState) emptyState.style.display = 'none'; } /** Update teks info jumlah hasil */ @@ -405,7 +408,12 @@ export function applySopFilter() { }); const emptyState = document.getElementById('sop-empty-state'); - if (emptyState) emptyState.style.display = visibleCount === 0 ? 'flex' : 'none'; + if (emptyState) { + // Tampilkan "SOP tidak ditemukan" HANYA jika memang ada data SOP tetapi hasil filter 0. + // Jika data SOP memang kosong (tidak ada card sama sekali di data source), sembunyikan. + const hasData = container._sopData && container._sopData.length > 0; + emptyState.style.display = (hasData && visibleCount === 0) ? 'flex' : 'none'; + } updateResultInfo(visibleCount, cards.length); }