Added world edit subscription

And also toast lifetimes
This commit is contained in:
Alexis
2025-03-01 14:14:55 +01:00
parent 189f0eec75
commit ba3eb29e04
7 changed files with 80 additions and 14 deletions

View File

@@ -1,6 +1,7 @@
<script lang="ts" setup>
import { PhCircleNotch } from "@phosphor-icons/vue";
import { useToast } from "~/components/ui/toast";
import { ToastLifetime } from "~/components/ui/toast/use-toast";
import type { Calendar } from "~/models/CalendarConfig";
const { toast } = useToast()
@@ -28,7 +29,7 @@ async function handleAction(): Promise<void> {
toast({
title: t("entity.calendar.deletedToast.title", { calendar: props.calendar.name }),
variant: "success",
duration: 3000
duration: ToastLifetime.SHORT
})
} catch (err) {
console.log(err)

View File

@@ -1,6 +1,7 @@
<script lang="ts" setup>
import { PhCircleNotch } from "@phosphor-icons/vue";
import { useToast } from "~/components/ui/toast";
import { ToastLifetime } from "~/components/ui/toast/use-toast";
const { resetSkeleton, deleteEventFromSkeleton, cancelLatestRequest } = useCalendar()
const { isDeleteEventModalOpen, eventSkeleton } = storeToRefs(useCalendar())
@@ -30,7 +31,7 @@ async function handleAction(): Promise<void> {
toast({
title: t("entity.calendar.event.deletedToast.title", { event: eventTitle }),
variant: "success",
duration: 3000
duration: ToastLifetime.MEDIUM
})
} catch (err) {
if (err instanceof Error) {

View File

@@ -1,6 +1,7 @@
<script lang="ts" setup>
import { PhAlarm, PhCircleNotch, PhEye, PhEyeClosed, PhMapPinArea, PhPencilSimpleLine, PhTag } from "@phosphor-icons/vue"
import { useToast } from "~/components/ui/toast";
import { ToastLifetime } from "~/components/ui/toast/use-toast";
import type { APIError } from "~/models/Errors";
const emit = defineEmits(["event-updated"])
@@ -30,7 +31,7 @@ async function handleAction() {
toast({
title: t("entity.calendar.event.updatedToast.title", { event: eventSkeleton.value.title }),
variant: "success",
duration: 3000
duration: ToastLifetime.SHORT
})
} catch (err) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -41,7 +42,7 @@ async function handleAction() {
title: t("entity.calendar.event.editErrors.toastTitle"),
variant: "destructive",
description: t(`entity.calendar.event.editErrors.${error.path[1]}_${error.code}`),
duration: 2000,
duration: ToastLifetime.MEDIUM,
})
})
} finally {

View File

@@ -5,6 +5,12 @@ import type { ToastProps } from "."
const TOAST_LIMIT = 3
const TOAST_REMOVE_DELAY = 1000000
export enum ToastLifetime {
SHORT = 2000,
MEDIUM = 3500,
LONG = 6000,
}
export type StringOrVNode =
| string
| VNode

View File

@@ -1,6 +1,7 @@
<script lang="ts" setup>
import { PhCircleNotch } from "@phosphor-icons/vue";
import { useToast } from "~/components/ui/toast";
import { ToastLifetime } from "~/components/ui/toast/use-toast";
import type { World } from "~/models/World";
const { toast } = useToast()
@@ -28,7 +29,7 @@ async function handleAction(): Promise<void> {
toast({
title: t("entity.world.deletedToast.title", { world: props.world.name }),
variant: "success",
duration: 3000
duration: ToastLifetime.SHORT
})
} catch (err) {
console.log(err)

View File

@@ -1,6 +1,7 @@
<script lang="ts" setup>
import { PhCircleNotch } from "@phosphor-icons/vue";
import { useToast } from "~/components/ui/toast";
import { ToastLifetime } from "~/components/ui/toast/use-toast";
import type { World } from "~/models/World";
const { toast } = useToast()
@@ -36,7 +37,7 @@ async function handleSubmit() {
toast({
title: t("entity.world.updatedToast.title", { world: worldSkeleton.value.name }),
variant: "success",
duration: 3000
duration: ToastLifetime.SHORT
})
emit("on-close")

View File

@@ -2,7 +2,7 @@
import type { RealtimeChannel } from "@supabase/supabase-js"
import type { World } from "~/models/World";
import type { Calendar } from "~/models/CalendarConfig";
import { PhArrowBendDoubleUpLeft, PhGlobeHemisphereWest, PhPlus, PhTrash } from "@phosphor-icons/vue";
import { PhArrowBendDoubleUpLeft, PhGlobeHemisphereWest, PhPencil, PhPlus, PhTrash } from "@phosphor-icons/vue";
const supabase = useSupabaseClient()
const route = useRoute()
@@ -30,11 +30,13 @@ function hideCreateDialog() {
}
/**
* === Calendar subscriptions ===
* === Subscriptions ===
*/
/** Active calendar channel */
let calendarChannel: RealtimeChannel
/** Active world channel */
let worldChannel: RealtimeChannel
/** Handles calendar insertion realtime events */
function handleInsertedCalendar(newCalendar: Calendar) {
@@ -81,24 +83,59 @@ onMounted(() => {
)
.subscribe()
})
onUnmounted(() => {
// Unsubscribe from realtime
supabase.removeChannel(calendarChannel)
})
onMounted(() => {
worldChannel = supabase.channel("realtime-world-channel")
.on(
"postgres_changes",
{ event: "*", schema: "public", table: "worlds" },
async (payload) => {
switch (payload.eventType) {
case "UPDATE":
if (!world.value?.data) return
world.value.data = (await $fetch<{ data: World }>("/api/worlds/query", { query: { id, full: true } })).data
break
default:
console.log("Unknown event has been triggered. This should not happen unless Supabase added one somehow.")
console.log(payload)
break
}
}
)
.subscribe()
})
onUnmounted(() => {
// Unsubscribe from realtime
supabase.removeChannel(worldChannel)
})
const markedCalendar = ref<Calendar | null>(null)
const isDeleteCalendarModalOpen = ref<boolean>(false)
const isEditWorldModalOpen = ref<boolean>(false)
function deployDeleteModal(calendar: Calendar) {
function deployDeleteCalendarModal(calendar: Calendar) {
isDeleteCalendarModalOpen.value = true
markedCalendar.value = calendar
}
function hideDeleteModal() {
function hideDeleteCalendarModal() {
isDeleteCalendarModalOpen.value = false
markedCalendar.value = null
}
function deployEditModal() {
isEditWorldModalOpen.value = true
}
function hideEditModal() {
isEditWorldModalOpen.value = false
}
</script>
<template>
@@ -119,7 +156,24 @@ function hideDeleteModal() {
<header class="lg:w-1/2 mb-8">
<Spacing>
<Heading level="h1">{{ world.data.name }}</Heading>
<div class="flex items-center gap-2">
<Heading level="h1">{{ world.data.name }}</Heading>
<UiTooltipProvider :delay-duration="250">
<UiTooltip>
<UiTooltipTrigger as-child>
<UiButton size="icon" class="rounded-full h-8 w-8" @click="deployEditModal">
<PhPencil size="17" weight="fill" />
</UiButton>
</UiTooltipTrigger>
<UiTooltipContent :side-offset="10">
<p>
{{ $t('entity.calendar.addSingle') }}
</p>
</UiTooltipContent>
</UiTooltip>
</UiTooltipProvider>
</div>
<p>{{ world.data.description }}</p>
</Spacing>
@@ -161,7 +215,7 @@ function hideDeleteModal() {
<UiCardContent>
<p class="italic">Description future (ou alors des informations sur le nb d'évènements)</p>
<UiButton size="icon" variant="ghost" class="absolute top-2 right-2 z-20 hover:text-white hover:bg-rose-400 dark:hover:bg-rose-700" @click="deployDeleteModal(calendar)">
<UiButton size="icon" variant="ghost" class="absolute top-2 right-2 z-20 hover:text-white hover:bg-rose-400 dark:hover:bg-rose-700" @click="deployDeleteCalendarModal(calendar)">
<PhTrash size="16" />
</UiButton>
</UiCardContent>
@@ -176,8 +230,9 @@ function hideDeleteModal() {
</Spacing>
</section>
<WorldDialogEdit :world="world.data" :modal-state="isEditWorldModalOpen" @on-close="hideEditModal" />
<CalendarDialogCreate :world="world.data" :modal-state="isCreateCalendarModalOpen" @on-close="hideCreateDialog" />
<CalendarDialogDelete :calendar="markedCalendar" :modal-state="isDeleteCalendarModalOpen" @on-close="hideDeleteModal" />
<CalendarDialogDelete :calendar="markedCalendar" :modal-state="isDeleteCalendarModalOpen" @on-close="hideDeleteCalendarModal" />
</template>
<template v-else>
<div class="h-full w-full grid place-items-center">