918 lines
48 KiB
PHP
918 lines
48 KiB
PHP
<?php
|
||
/** @var array $animals */
|
||
/** @var string $q */
|
||
/** @var string $status */
|
||
/** @var array $statuses */
|
||
/** @var string $sort */
|
||
/** @var string $dir */
|
||
$quality = $quality ?? '';
|
||
$qualityLabel = $qualityLabel ?? '';
|
||
$species = $species ?? '';
|
||
$speciesOptions = $speciesOptions ?? [];
|
||
$viewMode = $viewMode ?? 'table';
|
||
$speciesByCode = [];
|
||
foreach ($speciesOptions as $speciesOption) {
|
||
$speciesByCode[SpeciesService::normalize((string)$speciesOption['code'])] = $speciesOption;
|
||
}
|
||
$shortContactName = static function (?string $name): string {
|
||
$name = trim((string)$name);
|
||
if ($name === '') {
|
||
return '';
|
||
}$parts = preg_split('/\s+/u', $name) ?: [];
|
||
if (count($parts) < 2) {
|
||
return $name;
|
||
}$first = (string)array_shift($parts);
|
||
$last = (string)array_pop($parts);
|
||
$initial = mb_strtoupper(mb_substr($last, 0, 1));
|
||
return $first . ($initial !== '' ? ' ' . $initial . '.' : '');
|
||
};
|
||
$tableQs = $_GET;
|
||
$tableQs['view'] = 'table';
|
||
$mosaicQs = $_GET;
|
||
$mosaicQs['view'] = 'mosaic';
|
||
|
||
|
||
?>
|
||
|
||
|
||
|
||
<div class="card">
|
||
<div class="card-body">
|
||
<form class="row g-2 align-items-center" method="get" action="/animals">
|
||
<?php if ($quality !== ''): ?><input type="hidden" name="quality" value="<?= h($quality) ?>"><?php endif; ?>
|
||
<input type="hidden" name="sort" value="<?= h($sort) ?>">
|
||
<input type="hidden" name="dir" value="<?= h(strtolower($dir)) ?>">
|
||
<div class="col-12">
|
||
<input class="form-control" name="q" value="<?= htmlspecialchars($q, ENT_QUOTES) ?>"
|
||
placeholder="<?= h(t('animals.search_placeholder')) ?>">
|
||
</div>
|
||
|
||
<div class="col-12 col-md-auto animal-filter animal-filter-status">
|
||
<select class="form-select" name="status" onchange="this.form.requestSubmit()">
|
||
<?php foreach ($statuses as $k => $label): ?>
|
||
<option value="<?= htmlspecialchars($k, ENT_QUOTES) ?>" <?= $status === $k ? 'selected' : '' ?>>
|
||
<?= htmlspecialchars($label, ENT_QUOTES) ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="col-12 col-md-auto animal-filter animal-filter-species"><select class="form-select"
|
||
name="species" onchange="this.form.requestSubmit()">
|
||
<option value=""><?= h(t('animals.all_species')) ?></option>
|
||
<?php foreach ($speciesOptions as $option): ?><option value="<?= h($option['code']) ?>"
|
||
<?= $species === $option['code'] ? 'selected' : '' ?>>
|
||
<?= h($option['icon'] . ' ' . $option['name']) ?></option><?php endforeach; ?>
|
||
</select></div>
|
||
<div class="col-12 col-md-auto animal-filter animal-filter-availability"><select class="form-select"
|
||
name="availability" onchange="this.form.requestSubmit()">
|
||
<option value=""><?= h(t('animals.all_availability')) ?></option>
|
||
<option value="available" <?= (($availability ?? '') === 'available') ? 'selected' : '' ?>>
|
||
<?= h(t('animals.available')) ?></option>
|
||
<option value="not_available" <?= (($availability ?? '') === 'not_available') ? 'selected' : '' ?>>
|
||
<?= h(t('animals.unavailable')) ?></option>
|
||
<option value="unknown" <?= (($availability ?? '') === 'unknown') ? 'selected' : '' ?>>
|
||
<?= h(t('animals.to_define')) ?></option>
|
||
</select></div>
|
||
|
||
<div class="col-auto">
|
||
<a class="btn btn-outline-primary" href="/animal/new">🐈 <?= h(t('animals.add')) ?></a>
|
||
</div>
|
||
<div class="col-auto">
|
||
<a class="btn btn-outline-primary" href="/litter/new">🐾 <?= h(t('animals.add_litter')) ?></a>
|
||
</div>
|
||
<div class="col-auto ms-auto d-flex align-items-center gap-2">
|
||
<div class="btn-group" role="group" aria-label="<?= h(t('animals.table_view')) ?>"><a
|
||
class="btn px-3 <?= $viewMode === 'table' ? 'btn-dark' : 'btn-outline-secondary' ?>"
|
||
href="/animals?<?= h(http_build_query($tableQs)) ?>" title="<?= h(t('animals.table_view')) ?>"
|
||
aria-label="<?= h(t('animals.table_view')) ?>">☷</a><a
|
||
class="btn px-3 <?= $viewMode === 'mosaic' ? 'btn-dark' : 'btn-outline-secondary' ?>"
|
||
href="/animals?<?= h(http_build_query($mosaicQs)) ?>" title="<?= h(t('animals.mosaic_view')) ?>"
|
||
aria-label="<?= h(t('animals.mosaic_view')) ?>">▦</a></div>
|
||
<div class="dropdown flex-shrink-0">
|
||
<button class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown"
|
||
aria-expanded="false" aria-label="<?= h(t('animals.removed_management')) ?>"
|
||
title="<?= h(t('animals.removed_management')) ?>">
|
||
⚙️
|
||
</button>
|
||
<div class="dropdown-menu dropdown-menu-end shadow">
|
||
<a class="dropdown-item" href="/animals/archived">📦 <?= h(t('animals.archived')) ?></a>
|
||
<a class="dropdown-item text-danger" href="/animals/trash">🗑 <?= h(t('animals.trash')) ?></a>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<?php if ($quality !== ''): ?><div
|
||
class="alert alert-warning mx-3 mt-3 mb-0 d-flex flex-wrap align-items-center gap-2"><span>🔎
|
||
<?= h(t('animals.quality_filter')) ?> : <strong><?= h($qualityLabel) ?></strong></span><span
|
||
class="badge bg-orange-lt"><?= h(t('animals.records', ['count' => count($animals)])) ?></span><a
|
||
class="btn btn-sm btn-outline-secondary ms-auto"
|
||
href="/animals?view=<?= h($viewMode) ?>"><?= h(t('animals.remove_filter')) ?></a></div><?php endif; ?>
|
||
|
||
|
||
<style>
|
||
@media(min-width:768px) {
|
||
.animal-filter-status {
|
||
width: 12.5rem
|
||
}
|
||
|
||
.animal-filter-species {
|
||
width: 10.5rem
|
||
}
|
||
|
||
.animal-filter-availability {
|
||
width: 12.5rem
|
||
}
|
||
}
|
||
|
||
.litter-kitten-row td:nth-child(2) {
|
||
padding-left: 1.5rem;
|
||
}
|
||
|
||
.litter-member-row td:first-child {
|
||
padding-left: 2.75rem;
|
||
}
|
||
|
||
.litter-member-row>td {
|
||
background-color: rgba(169, 127, 69, .045);
|
||
}
|
||
|
||
.bonded-member-row>td {
|
||
background-color: rgba(111, 66, 193, .045);
|
||
}
|
||
|
||
.litter-member-row.bonded-member-row>td {
|
||
background: linear-gradient(90deg, rgba(169, 127, 69, .045), rgba(111, 66, 193, .045));
|
||
}
|
||
|
||
.litter-parent-placeholder td {
|
||
background: var(--tblr-bg-surface-secondary, #f6f8fb);
|
||
border-top-width: 2px;
|
||
}
|
||
|
||
.bonded-group-placeholder td {
|
||
background: rgba(111, 66, 193, .06);
|
||
border-top: 2px solid rgba(111, 66, 193, .2);
|
||
}
|
||
|
||
.litter-parent-placeholder-icon {
|
||
display: inline-flex;
|
||
width: 44px;
|
||
height: 44px;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-radius: 10px;
|
||
background: rgba(98, 105, 118, .12);
|
||
color: var(--tblr-secondary);
|
||
font-size: 1.25rem;
|
||
}
|
||
|
||
.animal-alert-icon {
|
||
display: inline-flex;
|
||
width: 1.4rem;
|
||
height: 1.4rem;
|
||
flex: 0 0 1.4rem;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-radius: 50%;
|
||
}
|
||
|
||
.animal-alert-icon svg {
|
||
width: .9rem;
|
||
height: .9rem;
|
||
}
|
||
|
||
.animal-photo-trigger {
|
||
display: inline-flex;
|
||
border-radius: 10px;
|
||
outline: none;
|
||
cursor: zoom-in;
|
||
}
|
||
|
||
.animal-photo-trigger:focus-visible {
|
||
box-shadow: 0 0 0 3px rgba(32, 107, 196, .25);
|
||
}
|
||
|
||
.animal-photo-zoom {
|
||
position: fixed;
|
||
z-index: 1090;
|
||
display: none;
|
||
pointer-events: none;
|
||
padding: .35rem;
|
||
background: #fff;
|
||
border: 1px solid rgba(98, 105, 118, .25);
|
||
border-radius: 14px;
|
||
box-shadow: 0 1rem 3rem rgba(31, 41, 55, .28);
|
||
}
|
||
|
||
.animal-photo-zoom.is-visible {
|
||
display: block;
|
||
}
|
||
|
||
.animal-photo-zoom img {
|
||
display: block;
|
||
width: auto;
|
||
height: auto;
|
||
max-width: min(320px, 70vw);
|
||
max-height: 60vh;
|
||
border-radius: 10px;
|
||
object-fit: contain;
|
||
}
|
||
|
||
.animal-mosaic-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(7, minmax(0, 1fr));
|
||
gap: .85rem;
|
||
padding: 1rem;
|
||
}
|
||
|
||
.animal-mosaic-card {
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
transition: transform .15s ease, box-shadow .15s ease;
|
||
}
|
||
|
||
.animal-mosaic-card:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 .55rem 1.5rem rgba(31, 41, 55, .12);
|
||
}
|
||
|
||
.animal-mosaic-photo {
|
||
display: block;
|
||
width: 100%;
|
||
aspect-ratio: 1/1;
|
||
object-fit: cover;
|
||
border-radius: 0;
|
||
}
|
||
|
||
.animal-mosaic-card .card-body {
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.animal-mosaic-name {
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.animal-mosaic-footer {
|
||
margin-top: auto;
|
||
}
|
||
|
||
.animal-mosaic-status {
|
||
text-align: center;
|
||
}
|
||
|
||
.animal-mosaic-icons {
|
||
min-height: 1.4rem;
|
||
justify-content: center;
|
||
text-align: center;
|
||
}
|
||
|
||
@media(max-width:1199.98px) {
|
||
.animal-mosaic-grid {
|
||
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||
}
|
||
}
|
||
|
||
@media(max-width:767.98px) {
|
||
.animal-mosaic-grid {
|
||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||
gap: .65rem;
|
||
padding: .75rem;
|
||
}
|
||
}
|
||
|
||
@media(max-width:479.98px) {
|
||
.animal-mosaic-grid {
|
||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||
}
|
||
}
|
||
|
||
.animal-sex-icon {
|
||
display: inline-flex;
|
||
width: 1.25rem;
|
||
height: 1.25rem;
|
||
flex: 0 0 1.25rem;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-radius: 50%;
|
||
font-size: .8rem;
|
||
font-weight: 700;
|
||
line-height: 1;
|
||
}
|
||
|
||
.animal-weight-column {
|
||
width: 7.5rem;
|
||
min-width: 7.5rem;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.animal-age-column {
|
||
width: 5.75rem;
|
||
min-width: 5.75rem;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.animal-species-column {
|
||
width: 7rem;
|
||
min-width: 7rem;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.life-profile-column {
|
||
width: 7.25rem;
|
||
min-width: 7.25rem;
|
||
text-align: center;
|
||
}
|
||
|
||
.life-profile-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(4, 1fr);
|
||
align-items: center;
|
||
gap: .15rem;
|
||
}
|
||
|
||
.life-profile-grid span {
|
||
display: inline-flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
min-width: 1.35rem;
|
||
line-height: 1.2;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.life-profile-sort {
|
||
display: inline-flex;
|
||
justify-content: center;
|
||
color: inherit;
|
||
text-decoration: none;
|
||
}
|
||
|
||
.life-profile-sort:hover,
|
||
.life-profile-sort:focus {
|
||
color: inherit;
|
||
text-decoration: none;
|
||
background: transparent;
|
||
}
|
||
|
||
.life-profile-yes {
|
||
color: var(--tblr-success);
|
||
}
|
||
|
||
.life-profile-no {
|
||
color: var(--tblr-danger);
|
||
}
|
||
|
||
.life-profile-unknown {
|
||
color: var(--tblr-secondary);
|
||
font-weight: 400 !important;
|
||
}
|
||
|
||
/* Conservé pour une éventuelle réactivation de la colonne Prochain vaccin.
|
||
.animal-vaccine-column {
|
||
width: 6.5rem;
|
||
max-width: 6.5rem;
|
||
}
|
||
*/
|
||
|
||
</style>
|
||
<?php if ($viewMode === 'mosaic'): ?>
|
||
<div class="animal-mosaic-grid">
|
||
<?php foreach ($animals as $a):
|
||
$mosaicSrc = !empty($a['primary_photo']) ? '/media/animals/' . (int)$a['id'] . '/' . rawurlencode($a['primary_photo']) : '/assets/cat_placeholder.svg';
|
||
$mosaicSpeciesCode = SpeciesService::normalize((string)($a['species'] ?? ''));
|
||
$mosaicSpecies = $speciesByCode[$mosaicSpeciesCode] ?? ['name' => species_label($mosaicSpeciesCode),'icon' => '🐾','color' => '#6c757d'];
|
||
[$mosaicStatusClass,$mosaicStatusLabel] = status_badge((string)($a['status'] ?? ''));
|
||
[$mosaicSexSymbol,$mosaicSexClass,$mosaicSexLabel] = match((string)($a['sex'] ?? 'U')) {
|
||
'M' => ['♂','bg-blue-lt text-blue',t('sex.male')],'F' => ['♀','bg-purple-lt text-purple',t('sex.female')],default => ['?','bg-secondary-lt text-secondary',t('sex.unknown')]
|
||
};
|
||
$mosaicFoster = in_array((string)($a['status'] ?? ''), ['fa','fa_permanente'], true) ? $shortContactName($a['foster_contact_name'] ?? null) : '';
|
||
$mosaicFreeCat = (string)($a['status'] ?? '') === 'chat_libre' ? trim((string)($a['free_cat_site_name'] ?: $a['free_cat_city'])) : '';
|
||
?>
|
||
<article class="card animal-mosaic-card">
|
||
<a href="/animal?id=<?= (int)$a['id'] ?>"
|
||
class="animal-photo-trigger d-flex w-100 text-reset text-decoration-none"
|
||
data-zoom-src="<?= h($mosaicSrc) ?>"
|
||
aria-label="<?= h(t('animals.open_record', ['name' => $a['name']])) ?>"><img class="animal-mosaic-photo"
|
||
src="<?= h($mosaicSrc) ?>" alt="<?= h(t('animals.photo_of', ['name' => $a['name']])) ?>"></a>
|
||
<div class="card-body p-2">
|
||
<div class="d-flex align-items-center gap-1 mb-1"><a
|
||
class="fw-bold text-reset text-decoration-none animal-mosaic-name me-auto"
|
||
href="/animal?id=<?= (int)$a['id'] ?>"
|
||
title="<?= h($a['name']) ?>"><?= h($a['name']) ?></a><span
|
||
class="animal-sex-icon <?= h($mosaicSexClass) ?>"
|
||
title="<?= h($mosaicSexLabel) ?>"><?= h($mosaicSexSymbol) ?></span></div>
|
||
<div class="d-flex justify-content-center mb-1"><span class="badge"
|
||
style="background:<?= h($mosaicSpecies['color']) ?>18;color:<?= h($mosaicSpecies['color']) ?>"><?= h($mosaicSpecies['icon'] . ' ' . $mosaicSpecies['name']) ?></span>
|
||
</div>
|
||
<div class="animal-mosaic-footer">
|
||
<?php if ($mosaicFoster !== ''): ?><div class="small text-muted text-truncate text-center mb-1"
|
||
title="<?= h(t('animals.foster')) ?> : <?= h($a['foster_contact_name']) ?>">
|
||
<?= h($mosaicFoster) ?></div><?php endif; ?>
|
||
<?php if ($mosaicFreeCat !== ''): ?><div class="small text-muted text-truncate text-center mb-1"
|
||
title="<?= h(t('animals.free_cat_site')) ?> : <?= h($mosaicFreeCat) ?>">🌿
|
||
<?= h($mosaicFreeCat) ?></div><?php endif; ?>
|
||
<div class="animal-mosaic-status mb-1"><span class="badge <?= h($mosaicStatusClass) ?>"
|
||
title="<?= h($mosaicStatusLabel) ?>"><?= h($mosaicStatusLabel) ?></span></div>
|
||
<div class="animal-mosaic-icons d-flex align-items-center gap-2 small">
|
||
<?php foreach ([['compatibility_dogs','🐶',t('animals.dogs')],['compatibility_cats','🐱',t('animals.cats')],['compatibility_children','🧒',t('animals.children')],['house_trained','🧼',t('animals.cleanliness')]] as [$field,$icon,$label]): $value = (string)($a[$field] ?? 'unknown'); ?><span
|
||
title="<?= h($label . ' : ' . t($value === 'yes' ? 'common.yes' : ($value === 'no' ? 'common.no' : 'common.unknown'))) ?>"
|
||
class="<?= $value === 'yes' ? 'text-success' : ($value === 'no' ? 'text-danger' : 'text-muted') ?>"><?= $icon ?><?= $value === 'yes' ? '✓' : ($value === 'no' ? '✕' : '—') ?></span><?php endforeach; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</article>
|
||
<?php endforeach; ?>
|
||
<?php if (!$animals): ?><div class="text-center text-muted py-5" style="grid-column:1/-1">
|
||
<?= h(t('animals.no_results')) ?></div><?php endif; ?>
|
||
</div>
|
||
<?php else: ?>
|
||
<div class="table-responsive mt-2">
|
||
<table class="table table-vcenter card-table">
|
||
<thead>
|
||
<tr>
|
||
<th><?= h(t('animals.photo')) ?></th>
|
||
<!--<th>Code</th>-->
|
||
<th>
|
||
<?= sort_th(t('animals.name'), 'name', $sort, $dir) ?>
|
||
<span class="text-muted mx-1">·</span>
|
||
<?= sort_th(t('animals.sex'), 'sex', $sort, $dir) ?>
|
||
</th>
|
||
<th class="animal-species-column text-center">
|
||
<?= sort_th(t('animals.species'), 'species', $sort, $dir) ?></th>
|
||
<th class="animal-age-column text-center"><?= sort_th(t('animals.age'), 'age', $sort, $dir) ?></th>
|
||
<th class="text-center"><?= sort_th(t('animals.status'), 'status', $sort, $dir) ?></th>
|
||
<th class="life-profile-column">
|
||
<div class="life-profile-grid" aria-label="<?= h(t('animals.life_profile')) ?>"><?php foreach (['compatibility_dogs' => ['🐶',t('animals.compatible_dogs')],'compatibility_cats' => ['🐱',t('animals.compatible_cats')],'compatibility_children' => ['🧒',t('animals.compatible_children')],'house_trained' => ['🧼',t('animals.cleanliness')]] as $profileSortKey => $profileHeader): $profileQs = $_GET;
|
||
$profileQs['sort'] = $profileSortKey;
|
||
$profileQs['dir'] = ($sort === $profileSortKey && strtoupper($dir) === 'ASC') ? 'desc' : 'asc';
|
||
$profileArrow = $sort === $profileSortKey ? (strtoupper($dir) === 'ASC' ? '↑' : '↓') : ''; ?><a
|
||
class="life-profile-sort text-reset"
|
||
href="/animals?<?= h(http_build_query($profileQs)) ?>"
|
||
title="<?= h(t('animals.sort_by', ['label' => mb_strtolower($profileHeader[1])])) ?>"
|
||
aria-label="<?= h(t('animals.sort_by', ['label' => mb_strtolower($profileHeader[1])])) ?>"><?= $profileHeader[0] ?><small><?= h($profileArrow) ?></small></a><?php endforeach; ?>
|
||
</div>
|
||
</th>
|
||
<th class="text-nowrap text-center" style="min-width:9rem"><?= h(t('animals.fiv_felv')) ?></th>
|
||
<!--<th class="animal-weight-column"><?= sort_th('Poids', 'weight', $sort, $dir) ?></th>-->
|
||
<!--<th><?= sort_th('Dernier médical', 'updated_at', $sort, $dir) ?></th>-->
|
||
<!--<th>Traitements</th>-->
|
||
<!--<th class="animal-vaccine-column"><?= h(t('animals.next_vaccine')) ?></th>-->
|
||
<th><?= sort_th(t('animals.location'), 'rescue_location_name', $sort, $dir) ?></th>
|
||
<th class="w-1 text-center"><?= h(t('animals.preview')) ?></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ($animals as $a): ?>
|
||
<?php
|
||
$src = !empty($a['primary_photo'])
|
||
? '/media/animals/' . (int)$a['id'] . '/' . rawurlencode($a['primary_photo'])
|
||
: '/assets/cat_placeholder.svg';
|
||
$animalSpecies = SpeciesService::normalize((string)($a['species'] ?? ''));
|
||
$speciesMeta = $speciesByCode[$animalSpecies] ?? ['name' => species_label($animalSpecies),'icon' => '🐾','color' => '#6c757d'];
|
||
$isCat = SpeciesService::isCat($animalSpecies);
|
||
|
||
$fiv = $a['fiv'] ?? null;
|
||
$felv = $a['felv'] ?? null;
|
||
$fivStatus = (string)(($a['fiv_status'] ?? '') ?: ((int)$fiv === 1 ? 'pos' : 'neg'));
|
||
$felvStatus = (string)(($a['felv_status'] ?? '') ?: ((int)$felv === 1 ? 'pos' : 'neg'));
|
||
$shortStatusLabels = ['unknown' => mb_strtolower(t('animals.test_unknown')), 'neg' => mb_strtolower(t('animals.test_negative')), 'pos' => mb_strtolower(t('animals.test_positive')), 'doubtful' => mb_strtolower(t('animals.test_doubtful'))];
|
||
$healthLabel = $isCat ? ('FIV ' . ($shortStatusLabels[$fivStatus] ?? mb_strtolower(t('animals.test_unknown')))
|
||
. ' · FeLV ' . ($shortStatusLabels[$felvStatus] ?? mb_strtolower(t('animals.test_unknown')))) : t('animals.tests_not_applicable');
|
||
$testBadgeMeta = [
|
||
'unknown' => ['?', 'bg-secondary-lt', t('animals.test_unknown')],
|
||
'neg' => ['−', 'bg-green-lt', t('animals.test_negative')],
|
||
'pos' => ['+', 'bg-red-lt', t('animals.test_positive')],
|
||
'doubtful' => ['?', 'bg-yellow-lt', t('animals.test_doubtful')],
|
||
];
|
||
[$fivSymbol, $fivBadgeClass, $fivBadgeTitle] = $testBadgeMeta[$fivStatus] ?? $testBadgeMeta['unknown'];
|
||
[$felvSymbol, $felvBadgeClass, $felvBadgeTitle] = $testBadgeMeta[$felvStatus] ?? $testBadgeMeta['unknown'];
|
||
|
||
$ageLabel = '—';
|
||
$ageTitle = t('animals.age_unknown');
|
||
if (!empty($a['birth_date'])) {
|
||
try {
|
||
$birth = new DateTimeImmutable((string)$a['birth_date']);
|
||
$age = $birth->diff(new DateTimeImmutable('today'));
|
||
if ($age->y > 0) {
|
||
$ageLabel = $age->y . ' a';
|
||
if ($age->m > 0) {
|
||
$ageLabel .= ' · ' . $age->m . ' m';
|
||
}
|
||
$ageTitle = $age->y . ' an' . ($age->y > 1 ? 's' : '');
|
||
if ($age->m > 0) {
|
||
$ageTitle .= ' et ' . $age->m . ' mois';
|
||
}
|
||
} else {
|
||
$ageLabel = $age->m . ' m';
|
||
$ageTitle = $age->m . ' mois';
|
||
}
|
||
if (!empty($a['birth_is_estimated'])) {
|
||
$ageLabel = '~ ' . $ageLabel;
|
||
$ageTitle .= ' (' . t('animals.age_estimated') . ')';
|
||
}
|
||
} catch (Throwable) {
|
||
$ageLabel = '—';
|
||
}
|
||
}
|
||
|
||
$sexLabel = match ((string)($a['sex'] ?? 'U')) {
|
||
'M' => t('sex.male'),
|
||
'F' => t('sex.female'),
|
||
default => t('animals.sex_not_provided'),
|
||
};
|
||
|
||
$hairLabel = match ((string)($a['hair_type'] ?? '')) {
|
||
'court' => t('animals.short_hair'),
|
||
'mi-long' => t('animals.medium_hair'),
|
||
'long' => t('animals.long_hair'),
|
||
'frise' => t('animals.curly_hair'),
|
||
'sans-poil' => t('animals.hairless'),
|
||
default => t('animals.hair_unknown'),
|
||
};
|
||
$appearance = implode(' · ', [
|
||
(string)($a['breed'] ?: t('animals.breed_unknown')),
|
||
(string)($a['color'] ?: t('animals.coat_unknown')),
|
||
$hairLabel,
|
||
]);
|
||
|
||
$weightLabel = t('animals.weight_unknown');
|
||
if ($a['last_weight'] !== null) {
|
||
$trend = '→';
|
||
if ($a['prev_weight'] !== null) {
|
||
if ((float)$a['last_weight'] > (float)$a['prev_weight']) {
|
||
$trend = '↑';
|
||
} elseif ((float)$a['last_weight'] < (float)$a['prev_weight']) {
|
||
$trend = '↓';
|
||
}
|
||
}
|
||
$weightLabel = number_format((float)$a['last_weight'], 2, ',', ' ') . ' kg ' . $trend;
|
||
}
|
||
|
||
$vaccineLabel = !empty($a['next_vaccine_due'])
|
||
? (($a['next_vaccine_name'] ?: t('animal.vaccine_booster')) . ' · ' . $a['next_vaccine_due'])
|
||
: t('animals.no_vaccine');
|
||
$treatmentLabel = $a['ongoing_treatment_names'] ?: t('animals.no_current_treatment');
|
||
$medicalPoint = $a['latest_medical_point'] ?: t('animals.no_recent_medical');
|
||
$profileMark = static function (string $value, string $label): string {
|
||
[$symbol,$class,$state] = match($value) {
|
||
'yes' => ['✓','life-profile-yes',t('common.yes')],
|
||
'no' => ['✕','life-profile-no',t('common.no')],
|
||
default => ['—','life-profile-unknown',t('common.unknown')],
|
||
};
|
||
return '<span class="' . h($class) . '" title="' . h($label . ' : ' . $state) . '" aria-label="' . h($label . ' : ' . $state) . '">' . h($symbol) . '</span>';
|
||
};
|
||
?>
|
||
<?php if (!empty($a['_bonded_group'])): ?>
|
||
<tr class="bonded-group-placeholder">
|
||
<td><span class="litter-parent-placeholder-icon text-purple" aria-hidden="true">🔗</span></td>
|
||
<td>
|
||
<div class="fw-bold text-purple"><?= h($a['_bonded_group']['label']) ?></div>
|
||
<div class="small text-muted"><?= h($a['_bonded_group']['details']) ?></div>
|
||
<?php if ($a['_bonded_group']['notes'] !== ''): ?><div class="small text-muted">
|
||
<?= h($a['_bonded_group']['notes']) ?></div><?php endif; ?>
|
||
</td>
|
||
<td></td>
|
||
<td></td>
|
||
<td><span class="badge bg-purple-lt"><?= h(t('animals.bonded')) ?></span></td>
|
||
<td></td>
|
||
<td></td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<?php endif; ?>
|
||
<?php if (!empty($a['_litter_group'])): ?>
|
||
<tr class="litter-parent-placeholder">
|
||
<td><span class="litter-parent-placeholder-icon" aria-hidden="true">🐾</span></td>
|
||
<td>
|
||
<div class="fw-bold text-muted"><?= h($a['_litter_group']['label']) ?></div>
|
||
<div class="small text-muted"><?= h($a['_litter_group']['details']) ?></div>
|
||
</td>
|
||
<td></td>
|
||
<td></td>
|
||
<td><span class="badge bg-secondary-lt"><?= h(t('animals.litter')) ?></span></td>
|
||
<td></td>
|
||
<td></td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
<?php endif; ?>
|
||
<tr
|
||
class="<?= (!empty($a['_litter_branch']) || !empty($a['_bonded_branch'])) ? 'litter-kitten-row ' : '' ?><?= !empty($a['_litter_branch']) ? 'litter-member-row ' : '' ?><?= !empty($a['_bonded_branch']) ? 'bonded-member-row' : '' ?>">
|
||
<td>
|
||
<span class="animal-photo-trigger" tabindex="0" data-zoom-src="<?= h($src) ?>"
|
||
aria-label="<?= h(t('animals.enlarge_photo', ['name' => $a['name']])) ?>">
|
||
<img src="<?= htmlspecialchars($src, ENT_QUOTES) ?>"
|
||
style="width:44px;height:44px;object-fit:cover;border-radius:10px" alt="">
|
||
</span>
|
||
</td>
|
||
|
||
<!--<td class="text-muted"><php echo //htmlspecialchars($a['internal_code'], ENT_QUOTES) ?></td>-->
|
||
<td>
|
||
<div class="d-flex align-items-center gap-2">
|
||
<?php $treeBranch = $a['_bonded_branch'] ?? $a['_litter_branch'] ?? ''; ?>
|
||
<?php if ($treeBranch !== ''): ?>
|
||
<span class="text-muted font-monospace" aria-hidden="true"><?= h($treeBranch) ?></span>
|
||
<?php endif; ?>
|
||
<span class="coat-swatch" style="<?= h(coat_swatch_style($a['color'] ?? '')) ?>"
|
||
title="<?= h($a['color'] ?: t('animals.coat_unknown')) ?>" aria-hidden="true"></span>
|
||
<a href="/animal?id=<?= (int)$a['id'] ?>" class="fw-bold">
|
||
<?= htmlspecialchars($a['name'], ENT_QUOTES) ?>
|
||
</a>
|
||
<?php
|
||
[$sexSymbol, $sexIconClass, $sexIconLabel] = match ((string)($a['sex'] ?? 'U')) {
|
||
'M' => ['♂', 'bg-blue-lt text-blue', t('sex.male')],
|
||
'F' => ['♀', 'bg-purple-lt text-purple', t('sex.female')],
|
||
default => ['?', 'bg-secondary-lt text-secondary', t('sex.unknown')],
|
||
};
|
||
?>
|
||
<span class="animal-sex-icon <?= h($sexIconClass) ?>" title="<?= h($sexIconLabel) ?>"
|
||
aria-label="<?= h($sexIconLabel) ?>"><?= h($sexSymbol) ?></span>
|
||
<?php if (!empty($a['_bonded_branch'])): ?><span
|
||
title="<?= h(t('animals.adopt_together')) ?>"
|
||
aria-label="<?= h(t('animals.adopt_together')) ?>">🔗</span><?php endif; ?>
|
||
<?php $sterilizationState = $a['sterilization_status'] ?? (!empty($a['sterilized']) ? 'yes' : 'unknown');
|
||
if ($sterilizationState !== 'yes'): ?>
|
||
<span
|
||
class="animal-alert-icon <?= $sterilizationState === 'no' ? 'bg-yellow-lt text-yellow' : 'bg-secondary-lt text-secondary' ?>"
|
||
title="<?= $sterilizationState === 'no' ? t('animals.not_sterilized') : t('animals.sterilization_unknown') ?>"
|
||
aria-label="<?= $sterilizationState === 'no' ? t('animals.not_sterilized') : t('animals.sterilization_unknown') ?>">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||
<circle cx="6" cy="7" r="3"></circle>
|
||
<circle cx="6" cy="17" r="3"></circle>
|
||
<path d="M8.7 8.3L20 14"></path>
|
||
<path d="M8.7 15.7L20 10"></path>
|
||
</svg>
|
||
</span>
|
||
<?php endif; ?>
|
||
<?php if (trim((string)($a['chip_id'] ?? '')) === ''): ?>
|
||
<span class="animal-alert-icon bg-orange-lt text-orange"
|
||
title="<?= h(t('animals.not_chipped')) ?>"
|
||
aria-label="<?= h(t('animals.not_chipped')) ?>">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||
<rect x="6" y="6" width="12" height="12" rx="2"></rect>
|
||
<path d="M9 1v3M15 1v3M9 20v3M15 20v3M20 9h3M20 14h3M1 9h3M1 14h3"></path>
|
||
<circle cx="12" cy="12" r="2"></circle>
|
||
</svg>
|
||
</span>
|
||
<?php endif; ?>
|
||
</div>
|
||
</td>
|
||
<td class="animal-species-column"><span class="badge"
|
||
style="background:<?= h($speciesMeta['color']) ?>18;color:<?= h($speciesMeta['color']) ?>"
|
||
title="<?= h(t('animals.species_label', ['name' => $speciesMeta['name']])) ?>"><?= h($speciesMeta['icon'] . ' ' . $speciesMeta['name']) ?></span>
|
||
</td>
|
||
<td class="animal-age-column" title="<?= h($ageTitle) ?>"><?= h($ageLabel) ?></td>
|
||
<td>
|
||
<?php [$stCls, $stLbl] = status_badge((string)($a['status'] ?? '')); ?>
|
||
<span class="badge <?= $stCls ?>"><?= htmlspecialchars($stLbl, ENT_QUOTES) ?></span>
|
||
<?php $availability = $a['adoption_availability'] ?? 'unknown';
|
||
if ($availability === 'available'): ?><span class="badge bg-green-lt ms-1"
|
||
title="<?= h(t('animals.available_title')) ?>"><?= h(t('animals.adoptable')) ?></span><?php elseif ($availability === 'not_available'): ?><span
|
||
class="badge bg-orange-lt ms-1"
|
||
title="<?= h($a['adoption_unavailability_reason'] ?: t('animals.unavailable_title')) ?>"><?= h(t('animals.not_adoptable')) ?></span><?php endif; ?>
|
||
<?php $fosterDisplay = in_array((string)($a['status'] ?? ''), ['fa','fa_permanente'], true) ? $shortContactName($a['foster_contact_name'] ?? null) : '';
|
||
if ($fosterDisplay !== ''): ?><div class="small text-muted mt-1"
|
||
title="<?= h(t('animals.foster')) ?> : <?= h($a['foster_contact_name']) ?>">
|
||
<?= h($fosterDisplay) ?></div><?php endif; ?>
|
||
<?php if ((string)($a['status'] ?? '') === 'chat_libre' && (!empty($a['free_cat_site_name']) || !empty($a['free_cat_city']))): ?>
|
||
<div class="small text-muted mt-1">🌿 <?= h($a['free_cat_site_name'] ?: $a['free_cat_city']) ?>
|
||
</div><?php endif; ?>
|
||
</td>
|
||
|
||
<td class="life-profile-column">
|
||
<div class="life-profile-grid">
|
||
<?= $profileMark((string)($a['compatibility_dogs'] ?? 'unknown'), t('animals.dogs')) ?><?= $profileMark((string)($a['compatibility_cats'] ?? 'unknown'), t('animals.cats')) ?><?= $profileMark((string)($a['compatibility_children'] ?? 'unknown'), t('animals.children')) ?><?= $profileMark((string)($a['house_trained'] ?? 'unknown'), t('animals.cleanliness')) ?>
|
||
</div>
|
||
</td>
|
||
|
||
<td class="text-nowrap">
|
||
<?php if ($isCat): ?>
|
||
<div class="d-flex flex-nowrap gap-1">
|
||
<span class="badge <?= $fivBadgeClass ?>" title="FIV : <?= h($fivBadgeTitle) ?>">FIV
|
||
<?= h($fivSymbol) ?></span>
|
||
<span class="badge <?= $felvBadgeClass ?>" title="FeLV : <?= h($felvBadgeTitle) ?>">FeLV
|
||
<?= h($felvSymbol) ?></span>
|
||
</div>
|
||
<?php else: ?><span class="text-muted">—</span><?php endif; ?>
|
||
</td>
|
||
|
||
<!--<td class="animal-weight-column">
|
||
<?php
|
||
$lw = $a['last_weight'];
|
||
$pw = $a['prev_weight'];
|
||
|
||
if ($lw === null) {
|
||
echo '—';
|
||
} else {
|
||
$arrow = '→';
|
||
if ($pw !== null) {
|
||
if ((float)$lw > (float)$pw) {
|
||
$arrow = '↑';
|
||
} elseif ((float)$lw < (float)$pw) {
|
||
$arrow = '↓';
|
||
}
|
||
}
|
||
echo htmlspecialchars(number_format((float)$lw, 2), ENT_QUOTES) . " kg <span class='text-muted'>$arrow</span>";
|
||
}
|
||
?>
|
||
</td>-->
|
||
|
||
<!--<td><?= $a['last_med_at'] ? htmlspecialchars($a['last_med_at'], ENT_QUOTES) : '—' ?></td>-->
|
||
<!--<td><?= (int)($a['ongoing_treatments'] ?? 0) ?></td>-->
|
||
<!--<td class="animal-vaccine-column"><?= $a['next_vaccine_due'] ? htmlspecialchars($a['next_vaccine_due'], ENT_QUOTES) : '—' ?></td>-->
|
||
<td>
|
||
<div class="fw-bold">
|
||
<?= h(($a['rescue_location_name'] ?? '') ?: ($a['rescue_address'] ?? '')) ?></div>
|
||
</td>
|
||
<td class="text-center">
|
||
<button class="btn btn-outline-primary btn-sm" data-bs-toggle="modal"
|
||
data-bs-target="#medPreview" data-id="<?= (int)$a['id'] ?>" data-name="<?= h($a['name']) ?>"
|
||
data-photo="<?= h($src) ?>" data-identity="<?= h($sexLabel . ' · ' . $ageLabel) ?>"
|
||
data-appearance="<?= h($appearance) ?>" data-coat="<?= h($a['color'] ?? '') ?>"
|
||
data-coat-style="<?= h(coat_swatch_style($a['color'] ?? '')) ?>"
|
||
data-health="<?= h($healthLabel) ?>" data-weight="<?= h($weightLabel) ?>"
|
||
data-vaccine="<?= h($vaccineLabel) ?>" data-treatment="<?= h($treatmentLabel) ?>"
|
||
data-deworming="<?= h($a['last_deworming_date'] ? (t('animals.latest') . ' : ' . (new DateTimeImmutable($a['last_deworming_date']))->format('d/m/Y') . ($a['next_deworming_due'] ? ' · ' . t('animals.next') . ' : ' . (new DateTimeImmutable($a['next_deworming_due']))->format('d/m/Y') : '')) : t('animals.never_provided')) ?>"
|
||
data-medical="<?= h($medicalPoint) ?>"
|
||
data-medical-date="<?= h($a['last_med_at'] ?: '') ?>">
|
||
<?= h(t('animals.medical_preview')) ?>
|
||
</button>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
<?php if (!$animals): ?>
|
||
<tr>
|
||
<td colspan="9" class="text-center text-muted py-4"><?= h(t('animals.no_results')) ?></td>
|
||
</tr>
|
||
<?php endif; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<div class="animal-photo-zoom" id="animalPhotoZoom" aria-hidden="true"><img src=""
|
||
alt="<?= h(t('animals.enlarged_preview')) ?>"></div>
|
||
|
||
<div class="modal modal-blur fade" id="medPreview" tabindex="-1" aria-hidden="true">
|
||
<div class="modal-dialog modal-lg modal-dialog-centered" role="document">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title"><?= h(t('animals.medical_preview')) ?></h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal"
|
||
aria-label="<?= h(t('common.close')) ?>"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div class="d-flex align-items-center gap-3 mb-4">
|
||
<img id="medPreviewPhoto" src="/assets/cat_placeholder.svg" alt=""
|
||
style="width:76px;height:76px;object-fit:cover;border-radius:14px">
|
||
<div>
|
||
<div id="medPreviewName" class="h2 mb-1"></div>
|
||
<div id="medPreviewIdentity" class="text-muted"></div>
|
||
<div class="d-flex align-items-center gap-1 text-muted small mt-1">
|
||
<span id="medPreviewCoatSwatch" class="coat-swatch"></span>
|
||
<span id="medPreviewAppearance"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="row row-cards">
|
||
<div class="col-12 col-md-6">
|
||
<div class="card card-sm h-100">
|
||
<div class="card-body">
|
||
<div class="subheader mb-1"><?= h(t('animals.fiv_felv')) ?></div>
|
||
<div id="medPreviewHealth" class="fw-bold"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-12 col-md-6">
|
||
<div class="card card-sm h-100">
|
||
<div class="card-body">
|
||
<div class="subheader mb-1"><?= h(t('animals.last_weight')) ?></div>
|
||
<div id="medPreviewWeight" class="fw-bold"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-12 col-md-6">
|
||
<div class="card card-sm h-100">
|
||
<div class="card-body">
|
||
<div class="subheader mb-1"><?= h(t('animals.next_vaccine')) ?></div>
|
||
<div id="medPreviewVaccine" class="fw-bold"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-12 col-md-6">
|
||
<div class="card card-sm h-100">
|
||
<div class="card-body">
|
||
<div class="subheader mb-1"><?= h(t('animals.current_treatment')) ?></div>
|
||
<div id="medPreviewTreatment" class="fw-bold"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-12 col-md-6">
|
||
<div class="card card-sm h-100">
|
||
<div class="card-body">
|
||
<div class="subheader mb-1"><?= h(t('animals.dewormer')) ?></div>
|
||
<div id="medPreviewDeworming" class="fw-bold"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-12">
|
||
<div class="card card-sm">
|
||
<div class="card-body">
|
||
<div class="subheader mb-1"><?= h(t('animals.latest_diagnosis')) ?></div>
|
||
<div id="medPreviewMedical" class="fw-bold"></div>
|
||
<div id="medPreviewMedicalDate" class="text-muted small mt-1"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-link link-secondary"
|
||
data-bs-dismiss="modal"><?= h(t('common.close')) ?></button>
|
||
<a id="medPreviewLink" class="btn btn-primary"
|
||
href="/animals"><?= h(t('animals.open_full_record')) ?></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
const animalListTranslations = <?= json_encode(['medicalPreview' => t('animals.medical_preview'),
|
||
'neverProvided' => t('animals.never_provided'), 'lastUpdate' => t('animals.last_update', ['date' =>
|
||
'__DATE__'
|
||
])
|
||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> ;
|
||
(() => {
|
||
const zoom = document.getElementById('animalPhotoZoom');
|
||
const image = zoom?.querySelector('img');
|
||
if (!zoom || !image) return;
|
||
const position = (trigger) => {
|
||
const rect = trigger.getBoundingClientRect();
|
||
const width = Math.min(332, window.innerWidth * .7 + 12);
|
||
let left = rect.right + 12;
|
||
if (left + width > window.innerWidth - 12) left = Math.max(12, rect.left - width - 12);
|
||
let top = rect.top + rect.height / 2 - Math.min(320, window.innerHeight * .6) / 2;
|
||
top = Math.max(12, Math.min(top, window.innerHeight - Math.min(332, window.innerHeight * .6) - 12));
|
||
zoom.style.left = left + 'px';
|
||
zoom.style.top = top + 'px';
|
||
};
|
||
const show = (trigger) => {
|
||
image.src = trigger.dataset.zoomSrc || '';
|
||
position(trigger);
|
||
zoom.classList.add('is-visible');
|
||
zoom.setAttribute('aria-hidden', 'false');
|
||
};
|
||
const hide = () => {
|
||
zoom.classList.remove('is-visible');
|
||
zoom.setAttribute('aria-hidden', 'true');
|
||
image.removeAttribute('src');
|
||
};
|
||
document.querySelectorAll('.animal-photo-trigger').forEach((trigger) => {
|
||
trigger.addEventListener('mouseenter', () => show(trigger));
|
||
trigger.addEventListener('mouseleave', hide);
|
||
trigger.addEventListener('focus', () => show(trigger));
|
||
trigger.addEventListener('blur', hide);
|
||
});
|
||
window.addEventListener('scroll', hide, true);
|
||
window.addEventListener('resize', hide);
|
||
})();
|
||
document.getElementById('medPreview')?.addEventListener('show.bs.modal', (ev) => {
|
||
const btn = ev.relatedTarget;
|
||
const name = btn?.getAttribute('data-name') || '';
|
||
document.querySelector('#medPreview .modal-title').textContent = animalListTranslations.medicalPreview +
|
||
' — ' + name;
|
||
document.getElementById('medPreviewName').textContent = name;
|
||
document.getElementById('medPreviewIdentity').textContent = btn?.getAttribute('data-identity') || '—';
|
||
document.getElementById('medPreviewAppearance').textContent = btn?.getAttribute('data-appearance') ||
|
||
'—';
|
||
const coatSwatch = document.getElementById('medPreviewCoatSwatch');
|
||
const coat = btn?.getAttribute('data-coat') || '';
|
||
coatSwatch.style.cssText = btn?.getAttribute('data-coat-style') || 'background:#d9dde3';
|
||
coatSwatch.style.display = coat ? 'inline-block' : 'none';
|
||
document.getElementById('medPreviewHealth').textContent = btn?.getAttribute('data-health') || '—';
|
||
document.getElementById('medPreviewWeight').textContent = btn?.getAttribute('data-weight') || '—';
|
||
document.getElementById('medPreviewVaccine').textContent = btn?.getAttribute('data-vaccine') || '—';
|
||
document.getElementById('medPreviewTreatment').textContent = btn?.getAttribute('data-treatment') || '—';
|
||
document.getElementById('medPreviewDeworming').textContent = btn?.getAttribute('data-deworming') ||
|
||
animalListTranslations.neverProvided;
|
||
document.getElementById('medPreviewMedical').textContent = btn?.getAttribute('data-medical') || '—';
|
||
|
||
const medicalDate = btn?.getAttribute('data-medical-date') || '';
|
||
document.getElementById('medPreviewMedicalDate').textContent = medicalDate ? animalListTranslations
|
||
.lastUpdate.replace('__DATE__', medicalDate) : '';
|
||
document.getElementById('medPreviewPhoto').src = btn?.getAttribute('data-photo') ||
|
||
'/assets/cat_placeholder.svg';
|
||
document.getElementById('medPreviewLink').href = '/animal?id=' + encodeURIComponent(btn?.getAttribute(
|
||
'data-id') || '');
|
||
});
|
||
|
||
</script>
|