577 lines
27 KiB
PHP
577 lines
27 KiB
PHP
<?php
|
|
$patient = $patient ?? null;
|
|
$service_names = $service_names ?? [];
|
|
$services = $services ?? [];
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Appointment Preview</title>
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/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://cdn.datatables.net/1.13.7/css/dataTables.bootstrap5.min.css">
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" rel="stylesheet">
|
|
<link rel="stylesheet" href="<?= base_url('css/app.css') ?>">
|
|
<link rel="stylesheet" href="<?= base_url('css/dashboard.css') ?>">
|
|
<style>
|
|
.toggle-expand-btn {
|
|
padding: 0;
|
|
font-size: 0.75rem;
|
|
text-decoration: none;
|
|
color: #0d6efd;
|
|
cursor: pointer;
|
|
display: inline-block;
|
|
margin-top: 4px;
|
|
}
|
|
.toggle-expand-btn:hover {
|
|
text-decoration: underline;
|
|
}
|
|
.expandable-container {
|
|
transition: all 0.3s ease;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body class="app-body overview-layout">
|
|
<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">
|
|
<a href="#" class="ov-nav__link d-flex justify-content-between align-items-center" onclick="toggleNavDropdown(event, this)">
|
|
<span><i class="bi bi-person-badge"></i> Doctors</span>
|
|
<i class="bi bi-chevron-down dropdown-icon"></i>
|
|
</a>
|
|
<div class="ov-dropdown-menu">
|
|
<a href="<?= base_url('admin/doctors') ?>" class="ov-nav__sublink">Doctor List</a>
|
|
<a href="<?= base_url('admin/doctors/add') ?>" class="ov-nav__sublink">Add Doctor</a>
|
|
</div>
|
|
</div>
|
|
<div class="ov-nav__dropdown">
|
|
<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>
|
|
<a href="<?= base_url('admin/patients/add') ?>" class="ov-nav__sublink">Add Patient</a>
|
|
</div>
|
|
</div>
|
|
<a href="<?= base_url('admin/appointments') ?>" class="ov-nav__link active"><i class="bi bi-calendar2-check"></i> Appointments</a>
|
|
<a href="<?= base_url('admin/activity-log') ?>" class="ov-nav__link"><i class="bi bi-clipboard-data"></i> Activity Log</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 w-100 gap-3">
|
|
|
|
<!-- Left Section -->
|
|
<div class="d-flex align-items-center gap-2">
|
|
<button class="ov-toggle-btn" onclick="toggleSidebar()" title="Toggle Sidebar">
|
|
<i class="bi bi-list" id="toggleIcon"></i>
|
|
</button>
|
|
|
|
<p class="ov-topbar__title mb-0">Appointment Preview</p>
|
|
</div>
|
|
|
|
<!-- Right Button -->
|
|
<a href="<?= base_url('admin/appointments') ?>"
|
|
class="btn btn-sm btn-outline-secondary px-3 ms-auto">
|
|
Back to Appointments
|
|
</a>
|
|
|
|
</div>
|
|
</header>
|
|
|
|
<main class="ov-content">
|
|
<div class="p-3">
|
|
<div class="card mb-3 shadow-sm">
|
|
<div class="card-header bg-light fw-semibold">
|
|
<i class="bi bi-person-vcard me-2"></i>Appointment Details
|
|
</div>
|
|
<div class="card-body">
|
|
<?php
|
|
$patientRecord = is_array($patient ?? null) ? $patient : [];
|
|
$fullName = trim(((string) ($patientRecord['first_name'] ?? '')) . ' ' . ((string) ($patientRecord['last_name'] ?? '')));
|
|
if ($fullName === '') {
|
|
$fullName = 'Not Available';
|
|
}
|
|
|
|
$gender = $patientRecord['patient_gender'] ?? $patientRecord['user_gender'] ?? null;
|
|
$serviceNameList = is_array($service_names ?? null) ? $service_names : [];
|
|
$serviceSummary = $serviceNameList !== [] ? implode(', ', $serviceNameList) : 'Not Specified';
|
|
|
|
?>
|
|
<div class="row">
|
|
|
|
<!-- LEFT SIDE -->
|
|
<div class="col-md-6 border-end pe-4">
|
|
<h6 class="section-title">Patient Info</h6>
|
|
|
|
<div class="row g-2">
|
|
<div class="col-md-8">
|
|
<strong>Patient ID:</strong><br>
|
|
<?= esc($patientRecord['formatted_user_id'] ?? 'N/A') ?>
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<strong>Full Name:</strong><br>
|
|
<span class="fw-semibold"><?= esc($fullName) ?></span>
|
|
</div>
|
|
|
|
<div class="col-md-8">
|
|
<strong>Contact:</strong><br>
|
|
|
|
<?php
|
|
$phone = $patientRecord['phone'] ?? '';
|
|
$email = $patientRecord['email'] ?? '';
|
|
?>
|
|
|
|
<div class="d-flex align-items-center flex-wrap gap-3 mt-1">
|
|
|
|
<!-- PHONE -->
|
|
<a
|
|
href="<?= $phone ? 'tel:' . esc($phone) : '#' ?>"
|
|
class="text-decoration-none text-primary d-flex align-items-center gap-1"
|
|
>
|
|
<i class="bi bi-telephone-fill"></i>
|
|
<?= $phone ? esc($phone) : 'Not Available' ?>
|
|
</a>
|
|
|
|
<!-- EMAIL -->
|
|
<a
|
|
href="<?= $email ? 'mailto:' . esc($email) : '#' ?>"
|
|
class="text-decoration-none text-primary d-flex align-items-center gap-1"
|
|
>
|
|
<i class="bi bi-envelope-fill"></i>
|
|
<?= $email ? esc($email) : 'Not Available' ?>
|
|
</a>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<!-- <div class="col-md-6">
|
|
<strong>Email:</strong><br>
|
|
<?= esc($patientRecord['email'] ?? 'Not Available') ?>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<strong>Phone:</strong><br>
|
|
<?= esc($patientRecord['phone'] ?? 'Not Available') ?>
|
|
</div> -->
|
|
|
|
<div class="col-md-4">
|
|
<strong>Gender:</strong><br>
|
|
<?= esc($gender ?: 'Not Available') ?>
|
|
</div>
|
|
|
|
<!-- <div class="col-md-12">
|
|
<strong>Requested Service:</strong><br>
|
|
<?= esc($serviceSummary) ?>
|
|
</div>
|
|
|
|
<div class="col-md-12">
|
|
<strong>Preferred Date & Time:</strong><br>
|
|
<?= esc(($date ?? '-') . ' ' . ($time ?? '-')) ?>
|
|
</div> -->
|
|
</div>
|
|
</div>
|
|
|
|
<!-- RIGHT SIDE -->
|
|
<div class="col-md-4 ps-4">
|
|
<h6 class="section-title">Preferences</h6>
|
|
|
|
<div class="info-box">
|
|
<strong>Requested Service:</strong><br>
|
|
<?= esc($serviceSummary) ?>
|
|
</div>
|
|
|
|
<div class="info-box">
|
|
<strong>Preferred Date & Time:</strong><br>
|
|
<?php
|
|
$displayDate = $date ?? '-';
|
|
$displayTime = $time ?? '-';
|
|
if ($displayTime !== '-' && $displayTime !== '') {
|
|
$displayTime = date('h:i A', strtotime($displayTime));
|
|
}
|
|
echo esc($displayDate . ' ' . $displayTime);
|
|
?>
|
|
</div>
|
|
|
|
<div class="info-box">
|
|
<strong>Preferred Physician:</strong><br>
|
|
<?= esc($doctor ?? 'Not Available') ?>
|
|
</div>
|
|
|
|
<!-- <div class="info-box">
|
|
<strong>Preferred Languages:</strong><br>
|
|
English, French
|
|
</div> -->
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
<!-- <div class="card-body">
|
|
<?php
|
|
$patientRecord = is_array($patient ?? null) ? $patient : [];
|
|
$fullName = trim(((string) ($patientRecord['first_name'] ?? '')) . ' ' . ((string) ($patientRecord['last_name'] ?? '')));
|
|
if ($fullName === '') {
|
|
$fullName = 'Not Available';
|
|
}
|
|
|
|
$gender = $patientRecord['patient_gender'] ?? $patientRecord['user_gender'] ?? null;
|
|
$serviceNameList = is_array($service_names ?? null) ? $service_names : [];
|
|
$serviceSummary = $serviceNameList !== [] ? implode(', ', $serviceNameList) : 'Not Specified';
|
|
?>
|
|
<div class="row g-3">
|
|
<div class="col-md-4"><strong>Patient ID:</strong> <?= esc($patientRecord['formatted_user_id'] ?? 'N/A') ?></div>
|
|
<div class="col-md-4"><strong>Full Name:</strong> <?= esc($fullName) ?></div>
|
|
<div class="col-md-4"><strong>Email:</strong> <?= esc($patientRecord['email'] ?? 'Not Available') ?></div>
|
|
<div class="col-md-4"><strong>Phone:</strong> <?= esc($patientRecord['phone'] ?? 'Not Available') ?></div>
|
|
<div class="col-md-4"><strong>DOB:</strong> <?= esc($patientRecord['dob'] ?? 'Not Available') ?></div>
|
|
<div class="col-md-4"><strong>Gender:</strong> <?= esc($gender ?: 'Not Available') ?></div>
|
|
<div class="col-md-4"><strong>Status:</strong> <?= esc($patientRecord['status'] ?? 'Not Available') ?></div>
|
|
<div class="col-md-8"><strong>Requested Service:</strong> <?= esc($serviceSummary) ?></div>
|
|
<div class="col-md-4"><strong>Preferred Date & Time:</strong> <?= esc(($date ?? '-') . ' ' . ($time ?? '-')) ?></div>
|
|
</div>
|
|
</div> -->
|
|
</div>
|
|
|
|
<div class="card shadow-sm">
|
|
<div class="card-header bg-light fw-semibold">
|
|
<i class="bi bi-person-badge me-2"></i>Physician List
|
|
</div>
|
|
<div class="card-body">
|
|
<table id="doctorTable" class="table table-hover" style="width:100%">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th>#ID</th>
|
|
<th>Name</th>
|
|
<th>Specialization</th>
|
|
<th>Experience</th>
|
|
<th>Availability</th>
|
|
<th>Status</th>
|
|
<th>Action</th>
|
|
</tr>
|
|
</thead>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- <div class="ov-panel">
|
|
<div class="ov-panel__header">
|
|
<h2 class="ov-panel__title">Appointment Preview</h2>
|
|
|
|
</div>
|
|
|
|
|
|
</div> -->
|
|
</main>
|
|
</div>
|
|
|
|
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
|
<script src="https://cdn.datatables.net/1.13.7/js/jquery.dataTables.min.js"></script>
|
|
<script src="https://cdn.datatables.net/1.13.7/js/dataTables.bootstrap5.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script>
|
|
let doctorTable = null;
|
|
const previewPatientId = <?= json_encode((int) ($patient_id ?? 0)) ?>;
|
|
const previewDate = <?= json_encode((string) ($date ?? '')) ?>;
|
|
const previewTime = <?= json_encode((string) ($time ?? '')) ?>;
|
|
const previewServices = <?= json_encode(array_values(is_array($services ?? []) ? $services : [])) ?>;
|
|
const previewId = <?= json_encode((int) ($preview_id ?? 0)) ?>;
|
|
|
|
function escapeHtml(value) {
|
|
return String(value ?? '')
|
|
.replace(/&/g, '&')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
.replace(/"/g, '"')
|
|
.replace(/'/g, ''');
|
|
}
|
|
|
|
$(document).ready(function() {
|
|
doctorTable = $('#doctorTable').DataTable({
|
|
processing: true,
|
|
ajax: {
|
|
url: "<?= base_url('admin/available-doctors') ?>",
|
|
method: 'POST',
|
|
data: {
|
|
date: previewDate,
|
|
time: previewTime,
|
|
preview_id: previewId,
|
|
specialization_id: previewServices
|
|
},
|
|
dataSrc: 'data',
|
|
error: function() {
|
|
$('#doctorTable tbody').html('<tr><td colspan="7" class="text-danger text-center">Failed to load doctors. Please try again later.</td></tr>');
|
|
}
|
|
},
|
|
columns: [
|
|
{
|
|
data: 'formatted_doctor_id',
|
|
render: function(data, type, row) {
|
|
const formattedId = escapeHtml(data || 'N/A');
|
|
if (type !== 'display' || !row.doctor_edit_token) {
|
|
return formattedId;
|
|
}
|
|
const url = "<?= base_url('admin/doctors/edit') ?>/" + encodeURIComponent(row.doctor_edit_token);
|
|
return `<a href="${url}" class="text-decoration-none fw-semibold">${formattedId}</a>`;
|
|
}
|
|
},
|
|
{ data: 'name' },
|
|
{
|
|
data: 'specializations',
|
|
render: function(data, type, row) {
|
|
if (!Array.isArray(data) || data.length === 0) {
|
|
return '<span class="text-muted">Not Assigned</span>';
|
|
}
|
|
|
|
const limit = 2;
|
|
const hasMore = data.length > limit;
|
|
const rowId = row.id || Math.random().toString(36).substr(2, 9);
|
|
|
|
let html = `<div class="expandable-container" id="spec-container-${rowId}">`;
|
|
|
|
data.forEach((spec, index) => {
|
|
const bg = spec.bg_color || '#e9ecef';
|
|
const text = spec.text_color || '#212529';
|
|
const isHidden = index >= limit ? 'd-none' : '';
|
|
|
|
html += `<span class="badge me-1 mb-1 ${isHidden}" style="background-color: ${escapeHtml(bg)}; color: ${escapeHtml(text)}; border: 1px solid rgba(0,0,0,0.1);">
|
|
${escapeHtml(spec.name)}
|
|
</span>`;
|
|
});
|
|
|
|
html += '</div>';
|
|
|
|
if (hasMore) {
|
|
html += `<a href="javascript:void(0);" class="toggle-expand-btn" onclick="toggleExpand(this, 'spec-container-${rowId}')">Show more</a>`;
|
|
}
|
|
|
|
return html;
|
|
}
|
|
},
|
|
{
|
|
data: 'experience',
|
|
render: function(data) {
|
|
if (!data || data === '0' || data === 0) {
|
|
return '<span class="text-muted">No Experience</span>';
|
|
}
|
|
|
|
let display = escapeHtml(data);
|
|
// If it's just a number (e.g. "12"), format it as "12 Years"
|
|
if (/^\d+$/.test(data)) {
|
|
display = data + (parseInt(data) === 1 ? ' Year' : ' Years');
|
|
}
|
|
|
|
return `<span class="badge bg-info-subtle text-info-emphasis border border-info-subtle px-2 py-1">
|
|
<i class="bi bi-briefcase me-1"></i>${display}
|
|
</span>`;
|
|
}
|
|
},
|
|
{
|
|
data: null,
|
|
render: function(data, type, row) {
|
|
const days = Array.isArray(row.available_days) ? row.available_days : [];
|
|
const allSlots = Array.isArray(row.all_slots) ? row.all_slots : [];
|
|
|
|
if (days.length === 0) {
|
|
return '<span class="text-muted">Not Available</span>';
|
|
}
|
|
|
|
const limit = 2;
|
|
let slotCount = 0;
|
|
const rowId = row.id || Math.random().toString(36).substr(2, 9);
|
|
|
|
let html = `<div class="expandable-container d-flex flex-wrap gap-2" id="slot-container-${rowId}">`;
|
|
|
|
days.forEach(day => {
|
|
const daySlots = allSlots.filter(slot => slot.day === day);
|
|
|
|
if (daySlots.length > 0) {
|
|
daySlots.forEach(slot => {
|
|
slotCount++;
|
|
const isHidden = slotCount > limit ? 'd-none' : '';
|
|
const dayAbbrev = day.substring(0, 3);
|
|
|
|
html += `
|
|
<span class="badge bg-primary-subtle text-primary-emphasis border border-primary-subtle px-2 py-1 ${isHidden}">
|
|
<i class="bi bi-calendar-day me-1"></i>${escapeHtml(dayAbbrev)}
|
|
<span class="fw-bold mx-1">|</span>
|
|
<i class="bi bi-clock me-1"></i>${escapeHtml(slot.start_time_formatted)} - ${escapeHtml(slot.end_time_formatted)}
|
|
</span>
|
|
`;
|
|
});
|
|
} else {
|
|
slotCount++;
|
|
const isHidden = slotCount > limit ? 'd-none' : '';
|
|
const dayAbbrev = day.substring(0, 3);
|
|
|
|
html += `
|
|
<span class="badge bg-secondary-subtle text-secondary-emphasis border border-secondary-subtle px-2 py-1 ${isHidden}">
|
|
<i class="bi bi-calendar-day me-1"></i>${escapeHtml(dayAbbrev)}
|
|
<span class="fw-bold mx-1">|</span>
|
|
<i class="bi bi-x-circle me-1"></i>No Slots
|
|
</span>
|
|
`;
|
|
}
|
|
});
|
|
|
|
html += '</div>';
|
|
|
|
if (slotCount > limit) {
|
|
html += `<a href="javascript:void(0);" class="toggle-expand-btn" onclick="toggleExpand(this, 'slot-container-${rowId}')">Show more</a>`;
|
|
}
|
|
|
|
return html;
|
|
}
|
|
},
|
|
// {
|
|
// data: 'available_days',
|
|
// render: function(data, type, row) {
|
|
// const days = Array.isArray(data) ? data : [];
|
|
// const text = row.available_days_text || 'Not Assigned';
|
|
// if (type !== 'display') {
|
|
// return text;
|
|
// }
|
|
// if (days.length === 0) {
|
|
// return '<span class="text-muted">Not Assigned</span>';
|
|
// }
|
|
// return days.map(day => `<span class="badge bg-info-subtle text-info-emphasis border border-info-subtle me-1 mb-1">${escapeHtml(day)}</span>`).join('');
|
|
// }
|
|
// },
|
|
// {
|
|
// data: 'time_slots',
|
|
// render: function(data) {
|
|
// if (!Array.isArray(data) || data.length === 0) {
|
|
// return '<span class="badge bg-warning text-dark">No Available Slots</span>';
|
|
// }
|
|
// return data.map(slot => `<span class="badge bg-info me-1">${escapeHtml(slot.start_time_formatted)} - ${escapeHtml(slot.end_time_formatted)}</span>`).join('<br>');
|
|
// }
|
|
// },
|
|
{
|
|
data: 'status',
|
|
render: function(data) {
|
|
if (data === 'Available') return '<span class="badge bg-success">Available</span>';
|
|
if (data === 'Booked') return '<span class="badge bg-danger">Assigned</span>';
|
|
return '<span class="badge bg-warning text-dark">Not Available</span>';
|
|
}
|
|
},
|
|
{
|
|
data: null,
|
|
render: function(data) {
|
|
if (data.status === 'Available') {
|
|
return `<button class="book-btn btn btn-success btn-sm" data-doctor="${escapeHtml(data.id)}">Assign</button>`;
|
|
} else if (data.status === 'Booked') {
|
|
return '<button class="btn btn-secondary btn-sm" disabled>Assigned</button>';
|
|
} else {
|
|
return '<button class="btn btn-secondary btn-sm" disabled>Not Available</button>';
|
|
}
|
|
}
|
|
}
|
|
],
|
|
pageLength: 10,
|
|
lengthMenu: [[10, 25, 50, -1], [10, 25, 50, 'All']],
|
|
order: [[0, 'asc']],
|
|
dom: '<"row mb-3"<"col-md-6 d-flex align-items-center"l><"col-md-6 d-flex justify-content-end"f>>rtip',
|
|
language: {
|
|
search: 'Search doctors:',
|
|
lengthMenu: 'Show _MENU_ doctors',
|
|
info: 'Showing _START_ to _END_ of _TOTAL_ doctors',
|
|
paginate: { first: 'First', last: 'Last', next: 'Next', previous: 'Previous' }
|
|
}
|
|
});
|
|
|
|
// Real-time update every 3 seconds
|
|
setInterval(function() {
|
|
if (doctorTable) {
|
|
doctorTable.ajax.reload(null, false); // false = don't reset paging
|
|
}
|
|
}, 3000);
|
|
});
|
|
|
|
$(document).on('click', '.book-btn', function() {
|
|
const btn = $(this);
|
|
const doctorId = btn.data('doctor');
|
|
btn.prop('disabled', true).text('Assigning...');
|
|
|
|
$.ajax({
|
|
url: "<?= base_url('admin/appointments/create') ?>",
|
|
method: 'POST',
|
|
contentType: 'application/json',
|
|
dataType: 'json',
|
|
headers: {
|
|
'X-Requested-With': 'XMLHttpRequest',
|
|
'X-CSRF-TOKEN': "<?= csrf_hash() ?>"
|
|
},
|
|
data: JSON.stringify({
|
|
doctor_id: doctorId,
|
|
patient_id: previewPatientId,
|
|
appointment_date: previewDate,
|
|
appointment_time: previewTime,
|
|
services: previewServices,
|
|
preview_id: previewId
|
|
}),
|
|
success: function(res) {
|
|
if (!res || !res.success) {
|
|
alert(res && res.message ? res.message : 'Assignment failed. Please try again.');
|
|
btn.prop('disabled', false).text('Assign');
|
|
return;
|
|
}
|
|
alert(res.message || 'Appointment assigned successfully.');
|
|
doctorTable.ajax.reload();
|
|
},
|
|
error: function(xhr) {
|
|
const message = (xhr.responseJSON && xhr.responseJSON.message) ? xhr.responseJSON.message : 'Assignment failed. Please try again.';
|
|
alert(message);
|
|
btn.prop('disabled', false).text('Assign');
|
|
}
|
|
});
|
|
});
|
|
|
|
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 toggleExpand(btn, containerId) {
|
|
const container = document.getElementById(containerId);
|
|
const hiddenItems = container.querySelectorAll('.d-none');
|
|
const shownItems = container.querySelectorAll('.badge:not(.d-none)');
|
|
|
|
if (btn.innerText === 'Show more') {
|
|
// Find all badges that were hidden and show them
|
|
// We'll add a temporary class to track them
|
|
container.querySelectorAll('.badge.d-none').forEach(el => {
|
|
el.classList.remove('d-none');
|
|
el.classList.add('was-hidden');
|
|
});
|
|
btn.innerText = 'Show less';
|
|
} else {
|
|
// Find all badges that were originally hidden and hide them again
|
|
container.querySelectorAll('.badge.was-hidden').forEach(el => {
|
|
el.classList.add('d-none');
|
|
el.classList.remove('was-hidden');
|
|
});
|
|
btn.innerText = 'Show more';
|
|
}
|
|
}
|
|
|
|
function toggleNavDropdown(event, element) {
|
|
event.preventDefault();
|
|
element.parentElement.classList.toggle('active');
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|