refactor(bovine) : redirige page case vers Vie du bovin et supprime l'édition front
- infrastructure/case : clic ligne → /bovine/{id}, bouton Ajouter retiré, row-clickable ouvert à tous
- infrastructure/bovine.vue supprimée (création/édition de bovin gérée via EDNOTIF)
- bouton précédent de la page Vie du bovin : router.back avec fallback /inventory
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
<div class="flex items-center justify-between relative mb-10">
|
||||
<div class="flex flex-row absolute -left-[60px]">
|
||||
<Icon
|
||||
@click="router.push('/inventory')"
|
||||
@click="goBack"
|
||||
name="gg:arrow-left-o"
|
||||
size="44"
|
||||
class="cursor-pointer text-primary-500"
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
<div v-show="activeTab === 'mouvement'">
|
||||
<form :class="{ submitted: movementSubmitted }" @submit.prevent="submitMovement">
|
||||
<div class="flex flex-cols-3 justify-between mb-11 pt-7">
|
||||
<div class="flex flex-cols-3 justify-between mb-10">
|
||||
<UiSelect
|
||||
id="movement-building"
|
||||
v-model="newMovementBuildingId"
|
||||
@@ -207,6 +207,14 @@ const router = useRouter()
|
||||
const route = useRoute()
|
||||
const api = useApi()
|
||||
|
||||
const goBack = () => {
|
||||
if (window.history.state?.back) {
|
||||
router.back()
|
||||
} else {
|
||||
router.push('/inventory')
|
||||
}
|
||||
}
|
||||
|
||||
const bovine = ref<BovinePassportData | null>(null)
|
||||
const buildings = ref<BuildingData[]>([])
|
||||
const newMovementBuildingId = ref<string | number | null>(null)
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
<template>
|
||||
<form :class="{ submitted }" @submit.prevent="validate">
|
||||
<div class="flex items-center relative">
|
||||
<div class="flex flex-row absolute -left-[60px]">
|
||||
<Icon
|
||||
@click="goBack"
|
||||
name="gg:arrow-left-o"
|
||||
size="40"
|
||||
class="cursor-pointer text-primary-500"
|
||||
/>
|
||||
</div>
|
||||
<h1 class="text-3xl text-primary-500 font-bold uppercase">
|
||||
{{ isEdit ? 'Modification d\'un bovin' : 'Ajout d\'un bovin' }}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-cols-3 justify-between mb-11 pt-7">
|
||||
<UiTextInput
|
||||
id="bovine-national-number"
|
||||
v-model="form.nationalNumber"
|
||||
label="Numéro national"
|
||||
:disabled="!auth.isAdmin || isLoading"
|
||||
wrapper-class="w-[280px]"
|
||||
required
|
||||
/>
|
||||
<UiNumberInput
|
||||
id="bovine-received-weight"
|
||||
v-model="form.receivedWeight"
|
||||
label="Poids à l'arrivée (kg)"
|
||||
:min="0"
|
||||
:disabled="!auth.isAdmin || isLoading"
|
||||
wrapper-class="w-[280px] flex-col"
|
||||
label-class="font-bold uppercase"
|
||||
/>
|
||||
<UiDateInput
|
||||
id="bovine-arrival-date"
|
||||
v-model="form.arrivalDate"
|
||||
label="Date d'arrivée"
|
||||
:disabled="!auth.isAdmin || isLoading"
|
||||
wrapper-class="w-[280px]"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-cols-3 justify-between mb-11">
|
||||
<UiSelect
|
||||
id="bovine-supplier"
|
||||
v-model="form.supplierId"
|
||||
label="Vendeur"
|
||||
:options="supplierOptions"
|
||||
:loading="isLoadingSuppliers"
|
||||
:disabled="!auth.isAdmin || isLoading"
|
||||
wrapper-class="w-[280px]"
|
||||
/>
|
||||
<div class="w-[280px]" />
|
||||
<div class="w-[280px]" />
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-center">
|
||||
<UiButton
|
||||
type="submit"
|
||||
:disabled="!auth.isAdmin || isLoading"
|
||||
class="inline-flex mb-28 items-center justify-center text-xl min-w-[194px] gap-2 text-white uppercase bg-primary-500 h-[50px] rounded hover:opacity-80 justify-self-end"
|
||||
@click="submitted = true"
|
||||
>
|
||||
<Icon :name="isEdit ? '' : 'mdi:plus'" size="28" />
|
||||
{{ isEdit ? 'Valider' : 'Ajouter' }}
|
||||
</UiButton>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
useHead({ title: 'Bovins' })
|
||||
|
||||
import { createBovine, getBovine, updateBovine } from '~/services/bovine'
|
||||
import type { BovinePayload } from '~/services/dto/bovine-data'
|
||||
import type { SupplierData } from '~/services/dto/supplier-data'
|
||||
import { getSupplierList } from '~/services/supplier'
|
||||
import { useAuthStore } from '~/stores/auth'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const auth = useAuthStore()
|
||||
|
||||
const caseId = computed(() => {
|
||||
const raw = Number(route.query.caseId)
|
||||
return Number.isFinite(raw) && raw > 0 ? raw : null
|
||||
})
|
||||
|
||||
const bovineId = computed(() => {
|
||||
const raw = Number(route.query.id)
|
||||
return Number.isFinite(raw) && raw > 0 ? raw : null
|
||||
})
|
||||
|
||||
const isEdit = computed(() => bovineId.value !== null)
|
||||
|
||||
const form = reactive<{
|
||||
nationalNumber: string
|
||||
receivedWeight: number | null
|
||||
arrivalDate: string | null
|
||||
supplierId: string
|
||||
}>({
|
||||
nationalNumber: '',
|
||||
receivedWeight: null,
|
||||
arrivalDate: null,
|
||||
supplierId: ''
|
||||
})
|
||||
|
||||
const isLoading = ref(false)
|
||||
const submitted = ref(false)
|
||||
const suppliers = ref<SupplierData[]>([])
|
||||
const isLoadingSuppliers = ref(false)
|
||||
|
||||
const supplierOptions = computed(() =>
|
||||
suppliers.value.map(s => ({ value: String(s.id), label: s.name }))
|
||||
)
|
||||
|
||||
const backRoute = computed(() => ({
|
||||
path: '/infrastructure/case',
|
||||
query: caseId.value ? { id: String(caseId.value) } : {}
|
||||
}))
|
||||
|
||||
const goBack = () => {
|
||||
router.push(backRoute.value)
|
||||
}
|
||||
|
||||
const loadSuppliers = async () => {
|
||||
isLoadingSuppliers.value = true
|
||||
try {
|
||||
suppliers.value = await getSupplierList()
|
||||
} finally {
|
||||
isLoadingSuppliers.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const hydrate = async () => {
|
||||
if (!isEdit.value || bovineId.value === null) {
|
||||
return
|
||||
}
|
||||
isLoading.value = true
|
||||
try {
|
||||
const bovine = await getBovine(bovineId.value)
|
||||
form.nationalNumber = bovine.nationalNumber ?? ''
|
||||
form.receivedWeight = bovine.receivedWeight ?? null
|
||||
form.arrivalDate = bovine.arrivalDate ?? null
|
||||
if (bovine.supplier) {
|
||||
const supplierId = bovine.supplier.replace(/.*\//, '')
|
||||
form.supplierId = supplierId
|
||||
}
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const validate = async () => {
|
||||
if (isLoading.value || !auth.isAdmin) return
|
||||
if (!caseId.value) return
|
||||
if (!form.nationalNumber.trim()) return
|
||||
|
||||
const payload: BovinePayload = {
|
||||
nationalNumber: form.nationalNumber.trim(),
|
||||
receivedWeight: form.receivedWeight,
|
||||
arrivalDate: form.arrivalDate,
|
||||
buildingCase: `/api/building_cases/${caseId.value}`,
|
||||
supplier: form.supplierId ? `/api/suppliers/${form.supplierId}` : null
|
||||
}
|
||||
|
||||
isLoading.value = true
|
||||
try {
|
||||
if (isEdit.value && bovineId.value !== null) {
|
||||
await updateBovine(bovineId.value, payload)
|
||||
} else {
|
||||
await createBovine(payload)
|
||||
}
|
||||
router.push(backRoute.value)
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(loadSuppliers)
|
||||
watch(bovineId, hydrate, { immediate: true })
|
||||
</script>
|
||||
@@ -23,14 +23,6 @@
|
||||
<Icon name="mdi:printer-outline" size="32" class="text-white" />
|
||||
</div>
|
||||
</div>
|
||||
<NuxtLink
|
||||
v-if="hasCaseId && auth.isAdmin"
|
||||
: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"
|
||||
>
|
||||
<Icon name="mdi:plus" size="28" />
|
||||
Ajouter
|
||||
</NuxtLink>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap gap-3 mt-4">
|
||||
@@ -56,7 +48,7 @@
|
||||
:items="items"
|
||||
:total-items="totalItems"
|
||||
:loading="loading"
|
||||
:row-clickable="auth.isAdmin"
|
||||
row-clickable
|
||||
empty-message="Aucun bovin dans cette case."
|
||||
@row-click="goToBovine"
|
||||
>
|
||||
@@ -134,7 +126,6 @@ useHead({ title: 'Cases' })
|
||||
|
||||
import type { BuildingCaseData } from '~/services/dto/building-case-data'
|
||||
import type { BovineData } from '~/services/dto/bovine-data'
|
||||
import { useAuthStore } from '~/stores/auth'
|
||||
import { useDataTableServerState } from '~/composables/useDataTableServerState'
|
||||
import { useBovineColumns } from '~/composables/useBovineColumns'
|
||||
import { formatAgeLabel, ageBadgeClass } from '~/utils/bovine-age'
|
||||
@@ -143,7 +134,6 @@ 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)
|
||||
@@ -233,11 +223,6 @@ const title = computed(() => {
|
||||
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)
|
||||
@@ -270,11 +255,7 @@ const printCaseReport = async () => {
|
||||
}
|
||||
|
||||
const goToBovine = (bovine: BovineData) => {
|
||||
if (!auth.isAdmin) return
|
||||
router.push({
|
||||
path: '/infrastructure/bovine',
|
||||
query: { id: String(bovine.id), caseId: String(caseId.value) }
|
||||
})
|
||||
router.push(`/bovine/${bovine.id}`)
|
||||
}
|
||||
|
||||
watch(caseId, (id) => {
|
||||
|
||||
Reference in New Issue
Block a user