Files
Ferme/frontend/components/reception/reception-form.vue
AUTIN Tristan 4a77449a41 [#203] Réceptions — Parcours de pesée multi-étapes (première partie) (!3)
| Numéro du ticket | Titre du ticket |
|------------------|-----------------|
|        #203          |      Réceptions — Parcours de pesée multi-étapes         |

## Description de la PR
[#203] Réceptions — Parcours de pesée multi-étapes

## Modification du .env

## Check list

- [x] Pas de régression
- [x] TU/TI/TF rédigée
- [x] TU/TI/TF OK
- [x] CHANGELOG modifié

Reviewed-on: #3
Reviewed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
Co-authored-by: AUTIN Tristan <tristan@yuno.malio.fr>
Co-committed-by: AUTIN Tristan <tristan@yuno.malio.fr>
2026-01-14 07:17:34 +00:00

108 lines
3.8 KiB
Vue

<template>
<form @submit.prevent="validate">
<div class="grid grid-cols-1 items-start gap-8 mb-16">
<h1 class="font-bold text-5xl uppercase">Réception</h1>
<div class="flex flex-col">
<label for="license-plate" class="font-bold uppercase text-xl mb-4">Immatriculation</label>
<input
id="license-plate"
v-model="form.licensePlate"
type="text"
class="border-b border-black justify-self-start text-xl pb-[6px] uppercase"
/>
<p v-if="fieldErrors.licensePlate" class="text-red-600 text-sm">{{ fieldErrors.licensePlate }}</p>
</div>
<div class="flex flex-col">
<label for="reception-date" class="font-bold uppercase text-xl mb-4">Date de reception</label>
<input
id="reception-date"
v-model="form.receptionDate"
type="date"
class="border-b border-black justify-self-start text-xl pb-[6px] uppercase"
/>
<p v-if="fieldErrors.receptionDate" class="text-red-600 text-sm">{{ fieldErrors.receptionDate }}</p>
</div>
</div>
<div class="flex justify-center">
<button
type="submit"
class="text-xl uppercase bg-primary-500 text-white h-[50px] w-[272px] justify-self-end"
>Valider
</button>
</div>
<p v-if="errorMessage" class="text-red-600 mt-4">{{ errorMessage }}</p>
</form>
</template>
<script setup lang="ts">
import { storeToRefs } from 'pinia'
import { z } from 'zod'
import { mapZodErrors } from '~/utils/zod-errors'
import { useReceptionStore } from '~/stores/reception'
type ReceptionFormData = {
licensePlate: string
receptionDate: string
}
const receptionStore = useReceptionStore()
const { errorMessage: storeErrorMessage, current: storeReception } = storeToRefs(receptionStore)
const form = reactive<ReceptionFormData>({
licensePlate: '',
receptionDate: ''
})
const fieldErrors = reactive<Partial<Record<keyof ReceptionFormData, string>>>({
licensePlate: undefined,
receptionDate: undefined
})
const errorMessage = computed(() => storeErrorMessage.value)
const formSchema = z.object({
licensePlate: z
.string()
.min(1, 'Immatriculation requise.')
.max(20, 'Immatriculation trop longue (20 caracteres max).'),
receptionDate: z
.string()
.min(1, 'Date de reception requise.')
.regex(/^\d{4}-\d{2}-\d{2}$/, 'Date de reception invalide.')
})
watch(
storeReception,
(reception) => {
form.licensePlate = reception?.licensePlate ?? ''
form.receptionDate = reception?.receptionDate ?? ''
},
{ immediate: true }
)
async function validate() {
if (!receptionStore.current) {
return
}
fieldErrors.licensePlate = undefined
fieldErrors.receptionDate = undefined
const normalizedLicensePlate = form.licensePlate.trim()
const normalizedReceptionDate = form.receptionDate.trim()
const result = formSchema.safeParse({
licensePlate: normalizedLicensePlate,
receptionDate: normalizedReceptionDate
})
if (!result.success) {
const errors = mapZodErrors<ReceptionFormData>(result.error)
fieldErrors.licensePlate = errors.licensePlate ?? 'Formulaire invalide.'
fieldErrors.receptionDate = errors.receptionDate ?? 'Formulaire invalide.'
return
}
const nextStep = receptionStore.current.currentStep + 1
await receptionStore.updateReception(receptionStore.current.id, {
currentStep: nextStep,
licensePlate: normalizedLicensePlate || null,
receptionDate: normalizedReceptionDate || null
})
}
</script>