// CredNX Underwrite — app shell, sidebar, upload flow, sessions, processing.
// Re-themed to Editorial Forest tokens. ALL fetch() calls, sessionStorage
// usage and API endpoint paths are preserved verbatim.
// document_type → icon key in I{...}
const DOC_TYPE_ICON = {
bank_statement: 'bank', credit_bureau: 'creditCard', invoice: 'receipt',
id_document: 'fileText', tax_return: 'fileText', medical_report: 'fileText',
medical_prescription: 'fileText', disbursement_report: 'fileText',
};
// Fallback used when the /api/v1/documents endpoint is unreachable
const FALLBACK_DOC_MASTER = [
{id:'DOC_001', name:'Bank Statement', icon:'bank', desc:'PDF statements, any bank'},
{id:'DOC_008', name:'Credit Bureau', icon:'creditCard', desc:'CIBIL / Experian reports'},
{id:'DOC_002', name:'Invoice', icon:'receipt', desc:'Supplier & buyer invoices'},
];
function useDocMaster() {
const [docs, setDocs] = React.useState(FALLBACK_DOC_MASTER);
const [loading, setLoading] = React.useState(true);
React.useEffect(() => {
const authKey = sessionStorage.getItem('crednx_auth_key');
const headers = authKey ? { 'X-Auth-Key': authKey } : {};
fetch('/api/v1/documents', { headers })
.then(r => r.ok ? r.json() : Promise.reject(r.status))
.then(data => {
const list = data?.result?.json?.documents;
if (Array.isArray(list) && list.length > 0) {
setDocs(list.map(d => ({
id: d.document_id,
name: d.document_name,
icon: DOC_TYPE_ICON[d.document_type] || 'fileText',
desc: d.description,
})));
}
})
.catch(() => {/* keep fallback */})
.finally(() => setLoading(false));
}, []);
return { docs, loading };
}
const MOCK_BORROWERS = [
{id:'BRW-2847', name:'PT Sinar Mas Agro', sessions:4},
{id:'BRW-2931', name:'Budi Santoso', sessions:2},
{id:'BRW-3012', name:'CV Karya Jaya', sessions:1},
{id:'BRW-3104', name:'Rahmat Hidayat', sessions:7},
];
// ——— Sidebar wordmark — uses the brand SVG. The wrapper is data-theme="dark" ———
// because the sidebar uses a dark deep-forest panel regardless of theme.
const SidebarWordmark = () => ;
function Sidebar({page, setPage, user, org, sessionCount}) {
const [collapsed, setCollapsed] = React.useState(() => {
try { return localStorage.getItem('crednx_sidebar_collapsed') === '1'; } catch { return false; }
});
const toggleCollapsed = () => setCollapsed(c => {
const next = !c;
try { localStorage.setItem('crednx_sidebar_collapsed', next ? '1' : '0'); } catch {}
return next;
});
const W = collapsed ? 72 : 240;
const sessionBadge = sessionCount == null ? null : String(sessionCount);
const items = [
{id:'home', label:'Home', icon:, badge:null},
{id:'underwrite', label:'Underwrite', icon:, badge:null},
{id:'sessions', label:'Sessions', icon:, badge:sessionBadge},
{id:'borrowers', label:'Borrowers', icon:, badge:null},
{id:'insights', label:'Insights', icon:, badge:null},
{divider:true},
{id:'settings', label:'Settings', icon:, badge:null},
...(user.role==='Admin' ? [{id:'team', label:'Team', icon:, badge:null}] : []),
];
return (
{collapsed ? : }