version 2.1
This commit is contained in:
parent
c8d83e1d5c
commit
fea1dbbb79
@ -1,124 +1,271 @@
|
||||
/* assets/css/custom.css */
|
||||
|
||||
:root {
|
||||
--primary-color: #6a5acd; /* SlateBlue */
|
||||
--primary-color-dark: #483d8b; /* DarkSlateBlue */
|
||||
--secondary-color: #f0f8ff; /* AliceBlue */
|
||||
--text-color: #333;
|
||||
--text-color-light: #777;
|
||||
--border-color: #e6e6fa; /* Lavender */
|
||||
--sidebar-bg: #ffffff;
|
||||
--sidebar-link-color: #555;
|
||||
--sidebar-link-hover-bg: #f0f0f0;
|
||||
--sidebar-link-active-color: #ffffff;
|
||||
--sidebar-link-active-bg: var(--primary-color);
|
||||
--card-bg: #ffffff;
|
||||
--card-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
--font-family: 'Poppins', sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Poppins', sans-serif;
|
||||
background-color: #F8F9FA;
|
||||
color: #212529;
|
||||
font-family: var(--font-family);
|
||||
background-color: var(--secondary-color);
|
||||
color: var(--text-color);
|
||||
font-size: 15px;
|
||||
background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23dcdcdc' fill-opacity='0.3'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.page-wrapper {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
background-color: #2c3e50;
|
||||
width: 260px;
|
||||
background-color: var(--sidebar-bg);
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
border-right: 1px solid var(--border-color);
|
||||
padding: 1.5rem 1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: 0 0 15px rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.sidebar-brand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
color: var(--primary-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.sidebar-brand .bi {
|
||||
font-size: 2rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.sidebar-nav {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.sidebar .nav-link {
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
color: var(--sidebar-link-color);
|
||||
border-radius: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.75rem 1rem;
|
||||
transition: background-color 0.2s, color 0.2s;
|
||||
}
|
||||
|
||||
.sidebar .nav-link:hover {
|
||||
color: #ffffff;
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
color: var(--primary-color);
|
||||
background-color: var(--sidebar-link-hover-bg);
|
||||
}
|
||||
|
||||
.sidebar .nav-link.active {
|
||||
color: #ffffff;
|
||||
background-color: #4A90E2;
|
||||
color: var(--sidebar-link-active-color);
|
||||
background-color: var(--sidebar-link-active-bg);
|
||||
box-shadow: 0 2px 5px rgba(106, 90, 205, 0.3);
|
||||
}
|
||||
|
||||
.sidebar .nav-link .bi {
|
||||
font-size: 1.2rem;
|
||||
margin-right: 1rem;
|
||||
width: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sidebar hr {
|
||||
border-color: rgba(255, 255, 255, 0.2);
|
||||
.sidebar-footer {
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
background-color: #F8F9FA;
|
||||
flex-grow: 1;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.btn-primary-custom {
|
||||
background-color: #4A90E2;
|
||||
border-color: #4A90E2;
|
||||
color: #ffffff;
|
||||
padding: 0.75rem 1.25rem;
|
||||
border-radius: 0.5rem;
|
||||
font-weight: 600;
|
||||
transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out;
|
||||
.header {
|
||||
margin-bottom: 2rem;
|
||||
padding-bottom: 1rem;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.btn-primary-custom:hover {
|
||||
background-color: #357ABD;
|
||||
border-color: #357ABD;
|
||||
color: #ffffff;
|
||||
.header-title {
|
||||
font-size: 2.2rem;
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.card {
|
||||
.header-subtitle {
|
||||
font-size: 1rem;
|
||||
color: var(--text-color-light);
|
||||
}
|
||||
|
||||
.content-card, .card {
|
||||
background-color: var(--card-bg);
|
||||
border-radius: 0.75rem;
|
||||
box-shadow: var(--card-shadow);
|
||||
border: none;
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: 0 0.15rem 1.75rem 0 rgba(58, 59, 69, 0.15) !important;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.card .card-header {
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #e3e6f0;
|
||||
padding: 1rem 1.25rem;
|
||||
.card-header {
|
||||
background-color: transparent;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
padding: 1.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.card .card-body {
|
||||
.card-title-text, .card-header .m-0 {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 600;
|
||||
margin: 0;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.card-body {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.border-left-primary {
|
||||
border-left: 0.25rem solid #4A90E2 !important;
|
||||
.table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
color: #4A90E2 !important;
|
||||
.table thead th {
|
||||
border-bottom: 2px solid var(--border-color);
|
||||
font-weight: 600;
|
||||
color: var(--text-color-light);
|
||||
padding: 1rem 1.5rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.border-left-success {
|
||||
border-left: 0.25rem solid #1cc88a !important;
|
||||
.table tbody tr {
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.text-success {
|
||||
color: #1cc88a !important;
|
||||
.table tbody tr:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.border-left-info {
|
||||
border-left: 0.25rem solid #36b9cc !important;
|
||||
.table tbody tr:hover {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.text-info {
|
||||
color: #36b9cc !important;
|
||||
.table td, .table th {
|
||||
padding: 1rem 1.5rem;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.text-gray-300 {
|
||||
color: #dddfeb !important;
|
||||
.table a {
|
||||
color: var(--primary-color);
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.text-gray-800 {
|
||||
color: #5a5c69 !important;
|
||||
.table a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.font-weight-bold {
|
||||
font-weight: 700 !important;
|
||||
.badge.bg-success-soft {
|
||||
background-color: rgba(28, 200, 138, 0.1);
|
||||
color: #1cc88a;
|
||||
}
|
||||
|
||||
.text-xs {
|
||||
font-size: .7rem;
|
||||
.badge.bg-warning-soft {
|
||||
background-color: rgba(246, 194, 62, 0.1);
|
||||
color: #f6c23e;
|
||||
}
|
||||
|
||||
.badge.bg-info-soft {
|
||||
background-color: rgba(54, 185, 204, 0.1);
|
||||
color: #36b9cc;
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.6rem 1.2rem;
|
||||
font-weight: 600;
|
||||
transition: all 0.2s;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.btn-primary, .btn-primary-custom {
|
||||
background-color: var(--primary-color);
|
||||
border-color: var(--primary-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover, .btn-primary-custom:hover {
|
||||
background-color: var(--primary-color-dark);
|
||||
border-color: var(--primary-color-dark);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.form-control, .form-select {
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.75rem 1rem;
|
||||
border: 1px solid var(--border-color);
|
||||
transition: border-color 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
|
||||
.form-control:focus, .form-select:focus {
|
||||
box-shadow: 0 0 0 0.25rem rgba(74, 144, 226, 0.25);
|
||||
border-color: #4A90E2;
|
||||
box-shadow: 0 0 0 0.25rem rgba(106, 90, 205, 0.15);
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
border-radius: 0.75rem;
|
||||
border: none;
|
||||
box-shadow: 0 8px 24px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.search-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
}
|
||||
.search-results {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
border: 1px solid #ccc;
|
||||
background-color: #fff;
|
||||
border-radius: 0 0 5px 5px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
display: none;
|
||||
}
|
||||
.search-results a {
|
||||
display: block;
|
||||
padding: 10px;
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
.search-results a:hover {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.search-results a:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
@ -50,6 +50,7 @@ try {
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@ -81,12 +82,12 @@ try {
|
||||
</a>
|
||||
</nav>
|
||||
<div class="sidebar-footer">
|
||||
<div class="dropdown">
|
||||
<a href="#" class="d-flex align-items-center text-white text-decoration-none dropdown-toggle" id="dropdownUser1" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<div class="dropdown">
|
||||
<a href="#" class="d-flex align-items-center dropdown-toggle" id="dropdownUser1" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="bi bi-person-circle me-2"></i>
|
||||
<strong><?php echo htmlspecialchars($_SESSION['username']); ?></strong>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-dark text-small shadow" aria-labelledby="dropdownUser1">
|
||||
<ul class="dropdown-menu text-small shadow" aria-labelledby="dropdownUser1">
|
||||
<li><a class="dropdown-item" href="logout.php">Sign out</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -95,75 +96,79 @@ try {
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="main-content">
|
||||
<div class="container-fluid">
|
||||
<div class="header">
|
||||
<div class="header d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h1 class="header-title">Doctor's Dashboard</h1>
|
||||
<p class="header-subtitle">Welcome, Dr. <?php echo htmlspecialchars($doctor['username'] ?? 'Doctor'); ?>!</p>
|
||||
<p class="header-subtitle mb-0">Welcome, Dr. <?php echo htmlspecialchars($doctor['username'] ?? 'Doctor'); ?>!</p>
|
||||
</div>
|
||||
<div class="search-container">
|
||||
<input type="text" id="patientSearch" class="form-control" placeholder="Search Patient by Name or ID...">
|
||||
<div id="searchResults" class="search-results"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Today's Patients -->
|
||||
<div class="card content-card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title-text"><i class="bi bi-list-ul me-2"></i>Today's Appointments</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Patient ID</th>
|
||||
<th>Name</th>
|
||||
<th>Status</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (!empty($visits)):
|
||||
foreach ($visits as $visit):
|
||||
?>
|
||||
<tr id="patient-row-<?php echo $visit['visit_id']; ?>">
|
||||
<td><?php echo htmlspecialchars($visit['patient_system_id']); ?></td>
|
||||
<td>
|
||||
<a href="patient_profile.php?id=<?php echo $visit['patient_id']; ?>"><?php echo htmlspecialchars($visit['patient_name']); ?></a>
|
||||
</td>
|
||||
<td><span class="badge bg-<?php echo get_status_badge_class($visit['status']); ?>-soft" id="status-<?php echo $visit['visit_id']; ?>"><?php echo htmlspecialchars($visit['status']); ?></span></td>
|
||||
<td id="action-cell-<?php echo $visit['visit_id']; ?>">
|
||||
<?php echo get_action_buttons($visit); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="notes-row" id="notes-row-<?php echo $visit['visit_id']; ?>" style="<?php echo $visit['status'] !== 'In Progress' ? 'display: none;' : ''; ?>">
|
||||
<td colspan="4">
|
||||
<form class="notes-form" data-visit-id="<?php echo $visit['visit_id']; ?>">
|
||||
<div class="mb-3">
|
||||
<label for="notes-<?php echo $visit['visit_id']; ?>" class="form-label">Consultation Notes</label>
|
||||
<textarea class="form-control" id="notes-<?php echo $visit['visit_id']; ?>" rows="3"><?php echo htmlspecialchars($visit['notes'] ?? ''); ?></textarea>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-8 mb-3">
|
||||
<label for="service-<?php echo $visit['visit_id']; ?>" class="form-label">Service Rendered</label>
|
||||
<input type="text" class="form-control" id="service-<?php echo $visit['visit_id']; ?>" placeholder="e.g., General Consultation">
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label for="cost-<?php echo $visit['visit_id']; ?>" class="form-label">Cost ($)</label>
|
||||
<input type="number" class="form-control" id="cost-<?php echo $visit['visit_id']; ?>" placeholder="e.g., 75.00" step="0.01">
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-sm btn-success">
|
||||
<i class="bi bi-check-circle me-1"></i>Complete Consultation & Bill
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else:
|
||||
?>
|
||||
<tr>
|
||||
<td colspan="4" class="text-center text-muted">No patients assigned for today.</td>
|
||||
<!-- Today's Patients -->
|
||||
<div class="content-card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title-text"><i class="bi bi-list-ul me-2"></i>Today's Appointments</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Patient ID</th>
|
||||
<th>Name</th>
|
||||
<th>Status</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (!empty($visits)):
|
||||
foreach ($visits as $visit):
|
||||
?>
|
||||
<tr id="patient-row-<?php echo $visit['visit_id']; ?>">
|
||||
<td><?php echo htmlspecialchars($visit['patient_system_id']); ?></td>
|
||||
<td>
|
||||
<a href="patient_profile.php?id=<?php echo $visit['patient_id']; ?>"><?php echo htmlspecialchars($visit['patient_name']); ?></a>
|
||||
</td>
|
||||
<td><span class="badge bg-<?php echo get_status_badge_class($visit['status']); ?>-soft" id="status-<?php echo $visit['visit_id']; ?>"><?php echo htmlspecialchars($visit['status']); ?></span></td>
|
||||
<td id="action-cell-<?php echo $visit['visit_id']; ?>">
|
||||
<?php echo get_action_buttons($visit); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<tr class="notes-row" id="notes-row-<?php echo $visit['visit_id']; ?>" style="<?php echo $visit['status'] !== 'In Progress' ? 'display: none;' : ''; ?>">
|
||||
<td colspan="4">
|
||||
<form class="notes-form" data-visit-id="<?php echo $visit['visit_id']; ?>">
|
||||
<div class="mb-3">
|
||||
<label for="notes-<?php echo $visit['visit_id']; ?>" class="form-label">Consultation Notes</label>
|
||||
<textarea class="form-control" id="notes-<?php echo $visit['visit_id']; ?>" rows="3"><?php echo htmlspecialchars($visit['notes'] ?? ''); ?></textarea>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-8 mb-3">
|
||||
<label for="service-<?php echo $visit['visit_id']; ?>" class="form-label">Service Rendered</label>
|
||||
<input type="text" class="form-control" id="service-<?php echo $visit['visit_id']; ?>" placeholder="e.g., General Consultation">
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label for="cost-<?php echo $visit['visit_id']; ?>" class="form-label">Cost ($)</label>
|
||||
<input type="number" class="form-control" id="cost-<?php echo $visit['visit_id']; ?>" placeholder="e.g., 75.00" step="0.01">
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-sm btn-success">
|
||||
<i class="bi bi-check-circle me-1"></i>Complete Consultation & Bill
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else:
|
||||
?>
|
||||
<tr>
|
||||
<td colspan="4" class="text-center text-muted">No patients assigned for today.</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -399,6 +404,51 @@ function updatePatientStatus(visitId, status, notes = null, service = null, cost
|
||||
alert('An unexpected error occurred.');
|
||||
});
|
||||
}
|
||||
|
||||
document.getElementById('patientSearch').addEventListener('input', function() {
|
||||
const searchTerm = this.value;
|
||||
const resultsContainer = document.getElementById('searchResults');
|
||||
|
||||
if (searchTerm.length < 2) {
|
||||
resultsContainer.innerHTML = '';
|
||||
resultsContainer.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(`search_patient.php?term=${encodeURIComponent(searchTerm)}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
resultsContainer.innerHTML = '';
|
||||
if (data.length > 0) {
|
||||
data.forEach(patient => {
|
||||
const patientLink = document.createElement('a');
|
||||
patientLink.href = `patient_profile.php?id=${patient.id}`;
|
||||
patientLink.textContent = `${patient.patient_name} (${patient.patient_id})`;
|
||||
resultsContainer.appendChild(patientLink);
|
||||
});
|
||||
resultsContainer.style.display = 'block';
|
||||
} else {
|
||||
resultsContainer.innerHTML = '<a href="#" class="disabled">No patients found</a>';
|
||||
resultsContainer.style.display = 'block';
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
resultsContainer.innerHTML = '<a href="#" class="disabled">Search error</a>';
|
||||
resultsContainer.style.display = 'block';
|
||||
});
|
||||
});
|
||||
|
||||
// Hide results when clicking outside
|
||||
document.addEventListener('click', function(e) {
|
||||
const searchContainer = document.querySelector('.search-container');
|
||||
if (searchContainer && !searchContainer.contains(e.target)) {
|
||||
const resultsContainer = document.getElementById('searchResults');
|
||||
if (resultsContainer) {
|
||||
resultsContainer.style.display = 'none';
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -42,6 +42,38 @@ $pending_tests = $pending_tests_stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css">
|
||||
<style>
|
||||
.search-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
}
|
||||
.search-results {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
border: 1px solid #ccc;
|
||||
background-color: #fff;
|
||||
border-radius: 0 0 5px 5px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
display: none;
|
||||
}
|
||||
.search-results a {
|
||||
display: block;
|
||||
padding: 10px;
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
.search-results a:hover {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.search-results a:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@ -89,6 +121,10 @@ $pending_tests = $pending_tests_stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
<main class="main-content">
|
||||
<header class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3 mb-0 text-gray-800">Pending Lab & Imaging Reports</h1>
|
||||
<div class="search-container">
|
||||
<input type="text" id="patientSearch" class="form-control" placeholder="Search Patient by Name or ID...">
|
||||
<div id="searchResults" class="search-results"></div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="card shadow-sm">
|
||||
@ -194,6 +230,51 @@ document.addEventListener('submit', function(e) {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('patientSearch').addEventListener('input', function() {
|
||||
const searchTerm = this.value;
|
||||
const resultsContainer = document.getElementById('searchResults');
|
||||
|
||||
if (searchTerm.length < 2) {
|
||||
resultsContainer.innerHTML = '';
|
||||
resultsContainer.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(`search_patient.php?term=${encodeURIComponent(searchTerm)}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
resultsContainer.innerHTML = '';
|
||||
if (data.length > 0) {
|
||||
data.forEach(patient => {
|
||||
const patientLink = document.createElement('a');
|
||||
patientLink.href = `patient_profile.php?id=${patient.id}`;
|
||||
patientLink.textContent = `${patient.patient_name} (${patient.patient_id})`;
|
||||
resultsContainer.appendChild(patientLink);
|
||||
});
|
||||
resultsContainer.style.display = 'block';
|
||||
} else {
|
||||
resultsContainer.innerHTML = '<a href="#" class="disabled">No patients found</a>';
|
||||
resultsContainer.style.display = 'block';
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
resultsContainer.innerHTML = '<a href="#" class="disabled">Search error</a>';
|
||||
resultsContainer.style.display = 'block';
|
||||
});
|
||||
});
|
||||
|
||||
// Hide results when clicking outside
|
||||
document.addEventListener('click', function(e) {
|
||||
const searchContainer = document.querySelector('.search-container');
|
||||
if (searchContainer && !searchContainer.contains(e.target)) {
|
||||
const resultsContainer = document.getElementById('searchResults');
|
||||
if (resultsContainer) {
|
||||
resultsContainer.style.display = 'none';
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
81
pharmacy.php
81
pharmacy.php
@ -36,6 +36,38 @@ $pending_prescriptions = $pending_prescriptions_stmt->fetchAll(PDO::FETCH_ASSOC)
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css">
|
||||
<style>
|
||||
.search-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
}
|
||||
.search-results {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
border: 1px solid #ccc;
|
||||
background-color: #fff;
|
||||
border-radius: 0 0 5px 5px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
display: none;
|
||||
}
|
||||
.search-results a {
|
||||
display: block;
|
||||
padding: 10px;
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
.search-results a:hover {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.search-results a:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@ -83,6 +115,10 @@ $pending_prescriptions = $pending_prescriptions_stmt->fetchAll(PDO::FETCH_ASSOC)
|
||||
<main class="main-content">
|
||||
<header class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3 mb-0 text-gray-800">Pharmacy - Pending Prescriptions</h1>
|
||||
<div class="search-container">
|
||||
<input type="text" id="patientSearch" class="form-control" placeholder="Search Patient by Name or ID...">
|
||||
<div id="searchResults" class="search-results"></div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="card shadow-sm">
|
||||
@ -160,6 +196,51 @@ document.addEventListener('click', function(e) {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('patientSearch').addEventListener('input', function() {
|
||||
const searchTerm = this.value;
|
||||
const resultsContainer = document.getElementById('searchResults');
|
||||
|
||||
if (searchTerm.length < 2) {
|
||||
resultsContainer.innerHTML = '';
|
||||
resultsContainer.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(`search_patient.php?term=${encodeURIComponent(searchTerm)}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
resultsContainer.innerHTML = '';
|
||||
if (data.length > 0) {
|
||||
data.forEach(patient => {
|
||||
const patientLink = document.createElement('a');
|
||||
patientLink.href = `patient_profile.php?id=${patient.id}`;
|
||||
patientLink.textContent = `${patient.patient_name} (${patient.patient_id})`;
|
||||
resultsContainer.appendChild(patientLink);
|
||||
});
|
||||
resultsContainer.style.display = 'block';
|
||||
} else {
|
||||
resultsContainer.innerHTML = '<a href="#" class="disabled">No patients found</a>';
|
||||
resultsContainer.style.display = 'block';
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
resultsContainer.innerHTML = '<a href="#" class="disabled">Search error</a>';
|
||||
resultsContainer.style.display = 'block';
|
||||
});
|
||||
});
|
||||
|
||||
// Hide results when clicking outside
|
||||
document.addEventListener('click', function(e) {
|
||||
const searchContainer = document.querySelector('.search-container');
|
||||
if (searchContainer && !searchContainer.contains(e.target)) {
|
||||
const resultsContainer = document.getElementById('searchResults');
|
||||
if (resultsContainer) {
|
||||
resultsContainer.style.display = 'none';
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -23,6 +23,7 @@ $total_revenue = $pdo->query("SELECT SUM(total_fee) FROM patients WHERE status =
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@ -76,6 +77,10 @@ $total_revenue = $pdo->query("SELECT SUM(total_fee) FROM patients WHERE status =
|
||||
<div class="main-content flex-grow-1 p-4">
|
||||
<header class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3 mb-0 text-gray-800">Receptionist Dashboard</h1>
|
||||
<div class="search-container">
|
||||
<input type="text" id="patientSearch" class="form-control" placeholder="Search Patient by Name or ID...">
|
||||
<div id="searchResults" class="search-results"></div>
|
||||
</div>
|
||||
<a href="patient_register.php" class="btn btn-primary-custom">
|
||||
<i class="bi bi-person-plus-fill me-2"></i>
|
||||
Register New Patient
|
||||
@ -136,20 +141,7 @@ $total_revenue = $pdo->query("SELECT SUM(total_fee) FROM patients WHERE status =
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Patient Search -->
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-header py-3">
|
||||
<h6 class="m-0 font-weight-bold text-primary">Find a Patient</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="reception.php" method="GET" class="d-flex">
|
||||
<input type="text" class="form-control me-2" name="search_query" placeholder="Enter Patient Name or ID..." value="<?php echo isset($_GET['search_query']) ? htmlspecialchars($_GET['search_query']) : ''; ?>">
|
||||
<button type="submit" class="btn btn-primary-custom">
|
||||
<i class="bi bi-search"></i> Search
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Patient List -->
|
||||
<div class="card shadow">
|
||||
@ -164,39 +156,26 @@ $total_revenue = $pdo->query("SELECT SUM(total_fee) FROM patients WHERE status =
|
||||
<th>Patient ID</th>
|
||||
<th>Patient Name</th>
|
||||
<th>Phone Number</th>
|
||||
<th>Assigned Doctor</th>
|
||||
<th>Status</th>
|
||||
<th>Date</th>
|
||||
<th>Registration Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$search_query = isset($_GET['search_query']) ? trim($_GET['search_query']) : '';
|
||||
|
||||
$sql = "SELECT p.*, d.doctor_name FROM patients p LEFT JOIN doctors d ON p.doctor_id = d.id";
|
||||
$params = [];
|
||||
|
||||
if (!empty($search_query)) {
|
||||
$sql .= " WHERE p.patient_name LIKE ? OR p.patient_id LIKE ?";
|
||||
$params = ["%$search_query%", "%$search_query%"];
|
||||
}
|
||||
|
||||
$sql .= " ORDER BY p.created_at DESC LIMIT 10";
|
||||
$sql = "SELECT * FROM patients ORDER BY created_at DESC LIMIT 10";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
$stmt->execute();
|
||||
|
||||
if ($stmt->rowCount() > 0) {
|
||||
while ($row = $stmt->fetch()) {
|
||||
echo "<tr>";
|
||||
echo "<td><a href='patient_profile.php?id=" . $row['id'] . "'>" . htmlspecialchars($row['patient_id']) . "</a></td>";
|
||||
echo "<td><a href='patient_profile.php?id=" . $row['id'] . "'>" . htmlspecialchars($row['patient_name']) . "</a></td>";
|
||||
echo "<td>" . htmlspecialchars($row['phone_number']) . "</td>";
|
||||
echo "<td>" . htmlspecialchars($row['doctor_name'] ?? 'N/A') . "</td>";
|
||||
echo "<td><span class='badge bg-secondary'>" . htmlspecialchars($row['status']) . "</span></td>";
|
||||
echo "<td>" . htmlspecialchars($row['phone']) . "</td>";
|
||||
echo "<td>" . date("Y-m-d H:i", strtotime($row['created_at'])) . "</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
} else {
|
||||
echo '<tr><td colspan="6" class="text-center">No patients found.</td></tr>';
|
||||
echo '<tr><td colspan="4" class="text-center">No patients found.</td></tr>';
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
@ -209,5 +188,51 @@ $total_revenue = $pdo->query("SELECT SUM(total_fee) FROM patients WHERE status =
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script>
|
||||
document.getElementById('patientSearch').addEventListener('input', function() {
|
||||
const searchTerm = this.value;
|
||||
const resultsContainer = document.getElementById('searchResults');
|
||||
|
||||
if (searchTerm.length < 2) {
|
||||
resultsContainer.innerHTML = '';
|
||||
resultsContainer.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(`search_patient.php?term=${encodeURIComponent(searchTerm)}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
resultsContainer.innerHTML = '';
|
||||
if (data.length > 0) {
|
||||
data.forEach(patient => {
|
||||
const patientLink = document.createElement('a');
|
||||
patientLink.href = `patient_profile.php?id=${patient.id}`;
|
||||
patientLink.textContent = `${patient.patient_name} (${patient.patient_id})`;
|
||||
resultsContainer.appendChild(patientLink);
|
||||
});
|
||||
resultsContainer.style.display = 'block';
|
||||
} else {
|
||||
resultsContainer.innerHTML = '<a href="#" class="disabled">No patients found</a>';
|
||||
resultsContainer.style.display = 'block';
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
resultsContainer.innerHTML = '<a href="#" class="disabled">Search error</a>';
|
||||
resultsContainer.style.display = 'block';
|
||||
});
|
||||
});
|
||||
|
||||
// Hide results when clicking outside
|
||||
document.addEventListener('click', function(e) {
|
||||
const searchContainer = document.querySelector('.search-container');
|
||||
if (searchContainer && !searchContainer.contains(e.target)) {
|
||||
const resultsContainer = document.getElementById('searchResults');
|
||||
if (resultsContainer) {
|
||||
resultsContainer.style.display = 'none';
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
13
search_patient.php
Normal file
13
search_patient.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (isset($_GET['term'])) {
|
||||
$term = $_GET['term'];
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare('SELECT id, patient_id, patient_name FROM patients WHERE patient_name LIKE :term OR patient_id LIKE :term LIMIT 10');
|
||||
$stmt->execute(['term' => '%' . $term . '%']);
|
||||
$patients = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode($patients);
|
||||
}
|
||||
?>
|
||||
Loading…
x
Reference in New Issue
Block a user