| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Doctor & Patient Management</title> |
| <style> |
| body { |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; |
| margin: 0; |
| padding: 20px; |
| background-color: #f8f9fa; |
| } |
| h1 { |
| text-align: center; |
| color: #2c3e50; |
| } |
| .tabs { |
| display: flex; |
| justify-content: center; |
| margin: 20px 0; |
| border-bottom: 2px solid #ddd; |
| } |
| .tab-button { |
| padding: 12px 30px; |
| font-size: 16px; |
| cursor: pointer; |
| background: none; |
| border: none; |
| border-bottom: 3px solid transparent; |
| margin: 0 10px; |
| transition: all 0.3s; |
| } |
| .tab-button.active { |
| border-bottom: 3px solid #3498db; |
| color: #3498db; |
| font-weight: bold; |
| } |
| .table-container { |
| max-width: 1200px; |
| margin: 20px auto; |
| background: white; |
| padding: 20px; |
| border-radius: 8px; |
| box-shadow: 0 2px 10px rgba(0,0,0,0.1); |
| } |
| table { |
| width: 100%; |
| border-collapse: collapse; |
| } |
| th, td { |
| padding: 12px; |
| text-align: left; |
| border-bottom: 1px solid #ddd; |
| } |
| th { |
| background-color: #3498db; |
| color: white; |
| } |
| tr:hover { |
| background-color: #f1f1f1; |
| } |
| .loading { |
| text-align: center; |
| padding: 20px; |
| color: #666; |
| } |
| .error { |
| color: red; |
| text-align: center; |
| } |
| </style> |
| </head> |
| <body> |
|
|
| <h1>Doctor & Patient Management System</h1> |
|
|
| <div class="tabs"> |
| <button class="tab-button" onclick="showTab(0)">Doctors</button> |
| <button class="tab-button" onclick="showTab(1)">Patients</button> |
| </div> |
|
|
| |
| <div id="doctors-tab" class="table-container" style="display:none;"> |
| <h2>Doctors List</h2> |
| <div id="doctors-loading" class="loading">Loading doctors...</div> |
| <table id="doctors-table" style="display:none;"> |
| <thead> |
| <tr> |
| <th>ID</th> |
| <th>Doctor Name</th> |
| <th>Category</th> |
| <th>Visiting Days</th> |
| <th>Visiting Time</th> |
| <th>Fee (BDT)</th> |
| </tr> |
| </thead> |
| <tbody></tbody> |
| </table> |
| </div> |
|
|
| |
| <div id="patients-tab" class="table-container" style="display:none;"> |
| <h2>Patients List</h2> |
| <div id="patients-loading" class="loading">Loading patients...</div> |
| <table id="patients-table" style="display:none;"> |
| <thead> |
| <tr> |
| <th>ID</th> |
| <th>Patient Name</th> |
| <th>Age</th> |
| <th>Phone</th> |
| <th>Email</th> |
| <th>Doctor</th> |
| <th>Category</th> |
| <th>Visiting Date</th> |
| <th>Visiting Day</th> |
| <th>Visiting Time</th> |
| </tr> |
| </thead> |
| <tbody></tbody> |
| </table> |
| </div> |
|
|
| <script> |
| const API_BASE = new URL('/dbapi', window.location.origin).toString().replace(/\/$/, ''); |
| |
| function showTab(tabIndex) { |
| const doctorsTab = document.getElementById('doctors-tab'); |
| const patientsTab = document.getElementById('patients-tab'); |
| const buttons = document.querySelectorAll('.tab-button'); |
| |
| buttons.forEach((btn, index) => { |
| btn.classList.toggle('active', index === tabIndex); |
| }); |
| |
| doctorsTab.style.display = tabIndex === 0 ? 'block' : 'none'; |
| patientsTab.style.display = tabIndex === 1 ? 'block' : 'none'; |
| |
| |
| try { localStorage.setItem('db_view_tab', String(tabIndex)); } catch {} |
| } |
| |
| async function fetchDoctors() { |
| const loading = document.getElementById('doctors-loading'); |
| const table = document.getElementById('doctors-table'); |
| const tbody = table.querySelector('tbody'); |
| |
| try { |
| const res = await fetch(`${API_BASE}/api/doctors`); |
| if (!res.ok) throw new Error(`HTTP Error: ${res.status}`); |
| |
| const doctors = await res.json(); |
| |
| tbody.innerHTML = doctors.map(doc => ` |
| <tr> |
| <td>${doc.id}</td> |
| <td>${doc.doctor_name}</td> |
| <td>${doc.category}</td> |
| <td>${doc.visiting_days}</td> |
| <td>${doc.visiting_time}</td> |
| <td>${doc.visiting_money}</td> |
| </tr>`).join(''); |
| |
| loading.style.display = 'none'; |
| table.style.display = 'table'; |
| } catch (err) { |
| console.error(err); |
| loading.innerHTML = `<span class="error">Failed to fetch doctors.<br>${err.message}</span>`; |
| } |
| } |
| |
| async function fetchPatients() { |
| const loading = document.getElementById('patients-loading'); |
| const table = document.getElementById('patients-table'); |
| const tbody = table.querySelector('tbody'); |
| |
| try { |
| const res = await fetch(`${API_BASE}/api/patients`); |
| if (!res.ok) throw new Error(`HTTP Error: ${res.status}`); |
| |
| const patients = await res.json(); |
| |
| tbody.innerHTML = patients.map(patient => ` |
| <tr> |
| <td>${patient.id}</td> |
| <td>${patient.patient_name}</td> |
| <td>${patient.patient_age}</td> |
| <td>${patient.patient_num}</td> |
| <td>${patient.patient_mail}</td> |
| <td>${patient.doctor_name}</td> |
| <td>${patient.doctor_category}</td> |
| <td>${patient.visiting_date}</td> |
| <td>${patient.visiting_day || ''}</td> |
| <td>${patient.visiting_time || ''}</td> |
| </tr>`).join(''); |
| |
| loading.style.display = 'none'; |
| table.style.display = 'table'; |
| } catch (err) { |
| console.error(err); |
| loading.innerHTML = `<span class="error">Failed to fetch patients.<br>${err.message}</span>`; |
| } |
| } |
| |
| |
| window.onload = () => { |
| fetchDoctors(); |
| fetchPatients(); |
| |
| let tab = 1; |
| try { |
| const saved = Number(localStorage.getItem('db_view_tab')); |
| if (saved === 0 || saved === 1) tab = saved; |
| } catch {} |
| showTab(tab); |
| }; |
| </script> |
| </body> |
| </html> |
|
|