versioning

This commit is contained in:
KONE SOREL 2026-02-24 12:35:39 +00:00
parent 15e53368d4
commit 25b1c2c035
8 changed files with 966 additions and 293 deletions

View File

@ -1,198 +1,636 @@
/* * THEME-MODERN.CSS
* Refonte UI/UX - Application Gestion Santé
*/
/* -------------------------------------------------------------------
THEME MODERN - INTER SANTE
Style SaaS Premium, épuré, professionnel.
------------------------------------------------------------------- */
/* 1. Variables et réinitialisations */
:root {
--primary-color: #0d6efd; /* Bleu médical */
--secondary-bg: #f8f9fa;
--sidebar-bg: #ffffff;
--primary: #0b5e7c; /* Bleu médical profond */
--primary-light: #e6f0f5;
--secondary: #6c757d;
--success: #28a745;
--info: #17a2b8;
--warning: #ffc107;
--danger: #dc3545;
--light: #f8f9fa;
--dark: #343a40;
--body-bg: #f2f5f9;
--card-bg: #ffffff;
--border-color: rgba(0,0,0,0.08);
--sidebar-width: 260px;
--sidebar-collapsed-width: 80px;
--border-radius: 12px;
--card-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
--soft-shadow: 0 10px 30px rgba(0, 0, 0, 0.05);
--transition-speed: 0.3s;
--header-height: 70px;
--font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
--border-radius: 14px;
--box-shadow: 0 8px 30px rgba(0, 0, 0, 0.05);
}
/* --- Global Layout --- */
body {
font-family: 'Inter', 'Poppins', -apple-system, sans-serif;
background-color: var(--secondary-bg);
color: #444;
font-family: var(--font-family);
background-color: var(--body-bg);
color: #1e293b;
font-size: 0.95rem;
}
.main {
margin-left: var(--sidebar-width);
padding: 20px 30px;
transition: all var(--transition-speed);
/* 2. Header */
.header {
height: var(--header-height);
background-color: white;
border-bottom: 1px solid var(--border-color);
padding: 0 1.5rem;
box-shadow: 0 2px 10px rgba(0,0,0,0.02);
}
.mode-test-active {
border-top: 5px solid orange;
.logo span {
font-weight: 600;
color: var(--primary);
letter-spacing: -0.3px;
}
/* --- Header & Navigation --- */
#header {
background: #fff;
box-shadow: 0 1px 10px rgba(0,0,0,0.05);
padding: 10px 20px;
.breadcrumb-nav {
margin-left: 2rem;
}
.breadcrumb {
border-radius: 8px;
background: transparent !important;
background: transparent;
padding: 0;
font-size: 0.9rem;
}
.initials {
background-color: var(--primary-color);
color: white;
width: 35px;
height: 35px;
.breadcrumb-item a {
color: var(--secondary);
}
.breadcrumb-item.active {
color: var(--primary);
font-weight: 500;
}
/* Badge mode test */
.test-badge {
background-color: #ffc107;
color: #1e1e1e;
font-size: 0.7rem;
font-weight: 600;
padding: 0.2rem 0.8rem;
border-radius: 30px;
letter-spacing: 0.3px;
text-transform: uppercase;
}
/* Infos entité */
.entity-info {
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
font-weight: bold;
gap: 0.75rem;
}
/* --- Sidebar (Navigation Latérale) --- */
.entity-logo {
width: 80px;
max-height: 40px;
object-fit: contain;
}
.entity-name {
font-weight: 500;
color: var(--dark);
max-width: 150px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* Initiales utilisateur */
.user-initials {
display: inline-flex;
align-items: center;
justify-content: center;
width: 38px;
height: 38px;
background: var(--primary);
color: white;
font-weight: 600;
font-size: 1rem;
border-radius: 10px;
text-transform: uppercase;
transition: var(--transition);
}
.user-initials:hover {
transform: scale(1.05);
box-shadow: 0 4px 12px rgba(11, 94, 124, 0.3);
}
/* 3. Sidebar */
.sidebar {
width: var(--sidebar-width);
background: var(--sidebar-bg);
border-right: 1px solid #eee;
padding: 15px;
background: white;
border-right: 1px solid var(--border-color);
padding: 1.5rem 0.5rem;
transition: width 0.3s ease;
}
.sidebar-nav .nav-link {
border-radius: var(--border-radius);
padding: 12px 15px;
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.7rem 1rem;
color: #4b5563;
border-radius: 12px;
margin-bottom: 0.2rem;
transition: all 0.2s;
font-weight: 500;
color: #555;
transition: 0.2s;
}
.sidebar-nav .nav-link:hover,
.sidebar-nav .nav-link.active-main {
background: #f0f7ff;
color: var(--primary-color);
.sidebar-nav .nav-link i:first-child {
font-size: 1.3rem;
width: 1.75rem;
color: var(--primary);
transition: all 0.2s;
}
.sidebar-nav .nav-link i {
font-size: 1.2rem;
margin-right: 10px;
color: #888;
.sidebar-nav .nav-link:hover {
background: var(--primary-light);
color: var(--primary);
}
.sidebar-nav .nav-link.active-main i {
color: var(--primary-color);
.sidebar-nav .nav-link[aria-expanded="true"] {
background: var(--primary-light);
color: var(--primary);
}
/* --- Barre de Contexte (Droite) --- */
#barre_laterale_d {
position: fixed;
top: 0;
right: -350px; /* Caché par défaut */
width: 320px;
height: 100vh;
background: #fff;
z-index: 1050;
transition: right 0.3s ease-in-out;
box-shadow: -5px 0 25px rgba(0,0,0,0.1);
/* Sous-menus */
.nav-content {
padding-left: 2.5rem;
list-style: none;
}
#barre_laterale_d.open {
right: 0; /* Apparaît au clic */
.nav-content a {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 0;
color: #6b7280;
font-size: 0.9rem;
text-decoration: none;
transition: all 0.2s;
border-radius: 10px;
}
.btn-info-context {
position: fixed;
right: 20px;
bottom: 20px;
background: var(--primary-color);
color: #fff;
border-radius: 50px;
padding: 12px 20px;
border: none;
box-shadow: 0 4px 12px rgba(13, 110, 253, 0.3);
z-index: 1001;
.nav-content a i {
font-size: 0.5rem;
color: #9ca3af;
}
/* --- Main Navigation (Scrollmenu) --- */
.nav-content a:hover,
.nav-content a.active {
color: var(--primary);
background: transparent;
}
.nav-content a.active i {
color: var(--primary);
}
/* 4. Main content */
.main {
margin-left: var(--sidebar-width);
padding: calc(var(--header-height) + 20px) 1.5rem 1.5rem 1.5rem;
transition: margin-left 0.3s ease;
}
/* Quand la sidebar est réduite */
.sidebar-collapsed .main {
margin-left: 80px;
}
/* Scrollmenu (sous-navigation) */
.scrollmenu {
overflow: auto;
white-space: nowrap;
padding: 10px 0;
background: #fff;
border-radius: var(--border-radius);
margin-bottom: 20px;
box-shadow: var(--soft-shadow);
background: white;
border-radius: 50px;
padding: 0.3rem;
margin-bottom: 2rem;
display: inline-flex;
flex-wrap: wrap;
gap: 0.2rem;
box-shadow: 0 2px 8px rgba(0,0,0,0.02);
border: 1px solid var(--border-color);
}
.scrollmenu a {
display: inline-block;
padding: 10px 20px;
padding: 0.5rem 1.2rem;
border-radius: 40px;
font-size: 0.9rem;
font-weight: 500;
color: var(--secondary);
text-decoration: none;
color: #666;
border-radius: 20px;
margin: 0 5px;
transition: all 0.2s;
white-space: nowrap;
}
.scrollmenu a:hover {
background-color: var(--secondary-bg);
color: var(--primary-color);
background: var(--primary-light);
color: var(--primary);
}
/* --- Cards & UI Elements --- */
/* 5. Cartes et conteneurs */
.card {
background: var(--card-bg);
border: none;
border-radius: var(--border-radius);
box-shadow: var(--soft-shadow);
transition: transform 0.2s;
box-shadow: var(--box-shadow);
transition: transform 0.2s, box-shadow 0.2s;
}
.card:hover {
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.08);
}
/* 6. Barre de contexte (Drawer) */
.btn-context-toggle {
position: fixed;
right: 20px;
top: 50%;
transform: translateY(-50%);
z-index: 1040;
background: var(--primary);
color: white;
border: none;
width: 48px;
height: 48px;
border-radius: 30px 0 0 30px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 0.2rem;
box-shadow: -4px 4px 15px rgba(0,0,0,0.1);
cursor: pointer;
transition: all 0.3s;
font-size: 1.1rem;
border-right: none;
}
.btn-context-toggle:hover {
background: #094c66;
right: 15px;
}
.context-drawer {
position: fixed;
top: 0;
right: -450px; /* Caché par défaut */
width: 400px;
height: 100vh;
background: white;
box-shadow: -5px 0 30px rgba(0,0,0,0.1);
z-index: 1050;
transition: right 0.4s cubic-bezier(0.16, 1, 0.3, 1);
border-left: 1px solid var(--border-color);
}
.context-drawer.show {
right: 0;
}
.context-drawer-content {
display: flex;
flex-direction: column;
height: 100%;
}
.drawer-header {
padding: 1.2rem 1.5rem;
border-bottom: 1px solid var(--border-color);
display: flex;
align-items: center;
justify-content: space-between;
}
.drawer-title {
font-weight: 600;
color: var(--primary);
margin: 0;
font-size: 1.1rem;
}
.drawer-body {
flex: 1;
overflow-y: auto;
padding: 1.5rem;
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.context-card {
background: var(--light);
border-radius: 16px;
overflow: hidden;
border: 1px solid var(--border-color);
}
.context-card-header {
background: rgba(0,0,0,0.02);
padding: 0.6rem 1rem;
font-weight: 600;
font-size: 0.8rem;
text-transform: uppercase;
letter-spacing: 0.3px;
color: var(--secondary);
border-bottom: 1px solid var(--border-color);
}
.context-card-header i {
margin-right: 0.5rem;
color: var(--primary);
}
.context-card-body {
padding: 1rem;
}
.context-link {
font-weight: 600;
color: var(--primary);
text-decoration: none;
font-size: 1rem;
}
.context-link:hover {
text-decoration: underline;
}
.family-stats {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
margin-top: 0.5rem;
}
.family-stats .badge {
background: white !important;
color: var(--dark) !important;
border: 1px solid var(--border-color);
font-weight: 400;
padding: 0.4rem 0.6rem;
}
.beneficiary-photo {
width: 60px;
height: 60px;
object-fit: cover;
border: 2px solid white;
box-shadow: 0 4px 8px rgba(0,0,0,0.05);
cursor: pointer;
}
/* 7. Tableaux modernes */
.table {
--bs-table-bg: transparent;
border-collapse: separate;
border-spacing: 0 8px;
margin-top: -8px;
}
.table thead th {
background: transparent;
color: var(--secondary);
font-weight: 500;
font-size: 0.8rem;
text-transform: uppercase;
letter-spacing: 0.3px;
border: none;
padding: 0.75rem 1rem;
}
.table tbody tr {
background: white;
border-radius: 16px;
box-shadow: 0 2px 8px rgba(0,0,0,0.02);
transition: all 0.2s;
}
.table tbody tr:hover {
box-shadow: 0 8px 20px rgba(0,0,0,0.06);
transform: translateY(-2px);
}
.btn {
border-radius: 8px;
padding: 8px 16px;
.table tbody td {
padding: 1rem 1rem;
border: none;
vertical-align: middle;
}
.table tbody td:first-child {
border-top-left-radius: 16px;
border-bottom-left-radius: 16px;
}
.table tbody td:last-child {
border-top-right-radius: 16px;
border-bottom-right-radius: 16px;
}
/* Badges de statut */
.badge-statut {
padding: 0.35rem 1rem;
border-radius: 30px;
font-weight: 500;
font-size: 0.75rem;
display: inline-block;
}
.btn-info {
background-color: #08C5D1;
border: none;
.badge-statut.valide {
background: #d4edda;
color: #155724;
}
.badge-statut.rejete {
background: #f8d7da;
color: #721c24;
}
.badge-statut.attente {
background: #fff3cd;
color: #856404;
}
/* 8. Boutons personnalisés */
.btn {
border-radius: 12px;
padding: 0.5rem 1.2rem;
font-weight: 500;
transition: all 0.2s;
}
.btn-primary {
background: var(--primary);
border-color: var(--primary);
}
.btn-primary:hover {
background: #094c66;
border-color: #094c66;
transform: translateY(-2px);
box-shadow: 0 8px 16px rgba(11, 94, 124, 0.2);
}
.btn-outline-primary {
border-color: var(--primary);
color: var(--primary);
}
.btn-outline-primary:hover {
background: var(--primary);
color: white;
transform: translateY(-2px);
}
/* --- Modals Modernisation --- */
/* 9. Formulaires */
.form-control, .form-select {
border-radius: 12px;
border: 1.5px solid #e9ecef;
padding: 0.5rem 1rem;
transition: all 0.2s;
}
.form-control:focus, .form-select:focus {
border-color: var(--primary);
box-shadow: 0 0 0 4px rgba(11, 94, 124, 0.1);
}
/* 10. Modals */
.modal-content {
border-radius: var(--border-radius);
border: none;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
border-radius: 24px;
box-shadow: 0 30px 60px rgba(0,0,0,0.2);
}
.modal-header {
border-bottom: 1px solid #f1f1f1;
background: #fafafa;
background: white;
color: var(--dark);
border-bottom: 1px solid var(--border-color);
padding: 1.2rem 1.5rem;
}
/* --- Tables (DataTables Custom) --- */
.table {
border-collapse: separate;
border-spacing: 0 8px;
.modal-header .close {
background: transparent;
color: var(--secondary);
border: none;
font-size: 1.5rem;
}
.table tr {
background: #fff;
box-shadow: 0 2px 4px rgba(0,0,0,0.02);
/* ================================================= */
/* AMÉLIORATIONS SPÉCIFIQUES POUR LES MODALS */
/* ================================================= */
/* Animation d'entrée des modals */
.modal.fade .modal-dialog {
transform: scale(0.95);
transition: transform 0.2s ease-out, opacity 0.2s ease-out;
opacity: 0;
}
.table td, .table th {
padding: 15px;
border: none !important;
.modal.show .modal-dialog {
transform: scale(1);
opacity: 1;
}
.table tr td:first-child { border-radius: 10px 0 0 10px; }
.table tr td:last-child { border-radius: 0 10px 10px 0; }
/* Style des boutons dans les modals */
.modal-footer .btn-light {
background: white;
border: 1px solid var(--border-color);
border-radius: 10px;
padding: 0.6rem 1.5rem;
font-weight: 500;
}
.modal-footer .btn-light:hover {
background: var(--light);
border-color: var(--secondary);
}
/* Zone de contenu des messages */
.messagerie-container {
min-height: 200px;
max-height: 60vh;
overflow-y: auto;
}
/* Style des messages individuels (si chargés dynamiquement) */
.message-item {
padding: 1rem;
border-bottom: 1px solid var(--border-color);
transition: background 0.2s;
}
.message-item:hover {
background: var(--primary-light);
}
.message-item.unread {
background: #f0f7ff;
border-left: 3px solid var(--primary);
}
.message-date {
font-size: 0.8rem;
color: var(--secondary);
}
/* ================================================= */
/* AMÉLIORATIONS POUR LE SCROLLMENU */
/* ================================================= */
.scrollmenu-wrapper {
margin-bottom: 2rem;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
scrollbar-width: thin;
padding-bottom: 0.5rem;
}
.scrollmenu {
display: inline-flex;
background: white;
border-radius: 50px;
padding: 0.3rem;
gap: 0.2rem;
border: 1px solid var(--border-color);
box-shadow: 0 2px 8px rgba(0,0,0,0.02);
min-width: min-content;
}
.scrollmenu-item {
padding: 0.6rem 1.5rem;
border-radius: 40px;
font-size: 0.9rem;
font-weight: 500;
color: var(--secondary);
text-decoration: none;
transition: all 0.2s;
white-space: nowrap;
}
.scrollmenu-item:hover {
background: var(--primary-light);
color: var(--primary);
}
.scrollmenu-item.active {
background: var(--primary);
color: white;
}
/* ================================================= */
/* ZONE DES INPUTS CACHÉS (invisible mais présents) */
/* ================================================= */
.hidden-inputs {
display: none;
}
/* Alternative pour garder les inputs accessibles mais invisibles */
.hidden-inputs input[type="hidden"] {
display: none;
}

View File

@ -1,37 +1,116 @@
<button class="btn-info-context" id="toggleContexte" title="<?= _("Infos Dossier") ?>">
<i class="bi bi-info-circle-fill"></i>
<!-- Bouton flottant pour ouvrir le panneau de contexte -->
<button class="btn-context-toggle" id="showSideNav" title="<?= _('Afficher le contexte') ?>">
<i class="fa-solid fa-angles-left"></i>
<i class="fa fa-cog fa-spin"></i>
</button>
<aside id="barre_laterale_d" class="contexte-sidebar shadow">
<div class="contexte-header d-flex justify-content-between align-items-center mb-4">
<h5 class="mb-0 fw-bold"><?= _("Contexte") ?></h5>
<button type="button" class="btn-close" id="closeContexte"></button>
</div>
<!-- Panneau de contexte (Drawer) -->
<div id="barre_laterale_d" class="context-drawer">
<div class="context-drawer-content">
<!-- En-tête du drawer avec bouton de fermeture -->
<div class="drawer-header">
<h5 class="drawer-title"><i class="fa fa-cog me-2"></i><?= _('Contexte actuel') ?></h5>
<button class="btn-close" id="hideSideNav" aria-label="Fermer"></button>
</div>
<div class="context-card mb-3 p-3 bg-light rounded border-start border-primary border-4">
<p class="small text-muted mb-1 text-uppercase fw-bold"><?= _("Garant") ?></p>
<div class="d-flex align-items-center">
<i class="bi bi-shield-check me-2 text-primary"></i>
<span class="fw-semibold"><?= $this->nettoyer($_SESSION['nomGarant_C']) ?></span>
<!-- Contenu de la fiche d'identité -->
<div class="drawer-body">
<!-- Garant -->
<div class="context-card">
<div class="context-card-header">
<i class="fas fa-user-shield"></i> <?= _('Garant') ?>
</div>
<div class="context-card-body">
<a href="javascript:afficher_garant('<?= $this->nettoyer($_SESSION['codeGcAssureur_C']) ?>');" class="context-link">
<strong><?= $this->nettoyer($_SESSION['codeGcAssureur_C']) ?></strong>
</a>
<p class="text-muted small mb-0"><?= $_SESSION['nomGcAssureur_C'] ?? '' ?></p>
</div>
</div>
<!-- Souscripteur -->
<div class="context-card">
<div class="context-card-header">
<i class="fas fa-user-tie"></i> <?= _('Souscripteur') ?>
</div>
<div class="context-card-body">
<a href="javascript:afficher_client_id();" class="context-link">
<strong><?= $this->nettoyer($_SESSION['numeroClient_C']) ?></strong>
</a>
<p class="text-muted small mb-0"><?= $this->nettoyer($_SESSION['nomClient_C']) ?></p>
</div>
</div>
<!-- Police en cours -->
<div class="context-card">
<div class="context-card-header">
<i class="fa fa-file-text"></i> <?= _('Police en cours') ?>
</div>
<div class="context-card-body">
<a href="javascript:afficher_police_id();" class="context-link">
<?= $this->nettoyer($_SESSION['numeroPolice_C']) ?>
</a>
<p class="text-muted small mb-1"><?= dateLang($_SESSION['dateEffet_C'], $_SESSION['lang']) ?> - <?= dateLang($_SESSION['dateEcheance_C'], $_SESSION['lang']) ?></p>
<div class="family-stats">
<span class="badge bg-light text-dark"><i class="fas fa-users me-1"></i>Fam. <?= format_N($_SESSION['ndAdh_C']) ?></span>
<span class="badge bg-light text-dark"><i class="fas fa-users me-1"></i>Dép. <?= format_N($_SESSION['ndDep_C']) ?></span>
<span class="badge bg-light text-dark"><i class="fas fa-user me-1"></i>Bén. <?= format_N($_SESSION['ndActif_C']) ?></span>
</div>
</div>
</div>
<!-- Adhérent -->
<div class="context-card">
<div class="context-card-header">
<i class="fa-solid fa-users"></i> <?= _('Famille en cours') ?>
</div>
<div class="context-card-body">
<a href="javascript:afficher_adherent_id();" class="context-link">
<?= $this->nettoyer($_SESSION['numeroAdherent_C']) ?>
</a>
<p class="text-muted small mb-0"><?= substr($this->nettoyer($_SESSION['adherent_C']), 0, 35) ?></p>
</div>
</div>
<!-- Bénéficiaire + Photo -->
<div class="context-card">
<div class="context-card-header">
<i class="fa-solid fa-user"></i> <?= _('Bénéficiaire en cours') ?>
</div>
<div class="context-card-body">
<div class="d-flex align-items-start gap-3">
<div>
<a href="javascript:afficher_beneficiaire_id();" class="context-link">
<?= $this->nettoyer($_SESSION['numeroBeneficiaire_C']) ?>
</a>
<p class="text-muted small mb-1"><?= substr($this->nettoyer($_SESSION['beneficiaire_C']), 0, 35) ?></p>
<p class="small mb-0"><i class="bi bi-calendar me-1"></i><?= dateLang($_SESSION['dateEntreeBeneficiaire_C'], $_SESSION['lang']) ?> - <?= dateLang($_SESSION['dateEcheancePolice_C'], $_SESSION['lang']) ?></p>
</div>
<?php if ($_SESSION['faceRegistered_C'] == "1" && $_SESSION['idBeneficiaire_C'] > 0): ?>
<img src="data:image/jpg;base64,<?= $imgData ?>" class="beneficiary-photo rounded-circle" alt="Photo" data-bs-toggle="modal" data-bs-target="#pop_photo">
<?php endif; ?>
</div>
</div>
</div>
<!-- Dernières polices ouvertes -->
<div class="context-card">
<div class="context-card-header">
<i class="bi bi-clock-history"></i> <?= _('Dernières polices') ?>
</div>
<div class="context-card-body p-0">
<ul class="list-unstyled mb-0">
<?php foreach ($_SESSION['contextPolice'] as $contextPolice): ?>
<li class="border-bottom p-2">
<a href="javascript:selectionner_police(<?= $contextPolice['idPolice'] ?>,'<?= $contextPolice['numeroPolice'] ?>');afficher_police_id();" class="text-decoration-none d-block">
<span class="fw-semibold"><?= htmlspecialchars($contextPolice['libellePolice']) ?></span>
<small class="text-muted d-block"><?= $contextPolice['numeroPolice'] ?></small>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
</div>
</div>
<div class="context-card mb-3 p-3 bg-light rounded border-start border-info border-4">
<p class="small text-muted mb-1 text-uppercase fw-bold"><?= _("Client") ?></p>
<div class="mb-2">
<span class="badge bg-info text-dark mb-1">ID: <?= $this->nettoyer($_SESSION['numeroClient_d_C']) ?></span>
<div class="fw-semibold text-truncate"><?= $this->nettoyer($_SESSION['nomClient_d_C']) ?></div>
</div>
<button class="btn btn-sm btn-outline-info w-100" onclick="javascript:afficher_client_d_id();">
<i class="bi bi-eye"></i> <?= _("Détails Client") ?>
</button>
</div>
<div class="context-card p-3 bg-light rounded border-start border-success border-4">
<p class="small text-muted mb-1 text-uppercase fw-bold"><?= _("Police / Contrat") ?></p>
<div class="fw-bold mb-2"># <?= $this->nettoyer($_SESSION['numeroPolice_d_C']) ?></div>
<button class="btn btn-sm btn-outline-success w-100" onclick="javascript:afficher_police_d_id_init();">
<i class="bi bi-file-earmark-text"></i> <?= _("Consulter") ?>
</button>
</div>
</aside>
</div>

View File

@ -1,38 +1,35 @@
<?php
/**
* VERSIONING AUTOMATIQUE (CACHE BUSTING)
* Génère une version unique basée sur la minute actuelle (Ex: 202602241530)
* Permet de forcer la mise à jour des fichiers CSS/JS chez tous les utilisateurs.
*/
if (!defined('APP_VERSION')) {
define('APP_VERSION', date('Y.m.d.H.i'));
}
// Versioning automatique pour le cache navigateur
$version = date('YmdHi'); // Ou utilise une constante APP_VERSION définie ailleurs
?>
<meta charset="UTF-8">
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<base href="<?= $racineWeb ?>">
<!-- Favicon -->
<link rel="icon" href="Bootstrap_new/images/favicon.ico"/>
<link rel="icon" href="Bootstrap_new/images/favicon.ico">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap" rel="stylesheet">
<!-- Google Fonts : Inter et Poppins en fallback -->
<link href="https://fonts.googleapis.com/css2?family=Inter:opsz@14..32&display=swap" rel="stylesheet">
<link href="https://fonts.gstatic.com" rel="preconnect">
<!-- Vendor CSS Files (Bootstrap et ses icônes) -->
<link href="Bootstrap/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="Bootstrap/vendor/bootstrap-icons/bootstrap-icons.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
<link href="Bootstrap/vendor/remixicon/remixicon.css" rel="stylesheet">
<link href="Bootstrap_new/css/datatables.min.css" rel="stylesheet">
<link href="Bootstrap/vendor/boxicons/css/boxicons.min.css" rel="stylesheet">
<link href="Bootstrap_new/css/select2.min.css" rel="stylesheet">
<link href="Bootstrap_new/select/css/bootstrap-select.min.css" rel="stylesheet">
<link href="Bootstrap_new/datatables/datatable.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/sweetalert2@11.14.1/dist/sweetalert2.min.css" rel="stylesheet">
<link href="Bootstrap/vendor/quill/quill.snow.css" rel="stylesheet">
<link href="Bootstrap/css/style.css?ver=<?= APP_VERSION ?>" rel="stylesheet">
<link href="Bootstrap_new/css/custom.css?ver=<?= APP_VERSION ?>" rel="stylesheet">
<link href="Bootstrap_new/css/theme-modern.css?ver=<?= APP_VERSION ?>" rel="stylesheet">
<!-- Font Awesome 6 (via CDN pour la simplicité) -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
<title><?= $_SESSION['descriptionVue'] ?? 'INTER SANTE' ?></title>
<!-- Thème principal : Notre nouveau fichier de style moderne -->
<link href="Bootstrap_new/css/theme-modern.css?ver=<?= $version ?>" rel="stylesheet">
<title><?= $_SESSION['descriptionVue'] ?? 'INTER SANTE' ?></title>
<!-- Scripts de bibliothèques globales (placés ici pour une disponibilité précoce si besoin) -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.0.0"></script>

View File

@ -1,61 +1,76 @@
<header id="header" class="header fixed-top d-flex align-items-center">
<div class="d-flex align-items-center justify-content-between">
<div class="d-flex align-items-center justify-content-between header-left">
<a class="logo d-flex align-items-center">
<img src="Bootstrap_new/images/new/favicon.png" alt="Inter Santé">
<div class="divider-v ms-2 me-2"></div>
<img src="<?= $_SESSION['logoSociete'] ?>" alt="Gestionnaire" style="max-height: 30px;">
<span class="d-none d-lg-block ms-2 fw-bold text-dark">INTER SANTE</span>
<img src="Bootstrap_new/images/new/favicon.png" alt="Logo Inter santé"/>
<span class="d-none d-lg-block brand-name">INTER SANTE</span>
</a>
<i class="bi bi-list toggle-sidebar-btn ms-3"></i>
<i class="bi bi-list toggle-sidebar-btn"></i>
</div>
<nav class="ms-4 d-none d-md-block">
<ol class="breadcrumb mb-0 bg-transparent">
<li class="breadcrumb-item small">
<a href="<?= $_SESSION['retourVue'] ?>" class="text-muted text-decoration-none">
<i class="bi bi-chevron-left"></i> <?= $_SESSION['titreRetour'] ?>
<!-- Breadcrumb intégré au header -->
<nav aria-label="breadcrumb" class="breadcrumb-nav">
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item">
<a href="<?= $_SESSION['retourVue']; ?>" class="text-decoration-none">
<i class="fas fa-arrow-left me-1"></i><?= $_SESSION['titreRetour']; ?>
</a>
</li>
<li class="breadcrumb-item active small fw-bold text-primary"><?= $_SESSION['descriptionVue'] ?></li>
<li class="breadcrumb-item active" aria-current="page"><?= $_SESSION['descriptionVue'] ?></li>
</ol>
</nav>
<nav class="header-nav ms-auto pe-3">
<ul class="d-flex align-items-center mb-0 list-unstyled">
<li class="nav-item me-2">
<a title="<?= _("Guide d'utilisation"); ?>" class="nav-link nav-icon" href="Guideutilisation/">
<i class="bi bi-question-circle text-muted fs-5"></i>
<nav class="header-nav ms-auto">
<ul class="d-flex align-items-center">
<!-- Badge Mode Test -->
<?php if ($_SESSION['bdTests_C'] == "1"): ?>
<li class="nav-item">
<span class="test-badge">MODE TEST</span>
</li>
<?php endif; ?>
<!-- Notifications -->
<li class="nav-item dropdown">
<a class="nav-link nav-icon" href="#" data-bs-toggle="dropdown">
<i class="bi bi-bell"></i>
<span id="span_notification" class="badge bg-primary badge-number" onclick="pop_messagerie();">0</span>
</a>
</li>
<li class="nav-item dropdown px-3 border-start">
<a class="nav-link d-flex align-items-center" href="#" data-bs-toggle="dropdown">
<img src="Bootstrap_new/images/<?= (est_anglophone()) ? 'england.png' : 'france.png' ?>" width="20" class="me-2 rounded-sm shadow-sm">
<span class="fw-bold small text-dark uppercase"><?= (est_anglophone()) ? 'EN' : 'FR' ?></span>
<!-- Logo / Nom de l'entité gestionnaire -->
<li class="nav-item">
<a class="nav-link nav-icon entity-info" href="javascript:infos_entite();" title="Gestionnaire d'assurance santé">
<img src="<?= $_SESSION['lienLogo'] ?>" alt="Logo" class="entity-logo">
<span class="entity-name"><?= $companyDisplayName ?></span>
</a>
<ul class="dropdown-menu dropdown-menu-end shadow border-0 mt-3">
<li><a class="dropdown-item" href="javascript:changer_langue();"><i class="bi bi-translate me-2"></i> <?= _("Changer de langue") ?></a></li>
</li>
<!-- Sélecteur de langue -->
<li class="nav-item dropdown">
<a class="nav-link nav-profile d-flex align-items-center" href="#" data-bs-toggle="dropdown">
<img src="Bootstrap_new/images/<?= $flag ?>" alt="<?= $alt ?>" width="24" class="rounded-circle">
<span class="d-none d-md-block ms-1"><?= $lib ?></span>
</a>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="javascript:changer_langue();"><i class="fa fa-exchange me-2"></i><?= _('Changer de langue') ?></a></li>
</ul>
</li>
<li class="nav-item dropdown ps-3">
<a class="nav-link nav-profile d-flex align-items-center" href="#" data-bs-toggle="dropdown">
<div class="initials-box"><?= $_SESSION['userInitials_C'] ?></div>
<span class="d-none d-md-block dropdown-toggle ps-2 fw-semibold text-dark"><?= $_SESSION['utilisateur_C'] ?></span>
<!-- Aide -->
<li class="nav-item">
<a class="nav-link nav-icon" href="Guideutilisation/" title="Guide d'utilisation">
<i class="bi bi-question-circle-fill"></i>
</a>
<ul class="dropdown-menu dropdown-menu-end shadow border-0 profile mt-3">
<li class="dropdown-header text-start">
<h6 class="mb-0 text-primary"><?= $_SESSION['nomSociete'] ?></h6>
<small class="text-muted"><?= $_SESSION['libeleRole_C'] ?></small>
</li>
</li>
<!-- Profil utilisateur avec initiales -->
<li class="nav-item dropdown">
<a class="nav-link nav-profile d-flex align-items-center" href="#" data-bs-toggle="dropdown">
<span class="user-initials"><?= $_SESSION['userInitials_C'] ?></span>
</a>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="javascript:change_password();"><i class="fa fa-user-circle me-2"></i><?= $_SESSION['utilisateur_C'] ?></a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item d-flex align-items-center" href="javascript:change_password();"><i class="bi bi-shield-lock me-2"></i> <span><?= _("Sécurité") ?></span></a></li>
<li><a class="dropdown-item d-flex align-items-center text-danger" href="LogOut/"><i class="bi bi-box-arrow-right me-2"></i> <span><?= _("Déconnexion") ?></span></a></li>
<li><a class="dropdown-item" href="#"><i class="bi bi-box-arrow-right me-2"></i><?= _('Déconnexion') ?></a></li>
</ul>
</li>
</ul>

View File

@ -1,26 +1,49 @@
<div id="div_entite" class="sr-only"></div>
<?php
// Ce fichier contient les inputs cachés vitaux pour les appels AJAX et le timer
// NE PAS SUPPRIMER - Utilisés par fonctions.js, messagerie, et divers contrôleurs
?>
<input class="sr-only" type="text" id="vue" name="vue" value="<?= isset($_SESSION['vue']) ? $_SESSION['vue'] : ''; ?>">
<input class="sr-only" type="text" id="racineWeb" name="racineWeb" value="<?= $racineWeb ?>">
<input class="sr-only" type="text" id="dureeSession" name="dureeSession" value="<?= $_SESSION['dureeSession'] ?>">
<input class="sr-only" type="text" id="codeLangue" name="codeLangue" value="<?= $_SESSION['codeLangue'] ?? 'fr_FR' ?>">
<!-- Inputs cachés critiques pour le fonctionnement de l'application -->
<div class="hidden-inputs">
<input type="hidden" id="vue" name="vue" value="<?= $_SESSION['vue'] ?? '' ?>">
<input type="hidden" id="racineWeb" name="racineWeb" value="<?= $racineWeb ?? '' ?>">
<input type="hidden" id="dureeSession" name="dureeSession" value="<?= $_SESSION['dureeSession'] ?? '' ?>">
<input type="hidden" id="nomSociete" name="nomSociete" value="<?= $_SESSION['nomSociete'] ?? '' ?>">
<input type="hidden" id="codeLangue" name="codeLangue" value="<?= $_SESSION['lang'] ?? 'fr_FR' ?>">
<!--
<input type="hidden" id="numeroClient_C" name="numeroClient_C" value="<?= $this->nettoyer($_SESSION['numeroClient_C'] ?? '') ?>">
<input type="hidden" id="codeGcAssureur_C" name="codeGcAssureur_C" value="<?= $this->nettoyer($_SESSION['codeGcAssureur_C'] ?? '') ?>">
<input type="hidden" id="numeroAdherent_C" name="numeroAdherent_C" value="<?= $this->nettoyer($_SESSION['numeroAdherent_C'] ?? '') ?>">
<input type="hidden" id="numeroBeneficiaire_C" name="numeroBeneficiaire_C" value="<?= $this->nettoyer($_SESSION['numeroBeneficiaire_C'] ?? '') ?>">
<input type="hidden" id="numeroPolice_C" name="numeroPolice_C" value="<?= $this->nettoyer($_SESSION['numeroPolice_C'] ?? '') ?>">
-->
<!-- Timer pour le rafraîchissement de la messagerie -->
<input type="hidden" id="timer" name="timer" value="0">
<input type="hidden" id="msgNonLus" name="msgNonLus" value="0">
</div>
<div class="fixed-div mb-4">
<div class="content">
<?php if (isset($menusvue) && count($menusvue) > 0) : ?>
<div class="scrollmenu shadow-sm">
<?php foreach ($menusvue as $menu) :
$current_page = basename($_SERVER['PHP_SELF']);
$menu_link = $menu['lienMenu'];
$active_class = (strpos($menu_link, $current_page) !== false) ? 'active' : '';
?>
<a title="<?= $menu['descriptionMenu']; ?>"
href="<?= $menu_link; ?>"
class="<?= $active_class ?>">
<?= $menu['libeleMenu'] ?>
</a>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</div>
<!-- Navigation secondaire (scrollmenu) -->
<?php if (!empty($menusvue)):
$current_url = $_SERVER['REQUEST_URI'];
$elements = explode("/", $current_url);
$activeLink = $elements[1] ?? '';
?>
<!-- Scrollmenu redesign -->
<div class="scrollmenu-wrapper">
<nav class="scrollmenu" aria-label="Navigation secondaire">
<?php foreach ($menusvue as $menu): ?>
<a href="<?= $menu['lienMenu'] ?>"
class="scrollmenu-item <?= (explode('/', $menu['lienMenu'])[0] == $activeLink) ? 'active' : '' ?>"
title="<?= htmlspecialchars($menu['descriptionMenu'] ?? '') ?>">
<?= htmlspecialchars($menu['libeleMenu']) ?>
</a>
<?php endforeach; ?>
</nav>
</div>
<?php endif; ?>
<!-- Div pour les tests/alertes AJAX -->
<div id="div_test_gabarit" class="d-none"></div>
<div id="div_entite" class="d-none"></div>

View File

@ -1,28 +1,119 @@
<div class="modal fade" id="popmessagerie" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content border-0 shadow-lg">
<div class="modal-header bg-light border-bottom">
<h5 class="modal-title fw-bold text-primary"><i class="bi bi-envelope-paper me-2"></i><?= _("Messages non lus") ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<!-- ================================================= -->
<!-- MODALS - NE PAS SUPPRIMER LES BOUTONS CACHÉS -->
<!-- Utilisés par les fonctions JavaScript existantes -->
<!-- ================================================= -->
<!-- Bouton caché pour déclencher la modal des messages non lus -->
<button id="btn_pop_messagerie" type="button" class="d-none" data-bs-toggle="modal" data-bs-target="#popmessagerie">
<?= _("Afficher les messages non lus...") ?>
</button>
<!-- Bouton caché pour déclencher la modal d'alerte message -->
<button id="btn_pop_dernier_messagerie" type="button" class="d-none" data-bs-toggle="modal" data-bs-target="#popderniermessagerie">
<?= _("Alerte Réception Message...") ?>
</button>
<!-- ================================================= -->
<!-- MODAL : Messages non lus -->
<!-- ================================================= -->
<div class="modal fade" id="popmessagerie" tabindex="-1" aria-labelledby="popmessagerieLabel" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="popmessagerieLabel">
<i class="bi bi-envelope me-2"></i><?= _("Messages non lus") ?>
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="<?= _("Fermer") ?>"></button>
</div>
<div class="modal-body p-0">
<div id="div_messagerie" class="modern-scroll" style="max-height: 450px; overflow-y: auto;">
<div class="modal-body">
<div id="div_messagerie" class="messagerie-container">
<!-- Contenu chargé dynamiquement par JavaScript -->
<div class="text-center text-muted py-4">
<i class="bi bi-hourglass-split me-2"></i><?= _("Chargement...") ?>
</div>
</div>
</div>
<div class="modal-footer border-0">
<button type="button" class="btn btn-light rounded-pill px-4" data-bs-dismiss="modal"><?= _("Fermer") ?></button>
<div class="modal-footer">
<button type="button" class="btn btn-light" data-bs-dismiss="modal">
<i class="bi bi-x-lg me-2"></i><?= _("Fermer") ?>
</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="pop_photo" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-md modal-dialog-centered">
<div class="modal-content bg-transparent border-0">
<div class="modal-body p-0 text-center">
<div id="div_photo_id" class="rounded shadow-lg bg-white p-2">
</div>
<!-- ================================================= -->
<!-- MODAL : Alerte dernier message -->
<!-- ================================================= -->
<div class="modal fade" id="popderniermessagerie" tabindex="-1" aria-labelledby="popderniermessagerieLabel" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="popderniermessagerieLabel">
<i class="bi bi-exclamation-circle me-2"></i><?= _("Alerte Réception Message...") ?>
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="<?= _("Fermer") ?>"></button>
</div>
<div class="modal-body">
<div id="div_dernier_messagerie" class="messagerie-container">
<!-- Contenu chargé dynamiquement par JavaScript -->
<div class="text-center text-muted py-4">
<i class="bi bi-hourglass-split me-2"></i><?= _("Chargement...") ?>
</div>
</div>
</div>
<div class="modal-footer">
<button id="btn_close_pop_dernier_messagerie" type="button" class="btn btn-light" data-bs-dismiss="modal">
<i class="bi bi-x-lg me-2"></i><?= _("Fermer") ?>
</button>
</div>
</div>
</div>
</div>
</div>
<!-- ================================================= -->
<!-- MODAL : Photo bénéficiaire -->
<!-- ================================================= -->
<div class="modal fade" id="pop_photo" tabindex="-1" aria-labelledby="pop_photoLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="pop_photoLabel">
<i class="bi bi-camera me-2"></i><?= _("Photo du bénéficiaire") ?>
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="<?= _("Fermer") ?>"></button>
</div>
<div class="modal-body text-center">
<?php if (!empty($imgData) && $_SESSION['faceRegistered_C'] == "1"): ?>
<img src="data:image/jpg;base64,<?= $imgData ?>"
class="img-fluid rounded-3"
style="max-height: 70vh; width: auto;"
alt="<?= _("Photo bénéficiaire") ?>">
<?php else: ?>
<div class="text-muted py-5">
<i class="bi bi-image fs-1 d-block mb-3"></i>
<p><?= _("Aucune photo disponible") ?></p>
</div>
<?php endif; ?>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light" data-bs-dismiss="modal">
<i class="bi bi-x-lg me-2"></i><?= _("Fermer") ?>
</button>
</div>
</div>
</div>
</div>
<!-- ================================================= -->
<!-- MODAL : Changement de mot de passe (si existante) -->
<!-- ================================================= -->
<?php if (function_exists('change_password_modal')): ?>
<!-- Si vous avez une modal dédiée au changement de mot de passe, elle peut être incluse ici -->
<?php endif; ?>
<!-- ================================================= -->
<!-- NOTE : Les IDs des boutons déclencheurs sont conservés -->
<!-- btn_pop_messagerie et btn_pop_dernier_messagerie sont utilisés -->
<!-- par les fonctions JavaScript pop_messagerie() et raffraichir_messagerie() -->
<!-- ================================================= -->

View File

@ -1,29 +1,57 @@
<?php $v_js = date('YmdHi'); ?>
<!-- jQuery first -->
<script src="Bootstrap/js/jquery.min.js"></script>
<script src="Bootstrap/js/jquery-ui.js"></script>
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
<script src="Bootstrap/vendor/simple-datatables/simple-datatables.js"></script>
<script src="Bootstrap_new/js/select2.min.js"></script>
<script src="Bootstrap/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="Bootstrap/js/timer.jquery.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script src="Js/fonctions.js?ver=<?= $v_scripts ?>"></script>
<script src="<?= $_SESSION['dossierSociete'].'/Js/societe.js?ver='.$v_scripts ?>"></script>
<script src="Bootstrap/js/main.js?v=<?= $v_scripts ?>"></script>
<!-- Vendor JS -->
<script src="Bootstrap/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="Bootstrap_new/js/select2.min.js"></script>
<script src="Bootstrap_new/select/js/bootstrap-select.min.js"></script>
<script src="Bootstrap_new/datatables/datatable.min.js"></script>
<script type="text/javascript">
<!-- Template Main JS -->
<script src="Bootstrap/js/main.js"></script>
<script src="Js/html2pdf.js"></script>
<script src="Js/fonctions.js?ver=<?= date('YmdHi') ?>"></script>
<!-- Internationalisation -->
<?php if (est_anglophone()): ?>
<script src="Js/datepicker-eng.js"></script>
<?php else: ?>
<script src="Js/datepicker-fr.js"></script>
<?php endif; ?>
<!-- Librairies tierces -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11.14.1/dist/sweetalert2.all.min.js"></script>
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<!-- Scripts d'initialisation -->
<script src="<?= $_SESSION['dossierSociete'] . '/Js/societe.js' ?>"></script>
<!-- Inputs cachés essentiels -->
<input type="hidden" id="vue" value="<?= $_SESSION['vue'] ?? '' ?>">
<input type="hidden" id="racineWeb" value="<?= $racineWeb ?>">
<input type="hidden" id="dureeSession" value="<?= $_SESSION['dureeSession'] ?>">
<input type="hidden" id="codeLangue" value="<?= $_SESSION['lang'] ?? 'fr_FR' ?>">
<div id="div_ajaxgabarit"></div>
<script>
$(document).ready(function() {
// Test rapide en console pour voir si les libs sont là
console.log("DataTables chargé :", typeof $.fn.DataTable !== 'undefined');
console.log("Select2 chargé :", typeof $.fn.select2 !== 'undefined');
// Gestion du drawer de contexte
$('#showSideNav').on('click', function() {
$('#barre_laterale_d').addClass('show');
});
$('#hideSideNav').on('click', function() {
$('#barre_laterale_d').removeClass('show');
});
if(typeof raffraichier_gabarit === "function") {
raffraichier_gabarit();
}
// Timer de rafraîchissement
$('#timer').timer({
duration: '60s',
callback: raffraichir_messagerie,
repeat: true
});
});
</script>

View File

@ -1,38 +1,40 @@
<aside id="sidebar" class="sidebar">
<ul class="sidebar-nav" id="sidebar-nav">
<?php foreach ($menus as $key0 => $menuParent):
$menuChildren = $gabary->get_menus_by_parent_code($menuParent['vue']);
$hasChildren = (sizeof($menuChildren) > 0);
$isActiveParent = (strtolower($menuParent['libeleMenu']) == strtolower($activeLevel1));
<?php foreach ($menus as $key0 => $menuParent):
$menuChildrenLevelOne = $gabary->get_menus_by_parent_code($menuParent['vue']);
$hasChildren = !empty($menuChildrenLevelOne);
$parentLink = explode('/', $menuParent['lienMenu'])[0];
$isActive = (strtolower($menuParent['libeleMenu']) == strtolower($activeLevel1));
?>
<li class="nav-item">
<?php if ($hasChildren): ?>
<a class="nav-link <?= $isActiveParent ? '' : 'collapsed' ?>"
data-bs-target="#menu-<?= $key0 ?>"
data-bs-toggle="collapse" href="#">
<?php if ($hasChildren): ?>
<!-- Menu Parent avec enfants -->
<li class="nav-item">
<a class="nav-link <?= $isActive ? '' : 'collapsed' ?>" data-bs-target="#nav-<?= $menuParent['codeMenu'].$key0 ?>" data-bs-toggle="collapse" href="#">
<i class="<?= $menuParent['icone'] ?>"></i>
<span><?= $menuParent['libeleMenu'] ?></span>
<i class="bi bi-chevron-down ms-auto"></i>
</a>
<ul id="menu-<?= $key0 ?>" class="nav-content collapse <?= $isActiveParent ? 'show' : '' ?>" data-bs-parent="#sidebar-nav">
<?php foreach ($menuChildren as $menuChild):
$link_clean = explode('/', $menuChild['lienMenu'])[0];
$isSubActive = ($link_clean == $_SESSION['firstLevelMenu']);
<ul id="nav-<?= $menuParent['codeMenu'].$key0 ?>" class="nav-content collapse <?= $isActive ? 'show' : '' ?>" data-bs-parent="#sidebar-nav">
<?php foreach ($menuChildrenLevelOne as $menuChild):
$childLink = explode('/', $menuChild['lienMenu'])[0];
?>
<li>
<a href="<?= $menuChild['lienMenu'] ?>" class="<?= $isSubActive ? 'active' : '' ?>">
<a href="<?= $menuChild['lienMenu'] ?>" class="<?= ($childLink == $activeLink) ? 'active' : '' ?>">
<i class="bi bi-circle"></i><span><?= $menuChild['libeleMenu'] ?></span>
</a>
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<a class="nav-link <?= $isActiveParent ? '' : 'collapsed' ?>" href="<?= $menuParent['lienMenu'] ?>">
</li>
<?php else: ?>
<!-- Menu Parent sans enfant (lien direct) -->
<li class="nav-item">
<a class="nav-link" href="<?= $menuParent['lienMenu'] ?>">
<i class="<?= $menuParent['icone'] ?>"></i>
<span><?= $menuParent['libeleMenu'] ?></span>
</a>
<?php endif; ?>
</li>
</li>
<?php endif; ?>
<?php endforeach; ?>
</ul>
</aside>