Fixed a bug with dates and some style issues

This commit is contained in:
Alexis
2025-03-05 20:03:52 +01:00
parent 8848fa75b1
commit 1aa3350da3
15 changed files with 90 additions and 33 deletions

View File

@@ -23,14 +23,14 @@ const calendarLink = computed(() => isOwner.value ? `/my/calendars/${props.calen
<template> <template>
<UiCard <UiCard
class="w-full h-full transition-all hover:bg-slate-50 dark:bg-gray-950 dark:hover:bg-indigo-950 dark:focus-within:outline-gray-900" class="w-full h-full flex flex-col transition-all hover:bg-slate-50 dark:bg-gray-950 dark:hover:bg-indigo-950 dark:focus-within:outline-gray-900"
:link="calendarLink" :link="calendarLink"
> >
<UiCardHeader> <UiCardHeader>
<UiCardTitle class="text-xl pr-12">{{ calendar.name }}</UiCardTitle> <UiCardTitle class="text-xl pr-12">{{ calendar.name }}</UiCardTitle>
</UiCardHeader> </UiCardHeader>
<UiCardContent> <UiCardContent class="grow">
<p class="flex items-center gap-1"> <p class="flex items-center gap-1">
<PhCalendarDots size="24" weight="fill" /> <PhCalendarDots size="24" weight="fill" />
<span>{{ $t("entity.calendar.hasXEvents", { count: calendar.eventNb?.[0].count }) }}</span> <span>{{ $t("entity.calendar.hasXEvents", { count: calendar.eventNb?.[0].count }) }}</span>
@@ -48,13 +48,13 @@ const calendarLink = computed(() => isOwner.value ? `/my/calendars/${props.calen
</UiCardContent> </UiCardContent>
<UiCardFooter> <UiCardFooter>
<ul class="grid gap-2"> <ul class="grid gap-1 text-sm">
<li class="flex gap-1 items-center"> <li class="flex gap-1 items-center">
<PhFilePlus size="20" /> <PhFilePlus size="18" />
<span>{{ $t('common.createdAt', { createdAt }) }}</span> <span>{{ $t('common.createdAt', { createdAt }) }}</span>
</li> </li>
<li v-if="updatedAt" class="flex gap-1 items-center"> <li v-if="updatedAt" class="flex gap-1 items-center">
<PhPencilSimpleLine size="20" /> <PhPencilSimpleLine size="18" />
<span>{{ $t('common.updatedAt', { updatedAt }) }}</span> <span>{{ $t('common.updatedAt', { updatedAt }) }}</span>
</li> </li>
</ul> </ul>

View File

@@ -17,6 +17,7 @@ const emit = defineEmits(["on-close"])
function handleClose() { function handleClose() {
emit("on-close") emit("on-close")
setTimeout(() => calendarSkeletonName.value = "", 100)
} }
</script> </script>

View File

@@ -97,7 +97,7 @@ function handleFormCancel() {
</div> </div>
</UiTabsTrigger> </UiTabsTrigger>
</UiTabsList> </UiTabsList>
<UiTabsContent value="global"> <UiTabsContent value="global" class="grid gap-6">
<input <input
id="new-calendar-name" id="new-calendar-name"
v-model="calendarSkeleton.name" v-model="calendarSkeleton.name"
@@ -105,9 +105,17 @@ function handleFormCancel() {
name="new-calendar-name" name="new-calendar-name"
required required
:placeholder="$t('common.title')" :placeholder="$t('common.title')"
class="w-full -my-1 py-2 -mx-1 px-1 text-xl border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600" class="w-full py-2 -mx-1 px-1 text-xl border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600"
@input="handleNameChange" @input="handleNameChange"
> >
<div class="-mx-1 px-1 grid gap-3">
<UiLabel for="new-calendar-state">
{{ $t('ui.contentState.label') }}
</UiLabel>
<InputContentState id="new-calendar-state" v-model="calendarSkeleton.state" />
</div>
</UiTabsContent> </UiTabsContent>
<UiTabsContent value="months"> <UiTabsContent value="months">
<CalendarInputMonthList v-model:model-value="calendarSkeleton.months" /> <CalendarInputMonthList v-model:model-value="calendarSkeleton.months" />

View File

@@ -6,7 +6,7 @@ const emit = defineEmits(["on-click"])
<template> <template>
<UiCard <UiCard
class="h-full md:w-fit transition-all bg-transparent dark:hover:bg-gray-950 dark:focus-within:outline-gray-900 hover:-translate-y-0" class="h-full md:w-fit transition-all bg-transparent hover:text-slate-900 text-slate-500 dark:hover:text-slate-100 dark:text-slate-500 dark:focus-within:outline-gray-900 hover:-translate-y-0"
has-click has-click
@on-click="emit('on-click')" @on-click="emit('on-click')"
> >

View File

@@ -2,12 +2,16 @@
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { type RPGColor, rpgColors } from "~/models/Color"; import { type RPGColor, rpgColors } from "~/models/Color";
defineProps<{
id: string
}>();
const model = defineModel<RPGColor>({ default: "white" }); const model = defineModel<RPGColor>({ default: "white" });
</script> </script>
<template> <template>
<UiSelect v-model="model"> <UiSelect v-model="model">
<UiSelectTrigger> <UiSelectTrigger :id>
<UiSelectValue <UiSelectValue
:placeholder="$t('ui.colors.selectOne')" :placeholder="$t('ui.colors.selectOne')"
class="input-color" class="input-color"

View File

@@ -1,12 +1,16 @@
<script lang="ts" setup> <script lang="ts" setup>
import { contentStates, type ContentState } from "~/models/Entity"; import { contentStates, type ContentState } from "~/models/Entity";
defineProps<{
id: string
}>();
const model = defineModel<ContentState>({ default: "draft" }); const model = defineModel<ContentState>({ default: "draft" });
</script> </script>
<template> <template>
<UiSelect v-model="model"> <UiSelect v-model="model">
<UiSelectTrigger> <UiSelectTrigger :id>
<UiSelectValue <UiSelectValue
:placeholder="$t('ui.contentState.selectOne')" :placeholder="$t('ui.contentState.selectOne')"
/> />

View File

@@ -17,7 +17,7 @@ const delegatedProps = computed(() => {
v-bind="delegatedProps" v-bind="delegatedProps"
:class=" :class="
cn( cn(
'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70', 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 cursor-pointer',
props.class, props.class,
) )
" "

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import { PhArchive, PhFileDashed, PhFilePlus, PhPencil, PhPencilSimpleLine, PhTrash } from "@phosphor-icons/vue"; import { PhArchive, PhFile, PhFileDashed, PhFilePlus, PhPencil, PhPencilSimpleLine, PhTrash } from "@phosphor-icons/vue";
import type { World } from "~/models/World"; import type { World } from "~/models/World";
import { DateTime } from "luxon"; import { DateTime } from "luxon";
@@ -16,7 +16,7 @@ const updatedAt = computed<string>(() => props.world.updatedAt ? DateTime.fromIS
<template> <template>
<UiCard <UiCard
class="w-full h-full transition-all" class="w-full h-full flex flex-col transition-all"
:link="`/my/worlds/${world.id}`" :link="`/my/worlds/${world.id}`"
:class="{ :class="{
'hover:bg-slate-50 dark:hover:bg-sky-950 dark:focus-within:outline-sky-900': !world.color, 'hover:bg-slate-50 dark:hover:bg-sky-950 dark:focus-within:outline-sky-900': !world.color,
@@ -38,13 +38,17 @@ const updatedAt = computed<string>(() => props.world.updatedAt ? DateTime.fromIS
'bg-pink-100 dark:bg-pink-950 border-pink-200 hover:bg-pink-50 dark:hover:bg-pink-900 dark:border-pink-900 dark:focus-within:outline-pink-900': world.color === 'pink', 'bg-pink-100 dark:bg-pink-950 border-pink-200 hover:bg-pink-50 dark:hover:bg-pink-900 dark:border-pink-900 dark:focus-within:outline-pink-900': world.color === 'pink',
'bg-pink-100 dark:bg-rose-950 border-rose-200 hover:bg-rose-50 dark:hover:bg-rose-900 dark:border-rose-900 dark:focus-within:outline-rose-900': world.color === 'rose', 'bg-pink-100 dark:bg-rose-950 border-rose-200 hover:bg-rose-50 dark:hover:bg-rose-900 dark:border-rose-900 dark:focus-within:outline-rose-900': world.color === 'rose',
'text-slate-100 bg-slate-900 border-slate-700 hover:bg-slate-700 dark:hover:bg-slate-800 dark:border-slate-900 dark:focus-within:outline-slate-900': world.color === 'black', 'text-slate-100 bg-slate-900 border-slate-700 hover:bg-slate-700 dark:hover:bg-slate-800 dark:border-slate-900 dark:focus-within:outline-slate-900': world.color === 'black',
' hover:bg-slate-50 dark:hover:text-slate-900 dark:hover:bg-slate-300 dark:border-slate-500 dark:focus-within:outline-slate-100': world.color === 'white', ' hover:bg-slate-50 dark:hover:text-slate-900 dark:hover:bg-slate-200 dark:border-slate-700 dark:focus-within:outline-slate-100': world.color === 'white',
}" }"
> >
<UiCardHeader class="gap-4"> <UiCardHeader class="gap-4">
<UiCardTitle> <UiCardTitle>
{{ world.name }} {{ world.name }}
</UiCardTitle> </UiCardTitle>
<div v-if="world.state === 'published'" class="flex items-center gap-1 text-sm">
<PhFile size="20" weight="fill" />
<span>{{ $t('ui.contentState.published') }}</span>
</div>
<div v-if="world.state === 'draft'" class="flex items-center gap-1 text-sm"> <div v-if="world.state === 'draft'" class="flex items-center gap-1 text-sm">
<PhFileDashed size="20" weight="fill" /> <PhFileDashed size="20" weight="fill" />
<span>{{ $t('ui.contentState.draft') }}</span> <span>{{ $t('ui.contentState.draft') }}</span>
@@ -54,7 +58,8 @@ const updatedAt = computed<string>(() => props.world.updatedAt ? DateTime.fromIS
<span>{{ $t('ui.contentState.archived') }}</span> <span>{{ $t('ui.contentState.archived') }}</span>
</div> </div>
</UiCardHeader> </UiCardHeader>
<UiCardContent>
<UiCardContent class="grow">
<p class="italic">{{ world.description }}</p> <p class="italic">{{ world.description }}</p>
<div class="flex gap-1 absolute top-4 right-4 z-20"> <div class="flex gap-1 absolute top-4 right-4 z-20">
@@ -69,13 +74,13 @@ const updatedAt = computed<string>(() => props.world.updatedAt ? DateTime.fromIS
</UiCardContent> </UiCardContent>
<UiCardFooter> <UiCardFooter>
<ul class="grid gap-2"> <ul class="grid gap-1 text-sm">
<li class="flex gap-1 items-center"> <li class="flex gap-1 items-center">
<PhFilePlus size="20" /> <PhFilePlus size="18" />
<span>{{ $t('common.createdAt', { createdAt }) }}</span> <span>{{ $t('common.createdAt', { createdAt }) }}</span>
</li> </li>
<li v-if="updatedAt" class="flex gap-1 items-center"> <li v-if="updatedAt" class="flex gap-1 items-center">
<PhPencilSimpleLine size="20" /> <PhPencilSimpleLine size="18" />
<span>{{ $t('common.updatedAt', { updatedAt }) }}</span> <span>{{ $t('common.updatedAt', { updatedAt }) }}</span>
</li> </li>
</ul> </ul>

View File

@@ -57,7 +57,7 @@ function handleFormCancel() {
<template> <template>
<template v-if="worldSkeleton"> <template v-if="worldSkeleton">
<form class="h-full grid grid-rows-[1fr_auto]" @submit.prevent="handleSubmit"> <form class="h-full grid grid-rows-[1fr_auto]" @submit.prevent="handleSubmit">
<div> <div class="grid gap-4">
<input <input
id="new-world-name" id="new-world-name"
v-model="worldSkeleton.name" v-model="worldSkeleton.name"
@@ -69,10 +69,6 @@ function handleFormCancel() {
@input="handleNameChange" @input="handleNameChange"
> >
<div class="-mx-1 mb-4">
<InputColor v-model="worldSkeleton.color" />
</div>
<textarea <textarea
id="new-world-description" id="new-world-description"
v-model="worldSkeleton.description" v-model="worldSkeleton.description"
@@ -80,6 +76,22 @@ function handleFormCancel() {
:placeholder="$t('entity.addDescription')" :placeholder="$t('entity.addDescription')"
class="w-full -my-1 py-1 -mx-1 px-1 min-h-24 max-h-36 text-sm border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600" class="w-full -my-1 py-1 -mx-1 px-1 min-h-24 max-h-36 text-sm border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600"
/> />
<div class="-mx-1 grid gap-3">
<UiLabel for="new-world-color">
{{ $t('ui.colors.label') }}
</UiLabel>
<InputColor id="new-world-color" v-model="worldSkeleton.color" />
</div>
<div class="-mx-1 grid gap-3">
<UiLabel for="new-world-state">
{{ $t('ui.contentState.label') }}
</UiLabel>
<InputContentState id="new-world-state" v-model="worldSkeleton.state" />
</div>
</div> </div>
<footer class="flex justify-end gap-2 mt-6"> <footer class="flex justify-end gap-2 mt-6">

View File

@@ -71,7 +71,7 @@ function handleFormCancel() {
<template> <template>
<template v-if="worldSkeleton"> <template v-if="worldSkeleton">
<form class="h-full grid grid-rows-[1fr_auto]" @submit.prevent="handleSubmit"> <form class="h-full grid grid-rows-[1fr_auto]" @submit.prevent="handleSubmit">
<div> <div class="grid gap-4">
<input <input
id="new-world-name" id="new-world-name"
v-model="worldSkeleton.name" v-model="worldSkeleton.name"
@@ -79,7 +79,7 @@ function handleFormCancel() {
name="new-world-name" name="new-world-name"
required required
:placeholder="$t('common.title')" :placeholder="$t('common.title')"
class="w-full -my-1 mb-4 py-2 -mx-1 px-1 text-xl border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600" class="w-full -my-1 py-2 -mx-1 px-1 text-xl border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600"
@input="handleNameChange" @input="handleNameChange"
> >
@@ -91,12 +91,20 @@ function handleFormCancel() {
class="w-full -my-1 py-1 -mx-1 px-1 min-h-24 max-h-36 text-sm border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600" class="w-full -my-1 py-1 -mx-1 px-1 min-h-24 max-h-36 text-sm border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600"
/> />
<div class="-mx-1 mb-4"> <div class="-mx-1 grid gap-3">
<InputColor v-model="worldSkeleton.color" /> <UiLabel for="new-world-color">
{{ $t('ui.colors.label') }}
</UiLabel>
<InputColor id="new-world-color" v-model="worldSkeleton.color" />
</div> </div>
<div class="-mx-1 mb-4"> <div class="-mx-1 grid gap-3">
<InputContentState v-model="worldSkeleton.state" /> <UiLabel for="new-world-state">
{{ $t('ui.contentState.label') }}
</UiLabel>
<InputContentState id="new-world-state" v-model="worldSkeleton.state" />
</div> </div>
</div> </div>

View File

@@ -17,6 +17,7 @@ export default defineI18nConfig(() => ({
edit: "Edit", edit: "Edit",
}, },
colors: { colors: {
label: "Color",
selectOne: "Select a color", selectOne: "Select a color",
red: "Red", red: "Red",
orange: "Orange", orange: "Orange",
@@ -39,6 +40,7 @@ export default defineI18nConfig(() => ({
white: "White", white: "White",
}, },
contentState: { contentState: {
label: "Status",
selectOne: "Select a publication state", selectOne: "Select a publication state",
published: "Published", published: "Published",
draft: "Draft", draft: "Draft",
@@ -278,6 +280,7 @@ export default defineI18nConfig(() => ({
edit: "Modifier", edit: "Modifier",
}, },
colors: { colors: {
label: "Couleur",
selectOne: "Sélectionner une couleur", selectOne: "Sélectionner une couleur",
red: "Rouge", red: "Rouge",
orange: "Orange", orange: "Orange",
@@ -300,7 +303,8 @@ export default defineI18nConfig(() => ({
white: "Blanc", white: "Blanc",
}, },
contentState: { contentState: {
selectOne: "Modify l'état de publication", label: tat de publication",
selectOne: "Modifier l'état de publication",
published: "Publié", published: "Publié",
draft: "Brouillon", draft: "Brouillon",
archived: "Archivé", archived: "Archivé",

View File

@@ -15,6 +15,9 @@ export interface World {
updatedAt?: string updatedAt?: string
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type WorldChannelPayload = World & Record<string, any>
export const postWorldSchema = z.object({ export const postWorldSchema = z.object({
name: z.string(), name: z.string(),
description: z.string().optional().nullable(), description: z.string().optional().nullable(),

View File

@@ -1,6 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { RealtimeChannel } from "@supabase/supabase-js" import type { RealtimeChannel } from "@supabase/supabase-js"
import type { World } from "~/models/World"; import type { World, WorldChannelPayload } from "~/models/World";
const supabase = useSupabaseClient() const supabase = useSupabaseClient()
const user = useSupabaseUser() const user = useSupabaseUser()
@@ -31,10 +31,14 @@ function hideCreateDialog() {
/** Active world channel */ /** Active world channel */
let worldChannel: RealtimeChannel let worldChannel: RealtimeChannel
/** Handles world insertion realtime events */ /** Handles world insertion realtime events */
function handleInsertedWorld(newWorld: World) { function handleInsertedWorld(newWorld: WorldChannelPayload) {
if (!worlds.value?.data) return if (!worlds.value?.data) return
newWorld.createdAt = newWorld.created_at;
newWorld.gmId = newWorld.gm_id;
try { try {
worlds.value?.data.push(newWorld) worlds.value?.data.push(newWorld)
} catch (err) { } catch (err) {

View File

@@ -58,7 +58,9 @@ export default defineEventHandler(async (event) => {
name, name,
description, description,
color, color,
gm_id, createdAt:created_at,
updatedAt:updated_at,
gmId:gm_id,
state state
`) `)
.single<World>() .single<World>()

View File

@@ -33,6 +33,8 @@ export default defineEventHandler(async (event) => {
name, name,
description, description,
color, color,
createdAt:created_at,
updatedAt:updated_at,
gmId:gm_id gmId:gm_id
`) `)
.single<World>() .single<World>()