1019 lines
48 KiB
HTML
1019 lines
48 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>City General Hospital - HIS System V2.0</title>
|
|
<style>
|
|
/* === CSS Variables & Reset === */
|
|
:root {
|
|
--primary: #007bff; /* Medical Blue */
|
|
--secondary: #6c757d;
|
|
--success: #28a745;
|
|
--danger: #dc3545;
|
|
--warning: #ffc107;
|
|
--info: #17a2b8;
|
|
--light: #f8f9fa;
|
|
--dark: #343a40;
|
|
--border-color: #dee2e6;
|
|
}
|
|
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
background-color: #f4f6f9;
|
|
color: #212529;
|
|
margin: 0;
|
|
font-size: 14px;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
a { text-decoration: none; color: var(--primary); }
|
|
a:hover { text-decoration: underline; }
|
|
|
|
/* === Layout Refactor: Override Table Styles === */
|
|
table, tbody, tr, td { display: block; width: 100% !important; border: none !important; background: transparent !important; padding: 0 !important; }
|
|
|
|
/* Top Broadcast - Notification Bar */
|
|
body > table:first-of-type {
|
|
background: #fff3cd !important; color: #856404; padding: 10px 20px !important; border-bottom: 1px solid #ffeeba !important;
|
|
}
|
|
body > table:first-of-type font { color: #856404 !important; font-weight: bold; }
|
|
body > table:first-of-type font[size="2"] { font-size: 12px; font-weight: normal; margin-left: 10px; }
|
|
|
|
/* Header Area */
|
|
body > table:nth-of-type(2) { background: white !important; padding: 10px 20px !important; border-bottom: 1px solid var(--border-color) !important; box-shadow: 0 1px 3px rgba(0,0,0,0.05); }
|
|
body > table:nth-of-type(2) tr { display: flex; justify-content: space-between; align-items: center; }
|
|
body > table:nth-of-type(2) td { width: auto !important; }
|
|
body > table:nth-of-type(2) font[size="5"] b { font-size: 20px; color: var(--primary); }
|
|
body > table:nth-of-type(2) td:last-child font { color: #666 !important; font-size: 13px; }
|
|
body > table:nth-of-type(2) a { color: var(--secondary) !important; margin-left: 10px; font-size: 12px; }
|
|
|
|
/* Nav Menu */
|
|
body > table:nth-of-type(3) { background: #343a40 !important; padding: 0 !important; }
|
|
body > table:nth-of-type(3) td { display: flex; gap: 0; padding: 0 !important; }
|
|
|
|
/* Nav Item Logic */
|
|
.nav-item {
|
|
color: rgba(255,255,255,0.7) !important; padding: 12px 20px;
|
|
border-right: 1px solid rgba(255,255,255,0.1); cursor: pointer;
|
|
}
|
|
.nav-item:hover { background: rgba(255,255,255,0.1); color: white !important; text-decoration: none; }
|
|
/* Active State */
|
|
.nav-item.active { background: var(--primary) !important; color: white !important; font-weight: bold; }
|
|
|
|
|
|
/* === 3-Column Grid Layout === */
|
|
.layout-table > tbody > tr {
|
|
display: grid; grid-template-columns: 240px 1fr 240px; gap: 20px; padding: 20px; max-width: 1600px; margin: 0 auto; align-items: start;
|
|
}
|
|
|
|
/* Left: Patient List */
|
|
.layout-table > tbody > tr > td:first-child {
|
|
background: white !important; border-radius: 4px; border: 1px solid var(--border-color) !important; overflow: hidden;
|
|
}
|
|
|
|
/* List Header */
|
|
.layout-table > tbody > tr > td:first-child table tr:first-child td {
|
|
background: #f8f9fa !important; padding: 10px 15px !important; border-bottom: 1px solid var(--border-color) !important;
|
|
}
|
|
.layout-table > tbody > tr > td:first-child table tr:first-child font { color: #333 !important; font-weight: bold; }
|
|
|
|
/* List Item */
|
|
.layout-table > tbody > tr > td:first-child table tr:not(:first-child) td {
|
|
padding: 15px !important; border-bottom: 1px solid #eee !important; cursor: pointer; transition: background 0.2s;
|
|
}
|
|
.layout-table > tbody > tr > td:first-child table tr:not(:first-child) td:hover { background: #f1f7ff !important; }
|
|
|
|
/* VIP Style */
|
|
.layout-table > tbody > tr > td:first-child table tr[bgcolor="#ffffcc"] td {
|
|
background: #fffbe6 !important; border-left: 3px solid var(--warning) !important;
|
|
}
|
|
|
|
/* Hide Ads */
|
|
.layout-table > tbody > tr > td:first-child table[bgcolor="#e0ffff"],
|
|
.layout-table > tbody > tr > td:first-child table[bgcolor="#ffe4e1"] { display: none !important; }
|
|
|
|
/* Center: Workspace */
|
|
.layout-table > tbody > tr > td:nth-child(2) {
|
|
background: transparent !important;
|
|
}
|
|
|
|
/* Patient Info Card */
|
|
.layout-table > tbody > tr > td:nth-child(2) > table:first-child {
|
|
background: white !important; padding: 20px !important; border-radius: 4px; border: 1px solid var(--border-color) !important; margin-bottom: 20px;
|
|
display: grid !important; grid-template-columns: 1fr 1fr; gap: 10px;
|
|
}
|
|
/* Title spans full width */
|
|
.layout-table > tbody > tr > td:nth-child(2) > table:first-child tr:first-child {
|
|
grid-column: 1 / -1; background: transparent !important; border-bottom: 1px solid #eee !important; padding-bottom: 10px !important; margin-bottom: 10px; font-size: 16px;
|
|
}
|
|
/* Info rows grid */
|
|
.layout-table > tbody > tr > td:nth-child(2) > table:first-child tr:not(:first-child) {
|
|
display: flex; gap: 10px; align-items: baseline;
|
|
}
|
|
|
|
/* Order Form */
|
|
.layout-table > tbody > tr > td:nth-child(2) form table {
|
|
background: white !important; border-radius: 4px; border: 1px solid var(--border-color) !important; overflow: hidden;
|
|
}
|
|
/* Form Header */
|
|
.layout-table > tbody > tr > td:nth-child(2) form table tr:first-child {
|
|
background: #f8f9fa !important; padding: 10px 15px !important; border-bottom: 1px solid var(--border-color) !important;
|
|
}
|
|
.layout-table > tbody > tr > td:nth-child(2) form table tr:nth-child(2) {
|
|
display: grid; grid-template-columns: 40px 1.5fr 1fr 2fr 80px; background: #fafafa; border-bottom: 1px solid var(--border-color); padding: 10px !important; font-weight: bold; font-size: 12px; color: #666;
|
|
}
|
|
/* Drug Row */
|
|
.layout-table > tbody > tr > td:nth-child(2) form table tr:not(:first-child):not(:nth-child(2)):not(:last-child) {
|
|
display: grid; grid-template-columns: 40px 1.5fr 1fr 2fr 80px; padding: 10px !important; border-bottom: 1px solid #eee; align-items: center;
|
|
}
|
|
/* Hide distraction rows */
|
|
.layout-table > tbody > tr > td:nth-child(2) form table tr[bgcolor="#ffebcd"] { display: none !important; }
|
|
|
|
/* Footer Buttons */
|
|
.layout-table > tbody > tr > td:nth-child(2) form table tr:last-child td {
|
|
padding: 15px !important; display: flex; gap: 10px; justify-content: flex-end; background: #f8f9fa !important;
|
|
}
|
|
|
|
/* Toast Styles */
|
|
.toast {
|
|
position: fixed; bottom: 30px; left: 50%; transform: translateX(-50%);
|
|
background: #333; color: white; padding: 12px 24px; border-radius: 4px;
|
|
z-index: 2000; opacity: 0; transition: opacity 0.3s; pointer-events: none;
|
|
}
|
|
.toast.show { opacity: 1; }
|
|
|
|
|
|
/* Lab Reports */
|
|
.layout-table > tbody > tr > td:nth-child(2) > table:last-of-type {
|
|
background: white !important; margin-top: 20px; border: 1px solid var(--border-color) !important; border-radius: 4px; padding: 15px !important;
|
|
}
|
|
|
|
/* Hide upgrade notice */
|
|
.layout-table > tbody > tr > td:nth-child(2) > div { display: none !important; }
|
|
|
|
/* Right: Utilities */
|
|
.layout-table > tbody > tr > td:last-child {
|
|
background: white !important; padding: 20px !important; border-radius: 4px; border: 1px solid var(--border-color) !important;
|
|
}
|
|
|
|
/* Right Panel Headers */
|
|
.layout-table > tbody > tr > td:last-child table tr:first-child td {
|
|
background: transparent !important; color: #333 !important; font-weight: bold; border-bottom: 2px solid var(--primary) !important; padding-bottom: 5px !important; margin-bottom: 10px;
|
|
}
|
|
.layout-table > tbody > tr > td:last-child table tr:first-child font { color: #333 !important; }
|
|
|
|
/* Checkbox Spacing */
|
|
.layout-table > tbody > tr > td:last-child table tr:not(:first-child) td { padding: 5px 0 !important; }
|
|
|
|
/* Hide legacy links */
|
|
.layout-table > tbody > tr > td:last-child > p { display: none; }
|
|
.layout-table > tbody > tr > td:last-child > ul { display: none; }
|
|
|
|
/* Footer */
|
|
center:last-of-type {
|
|
margin-top: 40px; border-top: 1px solid var(--border-color); padding: 20px; color: #999; font-size: 12px;
|
|
}
|
|
hr { display: none; }
|
|
|
|
/* === Enhanced Dynamic Styles === */
|
|
.patient-row { cursor: pointer; transition: 0.2s; }
|
|
.patient-row:hover { background-color: #f1f7ff; }
|
|
.patient-row.active { background-color: #e3f2fd !important; border-left: 4px solid var(--primary) !important; }
|
|
|
|
.status-badge { padding: 2px 6px; border-radius: 4px; font-size: 11px; color: white; display:inline-block; margin-left:5px; }
|
|
.badge-signed { background-color: var(--success); }
|
|
.badge-draft { background-color: var(--secondary); }
|
|
.badge-vip { background-color: var(--warning); color: #856404; }
|
|
|
|
/* Modal Styles */
|
|
.modal-overlay {
|
|
position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000;
|
|
display: flex; justify-content: center; align-items: center; opacity: 0; pointer-events: none; transition: 0.2s;
|
|
}
|
|
.modal-overlay.show { opacity: 1; pointer-events: auto; }
|
|
|
|
.modal-box {
|
|
background: white; padding: 20px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2); width: 450px;
|
|
transform: translateY(-20px); transition: 0.3s;
|
|
}
|
|
.modal-overlay.show .modal-box { transform: translateY(0); }
|
|
|
|
.form-group { margin-bottom: 15px; }
|
|
.form-group label { display: block; margin-bottom: 5px; font-weight: bold; color: #333; }
|
|
.form-group input, .form-group select { width: 100%; padding: 8px; box-sizing: border-box; border: 1px solid #ccc; border-radius: 4px; font-size:14px; }
|
|
|
|
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border-width: 0; }
|
|
|
|
</style>
|
|
</head>
|
|
<body bgcolor="#e6e6e6" text="#000000" link="#000080" vlink="#800080" alink="#FF0000">
|
|
|
|
<!-- Add Drug Modal -->
|
|
<div id="drug-modal" class="modal-overlay" role="dialog" aria-modal="true" aria-labelledby="drug-modal-title">
|
|
<div class="modal-box">
|
|
<h3 id="drug-modal-title" style="margin-top:0; color:var(--primary); border-bottom:1px solid #eee; padding-bottom:10px;">New Order</h3>
|
|
<div class="form-group">
|
|
<label for="modal-drug-name">Drug Name</label>
|
|
<select id="modal-drug-name" onchange="updateDrugSpecs()" aria-label="Select drug name">
|
|
<option value="">-- Select --</option>
|
|
<option value="Aspirin">Aspirin Enteric-coated Tablets</option>
|
|
<option value="Atorvastatin">Atorvastatin Calcium Tablets</option>
|
|
<option value="Metoprolol">Metoprolol Succinate</option>
|
|
<option value="Cefradine">Cefradine Capsules</option>
|
|
<option value="Ibuprofen">Ibuprofen Sustained Release</option>
|
|
<option value="Insulin">Human Insulin Injection</option>
|
|
<option value="Omeprazole">Omeprazole Capsules</option>
|
|
<option value="Metformin">Metformin Hydrochloride</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="modal-drug-spec">Spec & Package</label>
|
|
<input type="text" id="modal-drug-spec" readonly style="background:#f5f5f5; color:#666;" aria-label="Drug specification">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="modal-drug-dose">Dosage</label>
|
|
<div style="display:flex; gap:10px;">
|
|
<input type="text" id="modal-drug-dose" placeholder="Dose (e.g. 100mg)" aria-label="Drug dosage">
|
|
<select id="modal-drug-freq" style="width:140px;" aria-label="Frequency">
|
|
<option value="qd">qd (once daily)</option>
|
|
<option value="bid">bid (twice daily)</option>
|
|
<option value="tid">tid (3 times daily)</option>
|
|
<option value="qid">qid (4 times daily)</option>
|
|
<option value="qn">qn (once nightly)</option>
|
|
<option value="prn">prn (as needed)</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="modal-drug-route">Route</label>
|
|
<select id="modal-drug-route" aria-label="Administration route">
|
|
<option value="PO">PO (Oral)</option>
|
|
<option value="IV">IV (Intravenous)</option>
|
|
<option value="IH">IH (Hypodermic)</option>
|
|
<option value="Inhale">Inhale (Inhalation)</option>
|
|
</select>
|
|
</div>
|
|
<div style="text-align:right; margin-top:20px; padding-top:10px; border-top:1px solid #eee;">
|
|
<button type="button" onclick="closeModal()" style="padding:8px 15px; margin-right:10px; background:white; border:1px solid #ccc; border-radius:4px; cursor:pointer;" aria-label="Cancel">Cancel</button>
|
|
<button type="button" onclick="confirmAddDrug()" style="padding:8px 15px; background:var(--primary); color:white; border:none; border-radius:4px; cursor:pointer;" aria-label="Confirm add drug">Confirm</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Confirmation Modal -->
|
|
<div id="confirm-modal" class="modal-overlay" role="dialog" aria-modal="true" aria-labelledby="confirm-title">
|
|
<div class="modal-box" style="width:400px;">
|
|
<h3 id="confirm-title" style="margin-top:0; color:var(--primary); border-bottom:1px solid #eee; padding-bottom:10px;">Confirm Action</h3>
|
|
<div id="confirm-message" style="padding:15px 0; color:#333; line-height:1.6;"></div>
|
|
<div style="text-align:right; margin-top:20px; padding-top:10px; border-top:1px solid #eee;">
|
|
<button type="button" onclick="closeConfirmModal()" style="padding:8px 15px; margin-right:10px; background:white; border:1px solid #ccc; border-radius:4px; cursor:pointer;" aria-label="Cancel">Cancel</button>
|
|
<button type="button" id="confirm-btn" onclick="executeConfirm()" style="padding:8px 15px; background:var(--danger); color:white; border:none; border-radius:4px; cursor:pointer;" aria-label="Confirm">Confirm</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Input Modal -->
|
|
<div id="input-modal" class="modal-overlay" role="dialog" aria-modal="true" aria-labelledby="input-title">
|
|
<div class="modal-box" style="width:400px;">
|
|
<h3 id="input-title" style="margin-top:0; color:var(--primary); border-bottom:1px solid #eee; padding-bottom:10px;">Enter Information</h3>
|
|
<div id="input-message" style="padding:10px 0; color:#333; font-size:13px;"></div>
|
|
<input type="text" id="input-field" style="width:100%; padding:8px; border:1px solid #ccc; border-radius:4px; margin:15px 0; box-sizing:border-box;" aria-label="Input field">
|
|
<div style="text-align:right; margin-top:20px; padding-top:10px; border-top:1px solid #eee;">
|
|
<button type="button" onclick="closeInputModal()" style="padding:8px 15px; margin-right:10px; background:white; border:1px solid #ccc; border-radius:4px; cursor:pointer;" aria-label="Cancel">Cancel</button>
|
|
<button type="button" id="input-btn" onclick="executeInput()" style="padding:8px 15px; background:var(--primary); color:white; border:none; border-radius:4px; cursor:pointer;" aria-label="Submit">Submit</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="toast-container"></div>
|
|
|
|
<table width="100%" border="1" bgcolor="#ffcccc" cellpadding="5" role="region" aria-label="System broadcast">
|
|
<tr>
|
|
<td align="center">
|
|
<span style="color:red;"><strong>Broadcast:</strong> Attention all departments, emergency meeting on insurance cost control at 3 PM in the Admin Building.</span>
|
|
<br>
|
|
<span style="font-size:12px;">Posted: 2025-12-22 08:30</span>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<br>
|
|
|
|
<table width="100%" border="0" bgcolor="#008080" cellpadding="10" role="banner">
|
|
<tr>
|
|
<td width="50%">
|
|
<h1 style="color:white; font-size:20px; margin:0;"><strong>City General Hospital - Doctor Station</strong></h1>
|
|
</td>
|
|
<td width="50%" align="right">
|
|
<span style="color:white;">
|
|
User: <strong>Dr. Li (Attending)</strong> | Dept: Cardiology<br>
|
|
<button onclick="modifyPassword()" style="background:none; border:none; color:yellow; cursor:pointer; text-decoration:underline;" aria-label="Change password">[Change Pwd]</button>
|
|
<button onclick="logout()" style="background:none; border:none; color:white; cursor:pointer; text-decoration:underline;" aria-label="Logout">[Logout]</button>
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<table width="100%" border="1" cellpadding="0" cellspacing="0" bgcolor="#343a40" role="navigation" aria-label="Module navigation">
|
|
<tr>
|
|
<td style="display:flex; padding:0;">
|
|
<button id="nav-btn-clinic" class="nav-item active" onclick="switchModule(this, 'clinic')" role="menuitem" aria-current="page" aria-label="Outpatient module">Outpatient</button>
|
|
<button id="nav-btn-inpatient" class="nav-item" onclick="switchModule(this, 'inpatient')" role="menuitem" aria-label="Inpatient module">Inpatient</button>
|
|
<button id="nav-btn-surgery" class="nav-item" onclick="switchModule(this, 'surgery')" role="menuitem" aria-label="Surgery module">Surgery</button>
|
|
<button id="nav-btn-lab" class="nav-item" onclick="switchModule(this, 'lab')" role="menuitem" aria-label="Lab results module">Lab Results</button>
|
|
<button id="nav-btn-pharmacy" class="nav-item" onclick="switchModule(this, 'pharmacy')" role="menuitem" aria-label="Pharmacy module">Pharmacy</button>
|
|
<button id="nav-btn-admin" class="nav-item" onclick="switchModule(this, 'admin')" role="menuitem" aria-label="Order admin module">Order Admin</button>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<br>
|
|
|
|
<!-- Module: Clinic (Doctor Station) -->
|
|
<div id="module-clinic" class="main-module">
|
|
<table class="layout-table" width="100%" border="0" cellspacing="5" cellpadding="0">
|
|
<tr>
|
|
<td width="250" valign="top" bgcolor="#f0f0f0" style="height: 100%;">
|
|
<br>
|
|
<table width="100%" border="1" cellpadding="0" style="background:white; border-radius:4px; overflow:hidden; border-collapse:collapse;">
|
|
<tr><td bgcolor="#008080" style="padding:10px;"><font color="white"><b>Waiting List (<span id="patient-count">0</span>)</b></font></td></tr>
|
|
<tbody id="patient-list-container">
|
|
<!-- Dynamic Content -->
|
|
</tbody>
|
|
</table>
|
|
|
|
<div style="margin-top:20px; padding:15px; background:#fff3cd; border:1px solid #ffeeba; border-radius:4px; color:#856404; font-size:12px;">
|
|
<b>Shift Note:</b><br>
|
|
Emergency observation beds are full, please coordinate transfers.
|
|
</div>
|
|
</td>
|
|
|
|
<td valign="top">
|
|
|
|
<!-- Patient Info Header -->
|
|
<table width="100%" border="1" cellpadding="5" bgcolor="#ffffff" id="patient-info-card" style="margin-bottom:20px;">
|
|
<tr><td align="center" style="padding:40px; color:#999;">Loading patient info...</td></tr>
|
|
</table>
|
|
|
|
<!-- Order Entry Form -->
|
|
<div id="order-panel" style="display:none;">
|
|
<form onsubmit="event.preventDefault();">
|
|
<table width="100%" border="1" cellpadding="3" cellspacing="0">
|
|
<tr>
|
|
<td colspan="6" bgcolor="#dddddd" style="display:flex; justify-content:space-between; align-items:center;">
|
|
<b>Long-term Order Entry</b>
|
|
<span style="font-size:12px; color:#666;">Last refresh: <span id="last-sync-time">Just now</span></span>
|
|
</td>
|
|
</tr>
|
|
<thead style="background:#fafafa; color:#666; font-size:12px; font-weight:bold;">
|
|
<tr style="display:grid; grid-template-columns: 40px 1.5fr 1fr 2fr 100px 80px; padding:10px; border-bottom:1px solid #eee;">
|
|
<td>Sel</td>
|
|
<td>Drug Name</td>
|
|
<td>Spec</td>
|
|
<td>Dosage</td>
|
|
<td>Status</td>
|
|
<td>Action</td>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="order-list-body">
|
|
<!-- Dynamic Orders -->
|
|
</tbody>
|
|
|
|
<tr>
|
|
<td colspan="6" align="right" style="padding:15px; border-top:1px solid #eee; background:#f8f9fa;">
|
|
<button type="button" onclick="openAddDrugModal()" style="padding:8px 16px; background:white; border:1px solid #ced4da; color:var(--primary); border-radius:4px; cursor:pointer; font-weight:500;">+ Add Drug</button>
|
|
<button type="button" onclick="signOrder()" style="padding:8px 16px; background:var(--primary); color:white; border:none; border-radius:4px; cursor:pointer; margin-left:10px; font-weight:500;">Sign Orders</button>
|
|
<button type="button" onclick="voidOrder()" style="padding:8px 16px; background:var(--danger); color:white; border:none; border-radius:4px; cursor:pointer; margin-left:5px; font-weight:500;">Void Item</button>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</form>
|
|
</div>
|
|
<br>
|
|
|
|
<!-- Labs -->
|
|
<table width="100%" border="1" cellpadding="3" id="lab-panel" style="display:none; background:white; border-radius:4px;">
|
|
<tr><td bgcolor="#dddddd"><b>Lab / Exam Reports</b></td></tr>
|
|
<tr>
|
|
<td>
|
|
<ul style="padding-left:20px; margin:10px 0;" id="lab-list">
|
|
<!-- Dynamic Labs -->
|
|
</ul>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
|
|
<td width="200" valign="top" bgcolor="#f0f0f0">
|
|
<br>
|
|
<table width="100%" border="1" cellpadding="3">
|
|
<tr><td bgcolor="#008080"><font color="white"><b>Clinical Pathway</b></font></td></tr>
|
|
<tbody id="clinical-path-list">
|
|
<!-- Dynamic -->
|
|
</tbody>
|
|
</table>
|
|
<br>
|
|
|
|
<table width="100%" border="1" cellpadding="3">
|
|
<tr><td bgcolor="#008080"><font color="white"><b>Shift Roster</b></font></td></tr>
|
|
<tr><td>Mon: Dr. Zhang (Day)</td></tr>
|
|
<tr><td>Mon: Dr. Wang (Night)</td></tr>
|
|
<tr><td>Tue: Dr. Li (Day)</td></tr>
|
|
<tr><td>Tue: Dr. Zhao (Night)</td></tr>
|
|
</table>
|
|
<br>
|
|
|
|
<p><b>Quick Links:</b></p>
|
|
<ul>
|
|
<li><a href="javascript:void(0)" onclick="openOA()">OA System</a></li>
|
|
<li><a href="javascript:void(0)" onclick="openLibrary()">Medical Library</a></li>
|
|
</ul>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Module: Inpatient -->
|
|
<div id="module-inpatient" class="main-module" style="display:none; padding:20px;">
|
|
<div style="background:white; padding:30px; border-radius:8px; text-align:center; border:1px solid #ddd;">
|
|
<h2 style="color:#007bff;">Inpatient Bed Management</h2>
|
|
<p style="color:#666;">Free Beds: 12 | ICU: Full</p>
|
|
<div style="margin-top:20px; display:grid; grid-template-columns:repeat(auto-fill, minmax(100px, 1fr)); gap:10px;">
|
|
<div style="background:#d4edda; padding:10px; border-radius:4px; color:#155724;">Bed 01 (Free)</div>
|
|
<div style="background:#f8d7da; padding:10px; border-radius:4px; color:#721c24;">Bed 02 (Occupied)</div>
|
|
<div style="background:#f8d7da; padding:10px; border-radius:4px; color:#721c24;">Bed 03 (Occupied)</div>
|
|
<div style="background:#d4edda; padding:10px; border-radius:4px; color:#155724;">Bed 04 (Free)</div>
|
|
<div style="background:#fff3cd; padding:10px; border-radius:4px; color:#856404;">Bed 05 (Reserved)</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Module: Surgery -->
|
|
<div id="module-surgery" class="main-module" style="display:none; padding:20px;">
|
|
<div style="background:white; padding:30px; border-radius:8px; border:1px solid #ddd;">
|
|
<h2 style="color:#007bff; border-bottom:1px solid #eee; padding-bottom:10px;">Surgery Schedule (2025-12-23)</h2>
|
|
<table width="100%" border="0" cellpadding="10">
|
|
<tr bgcolor="#f8f9fa" style="font-weight:bold;"><td>Time</td><td>OR</td><td>Patient</td><td>Procedure</td><td>Surgeon</td></tr>
|
|
<tr><td>08:00</td><td>OR-01</td><td>Zhang San</td><td>CABG</td><td>Dr. Liu</td></tr>
|
|
<tr><td>09:30</td><td>OR-03</td><td>Unknown</td><td>Appendectomy</td><td>Dr. Wang</td></tr>
|
|
<tr><td>13:00</td><td>OR-02</td><td>Li Si</td><td>Cataract Phaco</td><td>Dr. Zhang</td></tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Module: Lab -->
|
|
<div id="module-lab" class="main-module" style="display:none; padding:20px;">
|
|
<div style="background:white; padding:40px; border-radius:8px; text-align:center; border:1px solid #ddd;">
|
|
<h2 style="color:#17a2b8;">LIS Report Search</h2>
|
|
<input id="lab-search-input" type="text" placeholder="Enter Patient ID/Name..." style="padding:10px; width:300px; border:1px solid #ccc; border-radius:4px;">
|
|
<button onclick="searchLabReport()" style="padding:10px 20px; background:#17a2b8; color:white; border:none; border-radius:4px; cursor:pointer;">Search</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Module: Pharmacy -->
|
|
<div id="module-pharmacy" class="main-module" style="display:none; padding:20px;">
|
|
<div style="background:white; padding:30px; border-radius:8px; border:1px solid #ddd;">
|
|
<h2 style="color:#28a745;">Pharmacy Stock Alert</h2>
|
|
<table width="100%" border="0" cellpadding="8">
|
|
<tr style="border-bottom:2px solid #eee;"><td>Drug Name</td><td>Stock</td><td>Status</td><td>Action</td></tr>
|
|
<tr><td>Aspirin</td><td>12,000</td><td style="color:green">Sufficient</td><td>-</td></tr>
|
|
<tr><td>Insulin Inj</td><td>50</td><td style="color:red; font-weight:bold;">Low Stock</td><td><a id="btn-restock-insulin" href="javascript:void(0)" onclick="restockDrug('Insulin')">Request Restock</a></td></tr>
|
|
<tr><td>Cefradine</td><td>340</td><td style="color:orange">Normal</td><td>-</td></tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Module: Admin -->
|
|
<div id="module-admin" class="main-module" style="display:none; padding:20px;">
|
|
<div style="background:white; padding:30px; border-radius:8px; border:1px solid #ddd;">
|
|
<h2 style="color:#6c757d;">System Admin & Order Audit</h2>
|
|
<div id="admin-task-area">
|
|
<p>You have <b>3</b> orders waiting for approval.</p>
|
|
<button onclick="batchApproveOrders()" style="padding:8px 15px; background:#007bff; color:white; border:none; border-radius:4px; cursor:pointer;">Batch Approve</button>
|
|
<button onclick="batchRejectOrders()" style="padding:8px 15px; background:#dc3545; color:white; border:none; border-radius:4px; cursor:pointer;">Batch Reject</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<hr>
|
|
|
|
<center>
|
|
<font size="1">
|
|
Tech Support: Health Info Center | Tel: 8888-1234<br>
|
|
Copyright © 2025 City General Hospital
|
|
</font>
|
|
</center>
|
|
|
|
<script>
|
|
// -------------------------------------------------------------------------
|
|
// Mock Data
|
|
// -------------------------------------------------------------------------
|
|
const DRUG_DICT = {
|
|
'Aspirin': { name: 'Aspirin Enteric-coated Tablets', spec: '100mg*30 tabs' },
|
|
'Atorvastatin': { name: 'Atorvastatin Calcium Tablets', spec: '20mg*7 tabs' },
|
|
'Metoprolol': { name: 'Metoprolol Succinate', spec: '47.5mg*7 tabs' },
|
|
'Cefradine': { name: 'Cefradine Capsules', spec: '0.25g*24 caps' },
|
|
'Ibuprofen': { name: 'Ibuprofen Sustained Release', spec: '0.3g*10 caps' },
|
|
'Insulin': { name: 'Human Insulin Injection', spec: '3ml:300IU' },
|
|
'Omeprazole': { name: 'Omeprazole Capsules', spec: '20mg*14 caps' },
|
|
'Metformin': { name: 'Metformin Hydrochloride', spec: '0.5g*20 tabs' }
|
|
};
|
|
|
|
let PATIENTS = [
|
|
{
|
|
id: 101, name: "Zhang San", gender: "M", age: 45, type: "common",
|
|
complaint: "Chest tightness for 3 days",
|
|
diagnosis: "Coronary Heart Disease; Angina",
|
|
tags: ["Chest Pain", "Hypertension"],
|
|
allergies: ["Penicillin"],
|
|
insurance: "Provincial Insurance",
|
|
vitals: { bp: "140/90", hr: 88, t: 36.5 },
|
|
orders: [
|
|
{ id: 1, drug: "Aspirin", dose: "100mg", freq: "qd", route: "PO", status: "signed" },
|
|
{ id: 2, drug: "Atorvastatin", dose: "20mg", freq: "qn", route: "PO", status: "signed" }
|
|
],
|
|
labs: [
|
|
{ date: "2025-12-20", name: "ECG", result: "Sinus rhythm, slight ST depression", link: true},
|
|
{ date: "2025-12-20", name: "Echo", result: "Diastolic dysfunction, EF 55%", link: true},
|
|
{ date: "2025-12-19", name: "CBC", result: "WBC 6.5, Hb 135, PLT 210", link: false}
|
|
],
|
|
pathways: [
|
|
{ name: "Admission Education", checked: true },
|
|
{ name: "Sign Consent Form", checked: true },
|
|
{ name: "Physician Ward Round", checked: false },
|
|
{ name: "Pre-op Discussion", checked: false }
|
|
]
|
|
},
|
|
{
|
|
id: 102, name: "Li Si", gender: "F", age: 62, type: "common",
|
|
complaint: "Dizziness and nausea for 1 week",
|
|
diagnosis: "Hypertension (Grade 3); Cervical Spondylosis",
|
|
tags: ["Dizziness"],
|
|
allergies: ["None"],
|
|
insurance: "Rural Cooperative Medical Scheme",
|
|
vitals: { bp: "160/100", hr: 76, t: 36.8 },
|
|
orders: [
|
|
{ id: 3, drug: "Metoprolol", dose: "23.75mg", freq: "qd", route: "PO", status: "draft" }
|
|
],
|
|
labs: [
|
|
{ date: "2025-12-21", name: "Head CT", result: "No significant abnormality", link: true},
|
|
{ date: "2025-12-21", name: "Biochemistry", result: "TG 2.3mmol/L (High)", link: false}
|
|
],
|
|
pathways: [
|
|
{ name: "Admission Education", checked: true },
|
|
{ name: "BP Monitoring (Q4H)", checked: true },
|
|
{ name: "Fundus Exam", checked: false }
|
|
]
|
|
},
|
|
{
|
|
id: 103, name: "Mr. Wang", gender: "M", age: 50, type: "vip",
|
|
complaint: "Consultation on annual checkup report",
|
|
diagnosis: "Fatty Liver; Hyperuricemia",
|
|
tags: ["VIP", "Checkup"],
|
|
allergies: ["Sulfonamides"],
|
|
insurance: "Self-pay",
|
|
vitals: { bp: "130/85", hr: 80, t: 36.6 },
|
|
orders: [], // Empty initially
|
|
labs: [
|
|
{ date: "2025-12-22", name: "Liver Function", result: "ALT 55, AST 40", link: false},
|
|
{ date: "2025-12-22", name: "Abdominal Ultrasound", result: "Moderate fatty liver", link: true}
|
|
]
|
|
},
|
|
{
|
|
id: 104, name: "Zhao Liu", gender: "M", age: 28, type: "common",
|
|
complaint: "Acute stomach pain for 2 hours",
|
|
diagnosis: "Acute Gastritis",
|
|
tags: ["Emergency"],
|
|
allergies: ["None"],
|
|
insurance: "City Insurance",
|
|
vitals: { bp: "120/75", hr: 92, t: 37.2 },
|
|
orders: [
|
|
{ id: 4, drug: "Omeprazole", dose: "20mg", freq: "qd", route: "PO", status: "signed" }
|
|
],
|
|
labs: []
|
|
}
|
|
];
|
|
|
|
let currentPatientId = null;
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Utils
|
|
// -------------------------------------------------------------------------
|
|
function showToast(msg, type = 'info') {
|
|
const container = document.getElementById('toast-container');
|
|
if(!container) return; // safety
|
|
|
|
const toast = document.createElement('div');
|
|
toast.className = 'toast';
|
|
toast.style.background = type === 'error' ? 'rgba(220, 53, 69, 0.9)' : 'rgba(0, 0, 0, 0.8)';
|
|
toast.innerText = msg;
|
|
container.appendChild(toast);
|
|
|
|
// Trigger reflow
|
|
void toast.offsetWidth;
|
|
toast.classList.add('show');
|
|
|
|
setTimeout(() => {
|
|
toast.classList.remove('show');
|
|
setTimeout(() => toast.remove(), 300);
|
|
}, 3000);
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Custom Modal Functions
|
|
// -------------------------------------------------------------------------
|
|
let confirmCallback = null;
|
|
let inputCallback = null;
|
|
|
|
function showConfirm(message, callback) {
|
|
confirmCallback = callback;
|
|
document.getElementById('confirm-message').innerText = message;
|
|
document.getElementById('confirm-modal').classList.add('show');
|
|
}
|
|
|
|
function closeConfirmModal() {
|
|
document.getElementById('confirm-modal').classList.remove('show');
|
|
confirmCallback = null;
|
|
}
|
|
|
|
function executeConfirm() {
|
|
if(confirmCallback) {
|
|
confirmCallback();
|
|
}
|
|
closeConfirmModal();
|
|
}
|
|
|
|
function showInput(message, callback) {
|
|
inputCallback = callback;
|
|
document.getElementById('input-message').innerText = message;
|
|
document.getElementById('input-field').value = '';
|
|
document.getElementById('input-modal').classList.add('show');
|
|
document.getElementById('input-field').focus();
|
|
}
|
|
|
|
function closeInputModal() {
|
|
document.getElementById('input-modal').classList.remove('show');
|
|
inputCallback = null;
|
|
}
|
|
|
|
function executeInput() {
|
|
const value = document.getElementById('input-field').value;
|
|
if(inputCallback) {
|
|
inputCallback(value);
|
|
}
|
|
closeInputModal();
|
|
}
|
|
|
|
// Allow Enter key to submit input modal
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const inputField = document.getElementById('input-field');
|
|
if(inputField) {
|
|
inputField.addEventListener('keypress', (e) => {
|
|
if(e.key === 'Enter' && document.getElementById('input-modal').classList.contains('show')) {
|
|
executeInput();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
function switchModule(el, moduleName) {
|
|
// Toggle active state in Nav
|
|
document.querySelectorAll('.nav-item').forEach(item => item.classList.remove('active'));
|
|
if (el) el.classList.add('active');
|
|
|
|
// Hide all modules
|
|
document.querySelectorAll('.main-module').forEach(m => m.style.display = 'none');
|
|
|
|
// Show target module
|
|
const target = document.getElementById(`module-${moduleName}`);
|
|
if(target) {
|
|
target.style.display = 'block';
|
|
showToast(`Switched to [${moduleName === 'clinic' ? 'Outpatient' :
|
|
moduleName === 'inpatient' ? 'Inpatient' :
|
|
moduleName === 'surgery' ? 'Surgery' :
|
|
moduleName === 'lab' ? 'Lab Results' :
|
|
moduleName === 'pharmacy' ? 'Pharmacy' : 'Order Admin'}]`);
|
|
} else {
|
|
// Fallback
|
|
document.getElementById('module-clinic').style.display = 'block';
|
|
showToast(`Module [${moduleName}] is under maintenance`, "warning");
|
|
}
|
|
}
|
|
|
|
function logout() {
|
|
showConfirm("Are you sure you want to logout Current User (Dr. Zhang)?", () => {
|
|
showToast("Logging out...", "info");
|
|
setTimeout(() => location.reload(), 1000);
|
|
});
|
|
}
|
|
|
|
function openOA() { showToast("Opening OA System..."); }
|
|
function openLibrary() { showToast("Connecting to Medical Knowledge Base..."); }
|
|
function modifyPassword() { showToast("Please contact IT dept to reset password"); }
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Core Logic
|
|
// -------------------------------------------------------------------------
|
|
|
|
// Initialize
|
|
window.onload = function() {
|
|
document.getElementById('patient-count').innerText = PATIENTS.length;
|
|
renderPatientList();
|
|
// Automatically select first patient
|
|
if(PATIENTS.length > 0) {
|
|
selectPatient(PATIENTS[0].id);
|
|
}
|
|
|
|
// Update time
|
|
document.getElementById('last-sync-time').innerText = new Date().toLocaleTimeString();
|
|
};
|
|
|
|
function renderPatientList() {
|
|
const tbody = document.getElementById('patient-list-container');
|
|
tbody.innerHTML = '';
|
|
|
|
PATIENTS.forEach(p => {
|
|
const tr = document.createElement('tr');
|
|
tr.id = `patient-row-${p.id}`;
|
|
tr.className = `patient-row ${currentPatientId === p.id ? 'active' : ''}`;
|
|
tr.onclick = () => selectPatient(p.id);
|
|
|
|
// Background color for VIP or special rows based on type/logic
|
|
let rowStyle = '';
|
|
if (p.type === 'vip') rowStyle = 'background-color:#fffbe6;';
|
|
|
|
// Name display formatting
|
|
let nameHtml = `<b>${p.id}. ${p.name} (${p.gender}, ${p.age}y)</b>`;
|
|
if (p.type === 'vip') nameHtml = `<font color="red"><b>VIP. ${p.name} (${p.gender}, ${p.age}y)</b></font>`;
|
|
|
|
const actionsHtml = `<div style="margin-top:5px;">
|
|
<a href="javascript:void(0)" style="font-size:12px;">[Consult]</a>
|
|
<a href="javascript:void(0)" style="font-size:12px; color:#999; margin-left:5px;">[Skip]</a>
|
|
</div>`;
|
|
|
|
tr.innerHTML = `
|
|
<td style="padding:15px; border-bottom:1px solid #eee; ${rowStyle}">
|
|
${nameHtml}<br>
|
|
<font size="2" color="#666">C/C: ${p.complaint}</font><br>
|
|
${actionsHtml}
|
|
</td>
|
|
`;
|
|
tbody.appendChild(tr);
|
|
});
|
|
}
|
|
|
|
function selectPatient(id) {
|
|
currentPatientId = id;
|
|
renderPatientList(); // Re-render to update highlight
|
|
|
|
const p = PATIENTS.find(x => x.id === id);
|
|
if(!p) return;
|
|
|
|
// Render Top Info
|
|
const infoCard = document.getElementById('patient-info-card');
|
|
const allergyHtml = p.allergies.includes("None") ? 'None' : `<font color="red" style="background:#ffe3e3; padding:2px 5px; border-radius:3px;">${p.allergies.join(',')}</font>`;
|
|
|
|
infoCard.innerHTML = `
|
|
<tr>
|
|
<td colspan="4" bgcolor="#cccccc"><b>Patient: ${p.name} (ID: 2025${p.id})</b> - <font color="#333">${p.diagnosis}</font></td>
|
|
</tr>
|
|
<tr>
|
|
<td width="15%"><b>Allergies:</b></td>
|
|
<td width="35%">${allergyHtml}</td>
|
|
<td width="15%"><b>Insurance:</b></td>
|
|
<td width="35%">${p.insurance}</td>
|
|
</tr>
|
|
<tr>
|
|
<td><b>Vitals:</b></td>
|
|
<td colspan="3">BP: ${p.vitals.bp} mmHg, HR: ${p.vitals.hr}, T: ${p.vitals.t}°C</td>
|
|
</tr>
|
|
`;
|
|
|
|
// Render Labs
|
|
const labList = document.getElementById('lab-list');
|
|
labList.innerHTML = '';
|
|
if (p.labs.length === 0) {
|
|
labList.innerHTML = '<li style="color:#999;font-style:italic;">No lab results</li>';
|
|
} else {
|
|
p.labs.forEach(lab => {
|
|
const safeLabName = lab.name.replace(/[^a-zA-Z0-9]/g, '-');
|
|
const linkPart = lab.link ? ` <a id="btn-view-lab-${safeLabName}" href="javascript:void(0)" onclick="viewLabImage('${lab.name}')" aria-label="View image for ${lab.name}">[View Image]</a>` : '';
|
|
const li = document.createElement('li');
|
|
li.style.marginBottom = '5px';
|
|
li.innerHTML = `${lab.date}: ${lab.name} - ${lab.result} ${linkPart}`;
|
|
labList.appendChild(li);
|
|
});
|
|
}
|
|
|
|
// Show Panels
|
|
document.getElementById('order-panel').style.display = 'block';
|
|
document.getElementById('lab-panel').style.display = 'block';
|
|
|
|
renderOrders();
|
|
renderClinicalPaths();
|
|
}
|
|
|
|
function renderClinicalPaths() {
|
|
const p = PATIENTS.find(x => x.id === currentPatientId);
|
|
const container = document.getElementById('clinical-path-list');
|
|
if(!container) return;
|
|
|
|
container.innerHTML = '';
|
|
if(!p.pathways || p.pathways.length === 0) {
|
|
container.innerHTML = '<tr><td colspan="2" style="color:#999; text-align:center;">No clinical pathway tasks</td></tr>';
|
|
return;
|
|
}
|
|
|
|
p.pathways.forEach((path, idx) => {
|
|
const tr = document.createElement('tr');
|
|
const isChecked = path.checked ? 'checked' : '';
|
|
const statusColor = path.checked ? 'green' : '#666';
|
|
|
|
tr.innerHTML = `
|
|
<td width="30" align="center">
|
|
<input type="checkbox" ${isChecked} disabled>
|
|
</td>
|
|
<td style="color:${statusColor};">${path.name}</td>
|
|
`;
|
|
container.appendChild(tr);
|
|
});
|
|
}
|
|
|
|
function renderOrders() {
|
|
const p = PATIENTS.find(x => x.id === currentPatientId);
|
|
const tbody = document.getElementById('order-list-body');
|
|
tbody.innerHTML = '';
|
|
|
|
if(p.orders.length === 0) {
|
|
tbody.innerHTML = '<tr><td colspan="6" align="center" style="padding:20px; color:#999;">No orders yet. Click "Add Drug" to start.</td></tr>';
|
|
return;
|
|
}
|
|
|
|
p.orders.forEach(order => {
|
|
const drugInfo = DRUG_DICT[order.drug] || { name: order.drug, spec: 'Unknown' };
|
|
|
|
let statusBadge = '';
|
|
let actionHtml = '';
|
|
|
|
if (order.status === 'signed') {
|
|
statusBadge = '<span class="status-badge badge-signed">Signed</span>';
|
|
actionHtml = '<span style="color:#ccc; font-size:12px;">Locked</span>'; // Simplify logic
|
|
} else {
|
|
statusBadge = '<span class="status-badge badge-draft">Draft</span>';
|
|
actionHtml = `<a href="javascript:void(0)" style="color:#dc3545;" onclick="removeOrder(${order.id})">Delete</a>`;
|
|
}
|
|
|
|
const tr = document.createElement('tr');
|
|
// Use grid style matching header
|
|
tr.style.display = 'grid';
|
|
tr.style.gridTemplateColumns = '40px 1.5fr 1fr 2fr 100px 80px';
|
|
tr.style.padding = '10px';
|
|
tr.style.borderBottom = '1px solid #eee';
|
|
tr.style.alignItems = 'center';
|
|
|
|
tr.innerHTML = `
|
|
<td align="center"><input type="checkbox" name="order-select" value="${order.id}"></td>
|
|
<td>${drugInfo.name}</td>
|
|
<td>${drugInfo.spec}</td>
|
|
<td>
|
|
${order.status === 'draft' ?
|
|
`<input type="text" value="${order.dose}" style="width:50px; border:1px solid #ddd; padding:2px;"> <span style="font-size:12px;">${order.freq}</span>` :
|
|
`<b>${order.dose}</b> ${order.freq} ${order.route}`
|
|
}
|
|
</td>
|
|
<td>${statusBadge}</td>
|
|
<td>${actionHtml}</td>
|
|
`;
|
|
tbody.appendChild(tr);
|
|
});
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Actions
|
|
// -------------------------------------------------------------------------
|
|
function openAddDrugModal() {
|
|
document.getElementById('drug-modal').classList.add('show');
|
|
// Reset form
|
|
document.getElementById('modal-drug-spec').value = '';
|
|
document.getElementById('modal-drug-name').value = '';
|
|
document.getElementById('modal-drug-dose').value = '';
|
|
}
|
|
|
|
function closeModal() {
|
|
document.getElementById('drug-modal').classList.remove('show');
|
|
}
|
|
|
|
function updateDrugSpecs() {
|
|
const key = document.getElementById('modal-drug-name').value;
|
|
const specInput = document.getElementById('modal-drug-spec');
|
|
if(key && DRUG_DICT[key]) {
|
|
specInput.value = DRUG_DICT[key].spec;
|
|
} else {
|
|
specInput.value = '';
|
|
}
|
|
}
|
|
|
|
function confirmAddDrug() {
|
|
const key = document.getElementById('modal-drug-name').value;
|
|
const dose = document.getElementById('modal-drug-dose').value;
|
|
|
|
if(!key || !dose) {
|
|
showToast("Please complete drug and dosage info", "error");
|
|
return;
|
|
}
|
|
|
|
const freq = document.getElementById('modal-drug-freq').value;
|
|
const route = document.getElementById('modal-drug-route').value;
|
|
|
|
const p = PATIENTS.find(x => x.id === currentPatientId);
|
|
|
|
// Add new order
|
|
p.orders.push({
|
|
id: Date.now(),
|
|
drug: key,
|
|
dose: dose,
|
|
freq: freq,
|
|
route: route,
|
|
status: 'draft'
|
|
});
|
|
|
|
closeModal();
|
|
renderOrders();
|
|
showToast("Order Created (Draft)", "success");
|
|
}
|
|
|
|
function removeOrder(orderId) {
|
|
showConfirm("Are you sure you want to delete this order?", () => {
|
|
const p = PATIENTS.find(x => x.id === currentPatientId);
|
|
p.orders = p.orders.filter(o => o.id !== orderId);
|
|
renderOrders();
|
|
showToast("Order Deleted");
|
|
});
|
|
}
|
|
|
|
function signOrder() {
|
|
const p = PATIENTS.find(x => x.id === currentPatientId);
|
|
const drafts = p.orders.filter(o => o.status === 'draft');
|
|
|
|
if (drafts.length === 0) {
|
|
showToast("No draft orders to sign.", "warning");
|
|
return;
|
|
}
|
|
|
|
showInput(`Signing ${drafts.length} orders for patient [${p.name}].\n\nPlease enter E-Signature PIN:`, (pin) => {
|
|
if(pin) {
|
|
drafts.forEach(o => o.status = 'signed');
|
|
showToast("Orders Signed & Sent to Pharmacy.", "success");
|
|
renderOrders();
|
|
}
|
|
});
|
|
}
|
|
|
|
function voidOrder() {
|
|
showToast("Select signed orders to void, then submit for Medical Director approval.", "warning");
|
|
}
|
|
|
|
function viewLabImage(name) {
|
|
showToast(`Retrieving PACS Image: ${name}...`, "info");
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Module Logic (New)
|
|
// -------------------------------------------------------------------------
|
|
function searchLabReport() {
|
|
const val = document.getElementById('lab-search-input').value;
|
|
if(!val) {
|
|
showToast("Please enter search keywords", "warning");
|
|
return;
|
|
}
|
|
showToast(`Searching LIS for [${val}]...`, "info");
|
|
setTimeout(() => {
|
|
showToast("No records found (Mock)", "error");
|
|
}, 1500);
|
|
}
|
|
|
|
function restockDrug(drugName) {
|
|
showConfirm(`Send restock request for [${drugName}]?`, () => {
|
|
showToast("Restock request sent to Supply Chain", "success");
|
|
});
|
|
}
|
|
|
|
function batchApproveOrders() {
|
|
showConfirm("Batch approve these 3 orders?", () => {
|
|
showToast("Batch Approval Complete", "success");
|
|
document.getElementById('admin-task-area').innerHTML = '<p style="color:green;">All pending tasks completed.</p>';
|
|
});
|
|
}
|
|
|
|
function batchRejectOrders() {
|
|
showInput("Enter Rejection Reason:", (reason) => {
|
|
if(reason) {
|
|
showToast(`3 Orders Rejected. Reason: ${reason}`, "info");
|
|
document.getElementById('admin-task-area').innerHTML = '<p style="color:green;">All pending tasks completed.</p>';
|
|
}
|
|
});
|
|
}
|
|
|
|
console.log("HIS System Loaded. Interface modernized.");
|
|
</script>
|
|
|
|
</body>
|
|
</html> |