Files
mt-drugs/frontend/index.html
T

685 lines
36 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Drug Inventory System</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<!-- Toast Notification Container -->
<div id="toastContainer" class="toast-container"></div>
<!-- Login Page -->
<div id="loginPage" class="login-page">
<div class="login-container">
<h1>MTAR Drug Inventory System</h1>
<form id="loginForm" class="login-form">
<h2>Login</h2>
<div class="form-group">
<label for="loginUsername">Username</label>
<input type="text" id="loginUsername" required>
</div>
<div class="form-group">
<label for="loginPassword">Password</label>
<input type="password" id="loginPassword" required>
</div>
<button type="submit" class="btn btn-primary">Login</button>
<p class="login-info">Contact an administrator to create an account</p>
</form>
<div id="loginError" class="error-message" style="display: none;"></div>
</div>
</div>
<!-- Main App (hidden until logged in) -->
<div id="mainApp" class="main-app" style="display: none;">
<div class="container">
<header>
<div class="header-top">
<h1>MTAR Drug Inventory System</h1>
<div class="user-menu">
<span id="currentUser">User</span>
<button id="userMenuBtn" class="btn btn-small"></button>
<div id="userDropdown" class="user-dropdown" style="display: none;">
<button id="changePasswordBtn" class="dropdown-item">🔑 Change Password</button>
<button id="adminBtn" class="dropdown-item" style="display: none;">👤 Admin</button>
<button id="locationsBtn" class="dropdown-item" style="display: none;">📍 Storage Locations</button>
<button id="reportsBtn" class="dropdown-item" style="display: none;">📊 Reports</button>
<button id="logoutBtn" class="dropdown-item">🚪 Logout</button>
</div>
</div>
</div>
</header>
<main>
<!-- Drug List Section -->
<section id="listSection" class="list-section">
<div class="section-header">
<h2>Current Inventory</h2>
<div class="inventory-toolbar">
<div class="header-actions">
<button id="printNotesBtn" class="btn btn-primary btn-small">📝 Print Notes</button>
<button id="receiveDeliveryBtn" class="btn btn-success btn-small">📦 Receive Delivery</button>
<button id="addDrugBtn" class="btn btn-primary btn-small"> Add Drug</button>
</div>
<div class="toolbar-search">
<input type="text" id="drugSearch" placeholder="Search drugs by name..." class="search-input">
</div>
<div class="filters">
<button id="showAllBtn" class="filter-btn active">All</button>
<button id="showLowStockBtn" class="filter-btn">Low Stock Only</button>
<select id="locationFilterSelect" class="filter-select" aria-label="Filter by location">
<option value="">All Locations</option>
</select>
</div>
</div>
</div>
<div id="drugsList" class="drugs-list">
<p class="loading">Loading drugs...</p>
</div>
</section>
</main>
<footer>
<p>Many Tears Confidential</p>
</footer>
</div>
<!-- Edit Drug Modal -->
<div id="editModal" class="modal">
<div class="modal-content">
<span class="close">&times;</span>
<h2>Edit Drug</h2>
<form id="editForm">
<input type="hidden" id="editDrugId">
<div class="form-group">
<label for="editDrugName">Drug Name *</label>
<input type="text" id="editDrugName" required>
</div>
<div class="form-group">
<label for="editDrugDescription">Description</label>
<input type="text" id="editDrugDescription">
</div>
<div class="form-group">
<label>
<input type="checkbox" id="editDrugIsControlled">
This is a Controlled Substance
</label>
</div>
<button type="submit" class="btn btn-primary">Save Changes</button>
<button type="button" class="btn btn-secondary" id="cancelEditBtn">Cancel</button>
</div>
</form>
</div>
</div>
<!-- Add Drug Modal -->
<div id="addModal" class="modal">
<div class="modal-content">
<span class="close">&times;</span>
<h2>Add New Drug</h2>
<form id="drugForm">
<div class="form-group">
<label for="drugName">Drug Name *</label>
<input type="text" id="drugName" required>
</div>
<div class="form-group">
<label for="drugDescription">Description</label>
<input type="text" id="drugDescription">
</div>
<div class="form-group">
<label>
<input type="checkbox" id="drugIsControlled">
This is a Controlled Substance
</label>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Add Drug</button>
<button type="button" class="btn btn-secondary" id="cancelAddBtn">Cancel</button>
</div>
</form>
</div>
</div>
<!-- Dispense Drug Modal -->
<div id="dispenseModal" class="modal">
<div class="modal-content modal-large dispense-modal-content">
<span class="close">&times;</span>
<h2>Dispense Drug</h2>
<form id="dispenseForm" novalidate>
<div class="form-group">
<label for="dispenseDrugSelect">Drug Variant *</label>
<select id="dispenseDrugSelect" onchange="updateBatchInfo()">
<option value="">-- Select a drug variant --</option>
</select>
</div>
<div class="form-group">
<label>Dispense Mode *</label>
<div style="display: flex; gap: 18px; align-items: center; flex-wrap: wrap; margin-top: 6px;">
<label style="display: inline-flex; align-items: center; gap: 8px; margin: 0; font-weight: 500;">
<input type="radio" name="dispenseMode" id="dispenseModeQuantity" value="subunit" checked>
Quantity
</label>
<label style="display: inline-flex; align-items: center; gap: 8px; margin: 0; font-weight: 500;">
<input type="radio" name="dispenseMode" id="dispenseModePack" value="pack">
Whole Pack
</label>
</div>
</div>
<div class="form-group" id="dispenseQuantityGroup">
<label for="dispenseQuantity">Quantity *</label>
<input type="number" id="dispenseQuantity" step="0.1">
</div>
<div class="form-row" id="dispensePackRow" style="display: none;">
<div class="form-group">
<label for="dispensePackSelect">Pack Type *</label>
<select id="dispensePackSelect" onchange="updateDispenseQuantityFromPack()">
<option value="">-- Select pack --</option>
</select>
</div>
<div class="form-group">
<label for="dispensePackCount">Pack Count *</label>
<input type="number" id="dispensePackCount" min="1" step="1" onchange="updateDispenseQuantityFromPack()">
<small id="dispensePackPreview" style="display: block; margin-top: 6px; color: #666;">Select a pack and whole-number count.</small>
</div>
</div>
<div class="form-group" id="dispenseSourceGroup" style="display: none;">
<label>Stock Source *</label>
<div style="display: flex; gap: 18px; align-items: center; flex-wrap: wrap; margin-top: 6px;">
<label style="display: inline-flex; align-items: center; gap: 8px; margin: 0; font-weight: 500;">
<input type="radio" name="dispenseSource" id="dispenseSourceBatch" value="batch" checked>
Batch stock
</label>
<label style="display: inline-flex; align-items: center; gap: 8px; margin: 0; font-weight: 500;">
<input type="radio" name="dispenseSource" id="dispenseSourceLegacy" value="legacy">
Legacy loose stock
</label>
</div>
<small id="dispenseSourceHelp" style="display: block; margin-top: 6px; color: #666;"></small>
</div>
<div id="batchInfoSection" style="display: none; margin: 15px 0; padding: 12px; background: #f5f5f5; border-radius: 4px;">
<h4 style="margin-top: 0; margin-bottom: 4px;">Batch Allocation</h4>
<p style="margin: 0 0 10px; color: #666;">Batches are shown in FEFO order. Adjust the allocation against each batch so the total matches the requested dispense amount.</p>
<details id="expiredBatchDetails" style="display: none; margin-bottom: 10px; background: #fffaf0; border: 1px solid #f5d08a; border-radius: 4px; padding: 8px 10px;">
<summary style="cursor: pointer; font-weight: 600; color: #7a4f01;">Show expired batches</summary>
<div id="expiredBatchContent" style="margin-top: 10px;"></div>
</details>
<div id="batchAllocationSummary" style="display: none; margin-bottom: 10px; padding: 8px 10px; background: #f0f8ff; border-left: 3px solid #2196F3; border-radius: 4px;">
<div id="batchAllocationSummaryContent"></div>
</div>
<div id="batchInfoContent">
<p class="loading">Loading batches...</p>
</div>
</div>
<div class="form-group">
<label for="dispenseAnimal">Animal Name/ID</label>
<input type="text" id="dispenseAnimal">
</div>
<div class="form-group" style="margin-top: 18px; padding: 12px; background: #f9fafb; border: 1px solid #d9e2ec; border-radius: 6px;">
<label style="display: inline-flex; align-items: center; gap: 8px; margin-bottom: 0; font-weight: 600;">
<input type="checkbox" id="dispensePrintEnabled">
Print label after dispensing
</label>
<div id="dispensePrintFields" style="display: none; margin-top: 12px;">
<p id="dispensePrintHelpText" style="margin: 0 0 12px; color: #666;">Uses the dispensed quantity, the animal name/ID entered above, the logged-in user, and the latest expiry date from the allocated batches.</p>
<div class="form-group">
<label for="dispenseDosage">Dosage Instructions *</label>
<input type="text" id="dispenseDosage" placeholder="e.g., 1 tablet twice daily with food">
</div>
<div class="form-group" id="dispenseLegacyExpiryGroup" style="display: none;">
<label for="dispenseLegacyExpiry">Expiry Date *</label>
<input type="date" id="dispenseLegacyExpiry">
</div>
</div>
</div>
<div class="form-group">
<label for="dispenseNotes">Notes</label>
<input type="text" id="dispenseNotes" placeholder="Optional">
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Dispense</button>
<button type="button" class="btn btn-secondary" id="cancelDispenseBtn">Cancel</button>
</div>
</form>
</div>
</div>
<!-- Add Variant Modal -->
<div id="addVariantModal" class="modal">
<div class="modal-content">
<span class="close">&times;</span>
<h2>Add Variant</h2>
<form id="variantForm">
<input type="hidden" id="variantDrugId">
<div class="form-group">
<label for="variantStrength">Strength *</label>
<input type="text" id="variantStrength" placeholder="e.g., 5.4mg, 0.5mg/ml" required>
</div>
<div class="form-group">
<label for="variantUnit">Base Unit *</label>
<select id="variantUnit">
<option value="ml">ml</option>
<option value="tablets" selected>tablets</option>
<option value="capsules">capsules</option>
<option value="units">units</option>
<option value="vials">vials</option>
</select>
</div>
<div class="form-group">
<label>Pack Sizes *</label>
<div id="variantPackRows" class="delivery-lines"></div>
<button type="button" id="addVariantPackRowBtn" class="btn btn-secondary btn-small">+ Add Another Size</button>
</div>
<div class="form-group">
<label for="variantThreshold">Low Stock Threshold *</label>
<input type="number" id="variantThreshold" step="0.1" value="10" required>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Add Variant</button>
<button type="button" class="btn btn-secondary" id="cancelVariantBtn">Cancel</button>
</div>
</form>
</div>
</div>
<!-- Edit Variant Modal -->
<div id="editVariantModal" class="modal">
<div class="modal-content">
<span class="close">&times;</span>
<h2>Edit Variant</h2>
<form id="editVariantForm">
<input type="hidden" id="editVariantId">
<p id="editVariantLockNotice" style="display:none; margin: 0 0 12px; padding: 8px 10px; background: #fff8e1; border: 1px solid #f5c15d; border-radius: 6px; color: #7a4f01;">
Strength, quantity, and base unit are locked once this variant has stock/batch history.
</p>
<div class="form-group">
<label for="editVariantStrength">Strength *</label>
<input type="text" id="editVariantStrength" required>
</div>
<div class="form-row">
<div class="form-group">
<label for="editVariantQuantity">Quantity *</label>
<input type="number" id="editVariantQuantity" step="0.1" required>
</div>
<div class="form-group">
<label for="editVariantUnit">Base Unit *</label>
<select id="editVariantUnit">
<option value="tablets">Tablets</option>
<option value="bottles">Bottles</option>
<option value="boxes">Boxes</option>
<option value="vials">Vials</option>
<option value="units">Units</option>
<option value="packets">Packets</option>
</select>
</div>
</div>
<div class="form-group">
<label>Add Pack Sizes</label>
<div id="editVariantPackRows" class="delivery-lines"></div>
<button type="button" id="addEditVariantPackRowBtn" class="btn btn-secondary btn-small">+ Add Another Size</button>
</div>
<div class="form-group">
<label for="editVariantThreshold">Low Stock Threshold *</label>
<input type="number" id="editVariantThreshold" step="0.1" required>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Save Changes</button>
<button type="button" class="btn btn-secondary" id="cancelEditVariantBtn">Cancel</button>
</div>
</form>
</div>
</div>
<!-- Dispensing History Modal -->
<div id="historyModal" class="modal">
<div class="modal-content modal-large">
<span class="close">&times;</span>
<h2>Dispensing History - <span id="historyDrugName"></span></h2>
<div id="historyContent" class="history-content">
<p class="loading">Loading history...</p>
</div>
<div class="form-actions">
<button type="button" class="btn btn-secondary" id="closeHistoryBtn">Close</button>
</div>
</div>
</div>
<!-- Change Password Modal -->
<div id="changePasswordModal" class="modal">
<div class="modal-content">
<span class="close">&times;</span>
<h2>Change Password</h2>
<form id="changePasswordForm">
<div class="form-group">
<label for="currentPassword">Current Password *</label>
<input type="password" id="currentPassword" required>
</div>
<div class="form-group">
<label for="newPassword">New Password *</label>
<input type="password" id="newPassword" required>
</div>
<div class="form-group">
<label for="confirmNewPassword">Confirm New Password *</label>
<input type="password" id="confirmNewPassword" required>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Change Password</button>
<button type="button" class="btn btn-secondary" id="cancelChangePasswordBtn">Cancel</button>
</div>
</form>
</div>
</div>
<!-- Admin Change User Password Modal -->
<div id="adminChangePasswordModal" class="modal">
<div class="modal-content">
<span class="close">&times;</span>
<h2>Change User Password</h2>
<form id="adminChangePasswordForm">
<input type="hidden" id="adminChangePasswordUserId">
<div class="form-group">
<label for="adminChangePasswordUsername">Username</label>
<input type="text" id="adminChangePasswordUsername" disabled>
</div>
<div class="form-group">
<label for="adminChangePasswordNewPassword">New Password *</label>
<input type="password" id="adminChangePasswordNewPassword" required>
</div>
<div class="form-group">
<label for="adminChangePasswordConfirm">Confirm Password *</label>
<input type="password" id="adminChangePasswordConfirm" required>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Set Password</button>
<button type="button" class="btn btn-secondary" id="cancelAdminChangePasswordBtn">Cancel</button>
</div>
</form>
</div>
</div>
<!-- User Management Modal -->
<div id="userManagementModal" class="modal">
<div class="modal-content modal-large">
<span class="close">&times;</span>
<h2>User Management</h2>
<div class="user-management-content">
<div class="form-group">
<h3>Create New User</h3>
<form id="createUserForm">
<div class="form-row">
<input type="text" id="newUsername" placeholder="Username" required>
<input type="password" id="newUserPassword" placeholder="Password" required>
<select id="newUserRole" required>
<option value="">-- Select Role --</option>
<option value="admin">Admin</option>
<option value="user">Regular User</option>
<option value="readonly">Read-Only</option>
</select>
</div>
<button type="submit" class="btn btn-primary btn-small">Create User</button>
</form>
</div>
<div id="usersList" class="users-list">
<h3>Users</h3>
<p class="loading">Loading users...</p>
</div>
</div>
<div class="form-actions">
<button type="button" class="btn btn-secondary" id="closeUserManagementBtn">Close</button>
</div>
</div>
</div>
<!-- Location Management Modal -->
<div id="locationManagementModal" class="modal">
<div class="modal-content modal-large">
<span class="close">&times;</span>
<h2>Storage Locations</h2>
<div class="location-management-content">
<div class="form-group">
<h3>Add New Location</h3>
<form id="createLocationForm">
<div class="form-row">
<input type="text" id="newLocationName" placeholder="Location name (e.g., Fridge, Cupboard)" required>
<button type="submit" class="btn btn-primary btn-small">Add Location</button>
</div>
</form>
</div>
<div id="locationsList" class="locations-list">
<h3>Active Locations</h3>
<p class="loading">Loading locations...</p>
</div>
</div>
<div class="form-actions">
<button type="button" class="btn btn-secondary" id="closeLocationManagementBtn">Close</button>
</div>
</div>
</div>
<!-- Print Notes Modal -->
<div id="printNotesModal" class="modal">
<div class="modal-content">
<span class="close">&times;</span>
<h2>Print Notes</h2>
<form id="printNotesForm" novalidate>
<div class="form-group">
<label for="notesAnimalName">Animal Name/ID *</label>
<input type="text" id="notesAnimalName" required>
</div>
<div class="form-group">
<label for="notesContent">Notes *</label>
<textarea id="notesContent" rows="6" placeholder="Enter notes to print..." required></textarea>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Print Notes</button>
<button type="button" class="btn btn-secondary" id="cancelPrintNotesBtn">Cancel</button>
</div>
</form>
</div>
</div>
<!-- Dispose Batch Modal -->
<div id="disposeBatchModal" class="modal">
<div class="modal-content">
<span class="close">&times;</span>
<h2>Dispose Expired Batch</h2>
<form id="disposeBatchForm" novalidate>
<input type="hidden" id="disposeBatchId">
<div class="form-group">
<label for="disposeBatchName">Batch</label>
<input type="text" id="disposeBatchName" disabled>
</div>
<div class="form-group">
<p style="margin: 0; color: #666;">This will mark the expired batch as disposed and remove its remaining stock from inventory.</p>
</div>
<div class="form-group">
<label for="disposeBatchNotes">Disposal Note</label>
<textarea id="disposeBatchNotes" rows="4" placeholder="Optional note for the audit log"></textarea>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-danger">Confirm Disposal</button>
<button type="button" class="btn btn-secondary" id="cancelDisposeBatchBtn">Cancel</button>
</div>
</form>
</div>
</div>
<!-- Batch Receive Modal -->
<div id="batchReceiveModal" class="modal">
<div class="modal-content">
<span class="close">&times;</span>
<h2>Receive New Batch</h2>
<form id="batchReceiveForm" novalidate>
<input type="hidden" id="batchVariantId">
<div class="form-group">
<label for="batchNumber">Batch Number *</label>
<input type="text" id="batchNumber" placeholder="e.g., LOT-2026-001" required>
</div>
<div class="form-group">
<label for="batchQuantity">Quantity *</label>
<input type="number" id="batchQuantity" step="0.1" required>
</div>
<div class="form-group">
<label for="batchExpiryDate">Expiry Date *</label>
<input type="date" id="batchExpiryDate" required>
</div>
<div class="form-group">
<label for="batchLocation">Storage Location *</label>
<select id="batchLocation" required>
<option value="">-- Select location --</option>
</select>
</div>
<div class="form-group">
<label for="batchNotes">Notes</label>
<input type="text" id="batchNotes" placeholder="Optional notes about this batch">
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Receive Batch</button>
<button type="button" class="btn btn-secondary" id="cancelBatchReceiveBtn">Cancel</button>
</div>
</form>
</div>
</div>
<!-- Add Pack Size Modal -->
<div id="addPackSizeModal" class="modal">
<div class="modal-content">
<span class="close">&times;</span>
<h2>Add Pack Size</h2>
<p id="addPackSizeDrugLabel" style="margin: 4px 0 14px; color: #666; font-weight: 600;"></p>
<form id="addPackSizeForm" novalidate>
<div class="form-group">
<label for="addPackSizeVariantSelect">Variant *</label>
<select id="addPackSizeVariantSelect" required>
<option value="">-- Select variant --</option>
</select>
</div>
<div class="form-group">
<label for="addPackSizeType">Pack Type *</label>
<select id="addPackSizeType" required>
<option value="box" selected>Box</option>
<option value="bottle">Bottle</option>
<option value="vial">Vial</option>
<option value="packet">Packet</option>
</select>
</div>
<div class="form-group">
<label for="addPackSizeCount">Pack Size (units) *</label>
<input type="number" id="addPackSizeCount" min="0.0001" step="0.0001" placeholder="e.g., 28" required>
<small id="addPackSizeHint" style="display: block; margin-top: 4px; color: #666;"></small>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Add Pack Size</button>
<button type="button" class="btn btn-secondary" id="cancelAddPackSizeBtn">Cancel</button>
</div>
</form>
</div>
</div>
<!-- Receive Delivery Modal -->
<div id="receiveDeliveryModal" class="modal">
<div class="modal-content modal-large receive-delivery-modal-content">
<span class="close">&times;</span>
<h2>Receive Delivery</h2>
<p id="receiveDeliveryDrugLabel" style="margin: 6px 0 16px; color: #666; font-weight: 600;"></p>
<form id="receiveDeliveryForm" novalidate>
<div id="deliveryLinesContainer" class="delivery-lines"></div>
<div class="delivery-toolbar">
<button type="button" id="addDeliveryLineBtn" class="btn btn-secondary">+ Add Delivery Line</button>
<button type="button" id="addVariantFromDeliveryBtn" class="btn btn-info">+ Add Variant</button>
<button type="button" id="addPackSizeFromDeliveryBtn" class="btn btn-info">+ Add Pack Size</button>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Receive Delivery</button>
<button type="button" class="btn btn-secondary" id="cancelReceiveDeliveryBtn">Cancel</button>
</div>
</form>
</div>
</div>
<!-- GTIN Mapping Modal -->
<div id="gtinMappingModal" class="modal">
<div class="modal-content">
<span class="close">&times;</span>
<h2>Unknown Barcode — Map GTIN</h2>
<p style="color:#666; margin-bottom:16px;">This barcode hasn't been seen before. Please map it to the correct drug, variant and pack.</p>
<div class="form-group">
<label>GTIN</label>
<input type="text" id="gtinMappingGtin" readonly style="background:#f5f5f5;">
</div>
<div class="form-group">
<label>Drug</label>
<div style="display:flex; gap:8px; align-items:center;">
<select id="gtinMappingDrugSelect" onchange="onGtinMappingDrugChange()" style="flex:1">
<option value="">-- Select drug --</option>
</select>
<button type="button" class="btn btn-info btn-small" onclick="gtinMappingAddDrug()">+ New Drug</button>
</div>
</div>
<div class="form-group">
<label>Variant</label>
<div style="display:flex; gap:8px; align-items:center;">
<select id="gtinMappingVariantSelect" onchange="onGtinMappingVariantChange()" style="flex:1">
<option value="">-- Select variant --</option>
</select>
<button type="button" class="btn btn-info btn-small" onclick="gtinMappingAddVariant()">+ New Variant</button>
</div>
</div>
<div class="form-group">
<label>Pack</label>
<div style="display:flex; gap:8px; align-items:center;">
<select id="gtinMappingPackSelect" style="flex:1">
<option value="">-- Select pack --</option>
</select>
<button type="button" class="btn btn-info btn-small" onclick="gtinMappingAddPack()">+ New Pack</button>
</div>
</div>
<div class="form-actions">
<button type="button" class="btn btn-primary" onclick="handleSaveGtinMapping()">Save Mapping</button>
<button type="button" class="btn btn-secondary" id="cancelGtinMappingBtn">Cancel</button>
</div>
</div>
</div>
</div>
<script src="app.js"></script>
</body>
</html>