702 lines
26 KiB
PHP
702 lines
26 KiB
PHP
<?php
|
||
// $this->titre = "INTER-SANTE - Fiche Bénéficiaire";
|
||
|
||
$datejour = $this->datejour;
|
||
$estcouvert = ($_SESSION['dateEcheancePolice_C']>=$datejour);
|
||
|
||
$sorti = $this->nettoyer($beneficiaire['sorti']);
|
||
$dateSortieBeneficiaire = $this->nettoyer($beneficiaire['dateSortieBeneficiaire']);
|
||
|
||
$estsorti = false;
|
||
// if($dateSortieBeneficiaire>"2000-01-01")
|
||
if($sorti=="1")
|
||
{
|
||
$estsorti = ($dateSortieBeneficiaire<=$datejour);
|
||
$estcouvert = ($estcouvert && ($dateSortieBeneficiaire>$datejour));
|
||
}
|
||
|
||
$dateEffetCouvert = $_SESSION['dateEffetCouvert'];
|
||
|
||
if (est_anglophone())
|
||
{
|
||
$produit = $beneficiaire['produitEng'];
|
||
$naturepiece = $beneficiaire['naturepieceEng'];
|
||
$lienparente = $beneficiaire['lienparenteEng'];
|
||
$motifsortie = $beneficiaire['motifsortieEng'];
|
||
$etatbeneficiaire = $beneficiaire['etatbeneficiaireEng'];
|
||
}
|
||
else
|
||
{
|
||
$produit = $beneficiaire['produit'];
|
||
$naturepiece = $beneficiaire['naturepiece'];
|
||
$lienparente = $beneficiaire['lienparente'];
|
||
$motifsortie = $beneficiaire['motifsortie'];
|
||
$etatbeneficiaire = $beneficiaire['etatbeneficiaire'];
|
||
}
|
||
|
||
$controlerPlafondAdherent = ($_SESSION['controlerPlafondAdherent']>0);
|
||
$controlerPlafondBeneficiaire = ($_SESSION['controlerPlafondBeneficiaire']>0);
|
||
|
||
$codeTypeContrat = $_SESSION['codeTypeContrat'];
|
||
|
||
$idApporteur = $this->nettoyer($beneficiaire['idApporteur']);
|
||
$libelleApporteur = $this->nettoyer($beneficiaire['libelleApporteur']);
|
||
$typeecheancier = $this->nettoyer($beneficiaire['typeecheancier']);
|
||
if (est_anglophone())
|
||
{
|
||
$typeecheancier = $this->nettoyer($beneficiaire['typeecheancierEng']);
|
||
}
|
||
$tauxInteretEcheancier = $this->nettoyer($beneficiaire['tauxInteretEcheancier']);
|
||
|
||
$photoAssureCrypte = $_SESSION['photoAssureCrypte'];
|
||
|
||
$faceRegistered = $this->nettoyer($beneficiaire['faceRegistered']);
|
||
$face_confirmee = $_SESSION['okId_face'];
|
||
$fingerActif = $_SESSION['fingerActif'];
|
||
$faceActif = $_SESSION['faceActif'];
|
||
|
||
?>
|
||
|
||
<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="<?= $beneficiaire['primeArchive'] ?>" >
|
||
<INPUT class="sr-only" TYPE="text" id="finger_id_C" name="finger_id_C" value="<?= $_SESSION['finger_id_C'] ?>">
|
||
<INPUT class="sr-only" TYPE="text" id="faceRegistered" name="faceRegistered" value="<?= $faceRegistered ?>">
|
||
|
||
<button class="sr-only" id="btn_pop_save_face" name="btn_pop_save_face" type="button" data-bs-toggle="modal" data-bs-target="#pop_rec_faciale" > </button>
|
||
|
||
<div id="div_urlFace">
|
||
<input class="sr-only" type="text" id="urlFace" name="urlFace" value="">
|
||
</div>
|
||
|
||
<div id="div_wait_face">
|
||
|
||
</div>
|
||
|
||
|
||
<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 bénéficiaire') ?></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="formfichebeneficiaire" id="formfichebeneficiaire" method="POST" class="container-fluid py-3">
|
||
<div class="d-flex flex-wrap justify-content-between align-items-center mb-4 bg-white p-4 rounded shadow-sm border-start border-primary border-5">
|
||
<div class="d-flex align-items-center mb-2 mb-lg-0">
|
||
<div class="bg-primary-subtle text-primary rounded-circle p-3 me-3 d-none d-md-flex">
|
||
<i class="fa-solid fa-user-gear fa-2x"></i>
|
||
</div>
|
||
<div>
|
||
<h4 class="h4 mb-1 text-dark fw-bold">
|
||
<?= _("Bénéficiaire") ?> : <span class="text-primary"><?= $beneficiaire['numeroBeneficiaire'] ?></span>
|
||
</h4>
|
||
<div class="d-flex align-items-center text-muted small">
|
||
<i class="fa-regular fa-calendar-check me-2"></i>
|
||
<?= _("Date Effet") ?> : <span class="fw-bold ms-1"><?= dateLang($this->nettoyer($beneficiaire['dateEffet']), $_SESSION['lang']) ?></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="flex-grow-1 px-lg-4 my-3 my-lg-0" style="max-width: 600px;">
|
||
<?php if($nombreGed > 0): ?>
|
||
<div class="alert alert-success d-flex align-items-center m-0 py-2 px-3 border-0 shadow-sm" style="border-radius: 12px; background-color: #e8f5e9;">
|
||
<i class="fas fa-check-circle fa-2x text-success me-3"></i>
|
||
<div class="flex-grow-1">
|
||
<h6 class="mb-0 fw-bold small text-success">
|
||
<?= est_anglophone() ? 'Verified Folder' : 'Dossier Vérifié'; ?>
|
||
</h6>
|
||
<small class="d-block text-dark opacity-75" style="font-size: 8.5pt;">
|
||
<?= est_anglophone() ? 'Identity documents are up to date.' : 'Les documents d’identité sont à jour.'; ?>
|
||
</small>
|
||
</div>
|
||
<a href="Gedbeneficiaireprod/" class="btn btn-success btn-sm rounded-pill px-3 ms-2">
|
||
<i class="fas fa-eye me-1"></i>
|
||
</a>
|
||
</div>
|
||
<?php else: ?>
|
||
<div class="alert alert-danger d-flex align-items-center m-0 py-2 px-3 border-0 shadow-sm animate__animated animate__pulse animate__infinite" style="border-radius: 12px; background-color: #ffebee;">
|
||
<i class="fas fa-exclamation-circle fa-2x text-danger me-3"></i>
|
||
<div class="flex-grow-1">
|
||
<h6 class="mb-0 fw-bold small text-danger">
|
||
<?= est_anglophone() ? 'Incomplete File' : 'Dossier Incomplet'; ?>
|
||
</h6>
|
||
<small class="d-block text-dark fw-bold" style="font-size: 8.5pt;">
|
||
<?= est_anglophone() ? 'Missing ID documents.' : 'Pièces d’identité manquantes.'; ?>
|
||
</small>
|
||
</div>
|
||
<a href="Gedbeneficiaireprod/" class="btn btn-danger btn-sm rounded-pill px-3 ms-2 shadow-sm">
|
||
<i class="fas fa-upload me-1"></i>
|
||
</a>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<div class="text-end">
|
||
<?php
|
||
$statusClass = "bg-danger"; $statusIcon = "fa-circle-xmark"; $statusText = _("Inconnu");
|
||
if ($dateEffetCouvert == "0") {
|
||
$statusText = _("Non renouvelé");
|
||
$statusIcon = "fa-calendar-minus";
|
||
}
|
||
elseif ($estcouvert) {
|
||
if ($beneficiaire['codeEtatBeneficiaire'] == "V") {
|
||
$statusClass = "bg-success";
|
||
$statusIcon = "fa-shield-check";
|
||
$statusText = $etatbeneficiaire;
|
||
}
|
||
else {
|
||
$statusText = $etatbeneficiaire;
|
||
$statusIcon = "fa-circle-exclamation";
|
||
}
|
||
} elseif ($estsorti) {
|
||
$statusText = _("Retiré");
|
||
$statusIcon = "fa-user-slash";
|
||
}
|
||
else {
|
||
$statusText = _("Expiré");
|
||
$statusIcon = "fa-clock-rotate-left";
|
||
}
|
||
?>
|
||
<div class="small text-muted text-uppercase fw-bold mb-1" style="font-size: 7pt; letter-spacing: 1px;"><?= _("Statut Couverture") ?></div>
|
||
<span class="badge <?= $statusClass ?> fs-6 shadow-sm p-2 px-4 rounded-pill d-inline-flex align-items-center">
|
||
<i class="fa-solid <?= $statusIcon ?> me-2"></i> <?= $statusText ?>
|
||
</span>
|
||
</div>
|
||
</div>
|
||
<div class="row g-4">
|
||
<div class="col-lg-8">
|
||
<div class="card shadow-sm h-100">
|
||
<div class="card-header bg-white fw-bold"><i class="fa-solid fa-user me-2"></i><?= _("Informations Personnelles") ?></div>
|
||
<div class="card-body">
|
||
<div class="row g-3">
|
||
<div class="col-md-6">
|
||
<label class="form-label small text-uppercase fw-bold"><?= _("Nom & Prénoms") ?></label>
|
||
<input class="form-control bg-light fw-bold" type="text" value="<?= $beneficiaire['nomBeneficiaire'] . ' ' . $beneficiaire['prenomsBeneficiaire'] ?>" readonly>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label class="form-label small text-uppercase fw-bold"><?= _("Genre") ?></label>
|
||
<input class="form-control bg-light text-center" type="text" value="<?= $beneficiaire['sexe'] ?>" readonly>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label class="form-label small text-uppercase fw-bold"><?= _("Groupe Sanguin") ?></label>
|
||
<input class="form-control bg-light text-center fw-bold text-danger" type="text" value="<?= $beneficiaire['codeGroupeSanguin'] ?>" readonly>
|
||
</div>
|
||
|
||
<div class="col-md-4">
|
||
<label class="form-label small text-uppercase fw-bold"><?= _("Naissance & Âge") ?></label>
|
||
<input class="form-control bg-light" type="text" value="<?= dateLang($this->nettoyer($beneficiaire['dateNaissance']), $_SESSION['lang']).' ('.$beneficiaire['age'].' ans)' ?>" readonly>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label class="form-label small text-uppercase fw-bold"><?= _("Lien Parenté") ?></label>
|
||
<input class="form-control bg-light" type="text" value="<?= $lienparente ?>" readonly>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label class="form-label small text-uppercase fw-bold"><?= _("Téléphone") ?></label>
|
||
<input class="form-control bg-light" type="tel" value="<?= $beneficiaire['telephonePortable'] ?>" readonly>
|
||
</div>
|
||
|
||
<div class="col-md-6">
|
||
<label class="form-label small text-uppercase fw-bold"><?= _("Pièce d'identité") ?></label>
|
||
<div class="input-group">
|
||
<span class="input-group-text small"><?= $naturepiece ?></span>
|
||
<input class="form-control bg-light" type="text" value="<?= $beneficiaire['numeroPiece'] ?>" readonly>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label class="form-label small text-uppercase fw-bold"><?= _("Collège / Produit") ?></label>
|
||
<input class="form-control bg-light text-primary fw-bold" type="text" value="<?= $beneficiaire['libelleCollege'] ?>" readonly>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col-lg-4">
|
||
<div class="card shadow-sm border-0 mb-3">
|
||
<div class="card-body text-center p-4">
|
||
<div class="position-relative d-inline-block mb-3">
|
||
<?php if($faceRegistered == "1"): ?>
|
||
<img src="<?=$photoAssureCrypte?>" class="img-thumbnail rounded-circle shadow" style="width: 150px; height: 150px; object-fit: cover;">
|
||
<button type="button" onClick="ebene_init_confirm_photo_face();" class="btn btn-sm btn-success position-absolute bottom-0 end-0 rounded-circle">
|
||
<i class="fa-solid fa-check"></i>
|
||
</button>
|
||
<?php else: ?>
|
||
<div class="rounded-circle bg-secondary d-flex align-items-center justify-content-center shadow" style="width: 150px; height: 150px;">
|
||
<i class="fa-solid fa-user-slash fa-4x text-white-50"></i>
|
||
</div>
|
||
<button type="button" onClick="ebene_init_photo_face();" class="btn btn-sm btn-primary position-absolute bottom-0 end-0 rounded-circle">
|
||
<i class="fa-solid fa-camera"></i>
|
||
</button>
|
||
<?php endif; ?>
|
||
</div>
|
||
<h5 class="mb-1 fw-bold"><?= $beneficiaire['numeroAdherent'] ?></h5>
|
||
<p class="text-muted small"><?= _("N° Famille") ?></p>
|
||
|
||
<div class="d-grid gap-2 mt-3">
|
||
<?php if($codeTypeContrat=="F"): ?>
|
||
<button type="button" class="btn btn-outline-info btn-sm" onClick="agent_commercial(<?= $idApporteur ?>);">
|
||
<i class="fa-solid fa-user-tie me-1"></i> <?= $libelleApporteur ?>
|
||
</button>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<?php if ($estsorti): ?>
|
||
<div class="alert alert-warning border-0 shadow-sm d-flex align-items-center">
|
||
<i class="fa-solid fa-door-open fa-2x me-3"></i>
|
||
<div>
|
||
<div class="fw-bold"><?= _("Sortie le") ?> : <?= dateLang($dateSortieBeneficiaire, $_SESSION['lang']) ?></div>
|
||
<small><?= $motifsortie ?></small>
|
||
</div>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="row mt-4 g-3">
|
||
<?php if($controlerPlafondAdherent): ?>
|
||
<div class="col-md-6">
|
||
<div class="card border-0 shadow-sm">
|
||
<div class="card-header bg-primary text-white py-2 fw-bold small text-uppercase"><?= _("Plafond Famille") ?></div>
|
||
<div class="card-body p-0">
|
||
<div class="d-flex text-center border-bottom">
|
||
<div class="flex-fill p-2 border-end">
|
||
<small class="text-muted d-block"><?= _("Limite") ?></small>
|
||
<span class="fw-bold text-primary"><?= format_N($limite_adherent['plafondAdherent']) ?></span>
|
||
</div>
|
||
<div class="flex-fill p-2 border-end">
|
||
<small class="text-muted d-block"><?= _("Conso.") ?></small>
|
||
<span class="fw-bold text-danger"><?= format_N($limite_adherent['consommationAdherent']) ?></span>
|
||
</div>
|
||
<div class="flex-fill p-2 bg-light">
|
||
<small class="text-muted d-block"><?= _("Solde") ?></small>
|
||
<span class="fw-bold text-success"><?= format_N($limite_adherent['soldeAdherent']) ?></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if($controlerPlafondBeneficiaire): ?>
|
||
<div class="col-md-6">
|
||
<div class="card border-0 shadow-sm">
|
||
<div class="card-header bg-dark text-white py-2 fw-bold small text-uppercase"><?= _("Plafond Individuel") ?></div>
|
||
<div class="card-body p-0">
|
||
<div class="d-flex text-center border-bottom">
|
||
<div class="flex-fill p-2 border-end">
|
||
<small class="text-muted d-block"><?= _("Limite") ?></small>
|
||
<span class="fw-bold text-primary"><?= format_N($limite_beneficiaire['plafondBeneficiaire']) ?></span>
|
||
</div>
|
||
<div class="flex-fill p-2 border-end">
|
||
<small class="text-muted d-block"><?= _("Conso.") ?></small>
|
||
<span class="fw-bold text-danger"><?= format_N($limite_beneficiaire['consommationBeneficiaire']) ?></span>
|
||
</div>
|
||
<div class="flex-fill p-2 bg-light">
|
||
<small class="text-muted d-block"><?= _("Solde") ?></small>
|
||
<span class="fw-bold text-success"><?= format_N($limite_beneficiaire['soldeBeneficiaire']) ?></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<div class="card mt-1 shadow-sm">
|
||
<div class="card-header fw-bold d-flex justify-content-between">
|
||
<span><i class="fa-solid fa-shield-halved me-2"></i><?= _("Détail des Garanties") ?></span>
|
||
</div>
|
||
<div class="table-responsive">
|
||
<table class="table table-hover align-middle mb-0" style="font-size: 0.9rem;">
|
||
<thead class="table-light">
|
||
<tr>
|
||
<th class="text-center"><?= _("Exercice") ?></th>
|
||
<th><?= _("Garantie") ?></th>
|
||
<th class="text-end"><?= _("Limite Contrat") ?></th>
|
||
<th class="text-center">%</th>
|
||
<th class="text-end"><?= _("Limite Vigueur") ?></th>
|
||
<th class="text-end"><?= _("Conso.") ?></th>
|
||
<th class="text-end fw-bold"><?= _("Solde") ?></th>
|
||
<th class="text-center"><?= _("Par tête") ?></th>
|
||
<th><?= _("Parent") ?></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ($garantieadherents as $garantieadherent): ?>
|
||
<tr>
|
||
<td class="text-center"><?= $this->nettoyer($garantieadherent['exercieReference'])?></td>
|
||
<td class="fw-bold"><?= $this->nettoyer($garantieadherent['garantie'])?></td>
|
||
<td class="text-end"><?= format_N($this->nettoyer($garantieadherent['plafondAnnuel'])) ?></td>
|
||
<td class="text-center text-muted"><?= $this->nettoyer($garantieadherent['tauxAvenant']) ?>%</td>
|
||
<td class="text-end"><?= format_N($this->nettoyer($garantieadherent['plafond'])) ?></td>
|
||
<td class="text-end text-danger"><?= format_N($this->nettoyer($garantieadherent['consommation'])) ?></td>
|
||
<td class="text-end fw-bold text-success"><?= format_N($this->nettoyer($garantieadherent['solde'])) ?></td>
|
||
<td class="text-center">
|
||
<input type="checkbox" class="form-check-input" <?= ($this->nettoyer($garantieadherent['champApplication'])=='1') ? 'checked' : '' ?> disabled>
|
||
</td>
|
||
<td class="small text-muted"><?= $this->nettoyer($garantieadherent['garantieparentaffichage'])?></td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
|
||
<div class="container-fluid mt-1">
|
||
<div class="card border-0 shadow-sm">
|
||
<div class="card-body">
|
||
<form enctype="multipart/form-data" action="Fichebeneficiaire/<?= $_SESSION['idBeneficiaire_C'] ?>/" method="post" class="row align-items-center g-3">
|
||
<div class="col-md-5">
|
||
<label class="form-label fw-bold small text-uppercase">
|
||
<?= ($_SESSION['lienPhoto_C'] > " ") ? _("Remplacer la photo") : _("Nouvelle photo") ?>
|
||
</label>
|
||
<input type="hidden" name="MAX_FILE_SIZE" value="500000" /> <input class="form-control form-control-sm" name="fichier_image_a_uploader" type="file" id="fichier_image_a_uploader" />
|
||
</div>
|
||
<div class="col-md-3">
|
||
<button type="submit" name="submit" class="btn btn-primary btn-sm mt-4 w-100">
|
||
<i class="fa-solid fa-cloud-arrow-up me-1"></i> <?= _("Mettre à jour") ?>
|
||
</button>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<?php if ($message > " "): ?>
|
||
<div class="alert <?= ($message == 'Chargement réussi !') ? 'alert-success' : 'alert-danger' ?> m-0 py-2 small">
|
||
<?= $message ?>
|
||
</div>
|
||
<?php else: ?>
|
||
<div class="text-muted small italic">
|
||
<i class="fa-solid fa-file-image me-1"></i>
|
||
<?= _("Fichier actuel") ?> : <?= $beneficiaire['lienPhoto'] ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Responsive Area Chart -->
|
||
<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 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 type="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>
|
||
</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 type="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>
|
||
<?php include 'faceebene/ebenetraitementimage.php'; ?>
|
||
|
||
<script>
|
||
// Configuration commune
|
||
(function() {
|
||
// Format numérique simplifié (sans devise)
|
||
const formatMoney = (value) => {
|
||
return new Intl.NumberFormat('fr-FR').format(value);
|
||
};
|
||
|
||
// Format pourcentage sécurisé
|
||
const formatPercentage = (value, total) => {
|
||
if (total === 0) {
|
||
return '0%'; // ou 'N/A' si tu préfères
|
||
}
|
||
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 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") ?>',
|
||
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
|
||
}
|
||
}
|
||
}
|
||
}
|
||
});
|
||
|
||
|
||
// Boutons d'export PDF
|
||
document.getElementById('exportTrendBtn').addEventListener('click', () => {
|
||
exportChartToPDF('expenseTrendChart', 'evolution_depenses_mensuelles');
|
||
});
|
||
|
||
|
||
document.getElementById('exportBarBtn').addEventListener('click', () => {
|
||
exportChartToPDF('depensesChart', 'depenses_par_garantie');
|
||
});
|
||
})();
|
||
</script>
|