384 lines
16 KiB
PHP
384 lines
16 KiB
PHP
<div class="container text-primary">
|
|
<h1><i class="fas fa-tachometer-alt"></i> <?= _('Tableau de bord') ?></h1>
|
|
|
|
<!-- KPIs -->
|
|
<div class="kpis">
|
|
<div class="card">
|
|
<h3><?= _('Total Contrats')?></h3>
|
|
<div class="value"><?= number_format($kpis["nbPolice"]) ?></div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h3><?= _('Total Assurés')?></h3>
|
|
<div class="sub-values">
|
|
<div class="sub-item">
|
|
<span><?= _('Adhérents') ?> :</span>
|
|
<strong><?= format_N($kpis["nbAdherent"]) ?></strong>
|
|
</div>
|
|
<div class="sub-item">
|
|
<span><?= _('Ayants droits') ?> :</span>
|
|
<strong><?= format_N($kpis["nbDependant"]) ?></strong>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h3><?= _('Primes')?></h3>
|
|
<div class="sub-values">
|
|
<div class="sub-item">
|
|
<span><?= _('Statistique') ?> :</span>
|
|
<strong class="text-success"><?= format_N($kpis["primeNetteStat"]).' '.$_SESSION['devise_C'] ?></strong>
|
|
</div>
|
|
|
|
<div class="sub-item">
|
|
<span><?= _('TTC') ?> :</span>
|
|
<strong><?= format_N($kpis["primeTtc"]).' '.$_SESSION['devise_C'] ?></strong>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h3><?= _('Sinistres')?></h3>
|
|
<div class="sub-values">
|
|
<div class="sub-item">
|
|
<span><?= _('Montant') ?> :</span>
|
|
<strong class="text-danger"><?= format_N($kpis["montantApayer"]).' '.$_SESSION['devise_C'] ?></strong>
|
|
</div>
|
|
<div class="sub-item">
|
|
<span><?= _('Rapport S/P') ?> :</span>
|
|
<?php if($kpis["rapportSp"] > 65 && $kpis["rapportSp"] <= 80):?>
|
|
<strong class="text-warning"><?= $kpis["rapportSp"].'%' ?></strong>
|
|
<?php elseif($kpis["rapportSp"] > 80):?>
|
|
<strong class="text-danger"><?= $kpis["rapportSp"].'%' ?></strong>
|
|
<?php else:?>
|
|
<strong class="text-primary"><?= $kpis["rapportSp"].'%' ?></strong>
|
|
<?php endif;?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid-1">
|
|
<div class="card">
|
|
<section class="accordion-section">
|
|
<h2 class="accordion-header">
|
|
<i class="fas fa-file-contract text-primary"></i>
|
|
<span class="accordion-title"><?= _("Liste des contrats")?></span>
|
|
<i class="accordion-icon bi bi-chevron-down"></i>
|
|
</h2>
|
|
<div class="accordion-content">
|
|
<div class="table-responsive">
|
|
<table class="table table-striped table-bordered table-hover table-condensed tabliste compact w-100" style="font-size:10pt; white-space:nowrap;">
|
|
<thead>
|
|
<tr>
|
|
<th style="text-align:center"> <?= _("No Police") ?> </th>
|
|
<th style="text-align:center"> <?= _("ID Police") ?> </th>
|
|
<th style="text-align:center">Type</th>
|
|
<th style="text-align:center"> <?= _("Effet") ?> </th>
|
|
<th style="text-align:center"> <?= _("Échéance") ?> </th>
|
|
<th style="text-align:center"> <?= _("Type Avenant") ?> </th>
|
|
<th style="text-align:center"> <?= _("État") ?> </th>
|
|
<th style="text-align:center"> <?= _("Prime") ?> </th>
|
|
<th style="text-align:center"> <?= _("Sinistres") ?> </th>
|
|
<th style="text-align:center"> <?= _("R S/P") ?> </th>
|
|
|
|
<!-- Colonnes cachées pour recherche -->
|
|
<th data-hidden="true">NoPoliceHidden</th>
|
|
<th data-hidden="true">IdPoliceHidden</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($polices as $police):
|
|
$id = $this->nettoyer($police['idPolice']);
|
|
$nopol = $this->nettoyer($police['numeroPolice']);
|
|
?>
|
|
<tr>
|
|
<!-- Boutons visibles -->
|
|
<td align="center">
|
|
<input type="button" class="form-control btn btn-primary" value="<?= $nopol ?>"
|
|
onClick="selectionner_police(<?= $id ?>,'<?= $nopol ?>');">
|
|
</td>
|
|
<td align="center">
|
|
<input type="button" class="form-control btn btn-info" value="<?= $id ?>"
|
|
onClick="selectionner_police(<?= $id ?>,'<?= $nopol ?>');">
|
|
</td>
|
|
|
|
<!-- Autres colonnes -->
|
|
<td align='center'><?= $this->nettoyer($police['typeContrat']) ?></td>
|
|
<td align='center'><?= dateLang($this->nettoyer($police['dateEffet']), $_SESSION['lang'])?></td>
|
|
<td align='center'><?= dateLang($this->nettoyer($police['dateEcheance']), $_SESSION['lang']) ?></td>
|
|
<td align='center'><?= $this->nettoyer($police['typeAvenant']) ?></td>
|
|
<td align='center'><?= $this->nettoyer($police['etatPolice']) ?></td>
|
|
<td align='center'><?= format_N($this->nettoyer($police['primeNetteStat'])) ?></td>
|
|
<td align='center'><?= format_N($this->nettoyer($police['montantApayer'])) ?></td>
|
|
|
|
<?php if($police["rapportSp"] > 65 && $police["rapportSp"] <= 80):?>
|
|
<td align='center' class="text-warning"><?= $police["rapportSp"].'%' ?></td>
|
|
<?php elseif($police["rapportSp"] > 80):?>
|
|
<td align='center' class="text-danger"><?= $police["rapportSp"].'%' ?></td>
|
|
<?php else:?>
|
|
<td align='center' class="text-primary"><?= $police["rapportSp"].'%' ?></td>
|
|
<?php endif;?>
|
|
|
|
<!-- Colonnes cachées -->
|
|
<td><?= $nopol ?></td>
|
|
<td><?= $id ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Activité & Alertes -->
|
|
<!--
|
|
<div class="grid-2">
|
|
<div class="card">
|
|
<h3><?= _('Activité récente')?></h3>
|
|
<ul>
|
|
<?php foreach ($activities as $activity): ?>
|
|
<li>
|
|
<i class="<?= $activity["icon"] ?>"></i>
|
|
<?= $activity["label"] ?>
|
|
<small style="float:right;color:#999"><?= $activity["time"] ?></small>
|
|
</li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h3><?= _('Alertes')?></h3>
|
|
<ul>
|
|
<?php foreach ($alerts as $alert): ?>
|
|
<li class="alert">
|
|
<i class="fas fa-exclamation-triangle"></i>
|
|
<?= $alert ?>
|
|
</li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
-->
|
|
|
|
<!-- Bouton Export PDF -->
|
|
<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>
|
|
|
|
<!-- Graphiques (placeholders) -->
|
|
<div class="grid-1">
|
|
<div class="card">
|
|
<h3><?= _('Évolution des sinistres mensuels') ?></h3>
|
|
<div class="chart">
|
|
<canvas id="claimsLine"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid-2">
|
|
<div class="card">
|
|
<h3><?= _('Sinitralité') ?></h3>
|
|
<div class="chart">
|
|
<canvas id="lossRatioBar"></canvas>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h3><?= _('Sinistres par garantie')?></h3>
|
|
<div class="chart">
|
|
<canvas id="claimsPie"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- Chart.js -->
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
|
|
|
|
<!-- librairie jsPDF -->
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
|
|
<script>
|
|
document.getElementById('exportPdfBtn').addEventListener('click', function () {
|
|
const { jsPDF } = window.jspdf;
|
|
const pdf = new jsPDF('p', 'mm', 'a4');
|
|
|
|
// --- Logo ---
|
|
const logo = new Image();
|
|
logo.src = "<?= $_SESSION['lienLogo'] ?>"; // chemin vers ton logo
|
|
logo.onload = function() {
|
|
pdf.addImage(logo, 'PNG', 150, 5, 40, 20);
|
|
|
|
// --- 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);
|
|
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);
|
|
}
|
|
});
|
|
|
|
// Sinistres par garantie
|
|
const dataClaims = <?= $dataTabClaims ?>;
|
|
new Chart(document.getElementById('claimsPie'), {
|
|
type: 'doughnut',
|
|
data: {
|
|
labels: dataClaims.claimsLabels,
|
|
datasets: [{
|
|
data: dataClaims.claimsValues
|
|
}]
|
|
},
|
|
options: {
|
|
plugins: {
|
|
legend: { position: 'right' }
|
|
}
|
|
}
|
|
});
|
|
|
|
// Evolution des sinistres par mois
|
|
const dataClaimsMonth = <?= $dataTabClaimsMonth ?>;
|
|
|
|
new Chart(document.getElementById('claimsLine'), {
|
|
data: {
|
|
labels: dataClaimsMonth.months,
|
|
datasets: [
|
|
{
|
|
type: 'line',
|
|
label: "Cumulés",
|
|
data: dataClaimsMonth.monthlyClaims, // cumulés
|
|
borderColor: "blue",
|
|
backgroundColor: "rgba(0,0,255,0.2)",
|
|
tension: 0.4,
|
|
yAxisID: 'y'
|
|
},
|
|
{
|
|
type: 'bar',
|
|
label: "Mensuels",
|
|
data: dataClaimsMonth.singleClaims, // valeurs brutes
|
|
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"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// Sinistralité
|
|
const dataLossRatio = <?= $dataLossRatio ?>;
|
|
|
|
new Chart(document.getElementById('lossRatioBar'), {
|
|
type: 'bar',
|
|
data: {
|
|
labels: dataLossRatio.lossRatioLabels,
|
|
datasets: [{
|
|
label: "Sinistralité (%)",
|
|
data: dataLossRatio.lossRatioValues
|
|
}]
|
|
},
|
|
options: {
|
|
scales: {
|
|
y: {
|
|
beginAtZero: true,
|
|
max: 100
|
|
}
|
|
}
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Laisser Bootstrap gérer les accordéons - suppression du script conflictuel
|
|
// Bootstrap s'occupe déjà du fonctionnement des accordéons
|
|
|
|
// Si vous voulez garder votre système personnalisé pour les grandes sections,
|
|
// assurez-vous qu'il ne cible pas les mêmes éléments que Bootstrap
|
|
|
|
const sectionHeaders = document.querySelectorAll('.accordion-section .accordion-header');
|
|
|
|
sectionHeaders.forEach(header => {
|
|
header.addEventListener('click', function() {
|
|
// Vérifier si cet accordéon est géré par Bootstrap
|
|
if (!this.querySelector('[data-bs-toggle="collapse"]')) {
|
|
const content = this.nextElementSibling;
|
|
const isCurrentlyActive = this.classList.contains('active');
|
|
|
|
// Fermer toutes les sections d'abord
|
|
document.querySelectorAll('.accordion-section .accordion-content').forEach(content => {
|
|
content.style.display = 'none';
|
|
});
|
|
document.querySelectorAll('.accordion-section .accordion-header').forEach(header => {
|
|
header.classList.remove('active');
|
|
});
|
|
|
|
// Si la section n'était pas active, l'ouvrir
|
|
if (!isCurrentlyActive) {
|
|
this.classList.add('active');
|
|
content.style.display = 'block';
|
|
}
|
|
}
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
|