Added client side realtime for calendars

This commit is contained in:
Alexis
2025-03-10 21:42:04 +01:00
parent ae8937e7a6
commit e0d5f679b0
6 changed files with 20 additions and 31 deletions

View File

@@ -1,15 +1,15 @@
<script lang="ts" setup> <script lang="ts" setup>
import { PhX } from "@phosphor-icons/vue"; import { PhX } from "@phosphor-icons/vue";
import type { Calendar } from "~/models/CalendarConfig"; import type { Calendar } from "~/models/CalendarConfig";
import type { World } from "~/models/World";
const props = defineProps<{ const props = defineProps<{
calendarId: number, calendar: Calendar | null,
world: World | null,
modalState?: boolean modalState?: boolean
}>() }>()
const { data: calendar } = await useFetch<{ data: Calendar }>("/api/calendars/query", { query: { id: props.calendarId } }) const calendarSkeletonName = ref<string>(props.calendar?.name ?? "")
const calendarSkeletonName = ref<string>("")
function onChangedName(newName: string) { function onChangedName(newName: string) {
calendarSkeletonName.value = newName calendarSkeletonName.value = newName
@@ -28,7 +28,7 @@ function handleClose() {
<UiAlertDialogContent class="grid grid-rows-[auto_1fr_auto] items-start min-h-[66vh] max-w-4xl gap-6" @close-auto-focus="(e) => e.preventDefault()"> <UiAlertDialogContent class="grid grid-rows-[auto_1fr_auto] items-start min-h-[66vh] max-w-4xl gap-6" @close-auto-focus="(e) => e.preventDefault()">
<UiAlertDialogTitle> <UiAlertDialogTitle>
<span class="text-2xl"> <span class="text-2xl">
<strong class="font-bold">{{ calendar?.data.world?.name }}</strong> <strong class="font-bold">{{ world?.name }}</strong>
<span class="opacity-30"> — </span> <span class="opacity-30"> — </span>
<span v-if="calendarSkeletonName"> <span v-if="calendarSkeletonName">
{{ calendarSkeletonName }} {{ calendarSkeletonName }}
@@ -43,7 +43,7 @@ function handleClose() {
<PhX size="20" /> <PhX size="20" />
</UiButton> </UiButton>
<CalendarFormUpdate v-if="calendar?.data" :calendar="calendar.data" @on-changed-name="onChangedName" @on-close="handleClose" /> <CalendarFormUpdate v-if="calendar" :world="world" :calendar="calendar" @on-changed-name="onChangedName" @on-close="handleClose" />
</UiAlertDialogContent> </UiAlertDialogContent>
</UiAlertDialog> </UiAlertDialog>
</template> </template>

View File

@@ -1,9 +1,11 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { Calendar } from "~/models/CalendarConfig"; import type { Calendar } from "~/models/CalendarConfig";
import { PhCircleNotch, PhWrench } from "@phosphor-icons/vue"; import { PhCircleNotch, PhWrench } from "@phosphor-icons/vue";
import type { World } from "~/models/World";
const props = defineProps<{ const props = defineProps<{
calendar: Calendar | null, calendar: Calendar | null,
world: World | null,
}>() }>()
const calendarSkeleton = ref<Calendar>({ ...props.calendar } as Calendar) const calendarSkeleton = ref<Calendar>({ ...props.calendar } as Calendar)
@@ -34,7 +36,7 @@ const isUpdatingCalendar = ref<boolean>(false)
async function handleSubmit() { async function handleSubmit() {
try { try {
isUpdatingCalendar.value = true isUpdatingCalendar.value = true
await $fetch(`/api/calendars/${calendarSkeleton.value.id}`, { method: "PATCH", body: { ...calendarSkeleton.value, worldId: props.calendar?.world?.id } }) await $fetch(`/api/calendars/${calendarSkeleton.value.id}`, { method: "PATCH", body: { ...calendarSkeleton.value, worldId: props.world?.id } })
emit("on-close") emit("on-close")
} catch (err) { } catch (err) {

View File

@@ -47,27 +47,6 @@ function handleInsertedCalendar(newCalendar: CalendarChannelPayload) {
} }
} }
/** Handles calendar insertion realtime events */
function handleUpdatedCalendar(newCalendar: CalendarChannelPayload) {
if (!world.value) return
try {
world.value.data.calendars = world.value.data.calendars?.map(c => {
if (c.id === newCalendar.id) {
const eventNb = c.eventNb
c = newCalendar
c.createdAt = newCalendar.created_at
c.updatedAt = newCalendar.updated_at
c.eventNb = eventNb
}
return c
})
} catch (err) {
console.log(err)
}
}
/** Handles calendar deletion realtime events */ /** Handles calendar deletion realtime events */
function handleDeletedCalendar(id: number) { function handleDeletedCalendar(id: number) {
if (!world.value) return if (!world.value) return
@@ -84,7 +63,7 @@ onMounted(() => {
.on( .on(
"postgres_changes", "postgres_changes",
{ event: "*", schema: "public", table: "calendars" }, { event: "*", schema: "public", table: "calendars" },
(payload) => { async (payload) => {
switch (payload.eventType) { switch (payload.eventType) {
case "INSERT": case "INSERT":
handleInsertedCalendar(payload.new as Calendar) handleInsertedCalendar(payload.new as Calendar)
@@ -94,8 +73,11 @@ onMounted(() => {
handleDeletedCalendar(payload.old.id) handleDeletedCalendar(payload.old.id)
break break
// Maybe this case could be handled better than doing a separate API call
case "UPDATE": case "UPDATE":
handleUpdatedCalendar(payload.new as Calendar) if (!world.value?.data) return
world.value.data = (await $fetch<{ data: World }>("/api/worlds/query", { query: { id, full: true } })).data
break break
default: default:
@@ -249,7 +231,7 @@ function hideEditModal() {
<WorldDialogEdit :world="world.data" :modal-state="isEditWorldModalOpen" @on-close="hideEditModal" /> <WorldDialogEdit :world="world.data" :modal-state="isEditWorldModalOpen" @on-close="hideEditModal" />
<CalendarDialogCreate :world="world.data" :modal-state="isCreateCalendarModalOpen" @on-close="hideCreateDialog" /> <CalendarDialogCreate :world="world.data" :modal-state="isCreateCalendarModalOpen" @on-close="hideCreateDialog" />
<CalendarDialogUpdate v-if="markedCalendar?.id" :calendar-id="markedCalendar.id" :modal-state="isUpdateCalendarModalOpen" @on-close="hideUpdateDialog" /> <CalendarDialogUpdate v-if="markedCalendar?.id" :world="world.data" :calendar="markedCalendar" :modal-state="isUpdateCalendarModalOpen" @on-close="hideUpdateDialog" />
<CalendarDialogDelete :calendar="markedCalendar" :modal-state="isDeleteCalendarModalOpen" @on-close="hideDeleteCalendarModal"/> <CalendarDialogDelete :calendar="markedCalendar" :modal-state="isDeleteCalendarModalOpen" @on-close="hideDeleteCalendarModal"/>
</template> </template>
<template v-else> <template v-else>

View File

@@ -23,6 +23,8 @@ export default defineEventHandler(async (event) => {
} }
if (bodyError) { if (bodyError) {
console.log(bodyData)
console.log(bodyError)
const error = createError({ const error = createError({
cause: "Utilisateur", cause: "Utilisateur",
fatal: false, fatal: false,

View File

@@ -29,6 +29,7 @@ export default defineEventHandler(async (event) => {
name: bodyData.name, name: bodyData.name,
today: bodyData.today, today: bodyData.today,
color: bodyData.color, color: bodyData.color,
state: bodyData.state,
world_id: bodyData.worldId world_id: bodyData.worldId
} as never } as never
) )

View File

@@ -27,6 +27,7 @@ export default defineEventHandler(async (event) => {
color, color,
today, today,
state, state,
months:calendar_months(*),
createdAt:created_at, createdAt:created_at,
updatedAt:updated_at, updatedAt:updated_at,
eventNb:calendar_events(count) eventNb:calendar_events(count)
@@ -43,6 +44,7 @@ export default defineEventHandler(async (event) => {
calendars ( calendars (
createdAt:created_at, createdAt:created_at,
updatedAt:updated_at, updatedAt:updated_at,
months:calendar_months(*),
eventNb:calendar_events(count) eventNb:calendar_events(count)
) )
` `