fix(c4a): fix 'SOP tidak ditemukan' visibility logic on page load

This commit is contained in:
cygouw
2026-06-05 14:50:20 +07:00
parent 946497214b
commit 24e1d6ec17
+51 -21
View File
@@ -12,6 +12,20 @@ function t(key, fallback) {
return fallback; return fallback;
} }
/**
* Helper untuk melokalisasi teks dari objek bilingual {id, en} atau string biasa.
* @param {string|Object} field - Data teks (bisa string biasa atau objek {id, en})
* @returns {string} Teks terlokalisasi
*/
function loc(field) {
if (!field) return '';
if (typeof field === 'object') {
const lang = (window.getLang && typeof window.getLang === 'function') ? window.getLang() : 'id';
return field[lang] || field['id'] || '';
}
return String(field);
}
/** /**
* Normalisasi nomor telepon ke format standard e.g. 628... * Normalisasi nomor telepon ke format standard e.g. 628...
* @param {string} phone - Nomor telepon mentah * @param {string} phone - Nomor telepon mentah
@@ -100,12 +114,12 @@ export function renderStaffCards(staffs) {
const scheduleHTML = schedule.map(sched => const scheduleHTML = schedule.map(sched =>
`<div class="schedule-item">` + `<div class="schedule-item">` +
`<span class="s-day">${sched.day}</span>` + `<span class="s-day">${loc(sched.day)}</span>` +
`<span class="s-time">${sched.time} <span class="s-break">| ${sched.break}</span></span>` + `<span class="s-time">${loc(sched.time)} <span class="s-break">| ${loc(sched.break)}</span></span>` +
`</div>` `</div>`
).join(''); ).join('');
const tasksHTML = tasks.map(task => `<li>${task}</li>`).join(''); const tasksHTML = tasks.map(task => `<li>${loc(task)}</li>`).join('');
const isPhoneValid = isValidWhatsAppNumber(phone); const isPhoneValid = isValidWhatsAppNumber(phone);
const encodedPhone = isPhoneValid ? encodePhone(phone) : ''; const encodedPhone = isPhoneValid ? encodePhone(phone) : '';
const displayPhone = isPhoneValid ? formatPhoneForDisplay(phone) : '-'; const displayPhone = isPhoneValid ? formatPhoneForDisplay(phone) : '-';
@@ -123,13 +137,13 @@ export function renderStaffCards(staffs) {
<img src="${image}" alt="${name}" onerror="this.style.display='none'"/> <img src="${image}" alt="${name}" onerror="this.style.display='none'"/>
</div> </div>
<div> <div>
<div class="staff-name">${name}</div> <div class="staff-name">${loc(name)}</div>
<div class="staff-role">${role}</div> <div class="staff-role">${loc(role)}</div>
</div> </div>
</div> </div>
<div class="staff-card-body"> <div class="staff-card-body">
<div class="staff-info-grid"> <div class="staff-info-grid">
<div class="staff-info-item"><span class="icon">📍</span><div><span class="label">${t('grp_c4a_label_location', 'Lokasi')}</span><span class="val">${location}</span></div></div> <div class="staff-info-item"><span class="icon">📍</span><div><span class="label">${t('grp_c4a_label_location', 'Lokasi')}</span><span class="val">${loc(location)}</span></div></div>
<div class="staff-info-item"> <div class="staff-info-item">
<span class="icon">🕒</span> <span class="icon">🕒</span>
<div style="flex:1"> <div style="flex:1">
@@ -202,27 +216,29 @@ function buildSopCard(sop) {
const catLabel = getCatLabel(category); const catLabel = getCatLabel(category);
const catClass = CATEGORY_COLORS[category] || ''; const catClass = CATEGORY_COLORS[category] || '';
const titleText = loc(title);
const descText = loc(description);
return ` return `
<article class="sop-grid-card reveal" data-tab-id="${tabId}" data-category="${category}" data-title="${title.toLowerCase()}"> <article class="sop-grid-card reveal" data-tab-id="${tabId}" data-category="${category}" data-title="${titleText.toLowerCase()}">
<div class="sgc-header"> <div class="sgc-header">
<div class="sgc-icon-wrap"> <div class="sgc-icon-wrap">
<i class="fas ${icon}"></i> <i class="fas ${icon}"></i>
</div> </div>
<div class="sgc-meta"> <div class="sgc-meta">
<h3 class="sgc-title">${title}</h3> <h3 class="sgc-title">${titleText}</h3>
</div> </div>
</div> </div>
<div class="sgc-category-row"> <div class="sgc-category-row">
<span class="sgc-category ${catClass}">${catLabel}</span> <span class="sgc-category ${catClass}">${catLabel}</span>
</div> </div>
<p class="sgc-desc">${description}</p> <p class="sgc-desc">${descText}</p>
<div class="sgc-footer"> <div class="sgc-footer">
<div class="sgc-steps"> <div class="sgc-steps">
<i class="fas fa-list-ol"></i> <i class="fas fa-list-ol"></i>
<span>${procedures.length} ${t('grp_c4a_label_steps', 'Langkah')}</span> <span>${procedures.length} ${t('grp_c4a_label_steps', 'Langkah')}</span>
</div> </div>
<button class="sgc-detail-btn" data-tab-id="${tabId}" aria-label="${t('grp_c4a_label_view_detail', 'Lihat Detail')} ${title}"> <button class="sgc-detail-btn" data-tab-id="${tabId}" aria-label="${t('grp_c4a_label_view_detail', 'Lihat Detail')} ${titleText}">
${t('grp_c4a_label_view_detail', 'Lihat Detail')} <i class="fas fa-arrow-right"></i> ${t('grp_c4a_label_view_detail', 'Lihat Detail')} <i class="fas fa-arrow-right"></i>
</button> </button>
</div> </div>
@@ -250,13 +266,18 @@ function buildSopModalContent(sop) {
const catLabel = getCatLabel(category); const catLabel = getCatLabel(category);
const catClass = CATEGORY_COLORS[category] || ''; const catClass = CATEGORY_COLORS[category] || '';
const reqsHTML = requirements.map(req => `<li>${req}</li>`).join(''); const titleText = loc(title);
const procsHTML = procedures.map(proc => `<li>${proc}</li>`).join(''); const descText = loc(description);
const purposeText = loc(purpose);
const additionalInfoText = loc(additionalInfo);
const reqsHTML = requirements.map(req => `<li>${loc(req)}</li>`).join('');
const procsHTML = procedures.map(proc => `<li>${loc(proc)}</li>`).join('');
// staffResponsible bersifat opsional — sembunyikan blok jika tidak ada // staffResponsible bersifat opsional — sembunyikan blok jika tidak ada
const hasStaff = Array.isArray(staffResponsible) && staffResponsible.length > 0; const hasStaff = Array.isArray(staffResponsible) && staffResponsible.length > 0;
const staffHTML = hasStaff const staffHTML = hasStaff
? staffResponsible.map(staffName => `<span class="sop-staff-pill">${staffName}</span>`).join('') ? staffResponsible.map(staffName => `<span class="sop-staff-pill">${loc(staffName)}</span>`).join('')
: ''; : '';
const staffBlockHTML = hasStaff const staffBlockHTML = hasStaff
? `<div class="sop-staff-block"> ? `<div class="sop-staff-block">
@@ -266,10 +287,10 @@ function buildSopModalContent(sop) {
: ''; : '';
// additionalInfo bersifat opsional — sembunyikan blok jika tidak ada // additionalInfo bersifat opsional — sembunyikan blok jika tidak ada
const additionalInfoHTML = additionalInfo const additionalInfoHTML = additionalInfoText
? `<div class="sop-info-box"> ? `<div class="sop-info-box">
<span class="iico">️</span> <span class="iico">️</span>
<p class="sop-info-box-text"><strong>${t('grp_c4a_label_additional_info', 'Informasi Tambahan (Bersifat Opsional):')}</strong> ${additionalInfo}</p> <p class="sop-info-box-text"><strong>${t('grp_c4a_label_additional_info', 'Informasi Tambahan (Bersifat Opsional):')}</strong> ${additionalInfoText}</p>
</div>` </div>`
: ''; : '';
@@ -283,15 +304,15 @@ function buildSopModalContent(sop) {
<div class="sop-modal-badges"> <div class="sop-modal-badges">
<span class="sgc-category ${catClass}">${catLabel}</span> <span class="sgc-category ${catClass}">${catLabel}</span>
</div> </div>
<h2 class="sop-modal-title" id="sop-modal-title">${title}</h2> <h2 class="sop-modal-title" id="sop-modal-title">${titleText}</h2>
<p class="sop-modal-desc">${description}</p> <p class="sop-modal-desc">${descText}</p>
</div> </div>
</div> </div>
</div> </div>
<div class="sop-modal-body"> <div class="sop-modal-body">
<div class="sop-block"> <div class="sop-block">
<div class="sop-block-label">${t('grp_c4a_label_purpose', 'Tujuan')}</div> <div class="sop-block-label">${t('grp_c4a_label_purpose', 'Tujuan')}</div>
<p class="sop-block-text">${purpose}</p> <p class="sop-block-text">${purposeText}</p>
</div> </div>
<div class="sop-two-col"> <div class="sop-two-col">
<div> <div>
@@ -319,15 +340,19 @@ export function renderSopCards(sops) {
// simpan data global di element agar bisa diakses filter/search // simpan data global di element agar bisa diakses filter/search
container._sopData = sops; container._sopData = sops;
const emptyState = document.getElementById('sop-empty-state');
// Tampilkan pesan jika data SOP kosong atau gagal dimuat // Tampilkan pesan jika data SOP kosong atau gagal dimuat
if (!sops || sops.length === 0) { if (!sops || sops.length === 0) {
container.innerHTML = `<p class="empty-state-msg">${t('grp_c4a_empty_sop', 'Data SOP tidak tersedia saat ini.')}</p>`; container.innerHTML = `<p class="empty-state-msg">${t('grp_c4a_empty_sop', 'Data SOP tidak tersedia saat ini.')}</p>`;
updateResultInfo(0, 0); updateResultInfo(0, 0);
if (emptyState) emptyState.style.display = 'none';
return; return;
} }
container.innerHTML = sops.map(buildSopCard).join(''); container.innerHTML = sops.map(buildSopCard).join('');
updateResultInfo(sops.length, sops.length); updateResultInfo(sops.length, sops.length);
if (emptyState) emptyState.style.display = 'none';
} }
/** Update teks info jumlah hasil */ /** Update teks info jumlah hasil */
@@ -371,7 +396,12 @@ export function applySopFilter() {
}); });
const emptyState = document.getElementById('sop-empty-state'); 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); updateResultInfo(visibleCount, cards.length);
} }
@@ -626,11 +656,11 @@ export function renderFaqSection(faqs) {
return ` return `
<div class="faq-item reveal ${delayClass}"> <div class="faq-item reveal ${delayClass}">
<div class="faq-question"> <div class="faq-question">
<span class="faq-question-text">${faq.question}</span> <span class="faq-question-text">${loc(faq.question)}</span>
<div class="faq-icon">+</div> <div class="faq-icon">+</div>
</div> </div>
<div class="faq-answer"> <div class="faq-answer">
<div class="faq-answer-inner">${faq.answer}</div> <div class="faq-answer-inner">${loc(faq.answer)}</div>
</div> </div>
</div>`; </div>`;
}).join(''); }).join('');