Globinours/app/Views/_animal_show_modals.php

1105 lines
60 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
// Fenêtres modales et scripts propres à la fiche animale.
?>
<?php
/** @var array $medications */
/** @var array $ref_med_administration */
/** @var array $vaccines */
$defaultDue = date('Y-m-d', strtotime('+1 year'));
$today = date('Y-m-d');
?>
<?php if ($canViewMedical): ?>
<div class="modal modal-blur fade" id="modalTreatment" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered" role="document">
<form class="modal-content" method="post" action="/animal/add-treatment">
<div class="modal-header">
<h5 class="modal-title"><?= h(t('animal.treatment_start')) ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"
aria-label="<?= h(t('common.close')) ?>"></button>
</div>
<div class="modal-body">
<input type="hidden" name="animal_id" value="<?= (int)$animal['id'] ?>">
<div class="row g-2">
<div class="col-md-8">
<label class="form-label"><?= h(t('animal.medication')) ?></label>
<div class="input-group">
<select class="form-select" name="medication_id" id="treatmentMedicationSelect" required>
<option value="">— Choisir —</option>
<?php foreach ($medications as $m): ?>
<option value="<?= (int)$m['id'] ?>"><?= htmlspecialchars($m['name'], ENT_QUOTES) ?>
</option>
<?php endforeach; ?>
</select>
<button class="btn btn-outline-primary" type="button" id="treatmentMedicationAdd"
aria-expanded="false" aria-controls="treatmentMedicationNew">+
<?= h(t('common.add')) ?></button>
</div>
</div>
<div class="col-md-4">
<label class="form-label"><?= h(t('animal.route')) ?></label>
<select class="form-select" name="route" required>
<option value="">— Choisir —</option>
<?php foreach ($ref_med_administration as $rma): ?>
<option value="<?= $rma['accro'] ?>"><?= htmlspecialchars($rma['name'], ENT_QUOTES) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-12 d-none" id="treatmentMedicationNew">
<input type="hidden" name="create_medication" id="treatmentMedicationCreate" value="0">
<div class="card bg-blue-lt border-blue-lt">
<div class="card-body py-3">
<div class="row g-2">
<div class="col-md-5"><label
class="form-label"><?= h(t('animal.new_medication')) ?></label><input
class="form-control" name="new_medication_name" id="treatmentMedicationName"
maxlength="150" placeholder="Ex. Doxybactin"></div>
<div class="col-md-4"><label class="form-label"><?= h(t('animal.molecule')) ?> <span
class="text-muted">(<?= h(mb_strtolower(t('common.optional'))) ?>)</span></label><input
class="form-control" name="new_medication_molecule" maxlength="150"
placeholder="Ex. Doxycycline"></div>
<div class="col-md-3"><label class="form-label"><?= h(t('animal.form_form')) ?>
<span
class="text-muted">(<?= h(mb_strtolower(t('common.optional'))) ?>)</span></label><input
class="form-control" name="new_medication_form" maxlength="100"
placeholder="<?= h(t('animal.medication_form_placeholder')) ?>"></div>
</div>
<div class="form-hint mt-2"><?= h(t('animal.medication_saved_hint')) ?></div>
</div>
</div>
</div>
<div class="col-12">
<label class="form-label"><?= h(t('animal.dosage')) ?></label>
<input class="form-control" name="dose_text" required placeholder="Ex: 1/2 cp matin & soir">
</div>
<div class="col-12">
<label class="form-label"><?= h(t('animal.administer_during')) ?></label>
<div class="d-flex flex-wrap gap-3">
<label class="form-check"><input class="form-check-input" type="checkbox"
name="give_morning" value="1"><span class="form-check-label">☀️
<?= h(t('animal.morning_round')) ?></span></label>
<label class="form-check"><input class="form-check-input" type="checkbox"
name="give_evening" value="1"><span class="form-check-label">🌙
<?= h(t('animal.evening_round')) ?></span></label>
<label class="form-check"><input class="form-check-input" type="checkbox"
name="give_as_needed" value="1"><span
class="form-check-label"><?= h(t('animal.as_needed')) ?></span></label>
</div>
</div>
<div class="col-md-6">
<label class="form-label"><?= h(t('animal.start')) ?></label>
<input class="form-control" type="date" name="start_date" value="<?= $today ?>">
</div>
<div class="col-md-6">
<label class="form-label"><?= h(t('animal.end_optional')) ?></label>
<input class="form-control" type="date" name="end_date">
</div>
<?php $directoryFieldId = 'treatment';
require __DIR__ . '/_directory_medical_fields.php'; ?>
<?php require __DIR__ . '/_expense_tariff_field.php'; ?>
<div class="col-12">
<label class="form-label"><?= h(t('common.notes')) ?></label>
<textarea class="form-control" name="notes" rows="2"></textarea>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn me-auto" data-bs-dismiss="modal"><?= h(t('common.cancel')) ?></button>
<button type="submit" class="btn btn-primary"><?= h(t('common.save')) ?></button>
</div>
</form>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const button = document.getElementById('treatmentMedicationAdd');
const select = document.getElementById('treatmentMedicationSelect');
const panel = document.getElementById('treatmentMedicationNew');
const create = document.getElementById('treatmentMedicationCreate');
const name = document.getElementById('treatmentMedicationName');
if (!button || !select || !panel || !create || !name) return;
button.addEventListener('click', function() {
const opening = panel.classList.contains('d-none');
panel.classList.toggle('d-none', !opening);
create.value = opening ? '1' : '0';
select.disabled = opening;
select.required = !opening;
name.required = opening;
button.setAttribute('aria-expanded', opening ? 'true' : 'false');
button.textContent = opening ? <?= json_encode(t('common.choose_from_list'),
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> : '+ ' + <?= json_encode(t(
'common.add'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> ;
if (opening) name.focus();
});
});
</script>
<div class="modal modal-blur fade" id="modalDeworming" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<form class="modal-content" method="post" action="/animal/add-deworming">
<div class="modal-header">
<h5 class="modal-title"><?= h(t('animal.deworming_record')) ?></h5><button type="button"
class="btn-close" data-bs-dismiss="modal" aria-label="<?= h(t('common.close')) ?>"></button>
</div>
<div class="modal-body"><input type="hidden" name="animal_id" value="<?= (int)$animal['id'] ?>">
<div class="row g-3">
<div class="col-md-6"><label class="form-label"><?= h(t('common.date')) ?></label><input
class="form-control" type="date" name="administered_on" value="<?= date('Y-m-d') ?>"
required></div>
<div class="col-md-6"><label class="form-label"><?= h(t('animal.product')) ?></label><select
class="form-select" name="dewormer_id">
<option value=""><?= h(t('common.not_provided')) ?></option>
<?php foreach ($dewormers as $m): ?><option value="<?= (int)$m['id'] ?>">
<?= h($m['name']) ?></option><?php endforeach; ?>
</select></div>
<div class="col-md-6"><label class="form-label"><?= h(t('animal.dose')) ?></label><input
class="form-control" name="dose_text" placeholder="<?= h(t('deworm.dose_example')) ?>">
</div>
<div class="col-md-6"><label class="form-label"><?= h(t('common.weight')) ?></label>
<div class="input-group"><input class="form-control" type="number" min="0" step="0.01"
name="weight_kg"><span class="input-group-text">kg</span></div>
</div>
<div class="col-md-8"><label class="form-label"><?= h(t('inventory.batch')) ?></label><select
class="form-select" name="inventory_batch_id">
<option value="">—</option><?php foreach (($inventoryBatches ?? []) as $b) {
if ($b['category'] === 'dewormer'): ?><option value="<?= (int)$b['id'] ?>">
<?= h($b['name'] . ' · ' . ($b['batch_number'] ?: t('inventory.no_batch')) . ' · ' . $b['quantity'] . ' ' . $b['unit']) ?>
</option><?php endif;
} ?>
</select></div>
<div class="col-md-4"><label class="form-label"><?= h(t('inventory.quantity')) ?></label><input
class="form-control" type="number" min="0" step="0.01" name="inventory_quantity"></div>
<div class="col-12"><label class="form-label"><?= h(t('animal.next_due')) ?> <span
class="text-muted">(<?= h(mb_strtolower(t('common.optional'))) ?>)</span></label><input
class="form-control" type="date" name="next_due_date">
<div class="form-hint"><?= h(t('animal.next_due_hint')) ?></div>
</div><?php if (!empty($litters)): ?><div class="col-12"><label class="form-check"><input
class="form-check-input" type="checkbox" name="apply_litter" value="1"><span
class="form-check-label"><?= h(t('animal.apply_litter')) ?></span></label></div>
<?php endif; ?><div class="col-12"><label
class="form-label"><?= h(t('animal.comment')) ?></label><textarea class="form-control"
name="notes" rows="2"></textarea></div>
</div>
</div>
<div class="modal-footer"><button class="btn me-auto" type="button"
data-bs-dismiss="modal"><?= h(t('common.cancel')) ?></button><button
class="btn btn-primary"><?= h(t('common.save')) ?></button></div>
</form>
</div>
</div>
<div class="modal modal-blur fade" id="modalPlacement" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<form class="modal-content" method="post" action="/animal/placement/save">
<div class="modal-header">
<h5 class="modal-title"><?= h(t('animal.add_placement')) ?></h5><button type="button" class="btn-close"
data-bs-dismiss="modal" aria-label="<?= h(t('common.close')) ?>"></button>
</div>
<div class="modal-body"><input type="hidden" name="animal_id" value="<?= (int)$animal['id'] ?>">
<div class="row g-3">
<div class="col-md-7"><label class="form-label"><?= h(t('animal.event')) ?></label><select
class="form-select" name="event_type" required>
<option value="reservation"><?= h(t('animal.reservation')) ?></option>
<option value="foster"><?= h(t('animal.foster_placement')) ?></option>
<option value="return"><?= h(t('animal.return_shelter')) ?></option>
<option value="cancellation"><?= h(t('animal.cancellation')) ?></option>
</select>
<div class="form-hint"><?= h(t('animal.placement_hint')) ?></div>
</div>
<div class="col-md-5"><label class="form-label"><?= h(t('common.date')) ?></label><input
class="form-control" type="date" name="event_date" value="<?= date('Y-m-d') ?>" required>
</div>
<div class="col-12"><label class="form-label"><?= h(t('animal.related_contact')) ?></label><select
class="form-select" name="contact_id">
<option value=""><?= h(t('animal.no_contact')) ?></option>
<?php foreach (($placementContacts ?? []) as $contact): ?><option
value="<?= (int)$contact['id'] ?>">
<?= h($contact['name'] . (!empty($contact['city']) ? ' · ' . $contact['city'] : '')) ?>
</option><?php endforeach; ?>
</select></div>
<div class="col-12"><label class="form-label"><?= h(t('animal.reason')) ?></label><input
class="form-control" name="reason" maxlength="255"
placeholder="<?= h(t('animal.return_reason_placeholder')) ?>"></div>
<div class="col-12"><label class="form-label"><?= h(t('common.notes')) ?></label><textarea
class="form-control" name="notes" rows="3"></textarea></div>
</div>
</div>
<div class="modal-footer"><button class="btn me-auto" type="button"
data-bs-dismiss="modal"><?= h(t('common.cancel')) ?></button><button
class="btn btn-primary"><?= h(t('common.save')) ?></button></div>
</form>
</div>
</div>
<div class="modal modal-blur fade" id="modalVaccine" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered" role="document">
<form class="modal-content" method="post" action="/animal/add-vaccine">
<div class="modal-header">
<h5 class="modal-title"><?= h(t('animal.vaccine_record')) ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"
aria-label="<?= h(t('common.close')) ?>"></button>
</div>
<div class="modal-body">
<input type="hidden" name="animal_id" value="<?= (int)$animal['id'] ?>">
<div class="row g-2">
<div class="col-md-6">
<label class="form-label"><?= h(t('animal.vaccine')) ?></label>
<select class="form-select" name="vaccine_id" required>
<option value="">— Choisir —</option>
<?php foreach ($vaccines as $v): ?>
<option value="<?= (int)$v['id'] ?>"><?= htmlspecialchars($v['name'], ENT_QUOTES) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-3">
<label class="form-label"><?= h(t('animal.done_on')) ?></label>
<input class="form-control" type="date" name="done_date" value="<?= $today ?>">
</div>
<div class="col-md-3">
<label class="form-label"><?= h(t('animal.reminder_due')) ?></label>
<input class="form-control" type="date" name="due_date" value="<?= $defaultDue ?>">
<div class="form-hint"><?= h(t('animal.kitten_vaccine_hint')) ?></div>
</div>
<?php $directoryFieldId = 'vaccine';
require __DIR__ . '/_directory_medical_fields.php'; ?>
<?php require __DIR__ . '/_expense_tariff_field.php'; ?>
<div class="col-md-4">
<label class="form-label"><?= h(t('animal.batch')) ?></label>
<input class="form-control" name="lot" placeholder="Optionnel">
</div>
<div class="col-md-4">
<label class="form-label"><?= h(t('animal.manufacturer')) ?></label>
<input class="form-control" name="manufacturer" placeholder="Ex : Boehringer Ingelheim">
</div>
<div class="col-md-4">
<label class="form-label"><?= h(t('animal.batch_expiry')) ?></label>
<input class="form-control" type="date" name="batch_expires_on">
</div>
<div class="col-md-8"><label class="form-label"><?= h(t('inventory.batch')) ?></label><select
class="form-select" name="inventory_batch_id">
<option value="">—</option><?php foreach (($inventoryBatches ?? []) as $b) {
if ($b['category'] === 'vaccine'): ?><option value="<?= (int)$b['id'] ?>">
<?= h($b['name'] . ' · ' . ($b['batch_number'] ?: t('inventory.no_batch')) . ' · ' . $b['quantity'] . ' ' . $b['unit']) ?>
</option><?php endif;
} ?>
</select></div>
<div class="col-md-4"><label class="form-label"><?= h(t('inventory.quantity')) ?></label><input
class="form-control" type="number" min="0" step="0.01" name="inventory_quantity"></div>
<div class="col-md-6">
<label class="form-label"><?= h(t('animal.administered_by')) ?></label>
<select class="form-select" name="administered_by_user_id" id="vaccineAdministrator">
<option value=""><?= h(t('common.not_provided')) ?></option>
<?php foreach (($activeUsers ?? []) as $user): ?><option value="<?= (int)$user['id'] ?>">
<?= h($user['name']) ?></option><?php endforeach; ?><option value="other">
<?= h(t('animal.other_person')) ?></option>
</select>
</div>
<div class="col-md-6 d-none" id="vaccineAdministratorOther">
<label class="form-label"><?= h(t('animal.person_name')) ?></label>
<input class="form-control" name="administered_by_name"
placeholder="<?= h(t('animal.person_placeholder')) ?>">
</div>
<div class="col-md-12">
<label class="form-label"><?= h(t('common.notes')) ?></label>
<input class="form-control" name="notes" placeholder="Optionnel">
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const select = document.getElementById('vaccineAdministrator');
const wrap = document.getElementById('vaccineAdministratorOther');
const sync = () => wrap?.classList.toggle('d-none', select?.value !== 'other');
select?.addEventListener('change', sync);
sync();
});
</script>
</div>
<div class="modal-footer">
<button type="button" class="btn me-auto" data-bs-dismiss="modal"><?= h(t('common.cancel')) ?></button>
<button type="submit" class="btn btn-primary"><?= h(t('common.save')) ?></button>
</div>
</form>
</div>
</div>
<div class="modal modal-blur fade" id="modalPrescription" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered">
<form class="modal-content" method="post" action="/animal/prescription/save" enctype="multipart/form-data">
<div class="modal-header">
<h5 class="modal-title">📄 <?= h(t('medical_document.add_prescription')) ?></h5><button type="button"
class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body"><input type="hidden" name="animal_id" value="<?= (int)$animal['id'] ?>">
<div class="alert alert-info py-2"><?= h(t('medical_document.private_hint')) ?></div>
<div class="row g-3">
<div class="col-md-4"><label
class="form-label"><?= h(t('medical_document.prescribed_on')) ?></label><input
class="form-control" type="date" name="prescribed_on" value="<?= date('Y-m-d') ?>" required>
</div>
<div class="col-md-4"><label class="form-label"><?= h(t('animal.status')) ?></label><select
class="form-select" name="status">
<option value="active"><?= h(t('medical_document.status_active')) ?></option>
<option value="finished"><?= h(t('medical_document.status_finished')) ?></option>
<option value="replaced"><?= h(t('medical_document.status_replaced')) ?></option>
</select></div>
<div class="col-md-4"><label class="form-label"><?= h(t('medical_document.file')) ?></label><input
class="form-control" type="file" name="document"
accept="application/pdf,image/jpeg,image/png,image/webp" capture="environment" required>
</div>
<div class="col-md-6"><label
class="form-label"><?= h(t('animal.veterinary_clinic')) ?></label><select
class="form-select" name="clinic_contact_id">
<option value=""><?= h(t('common.not_provided')) ?></option>
<?php foreach ($directoryClinics as $c): ?><option value="<?= (int)$c['id'] ?>">
<?= h($c['name']) ?></option><?php endforeach; ?>
</select></div>
<div class="col-md-6"><label
class="form-label"><?= h(t('animal.form.veterinarian')) ?></label><select
class="form-select" name="veterinarian_contact_id">
<option value=""><?= h(t('common.not_provided')) ?></option>
<?php foreach ($veterinarians as $v): ?><option value="<?= (int)$v['id'] ?>">
<?= h($v['name']) ?></option><?php endforeach; ?>
</select></div><?php if ($treatments): ?><div class="col-12"><label
class="form-label"><?= h(t('medical_document.link_treatments')) ?></label>
<div class="d-flex flex-wrap gap-3"><?php foreach ($treatments as $t): ?><label
class="form-check"><input class="form-check-input" type="checkbox"
name="treatment_ids[]" value="<?= (int)$t['id'] ?>"><span
class="form-check-label"><?= h($t['medication_name']) ?></span></label><?php endforeach; ?>
</div>
</div><?php endif; ?><div class="col-12"><label
class="form-label"><?= h(t('common.notes')) ?></label><textarea class="form-control"
name="notes" rows="2"></textarea></div>
</div>
</div>
<div class="modal-footer"><button type="button" class="btn me-auto"
data-bs-dismiss="modal"><?= h(t('common.cancel')) ?></button><button
class="btn btn-primary"><?= h(t('common.save')) ?></button></div>
</form>
</div>
</div>
<div class="modal modal-blur fade" id="modalLabReport" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-xl modal-dialog-centered modal-dialog-scrollable">
<form class="modal-content" method="post" action="/animal/lab-report/save" enctype="multipart/form-data">
<div class="modal-header">
<h5 class="modal-title">🧪 <?= h(t('medical_document.add_analysis')) ?></h5><button type="button"
class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body"><input type="hidden" name="animal_id" value="<?= (int)$animal['id'] ?>">
<div class="row g-3">
<div class="col-md-3"><label
class="form-label"><?= h(t('medical_document.sampled_on')) ?></label><input
class="form-control" type="date" name="sampled_on" value="<?= date('Y-m-d') ?>" required>
</div>
<div class="col-md-3"><label
class="form-label"><?= h(t('medical_document.analysis_type')) ?></label><input
class="form-control" name="report_type"
placeholder="<?= h(t('medical_document.analysis_example')) ?>"></div>
<div class="col-md-3"><label
class="form-label"><?= h(t('medical_document.laboratory')) ?></label><input
class="form-control" name="laboratory_name"></div>
<div class="col-md-3"><label
class="form-label"><?= h(t('medical_document.report_optional')) ?></label><input
class="form-control" type="file" name="document"
accept="application/pdf,image/jpeg,image/png,image/webp" capture="environment"></div>
<div class="col-md-6"><label
class="form-label"><?= h(t('animal.veterinary_clinic')) ?></label><select
class="form-select" name="clinic_contact_id">
<option value=""><?= h(t('common.not_provided')) ?></option>
<?php foreach ($directoryClinics as $c): ?><option value="<?= (int)$c['id'] ?>">
<?= h($c['name']) ?></option><?php endforeach; ?>
</select></div>
<div class="col-md-6"><label
class="form-label"><?= h(t('animal.form.veterinarian')) ?></label><select
class="form-select" name="veterinarian_contact_id">
<option value=""><?= h(t('common.not_provided')) ?></option>
<?php foreach ($veterinarians as $v): ?><option value="<?= (int)$v['id'] ?>">
<?= h($v['name']) ?></option><?php endforeach; ?>
</select></div>
<div class="col-12">
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2 mb-2">
<div><label
class="form-label mb-0"><?= h(t('medical_document.measured_parameters')) ?></label>
<div class="form-hint"><?= h(t('medical_document.parameters_help')) ?></div>
</div>
<div class="d-flex gap-2"><select class="form-select form-select-sm" id="labTemplate">
<option value=""><?= h(t('medical_document.template')) ?></option>
<?php foreach (($labReferenceSets ?? []) as $key => $set): ?><option
value="ref:<?= h($key) ?>"><?= h($set['label']) ?></option><?php endforeach; ?>
</select><button class="btn btn-sm btn-outline-primary" id="addLabRow" type="button">+
<?= h(t('medical_document.parameter')) ?></button></div>
</div>
<div class="table-responsive">
<table class="table table-sm align-middle">
<thead>
<tr>
<th><?= h(t('medical_document.parameter')) ?></th>
<th><?= h(t('medical_document.value')) ?></th>
<th><?= h(t('medical_document.unit')) ?></th>
<th><?= h(t('medical_document.reference_min')) ?></th>
<th><?= h(t('medical_document.reference_max')) ?></th>
<th></th>
</tr>
</thead>
<tbody id="labRows"></tbody>
</table>
</div>
</div>
<div class="col-12"><label class="form-label"><?= h(t('common.notes')) ?></label><textarea
class="form-control" name="notes" rows="2"></textarea></div>
</div>
</div>
<div class="modal-footer"><button type="button" class="btn me-auto"
data-bs-dismiss="modal"><?= h(t('common.cancel')) ?></button><button
class="btn btn-primary"><?= h(t('common.save')) ?></button></div>
</form>
</div>
</div>
<div class="modal modal-blur fade" id="modalMedicalStatus" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered" role="document">
<form class="modal-content" method="post" action="/animal/medical-status">
<div class="modal-header">
<h5 class="modal-title"><?= h(t('animal.medical_status_global')) ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"
aria-label="<?= h(t('common.close')) ?>"></button>
</div>
<div class="modal-body">
<input type="hidden" name="animal_id" value="<?= (int)$animal['id'] ?>">
<?php if ($isCat): ?><div class="alert alert-info">
<?= h(t('animal.positive_test_help')) ?>
</div>
<div class="row g-3">
<div class="col-md-6">
<label class="form-label"><?= h(t('animal.fiv_status')) ?></label>
<select class="form-select" name="fiv_status">
<?php foreach (['unknown' => t('animals.test_unknown'),'neg' => t('animals.test_negative'),'pos' => t('animals.test_positive'),'doubtful' => t('animals.test_doubtful')] as $value => $label): ?>
<option value="<?= h($value) ?>" <?= $fivStatus === $value ? 'selected' : '' ?>>
<?= h($label) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6">
<label class="form-label"><?= h(t('animal.felv_status')) ?></label>
<select class="form-select" name="felv_status">
<?php foreach (['unknown' => t('animals.test_unknown'),'neg' => t('animals.test_negative'),'pos' => t('animals.test_positive'),'doubtful' => t('animals.test_doubtful')] as $value => $label): ?>
<option value="<?= h($value) ?>" <?= $felvStatus === $value ? 'selected' : '' ?>>
<?= h($label) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-4">
<label class="form-label"><?= h(t('animal.test_date')) ?></label>
<input class="form-control" type="date" name="test_date" value="<?= date('Y-m-d') ?>">
</div>
<div class="col-md-8">
<label class="form-label"><?= h(t('animal.test_note')) ?></label>
<input class="form-control" name="test_notes"
placeholder="<?= h(t('animal.test_notes_placeholder')) ?>">
</div>
</div>
<hr class="my-4">
<?php endif; ?>
<div class="d-flex align-items-center justify-content-between mb-3">
<div>
<h4 class="m-0"><?= h(t('animal.conditions')) ?></h4>
<div class="text-muted small"><?= h(t('animal.conditions_help')) ?></div>
</div>
</div>
<?php foreach (($healthConditions ?? []) as $condition): ?>
<div class="row g-2 align-items-end mb-3">
<div class="col-md-4">
<label class="form-label"><?= h(t('animal.label')) ?></label>
<input class="form-control" name="conditions[<?= (int)$condition['id'] ?>][name]"
value="<?= h($condition['name']) ?>">
</div>
<div class="col-md-2">
<label class="form-label"><?= h(t('animal.state')) ?></label>
<select class="form-select" name="conditions[<?= (int)$condition['id'] ?>][status]">
<option value="active" <?= $condition['status'] === 'active' ? 'selected' : '' ?>>
<?= h(t('animal.active')) ?></option>
<option value="resolved" <?= $condition['status'] === 'resolved' ? 'selected' : '' ?>>
<?= h(t('animal.resolved')) ?></option>
</select>
</div>
<div class="col-md-2">
<label class="form-label"><?= h(t('animal.diagnosis')) ?></label>
<input class="form-control" type="date"
name="conditions[<?= (int)$condition['id'] ?>][diagnosed_at]"
value="<?= h($condition['diagnosed_at'] ?? '') ?>">
</div>
<div class="col-md-4">
<label class="form-label"><?= h(t('animal.note')) ?></label>
<input class="form-control" name="conditions[<?= (int)$condition['id'] ?>][notes]"
value="<?= h($condition['notes'] ?? '') ?>">
</div>
</div>
<?php endforeach; ?>
<div class="card bg-light-lt">
<div class="card-body">
<div class="subheader mb-2"><?= h(t('animal.add_condition')) ?></div>
<div class="row g-2">
<div class="col-md-4"><input class="form-control" name="conditions[new][name]"
placeholder="<?= h(t('animal.condition_placeholder')) ?>"></div>
<div class="col-md-2">
<select class="form-select" name="conditions[new][status]">
<option value="active"><?= h(t('animal.active')) ?></option>
<option value="resolved"><?= h(t('animal.resolved')) ?></option>
</select>
</div>
<div class="col-md-2"><input class="form-control" type="date"
name="conditions[new][diagnosed_at]" value="<?= date('Y-m-d') ?>"></div>
<div class="col-md-4"><input class="form-control" name="conditions[new][notes]"
placeholder="Note facultative"></div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn me-auto" data-bs-dismiss="modal"><?= h(t('common.cancel')) ?></button>
<button type="submit" class="btn btn-primary"><?= h(t('animal.save_medical_status')) ?></button>
</div>
</form>
</div>
</div>
<div class="modal modal-blur fade" id="modalMedical" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered" role="document">
<form class="modal-content" method="post" action="/animal/add-medical" enctype="multipart/form-data">
<div class="modal-header">
<h5 class="modal-title"><?= h(t('animal.add_medical_note')) ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"
aria-label="<?= h(t('common.close')) ?>"></button>
</div>
<div class="modal-body">
<input type="hidden" name="animal_id" value="<?= (int)$animal['id'] ?>">
<div class="row g-2">
<div class="col-md-4">
<label class="form-label"><?= h(t('animal.form.type')) ?></label>
<select class="form-select" name="kind">
<option value="consult"><?= h(t('animal.consultation')) ?></option>
<option value="controle"><?= h(t('animal.checkup')) ?></option>
<option value="symptome"><?= h(t('animal.symptom')) ?></option>
<option value="diagnostic"><?= h(t('animal.diagnosis')) ?></option>
<option value="acte"><?= h(t('animal.procedure')) ?></option>
<option value="hosp"><?= h(t('animal.hospitalization')) ?></option>
<option value="autre"><?= h(t('animal.other')) ?></option>
</select>
</div>
<div class="col-md-8">
<label class="form-label"><?= h(t('animal.reason')) ?></label>
<input class="form-control" name="reason" id="medicalReason"
placeholder="<?= h(t('animal.reason_placeholder')) ?>">
</div>
<div class="col-12">
<div class="card card-sm mb-0 <?= !empty($animal['sterilized']) ? 'bg-light-lt' : '' ?>">
<div class="card-body py-2 px-3">
<label class="form-check m-0">
<input class="form-check-input" type="checkbox" name="mark_sterilized"
id="markSterilized" value="1"
<?= !empty($animal['sterilized']) ? 'checked disabled' : '' ?>>
<span class="form-check-label">
<span class="fw-bold d-block"><?= h(t('animal.sterilization_act')) ?></span>
<span
class="form-hint mt-0"><?= h(!empty($animal['sterilized']) ? t('animal.already_sterilized') : t('animal.sterilization_auto', ['price' => AppSettings::int('adoption_fee_sterilized')])) ?></span>
</span>
</label>
</div>
</div>
</div>
<?php $directoryFieldId = 'medical';
require __DIR__ . '/_directory_medical_fields.php'; ?>
<?php require __DIR__ . '/_expense_tariff_field.php'; ?>
<div class="col-md-6">
<label class="form-label"><?= h(t('common.weight')) ?></label>
<input class="form-control" name="weight_kg" inputmode="decimal" placeholder="Ex: 4.2">
</div>
<div class="col-md-6">
<label class="form-label"><?= h(t('animal.temperature')) ?></label>
<input class="form-control" name="temperature_c" inputmode="decimal" placeholder="Ex: 38.6">
</div>
<div class="col-12">
<label class="form-label"><?= h(t('animal.symptoms')) ?></label>
<textarea class="form-control" name="symptoms" rows="2"></textarea>
</div>
<div class="col-12">
<label class="form-label"><?= h(t('animal.exam')) ?></label>
<textarea class="form-control" name="exam" rows="2"></textarea>
</div>
<div class="mb-3">
<label class="form-label"><?= h(t('animal.medical_photos')) ?></label>
<input type="file" name="medical_photos[]" class="form-control" accept="image/*" multiple>
<small class="text-muted">
<?= h(t('animal.medical_photos_hint')) ?>
</small>
</div>
<div class="col-12">
<label class="form-label"><?= h(t('animal.diagnosis')) ?></label>
<textarea class="form-control" name="diagnosis" rows="2"></textarea>
</div>
<div class="col-12">
<label class="form-label"><?= h(t('animal.plan')) ?></label>
<textarea class="form-control" name="plan" rows="2"></textarea>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn me-auto" data-bs-dismiss="modal"><?= h(t('common.cancel')) ?></button>
<button type="submit" class="btn btn-primary"><?= h(t('common.save')) ?></button>
</div>
</form>
</div>
</div>
<?php endif; ?>
<script>
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('.directory-contact-select').forEach(select => {
const target = document.getElementById(select.dataset.newTarget || '');
const sync = () => {
const creating = select.value === 'new';
target?.classList.toggle('d-none', !creating);
if (target) target.required = creating;
};
select.addEventListener('change', sync);
sync();
});
document.querySelectorAll('.medical-vet-select').forEach(vet => {
const pair = vet.dataset.pair;
const clinic = document.querySelector(`.medical-clinic-select[data-pair="${pair}"]`);
if (!clinic) return;
const filterVets = () => {
const clinicId = clinic.value;
[...vet.options].forEach(option => {
if (!option.value || option.value === 'new') return;
const organization = option.dataset.organization || '';
option.hidden = Boolean(clinicId && clinicId !== 'new' &&
organization && organization !== clinicId);
});
if (vet.selectedOptions[0]?.hidden) vet.value = '';
};
vet.addEventListener('change', () => {
const organization = vet.selectedOptions[0]?.dataset.organization;
if (organization && organization !== '0') {
clinic.value = organization;
clinic.dispatchEvent(new Event('change', {
bubbles: true
}));
}
});
clinic.addEventListener('change', filterVets);
filterVets();
});
const sterilizedCheckbox = document.getElementById('markSterilized');
sterilizedCheckbox?.addEventListener('change', () => {
if (!sterilizedCheckbox.checked) return;
const kind = sterilizedCheckbox.form.querySelector('select[name="kind"]');
const reason = document.getElementById('medicalReason');
if (kind) kind.value = 'acte';
if (reason && reason.value.trim() === '') reason.value = <?= json_encode(t(
'animal.sterilization_label'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> ;
});
const animalId = <?= (int) $animal['id'] ?> ;
const legacyKey = 'animal_show_active_tab_' + animalId;
// L'ancien comportement mémorisait le dernier onglet par animal. Une
// ouverture normale doit désormais toujours revenir sur Identité.
localStorage.removeItem(legacyKey);
const tabLinks = Array.from(document.querySelectorAll('a[data-bs-toggle="tab"]'));
function showTab(target) {
if (!target) return false;
const link = document.querySelector(`a[data-bs-toggle="tab"][href="${target}"]`);
if (!link) return false;
// 1) Bootstrap API si dispo
if (window.bootstrap && bootstrap.Tab) {
bootstrap.Tab.getOrCreateInstance(link).show();
return true;
}
// 2) Fallback “manuel” (au cas où)
tabLinks.forEach(a => a.classList.remove('active'));
document.querySelectorAll('.tab-pane').forEach(p => p.classList.remove('active', 'show'));
link.classList.add('active');
document.getElementById('animalMoreTabs')?.classList.toggle('active', link.classList.contains(
'dropdown-item'));
const pane = document.querySelector(target);
if (pane) pane.classList.add('active', 'show');
return true;
}
// Le fragment reste dans l'URL afin que les actions ciblées puissent
// revenir sur Médical, Photos, Portées, etc., sans mémorisation durable.
tabLinks.forEach(a => {
a.addEventListener('shown.bs.tab', (e) => {
const href = e.target.getAttribute('href');
if (!href) return;
const moreToggle = document.getElementById('animalMoreTabs');
moreToggle?.classList.toggle('active', e.target.classList.contains(
'dropdown-item'));
history.replaceState(null, '', href);
});
// Si jamais "shown.bs.tab" ne déclenche pas (rare), on sauvegarde au click aussi
a.addEventListener('click', () => {
const href = a.getAttribute('href');
if (!href) return;
history.replaceState(null, '', href);
});
});
// Un hash explicite est respecté ; sinon Identité est systématique.
const target = window.location.hash || '#tab-ident';
// Si bootstrap n'est pas prêt à l'instant T, on retente un peu (Tabler peut charger en bas)
let tries = 0;
(function retry() {
tries++;
const ok = showTab(target);
if (!ok && tries < 20) setTimeout(retry, 50);
})();
});
</script>
<script>
(function() {
const body = document.getElementById('labRows'),
add = document.getElementById('addLabRow'),
select = document.getElementById('labTemplate');
if (!body) return;
const presets = {};
const references = <?= json_encode($labReferenceSets ?? [], JSON_UNESCAPED_UNICODE |
JSON_UNESCAPED_SLASHES) ?> ;
Object.entries(references).forEach(([key, set]) => presets['ref:' + key] = (set.parameters || []).map(p => [
p.code + ' — ' + p.name, p.unit, p.min, p.max
]));
const esc = s => String(s ?? '').replace(/[&<>'"]/g, c => ({
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
"'": '&#039;',
'"': '&quot;'
} [c]));
const row = (name = '', unit = '', min = null, max = null) => {
const tr = document.createElement('tr');
tr.innerHTML =
`<td><input class="form-control form-control-sm" name="parameter_name[]" value="${esc(name)}" maxlength="120"></td><td><input class="form-control form-control-sm" type="number" step="any" name="value[]"></td><td><input class="form-control form-control-sm" name="unit[]" value="${esc(unit)}" maxlength="30"></td><td><input class="form-control form-control-sm" type="number" step="any" name="reference_min[]" value="${min??''}"></td><td><input class="form-control form-control-sm" type="number" step="any" name="reference_max[]" value="${max??''}"></td><td><button class="btn btn-sm btn-ghost-danger" type="button" aria-label="<?= h(t('common.delete')) ?>">×</button></td>`;
tr.querySelector('button').addEventListener('click', () => tr.remove());
body.appendChild(tr);
};
add?.addEventListener('click', () => row());
select?.addEventListener('change', () => {
if (!presets[select.value]) return;
body.innerHTML = '';
presets[select.value].forEach(v => row(v[0], v[1], v[2], v[3]));
});
body.addEventListener('keydown', event => {
if (event.key !== 'Tab' || !event.target.matches('input[name="value[]"]')) return;
const values = [...body.querySelectorAll('input[name="value[]"]')],
index = values.indexOf(event.target),
next = values[index + (event.shiftKey ? -1 : 1)];
if (!next) return;
event.preventDefault();
next.focus();
next.select();
});
row();
})();
</script>
<script>
(function() {
document.querySelectorAll('.lab-chart').forEach(canvas => {
const s = JSON.parse(canvas.dataset.series || '{}'),
points = s.points || [];
const color = p => p.min === null && p.max === null ? '#6c757d' : (p.min !== null && p.value < p
.min ? '#206bc4' : (p.max !== null && p.value > p.max ? '#d63939' : '#2fb344'));
new Chart(canvas, {
type: 'line',
data: {
labels: points.map(p => p.date.split('-').reverse().join('/')),
datasets: [{
label: s.name,
data: points.map(p => p.value),
borderColor: '#f59f00',
backgroundColor: '#f59f00',
pointBackgroundColor: points.map(color),
pointBorderColor: points.map(color),
pointRadius: 4,
tension: .2
}, {
label: <?= json_encode(t('medical_document.reference_min'),
JSON_UNESCAPED_UNICODE) ?> ,
data: points.map(p => p.min),
borderColor: '#74c0fc',
borderDash: [5, 5],
pointRadius: 0,
spanGaps: true
}, {
label: <?= json_encode(t('medical_document.reference_max'),
JSON_UNESCAPED_UNICODE) ?> ,
data: points.map(p => p.max),
borderColor: '#ffa8a8',
borderDash: [5, 5],
pointRadius: 0,
spanGaps: true
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
interaction: {
mode: 'index',
intersect: false
},
plugins: {
legend: {
display: true
}
},
scales: {
y: {
title: {
display: !!s.unit,
text: s.unit
}
},
x: {
title: {
display: true,
text: <?= json_encode(t('chart.date'), JSON_UNESCAPED_UNICODE) ?>
}
}
}
}
});
});
})();
</script>
<script>
(function() {
const el = document.getElementById('weightChart');
if (!el) return;
const rows = <?= json_encode($weights ?? [], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) ?> ;
// labels = dates, data = poids
const labels = rows.map(r => (r.measured_at || '').slice(0, 10)); // YYYY-MM-DD
const data = rows.map(r => Number(r.value));
// Chart.js default color (on ne fixe rien volontairement)
new Chart(el, {
type: 'line',
data: {
labels,
datasets: [{
label: <?= json_encode(t('chart.weight'), JSON_UNESCAPED_UNICODE) ?> ,
data,
tension: 0.25,
pointRadius: 2
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: true
}
},
scales: {
y: {
title: {
display: true,
text: 'kg'
}
},
x: {
title: {
display: true,
text: <?= json_encode(t('chart.date'), JSON_UNESCAPED_UNICODE) ?>
}
}
}
}
});
})();
</script>
<script>
(function() {
const btn = document.getElementById('btn-icad-refresh');
const body = document.getElementById('icad-card-body');
const tr = <?= json_encode(['error' => t('animal.icad_error'), 'empty' => t('animal.no_icad'), 'date' =>
t('common.date'), 'recorded' => t('animal.recorded'), 'noEvent' => t('animal.no_event'),
'holder' => t('animal.holder_internal'), 'name' => t('common.name'), 'phone' => t(
'common.phone'), 'email' => t('common.email'), 'icadName' => t('animal.icad_name'),
'microchip' => t('animal.microchip'), 'sex' => t('animal.sex'), 'birth' => t('animal.birth'),
'appearance' => t('animal.appearance'), 'history' => t('animal.icad_history'), 'fetching' => t(
'animal.icad_fetching'), 'fetchError' => t('animal.icad_fetch_error')
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> ;
if (!btn || !body) return;
function esc(s) {
return (s ?? '').toString()
.replaceAll('&', '&amp;').replaceAll('<', '&lt;')
.replaceAll('>', '&gt;').replaceAll('"', '&quot;')
.replaceAll("'", "&#039;");
}
function renderIcad(payload) {
const cache = payload?.cached;
const status = cache?.status ?? 'empty';
const err = cache?.error ?? '';
const d = cache?.data ?? null;
if (status === 'error') {
return `<div class="alert alert-danger"><strong>${esc(tr.error)}</strong><br>${esc(err)}</div>`;
}
if (status !== 'ok' || !d) {
return `<div class="text-muted">${esc(tr.empty)}</div>`;
}
const owner = d.owner ?? null;
const events = Array.isArray(d.events) ? d.events : [];
const eventsHtml = events.length ?
`<ul class="list list-timeline">` + events.map(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">${esc(e.label)}</div>
<div class="text-muted small">${esc(tr.date)} : ${esc(e.date)} — ${esc(tr.recorded)} : ${esc(e.recorded_at)}</div>
</div>
</li>
`).join('') + `</ul>` :
`<div class="text-muted">${esc(tr.noEvent)}</div>`;
let ownerHtml = '';
if (owner && (owner.name || owner.phone || owner.email)) {
ownerHtml = `
<hr class="my-3">
<div class="text-muted mb-2">${esc(tr.holder)}</div>
<div class="datagrid">
<div class="datagrid-item"><div class="datagrid-title">${esc(tr.name)}</div><div class="datagrid-content">${esc(owner.name)}</div></div>
<div class="datagrid-item"><div class="datagrid-title">${esc(tr.phone)}</div><div class="datagrid-content">${esc(owner.phone)}</div></div>
<div class="datagrid-item"><div class="datagrid-title">${esc(tr.email)}</div><div class="datagrid-content">${esc(owner.email)}</div></div>
</div>
`;
}
return `
<div class="row g-3">
<div class="col-md-6">
<div class="datagrid">
<div class="datagrid-item"><div class="datagrid-title">${esc(tr.icadName)}</div><div class="datagrid-content">${esc(d.name)}</div></div>
<div class="datagrid-item"><div class="datagrid-title">${esc(tr.microchip)}</div><div class="datagrid-content">${esc(d.insert)}</div></div>
<div class="datagrid-item"><div class="datagrid-title">${esc(tr.sex)}</div><div class="datagrid-content">${esc(d.sex)}</div></div>
<div class="datagrid-item"><div class="datagrid-title">${esc(tr.birth)}</div><div class="datagrid-content">${esc(d.birth_date)}</div></div>
<div class="datagrid-item"><div class="datagrid-title">${esc(tr.appearance)}</div><div class="datagrid-content">${esc(d.appearance)}</div></div>
</div>
</div>
<div class="col-md-6">
<div class="text-muted mb-2">${esc(tr.history)}</div>
${eventsHtml}
</div>
</div>
${ownerHtml}
`;
}
async function refresh() {
const id = btn.dataset.animalId;
btn.disabled = true;
const oldTxt = btn.innerText;
btn.innerText = '…';
const prev = body.innerHTML;
body.innerHTML = `<div class="text-muted">${esc(tr.fetching)}</div>`;
try {
const r = await fetch('/animal/icad', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
id,
force: '1',
csrf: <?= json_encode(Auth::csrf()) ?>
})
});
const j = await r.json();
body.innerHTML = renderIcad(j);
} catch (e) {
body.innerHTML = prev;
alert(tr.fetchError);
console.error(e);
} finally {
btn.disabled = false;
btn.innerText = oldTxt;
}
}
btn.addEventListener('click', refresh);
})();
</script>
<?php require __DIR__ . '/_deworming_modal.php'; ?>
<?php require __DIR__ . '/_expense_modal.php'; ?>