Rehabilitation en UX/UI.
This commit is contained in:
parent
d28c3d4695
commit
eef4f490ce
File diff suppressed because it is too large
Load Diff
833
Bootstrap_new/css/ux_enhancements.css
Normal file
833
Bootstrap_new/css/ux_enhancements.css
Normal 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;
|
||||
}
|
||||
}
|
||||
1377
Bootstrap_new/js/ux-manager.js
Normal file
1377
Bootstrap_new/js/ux-manager.js
Normal file
File diff suppressed because it is too large
Load Diff
850
Vue/gabarit.php
850
Vue/gabarit.php
|
|
@ -9,501 +9,437 @@ $_SESSION['firstLevelMenu'] = $activeLink;
|
|||
|
||||
$companyDisplayName = htmlspecialchars($_SESSION['nomSociete'], ENT_QUOTES);
|
||||
$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>
|
||||
<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') ?></title>
|
||||
|
||||
<!-- Bootstrap 5 -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<!-- Bootstrap Icons -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/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/@ttskch/select2-bootstrap5-theme@1.3.0/dist/select2-bootstrap5.min.css" rel="stylesheet">
|
||||
|
||||
<!-- DataTables -->
|
||||
<link href="https://cdn.datatables.net/v/bs5/dt-1.13.6/datatables.min.css" rel="stylesheet">
|
||||
|
||||
<!-- SweetAlert2 -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css" rel="stylesheet">
|
||||
|
||||
<!-- Office/PowerPoint Inspired Styles -->
|
||||
<link href="Bootstrap_new/css/style_office.css?ver=2025.12.20.00" rel="stylesheet">
|
||||
|
||||
<script>
|
||||
const modeDev = <?= $_SESSION['modeDev_C'] ?? 0 ?>;
|
||||
if (modeDev != "1") {
|
||||
document.addEventListener('contextmenu', function(e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Header -->
|
||||
<header class="app-header">
|
||||
<div class="header-content">
|
||||
<div class="logo-container">
|
||||
<button class="header-btn sidebar-toggle d-lg-none">
|
||||
<i class="bi bi-list"></i>
|
||||
</button>
|
||||
|
||||
<a href="#" class="app-logo">
|
||||
<img src="Bootstrap_new/images/new/favicon.png" alt="INTER-SANTE">
|
||||
<span class="ms-2">INTER-SANTE</span>
|
||||
</a>
|
||||
|
||||
<?php if($_SESSION['bdTests_C'] == "1"): ?>
|
||||
<div class="test-indicator">
|
||||
<i class="fas fa-flask"></i>
|
||||
<span>MODE TEST</span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<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 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 -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<!-- Bootstrap Icons -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/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/@ttskch/select2-bootstrap5-theme@1.3.0/dist/select2-bootstrap5.min.css" rel="stylesheet">
|
||||
|
||||
<!-- DataTables -->
|
||||
<link href="https://cdn.datatables.net/v/bs5/dt-1.13.6/datatables.min.css" rel="stylesheet">
|
||||
|
||||
<!-- SweetAlert2 -->
|
||||
<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 -->
|
||||
<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>
|
||||
// Mode développeur
|
||||
const modeDev = <?= $_SESSION['modeDev_C'] ?? 0 ?>;
|
||||
if (modeDev != "1") {
|
||||
document.addEventListener('contextmenu', function(e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
|
||||
<div class="header-controls">
|
||||
<!-- Notifications -->
|
||||
<button class="header-btn notification-btn" onclick="pop_messagerie()">
|
||||
<i class="bi bi-bell"></i>
|
||||
<span class="notification-badge" id="notificationCount">0</span>
|
||||
</button>
|
||||
|
||||
<!-- Company Info -->
|
||||
<div class="language-selector" onclick="changer_langue()">
|
||||
<?php
|
||||
$flag = est_anglophone() ? 'england.png' : 'france.png';
|
||||
$lib = est_anglophone() ? 'EN' : 'FR';
|
||||
?>
|
||||
<img src="Bootstrap_new/images/<?= $flag ?>" alt="Language" class="language-flag">
|
||||
<span ><?= $lib ?></span>
|
||||
// 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>
|
||||
</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">
|
||||
<i class="bi bi-list"></i>
|
||||
</button>
|
||||
|
||||
<a href="#" class="app-logo">
|
||||
<img src="Bootstrap_new/images/new/favicon.png" alt="INTER-SANTÉ" width="36" height="36">
|
||||
<span class="ms-2">INTER-SANTÉ</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>
|
||||
|
||||
<!-- User Menu -->
|
||||
<div class="user-menu dropdown-toggle" data-bs-toggle="dropdown">
|
||||
<div class="user-avatar">
|
||||
<?= $_SESSION['userInitials_C'] ?? 'U' ?>
|
||||
<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>
|
||||
<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">
|
||||
|
||||
<!-- 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="text-center">
|
||||
<div class="fw-bold"><?= $_SESSION['utilisateur_C'] ?? _('Utilisateur') ?></div>
|
||||
<small class="text-muted"><?= $_SESSION['nomClient_C'] ?? _('Client') ?></small>
|
||||
<div class="user-info">
|
||||
<div class="user-name"><?= $_SESSION['utilisateur_C'] ?? _('Utilisateur') ?></div>
|
||||
<div class="user-role"><?= $_SESSION['nomClient_C'] ?? _('Client') ?></div>
|
||||
</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:gerer_messagerie()">
|
||||
<i class="fas fa-envelope me-2"></i> <?= _('Messagerie') ?>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger" href="#">
|
||||
<i class="fas fa-sign-out-alt me-2"></i> <?= _('Déconnexion') ?>
|
||||
</a>
|
||||
|
||||
<!-- 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="#">
|
||||
<i class="fas fa-sign-out-alt me-2"></i> <?= _('Déconnexion') ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</header>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<aside class="app-sidebar" id="sidebar">
|
||||
<nav class="sidebar-nav">
|
||||
<div class="nav-section">
|
||||
<div class="nav-title"> <?= _('Navigation principale') ?></div>
|
||||
<?php foreach ($menus as $key0 => $menuParent):
|
||||
$menuChildrenLevelOne = $gabary->get_menus_by_parent_code($menuParent['vue']);
|
||||
$isActive = false;
|
||||
|
||||
// Check if any child is active
|
||||
foreach ($menuChildrenLevelOne as $menuChild) {
|
||||
if ((explode('/', $menuChild['lienMenu'])[0] ?? '') == $activeLink) {
|
||||
$isActive = true;
|
||||
break;
|
||||
<!-- 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
<div class="nav-item">
|
||||
<?php if (sizeof($menuChildrenLevelOne) > 0): ?>
|
||||
<a href="#submenu<?= $key0 ?>"
|
||||
class="nav-link <?= $isActive ? 'active' : '' ?>"
|
||||
data-bs-toggle="collapse"
|
||||
aria-expanded="<?= $isActive ? 'true' : 'false' ?>">
|
||||
<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 <?= $isActive ? 'show' : '' ?>" id="submenu<?= $key0 ?>">
|
||||
<?php foreach ($menuChildrenLevelOne as $key1 => $menuChild):
|
||||
$childActive = (explode('/', $menuChild['lienMenu'])[0] ?? '') == $activeLink;
|
||||
?>
|
||||
<div class="nav-item">
|
||||
<?php if (sizeof($menuChildrenLevelOne) > 0): ?>
|
||||
<a href="#submenu<?= $key0 ?>"
|
||||
class="nav-link <?= $isParentActive || $hasActiveChild ? 'active' : '' ?>"
|
||||
data-bs-toggle="collapse"
|
||||
aria-expanded="<?= $isParentActive || $hasActiveChild ? 'true' : 'false' ?>"
|
||||
aria-controls="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 <?= $isParentActive || $hasActiveChild ? 'show' : '' ?>"
|
||||
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="<?= $menuChild['lienMenu'] ?>"
|
||||
class="nav-link <?= $childActive ? 'active' : '' ?>">
|
||||
<?= $menuChild['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>
|
||||
<?php else: ?>
|
||||
<a href="<?= $menuParent['lienMenu'] ?>" class="nav-link">
|
||||
<i class="<?= $menuParent['icone'] ?>"></i>
|
||||
<span class="nav-text"><?= $menuParent['libeleMenu'] ?></span>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?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']) ?>">
|
||||
|
||||
<!-- Content Container -->
|
||||
<div class="content-card">
|
||||
<div class="card-body">
|
||||
<div id="contenu">
|
||||
<div id="div_test_gabarit"></div>
|
||||
<?= $contenu ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</aside>
|
||||
</main>
|
||||
|
||||
<!-- 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">
|
||||
<?php foreach ($menusvue as $menu):
|
||||
$isActive = ($_SESSION['vue'] ?? '') == $menu['libeleMenu'];
|
||||
?>
|
||||
<a href="<?= $menu['lienMenu'] ?>"
|
||||
class="nav-tab <?= $isActive ? 'active' : '' ?>"
|
||||
title="<?= $menu['descriptionMenu'] ?? '' ?>">
|
||||
<i class="bi bi-arrow-right-circle"></i>
|
||||
<?= $menu['libeleMenu'] ?>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
<!-- 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>
|
||||
</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']) ?>">
|
||||
|
||||
<!-- 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">
|
||||
<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="toggleContextPanel()">
|
||||
<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()">
|
||||
<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="openPhotoModal()"
|
||||
alt="<?= _('Photo du bénéficiaire') ?>">
|
||||
</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="gerer_messagerie()">
|
||||
<i class="bi bi-chat-dots"></i>
|
||||
<span><?= _('Gérer les notifications') ?></span>
|
||||
</button>
|
||||
|
||||
<button class="action-btn" onclick="change_password()">
|
||||
<i class="bi bi-key"></i>
|
||||
<span><?= _('Changer le mot de passe') ?></span>
|
||||
<button class="context-close" onclick="appUX.toggleContextPanel()" aria-label="Fermer le panneau de contexte">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Messages -->
|
||||
<div id="nbMessagesNonLus" class="d-none">
|
||||
<input type="hidden" id="msgNonLus" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Toggle Button -->
|
||||
<button class="context-toggle" onclick="toggleContextPanel()">
|
||||
<i class="bi bi-info-circle"></i>
|
||||
</button>
|
||||
|
||||
<!-- Modals -->
|
||||
<!-- Photo Modal -->
|
||||
<div class="modal fade modal-office" id="photoModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><?= _('Photo du bénéficiaire') ?></h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
<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>
|
||||
<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%;">
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- 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>
|
||||
</div>
|
||||
|
||||
<!-- Messages Modal -->
|
||||
<div class="modal fade modal-office" id="messagesModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><?= _('Notifications non lus') ?></h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="div_messagerie"></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>
|
||||
</div>
|
||||
|
||||
<!-- JavaScript Libraries -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-3.7.0.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.20.00"></script>
|
||||
|
||||
<?php if (est_anglophone()): ?>
|
||||
<script src="Js/datepicker-eng.js"></script>
|
||||
<?php else: ?>
|
||||
<script src="Js/datepicker-fr.js"></script>
|
||||
<?php endif; ?>
|
||||
|
||||
<script>
|
||||
// DOM Ready
|
||||
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);
|
||||
});
|
||||
<!-- JavaScript Libraries -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-3.7.0.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>
|
||||
|
||||
// Toggle Context Panel
|
||||
function toggleContextPanel() {
|
||||
document.getElementById('contextPanel').classList.toggle('open');
|
||||
}
|
||||
<!-- Application Scripts -->
|
||||
<script src="Js/fonctions.js?ver=2025.12.20.00"></script>
|
||||
|
||||
// Open Photo Modal
|
||||
function openPhotoModal() {
|
||||
var modal = new bootstrap.Modal(document.getElementById('photoModal'));
|
||||
modal.show();
|
||||
}
|
||||
<?php if (est_anglophone()): ?>
|
||||
<script src="Js/datepicker-eng.js"></script>
|
||||
<?php else: ?>
|
||||
<script src="Js/datepicker-fr.js"></script>
|
||||
<?php endif; ?>
|
||||
|
||||
// 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
<!-- UX Enhancement Script -->
|
||||
<script src="Bootstrap_new/js/ux-manager.js?ver=2025.12.20.01"></script>
|
||||
|
||||
// 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 -->
|
||||
<div id="div_ajaxgabarit"></div>
|
||||
</body>
|
||||
<!-- AJAX Content Area -->
|
||||
<div id="div_ajaxgabarit"></div>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in New Issue
Block a user