Rehabilitation en UX/UI.

This commit is contained in:
KONE SOREL 2025-12-20 17:31:00 +00:00
parent d28c3d4695
commit eef4f490ce
4 changed files with 3310 additions and 1124 deletions

View File

@ -1,4 +1,7 @@
/* Style Office pour le Portail RH*/ /* ============================================
STYLE OFFICE POUR LE PORTAIL RH - VERSION STRUCTURE
============================================ */
:root { :root {
/* PowerPoint/Office 2019 Color Palette */ /* PowerPoint/Office 2019 Color Palette */
--office-primary: #b7472a; /* Sidebar color - PowerPoint accent */ --office-primary: #b7472a; /* Sidebar color - PowerPoint accent */
@ -11,22 +14,39 @@
--office-hover: #f0f0f0; /* Hover states */ --office-hover: #f0f0f0; /* Hover states */
--office-card: #ffffff; /* Card backgrounds */ --office-card: #ffffff; /* Card backgrounds */
/* Dimensions */
--sidebar-width: 260px; --sidebar-width: 260px;
--sidebar-collapsed: 70px; --sidebar-collapsed: 70px;
--header-height: 64px; --header-height: 64px;
--transition-speed: 0.3s; --transition-speed: 0.3s;
/* Responsive breakpoints */
--breakpoint-tablet: 1200px;
--breakpoint-mobile: 768px;
}
/* ============================================
BASE STYLES & RESET
============================================ */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
} }
/* Base Styles */
body { body {
font-family: 'Segoe UI', 'Segoe UI Web (West European)', -apple-system, BlinkMacSystemFont, Roboto, 'Helvetica Neue', sans-serif; font-family: 'Segoe UI', 'Segoe UI Web (West European)', -apple-system, BlinkMacSystemFont, Roboto, 'Helvetica Neue', sans-serif;
background-color: var(--office-common); background-color: var(--office-common);
color: var(--office-dark); color: var(--office-dark);
line-height: 1.5; line-height: 1.5;
overflow-x: hidden; overflow-x: hidden;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
} }
/* Header - PowerPoint/Office Style */ /* ============================================
HEADER STYLES
============================================ */
.app-header { .app-header {
background-color: var(--office-light); background-color: var(--office-light);
height: var(--header-height); height: var(--header-height);
@ -64,10 +84,11 @@
.app-logo img { .app-logo img {
height: 36px; height: 36px;
/*filter: brightness(0) invert(1);*/
} }
/* Sidebar - PowerPoint Orange (#b7472a) */ /* ============================================
SIDEBAR STYLES
============================================ */
.app-sidebar { .app-sidebar {
width: var(--sidebar-width); width: var(--sidebar-width);
background: linear-gradient(180deg, var(--office-primary) 0%, #a53e24 100%); background: linear-gradient(180deg, var(--office-primary) 0%, #a53e24 100%);
@ -82,7 +103,7 @@
overflow-x: hidden; overflow-x: hidden;
} }
/* Subtle pattern overlay for modern look */ /* Pattern overlay */
.app-sidebar::before { .app-sidebar::before {
content: ''; content: '';
position: absolute; position: absolute;
@ -134,14 +155,12 @@
.nav-link:hover { .nav-link:hover {
background-color: rgba(255, 255, 255, 0.1); background-color: rgba(255, 255, 255, 0.1);
color: white; color: white;
transform: translateX(4px);
} }
.nav-link.active { .nav-link.active {
background-color: rgba(255, 255, 255, 0.15); background-color: rgba(255, 255, 255, 0.15);
color: white; color: white;
font-weight: 500; font-weight: 500;
box-shadow: inset 3px 0 0 white;
} }
.nav-link i { .nav-link i {
@ -194,7 +213,9 @@
opacity: 0.6; opacity: 0.6;
} }
/* Main Content Area */ /* ============================================
MAIN CONTENT AREA
============================================ */
.app-main { .app-main {
margin-left: var(--sidebar-width); margin-left: var(--sidebar-width);
padding-top: var(--header-height); padding-top: var(--header-height);
@ -209,7 +230,9 @@
margin: 0 auto; margin: 0 auto;
} }
/* Breadcrumb/Navigation Bar */ /* ============================================
NAVIGATION TABS
============================================ */
.nav-bar { .nav-bar {
background-color: white; background-color: white;
border-radius: 8px; border-radius: 8px;
@ -257,7 +280,9 @@
font-size: 16px; font-size: 16px;
} }
/* Content Cards */ /* ============================================
CONTENT CARDS
============================================ */
.content-card { .content-card {
background-color: white; background-color: white;
border-radius: 8px; border-radius: 8px;
@ -283,7 +308,9 @@
padding: 24px; padding: 24px;
} }
/* Header Controls */ /* ============================================
HEADER CONTROLS
============================================ */
.header-controls { .header-controls {
display: flex; display: flex;
align-items: center; align-items: center;
@ -364,7 +391,9 @@
font-size: 12px; font-size: 12px;
} }
/* Context Panel */ /* ============================================
CONTEXT PANEL
============================================ */
.context-panel { .context-panel {
position: fixed; position: fixed;
right: -380px; right: -380px;
@ -484,7 +513,6 @@
background-color: var(--office-hover); background-color: var(--office-hover);
border-color: var(--office-secondary); border-color: var(--office-secondary);
color: var(--office-secondary); color: var(--office-secondary);
transform: translateX(4px);
} }
.action-btn i { .action-btn i {
@ -516,7 +544,9 @@
transform: scale(1.05); transform: scale(1.05);
} }
/* Toggle Button */ /* ============================================
CONTEXT TOGGLE BUTTON
============================================ */
.context-toggle { .context-toggle {
position: fixed; position: fixed;
right: 24px; right: 24px;
@ -542,7 +572,9 @@
box-shadow: 0 6px 16px rgba(183, 71, 42, 0.4); box-shadow: 0 6px 16px rgba(183, 71, 42, 0.4);
} }
/* Test Mode Indicator */ /* ============================================
TEST MODE INDICATOR
============================================ */
.test-indicator { .test-indicator {
background: linear-gradient(45deg, #ffd700, #ffed4e); background: linear-gradient(45deg, #ffd700, #ffed4e);
color: #8a6d3b; color: #8a6d3b;
@ -563,7 +595,9 @@
100% { opacity: 1; } 100% { opacity: 1; }
} }
/* Language Selector */ /* ============================================
LANGUAGE SELECTOR
============================================ */
.language-selector { .language-selector {
display: flex; display: flex;
align-items: center; align-items: center;
@ -587,7 +621,9 @@
border-radius: 2px; border-radius: 2px;
} }
/* Modal Customization */ /* ============================================
MODAL CUSTOMIZATION
============================================ */
.modal-office .modal-header { .modal-office .modal-header {
background: linear-gradient(135deg, var(--office-secondary), #1e4a8b); background: linear-gradient(135deg, var(--office-secondary), #1e4a8b);
color: white; color: white;
@ -598,7 +634,9 @@
font-weight: 600; font-weight: 600;
} }
/* Responsive Design */ /* ============================================
RESPONSIVE DESIGN
============================================ */
@media (max-width: 1200px) { @media (max-width: 1200px) {
.app-sidebar { .app-sidebar {
width: var(--sidebar-collapsed); width: var(--sidebar-collapsed);
@ -674,7 +712,9 @@
} }
} }
/* Scrollbar Styling */ /* ============================================
SCROLLBAR STYLING
============================================ */
.app-sidebar::-webkit-scrollbar, .app-sidebar::-webkit-scrollbar,
.context-body::-webkit-scrollbar { .context-body::-webkit-scrollbar {
width: 6px; width: 6px;

View File

@ -0,0 +1,833 @@
/* ============================================
ENHANCEMENTS UX POUR PORTAIL INTER SANTÉ
============================================ */
:root {
/* Variables UX avancées */
--ux-transition-smooth: cubic-bezier(0.4, 0, 0.2, 1);
--ux-shadow-soft: 0 2px 15px rgba(0, 0, 0, 0.08);
--ux-shadow-medium: 0 5px 20px rgba(0, 0, 0, 0.12);
--ux-shadow-hard: 0 10px 30px rgba(0, 0, 0, 0.15);
--ux-border-radius-sm: 8px;
--ux-border-radius-md: 12px;
--ux-border-radius-lg: 20px;
/* Variables d'animation */
--animation-duration-fast: 150ms;
--animation-duration-normal: 300ms;
--animation-duration-slow: 500ms;
}
/* ============================================
ENHANCED SIDEBAR UX
============================================ */
.app-sidebar {
--sidebar-hover-glow: 0 0 20px rgba(255, 255, 255, 0.1);
}
.nav-item {
position: relative;
}
.nav-link {
position: relative;
overflow: visible;
transition: all var(--animation-duration-normal) var(--ux-transition-smooth);
border-left: 3px solid transparent;
will-change: transform, background-color, border-color;
}
.nav-link:hover {
background: linear-gradient(90deg,
rgba(255, 255, 255, 0.1) 0%,
rgba(255, 255, 255, 0.05) 100%);
transform: translateX(8px);
border-left-color: rgba(255, 255, 255, 0.5);
box-shadow: var(--sidebar-hover-glow);
}
.nav-link.active {
background: linear-gradient(90deg,
rgba(255, 255, 255, 0.2) 0%,
rgba(255, 255, 255, 0.1) 100%);
border-left-color: #ffffff;
box-shadow: inset 0 0 30px rgba(255, 255, 255, 0.1),
0 0 20px rgba(255, 255, 255, 0.15);
font-weight: 600;
letter-spacing: 0.3px;
}
/* Indicateur visuel pour lien actif */
.nav-link.active::before {
content: '';
position: absolute;
left: -3px;
top: 50%;
transform: translateY(-50%);
width: 6px;
height: 6px;
background-color: white;
border-radius: 50%;
box-shadow: 0 0 10px white;
animation: pulse-active 2s infinite;
}
@keyframes pulse-active {
0%, 100% {
opacity: 1;
transform: translateY(-50%) scale(1);
}
50% {
opacity: 0.7;
transform: translateY(-50%) scale(1.2);
}
}
/* Sous-menus améliorés */
.nav-submenu {
background: linear-gradient(180deg,
rgba(0, 0, 0, 0.15) 0%,
rgba(0, 0, 0, 0.1) 100%);
border-radius: var(--ux-border-radius-sm);
margin: 6px 12px;
border-left: 2px solid rgba(255, 255, 255, 0.2);
transition: all 0.4s var(--ux-transition-smooth);
max-height: 0;
overflow: hidden;
}
.nav-submenu.show {
max-height: 500px;
padding: 8px 0;
margin-top: 8px;
margin-bottom: 12px;
animation: slideDown 0.4s var(--ux-transition-smooth);
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-10px);
max-height: 0;
}
to {
opacity: 1;
transform: translateY(0);
max-height: 500px;
}
}
/* ============================================
CONTEXT BUTTON - QUILLBOT STYLE
============================================ */
.context-toggle {
position: fixed;
right: 30px;
bottom: 30px;
width: 60px;
height: 60px;
border-radius: 50%;
background: linear-gradient(135deg, #b7472a 0%, #ff6b35 100%);
color: white;
border: 3px solid white;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
z-index: 1050;
transition: all 0.5s var(--ux-transition-smooth);
opacity: 0.2;
transform: scale(0.8);
box-shadow:
0 4px 25px rgba(183, 71, 42, 0.15),
inset 0 0 20px rgba(255, 255, 255, 0.2);
backdrop-filter: blur(10px);
will-change: transform, opacity, box-shadow;
}
/* Animation d'attente */
.context-toggle::after {
content: '';
position: absolute;
width: 72px;
height: 72px;
border: 2px solid rgba(183, 71, 42, 0.3);
border-radius: 50%;
animation: ripple 3s infinite;
}
@keyframes ripple {
0% {
transform: scale(0.8);
opacity: 1;
}
100% {
transform: scale(1.2);
opacity: 0;
}
}
/* État au survol et activation */
.context-toggle:hover,
.context-toggle.active,
body:has(.proximity-hover-area:hover) .context-toggle {
opacity: 1 !important;
transform: scale(1.1) !important;
box-shadow:
0 8px 35px rgba(183, 71, 42, 0.4),
0 0 30px rgba(255, 107, 53, 0.3),
inset 0 0 25px rgba(255, 255, 255, 0.3);
animation: bounce 0.5s var(--ux-transition-smooth);
}
@keyframes bounce {
0%, 100% { transform: scale(1.1); }
50% { transform: scale(1.15); }
}
/* Rotation quand le panel est ouvert */
.context-panel.open ~ .context-toggle {
transform: rotate(180deg) scale(1.1);
background: linear-gradient(135deg, #2b579a 0%, #1e4a8b 100%);
right: 410px;
}
/* Zone de détection de proximité invisible */
.proximity-hover-area {
position: fixed;
right: 0;
bottom: 0;
width: 200px;
height: 200px;
z-index: 1049;
pointer-events: none;
}
/* Feedback visuel pour la zone */
.proximity-hover-area::before {
content: '';
position: absolute;
right: 30px;
bottom: 30px;
width: 100px;
height: 100px;
background: radial-gradient(circle, rgba(183, 71, 42, 0.1) 0%, transparent 70%);
border-radius: 50%;
opacity: 0;
transition: opacity var(--animation-duration-normal);
}
.proximity-hover-area:hover::before {
opacity: 1;
}
/* ============================================
ENHANCED CONTEXT PANEL
============================================ */
.context-panel {
transition: right var(--animation-duration-slow) var(--ux-transition-smooth);
box-shadow:
-5px 0 30px rgba(0, 0, 0, 0.15),
0 0 0 1px rgba(255, 255, 255, 0.1) inset;
border-left: 3px solid var(--office-primary);
will-change: right;
}
.context-panel.open {
animation: slideInRight 0.5s var(--ux-transition-smooth);
}
@keyframes slideInRight {
from {
transform: translateX(100px);
opacity: 0.8;
}
to {
transform: translateX(0);
opacity: 1;
}
}
.context-header {
background: linear-gradient(135deg, var(--office-primary) 0%, #d9534f 100%);
padding: 25px 30px;
border-bottom: 3px solid rgba(255, 255, 255, 0.2);
}
.context-title {
font-size: 20px;
font-weight: 700;
}
.context-close {
transition: all var(--animation-duration-normal);
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
}
.context-close:hover {
background: rgba(255, 255, 255, 0.2);
transform: rotate(90deg);
}
/* Sections avec effet de profondeur */
.context-section {
background: white;
border-radius: var(--ux-border-radius-md);
padding: 20px;
margin-bottom: 25px;
box-shadow: var(--ux-shadow-soft);
border: 1px solid var(--office-border);
transition: all var(--animation-duration-normal);
position: relative;
overflow: hidden;
}
.context-section:hover {
transform: translateY(-3px);
box-shadow: var(--ux-shadow-medium);
border-color: var(--office-secondary);
}
.context-section::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 4px;
height: 100%;
background: linear-gradient(to bottom, var(--office-primary), var(--office-secondary));
opacity: 0.7;
}
.section-title {
color: var(--office-secondary);
font-size: 15px;
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 2px solid rgba(43, 87, 154, 0.1);
position: relative;
}
.section-title::after {
content: '';
position: absolute;
bottom: -2px;
left: 0;
width: 50px;
height: 2px;
background: linear-gradient(90deg, var(--office-primary), var(--office-secondary));
}
/* Cards améliorées */
.info-box {
background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
border-radius: var(--ux-border-radius-sm);
padding: 18px;
border: 1px solid rgba(0, 0, 0, 0.08);
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.03);
transition: all var(--animation-duration-normal);
}
.info-box:hover {
border-color: var(--office-secondary);
box-shadow:
inset 0 2px 8px rgba(43, 87, 154, 0.05),
0 3px 10px rgba(0, 0, 0, 0.05);
}
.info-value {
font-size: 16px;
font-weight: 600;
color: var(--office-dark);
line-height: 1.5;
}
/* Boutons d'action améliorés */
.action-btn {
background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
border: 2px solid var(--office-border);
border-radius: var(--ux-border-radius-sm);
padding: 15px 20px;
margin-bottom: 12px;
transition: all var(--animation-duration-normal) var(--ux-transition-smooth);
position: relative;
overflow: hidden;
will-change: transform, border-color, background;
}
.action-btn:hover {
transform: translateX(8px);
border-color: var(--office-secondary);
background: linear-gradient(135deg, #f0f7ff 0%, #e3eeff 100%);
box-shadow:
5px 5px 15px rgba(43, 87, 154, 0.1),
inset 0 0 20px rgba(255, 255, 255, 0.5);
}
.action-btn::before {
content: '';
position: absolute;
left: -100%;
top: 0;
width: 100%;
height: 100%;
background: linear-gradient(90deg,
transparent,
rgba(255, 255, 255, 0.4),
transparent);
transition: left 0.6s;
}
.action-btn:hover::before {
left: 100%;
}
/* Photo patient améliorée */
.photo-container {
background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
border-radius: var(--ux-border-radius-md);
padding: 25px;
border: 2px dashed var(--office-border);
transition: all var(--animation-duration-normal);
}
.photo-container:hover {
border-color: var(--office-primary);
background: linear-gradient(135deg, #fff5f2 0%, #ffffff 100%);
transform: scale(1.02);
}
.patient-photo {
width: 180px;
height: 180px;
border-radius: var(--ux-border-radius-md);
object-fit: cover;
border: 5px solid white;
box-shadow:
0 10px 30px rgba(0, 0, 0, 0.15),
0 0 0 1px rgba(0, 0, 0, 0.05);
transition: all 0.4s var(--ux-transition-smooth);
cursor: pointer;
will-change: transform, box-shadow;
}
.patient-photo:hover {
transform: scale(1.08) rotate(2deg);
box-shadow:
0 20px 40px rgba(0, 0, 0, 0.2),
0 0 0 3px rgba(183, 71, 42, 0.3);
}
/* ============================================
HEADER ENHANCEMENTS
============================================ */
.app-header {
backdrop-filter: blur(10px);
background: linear-gradient(135deg,
rgba(243, 242, 241, 0.95) 0%,
rgba(255, 255, 255, 0.98) 100%);
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
box-shadow:
0 4px 20px rgba(0, 0, 0, 0.05),
inset 0 1px 0 rgba(255, 255, 255, 0.8);
}
.user-avatar {
background: linear-gradient(135deg, var(--office-primary) 0%, #ff8c69 100%);
box-shadow:
0 4px 15px rgba(183, 71, 42, 0.3),
inset 0 0 20px rgba(255, 255, 255, 0.3);
transition: all var(--animation-duration-normal);
will-change: transform, box-shadow;
}
.user-avatar:hover {
transform: scale(1.1) rotate(5deg);
box-shadow:
0 6px 25px rgba(183, 71, 42, 0.4),
inset 0 0 25px rgba(255, 255, 255, 0.4);
}
.notification-badge {
background: linear-gradient(135deg, #107c10 0%, #20a020 100%);
box-shadow: 0 3px 10px rgba(16, 124, 16, 0.4);
animation: pulse-notification 2s infinite;
}
@keyframes pulse-notification {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.1); }
}
/* ============================================
MAIN CONTENT ENHANCEMENTS
============================================ */
.app-main {
background: linear-gradient(135deg,
#f3f2f1 0%,
#f8f7f6 30%,
#fefefe 100%);
}
.content-area {
animation: fadeIn 0.6s var(--ux-transition-smooth);
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.nav-bar {
background: linear-gradient(135deg, #ffffff 0%, #fafafa 100%);
border-radius: var(--ux-border-radius-md);
box-shadow: var(--ux-shadow-soft);
border: 1px solid rgba(0, 0, 0, 0.06);
backdrop-filter: blur(10px);
}
.nav-tab {
transition: all var(--animation-duration-normal);
position: relative;
overflow: hidden;
will-change: transform, box-shadow;
}
.nav-tab:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(43, 87, 154, 0.1);
}
.nav-tab.active {
background: linear-gradient(135deg, var(--office-secondary) 0%, #3a6bc0 100%);
box-shadow:
0 5px 20px rgba(43, 87, 154, 0.3),
inset 0 0 20px rgba(255, 255, 255, 0.2);
transform: translateY(-2px);
animation: tab-active-pulse 3s infinite;
}
@keyframes tab-active-pulse {
0%, 100% {
box-shadow: 0 5px 20px rgba(43, 87, 154, 0.3);
}
50% {
box-shadow: 0 5px 25px rgba(43, 87, 154, 0.5);
}
}
.content-card {
background: linear-gradient(135deg, #ffffff 0%, #fcfcfc 100%);
border-radius: var(--ux-border-radius-md);
box-shadow: var(--ux-shadow-soft);
border: 1px solid rgba(0, 0, 0, 0.05);
transition: all 0.4s;
will-change: transform, box-shadow;
}
.content-card:hover {
transform: translateY(-3px);
box-shadow: var(--ux-shadow-medium);
border-color: rgba(43, 87, 154, 0.1);
}
/* ============================================
LOADING STATES
============================================ */
.loading-placeholder {
background: linear-gradient(90deg,
#f0f0f0 25%,
#e0e0e0 50%,
#f0f0f0 75%);
background-size: 200% 100%;
animation: loading 1.5s infinite;
border-radius: var(--ux-border-radius-sm);
}
@keyframes loading {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
/* ============================================
ACCESSIBILITY ENHANCEMENTS
============================================ */
/* Navigation au clavier */
body.keyboard-navigation .nav-link:focus,
body.keyboard-navigation .action-btn:focus,
body.keyboard-navigation .context-toggle:focus {
outline: 3px solid rgba(43, 87, 154, 0.5);
outline-offset: 3px;
box-shadow: 0 0 0 6px rgba(43, 87, 154, 0.1);
}
/* Lien skip pour accessibilité */
.skip-link {
position: absolute;
top: -40px;
left: 0;
background: var(--office-primary);
color: white;
padding: 8px 16px;
border-radius: 0 0 4px 0;
text-decoration: none;
font-weight: 600;
z-index: 9999;
transition: top 0.3s;
}
.skip-link:focus {
top: 0;
outline: 3px solid white;
outline-offset: -3px;
}
/* High contrast mode */
@media (prefers-contrast: high) {
.nav-link.active {
border-left: 4px solid white;
background-color: rgba(255, 255, 255, 0.3);
}
.context-section {
border: 2px solid var(--office-dark);
}
.action-btn {
border: 2px solid currentColor;
}
}
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
.context-toggle::after {
animation: none;
}
}
/* Dark mode support */
@media (prefers-color-scheme: dark) {
.app-header {
background: rgba(30, 30, 30, 0.95);
border-bottom-color: rgba(255, 255, 255, 0.1);
}
.content-card {
background: #2a2a2a;
border-color: #404040;
color: #e0e0e0;
}
.nav-bar {
background: #2a2a2a;
border-color: #404040;
}
.info-box {
background: #333;
border-color: #444;
}
.action-btn {
background: #333;
border-color: #444;
color: #e0e0e0;
}
}
/* ============================================
RESPONSIVE ENHANCEMENTS
============================================ */
@media (max-width: 1200px) {
.app-sidebar:hover {
width: var(--sidebar-width);
}
.app-sidebar:hover .nav-text,
.app-sidebar:hover .nav-arrow {
display: block;
animation: fadeIn 0.3s;
}
.context-panel {
width: 90%;
}
.context-panel.open ~ .context-toggle {
right: calc(90% + 20px);
}
}
@media (max-width: 768px) {
.context-toggle {
width: 50px;
height: 50px;
font-size: 20px;
right: 20px;
bottom: 20px;
}
.context-toggle::after {
width: 60px;
height: 60px;
}
.context-panel {
width: 100%;
}
.context-panel.open ~ .context-toggle {
right: calc(100% - 70px);
}
.nav-bar {
padding: 12px 15px;
margin: 10px;
}
.nav-tabs {
padding: 5px 0;
}
.nav-tab {
padding: 8px 12px;
font-size: 13px;
}
/* Masquer certains éléments sur mobile */
.user-info .user-role {
display: none;
}
.test-indicator span {
display: none;
}
.test-indicator {
padding: 4px 8px;
}
}
@media (max-width: 480px) {
.header-content {
padding: 0 12px;
}
.app-logo span {
font-size: 16px;
}
.user-name {
display: none;
}
.context-body {
padding: 16px;
}
.context-section {
padding: 15px;
}
.patient-photo {
width: 140px;
height: 140px;
}
}
/* ============================================
UTILITY CLASSES
============================================ */
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.text-balance {
text-wrap: balance;
}
.text-pretty {
text-wrap: pretty;
}
/* Connection warning */
.connection-warning {
position: fixed;
top: 70px;
left: 50%;
transform: translateX(-50%);
z-index: 9999;
max-width: 90%;
animation: slideDown 0.3s ease-out;
}
/* Animation for loaded images */
img.loaded {
animation: fadeInUp 0.5s ease-out;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Print styles */
@media print {
.app-sidebar,
.app-header,
.context-panel,
.context-toggle,
.nav-bar {
display: none !important;
}
.app-main {
margin-left: 0;
padding-top: 0;
}
.content-card {
box-shadow: none;
border: 1px solid #ddd;
}
body {
background: white;
color: black;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,22 @@ $_SESSION['firstLevelMenu'] = $activeLink;
$companyDisplayName = htmlspecialchars($_SESSION['nomSociete'], ENT_QUOTES); $companyDisplayName = htmlspecialchars($_SESSION['nomSociete'], ENT_QUOTES);
$imgData = $_SESSION['photoAssureCrypte'] ?? ''; $imgData = $_SESSION['photoAssureCrypte'] ?? '';
// Détection automatique des menus actifs
$activeParentId = null;
$activeChildId = null;
foreach ($menus as $key0 => $menuParent) {
$menuChildrenLevelOne = $gabary->get_menus_by_parent_code($menuParent['vue']);
foreach ($menuChildrenLevelOne as $key1 => $menuChild) {
if ((explode('/', $menuChild['lienMenu'])[0] ?? '') == $activeLink) {
$activeParentId = $key0;
$activeChildId = $key1;
break 2;
}
}
}
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
@ -19,7 +35,15 @@ $imgData = $_SESSION['photoAssureCrypte'] ?? '';
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<base href="<?= $racineWeb ?>"> <base href="<?= $racineWeb ?>">
<title><?= htmlspecialchars($_SESSION['vue'] ?? 'INTER SANTE') ?></title> <title><?= htmlspecialchars($_SESSION['vue'] ?? 'INTER SANTÉ') ?> | Portail Santé</title>
<!-- Meta pour UX améliorée -->
<meta name="description" content="Portail professionnel de gestion santé Inter Santé">
<meta name="theme-color" content="#b7472a">
<!-- Progressive Web App -->
<link rel="manifest" href="manifest.json">
<link rel="apple-touch-icon" href="Bootstrap_new/images/new/favicon.png">
<!-- Bootstrap 5 --> <!-- Bootstrap 5 -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
@ -40,34 +64,51 @@ $imgData = $_SESSION['photoAssureCrypte'] ?? '';
<!-- SweetAlert2 --> <!-- SweetAlert2 -->
<link href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css" rel="stylesheet">
<!-- Animate.css pour animations douces -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">
<!-- Office/PowerPoint Inspired Styles --> <!-- Office/PowerPoint Inspired Styles -->
<link href="Bootstrap_new/css/style_office.css?ver=2025.12.20.00" rel="stylesheet"> <link href="Bootstrap_new/css/style_office.css?ver=2025.12.20.00" rel="stylesheet">
<!-- UX Improvements CSS -->
<link href="Bootstrap_new/css/ux_enhancements.css?ver=2025.12.20.01" rel="stylesheet">
<script> <script>
// Mode développeur
const modeDev = <?= $_SESSION['modeDev_C'] ?? 0 ?>; const modeDev = <?= $_SESSION['modeDev_C'] ?? 0 ?>;
if (modeDev != "1") { if (modeDev != "1") {
document.addEventListener('contextmenu', function(e) { document.addEventListener('contextmenu', function(e) {
e.preventDefault(); e.preventDefault();
}); });
} }
// Variables globales accessibles par tous les scripts
window.appConfig = {
activeParentId: '<?= $activeParentId ?>',
activeLink: '<?= $activeLink ?>',
racineWeb: '<?= $racineWeb ?>',
isAnglophone: <?= est_anglophone() ? 'true' : 'false' ?>,
modeTest: <?= $_SESSION['bdTests_C'] == "1" ? 'true' : 'false' ?>
};
</script> </script>
</head> </head>
<body> <body>
<!-- Header --> <!-- Header -->
<header class="app-header"> <header class="app-header">
<div class="header-content"> <div class="header-content">
<div class="logo-container"> <div class="logo-container">
<button class="header-btn sidebar-toggle d-lg-none"> <button class="header-btn sidebar-toggle d-lg-none" aria-label="Menu navigation">
<i class="bi bi-list"></i> <i class="bi bi-list"></i>
</button> </button>
<a href="#" class="app-logo"> <a href="#" class="app-logo">
<img src="Bootstrap_new/images/new/favicon.png" alt="INTER-SANTE"> <img src="Bootstrap_new/images/new/favicon.png" alt="INTER-SANTÉ" width="36" height="36">
<span class="ms-2">INTER-SANTE</span> <span class="ms-2">INTER-SANTÉ</span>
</a> </a>
<?php if($_SESSION['bdTests_C'] == "1"): ?> <?php if($_SESSION['bdTests_C'] == "1"): ?>
<div class="test-indicator"> <div class="test-indicator" role="status" aria-label="Mode test activé">
<i class="fas fa-flask"></i> <i class="fas fa-flask"></i>
<span>MODE TEST</span> <span>MODE TEST</span>
</div> </div>
@ -76,24 +117,28 @@ $imgData = $_SESSION['photoAssureCrypte'] ?? '';
<div class="header-controls"> <div class="header-controls">
<!-- Notifications --> <!-- Notifications -->
<button class="header-btn notification-btn" onclick="pop_messagerie()"> <button class="header-btn notification-btn" onclick="appNotifications.showMessagesModal()"
aria-label="Notifications" title="<?= _('Voir les notifications') ?>">
<i class="bi bi-bell"></i> <i class="bi bi-bell"></i>
<span class="notification-badge" id="notificationCount">0</span> <span class="notification-badge" id="notificationCount" aria-live="polite">0</span>
</button> </button>
<!-- Company Info --> <!-- Language Selector -->
<div class="language-selector" onclick="changer_langue()"> <div class="language-selector" onclick="appLanguage.changeLanguage()"
role="button" tabindex="0"
aria-label="<?= _('Changer de langue') ?>">
<?php <?php
$flag = est_anglophone() ? 'england.png' : 'france.png'; $flag = est_anglophone() ? 'england.png' : 'france.png';
$lib = est_anglophone() ? 'EN' : 'FR'; $lib = est_anglophone() ? 'EN' : 'FR';
?> ?>
<img src="Bootstrap_new/images/<?= $flag ?>" alt="Language" class="language-flag"> <img src="Bootstrap_new/images/<?= $flag ?>" alt="<?= $lib ?>" class="language-flag" width="24" height="16">
<span><?= $lib ?></span> <span><?= $lib ?></span>
</div> </div>
<!-- User Menu --> <!-- User Menu -->
<div class="user-menu dropdown-toggle" data-bs-toggle="dropdown"> <div class="user-menu dropdown-toggle" data-bs-toggle="dropdown"
<div class="user-avatar"> aria-expanded="false" aria-label="Menu utilisateur">
<div class="user-avatar" role="img" aria-label="Avatar utilisateur">
<?= $_SESSION['userInitials_C'] ?? 'U' ?> <?= $_SESSION['userInitials_C'] ?? 'U' ?>
</div> </div>
<div class="user-info"> <div class="user-info">
@ -117,7 +162,7 @@ $imgData = $_SESSION['photoAssureCrypte'] ?? '';
<a class="dropdown-item" href="javascript:change_password()"> <a class="dropdown-item" href="javascript:change_password()">
<i class="fas fa-user-circle me-2"></i> <?= _('Mon compte') ?> <i class="fas fa-user-circle me-2"></i> <?= _('Mon compte') ?>
</a> </a>
<a class="dropdown-item" href="javascript:gerer_messagerie()"> <a class="dropdown-item" href="javascript:appNotifications.showMessagesModal()">
<i class="fas fa-envelope me-2"></i> <?= _('Messagerie') ?> <i class="fas fa-envelope me-2"></i> <?= _('Messagerie') ?>
</a> </a>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
@ -131,17 +176,17 @@ $imgData = $_SESSION['photoAssureCrypte'] ?? '';
<!-- Sidebar --> <!-- Sidebar -->
<aside class="app-sidebar" id="sidebar"> <aside class="app-sidebar" id="sidebar">
<nav class="sidebar-nav"> <nav class="sidebar-nav" aria-label="Navigation principale">
<div class="nav-section"> <div class="nav-section">
<div class="nav-title"> <?= _('Navigation principale') ?></div>
<?php foreach ($menus as $key0 => $menuParent): <?php foreach ($menus as $key0 => $menuParent):
$menuChildrenLevelOne = $gabary->get_menus_by_parent_code($menuParent['vue']); $menuChildrenLevelOne = $gabary->get_menus_by_parent_code($menuParent['vue']);
$isActive = false; $isParentActive = $activeParentId === $key0;
$hasActiveChild = false;
// Check if any child is active // Vérifier si un enfant est actif
foreach ($menuChildrenLevelOne as $menuChild) { foreach ($menuChildrenLevelOne as $key1 => $menuChild) {
if ((explode('/', $menuChild['lienMenu'])[0] ?? '') == $activeLink) { if ((explode('/', $menuChild['lienMenu'])[0] ?? '') == $activeLink) {
$isActive = true; $hasActiveChild = true;
break; break;
} }
} }
@ -149,26 +194,31 @@ $imgData = $_SESSION['photoAssureCrypte'] ?? '';
<div class="nav-item"> <div class="nav-item">
<?php if (sizeof($menuChildrenLevelOne) > 0): ?> <?php if (sizeof($menuChildrenLevelOne) > 0): ?>
<a href="#submenu<?= $key0 ?>" <a href="#submenu<?= $key0 ?>"
class="nav-link <?= $isActive ? 'active' : '' ?>" class="nav-link <?= $isParentActive || $hasActiveChild ? 'active' : '' ?>"
data-bs-toggle="collapse" data-bs-toggle="collapse"
aria-expanded="<?= $isActive ? 'true' : 'false' ?>"> aria-expanded="<?= $isParentActive || $hasActiveChild ? 'true' : 'false' ?>"
aria-controls="submenu<?= $key0 ?>">
<i class="<?= $menuParent['icone'] ?>"></i> <i class="<?= $menuParent['icone'] ?>"></i>
<span class="nav-text"><?= $menuParent['libeleMenu'] ?></span> <span class="nav-text"><?= $menuParent['libeleMenu'] ?></span>
<i class="nav-arrow bi bi-chevron-right"></i> <i class="nav-arrow bi bi-chevron-right"></i>
</a> </a>
<div class="nav-submenu collapse <?= $isActive ? 'show' : '' ?>" id="submenu<?= $key0 ?>"> <div class="nav-submenu collapse <?= $isParentActive || $hasActiveChild ? 'show' : '' ?>"
id="submenu<?= $key0 ?>">
<?php foreach ($menuChildrenLevelOne as $key1 => $menuChild): <?php foreach ($menuChildrenLevelOne as $key1 => $menuChild):
$childActive = (explode('/', $menuChild['lienMenu'])[0] ?? '') == $activeLink; $childActive = (explode('/', $menuChild['lienMenu'])[0] ?? '') == $activeLink;
?> ?>
<a href="<?= $menuChild['lienMenu'] ?>" <a href="<?= $menuChild['lienMenu'] ?>"
class="nav-link <?= $childActive ? 'active' : '' ?>"> class="nav-link <?= $childActive ? 'active' : '' ?>"
aria-current="<?= $childActive ? 'page' : 'false' ?>">
<?= $menuChild['libeleMenu'] ?> <?= $menuChild['libeleMenu'] ?>
</a> </a>
<?php endforeach; ?> <?php endforeach; ?>
</div> </div>
<?php else: ?> <?php else: ?>
<a href="<?= $menuParent['lienMenu'] ?>" class="nav-link"> <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> <i class="<?= $menuParent['icone'] ?>"></i>
<span class="nav-text"><?= $menuParent['libeleMenu'] ?></span> <span class="nav-text"><?= $menuParent['libeleMenu'] ?></span>
</a> </a>
@ -185,13 +235,16 @@ $imgData = $_SESSION['photoAssureCrypte'] ?? '';
<div class="content-area"> <div class="content-area">
<?php if(!empty($menusvue)): ?> <?php if(!empty($menusvue)): ?>
<div class="nav-bar"> <div class="nav-bar">
<div class="nav-tabs"> <div class="nav-tabs" role="tablist" aria-label="Navigation secondaire">
<?php foreach ($menusvue as $menu): <?php foreach ($menusvue as $menu):
$isActive = ($_SESSION['vue'] ?? '') == $menu['libeleMenu']; $isActive = ($_SESSION['vue'] ?? '') == $menu['libeleMenu'];
?> ?>
<a href="<?= $menu['lienMenu'] ?>" <a href="<?= $menu['lienMenu'] ?>"
class="nav-tab <?= $isActive ? 'active' : '' ?>" class="nav-tab <?= $isActive ? 'active' : '' ?>"
title="<?= $menu['descriptionMenu'] ?? '' ?>"> title="<?= $menu['descriptionMenu'] ?? '' ?>"
role="tab"
aria-selected="<?= $isActive ? 'true' : 'false' ?>"
<?= $isActive ? 'aria-current="page"' : '' ?>>
<i class="bi bi-arrow-right-circle"></i> <i class="bi bi-arrow-right-circle"></i>
<?= $menu['libeleMenu'] ?> <?= $menu['libeleMenu'] ?>
</a> </a>
@ -219,13 +272,13 @@ $imgData = $_SESSION['photoAssureCrypte'] ?? '';
</main> </main>
<!-- Context Panel --> <!-- Context Panel -->
<aside class="context-panel" id="contextPanel"> <aside class="context-panel" id="contextPanel" aria-label="Panneau de contexte">
<div class="context-header"> <div class="context-header">
<div class="context-title"> <div class="context-title">
<i class="bi bi-info-circle"></i> <i class="bi bi-info-circle"></i>
<span><?= _('Contexte de la session') ?></span> <span><?= _('Contexte de la session') ?></span>
</div> </div>
<button class="context-close" onclick="toggleContextPanel()"> <button class="context-close" onclick="appUX.toggleContextPanel()" aria-label="Fermer le panneau de contexte">
<i class="bi bi-x-lg"></i> <i class="bi bi-x-lg"></i>
</button> </button>
</div> </div>
@ -264,7 +317,7 @@ $imgData = $_SESSION['photoAssureCrypte'] ?? '';
<span><?= _('Bénéficiaire') ?></span> <span><?= _('Bénéficiaire') ?></span>
</div> </div>
<button class="action-btn" onclick="afficher_beneficiaire_id()"> <button class="action-btn" onclick="afficher_beneficiaire_id()" aria-label="Voir les détails du bénéficiaire">
<i class="bi bi-person"></i> <i class="bi bi-person"></i>
<span><?= _('Bénéficiaire').' : '.$this->nettoyer($_SESSION['numeroBeneficiaire_C']) ?></span> <span><?= _('Bénéficiaire').' : '.$this->nettoyer($_SESSION['numeroBeneficiaire_C']) ?></span>
</button> </button>
@ -286,8 +339,9 @@ $imgData = $_SESSION['photoAssureCrypte'] ?? '';
<div class="photo-container"> <div class="photo-container">
<img src="data:image/jpg;base64,<?= $imgData ?>" <img src="data:image/jpg;base64,<?= $imgData ?>"
class="patient-photo" class="patient-photo"
onclick="openPhotoModal()" onclick="appModals.openPhotoModal()"
alt="<?= _('Photo du bénéficiaire') ?>"> alt="<?= _('Photo du bénéficiaire') ?>"
loading="lazy">
</div> </div>
</div> </div>
<?php endif; ?> <?php endif; ?>
@ -299,12 +353,12 @@ $imgData = $_SESSION['photoAssureCrypte'] ?? '';
<span><?= _('Actions rapides') ?></span> <span><?= _('Actions rapides') ?></span>
</div> </div>
<button class="action-btn" onclick="gerer_messagerie()"> <button class="action-btn" onclick="appNotifications.showMessagesModal()" aria-label="Gérer les notifications">
<i class="bi bi-chat-dots"></i> <i class="bi bi-chat-dots"></i>
<span><?= _('Gérer les notifications') ?></span> <span><?= _('Gérer les notifications') ?></span>
</button> </button>
<button class="action-btn" onclick="change_password()"> <button class="action-btn" onclick="change_password()" aria-label="Changer le mot de passe">
<i class="bi bi-key"></i> <i class="bi bi-key"></i>
<span><?= _('Changer le mot de passe') ?></span> <span><?= _('Changer le mot de passe') ?></span>
</button> </button>
@ -317,25 +371,33 @@ $imgData = $_SESSION['photoAssureCrypte'] ?? '';
</div> </div>
</aside> </aside>
<!-- Toggle Button --> <!-- Zone de détection de proximité -->
<button class="context-toggle" onclick="toggleContextPanel()"> <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> <i class="bi bi-info-circle"></i>
</button> </button>
<!-- Modals --> <!-- Modals -->
<!-- Photo Modal --> <!-- Photo Modal -->
<div class="modal fade modal-office" id="photoModal" tabindex="-1"> <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-dialog modal-dialog-centered modal-lg">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title"><?= _('Photo du bénéficiaire') ?></h5> <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"></button> <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Fermer"></button>
</div> </div>
<div class="modal-body text-center"> <div class="modal-body text-center">
<?php if ($_SESSION['faceRegistered_C'] == "1"): ?> <?php if ($_SESSION['faceRegistered_C'] == "1"): ?>
<img src="data:image/jpg;base64,<?= $imgData ?>" <img src="data:image/jpg;base64,<?= $imgData ?>"
class="img-fluid rounded" class="img-fluid rounded"
style="max-height: 70vh; max-width: 100%;"> style="max-height: 70vh; max-width: 100%;"
alt="<?= _('Photo agrandie du bénéficiaire') ?>">
<?php endif; ?> <?php endif; ?>
</div> </div>
</div> </div>
@ -343,12 +405,13 @@ $imgData = $_SESSION['photoAssureCrypte'] ?? '';
</div> </div>
<!-- Messages Modal --> <!-- Messages Modal -->
<div class="modal fade modal-office" id="messagesModal" tabindex="-1"> <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-dialog modal-lg">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title"><?= _('Notifications non lus') ?></h5> <h5 class="modal-title" id="messagesModalLabel"><?= _('Notifications non lues') ?></h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button> <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Fermer"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div id="div_messagerie"></div> <div id="div_messagerie"></div>
@ -373,135 +436,8 @@ $imgData = $_SESSION['photoAssureCrypte'] ?? '';
<script src="Js/datepicker-fr.js"></script> <script src="Js/datepicker-fr.js"></script>
<?php endif; ?> <?php endif; ?>
<script> <!-- UX Enhancement Script -->
// DOM Ready <script src="Bootstrap_new/js/ux-manager.js?ver=2025.12.20.01"></script>
document.addEventListener('DOMContentLoaded', function() {
// Toggle Sidebar on Mobile
document.querySelector('.sidebar-toggle').addEventListener('click', function() {
document.getElementById('sidebar').classList.toggle('open');
});
// Initialize tooltips
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl);
});
// Initialize select2
$('.select2').select2({
theme: 'bootstrap-5',
width: '100%'
});
// Initialize DataTables
$('.datatable').DataTable({
responsive: true,
language: {
url: '//cdn.datatables.net/plug-ins/1.13.6/i18n/fr-FR.json'
},
dom: '<"row"<"col-sm-12 col-md-6"l><"col-sm-12 col-md-6"f>>' +
'<"row"<"col-sm-12"tr>>' +
'<"row"<"col-sm-12 col-md-5"i><"col-sm-12 col-md-7"p>>'
});
// Simulate notification count
updateNotificationCount();
// Auto-refresh notifications every 60 seconds
setInterval(updateNotificationCount, 60000);
// Auto-refresh sidebar content
setInterval(raffraichier_gabarit, 30000);
});
// Toggle Context Panel
function toggleContextPanel() {
document.getElementById('contextPanel').classList.toggle('open');
}
// Open Photo Modal
function openPhotoModal() {
var modal = new bootstrap.Modal(document.getElementById('photoModal'));
modal.show();
}
// Show Messages Modal
function pop_messagerie() {
var modal = new bootstrap.Modal(document.getElementById('messagesModal'));
modal.show();
// Load messages via AJAX
$.ajax({
url: 'load_messages.php',
method: 'GET',
success: function(data) {
$('#div_messagerie').html(data);
}
});
}
// Update Notification Count
function updateNotificationCount() {
// Simulate notification count update
// In production, this would be an AJAX call
var count = Math.floor(Math.random() * 10);
var badge = document.getElementById('notificationCount');
badge.textContent = count;
badge.style.display = count > 0 ? 'flex' : 'none';
}
// Change Language
function changer_langue() {
Swal.fire({
title: 'Changer de langue',
text: 'Sélectionnez la langue souhaitée:',
icon: 'question',
showCancelButton: true,
confirmButtonText: 'Français',
cancelButtonText: 'English',
reverseButtons: true
}).then((result) => {
if (result.isConfirmed) {
// Switch to French
window.location.href = '?lang=fr_FR';
} else if (result.dismiss === Swal.DismissReason.cancel) {
// Switch to English
window.location.href = '?lang=en_US';
}
});
}
// Format dates based on locale
function formatOfficeDate(dateString) {
const date = new Date(dateString);
const options = {
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
};
if (est_anglophone()) {
return date.toLocaleDateString('en-US', options);
} else {
return date.toLocaleDateString('fr-FR', options);
}
}
// Close sidebar when clicking outside on mobile
document.addEventListener('click', function(event) {
const sidebar = document.getElementById('sidebar');
const toggleBtn = document.querySelector('.sidebar-toggle');
if (window.innerWidth < 768 &&
!sidebar.contains(event.target) &&
!toggleBtn.contains(event.target) &&
sidebar.classList.contains('open')) {
sidebar.classList.remove('open');
}
});
</script>
<!-- AJAX Content Area --> <!-- AJAX Content Area -->
<div id="div_ajaxgabarit"></div> <div id="div_ajaxgabarit"></div>