459 lines
23 KiB
PHP
459 lines
23 KiB
PHP
<?php
|
|
// Sous-vue de la fiche animale ; les variables sont préparées par AnimalsController::show().
|
|
?>
|
|
<!-- IDENTITÉ -->
|
|
<div class="tab-pane active show" id="tab-ident">
|
|
|
|
<?php if ($canViewMedical && !empty($death)): ?>
|
|
<?php
|
|
$deathCauseLabels = array_combine(array_keys(DeathController::CAUSES), array_map(static fn ($key) => DeathController::causeLabel($key), array_keys(DeathController::CAUSES)));
|
|
$deathPlaceLabels = array_combine(array_keys(DeathController::PLACES), array_map(static fn ($key) => DeathController::placeLabel($key), array_keys(DeathController::PLACES)));
|
|
$deathDispositionLabels = array_combine(array_keys(DeathController::DISPOSITIONS), array_map(static fn ($key) => DeathController::dispositionLabel($key), array_keys(DeathController::DISPOSITIONS)));
|
|
$deathDate = DateTimeImmutable::createFromFormat('Y-m-d', (string)$death['deceased_date']);
|
|
$deathDateLabel = !empty($death['death_year']) ? t('animal.year', ['year' => (int)$death['death_year']]) : ($deathDate ? $deathDate->format('d/m/Y') : t('animal.date_unknown'));
|
|
?>
|
|
<div class="card border-dark mb-3 overflow-hidden">
|
|
<div class="card-status-start bg-dark"></div>
|
|
<div class="card-header d-flex align-items-center justify-content-between">
|
|
<div>
|
|
<h3 class="card-title mb-1">🌈 <?= h(t('animal.death_recorded')) ?></h3>
|
|
<div class="text-muted small"><?= h($deathDateLabel) ?> ·
|
|
<?= h($deathCauseLabels[$death['cause_code']] ?? $death['cause_code']) ?></div>
|
|
</div><a class="btn btn-outline-dark btn-sm"
|
|
href="/animal/death?id=<?= (int)$animal['id'] ?>"><?= h(t('common.edit')) ?></a>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row g-3">
|
|
<div class="col-md-3">
|
|
<div class="subheader"><?= h(t('animal.statistics')) ?></div><span
|
|
class="badge <?= !empty($death['occurred_in_care']) ? 'bg-dark' : 'bg-secondary-lt' ?>"><?= h(t(!empty($death['occurred_in_care']) ? 'animal.in_shelter_figures' : 'animal.outside_care')) ?></span>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="subheader"><?= h(t('death.place')) ?></div>
|
|
<strong><?= h($deathPlaceLabels[$death['place_type']] ?? $death['place_type']) ?></strong><?php if ($death['place_details']): ?>
|
|
<div class="small text-muted"><?= h($death['place_details']) ?></div><?php endif; ?>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="subheader"><?= h(t('death.care_body')) ?></div>
|
|
<strong><?= h($deathDispositionLabels[$death['body_disposition']] ?? $death['body_disposition']) ?></strong><?php if ($death['crematorium_name']): ?>
|
|
<div class="small text-muted"><?= h($death['crematorium_name']) ?></div><?php endif; ?>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="subheader"><?= h(t('animal.context')) ?></div>
|
|
<?php if (!empty($death['euthanized'])): ?><span
|
|
class="badge bg-purple-lt"><?= h(t('animal.euthanasia')) ?></span><?php else: ?><span
|
|
class="text-muted"><?= h(t('animal.natural_death_short')) ?></span><?php endif; ?><?php if ($death['veterinarian_name']): ?>
|
|
<div class="small text-muted"><?= h($death['veterinarian_name']) ?></div><?php endif; ?>
|
|
</div>
|
|
<?php if ($death['cause_details'] || $death['notes']): ?><div class="col-12 small">
|
|
<?php if ($death['cause_details']): ?><strong><?= h(t('animal.cause')) ?> :</strong>
|
|
<?= nl2br(h($death['cause_details'])) ?><?php endif; ?><?php if ($death['notes']): ?><div
|
|
class="mt-1"><strong><?= h(t('common.notes')) ?> :</strong> <?= nl2br(h($death['notes'])) ?>
|
|
</div><?php endif; ?></div><?php endif; ?>
|
|
<?php if (!empty($death['death_age_value'])): ?><div class="col-12 small">
|
|
<strong><?= h(t('animal.death_age')) ?></strong> <?= (int)$death['death_age_value'] ?> <?= h(match($death['death_age_unit']) {
|
|
'day' => t('animal.age_days'),'week' => t('animal.age_weeks'),'month' => t('animal.age_months'),'year' => t('animal.age_years'),default => ''
|
|
}) ?></div><?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if (!empty($bondedGroup)): ?>
|
|
<div class="card border-purple mb-3">
|
|
<div class="card-status-start bg-purple"></div>
|
|
<div class="card-header d-flex align-items-center justify-content-between">
|
|
<div>
|
|
<h3 class="card-title mb-1">🔗 <?= h($bondedGroup['name'] ?: t('animal.bonded_cats')) ?></h3>
|
|
<div class="text-muted small"><?= h(t('animal.bonded_help')) ?></div>
|
|
</div>
|
|
<form method="post" action="/bonded/dissolve"
|
|
onsubmit="return confirm(<?= h(json_encode(t('animal.bonded_dissolve_confirm'), JSON_HEX_APOS | JSON_HEX_QUOT)) ?>);">
|
|
<input type="hidden" name="group_id" value="<?= (int)$bondedGroup['id'] ?>">
|
|
<input type="hidden" name="animal_id" value="<?= (int)$animal['id'] ?>">
|
|
<button class="btn btn-outline-secondary btn-sm"
|
|
type="submit"><?= h(t('animal.dissolve_group')) ?></button>
|
|
</form>
|
|
</div>
|
|
<div class="card-body">
|
|
<?php if (!empty($bondedGroup['notes'])): ?><p class="text-muted mb-3">
|
|
<?= nl2br(h($bondedGroup['notes'])) ?></p><?php endif; ?>
|
|
<div class="d-flex flex-wrap gap-2">
|
|
<?php foreach ($bondedMembers as $member): ?>
|
|
<a class="btn <?= (int)$member['id'] === (int)$animal['id'] ? 'btn-purple' : 'btn-outline-purple' ?>"
|
|
href="/animal?id=<?= (int)$member['id'] ?>">
|
|
<span class="coat-swatch me-1"
|
|
style="<?= h(coat_swatch_style($member['color'] ?? '')) ?>"></span><?= h($member['name']) ?>
|
|
</a>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php
|
|
$lifeProfileMeta = [
|
|
'yes' => [t('common.yes'),'bg-green-lt text-green','✓'],
|
|
'no' => [t('common.no'),'bg-red-lt text-red','✕'],
|
|
'unknown' => [t('common.unknown'),'bg-secondary-lt text-secondary','—'],
|
|
];
|
|
?>
|
|
<div class="card mt-3">
|
|
<div class="card-header">
|
|
<div>
|
|
<h3 class="card-title mb-1"><?= h(t('animal.form.intake')) ?></h3>
|
|
<div class="text-muted small"><?= h(t('animal.intake_origin_help')) ?></div>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row g-3">
|
|
<div class="col-6 col-lg-3">
|
|
<div class="subheader"><?= h(t('common.date')) ?></div>
|
|
<strong><?= h(!empty($animal['intake_date']) ? date('d/m/Y', strtotime((string)$animal['intake_date'])) : '—') ?></strong>
|
|
</div>
|
|
<div class="col-6 col-lg-3">
|
|
<div class="subheader"><?= h(t('animal.intake_mode')) ?></div>
|
|
<strong><?= h($intakeTypes[$animal['intake_type'] ?? 'unknown'] ?? t('common.not_provided')) ?></strong>
|
|
</div>
|
|
<div class="col-6 col-lg-3">
|
|
<div class="subheader"><?= h(t('animal.reason')) ?></div>
|
|
<strong><?= h($intakeReasons[$animal['intake_reason'] ?? 'unknown'] ?? t('common.not_provided')) ?></strong>
|
|
</div>
|
|
<div class="col-6 col-lg-3">
|
|
<div class="subheader"><?= h(t('animal.origin_city')) ?></div>
|
|
<strong><?= h(($animal['rescue_location_name'] ?? '') ?: '—') ?></strong>
|
|
</div>
|
|
<div class="col-12 col-lg-6">
|
|
<div class="subheader"><?= h(t('animal.form.depositor')) ?></div><?php if ($depositor): ?><a
|
|
class="fw-bold"
|
|
href="/directory/edit?id=<?= (int)$depositor['id'] ?>"><?= h($depositor['name']) ?></a><?php if (!empty($depositor['city'])): ?><span
|
|
class="text-muted"> · <?= h($depositor['city']) ?></span><?php endif; ?><?php else: ?><span
|
|
class="text-muted"><?= h(t('animal.form.no_depositor')) ?></span><?php endif; ?>
|
|
</div>
|
|
<?php if (!empty($animal['intake_circumstances'])): ?><div class="col-12">
|
|
<div class="subheader"><?= h(t('animal.form.circumstances')) ?></div>
|
|
<div><?= nl2br(h($animal['intake_circumstances'])) ?></div>
|
|
</div><?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card mt-3">
|
|
<div class="card-header">
|
|
<div>
|
|
<h3 class="card-title mb-1"><?= h(t('animal.form.life_profile')) ?></h3>
|
|
<div class="text-muted small"><?= h(t('animal.life_profile_help')) ?></div>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row g-3">
|
|
<?php foreach ([
|
|
'compatibility_dogs' => ['🐶',t('animals.dogs')],
|
|
'compatibility_cats' => ['🐱',t('animals.cats')],
|
|
'compatibility_children' => ['🧒',t('animals.children')],
|
|
'house_trained' => ['🧼',t('animals.cleanliness')],
|
|
] as $field => $profile): [$profileLabel,$profileClass,$profileSymbol] = $lifeProfileMeta[$animal[$field] ?? 'unknown'] ?? $lifeProfileMeta['unknown']; ?>
|
|
<div class="col-6 col-lg-3">
|
|
<div class="border rounded p-3 h-100 d-flex align-items-center gap-3"><span class="fs-2"
|
|
aria-hidden="true"><?= $profile[0] ?></span>
|
|
<div>
|
|
<div class="text-muted small"><?= h($profile[1]) ?></div><span
|
|
class="badge <?= h($profileClass) ?>"><?= h($profileSymbol . ' ' . $profileLabel) ?></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php require __DIR__ . '/_expense_summary.php'; ?>
|
|
|
|
<div class="card mt-3">
|
|
<div class="card-header">
|
|
<h3 class="card-title m-0"><?= h(t('common.notes')) ?></h3>
|
|
</div>
|
|
<div class="card-body"><?= $animal['notes'] ? nl2br(h($animal['notes'])) : '—' ?></div>
|
|
</div>
|
|
|
|
|
|
<?php
|
|
$rescueAddr = trim((string)($animal['rescue_address'] ?? ''));
|
|
$rescueLat = isset($animal['rescue_lat']) && $animal['rescue_lat'] !== '' ? (float)$animal['rescue_lat'] : null;
|
|
$rescueLng = isset($animal['rescue_lng']) && $animal['rescue_lng'] !== '' ? (float)$animal['rescue_lng'] : null;
|
|
|
|
$currentAddr = trim((string)($animal['current_address'] ?? '5 RUE NOTRE DAME 29260 LESNEVEN'));
|
|
$currentLat = isset($animal['current_lat']) && $animal['current_lat'] !== '' ? (float)$animal['current_lat'] : null;
|
|
$currentLng = isset($animal['current_lng']) && $animal['current_lng'] !== '' ? (float)$animal['current_lng'] : null;
|
|
|
|
$hasRescue = ($rescueLat !== null && $rescueLng !== null);
|
|
$hasCurrent = ($currentLat !== null && $currentLng !== null);
|
|
?>
|
|
|
|
|
|
<div class="card mt-3">
|
|
<div class="card-header d-flex align-items-center justify-content-between">
|
|
<h3 class="card-title m-0"><?= h(t('animal.location')) ?></h3>
|
|
<div class="d-flex gap-2">
|
|
<span class="badge bg-azure-lt"><?= h(t('animal.rescue')) ?></span>
|
|
<span class="badge bg-lime-lt"><?= h(t('animal.current')) ?></span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
<div class="row g-3">
|
|
<div class="col-md-6">
|
|
<div class="text-muted mb-1"><?= h(t('animal.rescue_place')) ?></div>
|
|
<div class="fw-bold"><?= $rescueAddr !== '' ? h($rescueAddr) : '—' ?></div>
|
|
<?php if (!$hasRescue): ?>
|
|
<div class="text-muted small mt-1"><?= h(t('animal.coordinates_missing')) ?></div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<div class="text-muted mb-1"><?= h(t('animal.form.current_location')) ?></div>
|
|
<div class="fw-bold"><?= h($currentAddr) ?></div>
|
|
|
|
<?php if (!$hasCurrent): ?>
|
|
<div class="text-muted small mt-1"><?= h(t('animal.coordinates_missing')) ?></div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<?php if ($animal['status'] === 'adopte'): ?>
|
|
|
|
<div class="alert alert-success mt-3">
|
|
<strong><?= h(t('animal.adopted_by')) ?> :</strong><br>
|
|
<?= htmlspecialchars($adoption['adopter_name'] . ' - ' . $adoption['adopter_address'] . ' ' . $adoption['adopter_postal_code'] . ' ' . $adoption['adopter_city'] . ' - (' . $adoption['adopter_phone'] . ' - ' . $adoption['adopter_email'] . ')') ?>
|
|
</div>
|
|
|
|
<?php endif; ?>
|
|
|
|
<div class="mt-3" id="mapJourney"
|
|
style="height:320px;border-radius:10px;overflow:hidden; border:1px solid #ccc"></div>
|
|
|
|
<?php
|
|
function haversine_km($lat1, $lon1, $lat2, $lon2)
|
|
{
|
|
$earthRadius = 6371; // km
|
|
|
|
$dLat = deg2rad($lat2 - $lat1);
|
|
$dLon = deg2rad($lon2 - $lon1);
|
|
|
|
$a = sin($dLat / 2) * sin($dLat / 2) +
|
|
cos(deg2rad($lat1)) * cos(deg2rad($lat2)) *
|
|
sin($dLon / 2) * sin($dLon / 2);
|
|
|
|
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
|
|
return $earthRadius * $c;
|
|
}
|
|
|
|
$distanceKm = null;
|
|
|
|
if ($hasRescue && $hasCurrent) {
|
|
$distanceKm = haversine_km(
|
|
$rescueLat,
|
|
$rescueLng,
|
|
$currentLat,
|
|
$currentLng,
|
|
);
|
|
}
|
|
?>
|
|
|
|
<?php if ($distanceKm !== null): ?>
|
|
<div class="mt-3 text-muted small">
|
|
<?= h(t('animal.distance_story', ['name' => $animal['name'],'distance' => number_format($distanceKm, 2)])) ?><br>
|
|
<em><?= h(t('animal.distance_caption')) ?></em>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<?php
|
|
/** @var array|null $icad Structure = ['cached'=>..., 'stale'=>bool] comme ton endpoint */
|
|
$cache = $icad['cached'] ?? null;
|
|
$data = $cache['data'] ?? null;
|
|
$status = $cache['status'] ?? 'empty';
|
|
$fetched = $cache['fetched_at'] ?? '';
|
|
$icadUrl = $data['icad_url'] ?? null;
|
|
|
|
$badge = match ($status) {
|
|
'ok' => 'bg-success-lt',
|
|
'error' => 'bg-danger-lt',
|
|
default => 'bg-muted-lt',
|
|
};
|
|
|
|
$label = match ($status) {
|
|
'ok' => 'i-CAD : OK',
|
|
'error' => 'i-CAD : Erreur',
|
|
default => t('animal.icad_not_checked'),
|
|
};
|
|
|
|
$err = (string)($cache['error'] ?? '');
|
|
?>
|
|
|
|
<div class="card mt-3">
|
|
<div class="card-header d-flex align-items-center justify-content-between">
|
|
<div class="d-flex align-items-center gap-2">
|
|
<span class="badge <?= $badge ?>"><?= h($label) ?></span>
|
|
<?php if ($fetched): ?>
|
|
<span class="text-muted small"><?= h(t('animal.last_sync', ['date' => $fetched])) ?></span>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="d-flex gap-2">
|
|
<?php if ($icadUrl): ?>
|
|
<a class="btn btn-sm btn-outline-primary" href="<?= h($icadUrl) ?>" target="_blank" rel="noopener">
|
|
<?= h(t('animal.open_icad')) ?>
|
|
</a>
|
|
<?php endif; ?>
|
|
|
|
<button class="btn btn-sm btn-outline-secondary" type="button" id="btn-icad-refresh"
|
|
data-animal-id="<?= (int)$animal['id'] ?>">
|
|
<?= h(t('common.refresh')) ?>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card-body" id="icad-card-body">
|
|
<?php if ($status === 'error'): ?>
|
|
<div class="alert alert-danger">
|
|
<strong><?= h(t('animal.icad_error')) ?></strong><br>
|
|
<?= h($err) ?>
|
|
</div>
|
|
<?php elseif ($status !== 'ok' || !$data): ?>
|
|
<div class="text-muted"><?= h(t('animal.no_icad')) ?></div>
|
|
<?php else: ?>
|
|
<div class="row g-3">
|
|
<div class="col-md-6">
|
|
<div class="datagrid">
|
|
<div class="datagrid-item">
|
|
<div class="datagrid-title"><?= h(t('animal.icad_name')) ?></div>
|
|
<div class="datagrid-content"><?= h($data['name'] ?? '') ?></div>
|
|
</div>
|
|
<div class="datagrid-item">
|
|
<div class="datagrid-title">Puce</div>
|
|
<div class="datagrid-content"><?= h($data['insert'] ?? '') ?></div>
|
|
</div>
|
|
<div class="datagrid-item">
|
|
<div class="datagrid-title"><?= h(t('animal.sex')) ?></div>
|
|
<div class="datagrid-content"><?= h($data['sex'] ?? '') ?></div>
|
|
</div>
|
|
<div class="datagrid-item">
|
|
<div class="datagrid-title"><?= h(t('animal.birth')) ?></div>
|
|
<div class="datagrid-content"><?= h($data['birth_date'] ?? '') ?></div>
|
|
</div>
|
|
<div class="datagrid-item">
|
|
<div class="datagrid-title"><?= h(t('animal.appearance')) ?></div>
|
|
<div class="datagrid-content"><?= h($data['appearance'] ?? '') ?></div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php
|
|
$holder =
|
|
$data['holder'] ??
|
|
$data['owner'] ??
|
|
$data['detenteur'] ??
|
|
null;
|
|
|
|
// Si ton parse aplatit au lieu d'imbriquer :
|
|
if (!$holder && (
|
|
isset($data['holder_name']) || isset($data['holder_phone']) || isset($data['holder_email'])
|
|
)) {
|
|
$holder = [
|
|
'name' => $data['holder_name'] ?? '',
|
|
'phone' => $data['holder_phone'] ?? '',
|
|
'email' => $data['holder_email'] ?? '',
|
|
'type' => $data['holder_type'] ?? '',
|
|
'address' => $data['holder_address'] ?? '',
|
|
];
|
|
}
|
|
?>
|
|
|
|
<?php if (is_array($holder) && array_filter($holder, fn ($v) => trim((string)$v) !== '')): ?>
|
|
<hr class="my-3">
|
|
|
|
<div class="row g-3">
|
|
<div class="col-md-12">
|
|
<div class="d-flex align-items-center justify-content-between mb-2">
|
|
<div class="fw-bold"><?= h(t('animal.holder')) ?></div>
|
|
<span class="text-muted small"><span
|
|
class="badge bg-danger-lt"><?= h(t('animal.do_not_share')) ?></span></span>
|
|
</div>
|
|
|
|
<div class="datagrid">
|
|
<?php if (!empty($holder['type'])): ?>
|
|
<div class="datagrid-item">
|
|
<div class="datagrid-title">Type</div>
|
|
<div class="datagrid-content"><?= h($holder['type']) ?></div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if (!empty($holder['name'])): ?>
|
|
<div class="datagrid-item">
|
|
<div class="datagrid-title"><?= h(t('common.name')) ?></div>
|
|
<div class="datagrid-content"><?= h($holder['name']) ?></div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if (!empty($holder['phone'])): ?>
|
|
<div class="datagrid-item">
|
|
<div class="datagrid-title"><?= h(t('common.phone')) ?></div>
|
|
<div class="datagrid-content"><?= h($holder['phone']) ?></div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if (!empty($holder['email'])): ?>
|
|
<div class="datagrid-item">
|
|
<div class="datagrid-title"><?= h(t('common.email')) ?></div>
|
|
<div class="datagrid-content"><?= h($holder['email']) ?></div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if (!empty($holder['address'])): ?>
|
|
<div class="datagrid-item" style="grid-column: 1 / -1;">
|
|
<div class="datagrid-title"><?= h(t('common.address')) ?></div>
|
|
<div class="datagrid-content"><?= nl2br(h($holder['address'])) ?></div>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<div class="text-muted mb-2"><?= h(t('animal.icad_history')) ?></div>
|
|
<?php $events = $data['events'] ?? []; ?>
|
|
<?php if (empty($events)): ?>
|
|
<div class="text-muted"><?= h(t('animal.no_event')) ?></div>
|
|
<?php else: ?>
|
|
<ul class="list list-timeline">
|
|
<?php foreach ($events as $e): ?>
|
|
<li>
|
|
<div class="list-timeline-icon bg-blue-lt">
|
|
<i class="ti ti-history"></i>
|
|
</div>
|
|
<div class="list-timeline-content">
|
|
<div class="fw-bold"><?= h($e['label'] ?? '') ?></div>
|
|
<div class="text-muted small">
|
|
<?= h(t('common.date')) ?> : <?= h($e['date'] ?? '') ?> —
|
|
<?= h(t('animal.recorded')) ?> : <?= h($e['recorded_at'] ?? '') ?>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|