diff --git a/assets/main.css b/assets/main.css index 71f25ec..ad39aa5 100644 --- a/assets/main.css +++ b/assets/main.css @@ -5,64 +5,64 @@ :root { --background: 0 0% 100%; --foreground: 222.2 84% 4.9%; - + --muted: 210 40% 96.1%; --muted-foreground: 215.4 16.3% 46.9%; - + --popover: 0 0% 100%; --popover-foreground: 222.2 84% 4.9%; - + --card: 0 0% 100%; --card-foreground: 222.2 84% 4.9%; - + --border: 214.3 31.8% 91.4%; --input: 214.3 31.8% 91.4%; - + --primary: 222.2 47.4% 11.2%; --primary-foreground: 210 40% 98%; - + --secondary: 210 40% 96.1%; --secondary-foreground: 222.2 47.4% 11.2%; - + --accent: 210 40% 96.1%; --accent-foreground: 222.2 47.4% 11.2%; - + --destructive: 0 84.2% 60.2%; --destructive-foreground: 210 40% 98%; - + --ring: 222.2 84% 4.9%; - + --radius: 0.5rem; } - + :root.dark { --background: 222.2 84% 4.9%; --foreground: 210 40% 98%; - + --muted: 217.2 32.6% 17.5%; --muted-foreground: 215 20.2% 65.1%; - + --popover: 222.2 84% 4.9%; --popover-foreground: 210 40% 98%; - + --card: 222.2 84% 4.9%; --card-foreground: 210 40% 98%; - + --border: 217.2 32.6% 17.5%; --input: 217.2 32.6% 17.5%; - + --primary: 210 40% 98%; --primary-foreground: 222.2 47.4% 11.2%; - + --secondary: 217.2 32.6% 17.5%; --secondary-foreground: 210 40% 98%; - + --accent: 217.2 32.6% 17.5%; --accent-foreground: 210 40% 98%; - + --destructive: 0 62.8% 30.6%; --destructive-foreground: 210 40% 98%; - + --ring: 212.7 26.8% 83.9%; } @@ -73,4 +73,21 @@ body { @apply bg-background text-foreground; } -} \ No newline at end of file +} + +.fade-enter-active, +.fade-leave-active { + transition: all .5s ease; +} +.fade-delay-enter-active, +.fade-delay-leave-active { + transition: all .5s ease 1s; +} + +.fade-enter-from, +.fade-leave-to, +.fade-delay-enter-from, +.fade-delay-leave-to { + opacity: 0; + visibility: hidden; +} diff --git a/components/calendar/Calendar.vue b/components/calendar/Calendar.vue index 950b36b..9506e05 100644 --- a/components/calendar/Calendar.vue +++ b/components/calendar/Calendar.vue @@ -93,7 +93,7 @@ onMounted(() => { setCurrentMenu([ { - phIcon: PhMagnifyingGlass, + phIcon: shallowRef(PhMagnifyingGlass), tooltip: 'Recherche avancée', action: 'event-search' } @@ -116,10 +116,10 @@ onMounted(() => { - - - - + + + + diff --git a/components/calendar/form/CreateEvent.vue b/components/calendar/form/CreateEvent.vue index 7729509..524121f 100644 --- a/components/calendar/form/CreateEvent.vue +++ b/components/calendar/form/CreateEvent.vue @@ -1,11 +1,12 @@ diff --git a/components/global/sidebar/SidebarProps.ts b/components/global/sidebar/SidebarProps.ts index 4414df0..bb3cd9e 100644 --- a/components/global/sidebar/SidebarProps.ts +++ b/components/global/sidebar/SidebarProps.ts @@ -1,7 +1,9 @@ +import type { ShallowRef } from "vue" + export type SidebarMenuActionType = "event-search" export interface SidebarMenuItem { - phIcon: Component + phIcon: ShallowRef tooltip: string action?: SidebarMenuActionType to?: string diff --git a/stores/EventStore.ts b/stores/EventStore.ts index 454bd24..b3294e9 100644 --- a/stores/EventStore.ts +++ b/stores/EventStore.ts @@ -187,6 +187,12 @@ export const useCalendarEvents = defineStore('calendar-events', () => { * EVENT CREATION FUNCTIONS */ const lastActiveEvent = ref() + const isCreatingEvent = ref(false) + const isUpdatingEvent = ref(false) + const isDeletingEvent = ref(false) + const operationInProgress = computed(() => isCreatingEvent.value || isUpdatingEvent.value || isDeletingEvent.value) + let abortController: AbortController | null = null + /** * Dummy event to hold creation data */ @@ -205,31 +211,58 @@ export const useCalendarEvents = defineStore('calendar-events', () => { * We assume it's been sanitized by the caller */ async function submitSkeleton() { + abortController = new AbortController() + isCreatingEvent.value = true + try { - const res = await $fetch('/api/calendars/events/create', { method: 'POST', body: { event : eventSkeleton.value, calendarId: calendarId.value }}) + const res = await $fetch('/api/calendars/events/create', { method: 'POST', body: { event : eventSkeleton.value, calendarId: calendarId.value }, signal: abortController.signal }) + baseEvents.value.push(res) } catch (err) { console.log(err) + } finally { + abortController = null + isCreatingEvent.value = false } } async function updateEventFromSkeleton() { + abortController = new AbortController() + isUpdatingEvent.value = true + try { - const res = await $fetch(`/api/calendars/events/${eventSkeleton.value.id}`, { method: 'PATCH', body: { event : eventSkeleton.value, calendarId: calendarId.value }}) + const res = await $fetch(`/api/calendars/events/${eventSkeleton.value.id}`, { method: 'PATCH', body: { event : eventSkeleton.value, calendarId: calendarId.value }, 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 } } async function deleteEventFromSkeleton() { + abortController = new AbortController() + isDeletingEvent.value = true + try { - await $fetch(`/api/calendars/events/${eventSkeleton.value.id}`, { method: 'DELETE' }) + await $fetch(`/api/calendars/events/${eventSkeleton.value.id}`, { method: 'DELETE', signal: abortController.signal }) + const eventIndex = baseEvents.value.findIndex(e => e.id === eventSkeleton.value.id) baseEvents.value.splice(eventIndex, 1) } catch (err) { console.log(err) + } finally { + abortController = null + isDeletingEvent.value = false + } + } + + function cancelLatestRequest() { + if (abortController) { + abortController.abort() } } @@ -239,6 +272,11 @@ export const useCalendarEvents = defineStore('calendar-events', () => { currentEvents, getRelativeEventFromDate, getRelativeEventFromEvent, + cancelLatestRequest, + isCreatingEvent, + isUpdatingEvent, + isDeletingEvent, + operationInProgress, eventSkeleton, resetSkeleton, submitSkeleton,