388 lines
26 KiB
PHP
388 lines
26 KiB
PHP
<?php
|
||
$headline = ['handled' => [t('statistics.handled'),'teal'],'entries' => [t('statistics.entries'),'green'],'exits' => [t('statistics.exits'),'red'],'adoptions' => [t('statistics.adoptions'),'blue'],'deaths' => [t('statistics.deaths'),'dark'],'births' => [t('statistics.births'),'purple'],'vaccinations' => [t('statistics.vaccinations'),'cyan'],'treatments' => [t('statistics.treatments'),'orange'],'medical_notes' => [t('statistics.medical_notes'),'pink']];
|
||
$comparisonLabels = ['handled' => t('statistics.handled'),'entries' => t('statistics.entries'),'exits' => t('statistics.exits'),'adoptions' => t('statistics.adoptions'),'deaths' => t('statistics.deaths'),'births' => t('statistics.births'),'vaccinations' => t('statistics.vaccinations'),'treatments' => t('statistics.treatments_started'),'medical_notes' => t('statistics.medical_notes'),'avg' => t('statistics.avg_adoption_days')];
|
||
$intakeTypeLabels = [];
|
||
foreach (['unknown','found','owner_surrender','transfer','born_in_care','return','seizure','other'] as $key) {
|
||
$intakeTypeLabels[$key] = t('statistics.intake.' . $key);
|
||
}
|
||
$intakeReasonLabels = [];
|
||
foreach (['unknown','stray_found','unwanted_litter','owner_health','owner_death','owner_care_home','allergy','housing','financial','behavior','abandonment','danger','transfer','birth','other'] as $key) {
|
||
$intakeReasonLabels[$key] = t('statistics.reason.' . $key);
|
||
}
|
||
$distributionLabels = ['Femelles' => t('statistics.value.females'),'Mâles' => t('statistics.value.males'),'Inconnu' => t('statistics.value.unknown'),'Non renseigné' => t('statistics.value.not_provided'),'Non renseignée' => t('statistics.value.not_provided_f'),'Moins d’un an' => t('statistics.value.under_year'),'1 à 2 ans' => t('statistics.value.one_two_years'),'3 à 7 ans' => t('statistics.value.three_seven_years'),'8 ans et plus' => t('statistics.value.eight_plus'),'Moins d’un mois' => t('statistics.value.under_month'),'1 à 3 mois' => t('statistics.value.one_three_months'),'3 à 6 mois' => t('statistics.value.three_six_months'),'6 à 12 mois' => t('statistics.value.six_twelve_months'),'Plus d’un an' => t('statistics.value.over_year'),'Chats' => t('statistics.value.cats'),'Chiens' => t('statistics.value.dogs'),'Inconnue' => t('statistics.value.unknown_f'),'Refuge' => t('status.refuge'),'Famille d’accueil' => t('status.fa'),'Accueil permanent' => t('statistics.value.permanent_foster'),'Chats libres suivis' => t('statistics.free_cats'),'Quarantaine' => t('status.quarantaine'),'Infirmerie' => t('status.soin'),'Réservé' => t('status.reserve'),'Site non renseigné' => t('statistics.value.unprovided_site')];
|
||
$groups = [
|
||
[t('statistics.intake_modes'),$distributions['intakeTypes'],$intakeTypeLabels,'green'],
|
||
[t('statistics.intake_reasons'),$distributions['intakeReasons'],$intakeReasonLabels,'orange'],
|
||
[t('statistics.colors'),$distributions['colors'],[],'blue'],
|
||
[t('statistics.breeds'),$distributions['breeds'],[],'purple'],
|
||
[t('statistics.species'),$distributions['species'],[],'cyan'],
|
||
[t('statistics.sex'),$distributions['sex'],[],'pink'],
|
||
[t('statistics.age_at_entry'),$distributions['ages'],[],'orange'],
|
||
[t('statistics.origins'),$distributions['origins'],[],'green','municipality'],
|
||
[t('statistics.adoption_delay'),$distributions['stays'],[],'azure'],
|
||
[t('statistics.death_causes'),$distributions['deathCauses'],array_combine(array_keys(DeathController::CAUSES), array_map(static fn ($key) => DeathController::causeLabel($key), array_keys(DeathController::CAUSES))),'dark'],
|
||
[t('statistics.current_distribution'),$distributions['currentStatus'],[],'teal'],
|
||
[t('statistics.free_cat_sites'),$distributions['freeCatSites'] ?? [],[],'green'],
|
||
[$allYears ? t('statistics.releases_year') : t('statistics.releases_site'),$distributions['freeCatReleases'] ?? [],[],'lime'],
|
||
];
|
||
?>
|
||
<style>
|
||
@media print {
|
||
form[action="/statistics"] {
|
||
display: none !important
|
||
}
|
||
|
||
.page-body {
|
||
padding-top: 0
|
||
}
|
||
}
|
||
|
||
</style>
|
||
<div class="card mb-4 overflow-hidden">
|
||
<div class="card-status-top bg-cyan"></div>
|
||
<div class="card-body d-flex flex-wrap align-items-end gap-3">
|
||
<div class="me-auto">
|
||
<div class="subheader"><?= h(t('statistics.memory')) ?></div>
|
||
<h2 class="mb-1">
|
||
<?= $municipality !== '' ? t('statistics.city_report', ['city' => $municipality]) : t('statistics.figures') ?>
|
||
</h2>
|
||
<div class="text-muted"><?= $municipality !== '' ? t('statistics.city_help') : t('statistics.help') ?></div>
|
||
</div>
|
||
<form method="get" action="/statistics" class="d-flex flex-wrap align-items-end gap-2">
|
||
<div><label class="form-label"><?= h(t('statistics.period')) ?></label><select class="form-select"
|
||
name="year">
|
||
<option value="all" <?= $allYears ? 'selected' : '' ?>><?= h(t('statistics.all_years')) ?></option>
|
||
<?php foreach (array_reverse($years) as $y): ?><option value="<?= $y ?>"
|
||
<?= !$allYears && $y === $year ? 'selected' : '' ?>><?= $y ?></option><?php endforeach; ?>
|
||
</select></div>
|
||
<div><label class="form-label"><?= h(t('statistics.origin_city')) ?></label><select class="form-select"
|
||
name="municipality">
|
||
<option value=""><?= h(t('statistics.all_cities')) ?></option>
|
||
<?php foreach (($municipalities ?? []) as $city => $total): ?><option value="<?= h($city) ?>"
|
||
<?= $municipality === $city ? 'selected' : '' ?>><?= h($city) ?> · <?= (int)$total ?></option>
|
||
<?php endforeach; ?>
|
||
</select></div><button
|
||
class="btn btn-cyan"><?= h(t('common.show')) ?></button><?php if ($municipality !== ''): ?><a
|
||
class="btn btn-outline-secondary"
|
||
href="/statistics?year=<?= h($allYears ? 'all' : (string)$year) ?>"><?= h(t('common.clear')) ?></a><button
|
||
class="btn btn-outline-primary" type="button" onclick="window.print()">🖨
|
||
<?= h(t('common.print')) ?></button><?php endif; ?>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<?php if ($municipality !== ''): ?><div class="alert alert-info d-flex flex-wrap align-items-center gap-2">
|
||
<strong><?= h($municipality) ?> ·
|
||
<?= h($allYears ? t('statistics.all_years') : (string)$year) ?></strong><span><?= h(t('statistics.city_filter_summary', ['count' => (int)$stats['handled']])) ?></span><span
|
||
class="ms-auto small"><?= h(t('statistics.filter_applied')) ?></span></div><?php endif; ?>
|
||
<?php if ($municipality === '' && !empty($municipalityCoverage)): ?><div class="alert alert-info mb-4">
|
||
<div class="d-flex flex-wrap align-items-center gap-2">
|
||
<strong><?= h(t('statistics.location_coverage')) ?></strong><span
|
||
class="badge bg-green-lt"><?= h(t('statistics.location_documented', ['count' => $municipalityCoverage['documented']])) ?></span><span
|
||
class="badge bg-azure-lt"><?= h(t('statistics.location_inferred', ['count' => $municipalityCoverage['inferred']])) ?></span><span
|
||
class="badge bg-purple-lt"><?= h(t('statistics.location_born_in_care', ['count' => $municipalityCoverage['born_in_care']])) ?></span><span
|
||
class="badge bg-secondary-lt"><?= h(t('statistics.location_unknown', ['count' => $municipalityCoverage['unknown']])) ?></span>
|
||
</div>
|
||
<div class="small mt-1"><?= h(t('statistics.location_coverage_help')) ?></div>
|
||
</div><?php endif; ?>
|
||
<?php if ($allYears && $undatedDeaths): ?><div class="alert alert-info">
|
||
<?= h(t('statistics.undated_deaths', ['total' => (int)$stats['deaths'],'count' => (int)$undatedDeaths])) ?></div>
|
||
<?php endif; ?>
|
||
<?php if ($allYears): ?><div class="alert alert-info"><strong><?= h(t('statistics.global_memory')) ?></strong>
|
||
<?= h(t('statistics.undated_summary', ['entries' => (int)$undatedHandled,'exits' => (int)$undatedExits,'births' => (int)$undatedBirths,'vaccinations' => (int)$stats['vaccinations'],'vaccinated' => (int)($scopeCounts['vaccinated_animals'] ?? 0),'notes' => (int)$stats['medical_notes'],'medical' => (int)($scopeCounts['medical_animals'] ?? 0)])) ?>
|
||
</div><?php endif; ?>
|
||
|
||
<div class="row row-cards mb-4"><?php foreach ($headline as $key => [$label,$color]): ?><div class="col-6 col-md-3">
|
||
<div class="card h-100">
|
||
<div class="card-status-top bg-<?= $color ?>"></div>
|
||
<div class="card-body">
|
||
<div class="text-muted small text-uppercase"><?= h($label) ?></div>
|
||
<div class="display-6 fw-bold"><?= (int)$stats[$key] ?></div>
|
||
<div class="small text-muted">
|
||
<?= $allYears ? t('statistics.since_start') : t('statistics.in_year', ['year' => (int)$year]) ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><?php endforeach; ?></div>
|
||
|
||
<div class="card mb-4 overflow-hidden">
|
||
<div class="card-status-top bg-orange"></div>
|
||
<div class="card-header">
|
||
<div>
|
||
<h3 class="card-title"><?= h(t('statistics.vet_costs')) ?></h3>
|
||
<div class="text-muted small"><?= h(t('statistics.vet_costs_help')) ?></div>
|
||
</div>
|
||
<div class="ms-auto text-end">
|
||
<div class="h2 mb-0"><?= number_format(($costs['total_cents'] ?? 0) / 100, 2, ',', ' ') ?> €</div>
|
||
<div class="text-muted small">
|
||
<?= h(t('statistics.animals_concerned', ['count' => (int)($costs['animals'] ?? 0)])) ?></div>
|
||
</div>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="row g-3 mb-3">
|
||
<?php foreach ([[t('statistics.cost_scope_animals'),(int)($costs['scope_animals'] ?? 0),null],[t('statistics.cost_with_expense'),(int)($costs['animals'] ?? 0),null],[t('statistics.cost_avg_all'),(int)($costs['average_all_cents'] ?? 0),'money'],[t('statistics.cost_avg_spending'),(int)($costs['average_expense_cents'] ?? 0),'money'],[t('statistics.cost_median'),(int)($costs['median_expense_cents'] ?? 0),'money']] as [$label,$value,$format]): ?>
|
||
<div class="col-6 col-lg">
|
||
<div class="border rounded p-3 h-100">
|
||
<div class="text-muted small"><?= h($label) ?></div>
|
||
<div class="h3 mb-0">
|
||
<?= $format === 'money' ? number_format($value / 100, 2, ',', ' ') . ' €' : $value ?></div>
|
||
</div>
|
||
</div><?php endforeach;?></div>
|
||
<div class="alert alert-info py-2 small"><?= h(t('statistics.cost_metric_help')) ?></div>
|
||
<div class="row g-4">
|
||
<div class="col-md-6">
|
||
<h4 class="mb-1"><?= h(t('statistics.by_structure')) ?></h4>
|
||
<div class="text-muted small mb-2"><?= h(t('statistics.structure_cost_help')) ?></div>
|
||
<?php foreach (($costs['by_clinic'] ?? []) as $r): $structureUrl = !empty($r['contact_id']) ? '/directory/view?' . http_build_query(['id' => (int)$r['contact_id'],'year' => $allYears ? 'all' : $year,'municipality' => $municipality]) : null; ?>
|
||
<div class="d-flex justify-content-between align-items-start gap-3 border-bottom py-2">
|
||
<span><?php if ($structureUrl): ?><a class="fw-semibold" href="<?= h($structureUrl) ?>"
|
||
title="<?= h(t('statistics.open_structure_cost', ['structure' => $r['label']])) ?>"><?= h($r['label']) ?></a><?php else: ?><?= h($r['label']) ?><?php endif; ?><span
|
||
class="d-block text-muted small"><?= h(t('statistics.animals_short', ['count' => (int)$r['animals']])) ?>
|
||
· <?= number_format(((int)$r['average_cents']) / 100, 2, ',', ' ') ?> € /
|
||
<?= h(mb_strtolower(t('statistics.animals'))) ?></span></span><strong
|
||
class="text-nowrap"><?= number_format($r['total_cents'] / 100, 2, ',', ' ') ?> €</strong></div><?php endforeach;
|
||
if (empty($costs['by_clinic'])):?><span class="text-muted"><?= h(t('statistics.no_expense')) ?></span><?php endif;?>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<h4 class="mb-1"><?= h(t('statistics.by_category')) ?></h4>
|
||
<div class="text-muted small mb-2"><?= h(t('statistics.category_cost_help')) ?></div>
|
||
<?php foreach (($costs['by_category'] ?? []) as $r): ?><div
|
||
class="d-flex justify-content-between align-items-start gap-3 border-bottom py-2">
|
||
<span><?= h(PricingService::categoryLabel($r['label'])) ?><span
|
||
class="d-block text-muted small"><?= h(t('statistics.animals_short', ['count' => (int)$r['animals']])) ?>
|
||
· <?= number_format(((int)$r['average_cents']) / 100, 2, ',', ' ') ?> € /
|
||
<?= h(mb_strtolower(t('statistics.animals'))) ?></span></span><strong
|
||
class="text-nowrap"><?= number_format($r['total_cents'] / 100, 2, ',', ' ') ?> €</strong></div>
|
||
<?php endforeach;?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<?php if ($municipality === ''): ?><div class="card mb-4 overflow-hidden">
|
||
<div class="card-status-top bg-green"></div>
|
||
<div class="card-header">
|
||
<div>
|
||
<h3 class="card-title"><?= h(t('statistics.cost_by_city')) ?></h3>
|
||
<div class="text-muted small"><?= h(t('statistics.cost_by_city_help')) ?></div>
|
||
</div>
|
||
</div>
|
||
<div class="table-responsive">
|
||
<table class="table table-vcenter card-table mb-0">
|
||
<thead>
|
||
<tr>
|
||
<th><?= h(t('statistics.municipality')) ?></th>
|
||
<th class="text-end"><?= h(t('statistics.cost_scope_animals')) ?></th>
|
||
<th class="text-end"><?= h(t('statistics.expense_animals')) ?></th>
|
||
<th class="text-end"><?= h(t('statistics.total_cost')) ?></th>
|
||
<th class="text-end"><?= h(t('statistics.average_all')) ?></th>
|
||
<th class="text-end"><?= h(t('statistics.average_with_expense')) ?></th>
|
||
<th class="text-end"><?= h(t('statistics.median')) ?></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach (($municipalityCosts ?? []) as $row): $cityUrl = '/statistics?' . http_build_query(['year' => $allYears ? 'all' : $year,'municipality' => $row['municipality']]); ?>
|
||
<tr>
|
||
<td><a class="fw-semibold" href="<?= h($cityUrl) ?>"
|
||
title="<?= h(t('statistics.cost_city_open', ['city' => $row['municipality']])) ?>"><?= h($row['municipality']) ?></a>
|
||
</td>
|
||
<td class="text-end"><?= (int)$row['animals'] ?></td>
|
||
<td class="text-end"><?= (int)$row['animals_with_expense'] ?></td>
|
||
<td class="text-end fw-bold"><?= number_format($row['total_cents'] / 100, 2, ',', ' ') ?> €</td>
|
||
<td class="text-end"><?= number_format($row['average_all_cents'] / 100, 2, ',', ' ') ?> €</td>
|
||
<td class="text-end"><?= number_format($row['average_expense_cents'] / 100, 2, ',', ' ') ?> €</td>
|
||
<td class="text-end"><?= number_format($row['median_expense_cents'] / 100, 2, ',', ' ') ?> €</td>
|
||
</tr><?php endforeach;?><?php if (empty($municipalityCosts)): ?><tr>
|
||
<td colspan="7" class="text-muted text-center py-4"><?= h(t('statistics.cost_no_city')) ?></td>
|
||
</tr><?php endif;?></tbody>
|
||
</table>
|
||
</div>
|
||
</div><?php endif; ?>
|
||
|
||
<div class="row row-cards mb-4">
|
||
<div class="col-lg-8"><?php if ($allYears): ?><div class="card h-100">
|
||
<div class="card-header">
|
||
<div>
|
||
<h3 class="card-title"><?= h(t('statistics.annual_activity')) ?></h3>
|
||
<div class="text-muted small"><?= h(t('statistics.annual_activity_help')) ?></div>
|
||
</div>
|
||
</div>
|
||
<div class="card-body">
|
||
<div style="height:280px"><canvas id="activityHistoryChart"
|
||
aria-label="<?= h(t('statistics.chart_label')) ?>"></canvas></div><?php if ($undatedHandled): ?>
|
||
<div class="text-muted small mt-3">
|
||
<?= h(t('statistics.undated_handled', ['count' => (int)$undatedHandled])) ?></div><?php endif; ?>
|
||
</div>
|
||
<div class="table-responsive border-top">
|
||
<table class="table table-vcenter mb-0">
|
||
<thead>
|
||
<tr>
|
||
<th><?= h(t('statistics.year')) ?></th>
|
||
<th class="text-end"><?= h(t('statistics.handled')) ?></th>
|
||
<th class="text-end"><?= h(t('statistics.entries')) ?></th>
|
||
<th class="text-end"><?= h(t('statistics.exits')) ?></th>
|
||
<th class="text-end"><?= h(t('statistics.adoptions')) ?></th>
|
||
<th class="text-end"><?= h(t('statistics.deaths')) ?></th>
|
||
<th class="text-end"><?= h(t('statistics.births')) ?></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody><?php foreach (array_reverse($timeline, true) as $timelineYear => $annual): ?><tr>
|
||
<td class="fw-bold"><?= (int)$timelineYear ?></td>
|
||
<?php foreach (['handled','entries','exits','adoptions','deaths','births'] as $key): ?><td
|
||
class="text-end"><?= (int)$annual[$key] ?></td><?php endforeach; ?>
|
||
</tr><?php endforeach; ?><?php if ($undatedHandled): ?><tr class="text-muted">
|
||
<td class="fw-bold"><?= h(t('statistics.unknown_date')) ?></td>
|
||
<td class="text-end"><?= (int)$undatedHandled ?></td>
|
||
<td class="text-end" colspan="5">—</td>
|
||
</tr><?php endif; ?></tbody>
|
||
</table>
|
||
</div>
|
||
</div><?php else: ?><div class="card h-100">
|
||
<div class="card-header">
|
||
<div>
|
||
<h3 class="card-title"><?= h(t('grant.comparison', ['year' => $year - 1])) ?></h3>
|
||
<div class="text-muted small"><?= h(t('statistics.no_previous_percent')) ?></div>
|
||
</div>
|
||
</div>
|
||
<div class="table-responsive">
|
||
<table class="table table-vcenter mb-0">
|
||
<thead>
|
||
<tr>
|
||
<th><?= h(t('grant.indicator')) ?></th>
|
||
<th class="text-end"><?= $year - 1 ?></th>
|
||
<th class="text-end"><?= $year ?></th>
|
||
<th class="text-end"><?= h(t('grant.evolution')) ?></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody><?php foreach ($comparisonLabels as $key => $label): $c = $comparison[$key]; ?><tr>
|
||
<td><?= h($label) ?></td>
|
||
<td class="text-end"><?= (int)round($c['previous']) ?></td>
|
||
<td class="text-end fw-bold"><?= (int)round($c['current']) ?></td>
|
||
<td class="text-end"><span
|
||
class="badge <?= $c['difference'] > 0 ? 'bg-blue-lt' : ($c['difference'] < 0 ? 'bg-orange-lt' : 'bg-secondary-lt') ?>"><?= $c['difference'] > 0 ? '+' : '' ?><?= (int)round($c['difference']) ?><?= $c['percent'] !== null ? ' · ' . ($c['percent'] > 0 ? '+' : '') . number_format($c['percent'], 1, ',', ' ') . ' %' : '' ?></span>
|
||
</td>
|
||
</tr><?php endforeach; ?></tbody>
|
||
</table>
|
||
</div>
|
||
</div><?php endif; ?></div>
|
||
<div class="col-lg-4">
|
||
<div class="card h-100">
|
||
<div class="card-header">
|
||
<div>
|
||
<h3 class="card-title"><?= h(t('statistics.current_snapshot')) ?></h3>
|
||
<div class="text-muted small"><?= h(t('statistics.current_snapshot_help')) ?></div>
|
||
</div>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="display-5 fw-bold mb-3"><?= (int)($health['total'] ?? 0) ?> <span
|
||
class="fs-3 fw-normal text-muted"><?= h(t('statistics.animals')) ?></span></div>
|
||
<?php foreach ([[t('statistics.free_cats'),$health['free_cats'] ?? 0,'lime'],[t('statistics.sterilized'),$health['sterilized'] ?? 0,'green'],[t('statistics.chipped'),$health['chipped'] ?? 0,'blue'],[t('statistics.fiv_positive'),$health['fiv_positive'] ?? 0,'orange'],[t('statistics.felv_positive'),$health['felv_positive'] ?? 0,'red']] as [$label,$total,$color]): $pct = ($health['total'] ?? 0) > 0 ? round($total / $health['total'] * 100) : 0; ?>
|
||
<div class="mb-3">
|
||
<div class="d-flex justify-content-between mb-1">
|
||
<span><?= h($label) ?></span><strong><?= (int)$total ?> · <?= $pct ?> %</strong></div>
|
||
<div class="progress progress-sm">
|
||
<div class="progress-bar bg-<?= $color ?>" style="width:<?= $pct ?>%"></div>
|
||
</div>
|
||
</div><?php endforeach; ?><div class="alert alert-info py-2 mb-0 small">
|
||
<?= h(t('statistics.free_cat_help')) ?></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="d-flex flex-wrap align-items-baseline gap-2 mb-3">
|
||
<h2 class="mb-0"><?= h(t('statistics.profiles')) ?></h2><span
|
||
class="text-muted"><?= h($allYears ? t('statistics.profiles_help_all') : t('statistics.profiles_help_year', ['year' => (int)$year])) ?></span>
|
||
</div>
|
||
<div class="row row-cards"><?php foreach ($groups as $group): [$title,$items,$labels,$color] = $group;
|
||
$linkType = $group[4] ?? null;
|
||
$maximum = $items ? max($items) : 0;
|
||
$sum = array_sum($items); ?><div class="col-md-6 col-xl-4">
|
||
<div class="card h-100">
|
||
<div class="card-header">
|
||
<div>
|
||
<h3 class="card-title"><?= h($title) ?></h3>
|
||
<div class="text-muted small">
|
||
<?= h(t('statistics.observations', ['count' => $sum])) ?><?= $linkType === 'municipality' && $municipality === '' ? ' · ' . t('statistics.click_city') : '' ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="card-body"><?php if (!$items): ?><div class="text-muted">
|
||
<?= h(t('statistics.no_period_data')) ?></div><?php else: ?><div class="vstack gap-3">
|
||
<?php foreach ($items as $label => $total): $display = $labels[$label] ?? $distributionLabels[$label] ?? $label;
|
||
$width = $maximum > 0 ? max(4, round($total / $maximum * 100)) : 0;
|
||
$pct = $sum > 0 ? round($total / $sum * 100) : 0;
|
||
$cityUrl = '/statistics?' . http_build_query(['year' => $allYears ? 'all' : $year,'municipality' => $label]); ?><div>
|
||
<div class="d-flex justify-content-between gap-3 mb-1">
|
||
<?php if ($linkType === 'municipality' && $municipality === ''): ?><a
|
||
class="text-truncate fw-semibold" href="<?= h($cityUrl) ?>"
|
||
title="<?= h(t('statistics.show_city', ['city' => $display])) ?>"><?= h($display) ?></a><?php else: ?><span
|
||
class="text-truncate"
|
||
title="<?= h($display) ?>"><?= h($display) ?></span><?php endif; ?><strong
|
||
class="text-nowrap"><?= (int)$total ?> <span
|
||
class="text-muted fw-normal small"><?= $pct ?> %</span></strong></div>
|
||
<div class="progress progress-sm">
|
||
<div class="progress-bar bg-<?= $color ?>" style="width:<?= $width ?>%"></div>
|
||
</div>
|
||
</div><?php endforeach; ?></div><?php endif; ?></div>
|
||
</div>
|
||
</div><?php endforeach; ?></div>
|
||
<?php if ($allYears): ?><script>
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
const canvas = document.getElementById('activityHistoryChart');
|
||
if (!canvas || typeof Chart === 'undefined') return;
|
||
new Chart(canvas, {
|
||
type: 'line',
|
||
data: {
|
||
labels: <?= json_encode(array_map('strval', array_keys($timeline)),
|
||
JSON_UNESCAPED_UNICODE) ?> ,
|
||
datasets: [{
|
||
label: <?= json_encode(t('statistics.handled'), JSON_UNESCAPED_UNICODE) ?> ,
|
||
data: <?= json_encode(array_values(array_map(static fn($s) => (int) $s[
|
||
'handled'], $timeline))) ?> ,
|
||
borderColor: '#0ca678',
|
||
backgroundColor: 'rgba(12,166,120,.12)',
|
||
tension: .3
|
||
}, {
|
||
label: <?= json_encode(t('statistics.adoptions'),
|
||
JSON_UNESCAPED_UNICODE) ?> ,
|
||
data: <?= json_encode(array_values(array_map(static fn($s) => (int) $s[
|
||
'adoptions'], $timeline))) ?> ,
|
||
borderColor: '#206bc4',
|
||
backgroundColor: 'rgba(32,107,196,.12)',
|
||
tension: .3
|
||
}, {
|
||
label: <?= json_encode(t('statistics.deaths'), JSON_UNESCAPED_UNICODE) ?>
|
||
,
|
||
data: <?= json_encode(array_values(array_map(static fn($s) => (int) $s[
|
||
'deaths'], $timeline))) ?> ,
|
||
borderColor: '#343a40',
|
||
backgroundColor: 'rgba(52,58,64,.10)',
|
||
tension: .3
|
||
}]
|
||
},
|
||
options: {
|
||
responsive: true,
|
||
maintainAspectRatio: false,
|
||
interaction: {
|
||
mode: 'index',
|
||
intersect: false
|
||
},
|
||
plugins: {
|
||
legend: {
|
||
position: 'bottom'
|
||
}
|
||
},
|
||
scales: {
|
||
y: {
|
||
beginAtZero: true,
|
||
ticks: {
|
||
precision: 0
|
||
}
|
||
}
|
||
}
|
||
}
|
||
});
|
||
});
|
||
|
||
</script><?php endif; ?>
|