Publier Globinours 1.0.0-rc.3
This commit is contained in:
parent
ea8c24d622
commit
9a2b4068da
325 changed files with 38230 additions and 20 deletions
591
app/Views/dashboard.php
Normal file
591
app/Views/dashboard.php
Normal file
|
|
@ -0,0 +1,591 @@
|
|||
<?php
|
||||
$stats = $stats ?? [];
|
||||
$activity = $activity ?? [];
|
||||
$quality = $quality ?? [];
|
||||
|
||||
$vaccines_overdue = $vaccines_overdue ?? [];
|
||||
$vaccines_7d = $vaccines_7d ?? [];
|
||||
$vaccines_30d = $vaccines_30d ?? [];
|
||||
|
||||
$treatments = $treatments ?? [];
|
||||
$treatments_overdue = $treatments_overdue ?? [];
|
||||
|
||||
$recent_notes = $recent_notes ?? [];
|
||||
$quarantine = $quarantine ?? [];
|
||||
$careToday = $careToday ?? [];
|
||||
$careAlertsToday = $careAlertsToday ?? [];
|
||||
$grantAlerts = $grantAlerts ?? [];
|
||||
$agendaDue = $agendaDue ?? [];
|
||||
|
||||
function badgeKind(string $kind): string
|
||||
{
|
||||
return match ($kind) {
|
||||
'consult' => 'bg-blue-lt',
|
||||
'controle' => 'bg-green-lt',
|
||||
'symptome' => 'bg-yellow-lt',
|
||||
'diagnostic' => 'bg-purple-lt',
|
||||
'acte' => 'bg-orange-lt',
|
||||
'hosp' => 'bg-red-lt',
|
||||
default => 'bg-secondary-lt',
|
||||
};
|
||||
}
|
||||
|
||||
function badgeStatus(string $status): array
|
||||
{
|
||||
// [class, label]
|
||||
return match ($status) {
|
||||
'refuge' => ['bg-blue-lt',t('status.refuge')],
|
||||
'fa' => ['bg-cyan-lt',t('status.fa')],
|
||||
'fa_permanente' => ['bg-indigo-lt',t('status.fa_permanente')],
|
||||
'quarantaine' => ['bg-yellow-lt',t('status.quarantaine')],
|
||||
'soin' => ['bg-red-lt',t('status.soin')],
|
||||
'isolation' => ['bg-orange-lt',t('status.isolation')],
|
||||
'hospitalise', 'hospitalisé' => ['bg-red-lt',t('status.hospitalise')],
|
||||
'reserve', 'réservé' => ['bg-purple-lt',t('status.reserve')],
|
||||
'adopte', 'adopté' => ['bg-green-lt',t('status.adopte')],
|
||||
'decede', 'décédé' => ['bg-dark-lt',t('status.decede')],
|
||||
'enfui' => ['bg-secondary-lt',t('status.enfui')],
|
||||
default => ['bg-secondary-lt', $status],
|
||||
};
|
||||
}
|
||||
?>
|
||||
<?php
|
||||
$expiredQuarantines = array_filter($quarantine, static fn (array $q): bool => $q['days_left'] !== null && (int)$q['days_left'] <= 0);
|
||||
$weightLosses = array_filter($weight_alerts ?? [], static fn (array $w): bool => (float)$w['pct'] < 0);
|
||||
$urgentCount = count($vaccines_overdue) + count($treatments_overdue) + count($expiredQuarantines) + count($weightLosses) + count($careAlertsToday) + count($agendaDue);
|
||||
$morning = $careToday['morning'] ?? ['expected' => 0,'checked' => 0,'alerts' => 0];
|
||||
$evening = $careToday['evening'] ?? ['expected' => 0,'checked' => 0,'alerts' => 0];
|
||||
?>
|
||||
<div class="card mb-3 overflow-hidden <?= $urgentCount ? 'border-danger' : '' ?>">
|
||||
<div class="card-status-top <?= $urgentCount ? 'bg-red' : 'bg-green' ?>"></div>
|
||||
<div class="card-body">
|
||||
<div class="d-flex flex-wrap align-items-center justify-content-between gap-3 mb-3">
|
||||
<div>
|
||||
<div class="subheader"><?= h(t('dashboard.today_priorities')) ?></div>
|
||||
<h2 class="mb-0">
|
||||
<?= h($urgentCount ? tn('dashboard.watch_point', 'dashboard.watch_points', $urgentCount) : t('dashboard.controlled')) ?>
|
||||
</h2>
|
||||
</div><a class="btn btn-primary" href="/care-round"><?= h(t('dashboard.open_round')) ?></a>
|
||||
</div>
|
||||
<div class="row g-2">
|
||||
<div class="col-6 col-lg"><a href="#medical-priorities"
|
||||
class="card card-sm text-reset text-decoration-none h-100">
|
||||
<div class="card-body">
|
||||
<div class="h2 mb-1 text-danger"><?= $urgentCount ?></div>
|
||||
<div class="text-muted small"><?= h(t('dashboard.active_alerts')) ?></div>
|
||||
</div>
|
||||
</a></div>
|
||||
<div class="col-6 col-lg"><a href="#active-treatments"
|
||||
class="card card-sm text-reset text-decoration-none h-100">
|
||||
<div class="card-body">
|
||||
<div class="h2 mb-1"><?= count($treatments) ?></div>
|
||||
<div class="text-muted small"><?= h(t('dashboard.active_treatments')) ?></div>
|
||||
</div>
|
||||
</a></div>
|
||||
<div class="col-6 col-lg"><a href="/care-round?period=morning"
|
||||
class="card card-sm text-reset text-decoration-none h-100">
|
||||
<div class="card-body">
|
||||
<div class="h2 mb-1"><?= (int)$morning['checked'] ?>/<?= (int)$morning['expected'] ?></div>
|
||||
<div class="text-muted small"><?= h(t('dashboard.morning_round')) ?></div>
|
||||
</div>
|
||||
</a></div>
|
||||
<div class="col-6 col-lg"><a href="/care-round?period=evening"
|
||||
class="card card-sm text-reset text-decoration-none h-100">
|
||||
<div class="card-body">
|
||||
<div class="h2 mb-1"><?= (int)$evening['checked'] ?>/<?= (int)$evening['expected'] ?></div>
|
||||
<div class="text-muted small"><?= h(t('dashboard.evening_round')) ?></div>
|
||||
</div>
|
||||
</a></div>
|
||||
<div class="col-12 col-lg"><a href="#vaccine-deadlines"
|
||||
class="card card-sm text-reset text-decoration-none h-100">
|
||||
<div class="card-body">
|
||||
<div class="h2 mb-1"><?= count($vaccines_7d) ?></div>
|
||||
<div class="text-muted small"><?= h(t('dashboard.vaccines_7')) ?></div>
|
||||
</div>
|
||||
</a></div>
|
||||
<?php if (PermissionService::can('agenda')): ?><div class="col-12 col-lg"><a href="/agenda"
|
||||
class="card card-sm text-reset text-decoration-none h-100">
|
||||
<div class="card-body">
|
||||
<div class="h2 mb-1 <?= $agendaDue ? 'text-danger' : '' ?>"><?= count($agendaDue) ?></div>
|
||||
<div class="text-muted small"><?= h(t('dashboard.agenda_due')) ?></div>
|
||||
</div>
|
||||
</a></div><?php endif; ?>
|
||||
</div><?php if ($careAlertsToday): ?><div class="alert alert-warning py-2 mt-3 mb-0">
|
||||
<strong><?= h(t('dashboard.round_anomalies')) ?></strong>
|
||||
<?php foreach ($careAlertsToday as $i => $alert): ?><?= $i ? ', ' : '' ?><a
|
||||
href="/animal?id=<?= (int)$alert['id'] ?>"><?= h($alert['name']) ?></a>
|
||||
(<?= h(t($alert['period'] === 'morning' ? 'dashboard.morning' : 'dashboard.evening')) ?>)<?php endforeach; ?>
|
||||
</div><?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col">
|
||||
<form method="get" action="/animals">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" name="q" placeholder="<?= h(t('dashboard.quick_search')) ?>">
|
||||
<button class="btn btn-outline-primary" type="submit"><?= h(t('common.search')) ?></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- VUE D'ENSEMBLE -->
|
||||
<div class="d-flex align-items-center gap-2 mt-4 mb-3">
|
||||
<h2 class="m-0"><?= h(t('dashboard.overview')) ?></h2>
|
||||
<span class="text-muted"><?= h(t('dashboard.overview_help')) ?></span>
|
||||
</div>
|
||||
|
||||
<div class="row row-cards mb-4">
|
||||
<div class="col-6 col-md-3">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="subheader"><?= h(t('dashboard.total')) ?></div>
|
||||
<div class="h1 mb-2"><?= (int)($stats['total'] ?? 0) ?></div>
|
||||
<div class="d-flex flex-wrap gap-1">
|
||||
<span
|
||||
class="badge bg-blue-lt"><?= h(tn('dashboard.adult', 'dashboard.adults', (int)($stats['adults'] ?? 0))) ?></span>
|
||||
<span
|
||||
class="badge bg-cyan-lt"><?= h(tn('dashboard.kitten', 'dashboard.kittens', (int)($stats['kittens'] ?? 0))) ?></span>
|
||||
<?php if ((int)($stats['age_unknown'] ?? 0) > 0): ?>
|
||||
<span class="badge bg-secondary-lt"><?= (int)$stats['age_unknown'] ?>
|
||||
<?= h(t('dashboard.unknown_age')) ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6 col-md-3">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="subheader"><?= h(t('dashboard.shelter')) ?></div>
|
||||
<div class="h1 mb-2"><?= (int)($stats['refuge'] ?? 0) ?></div>
|
||||
<div class="d-flex flex-wrap gap-1">
|
||||
<?php foreach (($shelterRoomCounts ?? []) as $room):if ($room['status'] !== 'refuge') {
|
||||
continue;
|
||||
} ?><span class="badge"
|
||||
style="color:<?= h($room['color']) ?>;background:color-mix(in srgb,<?= h($room['color']) ?> 14%,transparent)"><?= (int)$room['count'] ?>
|
||||
<?= h($room['name']) ?></span><?php endforeach; ?>
|
||||
<?php if ((int)($stats['refuge_unassigned'] ?? 0) > 0): ?>
|
||||
<span class="badge bg-secondary-lt"><?= (int)$stats['refuge_unassigned'] ?>
|
||||
<?= h(t('dashboard.unassigned')) ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6 col-md-3">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<?php $fosterTotal = (int)($stats['fa'] ?? 0) + (int)($stats['fa_permanente'] ?? 0); ?>
|
||||
<div class="subheader"><?= h(t('dashboard.foster')) ?></div>
|
||||
<div class="h1 mb-2"><?= $fosterTotal ?></div>
|
||||
<div class="d-flex flex-wrap gap-1">
|
||||
<span class="badge bg-cyan-lt"><?= (int)($stats['fa'] ?? 0) ?>
|
||||
<?= h(t('dashboard.temporary')) ?></span>
|
||||
<span class="badge bg-indigo-lt"><?= (int)($stats['fa_permanente'] ?? 0) ?>
|
||||
<?= h(t('dashboard.permanent')) ?></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6 col-md-3">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<?php $medicalPoleTotal = (int)($stats['quarantaine'] ?? 0) + (int)($stats['soin'] ?? 0); ?>
|
||||
<div class="subheader"><?= h(t('dashboard.medical_pole')) ?></div>
|
||||
<div class="h1 mb-2"><?= $medicalPoleTotal ?></div>
|
||||
<div class="d-flex flex-wrap gap-1">
|
||||
<span class="badge bg-yellow-lt"><?= (int)($stats['quarantaine'] ?? 0) ?>
|
||||
<?= h(t('dashboard.in_quarantine')) ?></span>
|
||||
<span class="badge bg-red-lt"><?= (int)($stats['soin'] ?? 0) ?>
|
||||
<?= h(t('dashboard.in_medical')) ?></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php $qualityItems = [['birth_date','missing_birth_date',t('quality.birth'),'🎂'],['sex','missing_sex',t('quality.sex'),'⚥'],['color','missing_color',t('quality.color'),'🎨'],['breed','missing_breed',t('quality.breed'),'🐈'],['origin','missing_origin',t('quality.origin'),'📍'],['chip','missing_chip',t('quality.chip'),'🔎'],['identification_registration','unknown_identification_registration',t('quality.registration'),'🏷️'],['sterilization_unknown','unknown_sterilization',t('quality.sterilization'),'❔'],['adoption_availability','unknown_adoption_availability',t('quality.adoption'),'🏠'],['sterilized','unsterilized',t('quality.unsterilized'),'⚕️']]; ?>
|
||||
<div class="d-flex align-items-center gap-2 mt-4 mb-3">
|
||||
<h2 class="m-0"><?= h(t('dashboard.data_quality')) ?></h2><span
|
||||
class="text-muted"><?= h(t('dashboard.data_quality_help')) ?></span>
|
||||
</div>
|
||||
<div
|
||||
class="card mb-4 overflow-hidden <?= (int)($quality['incomplete'] ?? 0) > 0 ? 'border-warning' : 'border-success' ?>">
|
||||
<div class="card-status-top <?= (int)($quality['incomplete'] ?? 0) > 0 ? 'bg-orange' : 'bg-green' ?>"></div>
|
||||
<div class="card-body">
|
||||
<div class="d-flex flex-wrap align-items-center gap-3 mb-3">
|
||||
<div class="me-auto">
|
||||
<div class="subheader"><?= h(t('dashboard.current_records')) ?></div>
|
||||
<h3 class="mb-0">
|
||||
<?php if ((int)($quality['incomplete'] ?? 0) > 0): ?><?= h(tn('dashboard.record_to_complete', 'dashboard.records_to_complete', (int)$quality['incomplete'])) ?><?php else: ?><?= h(t('dashboard.records_complete')) ?><?php endif; ?>
|
||||
</h3>
|
||||
</div><a class="btn btn-outline-cyan" href="/statistics"><?= h(t('dashboard.see_statistics')) ?></a>
|
||||
</div>
|
||||
<div class="row g-2">
|
||||
<?php foreach ($qualityItems as [$filter,$key,$label,$icon]): $count = (int)($quality[$key] ?? 0); ?><div
|
||||
class="col-6 col-md-4 col-xl"><a
|
||||
class="card card-sm h-100 text-reset text-decoration-none <?= $count ? '' : 'bg-muted-lt' ?>"
|
||||
href="/animals?quality=<?= h($filter) ?>">
|
||||
<div class="card-body d-flex align-items-center gap-2"><span class="fs-2"><?= $icon ?></span>
|
||||
<div>
|
||||
<div class="h2 mb-0 <?= $count ? 'text-orange' : 'text-success' ?>"><?= $count ?></div>
|
||||
<div class="text-muted small"><?= h($label) ?></div>
|
||||
</div>
|
||||
</div>
|
||||
</a></div><?php endforeach; ?></div>
|
||||
<div class="text-muted small mt-3"><?= h(t('dashboard.quality_note')) ?></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php $grantAlertTotal = array_sum(array_map('intval', $grantAlerts));
|
||||
if ($grantAlertTotal > 0): ?><div class="alert alert-warning d-flex flex-wrap align-items-center gap-3 mb-4">
|
||||
<div class="fs-2">📁</div>
|
||||
<div class="me-auto"><strong><?= h(t('dashboard.grants_check')) ?></strong>
|
||||
<div class="small">
|
||||
<?= h(t('dashboard.grants_summary', ['overdue' => (int)($grantAlerts['overdue'] ?? 0),'deadlines' => (int)($grantAlerts['deadlines'] ?? 0),'incomplete' => (int)($grantAlerts['incomplete'] ?? 0),'documents' => (int)($grantAlerts['documents'] ?? 0)])) ?>
|
||||
</div>
|
||||
</div><a class="btn btn-warning" href="/admin/grants"><?= h(t('dashboard.open_grants')) ?></a>
|
||||
</div><?php endif; ?>
|
||||
|
||||
<!-- SOINS ET MEDICAL -->
|
||||
<div class="d-flex align-items-center gap-2 mt-4 mb-3" id="medical-priorities">
|
||||
<h2 class="m-0"><?= h(t('dashboard.medical')) ?></h2>
|
||||
<span class="text-muted"><?= h(t('dashboard.medical_help')) ?></span>
|
||||
</div>
|
||||
|
||||
<div class="row row-cards mb-3" id="vaccine-deadlines">
|
||||
<div class="col-12 col-lg-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">🚨 <?= h(t('dashboard.vaccines_overdue')) ?></h3>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-vcenter card-table">
|
||||
<tbody>
|
||||
<?php if (empty($vaccines_overdue)): ?>
|
||||
<tr>
|
||||
<td class="text-muted"><?= h(t('dashboard.nothing')) ?></td>
|
||||
</tr>
|
||||
<?php else: foreach ($vaccines_overdue as $v): ?>
|
||||
<tr>
|
||||
<td class="text-danger fw-bold"><?= h($v['due_date']) ?></td>
|
||||
<td><a href="/animal?id=<?= (int)$v['id'] ?>"><?= h($v['name']) ?></a> <span
|
||||
class="text-muted"><?= h($v['code'] ?? '') ?></span></td>
|
||||
<td><?= h($v['vaccine_name']) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">⏳ <?= h(t('dashboard.vaccines_soon')) ?></h3>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-vcenter card-table">
|
||||
<tbody>
|
||||
<?php if (empty($vaccines_7d)): ?>
|
||||
<tr>
|
||||
<td class="text-muted"><?= h(t('dashboard.nothing')) ?></td>
|
||||
</tr>
|
||||
<?php else: foreach ($vaccines_7d as $v): ?>
|
||||
<tr>
|
||||
<td class="text-warning fw-bold"><?= h($v['due_date']) ?></td>
|
||||
<td><a href="/animal?id=<?= (int)$v['id'] ?>"><?= h($v['name']) ?></a></td>
|
||||
<td><?= h($v['vaccine_name']) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">📅 <?= h(t('dashboard.vaccines_month')) ?></h3>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-vcenter card-table">
|
||||
<tbody>
|
||||
<?php if (empty($vaccines_30d)): ?>
|
||||
<tr>
|
||||
<td class="text-muted"><?= h(t('dashboard.nothing')) ?></td>
|
||||
</tr>
|
||||
<?php else: foreach ($vaccines_30d as $v): ?>
|
||||
<tr>
|
||||
<td class="text-primary fw-bold"><?= h($v['due_date']) ?></td>
|
||||
<td><a href="/animal?id=<?= (int)$v['id'] ?>"><?= h($v['name']) ?></a> <span
|
||||
class="text-muted"><?= h($v['code'] ?? '') ?></span></td>
|
||||
<td><?= h($v['vaccine_name']) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- QUARANTAINE -->
|
||||
<div class="row row-cards mb-3">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">🟨 <?= h(t('dashboard.quarantine_followup')) ?></h3>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-vcenter card-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= h(t('common.animal')) ?></th>
|
||||
<th><?= h(t('dashboard.entry')) ?></th>
|
||||
<th><?= h(t('dashboard.expected_exit')) ?></th>
|
||||
<th><?= h(t('dashboard.exit_followup')) ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($quarantine)): ?>
|
||||
<tr>
|
||||
<td colspan="4" class="text-muted"><?= h(t('dashboard.no_quarantine')) ?></td>
|
||||
</tr>
|
||||
<?php else: foreach ($quarantine as $q): ?>
|
||||
<?php
|
||||
$days = isset($q['days_left']) ? (int)$q['days_left'] : null;
|
||||
$timerClass = 'text-muted';
|
||||
$timerText = '—';
|
||||
|
||||
if (!empty($q['quarantine_until'])) {
|
||||
if ($days < 0) {
|
||||
$timerClass = 'text-danger fw-bold';
|
||||
$timerText = t('dashboard.overdue_days', ['days' => abs($days)]);
|
||||
} elseif ($days === 0) {
|
||||
$timerClass = 'text-warning fw-bold';
|
||||
$timerText = t('dashboard.exit_today');
|
||||
} elseif ($days === 1) {
|
||||
$timerClass = 'text-warning fw-bold';
|
||||
$timerText = t('dashboard.exit_tomorrow');
|
||||
} elseif ($days <= 5) {
|
||||
$timerClass = 'text-warning fw-bold';
|
||||
$timerText = t('dashboard.exit_days', ['days' => $days]);
|
||||
} else {
|
||||
$timerClass = 'text-success';
|
||||
$timerText = t('dashboard.exit_days', ['days' => $days]);
|
||||
}
|
||||
}
|
||||
?>
|
||||
<tr>
|
||||
<td><a href="/animal?id=<?= (int)$q['id'] ?>"><?= h($q['name']) ?></a> <span
|
||||
class="text-muted"><?= h($q['code'] ?? '') ?></span></td>
|
||||
<td><?= h($q['intake_date'] ?? '—') ?></td>
|
||||
<td><?= h($q['quarantine_until'] ?? '—') ?></td>
|
||||
<td class="<?= $timerClass ?>"><?= h($timerText) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="card-footer text-muted small">
|
||||
<?= h(t('dashboard.quarantine_tip')) ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row row-cards mb-3">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">📉📈 <?= h(t('dashboard.weight_alerts')) ?></h3>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-vcenter card-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= h(t('common.animal')) ?></th>
|
||||
<th>J-30</th>
|
||||
<th><?= h(t('dashboard.current')) ?></th>
|
||||
<th><?= h(t('dashboard.variation')) ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($weight_alerts)): ?>
|
||||
<tr>
|
||||
<td colspan="4" class="text-muted"><?= h(t('dashboard.no_alert')) ?></td>
|
||||
</tr>
|
||||
<?php else: foreach ($weight_alerts as $w): ?>
|
||||
<?php
|
||||
$pct = (float)$w['pct'];
|
||||
$cls = $pct < 0 ? 'text-danger fw-bold' : 'text-warning fw-bold';
|
||||
?>
|
||||
<tr>
|
||||
<td><a href="/animal?id=<?= (int)$w['id'] ?>"><?= h($w['name']) ?></a> <span
|
||||
class="text-muted"><?= h($w['code'] ?? '') ?></span></td>
|
||||
<td><?= h($w['w30_weight']) ?> kg <span
|
||||
class="text-muted small">(<?= h(substr((string)$w['w30_date'], 0, 10)) ?>)</span>
|
||||
</td>
|
||||
<td><?= h($w['last_weight']) ?> kg</td>
|
||||
<td class="<?= $cls ?>"><?= ($pct > 0 ? '+' : '') . h($w['pct']) ?>%</td>
|
||||
</tr>
|
||||
<?php endforeach; endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- LISTES -->
|
||||
<div class="row row-cards" id="active-treatments">
|
||||
<div class="col-12 col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">⚠️ <?= h(t('dashboard.treatments_close')) ?></h3>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-vcenter card-table">
|
||||
<tbody>
|
||||
<?php if (empty($treatments_overdue)): ?>
|
||||
<tr>
|
||||
<td class="text-muted"><?= h(t('dashboard.nothing')) ?></td>
|
||||
</tr>
|
||||
<?php else: foreach ($treatments_overdue as $t): ?>
|
||||
<tr>
|
||||
<td class="text-warning fw-bold"><?= h($t['end_date']) ?></td>
|
||||
<td><a href="/animal?id=<?= (int)$t['id'] ?>"><?= h($t['name']) ?></a></td>
|
||||
<td><?= h($t['medication_name']) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title"><?= h(t('dashboard.current_treatments')) ?></h3>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-vcenter card-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= h(t('common.animal')) ?></th>
|
||||
<th><?= h(t('dashboard.medication')) ?></th>
|
||||
<th><?= h(t('dashboard.start')) ?></th>
|
||||
<th><?= h(t('dashboard.end')) ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($treatments)): ?>
|
||||
<tr>
|
||||
<td colspan="4" class="text-muted"><?= h(t('dashboard.no_treatment')) ?></td>
|
||||
</tr>
|
||||
<?php else: foreach ($treatments as $t): ?>
|
||||
<tr>
|
||||
<td><a href="/animal?id=<?= (int)$t['id'] ?>"><?= h($t['name']) ?></a></td>
|
||||
<td>
|
||||
<?= h($t['medication_name']) ?>
|
||||
<?php if (!empty($t['dose_text']) || !empty($t['route'])): ?>
|
||||
<div class="text-muted small">
|
||||
<?= !empty($t['dose_text']) ? h($t['dose_text']) : '' ?>
|
||||
<?= (!empty($t['dose_text']) && !empty($t['route'])) ? ' • ' : '' ?>
|
||||
<?= !empty($t['route']) ? h($t['route']) : '' ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= h($t['start_date'] ?? '') ?></td>
|
||||
<td><?= h($t['end_date'] ?? '') ?></td>
|
||||
</tr>
|
||||
<?php endforeach; endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ACTIVITE RECENTE -->
|
||||
<div class="d-flex align-items-center gap-2 mt-4 mb-3">
|
||||
<h2 class="m-0"><?= h(t('dashboard.recent_activity')) ?></h2>
|
||||
<span class="text-muted"><?= h(t('dashboard.recent_activity_help')) ?></span>
|
||||
</div>
|
||||
|
||||
<div class="row row-cards mb-3">
|
||||
<div class="col-12 col-md-4">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="subheader"><?= h(t('dashboard.medical_notes_7')) ?></div>
|
||||
<div class="h1 mb-0"><?= (int)($activity['notes_7d'] ?? 0) ?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-4">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="subheader"><?= h(t('dashboard.vaccines_30')) ?></div>
|
||||
<div class="h1 mb-0"><?= (int)($activity['vaccines_30d'] ?? 0) ?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-4">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="subheader"><?= h(t('dashboard.treatments_30')) ?></div>
|
||||
<div class="h1 mb-0"><?= (int)($activity['treatments_30d'] ?? 0) ?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row row-cards">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title"><?= h(t('dashboard.latest_notes')) ?></h3>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-vcenter card-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= h(t('dashboard.date')) ?></th>
|
||||
<th><?= h(t('common.animal')) ?></th>
|
||||
<th><?= h(t('dashboard.type')) ?></th>
|
||||
<th><?= h(t('dashboard.reason')) ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($recent_notes)): ?>
|
||||
<tr>
|
||||
<td colspan="4" class="text-muted"><?= h(t('dashboard.no_note')) ?></td>
|
||||
</tr>
|
||||
<?php else: foreach ($recent_notes as $n): ?>
|
||||
<?php $kind = (string)($n['kind'] ?? ''); ?>
|
||||
<tr>
|
||||
<td><?= h(substr((string)$n['noted_at'], 0, 16)) ?></td>
|
||||
<td><a href="/animal?id=<?= (int)$n['animal_id'] ?>"><?= h($n['name']) ?></a> <span
|
||||
class="text-muted"><?= h($n['code'] ?? '') ?></span></td>
|
||||
<td><span class="badge <?= badgeKind($kind) ?>"><?= h($kind) ?></span></td>
|
||||
<td><?= h($n['reason'] ?? '') ?></td>
|
||||
</tr>
|
||||
<?php endforeach; endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Loading…
Add table
Add a link
Reference in a new issue