| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512 |
- <?php
- $dateData = get::jsonDateDataExcelProwebDossiers();
- $date = ($dateData != NULL) ? " (au " . core::convertDate($dateData, FALSE) . ")" : "";
- $jsonTarget = "/json.php?file=dossiers-proweb";
- if (debug::isFile("debug")) {
- debug::log(debug::getBadge($jsonTarget, "OUVRIR LE JSON : " . $jsonTarget), "JSON chargé en arrière plan");
- }
- ?>
- <header class="d-flex flex-column flex-md-row align-items-md-center p-3 bg-light ">
- <h2 class="bd-title" id="content">
- <span>Proweb : Liste des dossiers<?php echo $date ?></span>
- </h2>
- <?php if (access::ifAccesss("proweb-dossiers-upload")) { ?>
- <div class="fix-container-button-nav">
- <a href="proweb-dossiers-upload.html"><button type="submit" class="btn btn-outline-success btn-sm"><?php icon::getFont(["icon" => "bi bi-file-earmark-plus"]) ?> Importer un fichier Excel</button></a>
- <a href="<?= prowebDossiers::getLinkProweb() ?>" target="_blank"><button type="submit" class="btn btn-outline-secondary btn-sm"><?php icon::getFont(["icon" => "bi bi-link-45deg"]) ?> Exporter tous les dossiers depuis Proweb</button></a>
- </div>
- <?php } ?>
- </header>
- <?php
- echo core::filAriane(array(
- "current" => "Liste des dossiers",
- "arbo" => array(
- "Proweb" => NULL,
- "Liste des dossiers" => "proweb-dossiers.html"
- ),
- "refresh-json" => "dossiers-proweb"
- ));
- ?>
- <!-- Panel de filtres avancés avec checkboxes multi-sélection -->
- <div class="card mb-3" id="advancedFiltersPanel">
- <div class="card-header d-flex justify-content-between align-items-center" style="cursor: pointer;" onclick="toggleAdvancedFilters()">
- <span><i class="bi bi-funnel"></i> Filtres avancés (sélection multiple)</span>
- <i class="bi bi-chevron-up" id="advancedFiltersIcon"></i>
- </div>
- <div class="card-body" id="advancedFiltersBody">
- <div class="row">
- <div class="col-lg-2 col-md-4 mb-2">
- <label class="form-label fw-bold">Année</label>
- <input type="text" class="form-control form-control-sm mb-1 filter-search-input" id="search-exe_ref" placeholder="Rechercher..." oninput="filterCheckboxList('exe_ref')">
- <div class="filter-checkbox-container" id="filter-exe_ref"><small class="text-muted">Chargement...</small></div>
- </div>
- <div class="col-lg-2 col-md-4 mb-2">
- <label class="form-label fw-bold">Catégorie</label>
- <input type="text" class="form-control form-control-sm mb-1 filter-search-input" id="search-catprest_lib" placeholder="Rechercher..." oninput="filterCheckboxList('catprest_lib')">
- <div class="filter-checkbox-container" id="filter-catprest_lib"><small class="text-muted">Chargement...</small></div>
- </div>
- <div class="col-lg-2 col-md-4 mb-2">
- <label class="form-label fw-bold">Prestation</label>
- <input type="text" class="form-control form-control-sm mb-1 filter-search-input" id="search-prest_lib" placeholder="Rechercher..." oninput="filterCheckboxList('prest_lib')">
- <div class="filter-checkbox-container" id="filter-prest_lib"><small class="text-muted">Chargement...</small></div>
- </div>
- <div class="col-lg-2 col-md-4 mb-2">
- <label class="form-label fw-bold">Etat</label>
- <input type="text" class="form-control form-control-sm mb-1 filter-search-input" id="search-etdoss_lib" placeholder="Rechercher..." oninput="filterCheckboxList('etdoss_lib')">
- <div class="filter-checkbox-container" id="filter-etdoss_lib"><small class="text-muted">Chargement...</small></div>
- </div>
- <div class="col-lg-2 col-md-4 mb-2">
- <label class="form-label fw-bold">Commission</label>
- <input type="text" class="form-control form-control-sm mb-1 filter-search-input" id="search-comm_ref" placeholder="Rechercher..." oninput="filterCheckboxList('comm_ref')">
- <div class="filter-checkbox-container" id="filter-comm_ref"><small class="text-muted">Chargement...</small></div>
- </div>
- <div class="col-lg-2 col-md-4 mb-2">
- <label class="form-label fw-bold">Clôturé</label>
- <input type="text" class="form-control form-control-sm mb-1 filter-search-input" id="search-prest_closed" placeholder="Rechercher..." oninput="filterCheckboxList('prest_closed')">
- <div class="filter-checkbox-container" id="filter-prest_closed"><small class="text-muted">Chargement...</small></div>
- </div>
- </div>
- <div class="row">
- <div class="col-lg-2 col-md-4 mb-2">
- <label class="form-label fw-bold">Complément</label>
- <input type="text" class="form-control form-control-sm mb-1 filter-search-input" id="search-prest_lib2" placeholder="Rechercher..." oninput="filterCheckboxList('prest_lib2')">
- <div class="filter-checkbox-container" id="filter-prest_lib2"><small class="text-muted">Chargement...</small></div>
- </div>
- </div>
- <div class="mt-2">
- <button type="button" class="btn btn-sm btn-outline-secondary" onclick="clearAllAdvancedFilters()">
- <i class="bi bi-x-circle"></i> Réinitialiser les filtres
- </button>
- <span class="ms-3 text-muted" id="filterInfo"></span>
- </div>
- </div>
- </div>
- <style>
- .filter-checkbox-container {
- max-height: 150px;
- overflow-y: auto;
- border: 1px solid #dee2e6;
- border-radius: 4px;
- padding: 8px;
- background: #fff;
- }
- .filter-checkbox-container .form-check {
- margin-bottom: 2px;
- }
- .filter-checkbox-container .form-check-label {
- font-size: 0.85rem;
- cursor: pointer;
- }
- .filter-checkbox-container .form-check-input {
- cursor: pointer;
- }
- .filter-checkbox-container .filter-option-disabled {
- opacity: 0.5;
- text-decoration: line-through;
- }
- .filter-checkbox-container .filter-option-count {
- font-size: 0.75rem;
- color: #6c757d;
- margin-left: 4px;
- }
- #advancedFiltersPanel .card-header:hover {
- background-color: #f8f9fa;
- }
- .filter-search-input {
- font-size: 0.8rem;
- }
- .filter-search-input::placeholder {
- font-style: italic;
- color: #adb5bd;
- }
- .filter-checkbox-hidden {
- display: none !important;
- }
- </style>
- <div>
- <table
- id="ProWebDossiers"
- class="table-striped table-hover table-sm"
- data-sort-name="hismo_date_crea"
- data-sort-order="desc"
- data-page-size="50"
- data-show-footer="true"
- data-toggle="table"
- data-buttons-align="left"
- data-pagination="true"
- data-filter-control="true"
- data-flat="true"
- data-show-export="true"
- data-show-columns-toggle-all="true"
- data-page-list="[50, 100, 250, 500, 750, 1000]"
- data-url="<?php echo $jsonTarget ?>">
- <thead>
- <tr>
- <th data-sortable="true" data-field="exe_ref" data-filter-control="select">Année</th>
- <th data-sortable="true" data-field="hismo_date_crea" data-filter-control="select">Création</th>
- <th data-sortable="true" data-field="prest_lib" data-filter-control="input">Prestation</th>
- <th data-sortable="true" data-field="prest_lib2" data-filter-control="select">Complément</th>
- <th data-sortable="true" data-field="catprest_lib" data-filter-control="select">Catégorie</th>
- <th data-sortable="true" data-field="comm_ref" data-filter-control="select">Commission</th>
- <th data-sortable="true" data-field="prest_closed" data-filter-control="select" data-formatter="clotureFormatter">Clôturé</th>
- <th data-sortable="true" data-field="etdoss_lib" data-filter-control="select">Etat</th>
- <th data-sortable="true" data-field="od_matricule" data-filter-control="input">Matricule</th>
- <th data-sortable="true" data-field="nomComplet" data-filter-control="input" data-formatter="concatNomPrenom">Prénom Nom</th>
- <th data-sortable="true" data-field="doss_nb_inscrit" data-filter-control="select" data-footer-formatter="totalInscrits">Nb. Inscrits</th>
- <th data-sortable="true" data-formatter="dataFormatter" data-field="doss_partce" data-filter-control="input" data-footer-formatter="prixCSE">Part CSE</th>
- <th data-sortable="true" data-formatter="dataFormatter" data-field="doss_partod" data-filter-control="input" data-footer-formatter="prixSalarie">Part Salarié</th>
- <th data-sortable="true" data-formatter="dataFormatter" data-field="doss_montant_total" data-filter-control="input" data-footer-formatter="prixTotal">Total</th>
- </tr>
- </thead>
- </table>
- </div>
- <script>
- let euro = Intl.NumberFormat('de-DE', {
- style: 'currency',
- currency: 'EUR',
- });
- // Données originales et filtrées
- let originalData = [];
- let currentFilters = {};
- // Champs pour les filtres avancés avec checkboxes
- const advancedFilterFields = ['exe_ref', 'catprest_lib', 'prest_lib', 'etdoss_lib', 'comm_ref', 'prest_closed', 'prest_lib2'];
- function dataFormatter(value) {
- return euro.format(value);
- }
- function totalInscrits(data) {
- var total = 0;
- data.forEach(function(row) {
- var nb = parseFloat(row.doss_nb_inscrit);
- if (!isNaN(nb)) {
- total += nb;
- }
- });
- return total;
- }
- function prixCSE(data) {
- var total = 0;
- data.forEach(function(row) {
- total += parseFloat(row.doss_partce);
- });
- return parseFloat(total) === 0 ? euro.format(0.00) : euro.format(total.toFixed(2));
- }
- function prixSalarie(data) {
- var total = 0;
- data.forEach(function(row) {
- total += parseFloat(row.doss_partod);
- });
- return parseFloat(total) === 0 ? euro.format(0.00) : euro.format(total.toFixed(2));
- }
- function prixTotal(data) {
- var total = 0;
- data.forEach(function(row) {
- total += parseFloat(row.doss_montant_total);
- });
- return parseFloat(total) === 0 ? euro.format(0.00) : euro.format(total.toFixed(2));
- }
- function concatNomPrenom(value, row, index) {
- return row.od_prenom + ' ' + row.od_nom;
- }
- function clotureFormatter(value) {
- return value == 1 ? "Clôturé" : "Ouvert";
- }
- function subventionFormatter(value) {
- switch (value) {
- case "O":
- return "Subventionné"
- break;
- case "N":
- return "Non-subventionné"
- break;
- default:
- return "-"
- break;
- }
- }
- // Toggle du panneau de filtres avancés
- function toggleAdvancedFilters() {
- const body = document.getElementById('advancedFiltersBody');
- const icon = document.getElementById('advancedFiltersIcon');
- if (body.style.display === 'none') {
- body.style.display = 'block';
- icon.className = 'bi bi-chevron-up';
- } else {
- body.style.display = 'none';
- icon.className = 'bi bi-chevron-down';
- }
- }
- // Filtrer la liste des checkboxes par recherche textuelle
- function filterCheckboxList(field) {
- const searchInput = document.getElementById(`search-${field}`);
- const container = document.getElementById(`filter-${field}`);
- if (!searchInput || !container) return;
- const searchText = searchInput.value.toLowerCase().trim();
- const checkboxes = container.querySelectorAll('.form-check');
- checkboxes.forEach(checkDiv => {
- const label = checkDiv.querySelector('.form-check-label');
- if (label) {
- // Exclure le compteur entre parenthèses de la recherche
- const countSpan = label.querySelector('.filter-option-count');
- let labelText = label.textContent.toLowerCase();
- if (countSpan) {
- labelText = labelText.replace(countSpan.textContent.toLowerCase(), '').trim();
- }
- if (searchText === '' || labelText.includes(searchText)) {
- checkDiv.classList.remove('filter-checkbox-hidden');
- } else {
- checkDiv.classList.add('filter-checkbox-hidden');
- }
- }
- });
- }
- // Réinitialiser les barres de recherche
- function clearSearchInputs() {
- advancedFilterFields.forEach(field => {
- const searchInput = document.getElementById(`search-${field}`);
- if (searchInput) {
- searchInput.value = '';
- }
- });
- }
- // Formater la valeur pour l'affichage
- function formatFilterValue(field, value) {
- if (field === 'prest_closed') {
- return value == 1 ? 'Clôturé' : 'Ouvert';
- }
- return value || '(vide)';
- }
- // Obtenir les valeurs uniques pour un champ dans les données filtrées
- function getUniqueValues(data, field) {
- const values = new Map();
- data.forEach(row => {
- const val = row[field];
- const key = val === null || val === undefined || val === '' ? '__empty__' : String(val);
- values.set(key, (values.get(key) || 0) + 1);
- });
- return values;
- }
- // Obtenir les données filtrées selon les filtres actuels (sauf un champ exclu)
- function getFilteredData(excludeField = null) {
- return originalData.filter(row => {
- for (const [field, selectedValues] of Object.entries(currentFilters)) {
- if (field === excludeField) continue;
- if (selectedValues.length === 0) continue;
- const rowValue = row[field];
- const rowKey = rowValue === null || rowValue === undefined || rowValue === '' ? '__empty__' : String(rowValue);
- if (!selectedValues.includes(rowKey)) {
- return false;
- }
- }
- return true;
- });
- }
- // Mettre à jour les checkboxes d'un filtre
- function updateFilterCheckboxes(field) {
- const container = document.getElementById(`filter-${field}`);
- if (!container) return;
- // Obtenir les données filtrées en excluant ce champ
- const filteredData = getFilteredData(field);
- const availableValues = getUniqueValues(filteredData, field);
- const allValues = getUniqueValues(originalData, field);
- // Sauvegarder les valeurs actuellement sélectionnées
- const currentSelected = currentFilters[field] || [];
- container.innerHTML = '';
- // Trier les valeurs
- const sortedKeys = Array.from(allValues.keys()).sort((a, b) => {
- if (a === '__empty__') return 1;
- if (b === '__empty__') return -1;
- return String(a).localeCompare(String(b));
- });
- sortedKeys.forEach(key => {
- const count = availableValues.get(key) || 0;
- const totalCount = allValues.get(key);
- const isDisabled = count === 0;
- const isChecked = currentSelected.includes(key);
- const div = document.createElement('div');
- div.className = 'form-check';
- const input = document.createElement('input');
- input.type = 'checkbox';
- input.className = 'form-check-input';
- input.id = `chk-${field}-${key}`;
- input.value = key;
- input.checked = isChecked;
- input.dataset.field = field;
- input.addEventListener('change', onFilterCheckboxChange);
- const label = document.createElement('label');
- label.className = 'form-check-label' + (isDisabled && !isChecked ? ' filter-option-disabled' : '');
- label.htmlFor = input.id;
- label.innerHTML = `${formatFilterValue(field, key === '__empty__' ? '' : key)} <span class="filter-option-count">(${count}/${totalCount})</span>`;
- div.appendChild(input);
- div.appendChild(label);
- container.appendChild(div);
- });
- }
- // Mettre à jour tous les filtres
- function updateAllFilterCheckboxes() {
- advancedFilterFields.forEach(field => {
- updateFilterCheckboxes(field);
- });
- updateFilterInfo();
- }
- // Quand une checkbox change
- function onFilterCheckboxChange(event) {
- const field = event.target.dataset.field;
- const value = event.target.value;
- const isChecked = event.target.checked;
- if (!currentFilters[field]) {
- currentFilters[field] = [];
- }
- if (isChecked) {
- if (!currentFilters[field].includes(value)) {
- currentFilters[field].push(value);
- }
- } else {
- currentFilters[field] = currentFilters[field].filter(v => v !== value);
- }
- // Mettre à jour les autres filtres (cascade)
- advancedFilterFields.forEach(f => {
- if (f !== field) {
- updateFilterCheckboxes(f);
- }
- });
- // Appliquer le filtre à la table
- applyAdvancedFilters();
- updateFilterInfo();
- }
- // Appliquer les filtres avancés à la table
- function applyAdvancedFilters() {
- const $table = $('#ProWebDossiers');
- // Filtrer les données
- const filteredData = getFilteredData();
- // Recharger la table avec les données filtrées
- $table.bootstrapTable('load', filteredData);
- }
- // Réinitialiser tous les filtres avancés
- function clearAllAdvancedFilters() {
- currentFilters = {};
- advancedFilterFields.forEach(field => {
- currentFilters[field] = [];
- });
- // Réinitialiser les barres de recherche
- clearSearchInputs();
- // Recharger les données originales
- $('#ProWebDossiers').bootstrapTable('load', originalData);
- // Mettre à jour les checkboxes
- updateAllFilterCheckboxes();
- // Réinitialiser aussi les filtres de la table
- $('#ProWebDossiers').bootstrapTable('clearFilterControl');
- }
- // Mettre à jour l'info des filtres actifs
- function updateFilterInfo() {
- const activeFilters = [];
- for (const [field, values] of Object.entries(currentFilters)) {
- if (values.length > 0) {
- const fieldNames = {
- 'exe_ref': 'Année',
- 'catprest_lib': 'Catégorie',
- 'prest_lib': 'Prestation',
- 'etdoss_lib': 'Etat',
- 'comm_ref': 'Commission',
- 'prest_closed': 'Clôturé',
- 'prest_lib2': 'Complément'
- };
- activeFilters.push(`${fieldNames[field]}: ${values.length} sélection(s)`);
- }
- }
- const infoEl = document.getElementById('filterInfo');
- if (activeFilters.length > 0) {
- const filteredCount = getFilteredData().length;
- infoEl.innerHTML = `<strong>${filteredCount}</strong> dossier(s) affiché(s) | Filtres actifs: ${activeFilters.join(', ')}`;
- } else {
- infoEl.innerHTML = `<strong>${originalData.length}</strong> dossier(s) au total`;
- }
- }
- // Initialisation
- $(document).ready(function() {
- const $table = $('#ProWebDossiers');
- // Attendre que les données soient chargées
- $table.on('load-success.bs.table', function(e, data) {
- // Sauvegarder les données originales
- originalData = data;
- // Initialiser les filtres
- advancedFilterFields.forEach(field => {
- currentFilters[field] = [];
- });
- // Construire les checkboxes des filtres
- updateAllFilterCheckboxes();
- });
- // Synchroniser avec les filtres de la table Bootstrap
- $table.on('column-search.bs.table', function(e, field, text) {
- // Quand un filtre de colonne change, mettre à jour les compteurs
- setTimeout(updateFilterInfo, 100);
- });
- });
- </script>
|