Modif
This commit is contained in:
parent
58a2f533cb
commit
fb12a515ac
|
|
@ -810,6 +810,7 @@ function afficher_adherents_police()
|
||||||
|
|
||||||
|
|
||||||
function graphique_sinistre() {
|
function graphique_sinistre() {
|
||||||
|
// Spinner pendant le chargement
|
||||||
$("#div_graphique").html(`
|
$("#div_graphique").html(`
|
||||||
<div class="text-center my-5 py-5">
|
<div class="text-center my-5 py-5">
|
||||||
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;">
|
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;">
|
||||||
|
|
@ -824,20 +825,46 @@ function graphique_sinistre() {
|
||||||
type: 'get',
|
type: 'get',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
$("#div_graphique").empty();
|
console.log("Réponse JSON reçue:", data);
|
||||||
|
|
||||||
// Construis ton layout HTML ici
|
// Layout HTML
|
||||||
$("#div_graphique").append(`
|
$("#div_graphique").html(`
|
||||||
|
<div class="text-end my-3">
|
||||||
|
<button id="exportPdfBtn" class="btn btn-danger">
|
||||||
|
<i class="fas fa-file-pdf"></i> Exporter le tableau de bord en PDF
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6 mb-4"><canvas id="claimsChart"></canvas></div>
|
<div class="col-md-6 mb-4">
|
||||||
<div class="col-md-6 mb-4"><canvas id="claimsMonthChart"></canvas></div>
|
<div class="card shadow-sm">
|
||||||
<div class="col-md-12 mb-4"><canvas id="lossRatioChart"></canvas></div>
|
<div class="card-body">
|
||||||
|
<h5 class="card-title text-primary">Répartition des sinistres</h5>
|
||||||
|
<canvas id="claimsChart"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 mb-4">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title text-success">Évolution mensuelle</h5>
|
||||||
|
<canvas id="claimsMonthChart"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12 mb-4">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title text-danger">Ratio de sinistralité</h5>
|
||||||
|
<canvas id="lossRatioChart"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
// --- Graphiques Chart.js ---
|
||||||
|
|
||||||
// Initialise les graphiques avec Chart.js
|
// 1. Répartition
|
||||||
// Graphique 1 : répartition des sinistres
|
|
||||||
new Chart(document.getElementById('claimsChart'), {
|
new Chart(document.getElementById('claimsChart'), {
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
data: {
|
data: {
|
||||||
|
|
@ -850,7 +877,7 @@ function graphique_sinistre() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Graphique 2 : évolution mensuelle
|
// 2. Évolution mensuelle
|
||||||
new Chart(document.getElementById('claimsMonthChart'), {
|
new Chart(document.getElementById('claimsMonthChart'), {
|
||||||
type: 'line',
|
type: 'line',
|
||||||
data: {
|
data: {
|
||||||
|
|
@ -872,7 +899,7 @@ function graphique_sinistre() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Graphique 3 : ratio de sinistralité
|
// 3. Ratio de sinistralité
|
||||||
new Chart(document.getElementById('lossRatioChart'), {
|
new Chart(document.getElementById('lossRatioChart'), {
|
||||||
type: 'line',
|
type: 'line',
|
||||||
data: {
|
data: {
|
||||||
|
|
@ -886,9 +913,46 @@ function graphique_sinistre() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// --- Export PDF ---
|
||||||
|
$("#exportPdfBtn").on("click", function() {
|
||||||
|
if (!window.jspdf) {
|
||||||
|
alert("Erreur : jsPDF n'est pas chargé.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { jsPDF } = window.jspdf;
|
||||||
|
const pdf = new jsPDF('p', 'mm', 'a4');
|
||||||
|
|
||||||
|
pdf.setFontSize(18);
|
||||||
|
pdf.text("Tableau de bord - Synthèse", 10, 20);
|
||||||
|
|
||||||
|
// Ajout des graphiques
|
||||||
|
addChartToPdf(pdf, 'claimsChart', 'Répartition des sinistres', 40);
|
||||||
|
addChartToPdf(pdf, 'claimsMonthChart', 'Évolution mensuelle', 120);
|
||||||
|
|
||||||
|
pdf.addPage();
|
||||||
|
addChartToPdf(pdf, 'lossRatioChart', 'Ratio de sinistralité', 40);
|
||||||
|
|
||||||
|
pdf.save('Tableau_de_bord.pdf');
|
||||||
|
});
|
||||||
|
|
||||||
|
function addChartToPdf(pdf, canvasId, title, startY) {
|
||||||
|
const canvas = document.getElementById(canvasId);
|
||||||
|
if (canvas) {
|
||||||
|
const imgData = canvas.toDataURL('image/png', 1.0);
|
||||||
|
pdf.setFontSize(14);
|
||||||
|
pdf.text(title, 10, startY);
|
||||||
|
pdf.addImage(imgData, 'PNG', 10, startY + 5, 180, 60);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
error: function(err) {
|
error: function(err) {
|
||||||
$("#div_graphique").html(`<div class="alert alert-danger">Impossible de charger les graphiques.</div>`);
|
console.error("Erreur AJAX:", err);
|
||||||
|
$("#div_graphique").html(`
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
Impossible de charger les graphiques.
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -138,10 +138,13 @@
|
||||||
<i class="accordion-icon bi bi-chevron-down"></i>
|
<i class="accordion-icon bi bi-chevron-down"></i>
|
||||||
</h2>
|
</h2>
|
||||||
<div class="accordion-content">
|
<div class="accordion-content">
|
||||||
<button id="graphiqueBtn" class="btn btn-primary" onclick="graphique_sinistre();">
|
<button id="graphiqueBtn" onclick="graphique_sinistre()">
|
||||||
<i class="fas fa-sync-alt me-2"></i> <?= _('Actualiser') ?>
|
<i class="fas fa-sync-alt me-2"></i> <?= _('Actualiser') ?>
|
||||||
</button>
|
</button>
|
||||||
<div id="div_graphique">
|
<div id="div_graphique">
|
||||||
|
<canvas id="claimsChart"></canvas>
|
||||||
|
<canvas id="claimsMonthChart"></canvas>
|
||||||
|
<canvas id="lossRatioChart"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Graphiques (placeholders) -->
|
<!-- Graphiques (placeholders uniquement) -->
|
||||||
<div class="grid-1">
|
<div class="grid-1">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h3><?= _('Évolution des sinistres') ?></h3>
|
<h3><?= _('Évolution des sinistres') ?></h3>
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
<div class="grid-2">
|
<div class="grid-2">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h3><?= _('Sinitralité') ?></h3>
|
<h3><?= _('Sinistralité') ?></h3>
|
||||||
<div class="chart">
|
<div class="chart">
|
||||||
<canvas id="lossRatioBar"></canvas>
|
<canvas id="lossRatioBar"></canvas>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -30,189 +30,3 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--
|
|
||||||
NOTE: Les librairies Chart.js et jsPDF doivent être chargées
|
|
||||||
dans la page parente (Accueil.php) et non ici pour éviter les erreurs.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// On encapsule tout dans une fonction auto-exécutée (IIFE)
|
|
||||||
// Cela empêche les variables 'const' de polluer le scope global et de planter au 2ème clic.
|
|
||||||
(function() {
|
|
||||||
|
|
||||||
// Récupération des données injectées par PHP
|
|
||||||
// Grâce aux flags JSON_HEX dans le contrôleur, cette injection est sûre.
|
|
||||||
const dataClaims = <?= $dataTabClaims ?>;
|
|
||||||
const dataClaimsMonth = <?= $dataTabClaimsMonth ?>;
|
|
||||||
const dataLossRatio = <?= $dataLossRatio ?>;
|
|
||||||
|
|
||||||
// --- Gestion du bouton Export PDF ---
|
|
||||||
const btnExport = document.getElementById('exportPdfBtn');
|
|
||||||
if (btnExport) {
|
|
||||||
btnExport.addEventListener('click', function () {
|
|
||||||
// Vérification que la librairie est chargée
|
|
||||||
if (!window.jspdf) {
|
|
||||||
alert("Erreur : La librairie jsPDF n'est pas chargée.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { jsPDF } = window.jspdf;
|
|
||||||
const pdf = new jsPDF('p', 'mm', 'a4');
|
|
||||||
|
|
||||||
// --- Logo ---
|
|
||||||
const logo = new Image();
|
|
||||||
logo.src = "<?= $_SESSION['lienLogo'] ?>";
|
|
||||||
logo.onload = function() {
|
|
||||||
try {
|
|
||||||
pdf.addImage(logo, 'PNG', 150, 5, 40, 20);
|
|
||||||
} catch(e) {
|
|
||||||
console.warn("Impossible de charger le logo dans le PDF");
|
|
||||||
}
|
|
||||||
generatePdfContent(pdf);
|
|
||||||
};
|
|
||||||
logo.onerror = function() {
|
|
||||||
// Si le logo échoue, on génère quand même le PDF
|
|
||||||
generatePdfContent(pdf);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function generatePdfContent(pdf) {
|
|
||||||
// --- Titre principal ---
|
|
||||||
pdf.setFontSize(18);
|
|
||||||
pdf.text("<?= _("Tableau de bord - Synthèse") ?>", 10, 20);
|
|
||||||
|
|
||||||
// --- KPIs ---
|
|
||||||
pdf.setFontSize(12);
|
|
||||||
pdf.text("Total Contrats : <?= format_N($kpis['nbPolice']) ?>", 10, 35);
|
|
||||||
pdf.text("Total Assurés :", 10, 42);
|
|
||||||
pdf.text(" Salariés : <?= format_N($kpis['nbAdherent']) ?>", 10, 49);
|
|
||||||
pdf.text(" Ayants droits : <?= format_N($kpis['nbDependant']) ?>", 10, 56);
|
|
||||||
pdf.text("Primes :", 10, 66);
|
|
||||||
pdf.text(" TTC : <?= format_N($kpis['primeTtc']).' '.$_SESSION['devise_C'] ?>", 10, 73);
|
|
||||||
pdf.text(" Nette Stat : <?= format_N($kpis['primeNetteStat']).' '.$_SESSION['devise_C'] ?>", 10, 80);
|
|
||||||
pdf.text("Sinistres :", 10, 90);
|
|
||||||
pdf.text(" Nombre : <?= format_N($kpis['nbSinistres']) ?>", 10, 97);
|
|
||||||
pdf.text(" Montant : <?= format_N($kpis['montantApayer']).' '.$_SESSION['devise_C'] ?>", 10, 104);
|
|
||||||
pdf.text(" Rapport S/P : <?= $kpis['rapportSp'].'%' ?>", 10, 111);
|
|
||||||
|
|
||||||
// --- Graphiques ---
|
|
||||||
addChartToPdf(pdf, 'claimsPie', 'Sinistres par garantie', 125);
|
|
||||||
addChartToPdf(pdf, 'claimsLine', 'Évolution des sinistres mensuels', 200);
|
|
||||||
|
|
||||||
// Nouvelle page pour le dernier graphique
|
|
||||||
pdf.addPage();
|
|
||||||
addChartToPdf(pdf, 'lossRatioBar', 'Sinistralité (%)', 20);
|
|
||||||
|
|
||||||
// --- Sauvegarde ---
|
|
||||||
pdf.save('Tableau_de_bord.pdf');
|
|
||||||
}
|
|
||||||
|
|
||||||
function addChartToPdf(pdf, canvasId, title, startY) {
|
|
||||||
const canvas = document.getElementById(canvasId);
|
|
||||||
if (canvas) {
|
|
||||||
try {
|
|
||||||
const imgData = canvas.toDataURL('image/png', 1.0);
|
|
||||||
pdf.setFontSize(14);
|
|
||||||
pdf.text(title, 10, startY);
|
|
||||||
pdf.addImage(imgData, 'PNG', 10, startY + 5, 180, 60);
|
|
||||||
} catch (e) {
|
|
||||||
console.warn("Erreur export graphique " + canvasId, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Initialisation des graphiques ---
|
|
||||||
|
|
||||||
// 1. Sinistres par garantie
|
|
||||||
const ctxPie = document.getElementById('claimsPie');
|
|
||||||
if (ctxPie) {
|
|
||||||
new Chart(ctxPie, {
|
|
||||||
type: 'doughnut',
|
|
||||||
data: {
|
|
||||||
labels: dataClaims.claimsLabels,
|
|
||||||
datasets: [{
|
|
||||||
data: dataClaims.claimsValues
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
plugins: {
|
|
||||||
legend: { position: 'right' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Evolution des sinistres par mois
|
|
||||||
const ctxLine = document.getElementById('claimsLine');
|
|
||||||
if (ctxLine) {
|
|
||||||
new Chart(ctxLine, {
|
|
||||||
data: {
|
|
||||||
labels: dataClaimsMonth.months,
|
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
type: 'line',
|
|
||||||
label: "Cumulés",
|
|
||||||
data: dataClaimsMonth.monthlyClaims,
|
|
||||||
borderColor: "blue",
|
|
||||||
backgroundColor: "rgba(0,0,255,0.2)",
|
|
||||||
tension: 0.4,
|
|
||||||
yAxisID: 'y'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'bar',
|
|
||||||
label: "Mensuels",
|
|
||||||
data: dataClaimsMonth.singleClaims,
|
|
||||||
backgroundColor: "rgba(255,0,0,0.5)",
|
|
||||||
borderColor: "red",
|
|
||||||
borderWidth: 1,
|
|
||||||
yAxisID: 'y'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true,
|
|
||||||
interaction: {
|
|
||||||
mode: 'index',
|
|
||||||
intersect: false
|
|
||||||
},
|
|
||||||
stacked: false,
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
beginAtZero: true,
|
|
||||||
title: { display: true, text: "Montant des sinistres" }
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
title: { display: true, text: "Mois" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Sinistralité
|
|
||||||
const ctxBar = document.getElementById('lossRatioBar');
|
|
||||||
if (ctxBar) {
|
|
||||||
new Chart(ctxBar, {
|
|
||||||
type: 'bar',
|
|
||||||
data: {
|
|
||||||
labels: dataLossRatio.lossRatioLabels,
|
|
||||||
datasets: [{
|
|
||||||
label: "Sinistralité (%)",
|
|
||||||
data: dataLossRatio.lossRatioValues
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
beginAtZero: true,
|
|
||||||
max: 100
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
})(); // Fin de l'IIFE
|
|
||||||
</script>
|
|
||||||
|
|
@ -599,7 +599,7 @@ $activeChildId = $menuData['child'];
|
||||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
|
|
||||||
<!-- Application Scripts -->
|
<!-- Application Scripts -->
|
||||||
<script src="/Js/fonctions.js?ver=2025.12.31.00"></script>
|
<script src="/Js/fonctions.js?ver=2025.12.31.01"></script>
|
||||||
|
|
||||||
<?php if (est_anglophone()): ?>
|
<?php if (est_anglophone()): ?>
|
||||||
<script src="/Js/datepicker-eng.js"></script>
|
<script src="/Js/datepicker-eng.js"></script>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user