376 lines
18 KiB
PHP
Executable File
376 lines
18 KiB
PHP
Executable File
<?php
|
|
require_once 'gabarit_queries.php';
|
|
$gabary = new Gabary();
|
|
|
|
// Active menu tracking
|
|
$_SESSION['firstLevelMenu'] = '';
|
|
$current_url = $_SERVER['REQUEST_URI'];
|
|
$elements = explode("/", $current_url);
|
|
$activeLink = $elements[1];
|
|
$fullPath = $gabary->get_full_path($activeLink);
|
|
$fullPath = explode("\ ", $fullPath);
|
|
|
|
$activeLevel1 = $activeLink;
|
|
$activeLevel2 = sizeof($fullPath) > 1 ? $fullPath[1] : '';
|
|
$activeLevel3 = sizeof($fullPath) > 2 ? $fullPath[2] : '';
|
|
$activeLevel4 = sizeof($fullPath) > 3 ? $fullPath[3] : '';
|
|
$activeLevel5 = sizeof($fullPath) > 4 ? $fullPath[4] : '';
|
|
|
|
$_SESSION['firstLevelMenu'] = $activeLink;
|
|
|
|
const MAX_COMPANY_NAME_LENGTH = 20;
|
|
|
|
$companyDisplayName = htmlspecialchars($_SESSION['nomSociete'], ENT_QUOTES);
|
|
$modeDev = $_SESSION['modeDev_C'];
|
|
$imgData = $_SESSION['photoAssureCrypte'];
|
|
|
|
// Get breadcrumb info
|
|
$infovue = $gabary->getInfosVue($_SESSION['vue']);
|
|
$descriptionVue = est_anglophone() ? $infovue['DescriptionEng'] : $infovue['Description'];
|
|
$titreRetour = est_anglophone() ? $infovue['titreRetourEng'] : $infovue['titreRetour'];
|
|
$retourVue = $infovue['lienRetour'];
|
|
?>
|
|
|
|
<!DOCTYPE html>
|
|
<html lang="<?= est_anglophone() ? 'en' : 'fr' ?>" class="h-100">
|
|
|
|
<?php require_once 'head.php'; ?>
|
|
|
|
<body class="d-flex flex-column min-vh-100 bg-light">
|
|
|
|
<!-- Header -->
|
|
<?php include 'header.php'; ?>
|
|
|
|
<!-- Main Container -->
|
|
<div class="d-flex flex-grow-1" style="margin-top: 60px;">
|
|
|
|
<!-- Sidebar -->
|
|
<?php include 'sidebar.php'; ?>
|
|
|
|
<!-- Main Content -->
|
|
<main id="main" class="main flex-grow-1 p-0">
|
|
|
|
<!-- Hidden session variables -->
|
|
<input type="hidden" id="vue" value="<?= $_SESSION['vue'] ?? '' ?>">
|
|
<input type="hidden" id="racineWeb" value="<?= $racineWeb ?>">
|
|
<input type="hidden" id="dureeSession" value="<?= $_SESSION['dureeSession'] ?>">
|
|
<input type="hidden" id="nomSociete" value="<?= htmlspecialchars($_SESSION['nomSociete']) ?>">
|
|
<input type="hidden" id="modeDev" value="<?= $modeDev ?>">
|
|
|
|
<div class="container-fluid p-3 animate__animated animate__fadeIn">
|
|
|
|
<!-- Breadcrumb -->
|
|
<nav aria-label="breadcrumb" class="mb-4 px-2">
|
|
<ol class="breadcrumb bg-white shadow-sm rounded-pill py-2 px-4 border-0">
|
|
<li class="breadcrumb-item">
|
|
<a href="<?= $retourVue; ?>"
|
|
class="text-decoration-none text-muted small d-flex align-items-center">
|
|
<i class="fas fa-arrow-left me-2"></i>
|
|
<?= $titreRetour ?>
|
|
</a>
|
|
</li>
|
|
<li class="breadcrumb-item active text-primary fw-bold small text-uppercase"
|
|
aria-current="page">
|
|
<i class="fas fa-angle-right me-2 text-muted"></i>
|
|
<?= $descriptionVue ?>
|
|
</li>
|
|
</ol>
|
|
</nav>
|
|
|
|
<!-- Secondary Navigation -->
|
|
<?php if (isset($menusvue) && sizeof($menusvue) > 0): ?>
|
|
<div class="tabs-container mb-4 px-2">
|
|
<div class="card border-0 shadow-sm rounded-3 overflow-hidden">
|
|
<div class="d-flex overflow-auto">
|
|
<?php foreach ($menusvue as $menu):
|
|
$isActive = (basename($_SERVER['REQUEST_URI']) == basename($menu['lienMenu']));
|
|
$activeClass = $isActive ? 'active bg-primary text-white' : 'text-dark';
|
|
?>
|
|
<a class="nav-link-sub p-3 <?= $activeClass ?>"
|
|
href="<?= $menu['lienMenu']; ?>"
|
|
style="min-width: 150px; white-space: nowrap; border-right: 1px solid #e9ecef;">
|
|
<?php if (!empty($menu['icone'])): ?>
|
|
<i class="<?= $menu['icone'] ?> me-2"></i>
|
|
<?php endif; ?>
|
|
<?= $menu['libeleMenu'] ?>
|
|
<?php if ($isActive): ?>
|
|
<span class="badge bg-white text-primary ms-2 rounded-pill">
|
|
<i class="fas fa-check"></i>
|
|
</span>
|
|
<?php endif; ?>
|
|
</a>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<!-- Main Content Area -->
|
|
<section class="section main-dashboard px-2">
|
|
<div id="contenu" class="animate__animated animate__fadeIn">
|
|
<div id="div_test_gabarit"></div>
|
|
<?= $contenu ?>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</main>
|
|
|
|
<!-- Context Panel -->
|
|
<?php include 'contexte.php'; ?>
|
|
</div>
|
|
|
|
<!-- ======= Modals ======= -->
|
|
|
|
<!-- Unread Messages Modal -->
|
|
<div class="modal fade animate__animated animate__fadeInDown" id="popmessagerie" tabindex="-1" aria-hidden="true">
|
|
<div class="modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable">
|
|
<div class="modal-content border-0 shadow-lg">
|
|
<div class="modal-header bg-primary text-white">
|
|
<h5 class="modal-title fw-bold">
|
|
<i class="fas fa-envelope-open-text me-2"></i>
|
|
<?= _("Messages non lus") ?>
|
|
<span id="modalMsgCount" class="badge bg-white text-primary ms-2"></span>
|
|
</h5>
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body p-0">
|
|
<div id="div_messagerie" class="p-4" style="max-height: 400px; overflow-y: auto;">
|
|
<div class="text-center py-5 text-muted">
|
|
<i class="fas fa-envelope-open fa-3x mb-3"></i>
|
|
<p class="mb-0"><?= _("Aucun message non lu") ?></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer border-top">
|
|
<button type="button" class="btn btn-outline-secondary rounded-pill px-4" data-bs-dismiss="modal">
|
|
<?= _("Fermer") ?>
|
|
</button>
|
|
<button type="button" class="btn btn-primary rounded-pill px-4" onclick="javascript:gerer_messagerie();">
|
|
<i class="fas fa-cog me-2"></i>
|
|
<?= _("Gérer les messages") ?>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- New Message Alert Modal -->
|
|
<div class="modal fade animate__animated animate__bounceIn" id="popderniermessagerie" tabindex="-1" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered">
|
|
<div class="modal-content border-0 shadow-lg">
|
|
<div class="modal-header border-0 pb-0">
|
|
<h5 class="modal-title fw-bold text-danger">
|
|
<i class="fas fa-bell me-2"></i>
|
|
<?= _("Nouveau Message") ?>
|
|
</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body p-4">
|
|
<div id="div_dernier_messagerie" class="alert alert-info border-0 shadow-sm rounded-3">
|
|
<!-- Content loaded dynamically -->
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer border-0">
|
|
<button id="btn_close_pop_dernier_messagerie" type="button"
|
|
class="btn btn-danger w-100 rounded-pill py-2" data-bs-dismiss="modal">
|
|
<i class="fas fa-times me-2"></i>
|
|
<?= _("Fermer") ?>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Photo Modal -->
|
|
<div class="modal fade" id="pop_photo" tabindex="-1" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered">
|
|
<div class="modal-content bg-transparent border-0">
|
|
<div class="modal-header border-0">
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body text-center p-0">
|
|
<?php if (!empty($imgData) && $_SESSION['faceRegistered_C'] == "1"): ?>
|
|
<img src="data:image/jpg;base64,<?= $imgData ?>"
|
|
class="img-fluid rounded shadow-lg border border-5 border-white"
|
|
style="max-height: 80vh; object-fit: contain;"
|
|
alt="<?= _("Photo du bénéficiaire") ?>">
|
|
<h4 class="text-white mt-3 fw-bold"><?= $_SESSION['nomBeneficiaire_C'] ?? '' ?></h4>
|
|
<?php else: ?>
|
|
<div class="bg-white rounded shadow-lg p-5">
|
|
<i class="fas fa-user-slash fa-4x text-muted"></i>
|
|
<h4 class="mt-3 text-muted"><?= _("Photo non disponible") ?></h4>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Hidden Trigger Buttons -->
|
|
<button id="btn_pop_messagerie" type="button" class="d-none" data-bs-toggle="modal" data-bs-target="#popmessagerie"></button>
|
|
<button id="btn_pop_dernier_messagerie" type="button" class="d-none" data-bs-toggle="modal" data-bs-target="#popderniermessagerie"></button>
|
|
|
|
<!-- ======= Scripts ======= -->
|
|
|
|
<!-- Core Libraries -->
|
|
<script src="Bootstrap/js/jquery.min.js"></script>
|
|
<script src="Bootstrap/js/jquery-ui.js"></script>
|
|
<script src="Bootstrap/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
|
|
|
|
<!-- DataTables -->
|
|
<script src="Bootstrap_new/datatables/datatable.min.js"></script>
|
|
|
|
<!-- Charts -->
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
|
|
<!-- PDF Generation -->
|
|
<script src="Js/html2pdf.js"></script>
|
|
|
|
<!-- Select2 -->
|
|
<script src="Bootstrap_new/js/select2.min.js"></script>
|
|
|
|
<!-- Timer -->
|
|
<script src="Bootstrap/js/timer.jquery.js"></script>
|
|
|
|
<!-- SweetAlert2 -->
|
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
|
|
|
<!-- Toastr -->
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css">
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
|
|
|
|
<!-- Datepicker by language -->
|
|
<?php if (est_anglophone()) : ?>
|
|
<script src="Js/datepicker-eng.js"></script>
|
|
<?php else: ?>
|
|
<script src="Js/datepicker-fr.js"></script>
|
|
<?php endif; ?>
|
|
|
|
<!-- Core Functions -->
|
|
<script src="Js/fonctions.js?ver=<?= date('Y.m.d.H') ?>"></script>
|
|
<script src="<?= $_SESSION['dossierSociete'] . '/Js/societe.js' ?>"></script>
|
|
|
|
<!-- Animation Library -->
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.js"></script>
|
|
|
|
<!-- Font Awesome -->
|
|
<script src="https://kit.fontawesome.com/your-kit-code.js" crossorigin="anonymous"></script>
|
|
|
|
<!-- Script d'initialisation amélioré -->
|
|
<script type="text/javascript">
|
|
$(document).ready(function() {
|
|
// Initialisation des tooltips Bootstrap
|
|
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
|
|
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
|
|
return new bootstrap.Tooltip(tooltipTriggerEl);
|
|
});
|
|
|
|
// Gestion du sidebar
|
|
$('.toggle-sidebar-btn').on('click', function() {
|
|
$('body').toggleClass('toggle-sidebar');
|
|
$('#sidebar').toggleClass('collapsed');
|
|
$('.main').toggleClass('expanded');
|
|
});
|
|
|
|
// Gestion de la barre de contexte
|
|
$("#showSideNav").click(function() {
|
|
$("#barre_laterale_d").addClass("active");
|
|
$(this).fadeOut(200);
|
|
// Animation smooth
|
|
$('body').css('transition', 'margin-right 0.3s ease');
|
|
$('body').css('margin-right', '300px');
|
|
});
|
|
|
|
$("#hideSideNav").click(function() {
|
|
$("#barre_laterale_d").removeClass("active");
|
|
$("#showSideNav").fadeIn(200);
|
|
$('body').css('margin-right', '0');
|
|
});
|
|
|
|
// Synchronisation du badge de notifications
|
|
function syncBadge() {
|
|
var count = parseInt($("#msgNonLus").val()) || 0;
|
|
var badge = $("#badge_notif_msg");
|
|
|
|
if(count > 0) {
|
|
badge.text(count).show();
|
|
// Animation si nouveau message
|
|
if(count > parseInt(badge.data('last-count') || 0)) {
|
|
badge.addClass('animate__animated animate__pulse animate__fast');
|
|
setTimeout(() => {
|
|
badge.removeClass('animate__animated animate__pulse animate__fast');
|
|
}, 1000);
|
|
}
|
|
badge.data('last-count', count);
|
|
} else {
|
|
badge.hide();
|
|
}
|
|
}
|
|
|
|
// Vérifier toutes les 2 secondes
|
|
setInterval(syncBadge, 2000);
|
|
syncBadge(); // Première exécution
|
|
|
|
// Rafraîchir le gabarit
|
|
raffraichier_gabarit();
|
|
|
|
// Timer pour le rafraîchissement des messages
|
|
$('#timer').timer({
|
|
duration: '60s',
|
|
callback: function() {
|
|
raffraichier_messagerie();
|
|
syncBadge();
|
|
},
|
|
repeat: true
|
|
});
|
|
|
|
// Toastr configuration
|
|
toastr.options = {
|
|
"closeButton": true,
|
|
"progressBar": true,
|
|
"positionClass": "toast-top-right",
|
|
"timeOut": "5000",
|
|
"extendedTimeOut": "1000"
|
|
};
|
|
|
|
// Auto-focus sur les champs de recherche
|
|
if ($('input[autofocus]').length) {
|
|
setTimeout(function() {
|
|
$('input[autofocus]').focus().select();
|
|
}, 100);
|
|
}
|
|
|
|
// Prévenir la perte de données non sauvegardées
|
|
$(window).on('beforeunload', function() {
|
|
if ($('.unsaved-changes').length > 0) {
|
|
return "Vous avez des modifications non sauvegardées. Voulez-vous vraiment quitter ?";
|
|
}
|
|
});
|
|
});
|
|
|
|
// Fonction pour marquer les changements non sauvegardés
|
|
function markUnsaved() {
|
|
$('form').addClass('unsaved-changes');
|
|
}
|
|
|
|
// Démarrer l'auto-sauvegarde si besoin
|
|
function startAutosave(selector, interval = 30000) {
|
|
setInterval(function() {
|
|
if ($(selector).hasClass('unsaved-changes')) {
|
|
$(selector).submit();
|
|
}
|
|
}, interval);
|
|
}
|
|
</script>
|
|
|
|
<!-- AJAX Container -->
|
|
<div id="div_ajaxgabarit" class="d-none"></div>
|
|
|
|
<!-- Global Loading Overlay -->
|
|
<div id="globalLoading" class="position-fixed top-0 start-0 w-100 h-100 bg-white bg-opacity-75 d-flex justify-content-center align-items-center" style="z-index: 9999; display: none !important;">
|
|
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;">
|
|
<span class="visually-hidden"><?= _("Chargement...") ?></span>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|