diff --git a/server.js b/server.js index 52b298c..49ac817 100644 --- a/server.js +++ b/server.js @@ -244,6 +244,40 @@ function layout(title, body, { authenticated = false, activePath = "/", subtitle var modalRoot = document.getElementById('modal-root'); if (modalRoot) modalRoot.innerHTML = ''; } + + function normalizeDateForInput(value) { + var text = String(value || '').trim(); + if (!text || text === 'null' || text === 'undefined') return ''; + var iso = text.match(/^(\\d{4})-(\\d{2})-(\\d{2})$/); + if (iso) return iso[0]; + var slash = text.match(/^(\\d{2})\\/(\\d{2})\\/(\\d{4})$/); + if (slash) return slash[3] + '-' + slash[2] + '-' + slash[1]; + var dash = text.match(/^(\\d{2})-(\\d{2})-(\\d{4})$/); + if (dash) return dash[3] + '-' + dash[2] + '-' + dash[1]; + return ''; + } + + function fillPatientFromPick(button) { + var form = document.querySelector('[data-order-form]'); + if (!form || !button) return; + var fields = { + patient_name: button.getAttribute('data-patient-name') || '', + patient_dob: normalizeDateForInput(button.getAttribute('data-patient-dob') || ''), + patient_nik: button.getAttribute('data-patient-nik') || '', + patient_hp: button.getAttribute('data-patient-hp') || '', + patient_address: button.getAttribute('data-patient-address') || '', + }; + Object.keys(fields).forEach(function (name) { + var field = form.querySelector('[name="' + name.replace(/"/g, '\\"') + '"]'); + if (!field) return; + field.value = fields[name]; + field.dispatchEvent(new Event('input', { bubbles: true })); + field.dispatchEvent(new Event('change', { bubbles: true })); + }); + syncOrderDraft(form); + closeModal(); + } + document.addEventListener('input', function (event) { var form = isOrderField(event.target); if (!form) return; @@ -270,6 +304,12 @@ function layout(title, body, { authenticated = false, activePath = "/", subtitle injectOrderDraftPayload(form); }); document.addEventListener('click', function (event) { + var patientPick = event.target.closest && event.target.closest('[data-patient-pick]'); + if (patientPick) { + event.preventDefault(); + fillPatientFromPick(patientPick); + return; + } var printTrigger = event.target.closest && event.target.closest('[data-action="print-order"]'); if (printTrigger) { event.preventDefault(); @@ -793,9 +833,12 @@ function renderOrderForm(step, stepKey = "demografi", fppTests = [], mouId = "") demografi: `
- ${panelHeader("Mandatory", "These fields are required or expected by the backend before save.")} + ${panelHeader("Mandatory", "These fields are required before save.")} +
+ +
- +
@@ -804,7 +847,7 @@ function renderOrderForm(step, stepKey = "demografi", fppTests = [], mouId = "") - +
@@ -1651,6 +1694,18 @@ function normalizeDesktopOrder(raw, index = 0) { }; } +function normalizePatientOrder(raw, index = 0) { + return { + id: raw?.order_id || raw?.id || raw?.order_patient_id || "", + patient: raw?.order_name || raw?.patient_name || raw?.name || "", + orderDob: raw?.order_dob || "", + orderNik: raw?.order_nik || "", + orderHp: raw?.order_hp || "", + orderAddress: raw?.order_address || "", + updated: raw?.order_date || raw?.updated_at || raw?.updated || "", + }; +} + function normalizeResult(raw, index = 0) { const status = raw?.status || raw?.result_status || raw?.order_status || "Pending"; const detailsSource = raw?.details || raw?.items || raw?.order_details || []; @@ -1777,6 +1832,24 @@ async function loadDesktopOrders(session, { search = "", month = "", year = "", } } +async function loadPatientSearch(session, search = "") { + try { + const payload = await apiPost( + "/order/search_order_pasien_by_doktorid", + { + token: session.token, + OrderPatientM_DoctorID: session.doctorId || sampleLogin.doctorId, + search: String(search || ""), + }, + session.token, + ); + const rows = extractArray(payload) || []; + return Array.isArray(rows) ? rows.map((row, index) => normalizePatientOrder(row, index)).filter((item) => item.id || item.patient) : []; + } catch { + return []; + } +} + async function loadResults(session, search = "") { const term = String(search || "").trim(); try { @@ -2079,6 +2152,53 @@ function fragmentPesanKhusus(orderId) { `; } +async function fragmentPatientSearch(session, search = "") { + const patients = await loadPatientSearch(session, search); + return ` + + `; +} + async function fragmentResultDetail(session, resultId) { const result = await loadResultDetail(session, resultId); return ` @@ -2349,6 +2469,12 @@ async function renderRoute(req, res, url) { return; } + if (path === "/fragments/modals/patient-search" && isGet) { + if (!requireAuth(req, res)) return; + html(res, 200, await fragmentPatientSearch(session, query.search || "")); + return; + } + if (path.startsWith("/fragments/results/detail/") && isGet) { if (!requireAuth(req, res)) return; const resultId = path.split("/")[4] || ""; diff --git a/styles.css b/styles.css index 6b4d0f9..c05e346 100644 --- a/styles.css +++ b/styles.css @@ -950,6 +950,21 @@ tr:last-child td { border: 1px solid rgba(15, 23, 42, 0.06); } +.mini-item[data-patient-pick] { + width: 100%; + text-align: left; + cursor: pointer; + font: inherit; + color: inherit; + appearance: none; + -webkit-appearance: none; +} + +.mini-item[data-patient-pick]:hover { + background: rgba(185, 28, 28, 0.06); + border-color: rgba(185, 28, 28, 0.14); +} + .mini-item strong { display: block; margin-bottom: 4px;