forked from izu/student-web-if-development-kit
fix(c4a): fix 'SOP tidak ditemukan' visibility logic on page load
This commit is contained in:
+51
-21
@@ -12,6 +12,20 @@ function t(key, 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...
|
||||
* @param {string} phone - Nomor telepon mentah
|
||||
@@ -100,12 +114,12 @@ export function renderStaffCards(staffs) {
|
||||
|
||||
const scheduleHTML = schedule.map(sched =>
|
||||
`<div class="schedule-item">` +
|
||||
`<span class="s-day">${sched.day}</span>` +
|
||||
`<span class="s-time">${sched.time} <span class="s-break">| ${sched.break}</span></span>` +
|
||||
`<span class="s-day">${loc(sched.day)}</span>` +
|
||||
`<span class="s-time">${loc(sched.time)} <span class="s-break">| ${loc(sched.break)}</span></span>` +
|
||||
`</div>`
|
||||
).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 encodedPhone = isPhoneValid ? encodePhone(phone) : '';
|
||||
const displayPhone = isPhoneValid ? formatPhoneForDisplay(phone) : '-';
|
||||
@@ -123,13 +137,13 @@ export function renderStaffCards(staffs) {
|
||||
<img src="${image}" alt="${name}" onerror="this.style.display='none'"/>
|
||||
</div>
|
||||
<div>
|
||||
<div class="staff-name">${name}</div>
|
||||
<div class="staff-role">${role}</div>
|
||||
<div class="staff-name">${loc(name)}</div>
|
||||
<div class="staff-role">${loc(role)}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="staff-card-body">
|
||||
<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">
|
||||
<span class="icon">🕒</span>
|
||||
<div style="flex:1">
|
||||
@@ -202,27 +216,29 @@ function buildSopCard(sop) {
|
||||
|
||||
const catLabel = getCatLabel(category);
|
||||
const catClass = CATEGORY_COLORS[category] || '';
|
||||
const titleText = loc(title);
|
||||
const descText = loc(description);
|
||||
|
||||
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-icon-wrap">
|
||||
<i class="fas ${icon}"></i>
|
||||
</div>
|
||||
<div class="sgc-meta">
|
||||
<h3 class="sgc-title">${title}</h3>
|
||||
<h3 class="sgc-title">${titleText}</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sgc-category-row">
|
||||
<span class="sgc-category ${catClass}">${catLabel}</span>
|
||||
</div>
|
||||
<p class="sgc-desc">${description}</p>
|
||||
<p class="sgc-desc">${descText}</p>
|
||||
<div class="sgc-footer">
|
||||
<div class="sgc-steps">
|
||||
<i class="fas fa-list-ol"></i>
|
||||
<span>${procedures.length} ${t('grp_c4a_label_steps', 'Langkah')}</span>
|
||||
</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>
|
||||
</button>
|
||||
</div>
|
||||
@@ -250,13 +266,18 @@ function buildSopModalContent(sop) {
|
||||
const catLabel = getCatLabel(category);
|
||||
const catClass = CATEGORY_COLORS[category] || '';
|
||||
|
||||
const reqsHTML = requirements.map(req => `<li>${req}</li>`).join('');
|
||||
const procsHTML = procedures.map(proc => `<li>${proc}</li>`).join('');
|
||||
const titleText = loc(title);
|
||||
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
|
||||
const hasStaff = Array.isArray(staffResponsible) && staffResponsible.length > 0;
|
||||
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
|
||||
? `<div class="sop-staff-block">
|
||||
@@ -266,10 +287,10 @@ function buildSopModalContent(sop) {
|
||||
: '';
|
||||
|
||||
// additionalInfo bersifat opsional — sembunyikan blok jika tidak ada
|
||||
const additionalInfoHTML = additionalInfo
|
||||
const additionalInfoHTML = additionalInfoText
|
||||
? `<div class="sop-info-box">
|
||||
<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>`
|
||||
: '';
|
||||
|
||||
@@ -283,15 +304,15 @@ function buildSopModalContent(sop) {
|
||||
<div class="sop-modal-badges">
|
||||
<span class="sgc-category ${catClass}">${catLabel}</span>
|
||||
</div>
|
||||
<h2 class="sop-modal-title" id="sop-modal-title">${title}</h2>
|
||||
<p class="sop-modal-desc">${description}</p>
|
||||
<h2 class="sop-modal-title" id="sop-modal-title">${titleText}</h2>
|
||||
<p class="sop-modal-desc">${descText}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sop-modal-body">
|
||||
<div class="sop-block">
|
||||
<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 class="sop-two-col">
|
||||
<div>
|
||||
@@ -319,15 +340,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 = `<p class="empty-state-msg">${t('grp_c4a_empty_sop', 'Data SOP tidak tersedia saat ini.')}</p>`;
|
||||
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 */
|
||||
@@ -371,7 +396,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);
|
||||
}
|
||||
@@ -626,11 +656,11 @@ export function renderFaqSection(faqs) {
|
||||
return `
|
||||
<div class="faq-item reveal ${delayClass}">
|
||||
<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>
|
||||
<div class="faq-answer">
|
||||
<div class="faq-answer-inner">${faq.answer}</div>
|
||||
<div class="faq-answer-inner">${loc(faq.answer)}</div>
|
||||
</div>
|
||||
</div>`;
|
||||
}).join('');
|
||||
|
||||
Reference in New Issue
Block a user