Files
2026-09-16 10:38:01 +07:00

260 lines
14 KiB
JavaScript

// ═══════════════════════════════════════════════════════════════════
// SURVEY PAGE — Lapangan survey management
// ═══════════════════════════════════════════════════════════════════
function renderSurveyPage() {
const search = (document.getElementById('survey-search')?.value || '').toLowerCase().trim();
const statusF = document.getElementById('survey-filter-status')?.value || 'all';
const programF = document.getElementById('survey-filter-program')?.value || 'all';
const filtered = APP_STATE.surveys.filter(s => {
const matchS = !search || s.namaOfficer.toLowerCase().includes(search) || s.daerah.toLowerCase().includes(search) || s.issueId.toLowerCase().includes(search) || s.temuanUtama.toLowerCase().includes(search);
const matchSt = statusF === 'all' || s.status === statusF;
const matchP = programF === 'all' || s.programId === programF;
return matchS && matchSt && matchP;
});
const stats = {
total: APP_STATE.surveys.length,
verified: APP_STATE.surveys.filter(s => s.status === 'verified').length,
submitted: APP_STATE.surveys.filter(s => s.status === 'submitted').length,
draft: APP_STATE.surveys.filter(s => s.status === 'draft').length
};
document.getElementById('survey-body').innerHTML = `
<!-- Stats Row -->
<div style="display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:16px;">
<div class="card card-p-sm" style="text-align:center;">
<div style="font-size:22px;font-weight:800;color:var(--text-1);margin-bottom:4px;">${stats.total}</div>
<div style="font-size:11px;color:var(--text-3);">Total Survey</div>
</div>
<div class="card card-p-sm" style="text-align:center;">
<div style="font-size:22px;font-weight:800;color:var(--green);margin-bottom:4px;">${stats.verified}</div>
<div style="font-size:11px;color:var(--text-3);">Diverifikasi</div>
</div>
<div class="card card-p-sm" style="text-align:center;">
<div style="font-size:22px;font-weight:800;color:var(--blue);margin-bottom:4px;">${stats.submitted}</div>
<div style="font-size:11px;color:var(--text-3);">Menunggu Verifikasi</div>
</div>
<div class="card card-p-sm" style="text-align:center;">
<div style="font-size:22px;font-weight:800;color:var(--text-3);margin-bottom:4px;">${stats.draft}</div>
<div style="font-size:11px;color:var(--text-3);">Draft</div>
</div>
</div>
<!-- Survey List -->
${filtered.length === 0
? `<div class="empty-state"><div class="empty-icon">📋</div><div class="empty-title">Tidak ada survey</div><div class="empty-desc">Tidak ada survey yang cocok dengan filter yang dipilih</div></div>`
: filtered.map(s => renderSurveyCard(s)).join('')
}
`;
}
function renderSurveyCard(survey) {
const issue = APP_STATE.issues.find(i => i.id === survey.issueId);
const prog = getProgramById(survey.programId);
const skorColors = ['','var(--red)','var(--orange)','var(--amber)','var(--green)','var(--blue)'];
const skorLabel = ['','Sangat Kritis','Kritis','Perlu Perhatian','Minor','Normal'];
return `
<div class="survey-card fade-in" onclick="openSurveyDetail('${survey.id}')">
<div class="sc-header">
<div>
<div style="display:flex;align-items:center;gap:8px;margin-bottom:4px;">
<span class="sc-id">${survey.id}</span>
${getProgramBadge(survey.programId)}
${issue ? getSevBadge(issue.severity) : ''}
</div>
<div class="sc-officer">${survey.namaOfficer}</div>
<div class="sc-jabatan">${survey.jabatan}</div>
</div>
<span class="status-${survey.status}">${{draft:'Draft',submitted:'Diajukan',verified:'Diverifikasi'}[survey.status]}</span>
</div>
<div class="divider" style="margin:8px 0;"></div>
<div style="display:flex;gap:16px;align-items:flex-start;">
<div style="flex:1;">
<div style="font-size:10px;font-weight:700;color:var(--text-3);text-transform:uppercase;letter-spacing:0.4px;margin-bottom:4px;">Temuan Utama</div>
<div class="sc-temuan">${survey.temuanUtama}</div>
</div>
</div>
${survey.rekomendasi ? `
<div style="background:rgba(245,158,11,0.08);border:1px solid rgba(245,158,11,0.2);border-radius:var(--r);padding:8px 10px;margin-top:8px;">
<div style="font-size:10px;font-weight:700;color:var(--amber);margin-bottom:3px;">💡 Rekomendasi</div>
<div style="font-size:11px;color:var(--text-2);line-height:1.5;">${survey.rekomendasi.slice(0,120)}${survey.rekomendasi.length > 120 ? '...' : ''}</div>
</div>
` : ''}
<div class="sc-footer mt-2">
<div class="sc-meta">
<span>📍 ${survey.daerah}, ${survey.provinsi}</span>
<span>·</span>
<span>📅 ${formatDate(survey.tanggalSurvey)}</span>
${survey.issueId ? `<span>·</span><span style="font-family:monospace;font-size:10px;">${survey.issueId}</span>` : ''}
</div>
<div style="display:flex;align-items:center;gap:6px;">
${survey.skorKeparahan ? `
<div style="display:flex;align-items:center;gap:4px;">
<div style="width:8px;height:8px;border-radius:50%;background:${skorColors[survey.skorKeparahan]};"></div>
<span style="font-size:10px;color:${skorColors[survey.skorKeparahan]};font-weight:600;">${skorLabel[survey.skorKeparahan]}</span>
</div>
` : ''}
${survey.verifiedBy ? `<span style="font-size:10px;color:var(--green);">✓ ${survey.verifiedBy}</span>` : ''}
</div>
</div>
</div>
`;
}
function openSurveyDetail(surveyId) {
const s = APP_STATE.surveys.find(sv => sv.id === surveyId);
if (!s) return;
const issue = APP_STATE.issues.find(i => i.id === s.issueId);
const prog = getProgramById(s.programId);
const skorColors = ['','var(--red)','var(--orange)','var(--amber)','var(--green)','var(--blue)'];
const skorLabel = ['','Sangat Kritis — Tindakan Segera','Kritis','Perlu Perhatian Khusus','Minor — Tetap Perlu Ditangani','Kondisi Normal'];
document.getElementById('sd-title').textContent = `Survey Lapangan — ${s.id}`;
document.getElementById('sd-body').innerHTML = `
<div class="flex gap-3 items-center mb-4" style="flex-wrap:wrap;">
${getProgramBadge(s.programId)}
<span class="status-${s.status}">${{draft:'Draft',submitted:'Diajukan',verified:'Diverifikasi'}[s.status]}</span>
${issue ? getSevBadge(issue.severity) : ''}
</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px;">
<div>
<div style="font-size:10px;color:var(--text-3);margin-bottom:4px;">OFFICER SURVEI</div>
<div style="font-size:14px;font-weight:700;color:var(--text-1);">${s.namaOfficer}</div>
<div style="font-size:12px;color:var(--text-3);">${s.jabatan}</div>
</div>
<div>
<div style="font-size:10px;color:var(--text-3);margin-bottom:4px;">DETAIL SURVEI</div>
<div style="font-size:12px;color:var(--text-2);">📅 ${formatDate(s.tanggalSurvey)}</div>
<div style="font-size:12px;color:var(--text-2);">📍 ${s.daerah}, ${s.provinsi}</div>
</div>
</div>
${issue ? `
<div class="card card-p-sm mb-3" style="background:var(--bg);cursor:pointer;" onclick="closeModal('survey-detail-modal');openIssueDetail('${issue.id}')">
<div style="font-size:10px;color:var(--text-3);margin-bottom:4px;">ISSUE TERKAIT</div>
<div style="font-size:12px;font-weight:600;color:var(--text-1);">${issue.id}${issue.judul.slice(0,60)}${issue.judul.length>60?'...':''}</div>
<div style="font-size:11px;color:var(--blue);margin-top:4px;">Klik untuk lihat detail issue →</div>
</div>
` : ''}
<div class="card card-p mb-3" style="background:var(--bg);">
<div style="font-size:11px;font-weight:700;color:var(--text-3);text-transform:uppercase;letter-spacing:0.5px;margin-bottom:8px;">📋 Temuan Utama</div>
<div style="font-size:13px;color:var(--text-1);line-height:1.7;">${s.temuanUtama}</div>
</div>
${s.rekomendasi ? `
<div class="card card-p mb-3" style="background:rgba(245,158,11,0.05);border-color:rgba(245,158,11,0.2);">
<div style="font-size:11px;font-weight:700;color:var(--amber);text-transform:uppercase;letter-spacing:0.5px;margin-bottom:8px;">💡 Rekomendasi Tindak Lanjut</div>
<div style="font-size:13px;color:var(--text-2);line-height:1.7;">${s.rekomendasi}</div>
</div>
` : ''}
${s.skorKeparahan ? `
<div class="card card-p mb-3" style="background:var(--bg);border-color:${skorColors[s.skorKeparahan]}33;">
<div style="font-size:11px;font-weight:700;color:var(--text-3);text-transform:uppercase;letter-spacing:0.5px;margin-bottom:8px;">Penilaian Keparahan</div>
<div style="display:flex;align-items:center;gap:10px;">
<div style="width:40px;height:40px;border-radius:50%;background:${skorColors[s.skorKeparahan]}22;border:2px solid ${skorColors[s.skorKeparahan]};display:flex;align-items:center;justify-content:center;font-size:18px;font-weight:800;color:${skorColors[s.skorKeparahan]};">${s.skorKeparahan}</div>
<div>
<div style="font-size:13px;font-weight:600;color:${skorColors[s.skorKeparahan]};">${skorLabel[s.skorKeparahan]}</div>
<div style="font-size:11px;color:var(--text-3);">Skala 1 (paling parah) — 5 (normal)</div>
</div>
</div>
</div>
` : ''}
${s.verifiedBy ? `
<div style="display:flex;align-items:center;gap:8px;padding:10px;border-radius:var(--r);background:var(--green-soft);border:1px solid rgba(34,197,94,0.2);">
<span style="font-size:16px;">✅</span>
<div>
<div style="font-size:12px;font-weight:600;color:var(--green);">Diverifikasi oleh ${s.verifiedBy}</div>
<div style="font-size:11px;color:var(--text-3);">Survey ini telah divalidasi dan dapat dijadikan dasar tindak lanjut</div>
</div>
</div>
` : `
<div style="display:flex;align-items:center;gap:8px;padding:10px;border-radius:var(--r);background:var(--amber-soft);border:1px solid rgba(245,158,11,0.2);">
<span style="font-size:16px;">⏳</span>
<div>
<div style="font-size:12px;font-weight:600;color:var(--amber);">Menunggu Verifikasi</div>
<div style="font-size:11px;color:var(--text-3);">Survey belum diverifikasi oleh atasan</div>
</div>
<button class="btn btn-success btn-sm" onclick="verifySurvey('${s.id}')">Verifikasi</button>
</div>
`}
`;
openModal('survey-detail-modal');
}
function verifySurvey(surveyId) {
const s = APP_STATE.surveys.find(sv => sv.id === surveyId);
if (!s) return;
s.status = 'verified';
s.verifiedBy = 'Admin KSP';
showToast('Survey Diverifikasi', `${surveyId} berhasil diverifikasi`, 'success');
closeModal('survey-detail-modal');
renderSurveyPage();
}
// ─── NEW SURVEY MODAL ─────────────────────────────────────────────
function openNewSurveyModal(prefillIssueId) {
// Populate issue select
const issueSelect = document.getElementById('ns-issue');
const openIssues = APP_STATE.issues.filter(i => i.status !== 'resolved' && i.status !== 'closed');
issueSelect.innerHTML = '<option value="">Pilih Issue Terkait</option>' +
openIssues.map(i => `<option value="${i.id}" ${i.id === prefillIssueId ? 'selected' : ''}>${i.id}${i.judul.slice(0,40)}...</option>`).join('');
// Set today's date
const today = new Date().toISOString().split('T')[0];
document.getElementById('ns-tanggal').value = today;
if (prefillIssueId) {
const issue = APP_STATE.issues.find(i => i.id === prefillIssueId);
if (issue) {
document.getElementById('ns-program').value = issue.programId;
document.getElementById('ns-daerah').value = issue.daerah;
}
}
openModal('new-survey-modal');
}
function submitNewSurvey(e) {
e.preventDefault();
const issueId = document.getElementById('ns-issue').value;
const issue = APP_STATE.issues.find(i => i.id === issueId);
const id = `SRV-${String(APP_STATE.surveys.length + 1).padStart(3,'0')}`;
const now = new Date().toISOString().split('T')[0];
const ts = new Date().toLocaleTimeString('id-ID') + ' WIB';
const newSurvey = {
id, issueId: issueId || null,
programId: document.getElementById('ns-program').value,
namaOfficer: document.getElementById('ns-officer').value,
jabatan: document.getElementById('ns-jabatan').value,
tanggalSurvey:document.getElementById('ns-tanggal').value,
daerah: document.getElementById('ns-daerah').value,
provinsi: issue?.provinsi || '',
status: 'submitted',
temuanUtama: document.getElementById('ns-temuan').value,
rekomendasi: document.getElementById('ns-rekomendasi').value,
skorKeparahan: null, verifiedBy: null, createdAt: now
};
APP_STATE.surveys.push(newSurvey);
// Update issue if linked
if (issue && !issue.surveyIds.includes(id)) {
issue.surveyIds.push(id);
issue.timeline.push({ time: ts, action: `Survey lapangan dibuat oleh ${newSurvey.namaOfficer}`, actor: newSurvey.namaOfficer, type: 'survey' });
issue.status = 'in_progress';
}
document.getElementById('new-survey-form').reset();
closeModal('new-survey-modal');
updateIssuesBadge();
if (APP_STATE.currentPage === 'survey') renderSurveyPage();
showToast('Survey Dibuat', `${id} berhasil diajukan`, 'success');
}