// ═══════════════════════════════════════════════════════════════════ // ESCALASI PAGE — Escalation pipeline and management // ═══════════════════════════════════════════════════════════════════ function renderEscalasiPage() { const escs = APP_STATE.escalations; const active = escs.filter(e => e.status !== 'resolved'); const resolved = escs.filter(e => e.status === 'resolved'); const levelCounts = { L1:0, L2:0, L3:0, L4:0 }; active.forEach(e => { if (levelCounts[e.level] !== undefined) levelCounts[e.level]++; }); document.getElementById('escalasi-body').innerHTML = `
Pipeline Eskalasi
Manajemen eskalasi berjenjang: Daerah → KSP → Kementerian → Penegakan Hukum
${['L1','L2','L3','L4'].map((lv, idx) => { const cfg = ESCALATION_LEVELS[lv]; const desc = { L1: 'Tim / Dinas Daerah', L2: 'KSP Internal', L3: 'Kementerian / Lembaga', L4: 'Kejaksaan / POLRI / BPK' }[lv]; return `
${levelCounts[lv] > 0 ? levelCounts[lv] : idx+1}
${cfg.label.replace(lv+' — ','')}
${desc}
`; }).join('')}
${active.length}
Eskalasi Aktif
${escs.filter(e=>e.status==='pending').length}
Menunggu Persetujuan
${escs.filter(e=>e.status==='approved').length}
Disetujui
${resolved.length}
Selesai
⚡ Eskalasi Aktif
${active.length === 0 ? `
Tidak ada eskalasi aktif
Semua eskalasi telah diselesaikan
` : active.map(e => renderEscCard(e, false)).join('') } ${resolved.length > 0 ? `
✅ Riwayat Eskalasi Selesai
${resolved.map(e => renderEscCard(e, true)).join('')} ` : ''}
`; } function renderEscCard(esc, isResolved) { const issue = APP_STATE.issues.find(i => i.id === esc.issueId); const lvCfg = ESCALATION_LEVELS[esc.level]; const statusMap = { pending: { label: 'Menunggu', color: 'var(--amber)', bg: 'var(--amber-soft)' }, approved: { label: 'Disetujui', color: 'var(--blue)', bg: 'var(--blue-soft)' }, rejected: { label: 'Ditolak', color: 'var(--red)', bg: 'var(--red-soft)' }, resolved: { label: 'Selesai', color: 'var(--green)', bg: 'var(--green-soft)' } }; const st = statusMap[esc.status] || statusMap.pending; return `
${esc.id} ${esc.level} ${st.label} ${getProgramBadge(esc.programId)}
${esc.levelName}
Ditujukan ke: ${esc.assignTo}
📅 ${formatDate(esc.createdAt)}
${esc.resolvedAt ? `
✅ ${formatDate(esc.resolvedAt)}
` : ''}
${issue ? `
ISSUE TERKAIT — ${esc.daerah}, ${esc.provinsi}
${issue.id}: ${issue.judul.slice(0,70)}${issue.judul.length>70?'...':''}
` : ''}
${esc.notes}
Dibuat oleh: ${esc.createdBy}
${!isResolved ? `
${esc.status === 'pending' ? ` ` : ''} ${esc.status === 'approved' ? ` ` : ''}
` : ''}
`; } function approveEscalation(id) { const e = APP_STATE.escalations.find(e => e.id === id); if (!e) return; e.status = 'approved'; showToast('Eskalasi Disetujui', `${id} telah disetujui dan diteruskan`, 'success'); renderEscalasiPage(); } function rejectEscalation(id) { const e = APP_STATE.escalations.find(e => e.id === id); if (!e) return; e.status = 'rejected'; showToast('Eskalasi Ditolak', `${id} ditolak`, 'warning'); renderEscalasiPage(); } function resolveEscalation(id) { const e = APP_STATE.escalations.find(e => e.id === id); if (!e) return; e.status = 'resolved'; e.resolvedAt = new Date().toISOString().split('T')[0]; showToast('Eskalasi Diselesaikan', `${id} berhasil diselesaikan`, 'success'); renderEscalasiPage(); updateIssuesBadge(); } function openNewEscalasiModal() { // Simple prompt-based creation const issueList = APP_STATE.issues .filter(i => i.status !== 'resolved') .map(i => `${i.id}: ${i.judul.slice(0,50)}`).join('\n'); const issueId = prompt(`Masukkan ID issue untuk dieskalasi:\n\nIssue aktif:\n${issueList}`); if (!issueId) return; const issue = APP_STATE.issues.find(i => i.id.toUpperCase() === issueId.toUpperCase().trim()); if (!issue) { showToast('Issue Tidak Ditemukan', `ID ${issueId} tidak ditemukan`, 'error'); return; } const levelInput = prompt('Pilih level eskalasi:\nL1 - Daerah\nL2 - KSP Internal\nL3 - Kementerian/Lembaga\nL4 - Penegakan Hukum', 'L2'); const level = (levelInput || 'L2').toUpperCase().trim(); if (!ESCALATION_LEVELS[level]) { showToast('Level Tidak Valid', 'Pilih L1, L2, L3, atau L4', 'error'); return; } const assignTo = prompt('Ditujukan kepada:', 'KSP Div. Pengawasan'); const notes = prompt('Catatan eskalasi:', `Eskalasi dari issue ${issue.id}`); const id = `ESC-${Date.now().toString().slice(-4)}`; const now = new Date().toISOString().split('T')[0]; const ts = new Date().toLocaleTimeString('id-ID') + ' WIB'; const newEsc = { id, issueId: issue.id, programId: issue.programId, level, levelName: ESCALATION_LEVELS[level].label, assignTo: assignTo || 'KSP Div. Pengawasan', notes: notes || `Eskalasi dari issue ${issue.id}`, status: 'pending', createdBy: 'Admin KSP', createdAt: now, resolvedAt: null, daerah: issue.daerah, provinsi: issue.provinsi }; APP_STATE.escalations.push(newEsc); issue.escalationIds.push(id); issue.timeline.push({ time: ts, action: `Eskalasi ${level} dibuat ke ${assignTo}`, actor: 'Admin KSP', type: 'escalated' }); issue.status = 'in_progress'; showToast('Eskalasi Dibuat', `${id} berhasil dibuat`, 'success'); renderEscalasiPage(); }