import React, { useState, useEffect } from 'react'; import { School, ShieldCheck, Upload, FileText, CheckCircle2, AlertTriangle, MessageSquare, Bell, History, Send, Check, X, FileCheck, HelpCircle, Sparkles, Download, ArrowRight, Info, ChevronRight, RefreshCw, Search, BookOpen, FileSignature, Percent, CheckSquare, Award, UserCheck } from 'lucide-react'; // Data awal sekolah dampingan Inspektorat Provinsi NTB (Wilayah Lombok & Sumbawa) const INITIAL_SCHOOLS = [ { id: 1, npsn: "50201234", name: "SMA Negeri 1 Mataram", status: "Konsultasi Aktif", // Aman, Konsultasi Aktif, Butuh Pendampingan lastUpdate: "18 Juni 2026", budget: 450000000, consultedBudget: 315000000, address: "Jl. Pendidikan No. 21, Kota Mataram, Lombok", headmaster: "Drs. H. Lalu Muhammad, M.Pd", treasurer: "Baiq Rahmawati, S.E", complianceScore: 75, isReportSubmitted: false, signatureName: "", isSigned: false }, { id: 2, npsn: "50205678", name: "SMA Negeri 2 Sumbawa Besar", status: "Butuh Pendampingan", lastUpdate: "15 Juni 2026", budget: 520000000, consultedBudget: 120000000, address: "Jl. Garuda No. 12, Sumbawa Besar, Sumbawa", headmaster: "Dr. I Ketut Budi, M.Si", treasurer: "Rian Hidayat, A.Md", complianceScore: 25, isReportSubmitted: false, signatureName: "", isSigned: false }, { id: 3, npsn: "50209101", name: "SMA Swasta Harapan Lombok Barat", status: "Aman", lastUpdate: "18 Juni 2026", budget: 300000000, consultedBudget: 300000000, address: "Jl. Raya Senggigi, Lombok Barat", headmaster: "Elisa Anastasia, M.Hum", treasurer: "Dewi Lestari", complianceScore: 100, isReportSubmitted: true, signatureName: "Elisa Anastasia, M.Hum", isSigned: true } ]; // Data rancangan rencana belanja yang dikonsultasikan (Terdistribusi per Sekolah) const INITIAL_PROPOSED_ITEMS = [ { id: "PROP-101", schoolId: 1, activity: "Penyediaan Paket Internet Belajar Siswa Kurang Mampu", plannedCost: 15000000, consultationStatus: "Disetujui APIP", notes: "Sesuai dengan Juknis BOS terkait operasional digital daerah NTB. Pastikan daftar penerima dibuat terperinci." }, { id: "PROP-102", schoolId: 1, activity: "Rehab Sedang Sanitasi Toilet Siswa SMA Mataram", plannedCost: 45000000, consultationStatus: "Perbaikan Draft", notes: "Mohon lampirkan rincian volume bahan bangunan lokal NTB dan foto kondisi awal sanitasi toilet." }, { id: "PROP-103", schoolId: 1, activity: "Pengadaan Buku Referensi Adat Sasak Samawa Mbojo (SASAMBO)", plannedCost: 20000000, consultationStatus: "Draf Diajukan", notes: "Menunggu penelaahan dari Konsultan Inspektorat NTB." }, { id: "PROP-201", schoolId: 2, activity: "Sewa Bus Pariwisata Studi Banding Guru ke Mataram", plannedCost: 35000000, consultationStatus: "Perbaikan Draft", notes: "Pariwisata murni/studi banding guru tidak masuk dalam prioritas komponen Juknis BOS reguler. Harap tinjau kembali usulan Anda." }, { id: "PROP-301", schoolId: 3, activity: "Langganan Aplikasi Pembelajaran Digital Interaktif", plannedCost: 40000000, consultationStatus: "Sesuai Juknis (Advisory Issued)", notes: "Disetujui. Advisory Note resmi No. ADV/BOS-NTB/2026/089 telah diterbitkan." } ]; // Draft Bukti Transaksi (Kwitansi) sebelum transaksi riil dieksekusi const INITIAL_DRAFT_SPJ = [ { id: "CONS-501", schoolId: 1, proposedCode: "PROP-101", description: "Rencana Kuitansi Pembelian Paket Kuota Seluler - Provider Indolink Mataram", amount: 15000000, date: "14 Mei 2026", file: "Draft_Kwitansi_Internet.pdf", hasAdvice: true, adviceText: "Draf kwitansi sudah sah secara format perpajakan NTB. Lampirkan lembar penerima manfaat digital saat penutupan.", status: "Sesuai" }, { id: "CONS-502", schoolId: 1, proposedCode: "PROP-102", description: "Rencana Nota Pembelian Semen & Keramik - Toko Bangunan Mataram Jaya", amount: 28000000, date: "18 Juni 2026", file: "Draft_Nota_Sanitasi.pdf", hasAdvice: true, adviceText: "Nominal pengadaan di atas 10 juta disarankan melampirkan perbandingan minimal 2 e-commerce atau toko bangunan lokal terdekat di Lombok.", status: "Butuh Pendampingan" }, { id: "CONS-601", schoolId: 2, proposedCode: "PROP-201", description: "Draf Kontrak Penyewaan Bus Pariwisata Sumbawa - PO Lancar Jaya", amount: 35000000, date: "10 Juni 2026", file: "Draf_Sewa_Bus.pdf", hasAdvice: true, adviceText: "Sewa transportasi non-operasional harian sekolah dilarang keras dalam petunjuk penggunaan dana BOS reguler.", status: "Butuh Pendampingan" } ]; // Riwayat Chat Konsultasi Interaktif const INITIAL_CHATS = [ { schoolId: 1, sender: "Sekolah", time: "18 Juni 2026, 10:15", message: "Selamat pagi Pak Auditor Inspektorat NTB, kami berencana melakukan rehabilitasi toilet sekolah senilai 45 juta di SMAN 1 Mataram. Apakah draf rancangan belanja kami sudah aman secara Juknis?" }, { schoolId: 1, sender: "Konsultan APIP", time: "18 Juni 2026, 11:30", message: "Selamat pagi. Secara prinsip diperbolehkan selama masuk kategori pemeliharaan ringan/sedang. Silakan unggah draf rincian komponen materialnya di Menu Klinik SPJ agar kami teliti terlebih dahulu nilai wajarnya." }, { schoolId: 2, sender: "Sekolah", time: "15 Juni 2026, 09:00", message: "Mohon bimbingan terkait usulan sewa bus kami yang diberi status Perlu Perbaikan di Sumbawa." }, { schoolId: 2, sender: "Konsultan APIP", time: "15 Juni 2026, 14:20", message: "Sewa bus pariwisata tidak memiliki landasan hukum di Juknis BOS reguler. Kami sarankan mengalihkan anggaran ini ke penyediaan buku penunjang digital bermuatan lokal NTB (SASAMBO) atau pelatihan guru berbasis modul lokal." } ]; // Kuesioner Kepatuhan Sekolah const INITIAL_COMPLIANCE_ANSWERS = { 1: { q1: true, q2: true, q3: false, q4: true }, 2: { q1: false, q2: false, q3: false, q4: true }, 3: { q1: true, q2: true, q3: true, q4: true } }; export default function App() { const [role, setRole] = useState('sekolah'); // 'sekolah' | 'auditor' const [schools, setSchools] = useState(INITIAL_SCHOOLS); const [proposedItems, setProposedItems] = useState(INITIAL_PROPOSED_ITEMS); const [draftSpjList, setDraftSpjList] = useState(INITIAL_DRAFT_SPJ); const [chats, setChats] = useState(INITIAL_CHATS); const [complianceAnswers, setComplianceAnswers] = useState(INITIAL_COMPLIANCE_ANSWERS); // ID Sekolah Aktif yang dikonsultasikan / ditelaah const [selectedSchoolId, setSelectedSchoolId] = useState(1); // Status Langkah Internal Masing-masing Panel const [schoolStep, setSchoolStep] = useState(1); // 1: Klinik Perencanaan, 2: Klinik SPJ, 3: Chat Bimbingan & Advisory const [auditorStep, setAuditorStep] = useState(1); // 1: Peta Pendampingan, 2: Telaah Kwitansi, 3: Otorisasi Advisory const [activeSpjTab, setActiveSpjTab] = useState('list'); // 'list' | 'add' const [searchQuery, setSearchQuery] = useState(''); const [filterStatus, setFilterStatus] = useState('Semua'); // Form Input Rencana Anggaran Baru (Sekolah) const [newActivity, setNewActivity] = useState(''); const [newCost, setNewCost] = useState(''); // Form Input Telaah Transaksi Baru (Sekolah) const [newDraftDesc, setNewDraftDesc] = useState(''); const [newDraftAmount, setNewDraftAmount] = useState(''); const [newDraftTarget, setNewDraftTarget] = useState(''); const [newDraftFile, setNewDraftFile] = useState(null); // Custom Modal State untuk Auditor (Coaching Note) const [isCoachingModalOpen, setIsCoachingModalOpen] = useState(false); const [coachingTargetId, setCoachingTargetId] = useState(null); const [coachingText, setCoachingText] = useState(''); const [coachingStatusValue, setCoachingStatusValue] = useState(true); // true = Sesuai, false = Butuh Pendampingan // Form Advisory Note Baru (APIP) const [advisoryText, setAdvisoryText] = useState(''); const [isAdvisoryModalOpen, setIsAdvisoryModalOpen] = useState(false); const [selectedDraftId, setSelectedDraftId] = useState(null); // States Komunikasi const [chatMessage, setChatMessage] = useState(''); const [notifications, setNotifications] = useState([ { id: 1, schoolId: 1, type: "info", message: "Auditor Pendamping NTB memberikan saran perbaikan pada draf belanja Sanitasi.", date: "18 Juni 2026", read: false }, { id: 2, schoolId: 3, type: "success", message: "Advisory Note resmi e-Review untuk Kegiatan Pembelajaran Digital telah diterbitkan.", date: "17 Juni 2026", read: true } ]); const [consultingLogs, setConsultingLogs] = useState([ { id: 1, schoolId: 1, time: "18 Juni 2026, 11:30 WIB", user: "Konsultan APIP", action: "Menambahkan bimbingan preventif pada draf belanja Sanitasi" }, { id: 2, schoolId: 1, time: "18 Juni 2026, 10:15 WIB", user: "Bendahara BOS", action: "Mengirimkan draf perencanaan internet siswa untuk penelaahan awal" } ]); // States untuk Chatbot AI Juknis BOS (Gemini API) const [aiInput, setAiInput] = useState(''); const [aiChat, setAiChat] = useState([ { role: 'assistant', text: 'Halo! Saya Asisten AI Resmi e-Review Inspektorat NTB. Saya siap membantu menjawab pertanyaan preventif seputar regulasi Juknis BOS di lingkungan Provinsi Nusa Tenggara Barat. Silakan tanyakan hal-hal terkait kegiatan pengawasan BOS NTB!' } ]); const [isAiLoading, setIsAiLoading] = useState(false); const [toast, setToast] = useState(null); // Ambil data sekolah yang aktif saat ini const activeSchool = schools.find(s => s.id === selectedSchoolId) || schools[0]; // Set default draft target dropdown saat komponen di-load / sekolah diganti useEffect(() => { const schoolProposals = proposedItems.filter(p => p.schoolId === selectedSchoolId); if (schoolProposals.length > 0) { setNewDraftTarget(schoolProposals[0].id); } else { setNewDraftTarget(''); } }, [selectedSchoolId, proposedItems]); const showToast = (message, type = 'success') => { setToast({ message, type }); setTimeout(() => { setToast(null); }, 4000); }; const handleAskAi = async (e) => { e.preventDefault(); if (!aiInput.trim()) return; const userMessage = aiInput; setAiChat((prev) => [...prev, { role: 'user', text: userMessage }]); setAiInput(''); setIsAiLoading(true); const systemPrompt = ` Anda adalah "e-Review Smart Advisor", asisten konsultasi kecerdasan buatan resmi dari Inspektorat Provinsi Nusa Tenggara Barat (NTB). ATURAN SANGAT KETAT / WAJIB DIPATUHI: 1. Anda HANYA boleh menjawab pertanyaan yang berkaitan dengan kegiatan pengawasan, konsultasi preventif Dana BOS/BOSP, regulasi Juknis BOS, serta hal-hal substantif terkait program kerja di bawah naungan Inspektorat Provinsi Nusa Tenggara Barat (NTB) pada jenjang pendidikan menengah (SMA/SMK/SLB) di wilayah Lombok dan Sumbawa. 2. Jika pengguna menanyakan pertanyaan di luar konteks tersebut (misalnya tentang resep makanan, tips cinta, ilmu pemrograman umum, berita hiburan, matematika non-sekolah, atau daerah di luar NTB seperti Jakarta, Jawa, dll.), Anda HARUS menolaknya secara halus namun tegas. 3. Contoh kalimat penolakan wajib: "Mohon maaf, sebagai Asisten AI Resmi e-Review Inspektorat NTB, saya hanya berwenang melayani konsultasi preventif seputar Dana BOS/BOSP dan program pengawasan di lingkungan Provinsi Nusa Tenggara Barat. Silakan ajukan pertanyaan yang relevan." 4. Jika pertanyaan di dalam konteks, jawablah secara suportif dan berlandaskan aturan hukum nasional Indonesia & peraturan Gubernur NTB yang relevan. Berikan solusi jalan keluar alternatif yang aman apabila hal yang mereka tanyakan dilarang dalam Juknis BOS. `; try { const apiKey = ""; // Canvas menyuntikkan API Key secara otomatis const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-09-2025:generateContent?key=${apiKey}`; const payload = { contents: [ { role: 'user', parts: [{ text: userMessage }] } ], systemInstruction: { parts: [{ text: systemPrompt }] } }; const response = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); const result = await response.json(); const answer = result?.candidates?.[0]?.content?.parts?.[0]?.text || "Mohon maaf, saya sedang mengalami kendala jaringan pendampingan di server Inspektorat NTB. Silakan coba ajukan pertanyaan Anda kembali."; setAiChat((prev) => [...prev, { role: 'assistant', text: answer }]); } catch (err) { console.error(err); setAiChat((prev) => [...prev, { role: 'assistant', text: "Terjadi kesalahan koneksi ke server e-Review Inspektorat NTB. Namun secara umum, harap pastikan belanja Anda tertera dalam rencana kerja sekolah dan didukung kwitansi serta nota yang sah." }]); } finally { setIsAiLoading(false); } }; const handleAddProposedItem = (e) => { e.preventDefault(); if (!newActivity || !newCost) { showToast("Mohon isi kegiatan dan estimasi anggaran", "error"); return; } const newItem = { id: `PROP-${Math.floor(400 + Math.random() * 90)}`, schoolId: selectedSchoolId, activity: newActivity, plannedCost: parseInt(newCost), consultationStatus: "Draf Diajukan", notes: "Menunggu penelaahan awal oleh Konsultan APIP NTB" }; setProposedItems([...proposedItems, newItem]); addLog(`Mengajukan draf anggaran baru: "${newActivity}" senilai Rp ${parseInt(newCost).toLocaleString()}`); showToast("Draf berhasil diajukan! Auditor pendamping NTB Anda telah menerima notifikasi.", "success"); setNewActivity(''); setNewCost(''); }; const handleAddDraftSpj = (e) => { e.preventDefault(); if (!newDraftDesc || !newDraftAmount) { showToast("Mohon isi semua data deskripsi draf belanja", "error"); return; } const newDraft = { id: `CONS-${Math.floor(700 + Math.random() * 90)}`, schoolId: selectedSchoolId, proposedCode: newDraftTarget, description: newDraftDesc, amount: parseInt(newDraftAmount), date: new Date().toLocaleDateString('id-ID', { day: 'numeric', month: 'long', year: 'numeric' }), file: newDraftFile ? newDraftFile.name : "Draf_Kwitansi_Belanja.pdf", hasAdvice: false, adviceText: "", status: "Diproses" }; setDraftSpjList([...draftSpjList, newDraft]); addLog(`Mengajukan draf kwitansi: "${newDraftDesc}" sebesar Rp ${parseInt(newDraftAmount).toLocaleString()}`); showToast("Berkas draf transaksi terkirim! Konsultan APIP NTB kini dapat langsung mengulasnya.", "success"); setNewDraftDesc(''); setNewDraftAmount(''); setNewDraftFile(null); setActiveSpjTab('list'); }; const handleSendChat = (e, senderLabel) => { e.preventDefault(); if (!chatMessage.trim()) return; const newChat = { schoolId: selectedSchoolId, sender: senderLabel, time: "Hari ini, Baru saja", message: chatMessage }; setChats([...chats, newChat]); addLog(`Mengirim pesan bimbingan: "${chatMessage.substring(0, 30)}..."`); setChatMessage(''); showToast("Pesan bimbingan terkirim!", "success"); }; const handleToggleQuestion = (qKey) => { const currentSchoolAnswers = complianceAnswers[selectedSchoolId] || { q1: false, q2: false, q3: false, q4: false }; const updatedAnswers = { ...currentSchoolAnswers, [qKey]: !currentSchoolAnswers[qKey] }; let trueCount = 0; if (updatedAnswers.q1) trueCount++; if (updatedAnswers.q2) trueCount++; if (updatedAnswers.q3) trueCount++; if (updatedAnswers.q4) trueCount++; const newScore = trueCount * 25; setComplianceAnswers({ ...complianceAnswers, [selectedSchoolId]: updatedAnswers }); setSchools(schools.map(sch => { if (sch.id === selectedSchoolId) { return { ...sch, complianceScore: newScore, status: newScore >= 75 ? "Aman" : newScore >= 50 ? "Konsultasi Aktif" : "Butuh Pendampingan" }; } return sch; })); showToast("Jawaban disimpan! Kepatuhan internal sekolah diperbarui.", "info"); }; const handleSignAndSubmit = (e) => { e.preventDefault(); const signatureInput = activeSchool.signatureName; if (!signatureInput || !signatureInput.trim()) { showToast("Mohon ketik nama lengkap Kepala Sekolah sebagai tanda tangan virtual.", "error"); return; } setSchools(schools.map(sch => { if (sch.id === selectedSchoolId) { return { ...sch, isSigned: true, isReportSubmitted: true }; } return sch; })); addLog(`Kepala Sekolah (${signatureInput}) menandatangani draf laporan kepatuhan secara digital.`); showToast("Laporan Berkala & Deklarasi Kepatuhan telah resmi terkirim ke e-Review APIP NTB!", "success"); }; const handleApplyCoaching = (e) => { e.preventDefault(); if (!coachingText.trim()) { showToast("Mohon tuliskan catatan bimbingan atau rekomendasi perbaikan.", "error"); return; } setDraftSpjList(draftSpjList.map(item => { if (item.id === coachingTargetId) { return { ...item, hasAdvice: true, adviceText: coachingText, status: coachingStatusValue ? "Sesuai" : "Butuh Pendampingan" }; } return item; })); addLog(`[Auditor NTB] Menambahkan bimbingan preventif pada draf ${coachingTargetId}`); setNotifications([ { id: Date.now(), schoolId: selectedSchoolId, type: coachingStatusValue ? "success" : "warning", message: `Inspektorat NTB memperbarui status draf ${coachingTargetId}.`, date: "Baru saja", read: false }, ...notifications ]); setIsCoachingModalOpen(false); setCoachingText(''); showToast("Rekomendasi preventif (Coaching Note) berhasil dikirimkan!", "success"); }; const handlePublishAdvisoryNote = (e) => { e.preventDefault(); if (!advisoryText.trim()) { showToast("Mohon tuliskan pokok saran rekomendasi", "error"); return; } setProposedItems(proposedItems.map(item => { if (item.id === selectedDraftId) { return { ...item, consultationStatus: "Sesuai Juknis (Advisory Issued)", notes: `Rekomendasi Resmi APIP NTB: "${advisoryText}"` }; } return item; })); addLog(`[APIP NTB] Menerbitkan Advisory Note Resmi untuk program ${selectedDraftId}`); setIsAdvisoryModalOpen(false); setAdvisoryText(''); showToast("Advisory Note Resmi diterbitkan! Lembar rekomendasi PDF siap diunduh sekolah.", "success"); }; const addLog = (action) => { const newLog = { id: Date.now(), schoolId: selectedSchoolId, time: new Date().toLocaleTimeString('id-ID', { hour: '2-digit', minute: '2-digit' }) + " WITA, Hari ini", user: role === 'sekolah' ? 'Sekolah' : 'Auditor APIP NTB', action }; setConsultingLogs([newLog, ...consultingLogs]); }; const filteredSchools = schools.filter(sch => { const matchesSearch = sch.name.toLowerCase().includes(searchQuery.toLowerCase()) || sch.npsn.includes(searchQuery); const matchesStatus = filterStatus === 'Semua' || sch.status === filterStatus; return matchesSearch && matchesStatus; }); return (
{/* HEADER UTAMA */}

e-Review Inspektorat NTB Lombok & Sumbawa

Sistem Pendampingan & Pre-Review Anggaran BOS Provinsi Nusa Tenggara Barat

{/* ACTOR SWITCHER (Tampilan 1-per-1) */}
{/* TOAST NOTIFIKASI */} {toast && (
{toast.type === 'success' && } {toast.type === 'warning' && } {toast.type === 'info' && } {toast.message}
)} {/* WORKSPACE AREA */}
{/* RUNNING BANNER UNTUK MEMBERI INSTRUKSI INTERAKSI LIVE */}
Provinsi NTB

Aplikasi ini berfokus pada e-Review Pre-Review Dokumen secara preventif. Anda melihat dashboard: {role === 'sekolah' ? 'Sekolah Binaan NTB' : 'APIP Inspektorat NTB'}.

{/* ======================================================== PORTAL SEKOLAH (SMA/SMK DI NTB) ======================================================== */} {role === 'sekolah' && (
{/* Main Area: 3 Steps of e-Review */}
{/* SELECTOR SEKOLAH AKTIF */}
🏫

Portal e-Review Sekolah

Ulas rencana belanja Anda bersama tim pendamping Inspektorat NTB

{/* LANGKAH-LANGKAH PREVENTIF SEKOLAH */}
{/* INFORMASI DETAIL SEKOLAH BINAAN */}
Identitas Sekolah: {activeSchool.name} NPSN: {activeSchool.npsn} • {activeSchool.address}
Status Bimbingan NTB: {activeSchool.status}
{/* TAHAP 1 SEKOLAH: KLINIK PERENCANAAN */} {schoolStep === 1 && (
💡
Klinik Perencanaan Preventif NTB: Sebelum rancangan program draf sekolah diajukan secara resmi, unggah rencana belanja Anda di bawah ini agar mendapatkan analisis kesesuaian dari tim auditor Inspektorat Provinsi NTB.

Ajukan Rencana Belanja / Kegiatan Baru

setNewActivity(e.target.value)} className="w-full bg-white border border-slate-200 rounded-xl px-3.5 py-2.5 text-xs focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500 focus:outline-none transition-all font-semibold" />
setNewCost(e.target.value)} className="w-full bg-white border border-slate-200 rounded-xl px-3.5 py-2.5 text-xs focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500 focus:outline-none transition-all font-semibold" />
{/* DAFTAR DRAF KEGIATAN YANG SEDANG DIKONSULTASIKAN */}

Riwayat Konsultasi Rencana Belanja

{proposedItems.filter(p => p.schoolId === selectedSchoolId).length === 0 ? (

Belum ada usulan program yang didaftarkan. Gunakan form di atas untuk berkonsultasi.

) : ( proposedItems.filter(p => p.schoolId === selectedSchoolId).map((item) => (
{item.id} {item.consultationStatus}

{item.activity}

💡 Saran Preventif APIP NTB: {item.notes}

Rencana Belanja: Rp {item.plannedCost.toLocaleString()}
)) )}
)} {/* TAHAP 2 SEKOLAH: KLINIK SPJ & KEPATUHAN */} {schoolStep === 2 && (
{/* KEPATUHAN MANDIRI */}

Kuesioner Kepatuhan Mandiri (Self-Assessment NTB)

{activeSchool.complianceScore}% Tertib

Evaluasi tingkat administrasi sekolah Anda secara teratur terhadap aturan Juknis BOS Nasional dan Petunjuk Teknis Daerah NTB.

{/* KLINIK DRAFT SPJ */}
{activeSpjTab === 'list' ? (
{draftSpjList.filter(d => d.schoolId === selectedSchoolId).length === 0 ? (

Belum ada draf kwitansi yang diulas.

) : ( draftSpjList.filter(d => d.schoolId === selectedSchoolId).map((draft) => (
{draft.id} Pagu: {draft.proposedCode}
{draft.status}

{draft.description}

File Draft SPJ: {draft.file}

{draft.hasAdvice && (
📑 Saran / Hasil Pre-Review APIP NTB:

"{draft.adviceText}"

)}
Estimasi Pengeluaran: Rp {draft.amount.toLocaleString()}
)) )}
) : (

Ajukan Draft Nota/Kwitansi untuk Pre-Review

setNewDraftAmount(e.target.value)} className="w-full bg-slate-50 border border-slate-200 rounded-xl px-3.5 py-2.5 text-xs focus:ring-1 focus:ring-indigo-500 focus:outline-none font-semibold" />
setNewDraftDesc(e.target.value)} className="w-full bg-slate-50 border border-slate-200 rounded-xl px-3.5 py-2.5 text-xs focus:ring-1 focus:ring-indigo-500 focus:outline-none font-semibold" />
setNewDraftFile(e.target.files[0])} className="absolute inset-0 opacity-0 cursor-pointer" />
{newDraftFile ? newDraftFile.name : "Pilih file rancangan dokumen"} Format PDF / Gambar Maks. 10MB
)}
{/* DIGITAL SIGNATURE KEPALA SEKOLAH */}

Deklarasi & Persetujuan Kepala Sekolah

Sebelum draf diverifikasi secara formal oleh Inspektorat Provinsi NTB, Kepala Sekolah wajib menyetujui pernyataan mandiri kepatuhan ini secara virtual.

{activeSchool.isReportSubmitted ? (

Laporan Kepatuhan Mandiri Terkirim

Tanda Tangan Digital Sah: {activeSchool.signatureName || activeSchool.headmaster}

) : (
{ setSchools(schools.map(s => s.id === selectedSchoolId ? { ...s, signatureName: e.target.value } : s)); }} className="w-full bg-white border border-slate-200 rounded-xl px-3.5 py-2.5 text-xs focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500 focus:outline-none font-bold" />
)}
)} {/* TAHAP 3 SEKOLAH: CHAT & ADVISORY NOTE */} {schoolStep === 3 && (
{/* CHAT PENDAMPINGAN */}
Obrolan Konsultasi Aktif (APIP NTB)
{chats.filter(c => c.schoolId === selectedSchoolId).length === 0 ? (

Ketik pesan untuk memulai konsultasi langsung dengan Auditor pendamping Anda.

) : ( chats.filter(c => c.schoolId === selectedSchoolId).map((chat, idx) => (
{chat.sender} • {chat.time}
{chat.message}
)) )}
handleSendChat(e, 'Sekolah')} className="flex gap-2 border-t border-slate-200/50 pt-3"> setChatMessage(e.target.value)} className="flex-1 bg-white border border-slate-200 rounded-xl px-4 py-2.5 text-xs focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500 focus:outline-none" />
{/* ADVISORY NOTE RESMI */}

🛡️ Advisory Note Resmi e-Review NTB

Lembar Advisory Note bertindak sebagai surat rekomendasi tertulis dari Inspektorat NTB yang menjadi jaminan preventif draf belanja sekolah Anda telah disetujui.

{proposedItems.filter(p => p.schoolId === selectedSchoolId && p.consultationStatus.includes("Advisory")).length === 0 ? (

Belum ada rekomendasi formal yang diterbitkan oleh APIP NTB.

) : ( proposedItems.filter(p => p.schoolId === selectedSchoolId && p.consultationStatus.includes("Advisory")).map((item) => (
RESMI APIP NTB

{item.activity}

{item.notes}

)) )}
)}
{/* Sidebar Kanan Sekolah: Asisten AI */}
{/* ASISTEN AI JUKNIS BOS */}

Asisten AI e-Review NTB

Kecerdasan Buatan Terbatas Konteks NTB

{aiChat.map((msg, idx) => (
{msg.text}
))} {isAiLoading && (
Menganalisis draf dengan parameter Juknis BOS & NTB...
)}
setAiInput(e.target.value)} disabled={isAiLoading} className="flex-1 bg-slate-800 text-xs text-white border border-slate-700 rounded-xl px-3 py-2.5 focus:ring-2 focus:ring-indigo-500/40 focus:border-indigo-500 focus:outline-none placeholder-slate-500" />
{/* AUDIT TRAIL LOG */}

Log Aktivitas e-Review

{consultingLogs.filter(l => l.schoolId === selectedSchoolId).map((log) => (
{log.time}

{log.user}: {log.action}

))}
)} {/* ======================================================== PORTAL INSPEKTORAT (APIP PROVINSI NTB) ======================================================== */} {role === 'auditor' && (
{/* Main Area: 3 Steps for APIP NTB */}
🔍

Portal Inspektorat NTB (e-Review)

Evaluasi pre-review draf usulan preventif sekolah se-NTB

Wilayah NTB
{/* LANGKAH-LANGKAH PREVENTIF APIP */}
{/* TAHAP 1 APIP: PETA KATEGORI KEAKTIFAN */} {auditorStep === 1 && (

Daftar Sekolah Binaan Provinsi NTB

Pilih sekolah di Lombok / Sumbawa untuk melihat pre-review draf anggaran.

{filteredSchools.map((sch) => (
{ setSelectedSchoolId(sch.id); showToast(`Fokus ulasan dialihkan ke: ${sch.name}`, "info"); }} className={`p-4 rounded-2xl border transition-all cursor-pointer relative flex flex-col justify-between h-[140px] ${ selectedSchoolId === sch.id ? 'ring-2 ring-emerald-500 bg-emerald-50/10 border-emerald-200 shadow-md shadow-emerald-500/5' : 'bg-white hover:shadow-md border-slate-200/70' }`} >
{sch.npsn}

{sch.name}

{sch.address}

Kepatuhan Mandiri: {sch.complianceScore}% Pilih Sekolah →
{selectedSchoolId === sch.id && (
)}
))}
)} {/* TAHAP 2 APIP: PENILAIAN PREVENTIF DRAFT KWITANSI */} {auditorStep === 2 && (
SEKOLAH TERPILIH NTB

{activeSchool.name}

Hubungan Binaan: {activeSchool.status} • Kepatuhan: {activeSchool.complianceScore}%

Dokumen Draft SPJ Siap Ditelaah

{draftSpjList.filter(d => d.schoolId === selectedSchoolId).length === 0 ? (

Tidak ada draf kwitansi/SPJ yang dikirimkan oleh sekolah ini.

) : ( draftSpjList.filter(d => d.schoolId === selectedSchoolId).map((draft) => (
{draft.id} {draft.status}

{draft.description}

Berkas: {draft.file} • Estimasi: Rp {draft.amount.toLocaleString()}

{draft.hasAdvice && (
Catatan Bimbingan Anda (APIP NTB): "{draft.adviceText}"
)}
)) )}
)} {/* TAHAP 3 APIP: BIMBINGAN CHAT & OTORISASI */} {auditorStep === 3 && (
{/* CHAT PENDAMPINGAN SISI AUDITOR */}
Obrolan Pendampingan e-Review NTB
{chats.filter(c => c.schoolId === selectedSchoolId).length === 0 ? (

Ketik pesan pertama Anda untuk merespons sekolah.

) : ( chats.filter(c => c.schoolId === selectedSchoolId).map((chat, idx) => (
{chat.sender} • {chat.time}
{chat.message}
)) )}
handleSendChat(e, 'Konsultan APIP')} className="flex gap-2 pt-3 border-t border-slate-200/50"> setChatMessage(e.target.value)} className="flex-1 bg-white border border-slate-200 rounded-xl px-4 py-2.5 text-xs focus:ring-2 focus:ring-emerald-500/20 focus:border-emerald-500 focus:outline-none" />
{/* FORM PENERBITAN ADVISORY NOTE RESMI */}

Otorisasi Dokumen Advisory Note e-Review NTB

Rilis dokumen persetujuan final (Advisory Note) resmi dari Inspektorat NTB sebagai penutup hasil pre-review draf sekolah.

{proposedItems.filter(p => p.schoolId === selectedSchoolId).length === 0 ? (

Belum ada usulan program belanja dari sekolah ini.

) : ( proposedItems.filter(p => p.schoolId === selectedSchoolId).map((item) => (
{item.id}

{item.activity}

Rencana Pagu: Rp {item.plannedCost.toLocaleString()}

)) )}
)}
{/* Sidebar Kanan Inspektorat: Informasi & Log */}
{/* DETAIL SEKOLAH */}

Informasi Binaan NTB

Sekolah Terpilih: {activeSchool.name}
Kepala Sekolah: {activeSchool.headmaster}
Bendahara BOS: {activeSchool.treasurer}
Status Binaan: {activeSchool.status}
{/* NOTIFIKASI */}

Notifikasi Masuk

{notifications.filter(n => n.schoolId === selectedSchoolId).length === 0 ? (

Belum ada notifikasi baru untuk sekolah ini.

) : ( notifications.filter(n => n.schoolId === selectedSchoolId).map((notif) => (
{notif.date}

{notif.message}

)) )}
{/* AUDIT TRAIL LOG */}

Log Aktivitas APIP

{consultingLogs.filter(l => l.schoolId === selectedSchoolId).map((log) => (
{log.time}

{log.user}: {log.action}

))}
)} {/* ======================================================== BUILDING INTERACTIVE CUSTOM MODALS ======================================================== */} {/* COACHING NOTE */} {isCoachingModalOpen && (

Coaching Note e-Review NTB

Pemberian Review untuk Berkas: {coachingTargetId}