if (window.location.pathname.endsWith('/index.html')) { const cleanUrl = window.location.pathname.replace('/index.html', '/') + window.location.search + window.location.hash; window.history.replaceState(null, '', cleanUrl); } let state = { user: null, role: null, options: { items: [] }, data: [], currentMode: 'ADD', currentRowIndex: null, currentPage: 1, rowsPerPage: 10 }; const ENC = "aHR0cHM6Ly9zY3JpcHQuZ29vZ2xlLmNvbS9tYWNyb3Mvcy9BS2Z5Y2J4MG5tbDVJc1d0NXh1VWVNTGZpZjY5OU9MSEQ5NF9rdGZneExUWnRoQ1VpUDIyMFJhbE5kUDdfaFh1WGUyREpyMWhBQS9leGVj"; const GWP = atob(ENC); async function apiCall(action, payload = {}) { const reqPayload = { action, username: state.user, password: state.password, ...payload }; const response = await fetch(GWP, { method: 'POST', body: JSON.stringify(reqPayload) }); const res = await response.json(); if (res.status === 'error') throw new Error(res.message); return res.data; } async function login() { const u = document.getElementById('username').value; const p = document.getElementById('password').value; try { const data = await apiCall('login', { username: u, password: p }); state.user = u; state.password = p; state.role = data.role; document.getElementById('login-view').classList.add('d-none'); document.getElementById('app-view').classList.remove('d-none'); document.getElementById('nav-username').innerText = state.user; document.getElementById('drop-username').innerText = state.user; document.getElementById('drop-role').innerText = state.role; const btnAdd = document.getElementById('btn-add-new'); btnAdd.classList.remove('d-none'); if (state.role === 'Viewer') { btnAdd.disabled = true; } else { btnAdd.disabled = false; } await loadInitialData(); } catch (e) { document.getElementById('login-error').classList.remove('d-none'); } } function logout() { state.user = null; state.password = null; state.role = null; document.getElementById('app-view').classList.add('d-none'); document.getElementById('login-view').classList.remove('d-none'); document.getElementById('username').value = ''; document.getElementById('password').value = ''; } async function loadInitialData() { document.getElementById('tableBody').innerHTML = `Loading data...`; const result = await apiCall('getData'); state.options = result.options; state.data = result.data; populateDropdowns(); renderTable(); } function populateDropdowns() { const buildOptions = (arr, valKey, labelKey = null) => arr.map(i => `` + state.options.subinv.map(i => ``).join(''); } function updateUOM() { const selectedItemDisplay = document.getElementById('f_item').value; const itemData = state.options.items.find(i => i.display === selectedItemDisplay); document.getElementById('f_uom').value = itemData ? itemData.uom : ''; checkFormValidity(); } function resetPageAndRender() { state.rowsPerPage = parseInt(document.getElementById('rowsPerPage').value); state.currentPage = 1; renderTable(); } function changePage(page) { state.currentPage = page; renderTable(); } function displayDate(dateStr) { if (!dateStr) return ''; return new Date(dateStr).toLocaleDateString('id-ID', { year: 'numeric', month: '2-digit', day: '2-digit' }); } function renderTable() { const search = document.getElementById('searchInput').value.toLowerCase(); const filtered = state.data.filter(r => Object.values(r).some(v => String(v).toLowerCase().includes(search))); const total = filtered.length; const totalPages = Math.ceil(total / state.rowsPerPage); if (state.currentPage > totalPages) state.currentPage = totalPages || 1; const startIdx = (state.currentPage - 1) * state.rowsPerPage; const paginated = filtered.slice(startIdx, startIdx + state.rowsPerPage); document.getElementById('totalRows').innerText = total; document.getElementById('pageStart').innerText = total === 0 ? 0 : startIdx + 1; document.getElementById('pageEnd').innerText = Math.min(startIdx + state.rowsPerPage, total); let pageHTML = `
  • `; let pStart = Math.max(1, state.currentPage - 2); let pEnd = Math.min(totalPages, state.currentPage + 2); for(let i = pStart; i <= pEnd; i++) { pageHTML += `
  • `; } pageHTML += `
  • `; document.getElementById('paginationNav').innerHTML = pageHTML; let headHTML = ` Nama SupplierTgl KedatanganNo. SJ Supplier ItemQty AwalQty RejectQty Nett UOMSub InvNo. STG ManualEkspedisi PIC Nomer POTanggal PONo. ReceiveNotes StatusAction `; document.getElementById('tableHead').innerHTML = headHTML; if (paginated.length === 0) { document.getElementById('tableBody').innerHTML = `No data found`; return; } let bodyHTML = ''; paginated.forEach(row => { let statColor = row.stat === 'OK' ? 'bg-success' : (row.stat === 'EDITED' ? 'bg-primary' : 'bg-secondary'); // Disable edit button if role is Viewer OR if status is OK let isViewer = state.role === 'Viewer'; let btnDisabled = (isViewer || row.stat === 'OK') ? 'disabled' : ''; let btnClass = btnDisabled ? 'btn-secondary opacity-50' : 'btn-warning'; bodyHTML += ` ${row.supplier} ${displayDate(row.tglDatang)} ${row.noSj} ${row.item} ${row.qtyAwal} ${row.qtyReject} ${row.qtyNett} ${row.uom} ${row.subInv} ${row.stgManual} ${displayDate(row.ekspedisi)} ${row.noPo} ${displayDate(row.tglPo)} ${row.noReceive} ${row.notes} ${row.stat} `; }); document.getElementById('tableBody').innerHTML = bodyHTML; } function openAddModal() { if (state.role === 'Viewer') return; state.currentMode = 'ADD'; document.getElementById('recordForm').reset(); document.getElementById('modalTitle').innerText = "Kedatangan Baru"; document.getElementById('section-edit').classList.add('d-none'); document.getElementById('divider-edit').classList.add('d-none'); lockFields(false); document.getElementById('btnActionSave').innerText = "Save"; document.getElementById('btnActionSave').disabled = true; new coreui.Modal(document.getElementById('dataModal')).show(); } function openEditModal(rowIndex) { if (state.role === 'Viewer') return; state.currentMode = 'EDIT'; state.currentRowIndex = rowIndex; const rowData = state.data.find(r => r._rowIndex === rowIndex); document.getElementById('modalTitle').innerText = "Edit Row"; document.getElementById('section-edit').classList.remove('d-none'); document.getElementById('divider-edit').classList.remove('d-none'); document.getElementById('f_supplier').value = rowData.supplier; document.getElementById('f_tglDatang').value = formatDateForInput(rowData.tglDatang); document.getElementById('f_noSj').value = rowData.noSj; document.getElementById('f_item').value = rowData.item; document.getElementById('f_qtyAwal').value = rowData.qtyAwal; document.getElementById('f_qtyReject').value = rowData.qtyReject; document.getElementById('f_qtyNett').value = rowData.qtyNett; document.getElementById('f_uom').value = rowData.uom; document.getElementById('f_subInv').value = rowData.subInv; document.getElementById('f_stgManual').value = rowData.stgManual; document.getElementById('f_ekspedisi').value = formatDateForInput(rowData.ekspedisi); document.getElementById('f_notes').value = rowData.notes; const cleanPo = rowData.noPo ? String(rowData.noPo).replace('PO/SKL/', '') : ''; document.getElementById('f_noPo').value = cleanPo; document.getElementById('f_tglPo').value = formatDateForInput(rowData.tglPo); document.getElementById('f_noReceive').value = rowData.noReceive; lockFields(true); document.getElementById('btnActionSave').innerText = "Update"; document.getElementById('btnActionSave').disabled = true; new coreui.Modal(document.getElementById('dataModal')).show(); } function formatDateForInput(dateString) { if (!dateString) return ''; const d = new Date(dateString); return d.toISOString().split('T')[0]; } function lockFields(isEdit) { const toLock = ['f_supplier', 'f_tglDatang', 'f_noSj', 'f_item']; toLock.forEach(id => document.getElementById(id).disabled = isEdit); } function checkFormValidity() { let isValid = true; if (state.currentMode === 'ADD') { document.querySelectorAll('.req-add').forEach(el => { if (!el.value.trim()) isValid = false; }); } else { document.querySelectorAll('.req-edit').forEach(el => { if (!el.value.trim()) isValid = false; }); const noPoVal = document.getElementById('f_noPo').value.trim(); const tglPoVal = document.getElementById('f_tglPo').value.trim(); if ((noPoVal && !tglPoVal) || (!noPoVal && tglPoVal)) { isValid = false; } } document.getElementById('btnActionSave').disabled = !isValid; } async function submitData() { const btn = document.getElementById('btnActionSave'); btn.disabled = true; btn.innerHTML = ` Processing...`; const payload = { qtyAwal: document.getElementById('f_qtyAwal').value, qtyReject: document.getElementById('f_qtyReject').value, qtyNett: document.getElementById('f_qtyNett').value, subInv: document.getElementById('f_subInv').value, stgManual: document.getElementById('f_stgManual').value.toUpperCase(), ekspedisi: document.getElementById('f_ekspedisi').value, notes: document.getElementById('f_notes').value }; if (state.currentMode === 'ADD') { payload.supplier = document.getElementById('f_supplier').value; payload.tglDatang = document.getElementById('f_tglDatang').value; payload.noSj = document.getElementById('f_noSj').value; payload.item = document.getElementById('f_item').value; payload.uom = document.getElementById('f_uom').value; await apiCall('saveRow', { rowData: payload }); } else { payload.noPo = document.getElementById('f_noPo').value; payload.tglPo = document.getElementById('f_tglPo').value; payload.noReceive = document.getElementById('f_noReceive').value; await apiCall('updateRow', { rowData: payload, rowIndex: state.currentRowIndex }); } closeModal('dataModal'); await loadInitialData(); } function closeModal(id) { const modal = coreui.Modal.getInstance(document.getElementById(id)); if (modal) modal.hide(); }