feat : ajout de la génération du bon de reception, correction de la base du formulaire multi-etape de reception et ajout d'une gestion d'erreur global

This commit is contained in:
AUTIN Tristan
2026-01-15 18:37:44 +01:00
parent 4a77449a41
commit 94ea49587a
22 changed files with 1153 additions and 220 deletions
@@ -27,15 +27,13 @@
<button
type="submit"
class="text-xl uppercase bg-primary-500 text-white h-[50px] w-[272px] justify-self-end"
>Valider
>Peser
</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'
@@ -45,17 +43,16 @@ type ReceptionFormData = {
receptionDate: string
}
const router = useRouter()
const receptionStore = useReceptionStore()
const { errorMessage: storeErrorMessage, current: storeReception } = storeToRefs(receptionStore)
const form = reactive<ReceptionFormData>({
licensePlate: '',
receptionDate: ''
receptionDate: new Date().toISOString().slice(0, 10)
})
const fieldErrors = reactive<Partial<Record<keyof ReceptionFormData, string>>>({
licensePlate: undefined,
receptionDate: undefined
})
const errorMessage = computed(() => storeErrorMessage.value)
const formSchema = z.object({
licensePlate: z
.string()
@@ -68,19 +65,15 @@ const formSchema = z.object({
})
watch(
storeReception,
() => receptionStore.current,
(reception) => {
form.licensePlate = reception?.licensePlate ?? ''
form.receptionDate = reception?.receptionDate ?? ''
form.receptionDate = reception?.receptionDate ?? new Date().toISOString().slice(0, 10)
},
{ immediate: true }
)
async function validate() {
if (!receptionStore.current) {
return
}
fieldErrors.licensePlate = undefined
fieldErrors.receptionDate = undefined
const normalizedLicensePlate = form.licensePlate.trim()
@@ -96,6 +89,18 @@ async function validate() {
return
}
if (!receptionStore.current) {
const created = await receptionStore.createReception({
currentStep: 1,
licensePlate: normalizedLicensePlate || null,
receptionDate: normalizedReceptionDate || null
})
if (created) {
await router.push(`/reception/${created.id}`)
}
return
}
const nextStep = receptionStore.current.currentStep + 1
await receptionStore.updateReception(receptionStore.current.id, {
currentStep: nextStep,
@@ -2,13 +2,13 @@
<div class="flex flex-col items-center mt-[164px] gap-32">
<div class="flex gap-8 items-center justify-center">
<!--@TODO Prendre en compte que l'on peut aussi décharger de la marchandise-->
<h1 class="text-3xl uppercase font-bold">Décharger les bêtes</h1>
<h1 class="text-4xl uppercase font-bold">Décharger les bêtes</h1>
<UiLoadingDots />
</div>
<button
class="text-xl uppercase bg-primary-500 text-white h-[50px] w-[272px]"
@click="goNext"
>Suivant</button>
>Peser</button>
</div>
</template>
@@ -5,20 +5,19 @@
<!--@TODO Voir comment faire pour savoir si le pont-bascule et bien connecté + ajouter un icon comme sur la maquette-->
<p class="text-primary-500 uppercase text-2xl mt-2">Pont-bascule connecté</p>
<div
v-if="errorMessage || showLoadingBox"
v-if="showLoadingBox"
class="w-full flex flex-col items-center justify-center border border-black h-[90px] mt-12 mb-[86px]">
<p v-if="errorMessage" class="text-red-500">{{ errorMessage }}</p>
<UiLoadingDots v-else />
<UiLoadingDots />
</div>
<div v-else-if="displayWeight !== null" class="w-full">
<div
class="w-full flex flex-col items-center justify-center border border-black h-[90px] mt-12 mb-[25px] text-4xl">
{{ displayWeight }} kg
</div>
<div class="grid grid-cols-2 border border-black text-center">
<p class="border-r border-black py-3 text-4xl font-bold">DSD</p>
<p class="py-3 text-4xl">{{ displayDsd }}</p>
</div>
<!-- <div class="grid grid-cols-2 border border-black text-center">-->
<!-- <p class="border-r border-black py-3 text-4xl font-bold">DSD</p>-->
<!-- <p class="py-3 text-4xl">{{ displayDsd }}</p>-->
<!-- </div>-->
</div>
</div>
</div>
@@ -28,15 +27,22 @@
@click="fetchWeight"
>{{ displayWeight !== null ? 'refaire une pesee' : 'peser' }}</button>
<button
v-if="displayWeight !== null"
v-if="displayWeight !== null && !showGenerateReceipt"
class="text-xl uppercase bg-primary-500 text-white h-[50px] w-[272px] ml-4"
@click="saveWeight"
>Valider la pesée</button>
<button
v-if="showGenerateReceipt"
class="text-xl uppercase bg-primary-500 text-white h-[50px] w-[272px] ml-4"
@click="printReceipt"
>Générer le bon</button>
</div>
<UiPdfPrinter ref="pdfPrinter" />
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import { storeToRefs } from 'pinia'
import { useWeighing } from '~/composables/useWeighing'
import { useReceptionStore } from '~/stores/reception'
@@ -45,13 +51,18 @@ const props = defineProps<{
mode: 'gross' | 'tare'
}>()
const router = useRouter()
const receptionStore = useReceptionStore()
const { current: storeReception, errorMessage: storeErrorMessage } = storeToRefs(receptionStore)
const { current: storeReception } = storeToRefs(receptionStore)
type PdfPrinterHandle = {
print: (url: string) => Promise<void>
}
// Ref sur le composant d'impression pour déclencher le print() du PDF.
const pdfPrinter = ref<PdfPrinterHandle | null>(null)
const {
displayWeight,
displayDsd,
title,
errorMessage,
showLoadingBox,
fetchWeight,
saveWeight
@@ -59,9 +70,35 @@ const {
mode: props.mode,
reception: storeReception,
updateReception: receptionStore.updateReception,
loadReception: receptionStore.loadReception,
storeError: storeErrorMessage
loadReception: receptionStore.loadReception
})
// @TODO Voir comment mettre en place la genération du bon, la validation de la reception et le dernier step
const showGenerateReceipt = computed(
() => props.mode === 'tare' && displayWeight.value !== null
)
const printReceipt = async () => {
if (!import.meta.client || !receptionStore.current || !pdfPrinter.value) {
return
}
await saveWeight()
await pdfPrinter.value.print(`/receptions/${receptionStore.current.id}/receipt`)
// Laisse le temps a la boite de dialogue d'impression de s'ouvrir.
await new Promise((resolve) => setTimeout(resolve, 600))
const result = await receptionStore.updateReception(receptionStore.current.id, {
isValid: true
})
if (!result) {
return
}
receptionStore.clearCurrent()
await router.push('/')
}
onMounted(() => {
fetchWeight()
})
</script>
+20
View File
@@ -0,0 +1,20 @@
<template>
<iframe ref="printFrame" class="hidden" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { usePdfPrinter } from '~/composables/usePdfPrinter'
const printFrame = ref<HTMLIFrameElement | null>(null)
const { printPdf } = usePdfPrinter()
// Expose une methode simple pour imprimer un PDF depuis les ecrans.
const print = async (url: string): Promise<void> => {
return printPdf(url, printFrame)
}
defineExpose({
print
})
</script>
+65 -12
View File
@@ -4,22 +4,72 @@ import { $fetch, FetchError } from 'ofetch'
export type AnyObject = Record<string, unknown>
export type ApiClient = {
get<T>(url: string, query?: AnyObject, options?: FetchOptions<'json'>): Promise<T>
post<T>(url: string, body?: AnyObject, options?: FetchOptions<'json'>): Promise<T>
put<T>(url: string, body?: AnyObject, options?: FetchOptions<'json'>): Promise<T>
patch<T>(url: string, body?: AnyObject, options?: FetchOptions<'json'>): Promise<T>
delete<T>(url: string, query?: AnyObject, options?: FetchOptions<'json'>): Promise<T>
get<T>(url: string, query?: AnyObject, options?: ApiFetchOptions<'json'>): Promise<T>
getBlob(url: string, query?: AnyObject, options?: ApiFetchOptions<'blob'>): Promise<Blob>
post<T>(url: string, body?: AnyObject, options?: ApiFetchOptions<'json'>): Promise<T>
put<T>(url: string, body?: AnyObject, options?: ApiFetchOptions<'json'>): Promise<T>
patch<T>(url: string, body?: AnyObject, options?: ApiFetchOptions<'json'>): Promise<T>
delete<T>(url: string, query?: AnyObject, options?: ApiFetchOptions<'json'>): Promise<T>
}
export type ApiFetchOptions<ResponseType extends 'json' | 'blob'> =
FetchOptions<ResponseType> & {
toast?: boolean
toastTitle?: string
}
export const useApi = (): ApiClient => {
const config = useRuntimeConfig()
const baseURL = config.public.apiBase ?? '/api'
const client = $fetch.create({ baseURL, retry: 0 })
const toast = useToast()
const extractErrorMessage = (error: unknown, responseData?: unknown): string => {
const data = responseData ?? (error as FetchError)?.data
if (typeof data === 'string') {
return data
}
if (data && typeof data === 'object') {
const record = data as Record<string, unknown>
return (
(record['hydra:description'] as string) ||
(record.detail as string) ||
(record.message as string) ||
(record.error as string) ||
(record.title as string) ||
(record['hydra:title'] as string) ||
''
)
}
return (error as FetchError)?.message ?? 'Erreur inconnue.'
}
const client = $fetch.create({
baseURL,
retry: 0,
onResponseError({ response, error, options }) {
const apiOptions = options as ApiFetchOptions<'json'>
if (apiOptions?.toast === false) {
return
}
const message =
extractErrorMessage(error, response?._data) ||
'Une erreur est survenue.'
toast.error({
title: apiOptions?.toastTitle ?? 'Erreur',
message
})
}
})
const request = <T>(
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',
url: string,
options: FetchOptions<'json'> = {}
options: ApiFetchOptions<'json'> = {}
) => {
const needsJsonBody = method === 'POST' || method === 'PUT'
const needsMergePatch = method === 'PATCH'
@@ -36,19 +86,22 @@ export const useApi = (): ApiClient => {
}
return {
get<T>(url: string, query: AnyObject = {}, options: FetchOptions<'json'> = {}) {
get<T>(url: string, query: AnyObject = {}, options: ApiFetchOptions<'json'> = {}) {
return request<T>('GET', url, { ...options, query })
},
post<T>(url: string, body: AnyObject = {}, options: FetchOptions<'json'> = {}) {
getBlob(url: string, query: AnyObject = {}, options: ApiFetchOptions<'blob'> = {}) {
return client<Blob>(url, { ...options, method: 'GET', query, responseType: 'blob' })
},
post<T>(url: string, body: AnyObject = {}, options: ApiFetchOptions<'json'> = {}) {
return request<T>('POST', url, { ...options, body })
},
put<T>(url: string, body: AnyObject = {}, options: FetchOptions<'json'> = {}) {
put<T>(url: string, body: AnyObject = {}, options: ApiFetchOptions<'json'> = {}) {
return request<T>('PUT', url, { ...options, body })
},
patch<T>(url: string, body: AnyObject = {}, options: FetchOptions<'json'> = {}) {
patch<T>(url: string, body: AnyObject = {}, options: ApiFetchOptions<'json'> = {}) {
return request<T>('PATCH', url, { ...options, body })
},
delete<T>(url: string, query: AnyObject = {}, options: FetchOptions<'json'> = {}) {
delete<T>(url: string, query: AnyObject = {}, options: ApiFetchOptions<'json'> = {}) {
return request<T>('DELETE', url, { ...options, query })
}
}
+40
View File
@@ -0,0 +1,40 @@
import type { Ref } from 'vue'
import { useApi } from '~/composables/useApi'
type PrintFrameRef = Ref<HTMLIFrameElement | null>
export const usePdfPrinter = () => {
const api = useApi()
const printPdf = async (url: string, frameRef: PrintFrameRef): Promise<void> => {
if (!import.meta.client) {
return
}
const frame = frameRef.value
if (!frame) {
return
}
// On charge le PDF en blob pour rester en same-origin dans l'iframe.
const blob = await api.getBlob(url)
const blobUrl = URL.createObjectURL(blob)
const tryPrint = () => {
frame.contentWindow?.focus()
frame.contentWindow?.print()
}
frame.onload = () => {
tryPrint()
// On libere l'URL blob apres l'impression.
setTimeout(() => URL.revokeObjectURL(blobUrl), 2000)
}
frame.src = blobUrl
setTimeout(tryPrint, 1200)
}
return {
printPdf
}
}
+34 -44
View File
@@ -1,9 +1,9 @@
import { computed, ref } from 'vue'
import type { Ref } from 'vue'
import type { ReceptionData, WeightEntryData } from '~/services/dto/reception-data'
import type { WeightData } from '~/services/dto/weight-data'
import { getWeight } from '~/services/reception'
import { createWeight, updateWeight } from '~/services/weight'
import type {Ref} from 'vue'
import {computed, ref} from 'vue'
import type {ReceptionData, WeightEntryData} from '~/services/dto/reception-data'
import type {WeightData} from '~/services/dto/weight-data'
import {getWeight} from '~/services/reception'
import {createWeight, updateWeight} from '~/services/weight'
export type WeighingMode = 'gross' | 'tare'
@@ -12,18 +12,16 @@ type UseWeighingOptions = {
reception: Ref<ReceptionData | null>
updateReception: (id: number, payload: Partial<ReceptionData>) => Promise<ReceptionData | null>
loadReception?: (id: number) => Promise<ReceptionData | null>
storeError?: Ref<string | null>
}
export const useWeighing = ({
mode,
reception,
updateReception,
loadReception,
storeError
loadReception
}: UseWeighingOptions) => {
const weightData = ref<WeightData | null>(null)
const localErrorMessage = ref<string | null>(null)
const isFetching = ref(false)
const currentWeightEntry = computed<WeightEntryData | null>(() => {
const weights = reception.value?.weights ?? []
@@ -33,22 +31,19 @@ export const useWeighing = ({
const displayWeight = computed(() => weightData.value?.weight ?? currentWeightEntry.value?.weight ?? null)
const displayDsd = computed(() => weightData.value?.dsd ?? currentWeightEntry.value?.dsd ?? '-')
const title = computed(() => (mode === 'gross' ? 'Pesée à plein' : 'Pesée à vide'))
const errorMessage = computed(() => localErrorMessage.value ?? storeError?.value ?? null)
const showLoadingBox = computed(() => displayWeight.value === null && !errorMessage.value)
const showLoadingBox = computed(
() => isFetching.value || (displayWeight.value === null && currentWeightEntry.value === null)
)
const fetchWeight = async () => {
localErrorMessage.value = null
try {
weightData.value = await getWeight()
} catch (error) {
localErrorMessage.value = error?.data?.error ?? error?.message ?? 'Erreur inconnue.'
}
isFetching.value = true
weightData.value = await getWeight().finally(() => {
isFetching.value = false
})
}
const saveWeight = async () => {
localErrorMessage.value = null
if (!reception.value) {
localErrorMessage.value = 'Réception introuvable.'
return
}
@@ -58,36 +53,32 @@ export const useWeighing = ({
const baseWeighedAt = weightData.value?.weighedAt ?? existingEntry?.weighedAt ?? null
if (baseWeight === null) {
localErrorMessage.value = 'Veuillez dabord peser.'
return
}
try {
if (existingEntry?.id) {
await updateWeight(existingEntry.id, {
type: mode,
dsd: baseDsd,
weight: baseWeight,
weighedAt: baseWeighedAt
})
} else {
await createWeight({
reception: `/receptions/${reception.value.id}`,
type: mode,
dsd: baseDsd,
weight: baseWeight,
weighedAt: baseWeighedAt
})
}
} catch (error) {
localErrorMessage.value = error?.data?.error ?? error?.message ?? 'Erreur inconnue.'
return
if (existingEntry?.id) {
await updateWeight(existingEntry.id, {
type: mode,
dsd: baseDsd,
weight: baseWeight,
weighedAt: baseWeighedAt
})
} else {
await createWeight({
reception: `/receptions/${reception.value.id}`,
type: mode,
dsd: baseDsd,
weight: baseWeight,
weighedAt: baseWeighedAt
})
}
const nextStep = reception.value.currentStep + 1
const nextStep = mode === 'tare'
? reception.value.currentStep
: reception.value.currentStep + 1
await updateReception(reception.value.id, {
currentStep: nextStep,
isValid: mode === 'tare' ? true : reception.value.isValid
isValid: reception.value.isValid
})
if (loadReception) {
@@ -101,7 +92,6 @@ export const useWeighing = ({
displayWeight,
displayDsd,
title,
errorMessage,
showLoadingBox,
fetchWeight,
saveWeight
+1 -1
View File
@@ -2,7 +2,7 @@ export default defineNuxtConfig({
compatibilityDate: '2025-07-15',
devtools: { enabled: true },
ssr: false,
modules: ['@nuxtjs/tailwindcss', '@pinia/nuxt'],
modules: ['@nuxtjs/tailwindcss', '@pinia/nuxt', 'nuxt-toast'],
runtimeConfig: {
public: {
apiBase: process.env.NUXT_PUBLIC_API_BASE
+18
View File
@@ -8,7 +8,9 @@
"hasInstallScript": true,
"dependencies": {
"@pinia/nuxt": "^0.11.3",
"izitoast": "^1.4.0",
"nuxt": "^4.2.2",
"nuxt-toast": "^1.4.0",
"pinia": "^3.0.4",
"vue": "^3.5.26",
"vue-router": "^4.6.4",
@@ -6463,6 +6465,11 @@
"node": ">=16"
}
},
"node_modules/izitoast": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/izitoast/-/izitoast-1.4.0.tgz",
"integrity": "sha512-Oc1X2wiQtPp39i5VpIjf3GJf5sfCtHKXZ5szx7RareyEeFLUlcEW0FSfBni28+Ul6KNKZRKzhVuWzSP4Xngh0w=="
},
"node_modules/jackspeak": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
@@ -8056,6 +8063,17 @@
}
}
},
"node_modules/nuxt-toast": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/nuxt-toast/-/nuxt-toast-1.4.0.tgz",
"integrity": "sha512-LGqzlRlLj4ildwAPL8w0MEQWN++DNLYhYPLT+ONkanofTI0yY/5HcUa4x+Y0vozII/Z1e51O3v1hDyCzEWFcHQ==",
"dependencies": {
"@nuxt/kit": "^4.2.0"
},
"peerDependencies": {
"izitoast": "^1.4.0"
}
},
"node_modules/nypm": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.2.tgz",
+2
View File
@@ -12,7 +12,9 @@
},
"dependencies": {
"@pinia/nuxt": "^0.11.3",
"izitoast": "^1.4.0",
"nuxt": "^4.2.2",
"nuxt-toast": "^1.4.0",
"pinia": "^3.0.4",
"vue": "^3.5.26",
"vue-router": "^4.6.4",
+5 -8
View File
@@ -1,14 +1,13 @@
<template>
<div v-if="errorMessage" class="text-red-600">{{ errorMessage }}</div>
<div v-else>
<div>
<div class="flex justify-between h-[52px] mb-[90px]">
<p class="self-center">Indicateur détapes</p>
<NuxtLink to="/" class="flex flex-col justify-center uppercase text-xl bg-black text-white h-[50px] w-[272px] text-center">Mettre en attente</NuxtLink>
</div>
<ReceptionForm v-if="storeReception?.currentStep === 0"/>
<ReceptionForm v-if="!storeReception || storeReception.currentStep === 0"/>
<ReceptionWeight v-if="storeReception?.currentStep === 1" mode="gross"/>
<ReceptionUnloading v-if="storeReception?.currentStep === 2"/>
<ReceptionWeight v-if="storeReception?.currentStep === 3" mode="tare"/>
<ReceptionWeight v-if="storeReception?.currentStep !== null && storeReception?.currentStep >= 3" mode="tare"/>
</div>
</template>
@@ -20,16 +19,14 @@ const route = useRoute()
const router = useRouter()
const receptionStore = useReceptionStore()
const { current: storeReception, errorMessage } = storeToRefs(receptionStore)
const { current: storeReception } = storeToRefs(receptionStore)
onMounted(async () => {
const raw = route.params.id
const idStr = Array.isArray(raw) ? raw[0] : raw
const id = idStr ? Number(idStr) : null
if (id === null) {
await receptionStore.createReception()
} else {
if (id !== null) {
await receptionStore.loadReception(id)
}
})
+10 -32
View File
@@ -2,49 +2,27 @@ import { useApi } from '~/composables/useApi'
import type { ReceptionData } from '~/services/dto/reception-data'
import type { WeightData } from '~/services/dto/weight-data'
const api = useApi()
export async function getReceptionList() {
try {
return await api.get<ReceptionData>(`receptions`)
} catch (error) {
console.error(error.message, error)
return error
}
const api = useApi()
return api.get<ReceptionData>(`receptions`)
}
export async function getReception(id: number) {
try {
return await api.get<ReceptionData>(`receptions/${id}`)
} catch (error) {
console.error(error.message, error)
return error
}
const api = useApi()
return api.get<ReceptionData>(`receptions/${id}`)
}
export async function createReception(payload: Partial<ReceptionData> = {}) {
try {
return await api.post<ReceptionData>('receptions', payload)
} catch (error) {
console.error(error.message, error)
return error
}
const api = useApi()
return api.post<ReceptionData>('receptions', payload)
}
export async function updateReception(id: number, payload: Partial<ReceptionData>) {
try {
return await api.patch<ReceptionData>(`receptions/${id}`, payload)
} catch (error) {
console.error(error.message, error)
return error
}
const api = useApi()
return api.patch<ReceptionData>(`receptions/${id}`, payload)
}
export async function getWeight(): Promise<WeightData> {
try {
return await api.get<WeightData>('receptions/weigh')
} catch (error) {
console.error(error.message, error)
throw error
}
const api = useApi()
return api.get<WeightData>('receptions/weigh')
}
+4 -14
View File
@@ -1,8 +1,6 @@
import { useApi } from '~/composables/useApi'
import type { WeightEntryData } from '~/services/dto/reception-data'
const api = useApi()
export type WeightPayload = {
reception: string
type: 'gross' | 'tare'
@@ -12,19 +10,11 @@ export type WeightPayload = {
}
export async function createWeight(payload: WeightPayload) {
try {
return await api.post<WeightEntryData>('weights', payload)
} catch (error) {
console.error(error.message, error)
throw error
}
const api = useApi()
return api.post<WeightEntryData>('weights', payload)
}
export async function updateWeight(id: number, payload: Partial<WeightPayload>) {
try {
return await api.patch<WeightEntryData>(`weights/${id}`, payload)
} catch (error) {
console.error(error.message, error)
throw error
}
const api = useApi()
return api.patch<WeightEntryData>(`weights/${id}`, payload)
}
+26 -39
View File
@@ -9,64 +9,51 @@ const isReceptionData = (value: unknown): value is ReceptionData => {
export const useReceptionStore = defineStore('reception', {
state: () => ({
current: null as ReceptionData | null,
isLoading: false,
errorMessage: null as string | null
isLoading: false
}),
actions: {
setCurrent(reception: ReceptionData | null) {
this.current = reception
},
clearError() {
this.errorMessage = null
clearCurrent() {
this.current = null
},
async loadReception(id: number) {
this.isLoading = true
this.errorMessage = null
try {
const result = await getReception(id)
if (!isReceptionData(result)) {
this.errorMessage = 'Réception introuvable.'
this.current = null
return null
}
this.current = result
return result
} finally {
const result = await getReception(id).finally(() => {
this.isLoading = false
})
if (!isReceptionData(result)) {
this.current = null
return null
}
this.current = result
return result
},
async createReception() {
async createReception(payload: Partial<ReceptionData> = {}) {
this.isLoading = true
this.errorMessage = null
try {
const result = await createReception()
if (!isReceptionData(result)) {
this.errorMessage = 'Impossible de créer la réception.'
return null
}
this.current = result
return result
} finally {
const result = await createReception(payload).finally(() => {
this.isLoading = false
})
if (!isReceptionData(result)) {
return null
}
this.current = result
return result
},
async updateReception(id: number, payload: Partial<ReceptionData>) {
this.isLoading = true
this.errorMessage = null
try {
const result = await updateReception(id, payload)
if (!isReceptionData(result)) {
this.errorMessage = 'Impossible de mettre à jour la réception.'
return null
}
this.current = result
return result
} finally {
const result = await updateReception(id, payload).finally(() => {
this.isLoading = false
})
if (!isReceptionData(result)) {
return null
}
this.current = result
return result
}
}
})