feat(front) : sous-composant bovine-info-form (4 champs + valider)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-04 11:33:24 +02:00
parent 9af05ff449
commit 92c8c6a704

View File

@@ -0,0 +1,129 @@
<template>
<form class="space-y-6" :class="{ submitted }" @submit.prevent="submit">
<div class="grid grid-cols-2 gap-x-12 gap-y-6">
<UiNumberInput
v-model="form.receivedWeight"
label="Poids d'arrivée (kg)"
:min="0"
:step="1"
required
/>
<UiNumberInput
v-model="form.pricePerKg"
label="Prix d'achat (kg)"
:min="0"
:step="0.01"
required
/>
<UiSelect
v-model="form.buildingId"
label="Bâtiment"
:options="buildingOptions"
required
/>
<UiSelect
v-model="form.buildingCaseId"
label="Case"
:options="caseOptions"
:disabled="form.buildingId === null"
required
/>
</div>
<div class="flex justify-center">
<UiButton
type="submit"
class="text-md font-bold uppercase bg-primary-500 text-white h-[50px] px-8"
:disabled="isSaving"
:loading="isSaving"
>
Valider
</UiButton>
</div>
</form>
</template>
<script setup lang="ts">
import type { BovineData } from '~/services/dto/bovine-data'
import type { BuildingData } from '~/services/dto/building-data'
const props = defineProps<{
bovine: BovineData
buildings: BuildingData[]
}>()
const emit = defineEmits<{
saved: [bovine: BovineData]
}>()
const api = useApi()
interface FormState {
receivedWeight: number | null
pricePerKg: number | null
buildingId: number | null
buildingCaseId: number | null
}
const form = reactive<FormState>({
receivedWeight: props.bovine.receivedWeight,
pricePerKg: props.bovine.pricePerKg,
buildingId: props.bovine.buildingCase?.building?.id
?? props.bovine.effectiveBuilding?.id
?? null,
buildingCaseId: props.bovine.buildingCase?.id ?? null
})
const submitted = ref(false)
const isSaving = ref(false)
const buildingOptions = computed(() =>
props.buildings.map(b => ({ value: b.id, label: b.label }))
)
const caseOptions = computed(() => {
if (form.buildingId === null) return []
const building = props.buildings.find(b => b.id === form.buildingId)
if (!building?.buildingCases) return []
return building.buildingCases.map(c => ({
value: c.id,
label: c.caseNumber !== null ? `Case ${c.caseNumber}` : (c.code ?? `#${c.id}`)
}))
})
watch(() => form.buildingId, (newId) => {
if (form.buildingCaseId === null) return
const building = props.buildings.find(b => b.id === newId)
const caseStillValid = building?.buildingCases?.some(c => c.id === form.buildingCaseId)
if (!caseStillValid) {
form.buildingCaseId = null
}
})
const submit = async () => {
submitted.value = true
if (
form.receivedWeight === null
|| form.pricePerKg === null
|| form.buildingId === null
|| form.buildingCaseId === null
) {
return
}
isSaving.value = true
try {
const updated = await api.patch<BovineData>(
`bovines/${props.bovine.id}`,
{
receivedWeight: form.receivedWeight,
pricePerKg: form.pricePerKg,
buildingCase: `/api/building_cases/${form.buildingCaseId}`
}
)
emit('saved', updated)
} finally {
isSaving.value = false
}
}
</script>