Added check on client side (api)
This commit is contained in:
@@ -1,9 +1,14 @@
|
||||
<script lang="ts" setup>
|
||||
import { PhAlarm, PhCircleNotch, PhEye, PhEyeClosed, PhMapPinArea, PhPencilSimpleLine, PhTag } from "@phosphor-icons/vue"
|
||||
import { useToast } from "~/components/ui/toast";
|
||||
import type { APIError } from "~/models/Errors";
|
||||
|
||||
const { resetSkeleton, updateEventFromSkeleton, cancelLatestRequest } = useCalendar()
|
||||
const { eventSkeleton, lastActiveEvent, isEditEventModalOpen } = storeToRefs(useCalendar())
|
||||
|
||||
const { toast } = useToast()
|
||||
const { t } = useI18n()
|
||||
|
||||
const isLoading = ref(false)
|
||||
|
||||
const formErrors = reactive<{ message: string | null }>({
|
||||
@@ -24,15 +29,22 @@ async function handleAction() {
|
||||
|
||||
try {
|
||||
await updateEventFromSkeleton()
|
||||
|
||||
isEditEventModalOpen.value = false
|
||||
} catch (err) {
|
||||
if (err instanceof Error) {
|
||||
formErrors.message = err.message
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const apiError = (err as any).data as APIError
|
||||
|
||||
apiError.data.errors.forEach((error) => {
|
||||
toast({
|
||||
title: t("entity.calendar.event.editErrors.toastTitle"),
|
||||
variant: "destructive",
|
||||
description: t(`entity.calendar.event.editErrors.${error.path[1]}_${error.code}`),
|
||||
duration: 2000,
|
||||
})
|
||||
})
|
||||
} finally {
|
||||
resetSkeleton()
|
||||
isLoading.value = false
|
||||
isEditEventModalOpen.value = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,5 +13,5 @@ const delegatedProps = computed(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ToastViewport v-bind="delegatedProps" :class="cn('fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]', props.class)" />
|
||||
<ToastViewport v-bind="delegatedProps" :class="cn('fixed top-0 z-[100] flex gap-y-2 max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]', props.class)" />
|
||||
</template>
|
||||
|
||||
@@ -140,6 +140,11 @@ export default defineI18nConfig(() => ({
|
||||
title: "Edit event",
|
||||
subtitle: "Update event data",
|
||||
},
|
||||
editErrors: {
|
||||
toastTitle: "Event wasn't updated.",
|
||||
title_too_big: "Title should be less than 240 characters long.",
|
||||
description_too_big: "Description should be less than 1200 characters long.",
|
||||
},
|
||||
deleteDialog: {
|
||||
title: "Delete this event",
|
||||
subtitle: "Data associated with this event will be lost and you won't be able to retrieve it !",
|
||||
@@ -348,6 +353,11 @@ export default defineI18nConfig(() => ({
|
||||
title: "Modifier l'évènement",
|
||||
subtitle: "Mettre à jour les données de l'évènement",
|
||||
},
|
||||
editErrors: {
|
||||
toastTitle: "L'évènement n'a pas été modifié",
|
||||
title_too_big: "Le titre doit être inférieur à 240 caractères.",
|
||||
description_too_big: "La description doit être inférieure à 1200 caractères.",
|
||||
},
|
||||
deleteDialog: {
|
||||
title: "Supprimer l'évènement",
|
||||
subtitle: "Les données associés à cet évènement seront supprimées et vous ne pourrez plus les récupérer !",
|
||||
|
||||
@@ -20,8 +20,8 @@ export interface CalendarEvent {
|
||||
*/
|
||||
export const postEventBodySchema = z.object({
|
||||
event: z.object({
|
||||
title: z.string(),
|
||||
description: z.string().optional().nullable(),
|
||||
title: z.string().max(240),
|
||||
description: z.string().max(1200).optional().nullable(),
|
||||
location: z.string().optional().nullable(),
|
||||
startDate: dateSchema.required(),
|
||||
endDate: dateSchema.optional().nullable(),
|
||||
|
||||
14
models/Errors.ts
Normal file
14
models/Errors.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
export interface ValidationError {
|
||||
path: (string | number)[]
|
||||
message: string
|
||||
code: string
|
||||
}
|
||||
|
||||
export interface APIError {
|
||||
statusCode: number
|
||||
statusMessage: string
|
||||
message: string
|
||||
data: {
|
||||
errors: ValidationError[]
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||
export default defineNuxtConfig({
|
||||
devtools: { enabled: true },
|
||||
devtools: { enabled: false },
|
||||
|
||||
modules: [
|
||||
"@nuxtjs/supabase",
|
||||
|
||||
@@ -22,12 +22,22 @@ export default defineEventHandler(async (event) => {
|
||||
}
|
||||
|
||||
if (bodyError) {
|
||||
throw createError({
|
||||
const error = createError({
|
||||
cause: "Utilisateur",
|
||||
fatal: false,
|
||||
message: "Le schéma de la requête n'est pas complet ou mal renseigné.",
|
||||
status: 401,
|
||||
statusCode: 401,
|
||||
statusMessage: "Validation Error",
|
||||
message: "Erreur de validation du schéma, cela est probablement dû à une erreur utilisateur.",
|
||||
data: {
|
||||
errors: bodyError.issues.map(issue => ({
|
||||
path: issue.path,
|
||||
message: issue.message,
|
||||
code: issue.code
|
||||
}))
|
||||
}
|
||||
})
|
||||
|
||||
throw error
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -11,6 +11,8 @@ export default defineEventHandler(async (event) => {
|
||||
cause: "Utilisateur",
|
||||
fatal: false,
|
||||
message: "Le schéma de la requête n'est pas complet ou mal renseigné.",
|
||||
data: schemaError.issues,
|
||||
statusMessage: "test",
|
||||
status: 401,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -869,8 +869,8 @@ export const useCalendar = defineStore("calendar", () => {
|
||||
|
||||
const eventIndex = baseEvents.value.findIndex(e => e.id === eventSkeleton.value.id)
|
||||
baseEvents.value[eventIndex] = res
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
|
||||
return res
|
||||
} finally {
|
||||
abortController = null
|
||||
isUpdatingEvent.value = false
|
||||
|
||||
@@ -247,17 +247,13 @@ export const useCalendarEvents = defineStore("calendar-events", () => {
|
||||
abortController = new AbortController()
|
||||
isUpdatingEvent.value = true
|
||||
|
||||
try {
|
||||
const res = await $fetch(`/api/calendars/events/${eventSkeleton.value.id}`, { method: "PATCH", body: { event : eventSkeleton.value, calendarId: activeCalendar?.id }, signal: abortController.signal })
|
||||
const res = await $fetch(`/api/calendars/events/${eventSkeleton.value.id}`, { method: "PATCH", body: { event : eventSkeleton.value, calendarId: activeCalendar?.id }, signal: abortController.signal })
|
||||
|
||||
const eventIndex = baseEvents.value.findIndex(e => e.id === eventSkeleton.value.id)
|
||||
baseEvents.value[eventIndex] = res
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
} finally {
|
||||
abortController = null
|
||||
isUpdatingEvent.value = false
|
||||
}
|
||||
const eventIndex = baseEvents.value.findIndex(e => e.id === eventSkeleton.value.id)
|
||||
baseEvents.value[eventIndex] = res
|
||||
|
||||
abortController = null
|
||||
isUpdatingEvent.value = false
|
||||
}
|
||||
|
||||
async function deleteEventFromSkeleton() {
|
||||
|
||||
Reference in New Issue
Block a user