import http from "node:http"; import { readFile } from "node:fs/promises"; import { extname } from "node:path"; const PORT = Number(process.env.PORT || 5173); const API_BASE = process.env.DOCLINK_API_BASE || "https://devbandungraya.aplikasi.web.id/one-api-doctor/doctor_mitra"; const sessionKey = "doclink_session"; const mockUser = { name: "dr. Fajri", role: "Dokter Mitra", hospital: "Pramita Bandungraya", doctorId: "DR-10024", }; const mockOrders = [ { id: "ORD-24001", patient: "Siti Amelia", doctor: "dr. Fajri", updated: "2m ago", status: "Processing", tone: "warning", mode: "Inpatient", age: "34", gender: "F", tests: ["Hematology", "Glucose", "Urine"], diagnosis: "Check-up rutin", message: "Prioritize fasting sample and note dizziness symptom.", }, { id: "ORD-24002", patient: "Budi Santoso", doctor: "dr. Fajri", updated: "14m ago", status: "Ready", tone: "success", mode: "Outpatient", age: "52", gender: "M", tests: ["Lipid Profile", "Liver Function"], diagnosis: "Kontrol hipertensi", message: "Call if LDL exceeds threshold.", }, { id: "ORD-24003", patient: "Nia Putri", doctor: "dr. Fajri", updated: "40m ago", status: "Needs review", tone: "danger", mode: "Emergency", age: "27", gender: "F", tests: ["Electrolytes", "CBC", "CRP"], diagnosis: "Dehydration", message: "Urgent release once CRP is complete.", }, ]; const mockResults = [ { id: "RES-8821", patient: "Siti Amelia", test: "CBC", status: "Released", tone: "success", date: "13 Apr 2026", summary: "Hemoglobin slightly below baseline.", value: "11.2 g/dL", }, { id: "RES-8822", patient: "Budi Santoso", test: "Lipid Profile", status: "Pending", tone: "warning", date: "13 Apr 2026", summary: "Awaiting final approval.", value: "LDL 145 mg/dL", }, { id: "RES-8823", patient: "Nia Putri", test: "CRP", status: "Review", tone: "danger", date: "12 Apr 2026", summary: "Result flagged for clinical review.", value: "18.4 mg/L", }, ]; const mockFppGroups = [ { group: "HEMATOLOGI", count: 6, desc: "Complete blood count and related panels." }, { group: "KLINIK RUTIN", count: 5, desc: "Daily screening and basic chemistry." }, { group: "IMUNOLOGI", count: 3, desc: "Inflammation and antibody markers." }, { group: "URINALISA", count: 4, desc: "Urine screening and microscopic checks." }, ]; const mockPatients = [ { name: "Siti Amelia", mrn: "MRN-10011", gender: "Female", lastVisit: "Today", note: "Active order" }, { name: "Budi Santoso", mrn: "MRN-10012", gender: "Male", lastVisit: "Yesterday", note: "Repeat visit" }, { name: "Nia Putri", mrn: "MRN-10013", gender: "Female", lastVisit: "12 Apr", note: "New registration" }, ]; function escapeHtml(value) { return String(value) .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll('"', """); } function statusClass(status) { const mapping = { Processing: "warning", Ready: "success", "Needs review": "danger", Released: "success", Pending: "warning", Review: "danger", }; return mapping[status] || "neutral"; } function statusBadge(text) { return `${escapeHtml(text)}`; } function icon(name) { const map = { search: '', plus: '', bell: '', arrow: '', login: '', }; return map[name] || ""; } function layout(title, body, { authenticated = false, activePath = "/", subtitle = "", shell = true } = {}) { const nav = authenticated ? desktopNav(activePath) : ""; const mobile = authenticated ? mobileNav(activePath) : ""; const header = authenticated ? topbar(activePath, subtitle) : ""; return ` ${escapeHtml(title)}
${shell && authenticated ? `
${nav}
${header} ${body}
${mobile}
` : body}
`; } function topbar(activePath, subtitle) { const titleMap = { "/": ["Dashboard", "Overview of orders, results, and work queues."], "/orders": ["Orders", "Search, review, and create patient orders."], "/results": ["Results", "Monitor released and pending laboratory results."], "/fpp": ["FPP", "Browse grouped reference packages and filters."], "/patients": ["Patients", "Landing for patient registration and lookup."], "/settings": ["Settings", "Account profile and password management."], }; const [title, fallbackSubtitle] = titleMap[activePath] || ["DocLink Web", "Responsive clinical workflow shell."]; const searchForm = activePath === "/orders" ? ` ` : activePath === "/results" ? ` ` : ` Search orders `; return `
${escapeHtml(activePath === "/" ? "Clinical dashboard" : "Workflow view")}

${escapeHtml(title)}

${escapeHtml(subtitle || fallbackSubtitle)}

${searchForm} ${icon("plus")} New order
`; } function desktopNav(activePath) { const items = [ ["/", "Home", "Dashboard"], ["/orders", "Order", "Create & list"], ["/results", "Result", "History"], ["/fpp", "FPP", "Catalog"], ["/settings", "Akun", "Profile"], ]; const active = (href) => activePath === href || activePath.startsWith(`${href}/`); return ` `; } function mobileNav(activePath) { const items = [ ["/", "Home", "Dashboard"], ["/orders", "Order", "Create"], ["/results", "Result", "History"], ["/fpp", "FPP", "Catalog"], ["/settings", "Akun", "Profile"], ]; const active = (href) => activePath === href || activePath.startsWith(`${href}/`); return ` `; } function panelHeader(title, text, action = "") { return `

${escapeHtml(title)}

${escapeHtml(text)}

${action}
`; } function dashboardPage() { const stats = [ { label: "Orders today", value: "28", trend: "+12%", hint: "Vs yesterday" }, { label: "Results pending", value: "7", trend: "-3%", hint: "Still waiting release" }, { label: "FPP items", value: "14", trend: "+2", hint: "Active reference set" }, { label: "Special messages", value: "5", trend: "+1", hint: "Need follow-up" }, ]; const shortcuts = [ { title: "New order", desc: "Start registration flow", href: "/orders/new" }, { title: "Pending results", desc: "Review unreleased items", href: "/results/pending" }, { title: "FPP catalog", desc: "Inspect lab groups", href: "/fpp" }, { title: "Change password", desc: "Update account security", href: "/settings/change-password" }, ]; return `
${stats .map( (item) => `
${escapeHtml(item.label)} ${escapeHtml(item.trend)}
${escapeHtml(item.value)} ${escapeHtml(item.hint)}
`, ) .join("")}
${panelHeader("Quick actions", "Jump into the common flows without digging through nested screens.")}
${panelHeader("Recent orders", "A compact snapshot of the latest patient orders and their state.", 'View all')}
${mockOrders .map( (order) => ` `, ) .join("")}
PatientOrderStatusUpdated
${escapeHtml(order.patient)}
${escapeHtml(order.mode)}
${escapeHtml(order.id)}
${escapeHtml(order.diagnosis)}
${statusBadge(order.status)} ${escapeHtml(order.updated)}
${panelHeader("Today’s notes", "Items that need attention now, not later.")}
${[ ["FPP ready for release", "Review Hematology group before rounding."], ["Pending sample", "One fasting sample still waiting in the queue."], ["Password rotation", "Prompt user to refresh credentials after 90 days."], ] .map( ([title, text]) => `
${escapeHtml(title)}

${escapeHtml(text)}

${icon("arrow")}
`, ) .join("")}
`; } function renderOrdersTable(orders, selectedOrderId, filter = "All") { const selected = orders.find((item) => item.id === selectedOrderId) || orders[0] || mockOrders[0]; return `
${panelHeader("Search orders", "Use the filter to match the old app flow without giving up desktop readability.", 'Create order')}
${["All", "Processing", "Ready", "Needs review"] .map( (item) => ` `, ) .join("")}
${orders .map( (order) => ` `, ) .join("")}
PatientOrder IDDoctorStatusUpdated
${escapeHtml(order.patient)}
${escapeHtml(order.mode)}
${escapeHtml(order.id)} ${escapeHtml(order.doctor)} ${statusBadge(order.status)} ${escapeHtml(order.updated)}
${orders .map( (order) => `
${escapeHtml(order.patient)}

${escapeHtml(order.id)} · ${escapeHtml(order.mode)}

${statusBadge(order.status)}
${escapeHtml(order.doctor)} ${escapeHtml(order.updated)}
`, ) .join("")}
`; } function renderOrderDetail(order) { return `
${panelHeader( `${order.patient} · ${order.id}`, "Order detail with the same structure as the proposed master-detail workflow.", ``, )}
Status
${statusBadge(order.status)}
Patient${escapeHtml(order.patient)}${escapeHtml(order.mode)} · ${escapeHtml(order.age)} years
Doctor${escapeHtml(order.doctor)}${escapeHtml(mockUser.hospital)}
${panelHeader("Requested tests", "List/table treatment on desktop, cards on smaller screens.")}
${order.tests .map( (test) => `
${escapeHtml(test)}

Included in the current order bundle.

`, ) .join("")}
`; } function renderOrderForm(step, stepKey = "demografi") { const steps = [ ["demografi", "Demografi", "Patient identity and contact details."], ["diagnosa", "Diagnosa", "Clinical indication and diagnosis."], ["pemeriksaan", "Pemeriksaan", "Choose examination groups."], ["qrcode", "QR Code", "Fast entry for existing records."], ["review", "Review", "Check before submit."], ]; const activeIndex = Math.max(0, steps.findIndex((item) => item[0] === stepKey)); const stepBody = { demografi: `
`, diagnosa: `
`, pemeriksaan: `
${["Hematology", "Clinical Chemistry", "Urinalysis", "Immunology", "Microbiology"].map((item) => `${escapeHtml(item)}`).join("")}
${["CBC", "Glucose", "Lipid Profile", "CRP"].map((item) => ` `).join("")}
`, qrcode: `
Scan existing patient QR

Use a QR code to pull patient and visit context instantly.

QR preview area
Manual fallback

Still allow manual entry if the scan is unavailable.

`, review: `
Summary

All steps are merged into a final review before submit.

Patient

Siti Amelia

Diagnosis

Check-up rutin

Tests

CBC, Glucose, Urine

Message

Prioritize fasting sample

`, }[stepKey]; const prev = steps[activeIndex - 1]; const next = steps[activeIndex + 1]; return `
${panelHeader("Create new order", "The new project collapses the old step-heavy flow into a cleaner shell while keeping the same workflow.", 'Cancel')}
${steps .map( (item, index) => ` ${escapeHtml(item[1])} ${escapeHtml(item[2])} `, ) .join("")}
${stepBody}
`; } function renderResultsTable(results, selectedResultId) { const selected = results.find((item) => item.id === selectedResultId) || results[0] || mockResults[0]; return `
${panelHeader("Result history", "Desktop shows table detail. Mobile collapses into stacked cards.")}
Released

24 today

Pending

7 need approval

Reviewed

12 flagged

${results .map( (result) => ` `, ) .join("")}
PatientResult IDTestStatusDate
${escapeHtml(result.patient)}
${escapeHtml(result.summary)}
${escapeHtml(result.id)} ${escapeHtml(result.test)} ${statusBadge(result.status)} ${escapeHtml(result.date)}
${results .map( (result) => `
${escapeHtml(result.patient)}

${escapeHtml(result.test)} · ${escapeHtml(result.date)}

${statusBadge(result.status)}

${escapeHtml(result.summary)}

`, ) .join("")}
`; } function renderResultDetail(result) { return `
${panelHeader(`${result.patient} · ${result.id}`, "Result detail with summary, status, and interpretation fields.", 'Back to results')}
Status
${statusBadge(result.status)}
Test${escapeHtml(result.test)}
Value${escapeHtml(result.value)}
${escapeHtml(result.summary)}
`; } function renderFpp(groups) { return `
${panelHeader("FPP catalog", "Filter blocks and list cards on mobile, richer panel on desktop.")}
${["All", ...mockFppGroups.map((item) => item.group)] .map((item) => `${escapeHtml(item)}`) .join("")}
${groups.items .map( (item) => `

${escapeHtml(item.group)}

${escapeHtml(item.desc)}

${escapeHtml(item.count)} items
${["Filter", "Inspect", "Select", "Export"] .map( (action) => `
${escapeHtml(action)}

Workflow action for ${escapeHtml(item.group)}.

`, ) .join("")}
`, ) .join("")}
`; } function renderPatients() { return `
${panelHeader("Patient registration", "Landing page for registration, lookup, and entry flow.")}
New patient

Open the registration stepper and start a fresh case.

Start registration
Lookup

Search an existing patient and reuse their visit data.

QR entry

Fast path for scan-based intake.

Open QR flow
${panelHeader("Recent patients", "A compact list that becomes cards on mobile.")}
${mockPatients .map( (person) => ` `, ) .join("")}
NameMRNGenderLast visitNote
${escapeHtml(person.name)} ${escapeHtml(person.mrn)} ${escapeHtml(person.gender)} ${escapeHtml(person.lastVisit)} ${escapeHtml(person.note)}
`; } function renderSettings() { return `
${panelHeader("Account", "Profile data and security entry points.")}
Name${escapeHtml(mockUser.name)}
Doctor ID${escapeHtml(mockUser.doctorId)}
Role${escapeHtml(mockUser.role)}
Hospital${escapeHtml(mockUser.hospital)}
`; } function renderChangePassword() { return `
${panelHeader("Change password", "Inline validation and a straightforward submit path.")}
Cancel
`; } function loginPage({ error = "" } = {}) { return layout( "DocLink Login", `
DocLink rebuild · responsive shell

Clinical workflow that works on desktop and mobile.

The old app behavior is preserved in a cleaner layout with dashboard, orders, results, FPP, and settings routes.

Route structure
Login, dashboard, order flow, result flow, and account pages.
Responsive shell
Persistent sidebar on desktop, bottom nav on mobile.
Clean interaction model
HTMX fragments plus server-rendered templates.
Sign in

Login to DocLink

Use the upstream API or switch to demo mode if the backend is unavailable.

${error ? `
${escapeHtml(error)}
` : ""}
`, { authenticated: false, shell: false, activePath: "/login" }, ); } function splashPage() { return layout( "DocLink Splash", `
Starting DocLink

Loading workspace...

Checking session and routing into the right entry point.

Redirecting

We will move you to the correct route in a moment.

`, { authenticated: false, shell: false, activePath: "/splash" }, ); } function problemLoginPage() { return layout( "Problem Login", `
Login problem

Access needs attention.

Use this page when auth state is broken or a session expires.

Session expired

The session was cleared. Go back to login and sign in again.

Back to login
`, { authenticated: false, shell: false, activePath: "/problem-login" }, ); } function orderNewPage(path) { const step = path.split("/").filter(Boolean)[2] || "demografi"; return layout("Create Order", `
${renderOrderForm({}, step)}
`, { authenticated: true, activePath: "/orders", subtitle: "The new project collapses the old step-heavy flow into a cleaner shell while keeping the same workflow.", }); } function ordersPage({ query = {}, orders = mockOrders, selectedOrderId = mockOrders[0].id } = {}) { return layout("Orders", `
${renderOrdersTable(orders, selectedOrderId, query.status || "All")}
`, { authenticated: true, activePath: "/orders", }); } function resultsPage({ query = {}, results = mockResults, selectedResultId = mockResults[0].id } = {}) { return layout("Results", `
${renderResultsTable(results, selectedResultId)}
`, { authenticated: true, activePath: "/results", }); } function fppPage({ group = "All", groups = mockFppGroups } = {}) { return layout("FPP", `
${renderFpp({ items: groups, filter: group })}
`, { authenticated: true, activePath: "/fpp", }); } function patientsPage() { return layout("Patients", renderPatients(), { authenticated: true, activePath: "/patients" }); } function settingsPage() { return layout("Settings", renderSettings(), { authenticated: true, activePath: "/settings" }); } function changePasswordPage() { return layout("Change Password", renderChangePassword(), { authenticated: true, activePath: "/settings/change-password", }); } function orderDetailPage(order) { return layout("Order Detail", renderOrderDetail(order), { authenticated: true, activePath: "/orders", }); } function resultDetailPage(result) { return layout("Result Detail", renderResultDetail(result), { authenticated: true, activePath: "/results", }); } function specialMessagePage(order) { return layout( "Pesan Khusus", `
${panelHeader("Pesan khusus", "Desktop can treat this as a modal-style panel; mobile reads it as a dedicated page.", `Back`)}
${escapeHtml(order.patient)}

${escapeHtml(order.id)}

${statusBadge(order.status)}

${escapeHtml(order.message)}

${order.apiSaran ? `
${escapeHtml(typeof order.apiSaran === "string" ? order.apiSaran : JSON.stringify(order.apiSaran))}
` : ""}
Cancel
`, { authenticated: true, activePath: "/orders" }, ); } function emptyRoute(path) { return layout("Not Found", `
Route not found

${escapeHtml(path)} is not part of the current rebuild scope.

Go to dashboard
`, { authenticated: true, activePath: "/", }); } function cookieHeader(req) { return req.headers.cookie || ""; } function getCookie(req, name) { const cookies = cookieHeader(req) .split(";") .map((part) => part.trim()) .filter(Boolean); for (const item of cookies) { const [key, ...rest] = item.split("="); if (key === name) return decodeURIComponent(rest.join("=")); } return ""; } function setCookie(name, value, opts = {}) { const parts = [`${name}=${encodeURIComponent(value)}`, "Path=/", "HttpOnly", "SameSite=Lax"]; if (opts.maxAge != null) parts.push(`Max-Age=${opts.maxAge}`); if (opts.secure) parts.push("Secure"); return parts.join("; "); } function deleteCookie(name) { return `${name}=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0`; } function readSession(req) { const raw = getCookie(req, sessionKey); if (!raw) return null; try { return JSON.parse(raw); } catch { return null; } } function requireAuth(req, res) { const session = readSession(req); if (session) return session; redirect(res, "/login"); return null; } async function fetchJson(url, options = {}) { const response = await fetch(url, options); const contentType = response.headers.get("content-type") || ""; const body = contentType.includes("application/json") ? await response.json() : await response.text(); if (!response.ok) { const error = new Error(`Upstream error ${response.status}`); error.status = response.status; error.body = body; throw error; } return body; } async function apiPost(path, payload, token = "") { const headers = { "Content-Type": "application/json" }; if (token) { headers.Authorization = `Bearer ${token}`; payload.token = payload.token || token; } const url = `${API_BASE}${path}`; return fetchJson(url, { method: "POST", headers, body: JSON.stringify(payload), }); } function normalizeSession(payload) { const data = payload?.data || payload?.result || payload; const token = data?.token || data?.access_token || data?.accessToken || payload?.token || ""; const username = data?.username || data?.M_UserUsername || data?.name || ""; const doctorId = data?.doctor_id || data?.M_UserID || data?.doctorId || ""; return { token, username, doctorId, raw: payload, }; } function extractArray(payload) { if (Array.isArray(payload)) return payload; if (!payload || typeof payload !== "object") return null; for (const key of ["data", "result", "results", "items", "list"]) { const value = payload[key]; const found = extractArray(value); if (found) return found; } return null; } function normalizeOrder(raw, index = 0) { const testsSource = raw?.details || raw?.tests || raw?.items || raw?.order_details || []; const tests = Array.isArray(testsSource) ? testsSource .map((item) => { if (typeof item === "string") return item; return item?.name || item?.test_name || item?.detail_name || item?.exam || item?.label || ""; }) .filter(Boolean) : []; const status = raw?.status || raw?.order_status || raw?.state || "Processing"; return { id: raw?.order_patient_id || raw?.order_id || raw?.id || raw?.OrderPatientID || raw?.OrderID || `ORD-${String(index + 1).padStart(5, "0")}`, patient: raw?.patient_name || raw?.name || raw?.patient || raw?.patient_fullname || "Patient", doctor: raw?.doctor_name || raw?.doctor || raw?.M_UserUsername || mockUser.name, updated: raw?.updated_at || raw?.updated || raw?.created_at || "Today", status, tone: statusClass(status), mode: raw?.mode || raw?.visit_type || raw?.patient_type || "Outpatient", age: String(raw?.age || raw?.patient_age || ""), gender: raw?.gender || raw?.patient_gender || "", tests, diagnosis: raw?.patient_diagnosa || raw?.diagnosis || raw?.note || "", message: raw?.message || raw?.patient_note || "", }; } function normalizeResult(raw, index = 0) { const status = raw?.status || raw?.result_status || "Released"; return { id: raw?.result_id || raw?.order_id || raw?.id || raw?.hasil_id || `RES-${String(index + 1).padStart(4, "0")}`, patient: raw?.patient_name || raw?.name || raw?.patient || "Patient", test: raw?.test_name || raw?.item_name || raw?.test || "Result", status, tone: statusClass(status), date: raw?.date || raw?.created_at || raw?.updated_at || "Today", summary: raw?.summary || raw?.note || raw?.result_summary || "", value: raw?.value || raw?.result_value || raw?.result || "", }; } async function loadOrders(session, search = "", status = "All") { const term = String(search || "").trim(); try { const payload = await apiPost( "/order/search_order_pasien_by_doktorid", { token: session.token, OrderPatientM_DoctorID: session.doctorId || mockUser.doctorId, search: term, }, session.token, ); const rows = extractArray(payload) || []; const orders = rows.map((row, index) => normalizeOrder(row, index)).filter((item) => { const matchesSearch = !term || [item.id, item.patient, item.status, item.diagnosis, item.message].some((value) => String(value).toLowerCase().includes(term.toLowerCase()), ); const matchesStatus = !status || status === "All" || item.status === status; return matchesSearch && matchesStatus; }); if (orders.length) return orders; } catch { // Fall through to mock data. } return filterOrders(term, status); } async function loadResults(session, search = "") { const term = String(search || "").trim(); try { const payload = await apiPost( "/order/hasil_belum_keluar_by_id", { token: session.token, order_id: session.orderId || "" }, session.token, ); const rows = extractArray(payload) || []; const results = rows.map((row, index) => normalizeResult(row, index)).filter((item) => { if (!term) return true; return [item.id, item.patient, item.test, item.status, item.summary].some((value) => String(value).toLowerCase().includes(term.toLowerCase()), ); }); if (results.length) return results; } catch { // Fall through to mock data. } return filterResults(term); } async function loadResultDetail(session, resultId) { const fallback = mockResults.find((item) => item.id === resultId) || mockResults[0]; try { // Inferred from project-specs note about an additional result base path. const payload = await apiPost( "/result/getResult", { token: session.token, result_id: resultId, order_id: resultId, }, session.token, ); const rows = extractArray(payload); if (rows?.length) return normalizeResult(rows[0], 0); if (payload && typeof payload === "object") { return { ...fallback, ...normalizeResult(payload, 0), id: resultId || fallback.id, }; } } catch { // Fall through to local seed data when the upstream result API is unavailable. } return fallback; } async function loadFpp(session, group = "All") { try { const payload = await apiPost("/Fpp/load/1/1", { token: session.token }, session.token); const rows = extractArray(payload) || []; const items = rows.map((row, index) => ({ group: row?.group || row?.kategori || row?.name || `GROUP-${index + 1}`, count: Number(row?.count || row?.total || row?.qty || 1), desc: row?.description || row?.desc || "Laboratory reference item.", })); if (items.length) { const filtered = group === "All" ? items : items.filter((item) => item.group === group); return { items: filtered, filter: group }; } } catch { // Fall through to mock data. } const items = group === "All" ? mockFppGroups : mockFppGroups.filter((item) => item.group === group); return { items, filter: group }; } async function loadOrderDetail(session, orderId) { const order = mockOrders.find((item) => item.id === orderId) || mockOrders[0]; const detail = { ...order }; try { const saran = await apiPost( "/order/get_order_saran_by_order_patient_id", { token: session.token, order_patient_id: orderId }, session.token, ); detail.apiSaran = extractArray(saran) || saran?.message || saran?.note || saran?.result || ""; } catch { detail.apiSaran = ""; } try { const hasil = await apiPost( "/order/hasil_belum_keluar_by_id", { token: session.token, order_id: orderId }, session.token, ); detail.apiHasil = extractArray(hasil) || hasil?.message || hasil?.note || hasil?.result || ""; } catch { detail.apiHasil = ""; } return detail; } function json(res, status, payload) { res.writeHead(status, { "Content-Type": "application/json; charset=utf-8" }); res.end(JSON.stringify(payload)); } function redirect(res, location, headers = {}) { res.writeHead(302, { Location: location, ...headers }); res.end(); } function html(res, status, body, headers = {}) { res.writeHead(status, { "Content-Type": "text/html; charset=utf-8", ...headers }); res.end(body); } function isHtmx(req) { return req.headers["hx-request"] === "true"; } async function readBody(req) { const chunks = []; for await (const chunk of req) chunks.push(chunk); const raw = Buffer.concat(chunks).toString("utf8"); const contentType = req.headers["content-type"] || ""; if (contentType.includes("application/json")) return raw ? JSON.parse(raw) : {}; return Object.fromEntries(new URLSearchParams(raw)); } function filterOrders(search, status) { const term = String(search || "").trim().toLowerCase(); return mockOrders.filter((order) => { const matchesSearch = !term || [order.id, order.patient, order.status, order.diagnosis, order.message].some((value) => String(value).toLowerCase().includes(term), ); const matchesStatus = !status || status === "All" || order.status === status; return matchesSearch && matchesStatus; }); } function filterResults(search) { const term = String(search || "").trim().toLowerCase(); return mockResults.filter((result) => { if (!term) return true; return [result.id, result.patient, result.test, result.status, result.summary].some((value) => String(value).toLowerCase().includes(term), ); }); } function fragmentOrdersTable(search = "", status = "All", ordersData = null) { const orders = ordersData || filterOrders(search, status); const selected = orders[0] || mockOrders[0]; return `
${panelHeader("Search orders", "Filter the list without full page refresh.")}
${["All", "Processing", "Ready", "Needs review"] .map( (item) => ` `, ) .join("")}
${orders .map( (order) => ` `, ) .join("")}
PatientOrder IDDoctorStatusUpdated
${escapeHtml(order.patient)}
${escapeHtml(order.mode)}
${escapeHtml(order.id)} ${escapeHtml(order.doctor)} ${statusBadge(order.status)} ${escapeHtml(order.updated)}
`; } function fragmentResultsTable(search = "", resultsData = null) { const results = resultsData || filterResults(search); const selected = results[0] || mockResults[0]; return `
${panelHeader("Result history", "Desktop shows table detail. Mobile collapses into stacked cards.")}
Released

24 today

Pending

7 need approval

Reviewed

12 flagged

${results .map( (result) => ` `, ) .join("")}
PatientResult IDTestStatusDate
${escapeHtml(result.patient)}
${escapeHtml(result.summary)}
${escapeHtml(result.id)} ${escapeHtml(result.test)} ${statusBadge(result.status)} ${escapeHtml(result.date)}
`; } function fragmentFpp(group = "All", itemsData = null) { const items = itemsData || (group === "All" ? mockFppGroups : mockFppGroups.filter((item) => item.group === group)); return `
${panelHeader("FPP catalog", "Filter blocks and list cards on mobile, richer panel on desktop.")}
${["All", ...mockFppGroups.map((item) => item.group)] .map( (item) => ` ${escapeHtml(item)} `, ) .join("")}
${items .map( (item) => `

${escapeHtml(item.group)}

${escapeHtml(item.desc)}

${escapeHtml(item.count)} items
${["Filter", "Inspect", "Select", "Export"] .map( (action) => `
${escapeHtml(action)}

Workflow action for ${escapeHtml(item.group)}.

`, ) .join("")}
`, ) .join("")}
`; } function fragmentOrderStep(step) { return renderOrderForm({}, step); } function fragmentPesanKhusus(orderId) { const order = mockOrders.find((item) => item.id === orderId) || mockOrders[0]; return ` `; } async function fragmentResultDetail(session, resultId) { const result = await loadResultDetail(session, resultId); return `
${renderResultDetail(result)}
`; } async function renderRoute(req, res, url) { const path = url.pathname; const query = Object.fromEntries(url.searchParams.entries()); const session = readSession(req); const authed = Boolean(session); const isGet = req.method === "GET" || req.method === "HEAD"; if (path === "/styles.css") { const css = await readFile(new URL("./styles.css", import.meta.url), "utf8"); res.writeHead(200, { "Content-Type": "text/css; charset=utf-8" }); res.end(css); return; } if (path === "/login" && isGet) { html(res, 200, loginPage(), { "Cache-Control": "no-store" }); return; } if (path === "/splash" && isGet) { html(res, 200, splashPage(), { "Cache-Control": "no-store" }); return; } if (path === "/problem-login" && isGet) { html(res, 200, problemLoginPage(), { "Cache-Control": "no-store" }); return; } if (path === "/login" && req.method === "POST") { const body = await readBody(req); try { const payload = await apiPost("/auth/login", body); const normalized = normalizeSession(payload); const upstreamFailed = String(payload?.status || payload?.result_status || "").toUpperCase() === "ERR" || !normalized.token; if (upstreamFailed) { throw new Error(payload?.message || "Invalid login response"); } const sessionValue = JSON.stringify({ token: normalized.token, username: normalized.username || body.username || "", doctorId: normalized.doctorId || body.doctor_id || "", raw: payload, }); redirect(res, "/", { "Set-Cookie": setCookie(sessionKey, sessionValue, { maxAge: 60 * 60 * 12 }), }); } catch (error) { if (process.env.DOCLINK_DEMO_MODE !== "0") { const sessionValue = JSON.stringify({ token: "demo-token", username: body.username || mockUser.name, doctorId: body.doctor_id || mockUser.doctorId, raw: { demo: true }, }); redirect(res, "/", { "Set-Cookie": setCookie(sessionKey, sessionValue, { maxAge: 60 * 60 * 12 }), }); } else { html(res, 200, loginPage({ error: "Login failed or upstream API unavailable. Check credentials and network." })); } } return; } if (path === "/logout" && req.method === "POST") { const sessionData = readSession(req); if (sessionData?.token) { try { await apiPost( "/auth/logout", { M_UserID: sessionData.doctorId || mockUser.doctorId, M_UserUsername: sessionData.username || mockUser.name, }, sessionData.token, ); } catch { // Ignore upstream logout failures and still clear local session. } } redirect(res, "/login", { "Set-Cookie": deleteCookie(sessionKey) }); return; } if (path === "/settings/change-password" && req.method === "POST") { const sessionData = requireAuth(req, res); if (!sessionData) return; const body = await readBody(req); try { await apiPost( "/auth/change_password", { token: sessionData.token, M_UserID: sessionData.doctorId || mockUser.doctorId, username: sessionData.username || mockUser.name, doctor_id: sessionData.doctorId || mockUser.doctorId, new_password: body.new_password, confirm_password: body.confirm_password, }, sessionData.token, ); redirect(res, "/settings"); } catch (error) { html( res, 200, layout( "Change Password", `
${panelHeader("Change password", "Inline validation and a straightforward submit path.")}
Upstream change password call failed. Check API availability.
`, { authenticated: true, activePath: "/settings/change-password" }, ), ); } return; } if (path === "/orders/new" && isGet) { if (!requireAuth(req, res)) return; html(res, 200, orderNewPage(path)); return; } if (path.startsWith("/orders/new/") && isGet) { if (!requireAuth(req, res)) return; html(res, 200, orderNewPage(path)); return; } if (path === "/orders" && isGet) { if (!requireAuth(req, res)) return; const orders = await loadOrders(session, query.search || "", query.status || "All"); html(res, 200, ordersPage({ query, orders, selectedOrderId: orders[0]?.id || mockOrders[0].id })); return; } if (path === "/results" && isGet) { if (!requireAuth(req, res)) return; const results = await loadResults(session, query.search || ""); html(res, 200, resultsPage({ query, results, selectedResultId: results[0]?.id || mockResults[0].id })); return; } if (path === "/results/historical" && isGet) { if (!requireAuth(req, res)) return; html( res, 200, layout( "Historical results", `
${panelHeader("Historical results", "A compact historic view that still fits the responsive shell.")}
${mockResults.map((item) => `
${escapeHtml(item.patient)}

${escapeHtml(item.test)} · ${escapeHtml(item.date)}

${statusBadge(item.status)}
`).join("")}
`, { authenticated: true, activePath: "/results" }, ), ); return; } if (path === "/results/pending" && isGet) { if (!requireAuth(req, res)) return; html( res, 200, layout( "Pending results", `
${panelHeader("Pending results", "Items that need attention before release.")}
${mockResults.filter((item) => item.status !== "Released").map((item) => `
${escapeHtml(item.patient)}${statusBadge(item.status)}

${escapeHtml(item.test)} · ${escapeHtml(item.summary)}

Open detail
`).join("")}
`, { authenticated: true, activePath: "/results" }, ), ); return; } if (path === "/fpp" && isGet) { if (!requireAuth(req, res)) return; const groups = await loadFpp(session, query.group || "All"); html(res, 200, fppPage({ group: groups.filter, groups: groups.items })); return; } if (path === "/patients" && isGet) { if (!requireAuth(req, res)) return; html(res, 200, patientsPage()); return; } if ((path === "/settings" || path === "/settings/account") && isGet) { if (!requireAuth(req, res)) return; html(res, 200, settingsPage()); return; } if (path === "/settings/change-password" && isGet) { if (!requireAuth(req, res)) return; html(res, 200, changePasswordPage()); return; } if (path === "/" && isGet) { if (!requireAuth(req, res)) return; html(res, 200, layout("Dashboard", dashboardPage(), { authenticated: true, activePath: "/" })); return; } if (path.startsWith("/orders/") && path.endsWith("/pesan-khusus") && isGet) { if (!requireAuth(req, res)) return; const orderId = path.split("/")[2]; const order = await loadOrderDetail(session, orderId); html(res, 200, specialMessagePage(order)); return; } if (path.startsWith("/orders/") && isGet) { if (!requireAuth(req, res)) return; const orderId = path.split("/")[2]; const order = await loadOrderDetail(session, orderId); html(res, 200, orderDetailPage(order)); return; } if (path.startsWith("/results/") && isGet) { if (!requireAuth(req, res)) return; const resultId = path.split("/")[2]; const result = await loadResultDetail(session, resultId); html(res, 200, resultDetailPage(result)); return; } if (path === "/fragments/orders/table" && isGet) { if (!requireAuth(req, res)) return; const orders = await loadOrders(session, query.search || "", query.status || "All"); html(res, 200, fragmentOrdersTable(query.search || "", query.status || "All", orders), { "HX-Trigger": JSON.stringify({ "doclink:orders-updated": true }) }); return; } if (path === "/fragments/results/table" && isGet) { if (!requireAuth(req, res)) return; const results = await loadResults(session, query.search || ""); html(res, 200, fragmentResultsTable(query.search || "", results)); return; } if (path === "/fragments/fpp/list" && isGet) { if (!requireAuth(req, res)) return; const groups = await loadFpp(session, query.group || "All"); html(res, 200, fragmentFpp(groups.filter || "All", groups.items)); return; } if (path.startsWith("/fragments/forms/order-step/") && isGet) { if (!requireAuth(req, res)) return; const step = path.split("/")[4] || "demografi"; html(res, 200, fragmentOrderStep(step)); return; } if (path === "/fragments/modals/pesan-khusus" && isGet) { if (!requireAuth(req, res)) return; html(res, 200, fragmentPesanKhusus(query.order_id || mockOrders[0].id)); return; } if (path.startsWith("/fragments/results/detail/") && isGet) { if (!requireAuth(req, res)) return; const resultId = path.split("/")[4] || mockResults[0].id; html(res, 200, await fragmentResultDetail(session, resultId)); return; } if (path.startsWith("/api/") && isGet) { json(res, 200, { ok: true }); return; } if (path === "/orders" && req.method === "POST") { const sessionData = requireAuth(req, res); if (!sessionData) return; const body = await readBody(req); try { await apiPost( "/order/order_patient", { token: sessionData.token, M_MouID: body.M_MouID || mockUser.doctorId, patient_name: body.patient_name || "", patient_diagnosa: body.patient_diagnosa || "", patient_address: body.patient_address || "", patient_nik: body.patient_nik || "", patient_hp: body.patient_hp || "", patient_dob: body.patient_dob || "", patient_note: body.patient_note || "", details: body.details || [], }, sessionData.token, ); redirect(res, "/orders"); } catch { html( res, 200, layout( "Create Order", `
${panelHeader("Create new order", "The new project collapses the old step-heavy flow into a cleaner shell while keeping the same workflow.")}
Upstream order create call failed. Check API availability.
`, { authenticated: true, activePath: "/orders" }, ), ); } return; } if (path.startsWith("/orders/") && path.endsWith("/pesan-khusus") && req.method === "POST") { const sessionData = requireAuth(req, res); if (!sessionData) return; const orderId = path.split("/")[2]; const body = await readBody(req); try { await apiPost( "/Pesankhusus/add_pesan_khusus", { token: sessionData.token, order_id: orderId, pesan_khusus: body.pesan_khusus, }, sessionData.token, ); redirect(res, `/orders/${orderId}`); } catch { html( res, 200, layout( "Pesan Khusus", `
${panelHeader("Pesan khusus", "Desktop can treat this as a modal-style panel; mobile reads it as a dedicated page.")}
Upstream save failed. Check API availability.
`, { authenticated: true, activePath: "/orders" }, ), ); } return; } html(res, 404, emptyRoute(path)); } const server = http.createServer(async (req, res) => { try { const url = new URL(req.url, `http://${req.headers.host}`); await renderRoute(req, res, url); } catch (error) { res.writeHead(500, { "Content-Type": "text/plain; charset=utf-8" }); res.end(`Internal error: ${error.message}`); } }); server.listen(PORT, () => { console.log(`DocLink Web running on http://localhost:${PORT}`); });