945 lines
29 KiB
PHP
945 lines
29 KiB
PHP
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
|
|
<title>Doctor Search</title>
|
|
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" 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="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css">
|
|
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet"/>
|
|
<link rel="stylesheet" href="<?= base_url('css/dashboard.css') ?>">
|
|
|
|
<style>
|
|
body
|
|
{
|
|
background:#e6f1f2;
|
|
min-height:100vh;
|
|
font-family:system-ui,-apple-system,sans-serif;
|
|
}
|
|
|
|
/* Page Container */
|
|
.app-wrapper{
|
|
padding:20px;
|
|
width:100%;
|
|
max-width:none;
|
|
margin:0;
|
|
}
|
|
/* Top Filters */
|
|
.filter-bar{
|
|
background:#fff;
|
|
padding:18px;
|
|
border-radius:22px;
|
|
box-shadow:0 8px 30px rgba(0,0,0,.08);
|
|
margin-bottom:25px;
|
|
}
|
|
|
|
.search-group,
|
|
#specializationFilter,
|
|
#dateFilter,
|
|
#timeFilter,
|
|
#sortFilter{
|
|
height:48px !important;
|
|
border-radius:14px !important;
|
|
}
|
|
|
|
/* make select + inputs visually match */
|
|
#specializationFilter,
|
|
#dateFilter,
|
|
#timeFilter,
|
|
#sortFilter{
|
|
border:1px solid #d9e3ea !important;
|
|
padding:0 40px 0 16px !important;
|
|
box-shadow:none !important;
|
|
background:#fff !important;
|
|
appearance:none;
|
|
-webkit-appearance:none;
|
|
}
|
|
/* disabled time field */
|
|
#timeFilter:disabled{
|
|
background:#eef1f5 !important;
|
|
opacity:1;
|
|
}
|
|
|
|
/* align text vertically */
|
|
#specializationFilter,
|
|
#dateFilter,
|
|
#timeFilter{
|
|
line-height:48px;
|
|
}
|
|
|
|
/* Panels */
|
|
.panel-box{
|
|
background:#fff;
|
|
border-radius:22px;
|
|
padding:20px;
|
|
box-shadow:0 8px 30px rgba(0,0,0,.08);
|
|
height:100%;
|
|
}
|
|
|
|
/* Doctor Card */
|
|
.doctor-card{
|
|
padding:0;
|
|
margin-bottom:18px;
|
|
transition:.3s;
|
|
cursor:pointer;
|
|
|
|
height:auto; /* changed from 100% */
|
|
display:flex;
|
|
flex-direction:column;
|
|
}
|
|
|
|
.doctor-card{
|
|
border:1px solid transparent !important;
|
|
transition:all .25s ease;
|
|
}
|
|
|
|
.doctor-card:hover{
|
|
|
|
transform:translateY(-4px);
|
|
|
|
border:1px solid #7fd6d0 !important;
|
|
box-shadow:0 10px 20px rgba(127,214,208,.18);
|
|
|
|
background:#ffffff;
|
|
}
|
|
.doctor-card:hover .avatar{
|
|
transform:scale(1.05);
|
|
transition:.25s;
|
|
}
|
|
.doctor-top{
|
|
display:flex;
|
|
justify-content:space-between;
|
|
align-items:center;
|
|
margin-bottom:10px;
|
|
}
|
|
|
|
.doctor-profile{
|
|
display:flex;
|
|
align-items:center;
|
|
gap:12px;
|
|
}
|
|
|
|
.avatar{
|
|
/* width:56px; */
|
|
height:56px;
|
|
border-radius:50%;
|
|
/* background:#dbeafe; */
|
|
display:flex;
|
|
align-items:center;
|
|
justify-content:center;
|
|
font-weight:bold;
|
|
font-size:28px;
|
|
}
|
|
|
|
.doc-name{
|
|
font-weight:600;
|
|
font-size:16px;
|
|
margin-bottom:2px;
|
|
}
|
|
|
|
.doc-specialty{
|
|
font-size:13px;
|
|
color:#666;
|
|
}
|
|
|
|
/* Badges */
|
|
.spec-badge{
|
|
display:inline-block;
|
|
padding:6px 12px;
|
|
border-radius:30px;
|
|
background:#dff7f7;
|
|
color:#045d68;
|
|
font-size:12px;
|
|
margin-right:6px;
|
|
margin-bottom:10px;
|
|
}
|
|
/* Time Slots */
|
|
.time-slots,
|
|
.extra-slots{
|
|
display:flex;
|
|
flex-wrap:wrap;
|
|
gap:8px;
|
|
|
|
list-style:none;
|
|
padding:0;
|
|
margin:8px 0 0;
|
|
}
|
|
|
|
.slot-item{
|
|
background:#d9f7f4;
|
|
padding:5px 10px;
|
|
border-radius:10px;
|
|
font-size:13px;
|
|
line-height:1.3;
|
|
transition:.3s;
|
|
}
|
|
|
|
.slot-item:hover{
|
|
background:#b8efea;
|
|
}
|
|
|
|
/* hidden extra slots */
|
|
.extra-slots{
|
|
display:none;
|
|
width:100%;
|
|
}
|
|
|
|
/* see more */
|
|
.see-more-btn{
|
|
border:none;
|
|
background:transparent;
|
|
color:#0d6efd;
|
|
font-size:13px;
|
|
font-weight:600;
|
|
margin-top:6px;
|
|
}
|
|
|
|
/* mobile 2 per row */
|
|
@media(max-width:768px){
|
|
|
|
.slot-item{
|
|
flex:0 0 calc(50% - 6px);
|
|
}
|
|
|
|
}
|
|
|
|
/* Selected doctor box */
|
|
.selected-box{
|
|
border:2px dashed #dce6ee;
|
|
border-radius:18px;
|
|
padding:30px;
|
|
text-align:center;
|
|
color:#777;
|
|
min-height:280px;
|
|
}
|
|
|
|
/* Mobile filter button */
|
|
.mobile-filter-btn{
|
|
display:none;
|
|
}
|
|
|
|
@media(max-width:991px){
|
|
|
|
.right-panel{
|
|
margin-top:20px;
|
|
}
|
|
|
|
.middle-panel{
|
|
margin-top:20px;
|
|
}
|
|
|
|
}
|
|
|
|
@media(max-width:768px){
|
|
|
|
.filter-bar .row > div{
|
|
margin-bottom:12px;
|
|
}
|
|
|
|
.mobile-filter-btn{
|
|
display:block;
|
|
margin-bottom:15px;
|
|
}
|
|
|
|
.desktop-filter{
|
|
display:none;
|
|
}
|
|
|
|
}
|
|
#doctorList{
|
|
row-gap:10px;
|
|
}
|
|
.ov-dropdown-menu {
|
|
display: none;
|
|
padding-left: 30px;
|
|
}
|
|
|
|
/* Show when active */
|
|
.ov-nav__dropdown.active .ov-dropdown-menu {
|
|
display: block;
|
|
}
|
|
.doctor-card .card-body{
|
|
padding:14px 16px 4px 20px !important;
|
|
}
|
|
.search-group{
|
|
display:flex;
|
|
align-items:center;
|
|
border:1px solid #d9e3ea;
|
|
border-radius:14px;
|
|
overflow:hidden;
|
|
background:#fff;
|
|
height:48px;
|
|
}
|
|
|
|
.search-box{
|
|
border:none !important;
|
|
height:48px;
|
|
box-shadow:none !important;
|
|
padding-left:15px;
|
|
}
|
|
|
|
.search-box:focus{
|
|
box-shadow:none !important;
|
|
border:none !important;
|
|
}
|
|
|
|
.search-icon{
|
|
background:transparent !important;
|
|
border:none !important;
|
|
padding:0 16px;
|
|
font-size:18px;
|
|
color:#6c757d;
|
|
display:flex;
|
|
align-items:center;
|
|
justify-content:center;
|
|
}
|
|
.search-icon:hover{
|
|
color:#0d6efd;
|
|
}
|
|
.select2-container{
|
|
width:100% !important;
|
|
}
|
|
|
|
.select2-container--default .select2-selection--multiple{
|
|
|
|
height:48px !important;
|
|
min-height:48px !important;
|
|
|
|
display:flex !important;
|
|
align-items:center !important;
|
|
flex-wrap:nowrap !important;
|
|
|
|
border:1px solid #d9e3ea !important;
|
|
border-radius:14px !important;
|
|
|
|
padding:5px 38px 5px 10px !important;
|
|
|
|
overflow:hidden !important;
|
|
|
|
background:#fff !important;
|
|
}
|
|
|
|
.select2-selection__choice{
|
|
background:#d9f7f4 !important;
|
|
border:none !important;
|
|
border-radius:18px !important;
|
|
/* padding:4px 10px !important; */
|
|
margin-right:6px !important;
|
|
}
|
|
|
|
.select2-selection__rendered{
|
|
display:flex !important;
|
|
align-items:center !important;
|
|
overflow:hidden !important;
|
|
white-space:nowrap !important;
|
|
}
|
|
|
|
.select2-search__field{
|
|
margin-top:0 !important;
|
|
height:28px !important;
|
|
}
|
|
.select2-container--default .select2-selection--multiple::after{
|
|
content:"\f078";
|
|
font-family:"Font Awesome 6 Free";
|
|
font-weight:900;
|
|
|
|
position:absolute;
|
|
right:14px;
|
|
top:50%;
|
|
transform:translateY(-50%);
|
|
|
|
font-size:12px;
|
|
color:#6c757d;
|
|
}
|
|
/* mouse pointer on multiselect box */
|
|
.select2-container--default .select2-selection--multiple{
|
|
cursor:pointer !important;
|
|
}
|
|
|
|
/* pointer specifically on chevron */
|
|
.select2-container--default
|
|
.select2-selection--multiple::after{
|
|
pointer-events:none; /* keep arrow decorative */
|
|
}
|
|
|
|
/* pointer on all visible text/chips too */
|
|
.select2-selection__rendered,
|
|
.select2-selection__choice{
|
|
cursor:pointer !important;
|
|
}
|
|
.sort-wrap{
|
|
position:relative;
|
|
}
|
|
|
|
.sort-wrap::after{
|
|
content:"\f078";
|
|
font-family:"Font Awesome 6 Free";
|
|
font-weight:900;
|
|
|
|
position:absolute;
|
|
right:14px;
|
|
top:50%;
|
|
transform:translateY(-50%);
|
|
|
|
font-size:12px;
|
|
color:#6c757d;
|
|
|
|
pointer-events:none;
|
|
}
|
|
.form-label{
|
|
font-size:14px;
|
|
color:#495057;
|
|
margin-left:4px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body class="app-body overview-layout">
|
|
|
|
<!-- Sidebar -->
|
|
<aside class="ov-sidebar" id="sidebar">
|
|
<div class="ov-brand">
|
|
<h1><i class="bi bi-hospital me-1"></i> DoctGuide</h1>
|
|
<span>Control Panel</span>
|
|
</div>
|
|
|
|
<nav class="ov-nav">
|
|
<div class="ov-nav__section">Main</div>
|
|
<a href="<?= base_url('admin/dashboard') ?>" class="ov-nav__link">
|
|
<i class="bi bi-speedometer2"></i> Dashboard
|
|
</a>
|
|
|
|
<div class="ov-nav__section">Manage</div>
|
|
<div class="ov-nav__dropdown active">
|
|
<a href="#" class="ov-nav__link d-flex justify-content-between align-items-center" onclick="toggleNavDropdown(event, this)">
|
|
<span><i class="bi bi-people"></i> Patients</span>
|
|
<i class="bi bi-chevron-down dropdown-icon"></i>
|
|
</a>
|
|
<div class="ov-dropdown-menu">
|
|
<a href="<?= base_url('admin/patients') ?>" class="ov-nav__sublink">Patient List</a>
|
|
</div>
|
|
</div>
|
|
|
|
<a href="<?= base_url('admin/appointments') ?>" class="ov-nav__link">
|
|
<i class="bi bi-calendar2-check"></i> Appointments
|
|
</a>
|
|
</nav>
|
|
|
|
<div class="ov-sidebar__footer">
|
|
<a href="<?= base_url('logout') ?>">
|
|
<i class="bi bi-box-arrow-left"></i> Logout
|
|
</a>
|
|
</div>
|
|
</aside>
|
|
|
|
<div class="ov-main" id="mainContent">
|
|
<header class="ov-topbar">
|
|
<div class="d-flex align-items-center">
|
|
<button class="ov-toggle-btn" onclick="toggleSidebar()">
|
|
<i class="bi bi-list" id="toggleIcon"></i>
|
|
</button>
|
|
<p class="ov-topbar__title mb-0">Doctor Search</p>
|
|
</div>
|
|
</header>
|
|
|
|
<main class="ov-content">
|
|
<div class="container-fluid">
|
|
|
|
<!-- Mobile Filter Trigger -->
|
|
<button class="btn btn-primary mobile-filter-btn"
|
|
data-bs-toggle="offcanvas"
|
|
data-bs-target="#filterCanvas">
|
|
Filters
|
|
</button>
|
|
|
|
<!-- Desktop Filters -->
|
|
<!-- Filter Card -->
|
|
<div class="card shadow-sm border-0 rounded-4 mb-4 desktop-filter">
|
|
|
|
<div class="card-header bg-white py-3 rounded-top-4">
|
|
<h5 class="mb-0">
|
|
<i class="bi bi-funnel me-2"></i>
|
|
Advance Search Filters
|
|
</h5>
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<div class="row g-3">
|
|
|
|
<div class="col-lg-4 col-md-6">
|
|
<div class="input-group search-group">
|
|
|
|
<input type="text"
|
|
id="searchInput"
|
|
class="form-control search-box"
|
|
placeholder="Search doctor or speciality">
|
|
|
|
<span class="input-group-text search-icon">
|
|
<i class="fa-solid fa-magnifying-glass"></i>
|
|
</span>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-lg-3 col-md-6">
|
|
<?= view('components/select2_multiselect',[
|
|
'id' => 'specializationFilter',
|
|
'name' => 'specialization',
|
|
'placeholder' => 'Filter Specialization',
|
|
|
|
'options' => array_column($specializations,'name')
|
|
]); ?>
|
|
</div>
|
|
|
|
<div class="col-lg-2 col-md-6 col-6">
|
|
<input type="date"
|
|
id="dateFilter"
|
|
class="form-control">
|
|
</div>
|
|
|
|
<div class="col-lg-2 col-md-6 col-6">
|
|
<input type="time"
|
|
id="timeFilter"
|
|
class="form-control"
|
|
disabled>
|
|
</div>
|
|
|
|
<div class="col-lg-4 col-md-6 col-6">
|
|
|
|
<div class="d-flex align-items-center gap-2">
|
|
|
|
<label for="sortFilter"
|
|
class="mb-0 fw-semibold text-muted">
|
|
Sort By
|
|
</label>
|
|
|
|
<div class="sort-wrap flex-grow-1">
|
|
<select id="sortFilter" class="form-control">
|
|
<option value="name_asc" selected>Name (A-Z)</option>
|
|
<option value="name_desc">Name (Z-A)</option>
|
|
<option value="fees_low">Fees (Low to High)</option>
|
|
<option value="fees_high">Fees (High to Low)</option>
|
|
</select>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- Main 3 Panels -->
|
|
<div class="row g-4">
|
|
<div class="col-12">
|
|
|
|
<div class="card shadow-sm border-0 rounded-4">
|
|
|
|
<div class="card-header bg-white py-3 rounded-top-4">
|
|
<h5 class="mb-0">
|
|
<i class="bi bi-person-badge me-2"></i>
|
|
Available Doctors
|
|
</h5>
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<div class="row g-4" id="doctorList">
|
|
|
|
<?php foreach ($doctors as $doctor): ?>
|
|
|
|
<div class="col-lg-4 col-md-6 col-12 doctor-card-container"
|
|
data-doctor-id="<?= esc($doctor['id']) ?>"
|
|
data-doctor-name="<?= esc(strtolower($doctor['first_name'].' '.$doctor['last_name'])) ?>"
|
|
data-specialization="<?= esc(strtolower(implode(', ', array_column($doctor['specializations'] ?? [], 'name')))) ?>"
|
|
data-availability='<?= json_encode($doctor['availabilityByDate']) ?>'
|
|
data-fees="<?= !empty($doctor['fees']) ? (float)$doctor['fees'] : 0 ?>"
|
|
data-fees-missing="<?= empty($doctor['fees']) ? 1 : 0 ?>">
|
|
|
|
<div class="card h-100 shadow-sm border-0 rounded-4 doctor-card">
|
|
|
|
<div class="card-body">
|
|
|
|
<div class="d-flex justify-content-between align-items-start mb-3">
|
|
|
|
<div class="d-flex align-items-center gap-3">
|
|
|
|
<div class="avatar">
|
|
<i class="fa-solid fa-user-doctor"></i>
|
|
</div>
|
|
|
|
<div>
|
|
<h6 class="mb-1 fw-bold">
|
|
Dr <?= esc($doctor['first_name']) ?>
|
|
<?= esc($doctor['last_name']) ?>
|
|
</h6>
|
|
|
|
<small class="text-muted">
|
|
|
|
<?php if(!empty($doctor['specializations'])): ?>
|
|
|
|
<?php $spec = $doctor['specializations'][0]; ?>
|
|
|
|
<span class="badge rounded-pill me-1"
|
|
style="
|
|
background:<?= esc($spec['bg_color']) ?>;
|
|
color:<?= esc($spec['text_color']) ?>;
|
|
">
|
|
<?= esc($spec['name']) ?>
|
|
</span>
|
|
|
|
<?php else: ?>
|
|
Not Set
|
|
<?php endif; ?>
|
|
|
|
|
|
|
|
|
<?php if(!empty($doctor['experience'])): ?>
|
|
<?= esc($doctor['experience']) ?> yrs exp.
|
|
<?php else: ?>
|
|
Not Set
|
|
<?php endif; ?>
|
|
|
|
</small>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<span>⭐</span>
|
|
|
|
</div>
|
|
<?php
|
|
if(!empty($doctor['specializations']) && count($doctor['specializations']) > 1):
|
|
?>
|
|
|
|
<div class="mb-2">
|
|
|
|
<?php for($i=1; $i<count($doctor['specializations']); $i++):
|
|
$spec = $doctor['specializations'][$i];
|
|
?>
|
|
|
|
<span class="badge rounded-pill me-1 mb-2"
|
|
style="
|
|
background:<?= esc($spec['bg_color']) ?>;
|
|
color:<?= esc($spec['text_color']) ?>;
|
|
">
|
|
<?= esc($spec['name']) ?>
|
|
</span>
|
|
|
|
<?php endfor; ?>
|
|
|
|
</div>
|
|
|
|
<?php endif; ?>
|
|
<p class="mb-2">
|
|
<strong>Fees:</strong>
|
|
|
|
<?php if(!empty($doctor['fees'])): ?>
|
|
₹<?= esc($doctor['fees']) ?>
|
|
<?php else: ?>
|
|
Not Set
|
|
<?php endif; ?>
|
|
|
|
</p>
|
|
<p class="mb-1 fw-semibold">
|
|
Availability
|
|
</p>
|
|
|
|
<ul class="time-slots">
|
|
|
|
<?php if(!empty($doctor['timeSlots'])): ?>
|
|
|
|
<?php foreach($doctor['timeSlots'] as $index=>$slot): ?>
|
|
|
|
<?php if($index < 4): ?>
|
|
<li class="slot-item">
|
|
<?= $slot['day'] ?> - <?= $slot['start'] ?> to <?= $slot['end'] ?>
|
|
</li>
|
|
<?php endif; ?>
|
|
|
|
<?php endforeach; ?>
|
|
|
|
<?php else: ?>
|
|
|
|
<li class="text-muted">Not Set</li>
|
|
|
|
<?php endif; ?>
|
|
|
|
</ul>
|
|
|
|
<?php if(isset($doctor['timeSlots']) && is_array($doctor['timeSlots']) && count($doctor['timeSlots']) > 4): ?>
|
|
|
|
<ul class="extra-slots">
|
|
|
|
<?php for($i=4; $i<count($doctor['timeSlots']); $i++):
|
|
$slot = $doctor['timeSlots'][$i];
|
|
?>
|
|
|
|
<li class="slot-item">
|
|
<?= $slot['day'] ?> - <?= $slot['start'] ?> to <?= $slot['end'] ?>
|
|
</li>
|
|
|
|
<?php endfor; ?>
|
|
|
|
</ul>
|
|
|
|
<button class="see-more-btn" onclick="toggleSlots(this)">
|
|
See More
|
|
</button>
|
|
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php endforeach; ?>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</main>
|
|
</div>
|
|
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
|
|
|
<!-- JavaScript for sidebar toggle -->
|
|
<script>
|
|
function toggleSidebar() {
|
|
const sidebar =
|
|
document.getElementById('sidebar');
|
|
|
|
const main =
|
|
document.getElementById('mainContent');
|
|
|
|
const icon =
|
|
document.getElementById('toggleIcon');
|
|
|
|
sidebar.classList.toggle('collapsed');
|
|
main.classList.toggle('expanded');
|
|
|
|
icon.className =
|
|
sidebar.classList.contains('collapsed')
|
|
? 'bi bi-layout-sidebar'
|
|
: 'bi bi-list';
|
|
}
|
|
function toggleNavDropdown(event, element){
|
|
event.preventDefault();
|
|
|
|
const parent =
|
|
element.closest('.ov-nav__dropdown');
|
|
|
|
const icon =
|
|
element.querySelector('.dropdown-icon');
|
|
|
|
parent.classList.toggle('active');
|
|
|
|
icon.classList.toggle('rotated');
|
|
}
|
|
</script>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script>
|
|
// Toggle slots function
|
|
function toggleSlots(btn){
|
|
let extra = btn.previousElementSibling;
|
|
|
|
if(extra.style.display==="flex"){
|
|
extra.style.display="none";
|
|
btn.innerText="See More";
|
|
}else{
|
|
extra.style.display="flex";
|
|
btn.innerText="Show Less";
|
|
}
|
|
}
|
|
|
|
// Filter functionality
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const searchInput = document.getElementById('searchInput');
|
|
const specializationFilter = document.getElementById('specializationFilter');
|
|
const dateFilter = document.getElementById('dateFilter');
|
|
const timeFilter = document.getElementById('timeFilter');
|
|
const doctorCards = document.querySelectorAll('.doctor-card-container');
|
|
const sortFilter = document.getElementById('sortFilter');
|
|
sortFilter.addEventListener('change', function(){
|
|
applyFilters();
|
|
});
|
|
|
|
// Enable/disable time filter based on date selection
|
|
dateFilter.addEventListener('change', function() {
|
|
if (this.value) {
|
|
timeFilter.disabled = false;
|
|
timeFilter.removeAttribute('title');
|
|
} else {
|
|
timeFilter.disabled = true;
|
|
timeFilter.value = '';
|
|
timeFilter.setAttribute('title', 'Please select a date first');
|
|
}
|
|
applyFilters();
|
|
});
|
|
|
|
// Add event listeners to all filter inputs
|
|
searchInput.addEventListener('keyup', applyFilters);
|
|
$('#specializationFilter').on('change',applyFilters);
|
|
timeFilter.addEventListener('change', applyFilters);
|
|
applyFilters();
|
|
function applyFilters() {
|
|
const searchValue = searchInput.value.toLowerCase().trim();
|
|
const specializationValues = $('#specializationFilter').val() || [];
|
|
const dateValue = dateFilter.value;
|
|
const timeValue = timeFilter.value;
|
|
let visibleCount = 0;
|
|
|
|
doctorCards.forEach(card => {
|
|
let show = true;
|
|
|
|
// Filter by search (doctor name or specialization)
|
|
if (searchValue) {
|
|
const doctorName = card.getAttribute('data-doctor-name');
|
|
const specialization = card.getAttribute('data-specialization');
|
|
if (!doctorName.includes(searchValue) && !specialization.includes(searchValue)) {
|
|
show = false;
|
|
}
|
|
}
|
|
|
|
// Filter by specialization
|
|
if(show && specializationValues.length > 0){
|
|
|
|
const specialization =
|
|
card.getAttribute('data-specialization');
|
|
|
|
const selected =
|
|
specializationValues.map(v=>v.toLowerCase());
|
|
|
|
// if(!selected.includes(specialization)){
|
|
// show = false;
|
|
// }
|
|
const doctorSpecs = specialization
|
|
.split(',')
|
|
.map(s => s.trim());
|
|
|
|
const matched = selected.some(s =>
|
|
doctorSpecs.includes(s)
|
|
);
|
|
|
|
if(!matched){
|
|
show = false;
|
|
}
|
|
|
|
}
|
|
|
|
// Filter by date and time
|
|
// Filter by date and time
|
|
if (show && dateValue) {
|
|
const availabilityJSON = card.getAttribute('data-availability');
|
|
const availability = JSON.parse(availabilityJSON);
|
|
|
|
// Check if doctor has availability on the selected date
|
|
if (!availability[dateValue]) {
|
|
show = false;
|
|
} else if (timeValue) {
|
|
// Check if any slot's start time matches the selected time
|
|
const slots = availability[dateValue].slots || [];
|
|
const match = slots.some(slot => {
|
|
// slot.start is "06:27 PM", convert timeValue "18:27" to compare
|
|
const [h, m] = timeValue.split(':').map(Number);
|
|
const slotDate = new Date();
|
|
slotDate.setHours(h, m, 0);
|
|
const slotStart = new Date();
|
|
const [sh, sm] = slot.start_24.split(':').map(Number);
|
|
slotStart.setHours(sh, sm, 0);
|
|
return slotDate >= slotStart;
|
|
});
|
|
if (!match) show = false;
|
|
}
|
|
}
|
|
|
|
// Show or hide the card
|
|
if (show) {
|
|
card.style.display = '';
|
|
visibleCount++;
|
|
} else {
|
|
card.style.display = 'none';
|
|
}
|
|
});
|
|
|
|
const doctorList = document.getElementById('doctorList');
|
|
|
|
let cardsArray =
|
|
Array.from(document.querySelectorAll('.doctor-card-container'))
|
|
.filter(card => card.style.display !== 'none');
|
|
|
|
const sortValue = sortFilter.value;
|
|
|
|
if(sortValue === 'name_asc'){
|
|
cardsArray.sort((a,b)=>
|
|
a.dataset.doctorName.localeCompare(b.dataset.doctorName)
|
|
);
|
|
}
|
|
|
|
if(sortValue === 'name_desc'){
|
|
cardsArray.sort((a,b)=>
|
|
b.dataset.doctorName.localeCompare(a.dataset.doctorName)
|
|
);
|
|
}
|
|
|
|
if(sortValue === 'fees_low'){
|
|
cardsArray.sort((a,b)=>{
|
|
let af = parseFloat(a.dataset.fees);
|
|
let bf = parseFloat(b.dataset.fees);
|
|
|
|
if(af===0) return 1;
|
|
if(bf===0) return -1;
|
|
|
|
return af-bf;
|
|
});
|
|
}
|
|
|
|
if(sortValue === 'fees_high'){
|
|
cardsArray.sort((a,b)=>{
|
|
let af = parseFloat(a.dataset.fees);
|
|
let bf = parseFloat(b.dataset.fees);
|
|
|
|
if(af===0) return 1;
|
|
if(bf===0) return -1;
|
|
|
|
return bf-af;
|
|
});
|
|
}
|
|
|
|
cardsArray.forEach(card=>{
|
|
doctorList.appendChild(card);
|
|
});
|
|
|
|
// Show "No results" message if no doctors match filters
|
|
let noResultsMsg = doctorList.querySelector('.no-results-msg');
|
|
|
|
if (visibleCount === 0) {
|
|
if (!noResultsMsg) {
|
|
noResultsMsg = document.createElement('div');
|
|
noResultsMsg.className = 'col-12 no-results-msg';
|
|
noResultsMsg.innerHTML = '<p class="text-center text-muted">No doctors match your filters.</p>';
|
|
doctorList.appendChild(noResultsMsg);
|
|
}
|
|
noResultsMsg.style.display = '';
|
|
} else if (noResultsMsg) {
|
|
noResultsMsg.style.display = 'none';
|
|
}
|
|
}
|
|
});
|
|
</script>
|
|
<script src="<?= base_url('js/components/select2-init.js') ?>"></script>
|
|
</body>
|
|
</html>
|