748 lines
35 KiB
PHP
Executable File
748 lines
35 KiB
PHP
Executable File
<?php
|
|
require_once 'gabarit_queries.php';
|
|
$gabary = new Gabary();
|
|
$_SESSION['firstLevelMenu'] = '';
|
|
$current_url = $_SERVER['REQUEST_URI'];
|
|
$elements = explode("/", $current_url);
|
|
$activeLink = $elements[1] ?? '';
|
|
$_SESSION['firstLevelMenu'] = $activeLink;
|
|
|
|
$companyDisplayName = htmlspecialchars($_SESSION['nomSociete'], ENT_QUOTES);
|
|
$imgData = $_SESSION['photoAssureCrypte'] ?? '';
|
|
|
|
// Détection automatique des menus actifs - VERSION CORRIGÉE
|
|
$activeParentId = null;
|
|
$activeChildId = null;
|
|
|
|
foreach ($menus as $key0 => $menuParent) {
|
|
$menuChildrenLevelOne = $gabary->get_menus_by_parent_code($menuParent['vue']);
|
|
|
|
// 1. Vérifier si c'est un lien DIRECT (comme "Accueil")
|
|
if (empty($menuChildrenLevelOne)) {
|
|
// Menu sans enfants = lien direct
|
|
$parentLink = explode('/', $menuParent['lienMenu'])[0] ?? '';
|
|
if (!empty($parentLink) && $parentLink == $activeLink) {
|
|
$activeParentId = $key0;
|
|
break;
|
|
}
|
|
}
|
|
// 2. Vérifier les SOUS-MENUS (enfants)
|
|
else {
|
|
foreach ($menuChildrenLevelOne as $key1 => $menuChild) {
|
|
$childLink = explode('/', $menuChild['lienMenu'])[0] ?? '';
|
|
if ($childLink == $activeLink) {
|
|
$activeParentId = $key0;
|
|
$activeChildId = $key1;
|
|
break 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// CORRECTION IMPORTANTE : Si c'est "Accueil" et pas trouvé, c'est menu 0
|
|
if ($activeParentId === null && $activeLink == 'Accueil') {
|
|
$activeParentId = 0;
|
|
}
|
|
|
|
// Toujours avoir une valeur
|
|
if ($activeParentId === null) {
|
|
$activeParentId = 0;
|
|
}
|
|
?>
|
|
|
|
<!DOCTYPE html>
|
|
<html lang="fr" data-bs-theme="light">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
<base href="<?= $racineWeb ?>">
|
|
|
|
<title><?= htmlspecialchars($_SESSION['vue'] ?? 'INTER-SANTE') ?> | Portail Santé</title>
|
|
|
|
<!-- Meta pour UX améliorée -->
|
|
<meta name="description" content="Portail RH de gestion santé - INTER-SANTE">
|
|
<meta name="theme-color" content="#b7472a">
|
|
|
|
<!-- PWA Meta Tags -->
|
|
<meta name="mobile-web-app-capable" content="yes">
|
|
<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-SANTE">
|
|
|
|
<!-- Icône -->
|
|
<link rel="apple-touch-icon" href="<?= $racineWeb ?>Bootstrap_new/images/new/favicon.png">
|
|
<link rel="icon" href="<?= $racineWeb ?>Bootstrap_new/images/new/favicon.png" type="image/png">
|
|
|
|
<!-- ============================================
|
|
ORDRE CRITIQUE : CSS
|
|
============================================ -->
|
|
|
|
<!-- 1. BOOTSTRAP 5 (DOIT ÊTRE EN PREMIER) -->
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"
|
|
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
|
|
crossorigin="anonymous">
|
|
|
|
<!-- 2. OVERRIDE BOOTSTRAP (DOIT ÊTRE IMMÉDIATEMENT APRÈS) -->
|
|
<link href="<?= $racineWeb ?>Bootstrap_new/css/override.css?ver=2025.12.21.01" rel="stylesheet">
|
|
|
|
<!-- 3. AUTRES CDN (après l'override) -->
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
|
|
|
<!-- Select2 -->
|
|
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet">
|
|
<link href="https://cdn.jsdelivr.net/npm/select2-bootstrap-5-theme@1.3.0/dist/select2-bootstrap-5-theme.min.css" rel="stylesheet">
|
|
|
|
<!-- DataTables -->
|
|
<link href="https://cdn.datatables.net/v/bs5/jq-3.7.0/dt-2.0.3/datatables.min.css" rel="stylesheet">
|
|
|
|
<!-- SweetAlert2 -->
|
|
<link href="https://cdn.jsdelivr.net/npm/sweetalert2@11.10.5/dist/sweetalert2.min.css" rel="stylesheet">
|
|
|
|
<!-- Animate.css -->
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">
|
|
|
|
<!-- jQuery UI -->
|
|
<link rel="stylesheet" href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css">
|
|
|
|
<!-- Progressive Web App -->
|
|
<link rel="manifest" href="<?= $racineWeb ?>manifest.json">
|
|
|
|
<!-- 4. VOS STYLES PERSONNALISÉS (en dernier pour qu'ils dominent) -->
|
|
<link href="<?= $racineWeb ?>Bootstrap_new/css/style_office.css?ver=2025.12.21.02" rel="stylesheet">
|
|
<link href="<?= $racineWeb ?>Bootstrap_new/css/ux_enhancements.css?ver=2025.12.21.02" rel="stylesheet">
|
|
|
|
<!-- ============================================
|
|
SCRIPTS ET CONFIGURATION
|
|
============================================ -->
|
|
|
|
<script>
|
|
// Mode développeur
|
|
//const modeDev = <?= $_SESSION['modeDev_C'] ?? 0 ?>;
|
|
const modeDev = 1;
|
|
if (modeDev !== 1) {
|
|
document.addEventListener('contextmenu', e => e.preventDefault());
|
|
}
|
|
|
|
// Variables globales
|
|
window.appConfig = {
|
|
activeParentId: '<?= $activeParentId ?>',
|
|
activeChildId: '<?= $activeChildId ?>',
|
|
activeLink: '<?= $activeLink ?>',
|
|
racineWeb: '<?= $racineWeb ?>',
|
|
baseUrl: '<?= $racineWeb ?>',
|
|
isAnglophone: <?= est_anglophone() ? 'true' : 'false' ?>,
|
|
modeTest: <?= $_SESSION['bdTests_C'] == "1" ? 'true' : 'false' ?>,
|
|
userInitials: '<?= $_SESSION['userInitials_C'] ?? 'U' ?>',
|
|
// Debug info
|
|
debugMode: true,
|
|
cssOverride: true
|
|
};
|
|
|
|
// Debug CSS loading
|
|
console.log('[App] Configuration chargée:', window.appConfig);
|
|
|
|
// Vérifier le chargement CSS
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
setTimeout(function() {
|
|
const overrideLoaded = Array.from(document.styleSheets).some(sheet =>
|
|
sheet.href && sheet.href.includes('override.css')
|
|
);
|
|
|
|
console.log('[CSS] Override.css chargé:', overrideLoaded);
|
|
|
|
if (!overrideLoaded) {
|
|
console.warn('[CSS] Override.css manquant!');
|
|
// Charger dynamiquement
|
|
const link = document.createElement('link');
|
|
link.rel = 'stylesheet';
|
|
link.href = window.appConfig.baseUrl + 'Bootstrap_new/css/override.css?nocache=' + Date.now();
|
|
document.head.appendChild(link);
|
|
}
|
|
}, 100);
|
|
});
|
|
</script>
|
|
|
|
<!-- ============================================
|
|
CSS DE SECOURS INLINE (garanti de fonctionner)
|
|
============================================ -->
|
|
<style>
|
|
/* CSS DE SECOURS - S'applique immédiatement */
|
|
:root {
|
|
--office-primary: #b7472a;
|
|
--office-secondary: #2b579a;
|
|
--office-light: #f3f2f1;
|
|
}
|
|
|
|
/* Styles de base garantis */
|
|
body {
|
|
font-family: 'Segoe UI', Arial, sans-serif !important;
|
|
margin: 0 !important;
|
|
padding: 0 !important;
|
|
min-height: 100vh !important;
|
|
}
|
|
|
|
/* Debug visuel */
|
|
.css-loaded-indicator {
|
|
position: fixed !important;
|
|
top: 10px !important;
|
|
right: 10px !important;
|
|
background: #27ae60 !important;
|
|
color: white !important;
|
|
padding: 8px 12px !important;
|
|
border-radius: 4px !important;
|
|
z-index: 99999 !important;
|
|
font-size: 12px !important;
|
|
font-weight: bold !important;
|
|
display: none;
|
|
}
|
|
|
|
/* Forcer la visibilité pendant le chargement */
|
|
[class*="app-"] {
|
|
min-height: 20px !important;
|
|
min-width: 20px !important;
|
|
}
|
|
|
|
.context-body {
|
|
background-color: #d0d0d0 !important;
|
|
}
|
|
</style>
|
|
|
|
<!-- Open Graph pour le partage -->
|
|
<meta property="og:title" content="INTER-SANTE Portail RH">
|
|
<meta property="og:description" content="Portail professionnel de gestion santé">
|
|
<meta property="og:image" content="<?= $racineWeb ?>Bootstrap_new/images/new/favicon.png">
|
|
<meta property="og:url" content="<?= $racineWeb ?>">
|
|
<meta property="og:type" content="website">
|
|
|
|
<!-- Twitter Cards -->
|
|
<meta name="twitter:card" content="summary">
|
|
<meta name="twitter:title" content="INTER-SANTE Portail RH">
|
|
<meta name="twitter:description" content="Portail RH de gestion santé">
|
|
<meta name="twitter:image" content="<?= $racineWeb ?>Bootstrap_new/images/new/favicon.png">
|
|
</head>
|
|
|
|
<body>
|
|
<!-- Header -->
|
|
<header class="app-header">
|
|
<div class="header-content">
|
|
<div class="logo-container">
|
|
<button class="header-btn sidebar-toggle d-lg-none" aria-label="Menu navigation" onclick="appUX.toggleSidebar()">
|
|
<i class="bi bi-list"></i>
|
|
</button>
|
|
|
|
<a href="Accueil" class="app-logo">
|
|
<img src="Bootstrap_new/images/new/favicon.png" alt="INTER-SANTE" width="36" height="36">
|
|
<span class="ms-2">INTER-SANTE</span>
|
|
</a>
|
|
|
|
<?php if($_SESSION['bdTests_C'] == "1"): ?>
|
|
<div class="test-indicator" role="status" aria-label="Mode test activé">
|
|
<i class="fas fa-flask"></i>
|
|
<span>MODE TEST</span>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="header-controls">
|
|
<!-- Notifications -->
|
|
<button class="header-btn notification-btn" onclick="appNotifications.showMessagesModal()"
|
|
aria-label="Notifications" title="<?= _('Voir les notifications') ?>">
|
|
<i class="bi bi-bell"></i>
|
|
<span class="notification-badge" id="notificationCount" aria-live="polite">0</span>
|
|
</button>
|
|
|
|
<!-- Language Selector -->
|
|
<div class="language-selector" onclick="appLanguage.changeLanguage()"
|
|
role="button" tabindex="0"
|
|
aria-label="<?= _('Changer de langue') ?>">
|
|
<?php
|
|
$flag = est_anglophone() ? 'england.png' : 'france.png';
|
|
$lib = est_anglophone() ? 'EN' : 'FR';
|
|
?>
|
|
<img src="Bootstrap_new/images/<?= $flag ?>" alt="<?= $lib ?>" class="language-flag" width="24" height="16">
|
|
<span><?= $lib ?></span>
|
|
</div>
|
|
|
|
<!-- User Menu -->
|
|
<div class="user-menu dropdown-toggle" data-bs-toggle="dropdown"
|
|
aria-expanded="false" aria-label="Menu utilisateur">
|
|
<div class="user-avatar" role="img" aria-label="Avatar utilisateur">
|
|
<?= $_SESSION['userInitials_C'] ?? 'U' ?>
|
|
</div>
|
|
<div class="user-info">
|
|
<div class="user-name"><?= $_SESSION['utilisateur_C'] ?? _('Utilisateur') ?></div>
|
|
<div class="user-role"><?= $_SESSION['nomClient_C'] ?? _('Client') ?></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- User Dropdown -->
|
|
<div class="dropdown-menu dropdown-menu-end">
|
|
<div class="dropdown-header">
|
|
<div class="user-avatar mx-auto mb-2">
|
|
<?= $_SESSION['userInitials_C'] ?? 'U' ?>
|
|
</div>
|
|
<div class="text-center">
|
|
<div class="fw-bold"><?= $_SESSION['utilisateur_C'] ?? _('Utilisateur') ?></div>
|
|
<small class="text-muted"><?= $_SESSION['nomClient_C'] ?? _('Client') ?></small>
|
|
</div>
|
|
</div>
|
|
<div class="dropdown-divider"></div>
|
|
<a class="dropdown-item" href="javascript:change_password()">
|
|
<i class="fas fa-user-circle me-2"></i> <?= _('Mon compte') ?>
|
|
</a>
|
|
<a class="dropdown-item" href="javascript:appNotifications.showMessagesModal()">
|
|
<i class="fas fa-envelope me-2"></i> <?= _('Messagerie') ?>
|
|
</a>
|
|
<div class="dropdown-divider"></div>
|
|
<a class="dropdown-item text-danger" href="Connexion/deconnecter">
|
|
<i class="fas fa-sign-out-alt me-2"></i> <?= _('Déconnexion') ?>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Sidebar -->
|
|
<aside class="app-sidebar" id="sidebar">
|
|
<nav class="sidebar-nav" aria-label="Navigation principale">
|
|
<div class="nav-section">
|
|
<?php foreach ($menus as $key0 => $menuParent):
|
|
$menuChildrenLevelOne = $gabary->get_menus_by_parent_code($menuParent['vue']);
|
|
$isParentActive = $activeParentId === $key0;
|
|
$hasActiveChild = false;
|
|
|
|
// Vérifier si un enfant est actif
|
|
foreach ($menuChildrenLevelOne as $key1 => $menuChild) {
|
|
if ((explode('/', $menuChild['lienMenu'])[0] ?? '') == $activeLink) {
|
|
$hasActiveChild = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Déterminer si le menu DOIT être ouvert (seulement si actif)
|
|
$shouldBeOpen = ($isParentActive || $hasActiveChild) && $activeParentId !== null;
|
|
?>
|
|
<div class="nav-item">
|
|
<?php if (sizeof($menuChildrenLevelOne) > 0): ?>
|
|
<a href="#submenu<?= $key0 ?>"
|
|
class="nav-link <?= $shouldBeOpen ? 'active' : '' ?>"
|
|
data-bs-toggle="collapse"
|
|
onclick="appNavigation.toggleMenu('submenu<?= $key0 ?>', event)"
|
|
aria-expanded="<?= $shouldBeOpen ? 'true' : 'false' ?>"
|
|
aria-controls="submenu<?= $key0 ?>"
|
|
data-menu-id="submenu<?= $key0 ?>">
|
|
<i class="<?= $menuParent['icone'] ?>"></i>
|
|
<span class="nav-text"><?= $menuParent['libeleMenu'] ?></span>
|
|
<i class="nav-arrow bi bi-chevron-right"></i>
|
|
</a>
|
|
|
|
<div class="nav-submenu collapse <?= $shouldBeOpen ? 'show' : '' ?>"
|
|
id="submenu<?= $key0 ?>"
|
|
data-parent-id="submenu<?= $key0 ?>">
|
|
<?php foreach ($menuChildrenLevelOne as $key1 => $menuChild):
|
|
$childActive = (explode('/', $menuChild['lienMenu'])[0] ?? '') == $activeLink;
|
|
?>
|
|
<a href="<?= $menuChild['lienMenu'] ?>"
|
|
class="nav-link <?= $childActive ? 'active' : '' ?>"
|
|
aria-current="<?= $childActive ? 'page' : 'false' ?>">
|
|
<?= $menuChild['libeleMenu'] ?>
|
|
</a>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php else: ?>
|
|
<a href="<?= $menuParent['lienMenu'] ?>"
|
|
class="nav-link <?= ((explode('/', $menuParent['lienMenu'])[0] ?? '') == $activeLink) ? 'active' : '' ?>"
|
|
aria-current="<?= ((explode('/', $menuParent['lienMenu'])[0] ?? '') == $activeLink) ? 'page' : 'false' ?>">
|
|
<i class="<?= $menuParent['icone'] ?>"></i>
|
|
<span class="nav-text"><?= $menuParent['libeleMenu'] ?></span>
|
|
</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</nav>
|
|
</aside>
|
|
|
|
<!-- Main Content -->
|
|
<main class="app-main" id="mainContent">
|
|
<!-- Navigation Tabs -->
|
|
<div class="content-area">
|
|
<?php if(!empty($menusvue)): ?>
|
|
<div class="nav-bar">
|
|
<div class="nav-tabs" role="tablist" aria-label="Navigation secondaire">
|
|
<?php foreach ($menusvue as $menu):
|
|
$isActive = ($_SESSION['vue'] ?? '') == $menu['libeleMenu'];
|
|
?>
|
|
<a href="<?= $menu['lienMenu'] ?>"
|
|
class="nav-tab <?= $isActive ? 'active' : '' ?>"
|
|
title="<?= $menu['descriptionMenu'] ?? '' ?>"
|
|
role="tab"
|
|
aria-selected="<?= $isActive ? 'true' : 'false' ?>"
|
|
<?= $isActive ? 'aria-current="page"' : '' ?>>
|
|
<i class="bi bi-arrow-right-circle"></i>
|
|
<?= $menu['libeleMenu'] ?>
|
|
</a>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<!-- Hidden Inputs -->
|
|
<input type="hidden" id="racineWeb" value="<?= $racineWeb ?>">
|
|
<input type="hidden" id="dureeSession" value="<?= $_SESSION['dureeSession'] ?>">
|
|
<input type="hidden" id="nomSociete" value="<?= $_SESSION['nomSociete'] ?>">
|
|
<input type="hidden" id="nomClient" value="<?= htmlspecialchars($_SESSION['nomClient_C']) ?>">
|
|
<input type="hidden" id="idBeneficiaire_C" value="<?= $_SESSION['idBeneficiaire_C'] ?>">
|
|
<input type="hidden" id="okId" value="<?= $_SESSION['okId'] ?>">
|
|
|
|
<!-- Content Container -->
|
|
<div class="content-card">
|
|
<div class="card-body">
|
|
<div id="contenu">
|
|
<div id="div_test_gabarit"></div>
|
|
|
|
<?= $contenu ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<!-- Context Panel -->
|
|
<aside class="context-panel" id="contextPanel" aria-label="Panneau de contexte">
|
|
<div class="context-header">
|
|
<div class="context-title">
|
|
<i class="bi bi-info-circle"></i>
|
|
<span><?= _('Contexte de la session') ?></span>
|
|
</div>
|
|
<button class="context-close" onclick="appUX.toggleContextPanel()" aria-label="Fermer le panneau de contexte">
|
|
<i class="bi bi-x-lg"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="context-body">
|
|
<!-- Souscripteur -->
|
|
<div class="context-section">
|
|
<div class="section-title">
|
|
<i class="bi bi-building"></i>
|
|
<span><?= _('Souscripteur') ?></span>
|
|
</div>
|
|
<div class="info-box">
|
|
<div class="info-value">
|
|
<?= $this->nettoyer($_SESSION['nomClient_C']) ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Adhérent principal -->
|
|
<div class="context-section">
|
|
<div class="section-title">
|
|
<i class="bi bi-person-badge"></i>
|
|
<span><?= _('Assuré principal') ?></span>
|
|
</div>
|
|
<div class="info-box">
|
|
<div class="info-value">
|
|
<?= $this->nettoyer($_SESSION['adherent_C']) ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Patient -->
|
|
<div class="context-section">
|
|
<div class="section-title">
|
|
<i class="bi bi-person-heart"></i>
|
|
<span><?= _('Bénéficiaire') ?></span>
|
|
</div>
|
|
|
|
<button class="action-btn" onclick="afficher_beneficiaire_id()" aria-label="Voir les détails du bénéficiaire">
|
|
<i class="bi bi-person"></i>
|
|
<span><?= _('Bénéficiaire').' : '.$this->nettoyer($_SESSION['numeroBeneficiaire_C']) ?></span>
|
|
</button>
|
|
|
|
<div class="info-box">
|
|
<div class="info-value">
|
|
<?= $this->nettoyer($_SESSION['beneficiaire_C']) ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Photo patient -->
|
|
<?php if ($_SESSION['faceRegistered_C'] == "1" && ($_SESSION['idBeneficiaire_C'] ?? 0) > 0): ?>
|
|
<div class="context-section">
|
|
<div class="section-title">
|
|
<i class="bi bi-camera"></i>
|
|
<span><?= _('Photo du bénéficiaire') ?></span>
|
|
</div>
|
|
<div class="photo-container">
|
|
<img src="data:image/jpg;base64,<?= $imgData ?>"
|
|
class="patient-photo"
|
|
onclick="appModals.openPhotoModal()"
|
|
alt="<?= _('Photo du bénéficiaire') ?>"
|
|
loading="lazy">
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<!-- Actions -->
|
|
<div class="context-section">
|
|
<div class="section-title">
|
|
<i class="bi bi-lightning"></i>
|
|
<span><?= _('Actions rapides') ?></span>
|
|
</div>
|
|
|
|
<button class="action-btn" onclick="appNotifications.showMessagesModal()" aria-label="Gérer les notifications">
|
|
<i class="bi bi-chat-dots"></i>
|
|
<span><?= _('Gérer les notifications') ?></span>
|
|
</button>
|
|
|
|
<button class="action-btn" onclick="change_password()" aria-label="Changer le mot de passe">
|
|
<i class="bi bi-key"></i>
|
|
<span><?= _('Changer le mot de passe') ?></span>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Messages -->
|
|
<div id="nbMessagesNonLus" class="d-none">
|
|
<input type="hidden" id="msgNonLus" value="0">
|
|
</div>
|
|
</div>
|
|
</aside>
|
|
|
|
<!-- Zone de détection de proximité -->
|
|
<div class="proximity-hover-area" aria-hidden="true"></div>
|
|
|
|
<!-- Bouton contexte style QuillBot -->
|
|
<button class="context-toggle" onclick="appUX.toggleContextPanel()"
|
|
aria-label="Afficher/Masquer le panneau de contexte"
|
|
aria-expanded="false"
|
|
aria-controls="contextPanel">
|
|
<i class="bi bi-info-circle"></i>
|
|
</button>
|
|
|
|
<!-- Modals -->
|
|
<!-- Photo Modal -->
|
|
<div class="modal fade modal-office" id="photoModal" tabindex="-1"
|
|
aria-labelledby="photoModalLabel" 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="photoModalLabel"><?= _('Photo du bénéficiaire') ?></h5>
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Fermer"></button>
|
|
</div>
|
|
<div class="modal-body text-center">
|
|
<?php if ($_SESSION['faceRegistered_C'] == "1"): ?>
|
|
<img src="data:image/jpg;base64,<?= $imgData ?>"
|
|
class="img-fluid rounded"
|
|
style="max-height: 70vh; max-width: 100%;"
|
|
alt="<?= _('Photo agrandie du bénéficiaire') ?>">
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Messages Modal -->
|
|
<div class="modal fade modal-office" id="messagesModal" tabindex="-1"
|
|
aria-labelledby="messagesModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="messagesModalLabel"><?= _('Notifications non lues') ?></h5>
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Fermer"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div id="div_messagerie"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- JavaScript Libraries -->
|
|
<script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
|
|
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script src="https://cdn.datatables.net/v/bs5/dt-1.13.6/datatables.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
|
|
|
<!-- Application Scripts -->
|
|
<script src="/Js/fonctions.js?ver=2025.12.21.01"></script>
|
|
|
|
<?php if (est_anglophone()): ?>
|
|
<script src="/Js/datepicker-eng.js"></script>
|
|
<?php else: ?>
|
|
<script src="/Js/datepicker-fr.js"></script>
|
|
<?php endif; ?>
|
|
|
|
<!-- UX Enhancement Script -->
|
|
<script src="/Bootstrap_new/js/ux-manager.js?ver=2025.12.21.01"></script>
|
|
|
|
<!-- Service Worker Registration -->
|
|
<script src="/Js/sw-register.js?ver=2025.12.22.00"></script>
|
|
|
|
<!-- AJOUTEZ APRÈS LES INCLUDES DE SCRIPTS -->
|
|
<script>
|
|
// ATTENTION : Ce script doit venir APRÈS l'inclusion de ux-manager.js
|
|
window.appNavigation = null; // Initialisation
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Attendre que UXManager soit initialisé
|
|
setTimeout(function() {
|
|
if (window.appUX && window.appUX.navigation) {
|
|
window.appNavigation = window.appUX.navigation;
|
|
console.log('[App] Navigation disponible via window.appNavigation');
|
|
} else {
|
|
console.error('[App] NavigationManager non disponible');
|
|
}
|
|
}, 500);
|
|
});
|
|
</script>
|
|
|
|
<script>
|
|
// Test du système de menus - VERSION ROBUSTE
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Attendre un peu que tout soit chargé
|
|
setTimeout(function() {
|
|
testMenuSystem();
|
|
}, 300);
|
|
});
|
|
|
|
function testMenuSystem() {
|
|
console.group('=== TEST SYSTÈME DE MENUS ===');
|
|
|
|
// Méthode 1: Via appUX
|
|
if (window.appUX && window.appUX.navigation) {
|
|
console.log('✓ NavigationManager disponible via appUX');
|
|
executeMenuTest(window.appUX.navigation);
|
|
}
|
|
// Méthode 2: Via appNavigation global
|
|
else if (window.appNavigation && typeof window.appNavigation.closeAllExceptActive === 'function') {
|
|
console.log('✓ NavigationManager disponible via appNavigation');
|
|
executeMenuTest(window.appNavigation);
|
|
}
|
|
// Méthode 3: Via uxManager
|
|
else if (window.uxManager) {
|
|
console.log('✓ uxManager disponible');
|
|
executeMenuTest(window.uxManager);
|
|
}
|
|
else {
|
|
console.error('✗ Aucun gestionnaire de navigation disponible');
|
|
manualMenuFix();
|
|
}
|
|
|
|
console.groupEnd();
|
|
}
|
|
|
|
function executeMenuTest(navManager) {
|
|
// Vérifier l'état initial
|
|
const activeParentId = window.appConfig?.activeParentId;
|
|
const activeMenuId = activeParentId !== null && activeParentId !== '' ?
|
|
`submenu${activeParentId}` : null;
|
|
|
|
console.log('Menu actif configuré:', activeMenuId);
|
|
console.log('Page active:', window.appConfig?.activeLink);
|
|
|
|
// Compter les menus ouverts
|
|
const openMenus = document.querySelectorAll('.nav-submenu.show');
|
|
console.log('Menus initialement ouverts:', openMenus.length);
|
|
|
|
openMenus.forEach(menu => {
|
|
console.log(' -', menu.id);
|
|
});
|
|
|
|
// Vérifier que seul le menu actif est ouvert
|
|
if (openMenus.length > 1) {
|
|
console.warn('⚠️ Plusieurs menus sont ouverts!');
|
|
console.warn('Seul le menu', activeMenuId, 'devrait être ouvert.');
|
|
|
|
// Utiliser la méthode disponible
|
|
if (navManager.closeAllExceptActive) {
|
|
console.log('Correction via closeAllExceptActive...');
|
|
navManager.closeAllExceptActive();
|
|
} else if (navManager.closeAllMenus) {
|
|
console.log('Correction via closeAllMenus...');
|
|
navManager.closeAllMenus();
|
|
}
|
|
|
|
// Vérifier le résultat
|
|
setTimeout(() => {
|
|
const openAfter = document.querySelectorAll('.nav-submenu.show').length;
|
|
console.log('Menus ouverts après correction:', openAfter);
|
|
|
|
if (openAfter <= 1) {
|
|
console.log('✅ Correction réussie!');
|
|
} else {
|
|
console.warn('⚠️ Correction incomplète, forcer la fermeture...');
|
|
manualMenuFix();
|
|
}
|
|
}, 200);
|
|
} else {
|
|
console.log('✅ État correct des menus');
|
|
}
|
|
}
|
|
|
|
function manualMenuFix() {
|
|
console.log('🔧 Application du correctif manuel...');
|
|
|
|
const activeParentId = window.appConfig?.activeParentId;
|
|
const activeMenuId = activeParentId !== null && activeParentId !== '' ?
|
|
`submenu${activeParentId}` : null;
|
|
|
|
// 1. Fermer TOUS les menus
|
|
document.querySelectorAll('.nav-submenu').forEach(menu => {
|
|
menu.classList.remove('show');
|
|
menu.style.display = 'none';
|
|
|
|
const link = document.querySelector(`[href="#${menu.id}"]`);
|
|
if (link) {
|
|
link.setAttribute('aria-expanded', 'false');
|
|
link.classList.remove('active');
|
|
const arrow = link.querySelector('.nav-arrow');
|
|
if (arrow) arrow.style.transform = 'rotate(0deg)';
|
|
}
|
|
});
|
|
|
|
// 2. Ouvrir SEULEMENT le menu actif
|
|
if (activeMenuId) {
|
|
setTimeout(() => {
|
|
const menu = document.getElementById(activeMenuId);
|
|
const link = document.querySelector(`[href="#${activeMenuId}"]`);
|
|
|
|
if (menu && link) {
|
|
menu.classList.add('show');
|
|
menu.style.display = 'block';
|
|
link.setAttribute('aria-expanded', 'true');
|
|
link.classList.add('active');
|
|
|
|
const arrow = link.querySelector('.nav-arrow');
|
|
if (arrow) arrow.style.transform = 'rotate(90deg)';
|
|
|
|
console.log('✅ Menu actif ouvert:', activeMenuId);
|
|
}
|
|
}, 100);
|
|
}
|
|
|
|
// 3. Vérification finale
|
|
setTimeout(() => {
|
|
const openCount = document.querySelectorAll('.nav-submenu.show').length;
|
|
console.log('📊 Résultat final:', openCount, 'menu(s) ouvert(s)');
|
|
|
|
if (openCount === 1 || (openCount === 0 && !activeMenuId)) {
|
|
console.log('✅ Système de menus corrigé avec succès!');
|
|
} else {
|
|
console.error('❌ Échec de la correction manuelle');
|
|
}
|
|
}, 300);
|
|
}
|
|
|
|
// Exposer la fonction de test globalement
|
|
window.testMenuSystem = testMenuSystem;
|
|
window.manualMenuFix = manualMenuFix;
|
|
</script>
|
|
</body>
|
|
</html>
|
|
|