Merge pull request #24 from AlexisNP/features/add-categories-management-to-event-cr
Add categories to event
This commit is contained in:
128
assets/main.css
128
assets/main.css
@@ -77,6 +77,134 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Colors */
|
||||||
|
.event-red {
|
||||||
|
@apply text-slate-900 bg-red-500 hover:bg-red-600
|
||||||
|
}
|
||||||
|
.event-orange {
|
||||||
|
@apply text-slate-900 bg-orange-500 hover:bg-orange-600
|
||||||
|
}
|
||||||
|
.event-amber {
|
||||||
|
@apply text-slate-900 bg-amber-500 hover:bg-amber-600
|
||||||
|
}
|
||||||
|
.event-yellow {
|
||||||
|
@apply text-slate-900 bg-yellow-600 hover:bg-yellow-700
|
||||||
|
}
|
||||||
|
.event-lime {
|
||||||
|
@apply text-slate-900 bg-lime-500 hover:bg-lime-600
|
||||||
|
}
|
||||||
|
.event-green {
|
||||||
|
@apply text-white bg-green-600 hover:bg-green-700
|
||||||
|
}
|
||||||
|
.event-emerald {
|
||||||
|
@apply text-white bg-emerald-600 hover:bg-emerald-700
|
||||||
|
}
|
||||||
|
.event-teal {
|
||||||
|
@apply text-white bg-teal-600 hover:bg-teal-700
|
||||||
|
}
|
||||||
|
.event-cyan {
|
||||||
|
@apply text-white bg-cyan-600 hover:bg-cyan-700
|
||||||
|
}
|
||||||
|
.event-sky {
|
||||||
|
@apply text-white bg-sky-600 hover:bg-sky-700
|
||||||
|
}
|
||||||
|
.event-blue {
|
||||||
|
@apply text-white bg-blue-600 hover:bg-blue-700
|
||||||
|
}
|
||||||
|
.event-indigo {
|
||||||
|
@apply text-white bg-indigo-600 hover:bg-indigo-700
|
||||||
|
}
|
||||||
|
.event-violet {
|
||||||
|
@apply text-white bg-violet-600 hover:bg-violet-700
|
||||||
|
}
|
||||||
|
.event-purple {
|
||||||
|
@apply text-white bg-purple-600 hover:bg-purple-700
|
||||||
|
}
|
||||||
|
.event-fuchsia {
|
||||||
|
@apply text-white bg-fuchsia-600 hover:bg-fuchsia-700
|
||||||
|
}
|
||||||
|
.event-pink {
|
||||||
|
@apply text-white bg-pink-700 hover:bg-pink-800
|
||||||
|
}
|
||||||
|
.event-rose {
|
||||||
|
@apply text-white bg-rose-700 hover:bg-rose-800
|
||||||
|
}
|
||||||
|
.event-black {
|
||||||
|
@apply text-white bg-stone-500 hover:bg-stone-700
|
||||||
|
}
|
||||||
|
.event-white {
|
||||||
|
@apply text-slate-900 bg-white hover:bg-yellow-200
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-details-red {
|
||||||
|
--base-color: var(--color-red-800);
|
||||||
|
}
|
||||||
|
.event-details-orange {
|
||||||
|
--base-color: var(--color-orange-800);
|
||||||
|
}
|
||||||
|
.event-details-amber {
|
||||||
|
--base-color: var(--color-amber-800);
|
||||||
|
}
|
||||||
|
.event-details-yellow {
|
||||||
|
--base-color: var(--color-yellow-800);
|
||||||
|
}
|
||||||
|
.event-details-lime {
|
||||||
|
--base-color: var(--color-lime-800);
|
||||||
|
}
|
||||||
|
.event-details-green {
|
||||||
|
--base-color: var(--color-green-800);
|
||||||
|
}
|
||||||
|
.event-details-emerald {
|
||||||
|
--base-color: var(--color-emerald-800);
|
||||||
|
}
|
||||||
|
.event-details-teal {
|
||||||
|
--base-color: var(--color-teal-800);
|
||||||
|
}
|
||||||
|
.event-details-cyan {
|
||||||
|
--base-color: var(--color-cyan-800);
|
||||||
|
}
|
||||||
|
.event-details-sky {
|
||||||
|
--base-color: var(--color-sky-800);
|
||||||
|
}
|
||||||
|
.event-details-blue {
|
||||||
|
--base-color: var(--color-blue-800);
|
||||||
|
}
|
||||||
|
.event-details-indigo {
|
||||||
|
--base-color: var(--color-indigo-800);
|
||||||
|
}
|
||||||
|
.event-details-violet {
|
||||||
|
--base-color: var(--color-violet-800);
|
||||||
|
}
|
||||||
|
.event-details-purple {
|
||||||
|
--base-color: var(--color-purple-800);
|
||||||
|
}
|
||||||
|
.event-details-fuchsia {
|
||||||
|
--base-color: var(--color-fuchsia-800);
|
||||||
|
}
|
||||||
|
.event-details-pink {
|
||||||
|
--base-color: var(--color-pink-800);
|
||||||
|
}
|
||||||
|
.event-details-rose {
|
||||||
|
--base-color: var(--color-rose-800);
|
||||||
|
}
|
||||||
|
.event-details-black {
|
||||||
|
--base-color: var(--color-stone-800);
|
||||||
|
}
|
||||||
|
.event-details-white {
|
||||||
|
--base-color: var(--color-white);
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-details {
|
||||||
|
--bg-color: color-mix(in srgb, var(--base-color), var(--color-slate-950) 80%);
|
||||||
|
--border-color: color-mix(in srgb, var(--base-color), var(--color-slate-800) 50%);
|
||||||
|
background-color: var(--bg-color);
|
||||||
|
border-color: var(--border-color);
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border-color: var(--border-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.fade-enter-active,
|
.fade-enter-active,
|
||||||
.fade-leave-active {
|
.fade-leave-active {
|
||||||
transition: all .5s ease;
|
transition: all .5s ease;
|
||||||
|
|||||||
@@ -12,11 +12,12 @@ const route = useRoute()
|
|||||||
const worldId = route.params.id
|
const worldId = route.params.id
|
||||||
|
|
||||||
const { setCalendarId, setMonths, setDefaultDate, currentConfig, selectedDate, jumpToDate } = useCalendar()
|
const { setCalendarId, setMonths, setDefaultDate, currentConfig, selectedDate, jumpToDate } = useCalendar()
|
||||||
const { setEvents } = useCalendarEvents()
|
const { setEvents, setCategories } = useCalendarEvents()
|
||||||
const { setCharacters } = useCharacters()
|
const { setCharacters } = useCharacters()
|
||||||
|
|
||||||
const { data: calendar, pending: calPending, refresh: calRefresh } = await useLazyFetch(`/api/calendars/query?world_id=${worldId}`)
|
const { data: calendar, pending: calPending, refresh: calRefresh } = await useLazyFetch(`/api/calendars/query?world_id=${worldId}`)
|
||||||
const { data: characters, pending: charPending, refresh: charRefresh } = await useLazyFetch(`/api/characters/query?world_id=${worldId}`)
|
const { data: characters, pending: charPending, refresh: charRefresh } = await useLazyFetch(`/api/characters/query?world_id=${worldId}`)
|
||||||
|
const { data: categories, pending: categoryPending, refresh: categoryRefresh } = await useLazyFetch(`/api/calendars/categories/query`)
|
||||||
|
|
||||||
if (!calendar.value) {
|
if (!calendar.value) {
|
||||||
await calRefresh()
|
await calRefresh()
|
||||||
@@ -37,6 +38,15 @@ if (!calendar.value) {
|
|||||||
setEvents(calendar.value?.data?.events)
|
setEvents(calendar.value?.data?.events)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!categories.value) {
|
||||||
|
await categoryRefresh()
|
||||||
|
} else {
|
||||||
|
if (categories.value?.data) {
|
||||||
|
setCategories(categories.value?.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!characters.value) {
|
if (!characters.value) {
|
||||||
await charRefresh()
|
await charRefresh()
|
||||||
} else {
|
} else {
|
||||||
@@ -61,6 +71,13 @@ watch(calPending, (newStatus) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
watch(categoryPending, (newStatus) => {
|
||||||
|
if (!newStatus) {
|
||||||
|
if (categories.value?.data) {
|
||||||
|
setCategories(categories.value?.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
watch(charPending, (newStatus) => {
|
watch(charPending, (newStatus) => {
|
||||||
if (!newStatus) {
|
if (!newStatus) {
|
||||||
if (characters.value?.data) {
|
if (characters.value?.data) {
|
||||||
@@ -103,7 +120,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="h-full">
|
<div class="h-full">
|
||||||
<template v-if="calPending || charPending">
|
<template v-if="calPending || charPending || categoryPending">
|
||||||
<div class="h-full grid place-items-center">
|
<div class="h-full grid place-items-center">
|
||||||
Loading notamment
|
Loading notamment
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import type { RPGDate } from '@/models/Date'
|
import type { RPGDate } from '@/models/Date'
|
||||||
import type { CalendarEvent } from '~/models/CalendarEvent'
|
import type { CalendarEvent } from '~/models/CalendarEvent'
|
||||||
@@ -13,9 +12,9 @@ const { areDatesIdentical } = useCalendar()
|
|||||||
const { revealEditEventModal, revealDeleteEventModal } = useCalendarEvents()
|
const { revealEditEventModal, revealDeleteEventModal } = useCalendarEvents()
|
||||||
const { lastActiveEvent } = storeToRefs(useCalendarEvents())
|
const { lastActiveEvent } = storeToRefs(useCalendarEvents())
|
||||||
|
|
||||||
const spansMultipleDays = Boolean(props.event.startDate && props.event.endDate)
|
const spansMultipleDays = computed(() => Boolean(props.event.startDate && props.event.endDate))
|
||||||
const isStartEvent = spansMultipleDays && areDatesIdentical(props.tileDate, props.event.startDate)
|
const isStartEvent = computed(() => spansMultipleDays.value && areDatesIdentical(props.tileDate, props.event.startDate))
|
||||||
const isEndEvent = spansMultipleDays && props.event.endDate && areDatesIdentical(props.tileDate, props.event.endDate)
|
const isEndEvent = computed(() => spansMultipleDays.value && props.event.endDate && areDatesIdentical(props.tileDate, props.event.endDate))
|
||||||
|
|
||||||
const titleCharLimit = 50;
|
const titleCharLimit = 50;
|
||||||
const eventTitle = computed<string>(() => props.event.title.length <= titleCharLimit ? props.event.title : `${props.event.title.slice(0, titleCharLimit)}…`)
|
const eventTitle = computed<string>(() => props.event.title.length <= titleCharLimit ? props.event.title : `${props.event.title.slice(0, titleCharLimit)}…`)
|
||||||
@@ -59,30 +58,14 @@ onMounted(() => {
|
|||||||
<button
|
<button
|
||||||
class="text-xs px-2 py-1 block w-full text-left rounded-sm focus-visible:bg-red-200"
|
class="text-xs px-2 py-1 block w-full text-left rounded-sm focus-visible:bg-red-200"
|
||||||
:class="
|
:class="
|
||||||
cn({
|
cn(
|
||||||
|
event.category ? `event-${event.category.color}` : '',
|
||||||
|
{
|
||||||
'italic': event.hidden,
|
'italic': event.hidden,
|
||||||
'text-white bg-slate-600 hover:bg-slate-700': !event.category,
|
|
||||||
'text-white bg-lime-600 hover:bg-lime-700': event.category?.name === 'naissance',
|
|
||||||
'text-white bg-stone-500 hover:bg-stone-700': event.category?.name === 'mort',
|
|
||||||
'text-white bg-orange-600 hover:bg-orange-700': event.category?.name === 'catastrophe',
|
|
||||||
'text-white bg-pink-600 hover:bg-pink-700': event.category?.name === 'catastrophe naturelle',
|
|
||||||
'text-white bg-sky-600 hover:bg-sky-700': event.category?.name === 'législation',
|
|
||||||
'text-white bg-purple-600 hover:bg-purple-700': event.category?.name === 'religion',
|
|
||||||
'text-white bg-emerald-600 hover:bg-emerald-700': event.category?.name === 'joueurs',
|
|
||||||
'text-slate-900 bg-amber-300 hover:bg-amber-400': event.category?.name === 'inauguration',
|
|
||||||
'text-slate-900 bg-emerald-200 hover:bg-emerald-300': event.category?.name === 'invention',
|
|
||||||
'text-slate-900 bg-cyan-300 hover:bg-cyan-400': event.category?.name === 'science',
|
|
||||||
'text-slate-900 bg-white hover:bg-yellow-200': event.category?.name === 'bénédiction',
|
|
||||||
'text-slate-900 bg-purple-200 hover:bg-purple-300': event.category?.name === 'découverte',
|
|
||||||
'text-slate-900 bg-indigo-200 hover:bg-indigo-300': event.category?.name === 'exploration',
|
|
||||||
'text-white bg-amber-600 hover:bg-amber-700': event.category?.name === 'construction',
|
|
||||||
'text-slate-900 bg-violet-200 hover:bg-violet-300': event.category?.name === 'arcanologie',
|
|
||||||
'text-white bg-rose-600 hover:bg-rose-700': event.category?.name === 'criminalité',
|
|
||||||
'text-white bg-stone-600 hover:bg-stone-700': event.category?.name === 'scandale',
|
|
||||||
'text-slate-900 bg-yellow-500 hover:bg-yellow-600': event.category?.name === 'commerce',
|
|
||||||
'rounded-r-none': isStartEvent,
|
'rounded-r-none': isStartEvent,
|
||||||
'rounded-l-none': isEndEvent
|
'rounded-l-none': isEndEvent,
|
||||||
})
|
}
|
||||||
|
)
|
||||||
"
|
"
|
||||||
@dblclick="handleDoubleClick"
|
@dblclick="handleDoubleClick"
|
||||||
@keydown.delete="handleDelete"
|
@keydown.delete="handleDelete"
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
import type { RPGDate } from '@/models/Date'
|
import type { RPGDate } from '@/models/Date'
|
||||||
import type { CalendarEvent } from '@/models/CalendarEvent'
|
import type { CalendarEvent } from '@/models/CalendarEvent'
|
||||||
import { useCalendar } from '@/stores/CalendarStore'
|
import { useCalendar } from '@/stores/CalendarStore'
|
||||||
@@ -62,33 +63,18 @@ function deployDeleteModal() {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<UiPopoverContent
|
<UiPopoverContent
|
||||||
class="event-details w-96 bg-slate-900"
|
class=" w-96 bg-slate-900 border-slate-800"
|
||||||
:align="'center'"
|
:align="'center'"
|
||||||
:align-offset="50"
|
:align-offset="50"
|
||||||
:side="'left'"
|
:side="'left'"
|
||||||
:collision-padding="60"
|
:collision-padding="60"
|
||||||
:hide-when-detached="true"
|
:hide-when-detached="true"
|
||||||
:class="{
|
:class="cn(
|
||||||
'border-slate-800': !event.category,
|
event.category ? `event-details-${event.category.color}` : '',
|
||||||
'border-lime-800': event.category?.name === 'naissance',
|
{
|
||||||
'border-stone-600': event.category?.name === 'mort',
|
'event-details': event.category
|
||||||
'border-orange-800': event.category?.name === 'catastrophe',
|
}
|
||||||
'border-pink-800': event.category?.name === 'catastrophe naturelle',
|
)"
|
||||||
'border-sky-800': event.category?.name === 'législation',
|
|
||||||
'border-purple-800': event.category?.name === 'religion',
|
|
||||||
'border-emerald-800': event.category?.name === 'joueurs',
|
|
||||||
'border-amber-800': event.category?.name === 'inauguration',
|
|
||||||
'border-green-800': event.category?.name === 'invention',
|
|
||||||
'border-cyan-800': event.category?.name === 'science',
|
|
||||||
'border-slate-600': event.category?.name === 'bénédiction',
|
|
||||||
'border-purple-700': event.category?.name === 'découverte',
|
|
||||||
'border-indigo-700': event.category?.name === 'exploration',
|
|
||||||
'border-amber-700': event.category?.name === 'construction',
|
|
||||||
'border-violet-700': event.category?.name === 'arcanologie',
|
|
||||||
'border-rose-800': event.category?.name === 'criminalité',
|
|
||||||
'border-stone-700': event.category?.name === 'scandale',
|
|
||||||
'border-yellow-600': event.category?.name === 'commerce'
|
|
||||||
}"
|
|
||||||
>
|
>
|
||||||
<div ref="eventDetails" class="grid gap-1">
|
<div ref="eventDetails" class="grid gap-1">
|
||||||
<header class="pr-12">
|
<header class="pr-12">
|
||||||
@@ -128,13 +114,13 @@ function deployDeleteModal() {
|
|||||||
<template v-if="event.category || event.secondaryCategories">
|
<template v-if="event.category || event.secondaryCategories">
|
||||||
<ul class="flex gap-1">
|
<ul class="flex gap-1">
|
||||||
<li v-if="event.category">
|
<li v-if="event.category">
|
||||||
<UiBadge class="mix-blend-luminosity font-bold bg-gray-600" variant="secondary">
|
<UiBadge class="mix-blend-luminosity font-bold bg-gray-600 lowercase" variant="secondary">
|
||||||
{{ event.category?.name }}
|
{{ event.category?.name }}
|
||||||
</UiBadge>
|
</UiBadge>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li v-for="cat in event.secondaryCategories" :key="cat.id">
|
<li v-for="cat in event.secondaryCategories" :key="cat.id">
|
||||||
<UiBadge class="mix-blend-luminosity bg-gray-600" variant="secondary">
|
<UiBadge class="mix-blend-luminosity bg-gray-600 lowercase" variant="secondary">
|
||||||
{{ cat.name }}
|
{{ cat.name }}
|
||||||
</UiBadge>
|
</UiBadge>
|
||||||
</li>
|
</li>
|
||||||
@@ -205,72 +191,3 @@ function deployDeleteModal() {
|
|||||||
</UiTooltipProvider>
|
</UiTooltipProvider>
|
||||||
</UiPopoverContent>
|
</UiPopoverContent>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.border-slate-800 {
|
|
||||||
--base-color: var(--color-slate-800);
|
|
||||||
}
|
|
||||||
.border-lime-800 {
|
|
||||||
--base-color: var(--color-lime-800);
|
|
||||||
}
|
|
||||||
.border-stone-600 {
|
|
||||||
--base-color: var(--color-stone-600);
|
|
||||||
}
|
|
||||||
.border-orange-800 {
|
|
||||||
--base-color: var(--color-orange-800);
|
|
||||||
}
|
|
||||||
.border-pink-800 {
|
|
||||||
--base-color: var(--color-pink-800);
|
|
||||||
}
|
|
||||||
.border-sky-800 {
|
|
||||||
--base-color: var(--color-sky-800);
|
|
||||||
}
|
|
||||||
.border-purple-800 {
|
|
||||||
--base-color: var(--color-purple-800);
|
|
||||||
}
|
|
||||||
.border-emerald-800 {
|
|
||||||
--base-color: var(--color-emerald-800);
|
|
||||||
}
|
|
||||||
.border-amber-800 {
|
|
||||||
--base-color: var(--color-amber-800);
|
|
||||||
}
|
|
||||||
.border-green-800 {
|
|
||||||
--base-color: var(--color-green-800);
|
|
||||||
}
|
|
||||||
.border-cyan-800 {
|
|
||||||
--base-color: var(--color-cyan-800);
|
|
||||||
}
|
|
||||||
.border-slate-600 {
|
|
||||||
--base-color: var(--color-slate-600);
|
|
||||||
}
|
|
||||||
.border-purple-700 {
|
|
||||||
--base-color: var(--color-purple-700);
|
|
||||||
}
|
|
||||||
.border-indigo-700 {
|
|
||||||
--base-color: var(--color-indigo-700);
|
|
||||||
}
|
|
||||||
.border-amber-700 {
|
|
||||||
--base-color: var(--color-amber-700);
|
|
||||||
}
|
|
||||||
.border-violet-700 {
|
|
||||||
--base-color: var(--color-violet-700);
|
|
||||||
}
|
|
||||||
.border-rose-800 {
|
|
||||||
--base-color: var(--color-rose-800);
|
|
||||||
}
|
|
||||||
.border-stone-700 {
|
|
||||||
--base-color: var(--color-stone-700);
|
|
||||||
}
|
|
||||||
.border-yellow-600 {
|
|
||||||
--base-color: var(--color-yellow-600);
|
|
||||||
}
|
|
||||||
|
|
||||||
.event-details {
|
|
||||||
--bg-color: color-mix(in srgb, var(--base-color), var(--color-slate-950) 85%);
|
|
||||||
background-color: var(--bg-color);
|
|
||||||
|
|
||||||
hr {
|
|
||||||
border-color: var(--base-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { RPGDate } from '~/models/Date';
|
import type { RPGDate } from '~/models/Date';
|
||||||
import { PopoverAnchor } from 'radix-vue';
|
import { PhAlarm, PhCircleNotch, PhEye, PhEyeClosed, PhMapPinArea, PhTag } from '@phosphor-icons/vue'
|
||||||
import { PhAlarm, PhCircleNotch, PhEye, PhEyeClosed, PhMapPinArea } from '@phosphor-icons/vue'
|
|
||||||
|
|
||||||
const { eventSkeleton, operationInProgress } = storeToRefs(useCalendarEvents())
|
const { eventSkeleton, operationInProgress } = storeToRefs(useCalendarEvents())
|
||||||
const { resetSkeleton, submitSkeleton, cancelLatestRequest } = useCalendarEvents()
|
const { resetSkeleton, submitSkeleton, cancelLatestRequest } = useCalendarEvents()
|
||||||
@@ -80,9 +79,9 @@ function handleCancel() {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<UiPopover v-model:open="popoverOpen">
|
<UiPopover v-model:open="popoverOpen">
|
||||||
<PopoverAnchor as-child>
|
<UiPopoverTrigger as-child>
|
||||||
<button :class="btnClass" @dblclick="openEventCreatePopover()" />
|
<button :class="btnClass" @click="openEventCreatePopover()" />
|
||||||
</PopoverAnchor>
|
</UiPopoverTrigger>
|
||||||
<UiPopoverContent
|
<UiPopoverContent
|
||||||
:align="'center'"
|
:align="'center'"
|
||||||
:side="'right'"
|
:side="'right'"
|
||||||
@@ -96,7 +95,7 @@ function handleCancel() {
|
|||||||
@pointer-down-outside="handleClosing"
|
@pointer-down-outside="handleClosing"
|
||||||
>
|
>
|
||||||
<form @submit.prevent="handleSubmit">
|
<form @submit.prevent="handleSubmit">
|
||||||
<div class="grid grid-cols-2 gap-y-6">
|
<div class="grid grid-cols-2 gap-y-3">
|
||||||
<div class="col-span-2 pl-8">
|
<div class="col-span-2 pl-8">
|
||||||
<input
|
<input
|
||||||
id="new-event-title"
|
id="new-event-title"
|
||||||
@@ -108,7 +107,7 @@ function handleCancel() {
|
|||||||
class="w-full -my-1 py-1 -mx-1 px-1 text-lg 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 text-lg border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-span-2 pl-8">
|
<div class="col-span-2 my-2 pl-8">
|
||||||
<textarea
|
<textarea
|
||||||
id="new-event-description"
|
id="new-event-description"
|
||||||
v-model="eventSkeleton.description"
|
v-model="eventSkeleton.description"
|
||||||
@@ -140,6 +139,22 @@ function handleCancel() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-span-2">
|
<div class="col-span-2">
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<PhTag size="18" weight="fill" />
|
||||||
|
|
||||||
|
<CalendarInputEventCategory v-model="eventSkeleton.category" placeholder="Ajouter une catégorie principale" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- <div class="col-span-2">
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<PhTag size="18" weight="fill" />
|
||||||
|
|
||||||
|
<CalendarInputEventCategories v-model="eventSkeleton.secondaryCategories" placeholder="Ajouter des catégories secondaires" />
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
<div class="col-span-2 mb-2">
|
||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<PhMapPinArea size="18" weight="fill" />
|
<PhMapPinArea size="18" weight="fill" />
|
||||||
|
|
||||||
@@ -149,7 +164,7 @@ function handleCancel() {
|
|||||||
type="text"
|
type="text"
|
||||||
name="new-event-location"
|
name="new-event-location"
|
||||||
placeholder="Ajouter un endroit"
|
placeholder="Ajouter un endroit"
|
||||||
class="w-full -my-1 py-1 px-2 text-sm border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600">
|
class="w-full -my-1 py-2 px-2 text-sm border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { PhAlarm, PhCircleNotch, PhEye, PhEyeClosed, PhMapPinArea, PhPencilSimpleLine } from '@phosphor-icons/vue'
|
import { PhAlarm, PhCircleNotch, PhEye, PhEyeClosed, PhMapPinArea, PhPencilSimpleLine, PhTag } from '@phosphor-icons/vue'
|
||||||
import { VisuallyHidden } from 'radix-vue'
|
import { VisuallyHidden } from 'radix-vue'
|
||||||
|
|
||||||
const { isEditEventModalOpen } = storeToRefs(useCalendarEvents())
|
const { isEditEventModalOpen } = storeToRefs(useCalendarEvents())
|
||||||
@@ -81,7 +81,7 @@ function handleCancel() {
|
|||||||
</VisuallyHidden>
|
</VisuallyHidden>
|
||||||
|
|
||||||
<form @submit.prevent="handleAction">
|
<form @submit.prevent="handleAction">
|
||||||
<div class="grid grid-cols-2 gap-y-6">
|
<div class="grid grid-cols-2 gap-y-3">
|
||||||
<div class="col-span-2">
|
<div class="col-span-2">
|
||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<PhPencilSimpleLine size="20" weight="fill" />
|
<PhPencilSimpleLine size="20" weight="fill" />
|
||||||
@@ -98,7 +98,7 @@ function handleCancel() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-span-2 ml-8">
|
<div class="col-span-2 my-2 ml-8">
|
||||||
<textarea
|
<textarea
|
||||||
id="new-event-description"
|
id="new-event-description"
|
||||||
v-model="eventSkeleton.description"
|
v-model="eventSkeleton.description"
|
||||||
@@ -130,6 +130,26 @@ function handleCancel() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-span-2">
|
<div class="col-span-2">
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<PhTag size="18" weight="fill" />
|
||||||
|
|
||||||
|
<div class="w-1/2">
|
||||||
|
<CalendarInputEventCategory v-model="eventSkeleton.category" placeholder="Ajouter une catégorie principale" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- <div class="col-span-2">
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<PhTag size="18" weight="fill" />
|
||||||
|
|
||||||
|
<div class="w-1/2">
|
||||||
|
<CalendarInputEventCategories v-model="eventSkeleton.secondaryCategories" placeholder="Ajouter des catégories secondaires" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
<div class="col-span-2 mb-2">
|
||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<PhMapPinArea size="18" weight="fill" />
|
<PhMapPinArea size="18" weight="fill" />
|
||||||
|
|
||||||
@@ -139,7 +159,7 @@ function handleCancel() {
|
|||||||
type="text"
|
type="text"
|
||||||
name="new-event-location"
|
name="new-event-location"
|
||||||
placeholder="Ajouter un endroit"
|
placeholder="Ajouter un endroit"
|
||||||
class="w-full -my-1 py-1 px-2 text-sm border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600">
|
class="w-full -my-1 py-2 px-2 text-sm border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
88
components/calendar/input/EventCategories.vue
Normal file
88
components/calendar/input/EventCategories.vue
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import type { Category } from '~/models/Category';
|
||||||
|
|
||||||
|
import { PhCaretDown, PhCheck } from '@phosphor-icons/vue';
|
||||||
|
|
||||||
|
const isPopoverOpen = ref<boolean>(false)
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
placeholder?: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const model = defineModel<Category[]>({ default: [] })
|
||||||
|
const modelBuffer = ref<Category[]>([])
|
||||||
|
|
||||||
|
watch(modelBuffer.value, () => {
|
||||||
|
model.value = [ ...modelBuffer.value ]
|
||||||
|
})
|
||||||
|
|
||||||
|
const { categories: availableCategories } = useCalendarEvents()
|
||||||
|
|
||||||
|
const searchTerm = ref<string>('')
|
||||||
|
|
||||||
|
const filteredCategories = computed(() =>
|
||||||
|
searchTerm.value === ''
|
||||||
|
? availableCategories
|
||||||
|
: availableCategories.filter((category) => {
|
||||||
|
return category.name.toLowerCase().includes(searchTerm.value.toLowerCase())
|
||||||
|
})
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UiPopover v-model:open="isPopoverOpen">
|
||||||
|
<UiPopoverTrigger as-child>
|
||||||
|
<UiButton
|
||||||
|
variant="outline"
|
||||||
|
role="combobox"
|
||||||
|
class="relative w-full max-w-full h-fit justify-between"
|
||||||
|
>
|
||||||
|
<template v-if="!model.length">
|
||||||
|
{{ props.placeholder }}
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<ul class="flex flex-wrap gap-1">
|
||||||
|
<li v-for="category in model" :key="`selected-cat-${category.id}`">
|
||||||
|
<UiBadge class="lowercase" variant="secondary">
|
||||||
|
{{ category.name }}
|
||||||
|
</UiBadge>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<PhCaretDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||||
|
</UiButton>
|
||||||
|
</UiPopoverTrigger>
|
||||||
|
<UiPopoverContent
|
||||||
|
align="start"
|
||||||
|
side="bottom"
|
||||||
|
:collision-padding="50"
|
||||||
|
class="w-fit h-[33vh] p-0"
|
||||||
|
>
|
||||||
|
<UiCommand v-model="modelBuffer" v-model:searchTerm="searchTerm" :multiple="true">
|
||||||
|
<UiCommandInput placeholder="Rechercher les catégories" />
|
||||||
|
<UiCommandEmpty>Aucune catégorie trouvée.</UiCommandEmpty>
|
||||||
|
<UiCommandList>
|
||||||
|
<UiCommandGroup>
|
||||||
|
<UiCommandItem
|
||||||
|
v-for="category in filteredCategories"
|
||||||
|
:key="category.id"
|
||||||
|
:value="category"
|
||||||
|
class="cursor-pointer flex justify-between items-center"
|
||||||
|
:class="cn({
|
||||||
|
|
||||||
|
})"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
{{ category.name }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<PhCheck v-if="model.find(cat => cat.id === category.id)" />
|
||||||
|
</UiCommandItem>
|
||||||
|
</UiCommandGroup>
|
||||||
|
</UiCommandList>
|
||||||
|
</UiCommand>
|
||||||
|
</UiPopoverContent>
|
||||||
|
</UiPopover>
|
||||||
|
</template>
|
||||||
73
components/calendar/input/EventCategory.vue
Normal file
73
components/calendar/input/EventCategory.vue
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { PhCaretDown } from '@phosphor-icons/vue';
|
||||||
|
import type { Category } from '~/models/Category';
|
||||||
|
|
||||||
|
const isPopoverOpen = ref<boolean>(false)
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
placeholder?: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const model = defineModel<Category>()
|
||||||
|
|
||||||
|
const { categories: availableCategories } = useCalendarEvents()
|
||||||
|
|
||||||
|
const searchTerm = ref<string>('')
|
||||||
|
|
||||||
|
function handleCatSelect() {
|
||||||
|
isPopoverOpen.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const filteredCategories = computed(() =>
|
||||||
|
searchTerm.value === ''
|
||||||
|
? availableCategories
|
||||||
|
: availableCategories.filter((category) => {
|
||||||
|
return category.name.toLowerCase().includes(searchTerm.value.toLowerCase())
|
||||||
|
})
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UiPopover v-model:open="isPopoverOpen">
|
||||||
|
<UiPopoverTrigger as-child>
|
||||||
|
<UiButton
|
||||||
|
variant="outline"
|
||||||
|
role="combobox"
|
||||||
|
class="w-full max-w-full justify-between"
|
||||||
|
>
|
||||||
|
<template v-if="!model">
|
||||||
|
{{ props.placeholder }}
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
{{ model.name }}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<PhCaretDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||||
|
</UiButton>
|
||||||
|
</UiPopoverTrigger>
|
||||||
|
<UiPopoverContent
|
||||||
|
align="start"
|
||||||
|
side="bottom"
|
||||||
|
:collision-padding="50"
|
||||||
|
class="w-fit h-[33vh] p-0"
|
||||||
|
>
|
||||||
|
<UiCommand v-model="model" v-model:searchTerm="searchTerm">
|
||||||
|
<UiCommandInput placeholder="Rechercher les catégories" />
|
||||||
|
<UiCommandEmpty>Aucune catégorie trouvée.</UiCommandEmpty>
|
||||||
|
<UiCommandList>
|
||||||
|
<UiCommandGroup>
|
||||||
|
<UiCommandItem
|
||||||
|
v-for="category in filteredCategories"
|
||||||
|
:key="category.id"
|
||||||
|
:value="category"
|
||||||
|
class="cursor-pointer"
|
||||||
|
@select="handleCatSelect"
|
||||||
|
>
|
||||||
|
{{ category.name }}
|
||||||
|
</UiCommandItem>
|
||||||
|
</UiCommandGroup>
|
||||||
|
</UiCommandList>
|
||||||
|
</UiCommand>
|
||||||
|
</UiPopoverContent>
|
||||||
|
</UiPopover>
|
||||||
|
</template>
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
import type { RPGDate } from '@/models/Date'
|
import type { RPGDate } from '@/models/Date'
|
||||||
import type { CalendarEvent } from '@/models/CalendarEvent'
|
import type { CalendarEvent } from '@/models/CalendarEvent'
|
||||||
import { useCalendar } from '@/stores/CalendarStore'
|
import { useCalendar } from '@/stores/CalendarStore'
|
||||||
@@ -26,28 +27,11 @@ const dateDuration: string | null = props.event.endDate
|
|||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
class="relative block w-full text-left py-3 px-4 rounded-sm transition-colors"
|
class="relative block w-full text-left py-3 px-4 rounded-sm transition-colors"
|
||||||
:class="{
|
:class="cn(
|
||||||
|
event.category ? `event-${event.category.color}` : '',
|
||||||
|
{
|
||||||
'pt-4': event.hidden,
|
'pt-4': event.hidden,
|
||||||
'text-white bg-slate-600 hover:bg-slate-700': !event.category,
|
})"
|
||||||
'text-white bg-lime-600 hover:bg-lime-700': event.category?.name === 'naissance',
|
|
||||||
'text-white bg-stone-500 hover:bg-stone-700': event.category?.name === 'mort',
|
|
||||||
'text-white bg-orange-600 hover:bg-orange-700': event.category?.name === 'catastrophe',
|
|
||||||
'text-white bg-pink-600 hover:bg-pink-700': event.category?.name === 'catastrophe naturelle',
|
|
||||||
'text-white bg-sky-600 hover:bg-sky-700': event.category?.name === 'législation',
|
|
||||||
'text-white bg-purple-600 hover:bg-purple-700': event.category?.name === 'religion',
|
|
||||||
'text-white bg-emerald-600 hover:bg-emerald-700': event.category?.name === 'joueurs',
|
|
||||||
'text-slate-900 bg-amber-300 hover:bg-amber-400': event.category?.name === 'inauguration',
|
|
||||||
'text-slate-900 bg-emerald-200 hover:bg-emerald-300': event.category?.name === 'invention',
|
|
||||||
'text-slate-900 bg-cyan-300 hover:bg-cyan-400': event.category?.name === 'science',
|
|
||||||
'text-slate-900 bg-white hover:bg-yellow-200': event.category?.name === 'bénédiction',
|
|
||||||
'text-slate-900 bg-purple-200 hover:bg-purple-300': event.category?.name === 'découverte',
|
|
||||||
'text-slate-900 bg-indigo-200 hover:bg-indigo-300': event.category?.name === 'exploration',
|
|
||||||
'text-white bg-amber-600 hover:bg-amber-700': event.category?.name === 'construction',
|
|
||||||
'text-slate-900 bg-violet-200 hover:bg-violet-300': event.category?.name === 'arcanologie',
|
|
||||||
'text-white bg-rose-600 hover:bg-rose-700': event.category?.name === 'criminalité',
|
|
||||||
'text-white bg-stone-600 hover:bg-stone-700': event.category?.name === 'scandale',
|
|
||||||
'text-slate-900 bg-yellow-500 hover:bg-yellow-600': event.category?.name === 'commerce'
|
|
||||||
}"
|
|
||||||
@click="$emit('query:date-jump', event.startDate)"
|
@click="$emit('query:date-jump', event.startDate)"
|
||||||
>
|
>
|
||||||
<div class="flex gap-2 items-center mb-1">
|
<div class="flex gap-2 items-center mb-1">
|
||||||
@@ -97,13 +81,13 @@ const dateDuration: string | null = props.event.endDate
|
|||||||
<div v-if="event.category || event.secondaryCategories" class="absolute top-3 right-4">
|
<div v-if="event.category || event.secondaryCategories" class="absolute top-3 right-4">
|
||||||
<ul class="flex gap-1">
|
<ul class="flex gap-1">
|
||||||
<li v-if="event.category">
|
<li v-if="event.category">
|
||||||
<UiBadge class="mix-blend-luminosity font-bold bg-gray-600" variant="secondary">
|
<UiBadge class="mix-blend-luminosity font-bold bg-gray-600 lowercase" variant="secondary">
|
||||||
{{ event.category?.name }}
|
{{ event.category?.name }}
|
||||||
</UiBadge>
|
</UiBadge>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li v-for="cat in event.secondaryCategories" :key="cat.id">
|
<li v-for="cat in event.secondaryCategories" :key="cat.id">
|
||||||
<UiBadge class="mix-blend-luminosity bg-gray-600" variant="secondary">
|
<UiBadge class="mix-blend-luminosity bg-gray-600 lowercase" variant="secondary">
|
||||||
{{ cat.name }}
|
{{ cat.name }}
|
||||||
</UiBadge>
|
</UiBadge>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
33
components/ui/checkbox/Checkbox.vue
Normal file
33
components/ui/checkbox/Checkbox.vue
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { type HTMLAttributes, computed } from 'vue'
|
||||||
|
import type { CheckboxRootEmits, CheckboxRootProps } from 'radix-vue'
|
||||||
|
import { CheckboxIndicator, CheckboxRoot, useForwardPropsEmits } from 'radix-vue'
|
||||||
|
import { Check } from 'lucide-vue-next'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<CheckboxRootProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
const emits = defineEmits<CheckboxRootEmits>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<CheckboxRoot
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="
|
||||||
|
cn('peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground',
|
||||||
|
props.class)"
|
||||||
|
>
|
||||||
|
<CheckboxIndicator class="flex h-full w-full items-center justify-center text-current">
|
||||||
|
<slot>
|
||||||
|
<Check class="h-4 w-4" />
|
||||||
|
</slot>
|
||||||
|
</CheckboxIndicator>
|
||||||
|
</CheckboxRoot>
|
||||||
|
</template>
|
||||||
1
components/ui/checkbox/index.ts
Normal file
1
components/ui/checkbox/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export { default as Checkbox } from './Checkbox.vue'
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import type { Category } from './Category'
|
import { categorySchema, type Category } from './Category'
|
||||||
import { dateSchema, type RPGDate } from './Date'
|
import { dateSchema, type RPGDate } from './Date'
|
||||||
|
|
||||||
export interface CalendarEvent {
|
export interface CalendarEvent {
|
||||||
@@ -25,7 +25,8 @@ export const postEventBodySchema = z.object({
|
|||||||
location: z.string().optional().nullable(),
|
location: z.string().optional().nullable(),
|
||||||
startDate: dateSchema.required(),
|
startDate: dateSchema.required(),
|
||||||
endDate: dateSchema.optional().nullable(),
|
endDate: dateSchema.optional().nullable(),
|
||||||
hidden: z.boolean().optional().nullable()
|
hidden: z.boolean().optional().nullable(),
|
||||||
|
category: categorySchema.optional().nullable(),
|
||||||
}),
|
}),
|
||||||
calendarId: z.number({ coerce: true }).int().positive()
|
calendarId: z.number({ coerce: true }).int().positive()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,4 +1,14 @@
|
|||||||
|
import { z } from 'zod'
|
||||||
|
import type { RPGColor } from './Color'
|
||||||
|
|
||||||
export interface Category {
|
export interface Category {
|
||||||
id: number
|
id: number
|
||||||
name: string
|
name: string
|
||||||
|
color?: RPGColor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const categorySchema = z.object({
|
||||||
|
id: z.number().int(),
|
||||||
|
name: z.string(),
|
||||||
|
color: z.string().default("black")
|
||||||
|
})
|
||||||
|
|||||||
1
models/Color.ts
Normal file
1
models/Color.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export type RPGColor = "red" | "orange" | "amber" | "yellow" | "lime" | "green" | "emerald" | "teal" | "cyan" | "sky" | "blue" | "indigo" | "violet" | "purple" | "fuchsia" | "pink" | "rose" | "black" | "white"
|
||||||
15
server/api/calendars/categories/query.get.ts
Normal file
15
server/api/calendars/categories/query.get.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { serverSupabaseClient } from "#supabase/server";
|
||||||
|
import type { Category } from "~/models/Category";
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
const client = await serverSupabaseClient(event)
|
||||||
|
|
||||||
|
const output = client
|
||||||
|
.from('calendar_event_categories')
|
||||||
|
.select(`
|
||||||
|
id,
|
||||||
|
name
|
||||||
|
`)
|
||||||
|
|
||||||
|
return output.returns<Category[]>()
|
||||||
|
})
|
||||||
@@ -22,7 +22,6 @@ export default defineEventHandler(async (event) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bodyError) {
|
if (bodyError) {
|
||||||
console.log(bodyData)
|
|
||||||
throw createError({
|
throw createError({
|
||||||
cause: 'Utilisateur',
|
cause: 'Utilisateur',
|
||||||
fatal: false,
|
fatal: false,
|
||||||
@@ -42,6 +41,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
description: bodyData.event.description,
|
description: bodyData.event.description,
|
||||||
location: bodyData.event.location,
|
location: bodyData.event.location,
|
||||||
hidden: bodyData.event.hidden,
|
hidden: bodyData.event.hidden,
|
||||||
|
category: bodyData.event.category?.id,
|
||||||
calendar_id: bodyData?.calendarId
|
calendar_id: bodyData?.calendarId
|
||||||
} as never
|
} as never
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
description: bodyData.event.description,
|
description: bodyData.event.description,
|
||||||
location: bodyData.event.location,
|
location: bodyData.event.location,
|
||||||
hidden: bodyData.event.hidden,
|
hidden: bodyData.event.hidden,
|
||||||
|
category: bodyData.event.category?.id,
|
||||||
calendar_id: bodyData?.calendarId
|
calendar_id: bodyData?.calendarId
|
||||||
} as never
|
} as never
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import type { RPGDate } from '@/models/Date'
|
|
||||||
import type { CalendarEvent } from '@/models/CalendarEvent'
|
import type { CalendarEvent } from '@/models/CalendarEvent'
|
||||||
|
import type { RPGDate } from '@/models/Date'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { ref, watch, type Ref } from 'vue'
|
import { ref, watch, type Ref } from 'vue'
|
||||||
|
import type { Category } from '~/models/Category'
|
||||||
import { useCalendar } from './CalendarStore'
|
import { useCalendar } from './CalendarStore'
|
||||||
|
|
||||||
export const useCalendarEvents = defineStore('calendar-events', () => {
|
export const useCalendarEvents = defineStore('calendar-events', () => {
|
||||||
@@ -14,6 +15,12 @@ export const useCalendarEvents = defineStore('calendar-events', () => {
|
|||||||
baseEvents.value = data
|
baseEvents.value = data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const categories = ref<Category[]>([])
|
||||||
|
|
||||||
|
function setCategories(data: Category[]) {
|
||||||
|
categories.value = data
|
||||||
|
}
|
||||||
|
|
||||||
// Order base events by dates
|
// Order base events by dates
|
||||||
const allEvents = computed(() => baseEvents.value.sort((a, b) => {
|
const allEvents = computed(() => baseEvents.value.sort((a, b) => {
|
||||||
return compareDates(a.startDate, b.startDate, 'desc')
|
return compareDates(a.startDate, b.startDate, 'desc')
|
||||||
@@ -269,6 +276,8 @@ export const useCalendarEvents = defineStore('calendar-events', () => {
|
|||||||
return {
|
return {
|
||||||
allEvents,
|
allEvents,
|
||||||
setEvents,
|
setEvents,
|
||||||
|
categories,
|
||||||
|
setCategories,
|
||||||
currentEvents,
|
currentEvents,
|
||||||
getRelativeEventFromDate,
|
getRelativeEventFromDate,
|
||||||
getRelativeEventFromEvent,
|
getRelativeEventFromEvent,
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ create table public.worlds (
|
|||||||
id bigint generated by default as identity primary key,
|
id bigint generated by default as identity primary key,
|
||||||
name text not null,
|
name text not null,
|
||||||
description text,
|
description text,
|
||||||
color app_colors,
|
color app_colors default 'black',
|
||||||
gm_id uuid references public.users on delete cascade
|
gm_id uuid references public.users on delete cascade
|
||||||
);
|
);
|
||||||
comment on table public.worlds is 'Worlds belonging to a single user ; a game master.';
|
comment on table public.worlds is 'Worlds belonging to a single user ; a game master.';
|
||||||
@@ -49,6 +49,7 @@ create table public.calendars (
|
|||||||
id bigint generated by default as identity primary key,
|
id bigint generated by default as identity primary key,
|
||||||
name text not null,
|
name text not null,
|
||||||
today json not null,
|
today json not null,
|
||||||
|
color app_colors default 'black',
|
||||||
world_id bigint references public.worlds on delete cascade not null
|
world_id bigint references public.worlds on delete cascade not null
|
||||||
);
|
);
|
||||||
comment on table public.calendars is 'Calendar settings and configuration attached to a single world.';
|
comment on table public.calendars is 'Calendar settings and configuration attached to a single world.';
|
||||||
@@ -67,6 +68,7 @@ comment on table public.calendar_months is 'A calendar month.';
|
|||||||
create table public.calendar_event_categories (
|
create table public.calendar_event_categories (
|
||||||
id bigint generated by default as identity primary key,
|
id bigint generated by default as identity primary key,
|
||||||
name text not null,
|
name text not null,
|
||||||
|
color app_colors default 'black',
|
||||||
unique (name)
|
unique (name)
|
||||||
);
|
);
|
||||||
comment on table public.calendar_event_categories is 'Categories describing events.';
|
comment on table public.calendar_event_categories is 'Categories describing events.';
|
||||||
@@ -98,6 +100,7 @@ comment on table public.calendar_event_categories_links is 'Link tables for mult
|
|||||||
create table public.character_categories (
|
create table public.character_categories (
|
||||||
id bigint generated by default as identity primary key,
|
id bigint generated by default as identity primary key,
|
||||||
name text not null,
|
name text not null,
|
||||||
|
color app_colors default 'black',
|
||||||
unique (name)
|
unique (name)
|
||||||
);
|
);
|
||||||
comment on table public.character_categories is 'Categories describing characters';
|
comment on table public.character_categories is 'Categories describing characters';
|
||||||
|
|||||||
@@ -2,38 +2,38 @@ insert into public.role_permissions (role, permission) values ('sa', 'events.see
|
|||||||
insert into public.role_permissions (role, permission) values ('sa', 'users.ban');
|
insert into public.role_permissions (role, permission) values ('sa', 'users.ban');
|
||||||
|
|
||||||
-- Event categories
|
-- Event categories
|
||||||
insert into public.calendar_event_categories (name) values ('naissance');
|
insert into public.calendar_event_categories (name, color) values ('Naissance', 'white');
|
||||||
insert into public.calendar_event_categories (name) values ('mort');
|
insert into public.calendar_event_categories (name, color) values ('Mort', 'black');
|
||||||
insert into public.calendar_event_categories (name) values ('catastrophe');
|
insert into public.calendar_event_categories (name, color) values ('Catastrophe', 'orange');
|
||||||
insert into public.calendar_event_categories (name) values ('catastrophe naturelle');
|
insert into public.calendar_event_categories (name, color) values ('Catastrophe naturelle', 'red');
|
||||||
insert into public.calendar_event_categories (name) values ('inauguration');
|
insert into public.calendar_event_categories (name, color) values ('Inauguration', 'green');
|
||||||
insert into public.calendar_event_categories (name) values ('religion');
|
insert into public.calendar_event_categories (name, color) values ('Religion', 'violet');
|
||||||
insert into public.calendar_event_categories (name) values ('invention');
|
insert into public.calendar_event_categories (name, color) values ('Invention', 'teal');
|
||||||
insert into public.calendar_event_categories (name) values ('science');
|
insert into public.calendar_event_categories (name, color) values ('Science', 'indigo');
|
||||||
insert into public.calendar_event_categories (name) values ('bénédiction');
|
insert into public.calendar_event_categories (name, color) values ('Bénédiction', 'white');
|
||||||
insert into public.calendar_event_categories (name) values ('joueurs');
|
insert into public.calendar_event_categories (name, color) values ('Joueurs', 'white');
|
||||||
insert into public.calendar_event_categories (name) values ('découverte');
|
insert into public.calendar_event_categories (name, color) values ('Découverte', 'purple');
|
||||||
insert into public.calendar_event_categories (name) values ('exploration');
|
insert into public.calendar_event_categories (name, color) values ('Exploration', 'lime');
|
||||||
insert into public.calendar_event_categories (name) values ('construction');
|
insert into public.calendar_event_categories (name, color) values ('Construction', 'blue');
|
||||||
insert into public.calendar_event_categories (name) values ('arcanologie');
|
insert into public.calendar_event_categories (name, color) values ('Arcanologie', 'cyan');
|
||||||
insert into public.calendar_event_categories (name) values ('criminalité');
|
insert into public.calendar_event_categories (name, color) values ('Criminalité', 'rose');
|
||||||
insert into public.calendar_event_categories (name) values ('scandale');
|
insert into public.calendar_event_categories (name, color) values ('Scandale', 'pink');
|
||||||
insert into public.calendar_event_categories (name) values ('commerce');
|
insert into public.calendar_event_categories (name, color) values ('Commerce', 'amber');
|
||||||
insert into public.calendar_event_categories (name) values ('législation');
|
insert into public.calendar_event_categories (name, color) values ('Législation', 'blue');
|
||||||
|
|
||||||
-- Character categories
|
-- Character categories
|
||||||
insert into public.character_categories (name) values ('joueur');
|
insert into public.character_categories (name, color) values ('Joueur', 'white');
|
||||||
insert into public.character_categories (name) values ('comte');
|
insert into public.character_categories (name, color) values ('Comte', 'emerald');
|
||||||
insert into public.character_categories (name) values ('scientifique');
|
insert into public.character_categories (name, color) values ('Scientifique', 'indigo');
|
||||||
insert into public.character_categories (name) values ('mage');
|
insert into public.character_categories (name, color) values ('Mage', 'cyan');
|
||||||
insert into public.character_categories (name) values ('professeur');
|
insert into public.character_categories (name, color) values ('Professeur', 'teal');
|
||||||
insert into public.character_categories (name) values ('criminel');
|
insert into public.character_categories (name, color) values ('Criminel', 'rose');
|
||||||
insert into public.character_categories (name) values ('étincelle');
|
insert into public.character_categories (name, color) values ('Étincelle', 'lime');
|
||||||
insert into public.character_categories (name) values ('buse blanche');
|
insert into public.character_categories (name, color) values ('Buse blanche', 'yellow');
|
||||||
insert into public.character_categories (name) values ('ecclésiastique');
|
insert into public.character_categories (name, color) values ('Ecclésiastique', 'violet');
|
||||||
insert into public.character_categories (name) values ('militaire');
|
insert into public.character_categories (name, color) values ('Militaire', 'orange');
|
||||||
insert into public.character_categories (name) values ('activiste');
|
insert into public.character_categories (name, color) values ('Activiste', 'sky');
|
||||||
insert into public.character_categories (name) values ('commerçant');
|
insert into public.character_categories (name, color) values ('Commerçant', 'amber');
|
||||||
|
|
||||||
-- Worlds
|
-- Worlds
|
||||||
insert into public.worlds (name, description, color) values ('Léïm', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis aliquet congue aliquet. Curabitur eu iaculis diam. Nunc iaculis nibh orci, eu semper nunc congue congue. Praesent euismod tortor eget metus tristique lobortis vel in risus. In volutpat ligula orci, id pharetra lectus egestas at.', 'black');
|
insert into public.worlds (name, description, color) values ('Léïm', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis aliquet congue aliquet. Curabitur eu iaculis diam. Nunc iaculis nibh orci, eu semper nunc congue congue. Praesent euismod tortor eget metus tristique lobortis vel in risus. In volutpat ligula orci, id pharetra lectus egestas at.', 'black');
|
||||||
@@ -239,7 +239,7 @@ insert into public.calendar_events (title, description, location, start_date, en
|
|||||||
1
|
1
|
||||||
);
|
);
|
||||||
insert into public.calendar_events (title, description, location, start_date, end_date, category, hidden, wiki, calendar_id) values (
|
insert into public.calendar_events (title, description, location, start_date, end_date, category, hidden, wiki, calendar_id) values (
|
||||||
'1ère disparation',
|
'1ère disparition',
|
||||||
'Taleb Vaht décède dans une grotte à la suite d''une attaque d''ischiels enragées.',
|
'Taleb Vaht décède dans une grotte à la suite d''une attaque d''ischiels enragées.',
|
||||||
'Cantane',
|
'Cantane',
|
||||||
'{ "day": 28, "month": 7, "year": 3209 }',
|
'{ "day": 28, "month": 7, "year": 3209 }',
|
||||||
@@ -250,7 +250,7 @@ insert into public.calendar_events (title, description, location, start_date, en
|
|||||||
1
|
1
|
||||||
);
|
);
|
||||||
insert into public.calendar_events (title, description, location, start_date, end_date, category, hidden, wiki, calendar_id) values (
|
insert into public.calendar_events (title, description, location, start_date, end_date, category, hidden, wiki, calendar_id) values (
|
||||||
'2ème disparation',
|
'2ème disparition',
|
||||||
'Donovane le mineur kéturien disparait sans laisser de traces.',
|
'Donovane le mineur kéturien disparait sans laisser de traces.',
|
||||||
'Cantane',
|
'Cantane',
|
||||||
'{ "day": 32, "month": 7, "year": 3209 }',
|
'{ "day": 32, "month": 7, "year": 3209 }',
|
||||||
@@ -261,7 +261,7 @@ insert into public.calendar_events (title, description, location, start_date, en
|
|||||||
1
|
1
|
||||||
);
|
);
|
||||||
insert into public.calendar_events (title, description, location, start_date, end_date, category, hidden, wiki, calendar_id) values (
|
insert into public.calendar_events (title, description, location, start_date, end_date, category, hidden, wiki, calendar_id) values (
|
||||||
'3ème disparation',
|
'3ème disparition',
|
||||||
'Disparition de Sébastien, gredin sauride.',
|
'Disparition de Sébastien, gredin sauride.',
|
||||||
'Cantane',
|
'Cantane',
|
||||||
'{ "day": 10, "month": 8, "year": 3209 }',
|
'{ "day": 10, "month": 8, "year": 3209 }',
|
||||||
@@ -272,7 +272,7 @@ insert into public.calendar_events (title, description, location, start_date, en
|
|||||||
1
|
1
|
||||||
);
|
);
|
||||||
insert into public.calendar_events (title, description, location, start_date, end_date, category, hidden, wiki, calendar_id) values (
|
insert into public.calendar_events (title, description, location, start_date, end_date, category, hidden, wiki, calendar_id) values (
|
||||||
'4ème disparation',
|
'4ème disparition',
|
||||||
'Disparition de Thérence, patrouilleur sauride de la Vieille Garde.',
|
'Disparition de Thérence, patrouilleur sauride de la Vieille Garde.',
|
||||||
'Cantane',
|
'Cantane',
|
||||||
'{ "day": 19, "month": 8, "year": 3209 }',
|
'{ "day": 19, "month": 8, "year": 3209 }',
|
||||||
@@ -283,7 +283,7 @@ insert into public.calendar_events (title, description, location, start_date, en
|
|||||||
1
|
1
|
||||||
);
|
);
|
||||||
insert into public.calendar_events (title, description, location, start_date, end_date, category, hidden, wiki, calendar_id) values (
|
insert into public.calendar_events (title, description, location, start_date, end_date, category, hidden, wiki, calendar_id) values (
|
||||||
'5ème disparation',
|
'5ème disparition',
|
||||||
'Disparition de Mathilda Boulais, vendeuse de pierres.',
|
'Disparition de Mathilda Boulais, vendeuse de pierres.',
|
||||||
'Cantane',
|
'Cantane',
|
||||||
'{ "day": 22, "month": 8, "year": 3209 }',
|
'{ "day": 22, "month": 8, "year": 3209 }',
|
||||||
|
|||||||
Reference in New Issue
Block a user