691 lines
30 KiB
PHP
691 lines
30 KiB
PHP
<?php
|
|
// $this->titre = "INTER-SANTE - Fiche Adhérent";
|
|
|
|
$codeTypeAvenant = $_SESSION['codeTypeAvenant_C'];
|
|
$estsupprimable_0 = false;
|
|
$garantieArchive = $_SESSION['garantieArchive_C'];
|
|
$estsupprimable = false;
|
|
|
|
$primeArchiveAdh = $this->nettoyer($adherent['primeArchive']);
|
|
$estsupprimableAdh = ($primeArchiveAdh=="0");
|
|
|
|
//$superUser = $_SESSION['superUser'];
|
|
|
|
$idAdherent = $this->nettoyer($adherent['idAdherent']);
|
|
|
|
$adherentRetire = $adherent['sorti'];
|
|
$dateSortieAdherent = $adherent['dateSortieAdherent'];
|
|
|
|
$controlerPlafondAdherent = ($_SESSION['controlerPlafondAdherent']>0);
|
|
|
|
$codeTypeContrat = $_SESSION['codeTypeContrat'];
|
|
|
|
$idApporteur = $this->nettoyer($adherent['idApporteur']);
|
|
$libelleApporteur = $this->nettoyer($adherent['libelleApporteur']);
|
|
$typeecheancier = $this->nettoyer($adherent['typeecheancier']);
|
|
if (est_anglophone())
|
|
{
|
|
$typeecheancier = $this->nettoyer($adherent['typeecheancierEng']);
|
|
}
|
|
$tauxInteretEcheancier = $this->nettoyer($adherent['tauxInteretEcheancier']);
|
|
/*
|
|
var_dump(
|
|
array(
|
|
"dateEffetAdherent_C"=> $_SESSION['dateEffetAdherent_C'],
|
|
)
|
|
);
|
|
*/
|
|
?>
|
|
|
|
<script type="text/javascript">
|
|
|
|
</script>
|
|
|
|
<INPUT class="sr-only" TYPE="text" id="garantieArchive_C" name="garantieArchive_C" value="<?= $_SESSION['garantieArchive_C'] ?>">
|
|
<INPUT class="sr-only" TYPE="text" id="primeArchive" name="primeArchive" value="<?= $adherent['primeArchive'] ?>" >
|
|
<INPUT class="sr-only" TYPE="text" id="remplacementAdherent" name="remplacementAdherent" value="<?= $adherent['remplacementAdherent'] ?>" >
|
|
<INPUT class="sr-only" TYPE="text" id="remplace" name="remplace" value="<?= $adherent['remplace'] ?>" >
|
|
<INPUT class="sr-only" TYPE="text" id="remplacant" name="remplace" value="<?= $adherent['remplacant'] ?>" >
|
|
<INPUT class="sr-only" TYPE="text" id="idApporteur" name="idApporteur" value="<?= $idApporteur ?>" >
|
|
|
|
<div id="div_adherent" class="container-fluid py-1 animate__animated animate__fadeIn">
|
|
|
|
<h1 class="text-primary"><i class="fas fa-id-card me-2"></i><?= _('Fiche adhérent') ?></h1>
|
|
|
|
<div class="card-header d-flex justify-content-between align-items-center py-1">
|
|
<h5 class="mb-0 fw-bold">
|
|
<?= _("POLICE") ?> : <span class="text-secondary"><?= $this->nettoyer($_SESSION['numeroPolice_C']) ?></span>
|
|
<span class="ms-3 badge bg-primary text-light small fw-normal">ID: <?= $this->nettoyer($_SESSION['idPolice_C']) ?></span>
|
|
</h5>
|
|
</div>
|
|
|
|
<form name="formficheadehrent" id="formficheadehrent" method="POST" class="container-fluid py-1">
|
|
<input type="hidden" id="codeEtatFacturation" name="codeEtatFacturation" value="<?= $adherent['codeEtatFacturation'] ?>">
|
|
<input type="hidden" id="numeroBeneficiaire" name="numeroBeneficiaire" value="<?= $adherent['numeroBeneficiaire'] ?>">
|
|
<input type="hidden" id="codeEtatAdherent" name="codeEtatAdherent" value="<?= $adherent['codeEtatAdherent'] ?>">
|
|
|
|
<?php if ($adherentRetire == "1") : ?>
|
|
<div class="alert alert-danger d-flex align-items-center mb-4 shadow-sm" role="alert">
|
|
<i class="fas fa-exclamation-triangle me-3 fa-2x"></i>
|
|
<div>
|
|
<h4 class="alert-heading mb-0"><?= _("Adhérent sorti le") . " : " . dateLang($dateSortieAdherent) ?></h4>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="card shadow-sm mb-4">
|
|
<div class="card-header bg-primary text-white d-flex justify-content-between align-items-center">
|
|
<h5 class="mb-0"><i class="fas fa-user-circle me-2"></i><?= _("Informations sur l'adhérent") ?> : <span class="badge bg-light text-primary"><?= $this->nettoyer($adherent['numeroAdherent']) ?></span></h5>
|
|
</div>
|
|
<div class="card-body bg-light">
|
|
<div class="row g-3">
|
|
<div class="col-md-4">
|
|
<label class="form-label small text-uppercase fw-bold"><?= _("Nom & Prénoms") ?></label>
|
|
<div class="input-group">
|
|
<span class="input-group-text"><i class="fas fa-id-card"></i></span>
|
|
<input type="text" class="form-control" value="<?= $this->nettoyer($adherent['nom']) ?> <?= $this->nettoyer($adherent['prenoms']) ?>" readonly>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<label class="form-label small text-uppercase fw-bold"><?= _("Collège") ?></label>
|
|
<input type="text" class="form-control" value="<?= $this->nettoyer($adherent['libelleCollege']) ?>" readonly>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<label class="form-label small text-uppercase fw-bold"><?= _("Contact") ?></label>
|
|
<div class="input-group">
|
|
<span class="input-group-text"><i class="fas fa-phone"></i></span>
|
|
<input type="text" class="form-control" value="<?= $this->nettoyer($adherent['telephonePortable']) ?>" readonly>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<label class="form-label small text-uppercase fw-bold"><?= _("E-mail") ?></label>
|
|
<input type="email" class="form-control" value="<?= $this->nettoyer($adherent['email']) ?>" readonly>
|
|
</div>
|
|
<div class="col-md-8">
|
|
<label class="form-label small text-uppercase fw-bold"><?= _("Localisation") ?></label>
|
|
<div class="input-group">
|
|
<span class="input-group-text"><i class="fas fa-map-marker-alt"></i></span>
|
|
<input type="text" class="form-control" value="<?= $this->nettoyer($adherent['pays']) ?> / <?= $this->nettoyer($adherent['ville']) ?> / <?= $this->nettoyer($adherent['localite']) ?>" readonly>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php if ($controlerPlafondAdherent): ?>
|
|
<hr class="my-4">
|
|
<div class="row g-3 text-center">
|
|
<div class="col-md-4">
|
|
<div class="p-3 border rounded bg-white shadow-sm">
|
|
<div class="small fw-bold text-primary text-uppercase"><?= _("Plafond Famille") ?></div>
|
|
<div class="h4 mb-0 text-primary fw-bold"><?= format_N($limite_adherent['plafondAdherent']) ?></div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="p-3 border rounded bg-white shadow-sm border-danger">
|
|
<div class="small fw-bold text-danger text-uppercase"><?= _("Consommations") ?></div>
|
|
<div class="h4 mb-0 text-danger fw-bold"><?= format_N($limite_adherent['consommationAdherent']) ?></div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="p-3 border rounded bg-success text-white shadow-sm">
|
|
<div class="small fw-bold text-uppercase"><?= _("Solde Disponible") ?></div>
|
|
<div class="h4 mb-0 fw-bold"><?= format_N($limite_adherent['soldeAdherent']) ?></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<?php if ($codeTypeContrat == "F"): ?>
|
|
<div class="card shadow-sm mb-4 border-info">
|
|
<div class="card-header bg-info text-dark fw-bold">
|
|
<i class="fas fa-file-invoice-dollar me-2"></i><?= _("Récapitulatif des primes") ?>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
<div class="table-responsive">
|
|
<table class="table table-sm table-hover mb-0 align-middle">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th class="text-center"><?= _("Prime HT") ?></th>
|
|
<th class="text-center"><?= _("Taxes") ?></th>
|
|
<th class="text-center"><?= _("Prime TTC") ?></th>
|
|
<th class="text-center"><?= _("Nb Échéances") ?></th>
|
|
<th class="text-center"><?= _("Part Assureur") ?></th>
|
|
<th class="text-center"><?= _("Part Tiers") ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td class="text-center fw-bold"><?= format_N($adherent['primeHt']) ?></td>
|
|
<td class="text-center text-muted"><?= format_N($adherent['taxe']) ?></td>
|
|
<td class="text-center fw-bold text-primary"><?= format_N($adherent['primeTtc']) ?></td>
|
|
<td class="text-center"><?= $adherent['nbEcheance'] ?></td>
|
|
<td class="text-center"><span class="badge bg-primary"><?= format_N($adherent['partAssureur']) ?></span></td>
|
|
<td class="text-center"><span class="badge bg-danger"><?= format_N($adherent['partTiers']) ?></span></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="card shadow-sm mb-4">
|
|
<div class="card-header bg-secondary text-white">
|
|
<h5 class="mb-0"><i class="fas fa-users me-2"></i><?= _('Composition de la famille') ?></h5>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
<div class="table-responsive" style="max-height: 400px; overflow-y: auto;">
|
|
<table class="table table-hover table-striped mb-0 align-middle shadow-sm">
|
|
<thead class="table-dark sticky-top">
|
|
<tr class="small">
|
|
<th><?= _("Photo") ?></th>
|
|
<th><?= _("N° Bénéf.") ?></th>
|
|
<th><?= _("Nom & Prénoms") ?></th>
|
|
<th class="text-center"><?= _("Sexe") ?></th>
|
|
<th><?= _("Lien") ?></th>
|
|
<th class="text-center"><?= _("Âge") ?></th>
|
|
<th class="text-end"><?= _("Prime HT") ?></th>
|
|
<th class="text-end"><?= _("Prime TTC") ?></th>
|
|
<th class="text-center"><?= _("État") ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($beneficiaires as $beneficiaire):
|
|
$photoPath = ($beneficiaire['faceRegistered'] == "1") ? $_SESSION['dossierPhoto_C'].$_SESSION['dossierSociete'].'/Photos/'.$beneficiaire['lienPhoto'] : '';
|
|
$faceRegistered = $this->nettoyer($beneficiaire['faceRegistered']);
|
|
?>
|
|
<tr class="pointer-cursor" onclick="selectionner_beneficiaire(<?= $beneficiaire['idBeneficiaire'] ?>,'<?= $beneficiaire['numeroBeneficiaire'] ?>'); afficher_beneficiaire_id();">
|
|
<td class="text-center">
|
|
<?php if($faceRegistered == "1"): ?>
|
|
<img src="<?= $photoPath ?>" class="rounded-circle border" width="30" height="30" alt="Photo">
|
|
<?php else: ?>
|
|
<i class="fas fa-user-circle photo-zoom" style="color: #ccc; font-size: 30px;"></i>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><span class="badge bg-secondary text-light border"><?= $beneficiaire['numeroBeneficiaire'] ?></span></td>
|
|
<td class="fw-bold"><?= $this->nettoyer($beneficiaire['nomBeneficiaire']) ?> <?= $this->nettoyer($beneficiaire['prenomsBeneficiaire']) ?></td>
|
|
<td class="text-center"><?= $beneficiaire['sexe'] ?></td>
|
|
<td><?= (est_anglophone()) ? $beneficiaire['LienParenteEng'] : $beneficiaire['LienParente'] ?></td>
|
|
<td class="text-center"><?= $beneficiaire['age'] ?> ans</td>
|
|
<td class="text-end"><?= format_N($beneficiaire['primeHt']) ?></td>
|
|
<td class="text-end fw-bold"><?= format_N($beneficiaire['primeTtc']) ?></td>
|
|
<td class="text-center">
|
|
<span class="badge <?= ($beneficiaire['codeEtatBeneficiaire'] == 'V') ? 'bg-success' : 'bg-danger' ?>">
|
|
<?= $beneficiaire['codeEtatBeneficiaire'] ?>
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
<tfoot class="table-light fw-bold text-end">
|
|
<tr>
|
|
<td colspan="6" class="text-center"><?= _("TOTAL FAMILLE") ?></td>
|
|
<td><?= format_N($totalbeneficiaires['primeHt']) ?></td>
|
|
<td class="text-primary"><?= format_N($totalbeneficiaires['primeTtc']) ?></td>
|
|
<td></td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card shadow-sm border-warning">
|
|
<div class="card-header bg-warning text-dark fw-bold">
|
|
<i class="fas fa-shield-alt me-2"></i><?= _("Limites et Garanties de la famille") ?>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
<div class="table-responsive">
|
|
<table class="table table-sm table-hover align-middle mb-0">
|
|
<thead class="bg-light">
|
|
<tr class="small text-uppercase">
|
|
<th class="ps-3"><?= _("Garantie") ?></th>
|
|
<th class="text-center"><?= _("Plafond") ?></th>
|
|
<th class="text-center"><?= _("Conso.") ?></th>
|
|
<th class="text-center"><?= _("Solde") ?></th>
|
|
<th class="text-center"><?= _("Par tête") ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($garantieadherents as $garantieadherent): ?>
|
|
<tr>
|
|
<td class="ps-3 fw-bold"><?= $this->nettoyer($garantieadherent['garantie']) ?></td>
|
|
<td class="text-center fw-bold"><?= format_N($garantieadherent['plafond']) ?></td>
|
|
<td class="text-center text-danger"><?= ($garantieadherent['champApplication'] != '1') ? format_N($garantieadherent['consommation']) : '-' ?></td>
|
|
<td class="text-center fw-bold text-success"><?= ($garantieadherent['champApplication'] != '1') ? format_N($garantieadherent['solde']) : '-' ?></td>
|
|
<td class="text-center text-primary">
|
|
<i class="fas <?= ($garantieadherent['champApplication'] == '1') ? 'fa-check-circle' : 'fa-minus text-muted' ?>"></i>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
<!-- Responsive Area Chart -->
|
|
<div class="row mt-4">
|
|
<div class="col-xl-8 col-lg-7 mb-4">
|
|
<div class="card shadow h-100">
|
|
<div class="card-header py-3 d-flex flex-column flex-md-row justify-content-between align-items-center">
|
|
<h6 class="m-0 font-weight-bold text-primary"><?= _("Dépenses mensuelles") ?></h6>
|
|
<div class="mt-2 mt-md-0">
|
|
<button id="exportTrendBtn" class="btn btn-sm btn-danger mr-2">
|
|
<i class="fas fa-download"></i> PDF
|
|
</button>
|
|
<small class="text-muted"><?= _("Évolution sur 12 mois") ?></small>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="chart-container" style="position: relative; height:300px; width:100%">
|
|
<canvas id="expenseTrendChart"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Responsive Pie Chart -->
|
|
<div class="col-xl-4 col-lg-5 mb-4">
|
|
<div class="card shadow h-100">
|
|
<div class="card-header py-3 d-flex justify-content-between align-items-center">
|
|
<h6 class="m-0 font-weight-bold text-primary"><?= _("Dépenses par lien parenté") ?></h6>
|
|
<button id="exportPieBtn" class="btn btn-sm btn-danger">
|
|
<i class="fas fa-download"></i> PDF
|
|
</button>
|
|
</div>
|
|
<div class="card-body d-flex flex-column">
|
|
<div class="chart-container" style="position: relative; height:250px; width:100%">
|
|
<canvas id="expenseDistributionChart"></canvas>
|
|
</div>
|
|
<div id="pieChartLegend" class="mt-3 text-center"></div>
|
|
<div class="mt-auto pt-3">
|
|
<small class="text-muted"><?= _("Répartition en pourcentage") ?></small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Bar Chart Section -->
|
|
<div class="row mt-4">
|
|
<div class="col-12 mb-4">
|
|
<div class="card shadow h-100">
|
|
<div class="card-header py-3 d-flex justify-content-between align-items-center">
|
|
<h6 class="m-0 font-weight-bold text-primary"><?= _("Dépenses par garantie") ?></h6>
|
|
<button id="exportBarBtn" class="btn btn-sm btn-danger">
|
|
<i class="fas fa-download"></i> PDF
|
|
</button>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="chart-container" style="position: relative; height:400px; width:100%">
|
|
<canvas id="depensesChart"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.pointer-cursor { cursor: pointer; transition: background 0.2s; }
|
|
.pointer-cursor:hover { background-color: #f1f8ff !important; }
|
|
.sticky-top { top: -1px; z-index: 10; }
|
|
.table-responsive { border-radius: 0.375rem; }
|
|
.input-group-text { background-color: #f8f9fa; color: #6c757d; }
|
|
input[readonly] { cursor: default; }
|
|
</style>
|
|
|
|
<script>
|
|
// Configuration commune
|
|
(function() {
|
|
// Récupération de la devise depuis PHP
|
|
const userCurrency = '<?= isset($_SESSION['devise_C']) ? $_SESSION['devise_C'] : 'FRW' ?>';
|
|
|
|
// Configuration des devises
|
|
const currencyFormats = {
|
|
'FRW': {
|
|
symbol: 'FRW',
|
|
format: (value) => new Intl.NumberFormat('fr-FR').format(value) + ' FRW'
|
|
},
|
|
'€': {
|
|
symbol: '€',
|
|
format: (value) => new Intl.NumberFormat('fr-FR', {style: 'currency', currency: 'EUR'}).format(value)
|
|
},
|
|
'$': {
|
|
symbol: '$',
|
|
format: (value) => new Intl.NumberFormat('fr-FR', {style: 'currency', currency: 'USD'}).format(value)
|
|
},
|
|
'XOF': {
|
|
symbol: 'FRW',
|
|
format: (value) => new Intl.NumberFormat('fr-FR').format(value) + ' FRW'
|
|
}
|
|
};
|
|
|
|
// Format monétaire dynamique
|
|
const formatMoney = (value) => {
|
|
const currencyConfig = currencyFormats[userCurrency] || currencyFormats['FRW'];
|
|
return currencyConfig.format(value);
|
|
};
|
|
|
|
// Format pourcentage sécurisé
|
|
const formatPercentage = (value, total) => {
|
|
if (total === 0) {
|
|
return '0%'; // ou éventuellement 'N/A' selon ton besoin
|
|
}
|
|
const percentage = (value * 100 / total).toFixed(1);
|
|
return percentage + '%';
|
|
};
|
|
|
|
// Détection mobile
|
|
const isMobile = window.matchMedia("(max-width: 768px)").matches;
|
|
|
|
// Génération des couleurs
|
|
const generateColors = (count) => {
|
|
const palette = [
|
|
'#4e73df', '#1cc88a', '#36b9cc', '#f6c23e',
|
|
'#e74a3b', '#858796', '#5a5c69', '#3a3b45',
|
|
'#2e59a9', '#17a673', '#2c9faf', '#dda20a'
|
|
];
|
|
return palette.slice(0, count).concat(
|
|
Array.from({length: Math.max(0, count - palette.length)}, (_, i) => {
|
|
const hue = Math.floor(360 * (i / Math.max(1, count - palette.length)));
|
|
return `hsl(${hue}, 70%, 60%)`;
|
|
})
|
|
);
|
|
};
|
|
|
|
// Fonction pour générer une légende personnalisée
|
|
function generateCustomLegend(chart, containerId) {
|
|
const legendContainer = document.getElementById(containerId);
|
|
legendContainer.innerHTML = '';
|
|
|
|
const items = chart.data.datasets[0].data.map((value, i) => {
|
|
const total = chart.data.datasets[0].data.reduce((a, b) => a + b, 0);
|
|
const percentage = formatPercentage(value, total);
|
|
|
|
return `
|
|
<div class="d-inline-block mx-2 my-1">
|
|
<span class="legend-color" style="
|
|
display: inline-block;
|
|
width: 12px;
|
|
height: 12px;
|
|
background-color: ${chart.data.datasets[0].backgroundColor[i]};
|
|
border: 1px solid #fff;
|
|
vertical-align: middle;
|
|
"></span>
|
|
<span class="legend-text small ml-1">
|
|
${chart.data.labels[i]}: ${formatMoney(value)} (${percentage})
|
|
</span>
|
|
</div>
|
|
`;
|
|
});
|
|
|
|
legendContainer.innerHTML = items.join('');
|
|
}
|
|
|
|
// Fonction pour exporter un graphique en PDF
|
|
function exportChartToPDF(chartId, fileName) {
|
|
const { jsPDF } = window.jspdf;
|
|
const canvas = document.getElementById(chartId);
|
|
|
|
html2canvas(canvas).then(canvasImage => {
|
|
const imgData = canvasImage.toDataURL('image/png');
|
|
const pdf = new jsPDF({
|
|
orientation: canvasImage.width > canvasImage.height ? 'landscape' : 'portrait'
|
|
});
|
|
|
|
const pageWidth = pdf.internal.pageSize.getWidth();
|
|
const pageHeight = pdf.internal.pageSize.getHeight();
|
|
|
|
const ratio = canvasImage.height / canvasImage.width;
|
|
let imgWidth = pageWidth - 20;
|
|
let imgHeight = imgWidth * ratio;
|
|
|
|
if (imgHeight > pageHeight - 20) {
|
|
imgHeight = pageHeight - 20;
|
|
imgWidth = imgHeight / ratio;
|
|
}
|
|
|
|
pdf.addImage(imgData, 'PNG',
|
|
(pageWidth - imgWidth) / 2,
|
|
(pageHeight - imgHeight) / 2,
|
|
imgWidth,
|
|
imgHeight
|
|
);
|
|
|
|
pdf.save(fileName + '.pdf');
|
|
});
|
|
}
|
|
|
|
// Graphique d'évolution des dépenses
|
|
const dataMois = <?= $dataConsoParMois ?>;
|
|
const trendCtx = document.getElementById('expenseTrendChart').getContext('2d');
|
|
const trendChart = new Chart(trendCtx, {
|
|
type: 'line',
|
|
data: {
|
|
labels: dataMois.mois,
|
|
datasets: [{
|
|
label: '<?= _("Montant dépensé") ?>',
|
|
data: dataMois.consos,
|
|
backgroundColor: 'rgba(78, 115, 223, 0.05)',
|
|
borderColor: 'rgba(78, 115, 223, 1)',
|
|
borderWidth: 2,
|
|
pointBackgroundColor: 'rgba(78, 115, 223, 1)',
|
|
pointRadius: isMobile ? 3 : 4,
|
|
pointHoverRadius: 6,
|
|
fill: true,
|
|
tension: 0.3
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
legend: {
|
|
display: false
|
|
},
|
|
tooltip: {
|
|
mode: 'index',
|
|
intersect: false,
|
|
callbacks: {
|
|
label: function(context) {
|
|
return context.dataset.label + ': ' + formatMoney(context.parsed.y);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
scales: {
|
|
x: {
|
|
grid: {
|
|
display: false
|
|
},
|
|
ticks: {
|
|
maxRotation: isMobile ? 45 : 0,
|
|
autoSkip: true,
|
|
maxTicksLimit: isMobile ? 6 : 12
|
|
}
|
|
},
|
|
y: {
|
|
beginAtZero: false,
|
|
ticks: {
|
|
callback: function(value) {
|
|
return formatMoney(value);
|
|
}
|
|
},
|
|
grid: {
|
|
color: 'rgba(0, 0, 0, 0.05)'
|
|
}
|
|
}
|
|
},
|
|
interaction: {
|
|
mode: 'nearest',
|
|
axis: 'x',
|
|
intersect: false
|
|
}
|
|
}
|
|
});
|
|
|
|
// Graphique de répartition
|
|
const dataLiens = <?= $dataConsoParLiens ?>;
|
|
const distributionCtx = document.getElementById('expenseDistributionChart').getContext('2d');
|
|
const distributionChart = new Chart(distributionCtx, {
|
|
type: 'pie',
|
|
data: {
|
|
labels: dataLiens.lienparente,
|
|
datasets: [{
|
|
data: dataLiens.consos_liens,
|
|
backgroundColor: generateColors(<?= $nbreLienParente; ?>),
|
|
borderColor: '#fff',
|
|
borderWidth: 2
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
legend: {
|
|
display: false,
|
|
},
|
|
datalabels: {
|
|
formatter: (value, ctx) => {
|
|
const sum = ctx.chart.data.datasets[0].data.reduce((a, b) => a + b, 0);
|
|
return formatPercentage(value, sum);
|
|
},
|
|
color: '#fff',
|
|
font: {
|
|
weight: 'bold',
|
|
size: isMobile ? 10 : 12
|
|
}
|
|
},
|
|
tooltip: {
|
|
callbacks: {
|
|
label: function(context) {
|
|
const label = context.label || '';
|
|
const value = context.raw || 0;
|
|
const sum = context.dataset.data.reduce((a, b) => a + b, 0);
|
|
const percentage = formatPercentage(value, sum);
|
|
return `${label}: ${formatMoney(value)} (${percentage})`;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
cutout: isMobile ? '60%' : '50%'
|
|
},
|
|
plugins: [ChartDataLabels]
|
|
});
|
|
|
|
// Graphique des dépenses par garantie
|
|
const dataConso = <?= $dataConsoParGaranties ?>;
|
|
const barCtx = document.getElementById('depensesChart').getContext('2d');
|
|
const barChart = new Chart(barCtx, {
|
|
type: 'bar',
|
|
data: {
|
|
labels: dataConso.garanties,
|
|
datasets: [{
|
|
label: 'Dépenses',
|
|
data: dataConso.depenses,
|
|
backgroundColor: 'rgba(54, 162, 235, 0.7)',
|
|
borderColor: 'rgba(54, 162, 235, 1)',
|
|
borderWidth: 1
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
annotation: {
|
|
annotations: dataConso.plafonds.map((plafond, index) => {
|
|
if (plafond === null) return null;
|
|
|
|
return {
|
|
type: 'line',
|
|
yMin: plafond,
|
|
yMax: plafond,
|
|
borderColor: 'rgba(255, 99, 132, 0.7)',
|
|
borderWidth: 2,
|
|
borderDash: [6, 6],
|
|
label: {
|
|
content: `Plafond: ${formatMoney(plafond)}`,
|
|
enabled: true,
|
|
position: 'right'
|
|
}
|
|
};
|
|
}).filter(annotation => annotation !== null)
|
|
},
|
|
legend: {
|
|
display: false
|
|
},
|
|
tooltip: {
|
|
callbacks: {
|
|
label: function(context) {
|
|
const plafond = dataConso.plafonds[context.dataIndex];
|
|
let tooltip = `Dépenses: ${formatMoney(context.parsed.y)}`;
|
|
|
|
if (plafond !== null) {
|
|
const pourcentage = Math.min(100, Math.round((context.parsed.y / plafond) * 100));
|
|
tooltip += ` (${pourcentage}% du plafond)`;
|
|
} else {
|
|
tooltip += ' (plafond illimité)';
|
|
}
|
|
|
|
return tooltip;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
scales: {
|
|
y: {
|
|
beginAtZero: true,
|
|
title: {
|
|
display: true,
|
|
text: `Montant des dépenses (${userCurrency})`,
|
|
font: {
|
|
weight: 'bold'
|
|
}
|
|
},
|
|
ticks: {
|
|
callback: function(value) {
|
|
return formatMoney(value);
|
|
}
|
|
},
|
|
suggestedMax: Math.max(...dataConso.depenses) * 1.5
|
|
},
|
|
x: {
|
|
title: {
|
|
display: true,
|
|
text: 'Garanties',
|
|
font: {
|
|
weight: 'bold'
|
|
}
|
|
},
|
|
grid: {
|
|
display: false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// Générer la légende au chargement et lors du redimensionnement
|
|
generateCustomLegend(distributionChart, 'pieChartLegend');
|
|
window.addEventListener('resize', function() {
|
|
generateCustomLegend(distributionChart, 'pieChartLegend');
|
|
});
|
|
|
|
// Boutons d'export PDF
|
|
document.getElementById('exportTrendBtn').addEventListener('click', () => {
|
|
exportChartToPDF('expenseTrendChart', 'evolution_depenses_mensuelles');
|
|
});
|
|
|
|
document.getElementById('exportPieBtn').addEventListener('click', () => {
|
|
exportChartToPDF('expenseDistributionChart', 'repartition_depenses_parente');
|
|
});
|
|
|
|
document.getElementById('exportBarBtn').addEventListener('click', () => {
|
|
exportChartToPDF('depensesChart', 'depenses_par_garantie');
|
|
});
|
|
})();
|
|
</script>
|