This commit is contained in:
KONE SOREL 2026-02-02 18:34:02 +00:00
parent b6a01b9741
commit deea375d56
5 changed files with 323 additions and 166 deletions

View File

@ -242,32 +242,38 @@ body {
} }
/* ========================================================================== /* ==========================================================================
SECONDARY NAVIGATION (TABS) GABARIT SPECIFIC STYLES
========================================================================== */ ========================================================================== */
/* Main container */
.main-container {
margin-top: 60px;
}
/* Secondary navigation */
.secondary-nav-container {
flex-wrap: nowrap;
}
.nav-link-sub { .nav-link-sub {
transition: all 0.3s ease;
border-right: 1px solid var(--border-color);
padding: 1rem 1.5rem;
display: block;
text-decoration: none;
color: #495057;
font-weight: 500;
min-width: 150px; min-width: 150px;
white-space: nowrap; white-space: nowrap;
border-right: 1px solid var(--border-color);
padding: 1rem 1.5rem;
text-decoration: none;
color: var(--dark-color);
text-align: center; text-align: center;
transition: all 0.3s ease;
} }
.nav-link-sub:hover { .nav-link-sub:hover {
background-color: rgba(0, 136, 207, 0.05); background-color: rgba(0, 136, 207, 0.05);
transform: translateY(-2px);
} }
.nav-link-sub.active { .nav-link-sub.active {
background: linear-gradient(135deg, var(--primary-color), var(--primary-dark)); background: linear-gradient(135deg, var(--primary-color), var(--primary-dark));
color: white !important; color: white !important;
font-weight: 600; font-weight: 600;
box-shadow: 0 4px 12px rgba(0, 136, 207, 0.2);
} }
.nav-link-sub:last-child { .nav-link-sub:last-child {
@ -401,9 +407,10 @@ body {
} }
/* ========================================================================== /* ==========================================================================
CONTEXT BAR (BARRE LATERALE D) CONTEXT BAR (BARRE LATERALE D) - UNIFIED VERSION
========================================================================== */ ========================================================================== */
/* Context Panel */
#barre_laterale_d { #barre_laterale_d {
background: white; background: white;
width: 300px; width: 300px;
@ -416,47 +423,165 @@ body {
top: 60px; top: 60px;
height: calc(100vh - 60px); height: calc(100vh - 60px);
z-index: 1010; z-index: 1010;
transition: transform 0.3s ease; transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
transform: translateX(100%); /* Ajouté pour l'animation */ transform: translateX(100%);
display: flex;
flex-direction: column;
} }
#barre_laterale_d.active { #barre_laterale_d.active {
transform: translateX(0); /* Ajouté pour l'animation */ transform: translateX(0);
} }
#barre_laterale_d .card { /* Context toggle button */
border: none;
box-shadow: var(--shadow-sm);
border-radius: var(--border-radius);
margin-bottom: 1rem;
}
/* Bouton toggle pour la barre de contexte */
.btn-context-toggle { .btn-context-toggle {
position: fixed; position: fixed;
right: 0; right: 0;
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
z-index: 1000; z-index: 1005;
border-radius: 20px 0 0 20px; border-radius: 20px 0 0 20px;
padding: 12px 8px; padding: 12px 8px;
transition: right 0.3s ease; background: linear-gradient(135deg, var(--primary-color), var(--primary-dark));
background: var(--primary-color);
color: white; color: white;
border: none; border: none;
cursor: pointer; cursor: pointer;
box-shadow: var(--shadow-md);
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
} }
.btn-context-toggle:hover { .btn-context-toggle:hover {
right: 5px; right: 5px;
background: var(--primary-dark); background: linear-gradient(135deg, var(--primary-dark), var(--primary-color));
} }
/* Quand la barre est active, cacher le bouton toggle */ .btn-context-toggle i {
font-size: 1.2rem;
margin: 0 2px;
}
/* Hide context button when panel is active */
#barre_laterale_d.active ~ .btn-context-toggle { #barre_laterale_d.active ~ .btn-context-toggle {
display: none; display: none;
} }
/* Context Panel internal structure */
.context-panel {
display: flex;
flex-direction: column;
height: 100%;
}
.context-header {
flex-shrink: 0;
}
.context-body {
flex: 1;
overflow-y: auto;
}
.context-footer {
flex-shrink: 0;
}
.context-card {
margin-bottom: 1rem;
}
.context-card .card-header {
padding: 0.5rem 1rem;
}
.context-card .card-body {
padding: 1rem;
}
/* Context Panel specific elements */
.context-scrollable {
max-height: calc(100vh - 180px);
overflow-y: auto;
}
.context-button {
transition: all 0.2s ease;
}
.context-button:hover {
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.context-text-truncate {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 100%;
}
.context-text-truncate-long {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 100%;
}
.context-photo {
width: 120px;
height: 120px;
object-fit: cover;
cursor: pointer;
transition: transform 0.3s ease;
border: 3px solid var(--primary-color);
}
.context-photo:hover {
transform: scale(1.05);
}
.context-stats-item {
min-height: 60px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.context-list {
max-height: 200px;
overflow-y: auto;
}
.context-list-item {
border-bottom: 1px solid var(--border-color) !important;
}
.context-list-item:last-child {
border-bottom: none !important;
}
.context-list-item:hover {
background-color: rgba(0, 136, 207, 0.05);
}
.context-badge-index {
width: 24px;
height: 24px;
font-size: 0.7rem;
}
.context-action-button {
min-height: 38px;
display: flex;
align-items: center;
justify-content: center;
}
/* ========================================================================== /* ==========================================================================
MODALS MODALS
========================================================================== */ ========================================================================== */
@ -465,6 +590,17 @@ body {
transition: transform 0.3s ease-out; transition: transform 0.3s ease-out;
} }
/* Modal specific styles */
.modal-messages-content {
max-height: 400px;
overflow-y: auto;
}
.modal-photo-image {
max-height: 80vh;
object-fit: contain;
}
/* ========================================================================== /* ==========================================================================
ANIMATIONS ANIMATIONS
========================================================================== */ ========================================================================== */
@ -559,18 +695,22 @@ body {
LOADERS & OVERLAYS LOADERS & OVERLAYS
========================================================================== */ ========================================================================== */
.loading-overlay { .global-loading-overlay {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
background: rgba(255, 255, 255, 0.85); background: rgba(255, 255, 255, 0.75);
display: flex; display: none;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
z-index: 9999; z-index: 9999;
backdrop-filter: blur(3px); }
.global-loading-spinner {
width: 3rem;
height: 3rem;
} }
.loader-modern { .loader-modern {
@ -659,6 +799,10 @@ body {
padding: 1rem; padding: 1rem;
} }
.main-container {
margin-top: 56px;
}
.breadcrumb { .breadcrumb {
font-size: 0.8rem; font-size: 0.8rem;
padding: 0.5rem; padding: 0.5rem;
@ -675,7 +819,33 @@ body {
.nav-link-sub { .nav-link-sub {
min-width: 120px; min-width: 120px;
padding: 0.75rem 1rem; padding: 0.75rem 1rem;
font-size: 0.8rem; font-size: 0.875rem;
}
.btn-context-toggle {
padding: 10px 6px;
}
.context-scrollable {
max-height: calc(100vh - 160px);
}
.context-photo {
width: 100px;
height: 100px;
}
.context-stats-item {
min-height: 50px;
padding: 0.25rem;
}
.context-text-truncate {
max-width: 180px;
}
.context-text-truncate-long {
max-width: 200px;
} }
} }
@ -693,6 +863,23 @@ body {
#barre_laterale_d { #barre_laterale_d {
width: 100%; width: 100%;
} }
.context-scrollable {
max-height: calc(100vh - 140px);
}
.context-photo {
width: 80px;
height: 80px;
}
.context-text-truncate {
max-width: 150px;
}
.context-text-truncate-long {
max-width: 170px;
}
} }
/* ========================================================================== /* ==========================================================================
@ -825,22 +1012,9 @@ body {
animation-name: bounceIn; animation-name: bounceIn;
} }
/* Critical CSS Inline (optionnel pour les performances) */ /* Prévenir le FOUC (Flash of Unstyled Content) */
.sr-only { .js-loading *,
position: absolute; .js-loading *:before,
width: 1px; .js-loading *:after {
height: 1px; animation-play-state: paused !important;
padding: 0; }
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
/* Prévenir le FOUC (Flash of Unstyled Content) */
.js-loading *,
.js-loading *:before,
.js-loading *:after {
animation-play-state: paused !important;
}

View File

@ -2,15 +2,6 @@
<input type="hidden" id="numeroClient_C" name="numeroClient_C" value="<?= $this->nettoyer($_SESSION['numeroClient_C']) ?>"> <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="codeGcAssureur_C" name="codeGcAssureur_C" value="<?= $this->nettoyer($_SESSION['codeGcAssureur_C']) ?>">
<!-- Toggle button -->
<button class="btn btn-primary btn-context-toggle shadow-lg"
id="showSideNav"
title="<?= _("Afficher le contexte") ?>"
style="position: fixed; right: 0; top: 50%; transform: translateY(-50%); z-index: 1000; border-radius: 20px 0 0 20px; padding: 12px 8px;">
<i class="fas fa-chevron-left me-1"></i>
<i class="fas fa-info-circle"></i>
</button>
<!-- Context Panel --> <!-- Context Panel -->
<div id="barre_laterale_d" class="context-panel shadow-lg"> <div id="barre_laterale_d" class="context-panel shadow-lg">
<div class="context-header bg-primary text-white py-3 px-4 d-flex justify-content-between align-items-center"> <div class="context-header bg-primary text-white py-3 px-4 d-flex justify-content-between align-items-center">
@ -23,7 +14,7 @@
</button> </button>
</div> </div>
<div class="context-body p-3" style="max-height: calc(100vh - 180px); overflow-y: auto;"> <div class="context-body p-3 context-scrollable">
<!-- Garant --> <!-- Garant -->
<div class="context-card card border-0 shadow-sm mb-3"> <div class="context-card card border-0 shadow-sm mb-3">
@ -43,7 +34,7 @@
<i class="fas fa-external-link-alt"></i> <i class="fas fa-external-link-alt"></i>
</a> </a>
</div> </div>
<button class="btn btn-outline-primary btn-sm w-100 text-start py-2" <button class="btn btn-outline-primary btn-sm w-100 text-start py-2 context-button"
onclick="javascript:afficher_garant('<?= $this->nettoyer($_SESSION['codeGcAssureur_C']) ?>');" onclick="javascript:afficher_garant('<?= $this->nettoyer($_SESSION['codeGcAssureur_C']) ?>');"
title="<?= _("Afficher le Garant") ?>"> title="<?= _("Afficher le Garant") ?>">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
@ -72,7 +63,7 @@
<i class="fas fa-external-link-alt"></i> <i class="fas fa-external-link-alt"></i>
</a> </a>
</div> </div>
<button class="btn btn-outline-primary btn-sm w-100 text-start py-2" <button class="btn btn-outline-primary btn-sm w-100 text-start py-2 context-button"
onclick="javascript:afficher_client_id();"> onclick="javascript:afficher_client_id();">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<i class="fas fa-user me-2"></i> <i class="fas fa-user me-2"></i>
@ -85,7 +76,7 @@
<!-- Police en cours --> <!-- Police en cours -->
<div class="context-card card border-0 shadow-sm mb-3"> <div class="context-card card border-0 shadow-sm mb-3">
<div class="card-body p-3"> <div class="card-body p-3">
<button class="btn btn-primary btn-sm w-100 text-start py-2 mb-2" <button class="btn btn-primary btn-sm w-100 text-start py-2 mb-2 context-button"
onclick="javascript:afficher_police_id();" onclick="javascript:afficher_police_id();"
title="<?= _("Couverture") . ": " . dateLang($_SESSION['dateEffet_C'], $_SESSION['lang']) . ' - ' . dateLang($_SESSION['dateEcheance_C'], $_SESSION['lang']) ?>"> title="<?= _("Couverture") . ": " . dateLang($_SESSION['dateEffet_C'], $_SESSION['lang']) . ' - ' . dateLang($_SESSION['dateEcheance_C'], $_SESSION['lang']) ?>">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
@ -102,19 +93,19 @@
<div class="stats-container bg-light rounded p-2 mb-3"> <div class="stats-container bg-light rounded p-2 mb-3">
<div class="row text-center g-2"> <div class="row text-center g-2">
<div class="col-4"> <div class="col-4">
<div class="bg-white rounded p-2"> <div class="bg-white rounded p-2 context-stats-item">
<div class="fw-bold text-primary"><?= format_N($_SESSION['ndAdh_C']) ?></div> <div class="fw-bold text-primary"><?= format_N($_SESSION['ndAdh_C']) ?></div>
<div class="x-small text-muted"><?= _("Fam.") ?></div> <div class="x-small text-muted"><?= _("Fam.") ?></div>
</div> </div>
</div> </div>
<div class="col-4"> <div class="col-4">
<div class="bg-white rounded p-2"> <div class="bg-white rounded p-2 context-stats-item">
<div class="fw-bold text-success"><?= format_N($_SESSION['ndDep_C']) ?></div> <div class="fw-bold text-success"><?= format_N($_SESSION['ndDep_C']) ?></div>
<div class="x-small text-muted"><?= _("Dép.") ?></div> <div class="x-small text-muted"><?= _("Dép.") ?></div>
</div> </div>
</div> </div>
<div class="col-4"> <div class="col-4">
<div class="bg-white rounded p-2"> <div class="bg-white rounded p-2 context-stats-item">
<div class="fw-bold text-info"><?= format_N($_SESSION['ndActif_C']) ?></div> <div class="fw-bold text-info"><?= format_N($_SESSION['ndActif_C']) ?></div>
<div class="x-small text-muted"><?= _("Bén.") ?></div> <div class="x-small text-muted"><?= _("Bén.") ?></div>
</div> </div>
@ -123,27 +114,27 @@
</div> </div>
<!-- Famille en cours --> <!-- Famille en cours -->
<button class="btn btn-outline-primary btn-sm w-100 text-start py-2 mb-2" <button class="btn btn-outline-primary btn-sm w-100 text-start py-2 mb-2 context-button"
onclick="javascript:afficher_adherent_id();" onclick="javascript:afficher_adherent_id();"
title="<?= _("Voir les membres de famille") ?>"> title="<?= _("Voir les membres de famille") ?>">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<i class="fas fa-users me-2"></i> <i class="fas fa-users me-2"></i>
<div class="flex-grow-1"> <div class="flex-grow-1">
<div class="fw-bold small"><?= _("Famille") ?> <?= $this->nettoyer($_SESSION['numeroAdherent_C']) ?></div> <div class="fw-bold small"><?= _("Famille") ?> <?= $this->nettoyer($_SESSION['numeroAdherent_C']) ?></div>
<div class="x-small text-truncate"><?= substr($this->nettoyer($_SESSION['adherent_C']), 0, 25) ?></div> <div class="x-small text-truncate context-text-truncate"><?= substr($this->nettoyer($_SESSION['adherent_C']), 0, 25) ?></div>
</div> </div>
</div> </div>
</button> </button>
<!-- Bénéficiaire en cours --> <!-- Bénéficiaire en cours -->
<button class="btn btn-outline-primary btn-sm w-100 text-start py-2" <button class="btn btn-outline-primary btn-sm w-100 text-start py-2 context-button"
onclick="javascript:afficher_beneficiaire_id();" onclick="javascript:afficher_beneficiaire_id();"
title="<?= _("Couverture") . ": " . dateLang($_SESSION['dateEntreeBeneficiaire_C'], $_SESSION['lang']) . ' - ' . dateLang($_SESSION['dateEcheancePolice_C'], $_SESSION['lang']) ?>"> title="<?= _("Couverture") . ": " . dateLang($_SESSION['dateEntreeBeneficiaire_C'], $_SESSION['lang']) . ' - ' . dateLang($_SESSION['dateEcheancePolice_C'], $_SESSION['lang']) ?>">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<i class="fas fa-user me-2"></i> <i class="fas fa-user me-2"></i>
<div class="flex-grow-1"> <div class="flex-grow-1">
<div class="fw-bold small"><?= _("Bénéficiaire") ?> <?= $this->nettoyer($_SESSION['numeroBeneficiaire_C']) ?></div> <div class="fw-bold small"><?= _("Bénéficiaire") ?> <?= $this->nettoyer($_SESSION['numeroBeneficiaire_C']) ?></div>
<div class="x-small text-truncate"><?= substr($this->nettoyer($_SESSION['beneficiaire_C']), 0, 25) ?></div> <div class="x-small text-truncate context-text-truncate"><?= substr($this->nettoyer($_SESSION['beneficiaire_C']), 0, 25) ?></div>
</div> </div>
</div> </div>
</button> </button>
@ -156,8 +147,7 @@
<div class="card-body p-3 text-center"> <div class="card-body p-3 text-center">
<div class="photo-wrapper mb-2"> <div class="photo-wrapper mb-2">
<img src="data:image/jpg;base64,<?= $imgData ?>" <img src="data:image/jpg;base64,<?= $imgData ?>"
class="img-fluid rounded-circle shadow-sm border border-3 border-primary" class="img-fluid rounded-circle shadow-sm border border-3 border-primary context-photo"
style="width: 120px; height: 120px; object-fit: cover; cursor: pointer;"
data-bs-toggle="modal" data-bs-toggle="modal"
data-bs-target="#pop_photo" data-bs-target="#pop_photo"
alt="<?= _("Photo du bénéficiaire") ?>" alt="<?= _("Photo du bénéficiaire") ?>"
@ -177,14 +167,13 @@
</h6> </h6>
</div> </div>
<div class="card-body p-3"> <div class="card-body p-3">
<div class="list-group list-group-flush"> <div class="list-group list-group-flush context-list">
<?php foreach ($_SESSION['contextPolice'] as $index => $contextPolice): ?> <?php foreach ($_SESSION['contextPolice'] as $index => $contextPolice): ?>
<?php if ($index < 5): ?> <?php if ($index < 5): ?>
<a href="javascript:selectionner_police(<?= $contextPolice['idPolice'] ?>,'<?= $contextPolice['numeroPolice'] ?>');afficher_police_id();" <a href="javascript:selectionner_police(<?= $contextPolice['idPolice'] ?>,'<?= $contextPolice['numeroPolice'] ?>');afficher_police_id();"
class="list-group-item list-group-item-action border-0 py-2 px-0"> class="list-group-item list-group-item-action border-0 py-2 px-0 context-list-item">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<div class="badge bg-primary bg-opacity-10 text-primary rounded-circle me-2 d-flex align-items-center justify-content-center" <div class="badge bg-primary bg-opacity-10 text-primary rounded-circle me-2 d-flex align-items-center justify-content-center context-badge-index">
style="width: 24px; height: 24px; font-size: 0.7rem;">
<?= $index + 1 ?> <?= $index + 1 ?>
</div> </div>
<div class="flex-grow-1"> <div class="flex-grow-1">
@ -205,14 +194,14 @@
<div class="card-body p-3"> <div class="card-body p-3">
<div class="row g-2"> <div class="row g-2">
<div class="col-6"> <div class="col-6">
<button class="btn btn-outline-primary btn-sm w-100 py-2" <button class="btn btn-outline-primary btn-sm w-100 py-2 context-action-button"
onclick="javascript:gerer_messagerie();"> onclick="javascript:gerer_messagerie();">
<i class="fas fa-comments me-1"></i> <i class="fas fa-comments me-1"></i>
<span class="d-none d-md-inline"><?= _("Messages") ?></span> <span class="d-none d-md-inline"><?= _("Messages") ?></span>
</button> </button>
</div> </div>
<div class="col-6"> <div class="col-6">
<button class="btn btn-outline-primary btn-sm w-100 py-2" <button class="btn btn-outline-primary btn-sm w-100 py-2 context-action-button"
onclick="javascript:change_password();"> onclick="javascript:change_password();">
<i class="fas fa-key me-1"></i> <i class="fas fa-key me-1"></i>
<span class="d-none d-md-inline"><?= est_anglophone() ? 'Password' : 'MDP' ?></span> <span class="d-none d-md-inline"><?= est_anglophone() ? 'Password' : 'MDP' ?></span>
@ -233,7 +222,7 @@
</div> </div>
<div class="card-body p-3"> <div class="card-body p-3">
<!-- Prospect --> <!-- Prospect -->
<button class="btn btn-outline-warning btn-sm w-100 text-start py-2 mb-2" <button class="btn btn-outline-warning btn-sm w-100 text-start py-2 mb-2 context-button"
onclick="javascript:afficher_client_d_id();"> onclick="javascript:afficher_client_d_id();">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<i class="fas fa-user-clock me-2"></i> <i class="fas fa-user-clock me-2"></i>
@ -243,12 +232,12 @@
</div> </div>
</div> </div>
</button> </button>
<div class="small text-muted mb-3 text-truncate"> <div class="small text-muted mb-3 text-truncate context-text-truncate-long">
<?= substr($this->nettoyer($_SESSION['nomClient_d_C']), 0, 30) ?> <?= substr($this->nettoyer($_SESSION['nomClient_d_C']), 0, 30) ?>
</div> </div>
<!-- Police devis --> <!-- Police devis -->
<button class="btn btn-warning btn-sm w-100 text-start py-2" <button class="btn btn-warning btn-sm w-100 text-start py-2 context-button"
onclick="javascript:afficher_police_d_id_init();"> onclick="javascript:afficher_police_d_id_init();">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<i class="fas fa-file-invoice-dollar me-2"></i> <i class="fas fa-file-invoice-dollar me-2"></i>

View File

@ -42,7 +42,7 @@ $retourVue = $infovue['lienRetour'];
<?php include 'header.php'; ?> <?php include 'header.php'; ?>
<!-- Main Container --> <!-- Main Container -->
<div class="d-flex flex-grow-1" style="margin-top: 60px;"> <div class="d-flex flex-grow-1 main-container">
<!-- Sidebar --> <!-- Sidebar -->
<?php include 'sidebar.php'; ?> <?php include 'sidebar.php'; ?>
@ -81,14 +81,13 @@ $retourVue = $infovue['lienRetour'];
<?php if (isset($menusvue) && sizeof($menusvue) > 0): ?> <?php if (isset($menusvue) && sizeof($menusvue) > 0): ?>
<div class="tabs-container mb-4 px-2"> <div class="tabs-container mb-4 px-2">
<div class="card border-0 shadow-sm rounded-3 overflow-hidden"> <div class="card border-0 shadow-sm rounded-3 overflow-hidden">
<div class="d-flex overflow-auto"> <div class="d-flex overflow-auto secondary-nav-container">
<?php foreach ($menusvue as $menu): <?php foreach ($menusvue as $menu):
$isActive = (basename($_SERVER['REQUEST_URI']) == basename($menu['lienMenu'])); $isActive = (basename($_SERVER['REQUEST_URI']) == basename($menu['lienMenu']));
$activeClass = $isActive ? 'active bg-primary text-white' : 'text-dark'; $activeClass = $isActive ? 'active' : '';
?> ?>
<a class="nav-link-sub p-3 <?= $activeClass ?>" <a class="nav-link-sub p-3 <?= $activeClass ?>"
href="<?= $menu['lienMenu']; ?>" href="<?= $menu['lienMenu']; ?>">
style="min-width: 150px; white-space: nowrap; border-right: 1px solid #e9ecef;">
<?php if (!empty($menu['icone'])): ?> <?php if (!empty($menu['icone'])): ?>
<i class="<?= $menu['icone'] ?> me-2"></i> <i class="<?= $menu['icone'] ?> me-2"></i>
<?php endif; ?> <?php endif; ?>
@ -118,10 +117,10 @@ $retourVue = $infovue['lienRetour'];
<!-- Context Panel --> <!-- Context Panel -->
<?php include 'contexte.php'; ?> <?php include 'contexte.php'; ?>
<button class="btn btn-primary btn-context-toggle shadow-lg" <!-- Context Toggle Button -->
<button class="btn-context-toggle"
id="showSideNav" id="showSideNav"
title="<?= _("Afficher le contexte") ?>" title="<?= _("Afficher le contexte") ?>">
style="position: fixed; right: 0; top: 50%; transform: translateY(-50%); z-index: 1005; border-radius: 20px 0 0 20px; padding: 12px 8px; background: #0088cf; color: white; border: none; cursor: pointer; display: flex; align-items: center; justify-content: center;">
<i class="fas fa-chevron-left me-1"></i> <i class="fas fa-chevron-left me-1"></i>
<i class="fas fa-info-circle"></i> <i class="fas fa-info-circle"></i>
</button> </button>
@ -142,7 +141,7 @@ $retourVue = $infovue['lienRetour'];
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body p-0"> <div class="modal-body p-0">
<div id="div_messagerie" class="p-4" style="max-height: 400px; overflow-y: auto;"> <div id="div_messagerie" class="p-4 modal-messages-content">
<div class="text-center py-5 text-muted"> <div class="text-center py-5 text-muted">
<i class="fas fa-envelope-open fa-3x mb-3"></i> <i class="fas fa-envelope-open fa-3x mb-3"></i>
<p class="mb-0"><?= _("Aucun message non lu") ?></p> <p class="mb-0"><?= _("Aucun message non lu") ?></p>
@ -199,8 +198,7 @@ $retourVue = $infovue['lienRetour'];
<div class="modal-body text-center p-0"> <div class="modal-body text-center p-0">
<?php if (!empty($imgData) && $_SESSION['faceRegistered_C'] == "1"): ?> <?php if (!empty($imgData) && $_SESSION['faceRegistered_C'] == "1"): ?>
<img src="data:image/jpg;base64,<?= $imgData ?>" <img src="data:image/jpg;base64,<?= $imgData ?>"
class="img-fluid rounded shadow-lg border border-5 border-white" class="img-fluid rounded shadow-lg border border-5 border-white modal-photo-image"
style="max-height: 80vh; object-fit: contain;"
alt="<?= _("Photo du bénéficiaire") ?>"> alt="<?= _("Photo du bénéficiaire") ?>">
<h4 class="text-white mt-3 fw-bold"><?= $_SESSION['nomBeneficiaire_C'] ?? '' ?></h4> <h4 class="text-white mt-3 fw-bold"><?= $_SESSION['nomBeneficiaire_C'] ?? '' ?></h4>
<?php else: ?> <?php else: ?>
@ -222,10 +220,6 @@ $retourVue = $infovue['lienRetour'];
<script src="Bootstrap/js/jquery.min.js"></script> <script src="Bootstrap/js/jquery.min.js"></script>
<script src="Bootstrap/js/jquery-ui.js"></script> <script src="Bootstrap/js/jquery-ui.js"></script>
<!-- ======= Scripts ======= -->
<script src="Bootstrap/js/jquery.min.js"></script>
<script src="Bootstrap/js/jquery-ui.js"></script>
<!-- Bootstrap 5 Bundle --> <!-- Bootstrap 5 Bundle -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
@ -293,16 +287,15 @@ $retourVue = $infovue['lienRetour'];
$('body').toggleClass('toggle-sidebar'); $('body').toggleClass('toggle-sidebar');
}); });
// Gestion de la barre de contexte - version corrigée // Gestion de la barre de contexte
$(document).on('click', '#showSideNav', function(e) { $(document).on('click', '#showSideNav', function(e) {
console.log("Show context panel cliqué"); console.log("Show context panel cliqué");
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
// Vérifier si l'élément existe
if ($('#barre_laterale_d').length) { if ($('#barre_laterale_d').length) {
$('#barre_laterale_d').addClass('active'); $('#barre_laterale_d').addClass('active');
$(this).fadeOut(200); $(this).hide();
console.log("Panel de contexte activé"); console.log("Panel de contexte activé");
} else { } else {
console.error("Élément #barre_laterale_d non trouvé"); console.error("Élément #barre_laterale_d non trouvé");
@ -315,7 +308,7 @@ $retourVue = $infovue['lienRetour'];
e.stopPropagation(); e.stopPropagation();
$('#barre_laterale_d').removeClass('active'); $('#barre_laterale_d').removeClass('active');
$('#showSideNav').fadeIn(200); $('#showSideNav').show();
}); });
// Fermer le panneau si on clique en dehors // Fermer le panneau si on clique en dehors
@ -324,7 +317,7 @@ $retourVue = $infovue['lienRetour'];
!$(e.target).closest('#barre_laterale_d').length && !$(e.target).closest('#barre_laterale_d').length &&
!$(e.target).closest('#showSideNav').length) { !$(e.target).closest('#showSideNav').length) {
$('#barre_laterale_d').removeClass('active'); $('#barre_laterale_d').removeClass('active');
$('#showSideNav').fadeIn(200); $('#showSideNav').show();
} }
}); });
@ -348,7 +341,7 @@ $retourVue = $infovue['lienRetour'];
// Vérifier toutes les 2 secondes // Vérifier toutes les 2 secondes
setInterval(syncBadge, 2000); setInterval(syncBadge, 2000);
syncBadge(); // Première exécution syncBadge();
// Rafraîchir le gabarit // Rafraîchir le gabarit
if (typeof raffraichier_gabarit === 'function') { if (typeof raffraichier_gabarit === 'function') {
@ -379,24 +372,18 @@ $retourVue = $infovue['lienRetour'];
"extendedTimeOut": "1000" "extendedTimeOut": "1000"
}; };
} }
// Debug: Vérifier que les éléments existent
console.log("Éléments trouvés:");
console.log("#showSideNav:", $('#showSideNav').length);
console.log("#hideSideNav:", $('#hideSideNav').length);
console.log("#barre_laterale_d:", $('#barre_laterale_d').length);
}); });
// Fonction pour ouvrir le panneau depuis d'autres scripts // Fonction pour ouvrir le panneau depuis d'autres scripts
function ouvrirPanneauContexte() { function ouvrirPanneauContexte() {
$('#barre_laterale_d').addClass('active'); $('#barre_laterale_d').addClass('active');
$('#showSideNav').fadeOut(200); $('#showSideNav').hide();
} }
// Fonction pour fermer le panneau depuis d'autres scripts // Fonction pour fermer le panneau depuis d'autres scripts
function fermerPanneauContexte() { function fermerPanneauContexte() {
$('#barre_laterale_d').removeClass('active'); $('#barre_laterale_d').removeClass('active');
$('#showSideNav').fadeIn(200); $('#showSideNav').show();
} }
</script> </script>
@ -404,8 +391,8 @@ $retourVue = $infovue['lienRetour'];
<div id="div_ajaxgabarit" class="d-none"></div> <div id="div_ajaxgabarit" class="d-none"></div>
<!-- Global Loading Overlay --> <!-- Global Loading Overlay -->
<div id="globalLoading" class="position-fixed top-0 start-0 w-100 h-100 bg-white bg-opacity-75 d-flex justify-content-center align-items-center" style="z-index: 9999; display: none !important;"> <div id="globalLoading" class="global-loading-overlay">
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"> <div class="spinner-border text-primary global-loading-spinner" role="status">
<span class="visually-hidden"><?= _("Chargement...") ?></span> <span class="visually-hidden"><?= _("Chargement...") ?></span>
</div> </div>
</div> </div>

View File

@ -5,120 +5,127 @@
<meta name="description" content="INTER SANTÉ - Gestionnaire de santé"> <meta name="description" content="INTER SANTÉ - Gestionnaire de santé">
<meta name="author" content="INTER SANTÉ"> <meta name="author" content="INTER SANTÉ">
<meta name="robots" content="noindex, nofollow"> <meta name="robots" content="noindex, nofollow">
<meta name="theme-color" content="#0088cf">
<!-- Pour PWA/iOS -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="INTER SANTÉ">
<base href="<?= $racineWeb ?>"> <base href="<?= $racineWeb ?>">
<!-- Favicon --> <!-- Favicon -->
<link rel="icon" href="Bootstrap_new/images/favicon.ico" type="image/x-icon"> <link rel="icon" href="Bootstrap_new/images/favicon.ico" type="image/x-icon">
<link rel="icon" href="Bootstrap_new/images/favicon-32x32.png" type="image/png" sizes="32x32">
<link rel="icon" href="Bootstrap_new/images/favicon-16x16.png" type="image/png" sizes="16x16">
<link rel="apple-touch-icon" href="Bootstrap_new/images/apple-touch-icon.png"> <link rel="apple-touch-icon" href="Bootstrap_new/images/apple-touch-icon.png">
<!-- Preconnect pour améliorer les performances --> <!-- Preconnect pour améliorer les performances -->
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="dns-prefetch" href="https://cdn.jsdelivr.net"> <link rel="dns-prefetch" href="https://cdn.jsdelivr.net">
<link rel="dns-prefetch" href="https://cdnjs.cloudflare.com">
<!-- Google Fonts --> <!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Poppins:wght@400;500;600&display=swap" rel="stylesheet" media="print" onload="this.media='all'"> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Poppins:wght@400;500;600&display=swap"
rel="stylesheet"
crossorigin="anonymous">
<!-- Bootstrap 5 CSS --> <!-- Bootstrap 5 CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM"
crossorigin="anonymous">
<!-- Font Awesome avec fallback --> <!-- Font Awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" integrity="sha512-Avb2QiuDEEvB4bZJYdft2mNjVShBftLdPG8FJ0V7irTLQ8Uo0qcPxh4Plq7G5tGm0rU+1SPhVotteLpBERwTkw==" crossorigin="anonymous" referrerpolicy="no-referrer"> <link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"
integrity="sha512-Avb2QiuDEEvB4bZJYdft2mNjVShBftLdPG8FJ0V7irTLQ8Uo0qcPxh4Plq7G5tGm0rU+1SPhVotteLpBERwTkw=="
crossorigin="anonymous"
referrerpolicy="no-referrer">
<!-- Vendor CSS - Chargement différé --> <!-- Vendor CSS -->
<link href="Bootstrap/vendor/boxicons/css/boxicons.min.css" rel="stylesheet" media="print" onload="this.media='all'"> <link href="Bootstrap/vendor/boxicons/css/boxicons.min.css" rel="stylesheet">
<!-- Toastr CSS --> <!-- Toastr CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css" integrity="sha512-vKMx8UnXk60zUwyUnUPM3HbQo8QfmNx7+ltw8Pm5zLusl1XIfwcxo8DbWCqMGKaWeNxWA8yrx5v3SaVpMvR3CA==" crossorigin="anonymous" referrerpolicy="no-referrer"> <link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css"
integrity="sha512-vKMx8UnXk60zUwyUnUPM3HbQo8QfmNx7+ltw8Pm5zLusl1XIfwcxo8DbWCqMGKaWeNxWA8yrx5v3SaVpMvR3CA=="
crossorigin="anonymous"
referrerpolicy="no-referrer">
<!-- SweetAlert2 --> <!-- SweetAlert2 -->
<link href="https://cdn.jsdelivr.net/npm/sweetalert2@11.14.1/dist/sweetalert2.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/sweetalert2@11.14.1/dist/sweetalert2.min.css"
rel="stylesheet">
<!-- Animate.css - version locale recommandée --> <!-- Animate.css -->
<link href="Bootstrap_new/css/animate.min.css" rel="stylesheet"> <link href="Bootstrap_new/css/animate.min.css" rel="stylesheet">
<!-- Vendor CSS spécifiques (chargement conditionnel) --> <!-- Vendor CSS spécifiques (chargement conditionnel) -->
<?php if (strpos($_SERVER['REQUEST_URI'], 'quill') !== false): ?> <?php
$current_page = $_SERVER['REQUEST_URI'] ?? '';
$needQuill = strpos($current_page, 'quill') !== false;
$needDatatables = isset($needDatatables) ? $needDatatables : false;
$needSelect2 = isset($needSelect2) ? $needSelect2 : false;
?>
<?php if ($needQuill): ?>
<link href="Bootstrap/vendor/quill/quill.snow.css" rel="stylesheet"> <link href="Bootstrap/vendor/quill/quill.snow.css" rel="stylesheet">
<?php endif; ?> <?php endif; ?>
<!-- DataTables CSS (seulement si nécessaire) --> <?php if ($needDatatables): ?>
<?php if (isset($needDatatables) && $needDatatables): ?>
<link href="Bootstrap_new/css/datatables.min.css" rel="stylesheet"> <link href="Bootstrap_new/css/datatables.min.css" rel="stylesheet">
<?php endif; ?> <?php endif; ?>
<!-- Select2 CSS (seulement si nécessaire) --> <?php if ($needSelect2): ?>
<?php if (isset($needSelect2) && $needSelect2): ?>
<link href="Bootstrap_new/css/select2.min.css" rel="stylesheet"> <link href="Bootstrap_new/css/select2.min.css" rel="stylesheet">
<link href="Bootstrap_new/css/select2-bootstrap-5-theme.min.css" rel="stylesheet">
<?php endif; ?> <?php endif; ?>
<!-- Chart.js - déplacé en bas du body pour les performances -->
<!-- Styles personnalisés --> <!-- Styles personnalisés -->
<link href="Bootstrap_new/css/style_moderne.css?ver=<?= date('Y.m.d.H') ?>" rel="stylesheet"> <link href="Bootstrap_new/css/style_moderne.css?ver=<?= date('Y.m.d.H') ?>" rel="stylesheet">
<title><?= htmlspecialchars($_SESSION['vue'] ?? 'Dashboard') ?> - INTER SANTÉ</title> <title><?= htmlspecialchars($_SESSION['vue'] ?? 'Dashboard') ?> - INTER SANTÉ</title>
<!-- Scripts de prévention de clic droit en mode production --> <!-- Scripts de prévention de clic droit -->
<script type="text/javascript"> <script type="text/javascript">
// Marquer le body comme loading
document.documentElement.className = 'js-loading';
var modeDev = <?= json_encode($modeDev ?? '0') ?>; var modeDev = <?= json_encode($modeDev ?? '0') ?>;
// Charger toastr seulement si disponible
function safeToastr() {
if (typeof toastr !== 'undefined') {
return toastr;
}
return {
warning: function(msg) { console.warn(msg); },
error: function(msg) { console.error(msg); },
success: function(msg) { console.log(msg); },
info: function(msg) { console.info(msg); }
};
}
if (modeDev != "1") { if (modeDev != "1") {
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
// Prévention clic droit
document.addEventListener('contextmenu', function(e) { document.addEventListener('contextmenu', function(e) {
e.preventDefault(); e.preventDefault();
safeToastr().warning('<?= _("Le clic droit est désactivé en mode production") ?>'); if (typeof toastr !== 'undefined') {
toastr.warning('<?= _("Le clic droit est désactivé en mode production") ?>');
}
}); });
// Prévention des raccourcis clavier // Prévention des raccourcis clavier
document.addEventListener('keydown', function(e) { document.addEventListener('keydown', function(e) {
// Ctrl+U (afficher le code source) // Ctrl+U (code source)
if (e.ctrlKey && e.keyCode === 85) { if (e.ctrlKey && e.keyCode === 85) {
e.preventDefault(); e.preventDefault();
safeToastr().warning('<?= _("Cette fonctionnalité est désactivée") ?>'); if (typeof toastr !== 'undefined') {
toastr.warning('<?= _("Cette fonctionnalité est désactivée") ?>');
}
} }
// F12 (outils de développement) // F12 (outils de développement)
if (e.keyCode === 123) { if (e.keyCode === 123) {
e.preventDefault(); e.preventDefault();
safeToastr().warning('<?= _("Les outils de développement sont désactivés") ?>'); if (typeof toastr !== 'undefined') {
toastr.warning('<?= _("Les outils de développement sont désactivés") ?>');
}
} }
// Ctrl+Shift+I, Ctrl+Shift+J, Ctrl+Shift+C // Ctrl+Shift+I, Ctrl+Shift+J, Ctrl+Shift+C
if (e.ctrlKey && e.shiftKey && [73, 74, 67].includes(e.keyCode)) { if (e.ctrlKey && e.shiftKey && [73, 74, 67].includes(e.keyCode)) {
e.preventDefault(); e.preventDefault();
safeToastr().warning('<?= _("Cette fonctionnalité est désactivée") ?>'); if (typeof toastr !== 'undefined') {
toastr.warning('<?= _("Cette fonctionnalité est désactivée") ?>');
}
} }
}); });
}); });
} }
// Retirer la classe loading quand la page est chargée
window.addEventListener('load', function() {
document.documentElement.className = document.documentElement.className.replace('js-loading', '');
});
</script>
<!-- Polyfill pour les vieux navigateurs -->
<script>
// Polyfill pour les fonctions ES6 si nécessaire
if (!window.Promise) {
document.write('<script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"><\/script>');
}
</script> </script>
</head> </head>

View File

@ -23,10 +23,10 @@
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<a class="logo d-flex align-items-center text-decoration-none me-4"> <a class="logo d-flex align-items-center text-decoration-none me-4">
<img src="Bootstrap_new/images/new/favicon.png" alt="Logo INTER SANTÉ" class="img-fluid"> <img src="Bootstrap_new/images/new/favicon.png" alt="Logo INTER SANTÉ" class="img-fluid">
<span class="d-none d-lg-block fw-bold fs-5">INTER SANTÉ</span> <span class="d-none d-lg-block">INTER SANTE</span>
</a> </a>
<button class="toggle-sidebar-btn btn btn-link text-dark d-lg-none"> <button class="toggle-sidebar-btn btn btn-link text-dark d-lg-none">
<i class="fas fa-bars fs-5"></i> <i class="bi bi-list"></i>
</button> </button>
</div> </div>