Changed ways to access calendars
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
import { useCalendar } from '@/stores/CalendarStore'
|
import { useCalendar } from '@/stores/CalendarStore'
|
||||||
import { computed, type Component, type ComputedRef } from 'vue'
|
import { computed, type Component, type ComputedRef } from 'vue'
|
||||||
|
|
||||||
import { PhMagnifyingGlass } from '@phosphor-icons/vue'
|
import { PhCircleNotch, PhMagnifyingGlass } from '@phosphor-icons/vue'
|
||||||
import MonthlyLayout from './state/monthly/Layout.vue'
|
import MonthlyLayout from './state/monthly/Layout.vue'
|
||||||
import CenturyLayout from './state/centennially/Layout.vue'
|
import CenturyLayout from './state/centennially/Layout.vue'
|
||||||
import DecadeLayout from './state/decennially/Layout.vue'
|
import DecadeLayout from './state/decennially/Layout.vue'
|
||||||
@@ -15,9 +15,11 @@ const { setCalendarId, setMonths, setDefaultDate, currentConfig, selectedDate, j
|
|||||||
const { setEvents, setCategories } = 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 { months } = storeToRefs(useCalendar())
|
||||||
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`)
|
const { data: calendar, pending: calPending, refresh: calRefresh } = useFetch(`/api/calendars/query?world_id=${worldId}`)
|
||||||
|
const { data: characters, pending: charPending, refresh: charRefresh } = useFetch(`/api/characters/query?world_id=${worldId}`)
|
||||||
|
const { data: categories, pending: categoryPending, refresh: categoryRefresh } = useFetch(`/api/calendars/categories/query`)
|
||||||
|
|
||||||
if (!calendar.value) {
|
if (!calendar.value) {
|
||||||
await calRefresh()
|
await calRefresh()
|
||||||
@@ -119,24 +121,44 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="h-full">
|
<div class="h-full w-full relative">
|
||||||
<template v-if="calPending || charPending || categoryPending">
|
<TransitionGroup name="screen">
|
||||||
<div class="h-full grid place-items-center">
|
<div v-if="calPending || charPending || categoryPending" class="h-full w-full grid place-items-center">
|
||||||
Loading notamment
|
<div class="flex flex-col items-center">
|
||||||
|
<PhCircleNotch size="42" class="animate-spin" />
|
||||||
|
<p class="text-lg mt-2">Chargement en cours…</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
<div v-else-if="months.length > 0" class="h-full grid grid-rows-[auto,1fr]">
|
||||||
<template v-else>
|
|
||||||
<div class="h-full grid grid-rows-[auto,1fr]">
|
|
||||||
<CalendarMenu />
|
<CalendarMenu />
|
||||||
|
|
||||||
<KeepAlive>
|
<KeepAlive>
|
||||||
<component :is="currentViewComponent"/>
|
<component :is="currentViewComponent"/>
|
||||||
</KeepAlive>
|
</KeepAlive>
|
||||||
</div>
|
|
||||||
|
|
||||||
<LazyCalendarSearch />
|
<LazyCalendarSearch />
|
||||||
<LazyCalendarFormUpdateEvent />
|
<LazyCalendarFormUpdateEvent />
|
||||||
<LazyCalendarFormDeleteEvent />
|
<LazyCalendarFormDeleteEvent />
|
||||||
</template>
|
</div>
|
||||||
|
</TransitionGroup>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.screen-move, /* apply transition to moving elements */
|
||||||
|
.screen-enter-active,
|
||||||
|
.screen-leave-active {
|
||||||
|
transition: all .4s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.screen-enter-from,
|
||||||
|
.screen-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ensure leaving items are taken out of layout flow so that moving
|
||||||
|
animations can be calculated correctly. */
|
||||||
|
.screen-leave-active {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
5
components/global/Spacing.vue
Normal file
5
components/global/Spacing.vue
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<template>
|
||||||
|
<div class="space-y-2">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -43,7 +43,7 @@ async function handleLogout() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function gotoProfilePage() {
|
function gotoProfilePage() {
|
||||||
router.push({ path: '/profile' })
|
router.push({ path: '/i' })
|
||||||
|
|
||||||
closeMenu()
|
closeMenu()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
|
import type { Calendar } from "./CalendarConfig"
|
||||||
|
|
||||||
export interface World {
|
export interface World {
|
||||||
id: number
|
id: number
|
||||||
uuid: string
|
uuid: string
|
||||||
name: string
|
name: string
|
||||||
description?: string
|
description?: string
|
||||||
color?: string
|
color?: string,
|
||||||
|
calendars?: Calendar[]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,44 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import type { World } from '~/models/World';
|
||||||
|
|
||||||
|
const { data: res } = await useFetch('/api/worlds/query')
|
||||||
|
|
||||||
|
const worlds = res.value?.data as World[]
|
||||||
|
|
||||||
|
useHead({
|
||||||
|
title: 'Profil'
|
||||||
|
})
|
||||||
|
definePageMeta({
|
||||||
|
middleware: ['auth-guard']
|
||||||
|
})
|
||||||
|
|
||||||
const user = useSupabaseUser()
|
const user = useSupabaseUser()
|
||||||
|
|
||||||
const { data: worlds } = await useLazyFetch('/api/worlds')
|
// Redirect user back home when they log out on the page
|
||||||
|
watch(user, (n, _o) => {
|
||||||
|
if (!n) {
|
||||||
|
navigateTo('/')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const { setCurrentMenu } = useUiStore()
|
||||||
|
setCurrentMenu([])
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<main class="p-8">
|
<main class="p-8">
|
||||||
<Heading>{{ user?.user_metadata.full_name }}</Heading>
|
<Heading>{{ user?.user_metadata.full_name }}</Heading>
|
||||||
|
|
||||||
<section v-if="worlds?.data" class="mt-4">
|
<section v-if="worlds" class="mt-4">
|
||||||
<h2 class="mb-4 text-lg font-bold">
|
<h2 class="mb-4 text-lg font-bold">
|
||||||
Mondes
|
Mondes
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<ul class="grid md:grid-cols-3 gap-2">
|
<ul class="grid md:grid-cols-3 gap-2">
|
||||||
<li v-for="(world, i) in worlds.data" :key="i">
|
<li v-for="world in worlds" :key="world.id">
|
||||||
<UiCard
|
<UiCard
|
||||||
class="w-full transition-all"
|
class="w-full transition-all"
|
||||||
:link="`/calendar/${world.id}`"
|
:link="`/i/world/${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,
|
||||||
'bg-red-100 dark:bg-red-950 border-red-200 hover:bg-red-50 dark:hover:bg-red-900 dark:border-red-900 dark:focus-within:outline-red-900': world.color === 'red',
|
'bg-red-100 dark:bg-red-950 border-red-200 hover:bg-red-50 dark:hover:bg-red-900 dark:border-red-900 dark:focus-within:outline-red-900': world.color === 'red',
|
||||||
64
pages/i/world/[id]/index.vue
Normal file
64
pages/i/world/[id]/index.vue
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import type { World } from '~/models/World';
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const id = route.params.id
|
||||||
|
|
||||||
|
const { data: res, pending } = await useFetch(`/api/worlds/query`, { query: { id, full: true } })
|
||||||
|
|
||||||
|
const world = res.value?.data as World
|
||||||
|
|
||||||
|
useHead({
|
||||||
|
title: 'Profil'
|
||||||
|
})
|
||||||
|
definePageMeta({
|
||||||
|
middleware: ['auth-guard']
|
||||||
|
})
|
||||||
|
|
||||||
|
const user = useSupabaseUser()
|
||||||
|
|
||||||
|
// Redirect user back home when they log out on the page
|
||||||
|
watch(user, (n, _o) => {
|
||||||
|
if (!n) {
|
||||||
|
navigateTo('/')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const { setCurrentMenu } = useUiStore()
|
||||||
|
setCurrentMenu([])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<main class="p-8">
|
||||||
|
<template v-if="pending">
|
||||||
|
<Heading>Chargement...</Heading>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="world">
|
||||||
|
<header class="lg:w-1/2 mb-8">
|
||||||
|
<Spacing>
|
||||||
|
<Heading>{{ world.name }}</Heading>
|
||||||
|
|
||||||
|
<p>{{ world.description }}</p>
|
||||||
|
</Spacing>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<ul v-if="world.calendars && world.calendars?.length > 0" class="grid md:grid-cols-3 gap-2">
|
||||||
|
<li v-for="calendar in world.calendars" :key="calendar.id">
|
||||||
|
<UiCard
|
||||||
|
v-if="calendar"
|
||||||
|
class="w-full transition-all"
|
||||||
|
:link="`/i/world/${world.id}/calendar`"
|
||||||
|
>
|
||||||
|
<UiCardHeader>
|
||||||
|
<UiCardTitle>{{ calendar.name }}</UiCardTitle>
|
||||||
|
|
||||||
|
<UiCardContent>
|
||||||
|
<p class="italic">{{ calendar.events }}</p>
|
||||||
|
</UiCardContent>
|
||||||
|
</UiCardHeader>
|
||||||
|
</UiCard>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
</main>
|
||||||
|
</template>
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
const user = useSupabaseUser()
|
|
||||||
|
|
||||||
useHead({
|
|
||||||
title: 'Profil'
|
|
||||||
})
|
|
||||||
|
|
||||||
definePageMeta({
|
|
||||||
middleware: ['auth-guard']
|
|
||||||
})
|
|
||||||
|
|
||||||
// Redirect user back home when they log out on the page
|
|
||||||
watch(user, (n, _o) => {
|
|
||||||
if (!n) {
|
|
||||||
navigateTo('/')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const { setCurrentMenu } = useUiStore()
|
|
||||||
setCurrentMenu([])
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<ProfileDashboard />
|
|
||||||
</template>
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { serverSupabaseClient } from "#supabase/server";
|
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
import { serverSupabaseClient } from "#supabase/server";
|
||||||
import type { Character } from "~/models/Characters";
|
import type { Character } from "~/models/Characters";
|
||||||
|
|
||||||
const querySchema = z.object({
|
const querySchema = z.object({
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
import { serverSupabaseClient } from "#supabase/server";
|
|
||||||
import type { World } from "~/models/World";
|
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
|
||||||
const client = await serverSupabaseClient(event)
|
|
||||||
|
|
||||||
return client.from('worlds')
|
|
||||||
.select(`id, name, description, color`)
|
|
||||||
.returns<World[]>()
|
|
||||||
})
|
|
||||||
30
server/api/worlds/query.get.ts
Normal file
30
server/api/worlds/query.get.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { z } from 'zod'
|
||||||
|
import { serverSupabaseClient } from "#supabase/server";
|
||||||
|
import type { World } from "~/models/World";
|
||||||
|
|
||||||
|
const querySchema = z.object({
|
||||||
|
id: z.number({ coerce: true }).positive().int().optional(),
|
||||||
|
full: z.boolean({ coerce: true }).optional()
|
||||||
|
})
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
const client = await serverSupabaseClient(event)
|
||||||
|
const query = await getValidatedQuery(event, querySchema.parse)
|
||||||
|
|
||||||
|
const fullFields = `id, name, description, color, calendars (id, name, color, today)`
|
||||||
|
const partialFields = `id, name, description, color`
|
||||||
|
|
||||||
|
let output
|
||||||
|
|
||||||
|
if (query.full) {
|
||||||
|
output = client.from('worlds').select(fullFields)
|
||||||
|
} else {
|
||||||
|
output = client.from('worlds').select(partialFields)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query.id) {
|
||||||
|
return output.eq('id', query.id).single<World>()
|
||||||
|
}
|
||||||
|
|
||||||
|
return output.returns<World[]>()
|
||||||
|
})
|
||||||
@@ -22,6 +22,9 @@ type CalendarCurrentDate = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const useCalendar = defineStore('calendar', () => {
|
export const useCalendar = defineStore('calendar', () => {
|
||||||
|
const route = useRoute()
|
||||||
|
const isCalendarView: boolean = route.name === 'i-world-id-calendar'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static calendar config
|
* Static calendar config
|
||||||
* This shouldn't change
|
* This shouldn't change
|
||||||
@@ -70,14 +73,22 @@ export const useCalendar = defineStore('calendar', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Get date from URL params
|
// Set initial value for url search params
|
||||||
const params = useUrlSearchParams('history', {
|
// The route needs to be check because it should proc the params on anything BUT the calendar route
|
||||||
write: false,
|
let initialParams: { day?: string, month?: string, year?: string } = {}
|
||||||
initialValue: {
|
|
||||||
|
if (isCalendarView) {
|
||||||
|
initialParams = {
|
||||||
day: defaultDate.value.day.toString(),
|
day: defaultDate.value.day.toString(),
|
||||||
month: defaultDate.value.month.toString(),
|
month: defaultDate.value.month.toString(),
|
||||||
year: defaultDate.value.year.toString()
|
year: defaultDate.value.year.toString()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get date from URL params
|
||||||
|
const params = useUrlSearchParams('history', {
|
||||||
|
write: false,
|
||||||
|
initialValue: initialParams,
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -157,6 +168,13 @@ export const useCalendar = defineStore('calendar', () => {
|
|||||||
|
|
||||||
const selectedDate = useLocalStorage<RPGDate>('selected-date', currentRPGDate.value, { deep: true })
|
const selectedDate = useLocalStorage<RPGDate>('selected-date', currentRPGDate.value, { deep: true })
|
||||||
|
|
||||||
|
// Same check as above, for selectedDate history
|
||||||
|
if (isCalendarView) {
|
||||||
|
params.day = selectedDate.value.day.toString()
|
||||||
|
params.month = selectedDate.value.month.toString()
|
||||||
|
params.year = selectedDate.value.year.toString()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether the current viewType is active
|
* Check whether the current viewType is active
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user