- Ajout page infrastructure/bovine avec CRUD - Refacto BuildingCase (suppression Statut, simplification) - Commande EnrichBovinesCommand pour enrichir les données bovins - 4 migrations Doctrine - Mise à jour composables shipment/weighing - Mise à jour README et CHANGELOG Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
135 lines
4.7 KiB
Vue
135 lines
4.7 KiB
Vue
<template>
|
|
<div class="px-[86px]">
|
|
<div class="flex items-center justify-between relative">
|
|
<div class="flex flex-row absolute -left-[60px]">
|
|
<Icon
|
|
@click="router.push('/infrastructure/building')"
|
|
name="gg:arrow-left-o"
|
|
size="44"
|
|
class="cursor-pointer text-primary-500"
|
|
/>
|
|
</div>
|
|
<div class="flex items-center gap-4">
|
|
<h1 class="font-bold text-4xl text-primary-500 uppercase">
|
|
{{ title }}
|
|
</h1>
|
|
<div
|
|
v-if="hasCaseId"
|
|
class="bg-primary-500 p-1 rounded-md flex items-center cursor-pointer"
|
|
title="Imprimer"
|
|
@click="printCaseReport"
|
|
>
|
|
<Icon name="mdi:printer-outline" size="32" class="text-white" />
|
|
</div>
|
|
</div>
|
|
<NuxtLink
|
|
v-if="hasCaseId"
|
|
:to="addBovineRoute"
|
|
class="inline-flex items-center justify-center text-xl text-white uppercase bg-primary-500 h-[50px] px-6 rounded hover:opacity-80 gap-2"
|
|
:class="auth.isAdmin ? '' : 'cursor-not-allowed opacity-60 pointer-events-none'"
|
|
>
|
|
<Icon name="mdi:plus" size="28" />
|
|
Ajouter
|
|
</NuxtLink>
|
|
</div>
|
|
|
|
<div class="mt-8 border border-slate-200 mb-16">
|
|
<div
|
|
class="grid grid-cols-3 gap-4 bg-slate-100 px-4 py-3 text-sm font-semibold uppercase tracking-wide"
|
|
>
|
|
<div>Numéro national</div>
|
|
<div>Poids à l'arrivée (kg)</div>
|
|
<div>Date d'arrivée</div>
|
|
</div>
|
|
<template v-if="bovines.length > 0">
|
|
<div
|
|
v-for="bovine in bovines"
|
|
:key="bovine.id"
|
|
class="grid grid-cols-3 gap-4 px-4 py-3 text-sm border-t border-slate-200"
|
|
:class="auth.isAdmin ? 'cursor-pointer hover:bg-slate-50' : ''"
|
|
:role="auth.isAdmin ? 'button' : undefined"
|
|
:tabindex="auth.isAdmin ? 0 : undefined"
|
|
@click="goToBovine(bovine.id)"
|
|
@keydown.enter="goToBovine(bovine.id)"
|
|
>
|
|
<div>{{ bovine.nationalNumber }}</div>
|
|
<div>{{ bovine.receivedWeight ?? '—' }}</div>
|
|
<div>{{ formatDate(bovine.arrivalDate) }}</div>
|
|
</div>
|
|
</template>
|
|
<div
|
|
v-else
|
|
class="px-4 py-3 text-sm border-t border-slate-200 text-slate-500"
|
|
>
|
|
Aucun bovin dans cette case.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<script setup lang="ts">
|
|
import type { BuildingCaseData } from '~/services/dto/building-case-data'
|
|
import { useAuthStore } from '~/stores/auth'
|
|
|
|
const route = useRoute()
|
|
const router = useRouter()
|
|
const { printPdf } = usePdfPrinter()
|
|
const api = useApi()
|
|
const auth = useAuthStore()
|
|
|
|
const caseId = computed(() => Number(route.query.id))
|
|
const hasCaseId = computed(() => Number.isFinite(caseId.value) && caseId.value > 0)
|
|
|
|
const buildingCase = ref<BuildingCaseData | null>(null)
|
|
const bovines = computed(() => buildingCase.value?.bovines ?? [])
|
|
|
|
const title = computed(() => {
|
|
if (!buildingCase.value) return ''
|
|
const buildingLabel = buildingCase.value.building?.label ?? ''
|
|
const caseNumber = buildingCase.value.caseNumber ?? ''
|
|
return `${buildingLabel} case ${caseNumber}`.trim()
|
|
})
|
|
|
|
const addBovineRoute = computed(() => ({
|
|
path: '/infrastructure/bovine',
|
|
query: { caseId: String(caseId.value) }
|
|
}))
|
|
|
|
const formatDate = (date: string | null) => {
|
|
if (!date) return '—'
|
|
const d = new Date(date)
|
|
if (isNaN(d.getTime())) return date
|
|
return d.toLocaleDateString('fr-FR', {
|
|
day: '2-digit',
|
|
month: '2-digit',
|
|
year: 'numeric'
|
|
})
|
|
}
|
|
|
|
const loadCase = async () => {
|
|
if (!hasCaseId.value) {
|
|
buildingCase.value = null
|
|
return
|
|
}
|
|
buildingCase.value = await api.get<BuildingCaseData>(`/building_cases/${caseId.value}`)
|
|
}
|
|
|
|
const printCaseReport = async () => {
|
|
if (!hasCaseId.value) {
|
|
return
|
|
}
|
|
|
|
const filename = `tableau_poids_case_${caseId.value}.pdf`
|
|
await printPdf(`/building_cases/${caseId.value}/weights-report`, filename)
|
|
}
|
|
|
|
const goToBovine = (id: number) => {
|
|
if (!auth.isAdmin) return
|
|
router.push({
|
|
path: '/infrastructure/bovine',
|
|
query: { id: String(id), caseId: String(caseId.value) }
|
|
})
|
|
}
|
|
|
|
watch(caseId, loadCase, { immediate: true })
|
|
</script>
|