Fixed hydration errors
Moved some code to client only (it makes sense given the localstorage stuff)
This commit is contained in:
@@ -10,7 +10,10 @@ import DecadeLayout from './state/decennially/Layout.vue'
|
||||
import YearLayout from './state/yearly/Layout.vue'
|
||||
|
||||
const { currentConfig } = useCalendar()
|
||||
const { eventsLoaded, eventsAreLoading } = storeToRefs(useCalendarEvents())
|
||||
const { selectedDate, jumpToDate } = useCalendar()
|
||||
|
||||
const { fetchEvents } = useCalendarEvents()
|
||||
fetchEvents()
|
||||
|
||||
const currentViewComponent: ComputedRef<Component> = computed<Component>(() => {
|
||||
switch (currentConfig.viewType) {
|
||||
@@ -28,19 +31,18 @@ const currentViewComponent: ComputedRef<Component> = computed<Component>(() => {
|
||||
return CenturyLayout
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
jumpToDate(selectedDate)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="h-full grid grid-rows-[auto,1fr]">
|
||||
<CalendarMenu />
|
||||
|
||||
<template v-if="eventsAreLoading">
|
||||
<div>
|
||||
Loading
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="eventsLoaded">
|
||||
<component :is="currentViewComponent" v-if="eventsLoaded" />
|
||||
</template>
|
||||
<KeepAlive>
|
||||
<component :is="currentViewComponent" />
|
||||
</KeepAlive>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import { getRelativeString } from '@/models/Date'
|
||||
import { useCalendar } from '@/stores/CalendarStore'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { computed } from 'vue'
|
||||
|
||||
@@ -15,10 +14,19 @@ const dateDifference = computed(() => getRelativeString(defaultDate, selectedDat
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ClientOnly>
|
||||
<h1 class="text-2xl font-bold flex items-center gap-1">
|
||||
<PhMapPin size="26" weight="bold" /> {{ mainDateTitle }}
|
||||
</h1>
|
||||
<h2 class="text-lg italic opacity-75">
|
||||
{{ dateDifference }}
|
||||
</h2>
|
||||
|
||||
<template #fallback>
|
||||
<div class="grid gap-1">
|
||||
<UiSkeleton class="h-8 w-64" />
|
||||
<UiSkeleton class="h-6 w-28" />
|
||||
</div>
|
||||
</template>
|
||||
</ClientOnly>
|
||||
</template>
|
||||
|
||||
@@ -60,8 +60,16 @@ function handleGotoPreviousEventPage(position: 'next' | 'prev' = 'next') {
|
||||
|
||||
<template>
|
||||
<div class="flex gap-2">
|
||||
<div class="w-40 px-4 py-2 border-slate-700 border-x-[1px] border-t-[1px] rounded-t-sm">
|
||||
<span class="text-sm">{{ currentDate.currentDateTitle }}</span>
|
||||
<div class="grid items-end w-40 px-4 py-2 border-slate-700 border-x-[1px] border-t-[1px] rounded-t-sm text-sm">
|
||||
<ClientOnly>
|
||||
<span>{{ currentDate.currentDateTitle }}</span>
|
||||
|
||||
<template #fallback>
|
||||
<span class="inline-block">
|
||||
<UiSkeleton class="h-[19px] w-full rounded-sm" />
|
||||
</span>
|
||||
</template>
|
||||
</ClientOnly>
|
||||
</div>
|
||||
<div class="border-slate-700 border-x-[1px] border-t-[1px] rounded-t-sm">
|
||||
<UiTooltipProvider :delay-duration="250">
|
||||
|
||||
@@ -5,21 +5,30 @@ import { computed } from 'vue'
|
||||
|
||||
import { areDatesIdentical } from '@/models/Date'
|
||||
|
||||
const { defaultDate, selectedDate } = storeToRefs(useCalendar())
|
||||
const { defaultDate } = useCalendar()
|
||||
const { selectedDate } = storeToRefs(useCalendar())
|
||||
const { jumpToDefaultDate, getFormattedDateTitle } = useCalendar()
|
||||
|
||||
const defaultDateFormatted: string = getFormattedDateTitle(defaultDate.value, true)
|
||||
const defaultDateFormatted: string = getFormattedDateTitle(defaultDate, true)
|
||||
|
||||
const isDefaultDate: ComputedRef<boolean> = computed<boolean>(() => areDatesIdentical(selectedDate.value, defaultDate.value))
|
||||
const isDefaultDate: ComputedRef<boolean> = computed<boolean>(() => areDatesIdentical(selectedDate.value, defaultDate))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UiTooltipProvider :delay-duration="250">
|
||||
<UiTooltip>
|
||||
<UiTooltipTrigger as-child>
|
||||
<ClientOnly>
|
||||
<UiButton size="sm" :disabled="isDefaultDate" @click="jumpToDefaultDate">
|
||||
Aujourd'hui
|
||||
</UiButton>
|
||||
|
||||
<template #fallback>
|
||||
<UiButton size="sm">
|
||||
Aujourd'hui
|
||||
</UiButton>
|
||||
</template>
|
||||
</ClientOnly>
|
||||
</UiTooltipTrigger>
|
||||
<UiTooltipContent>
|
||||
<p>{{ defaultDateFormatted }}</p>
|
||||
|
||||
@@ -201,7 +201,7 @@ whenever(keys.control_period, () => {
|
||||
const searchResultsRef = ref<HTMLElement | null>(null)
|
||||
const { y: searchResultsY } = useScroll(searchResultsRef)
|
||||
|
||||
watch(currentPage, () => {
|
||||
watch([currentPage, selectedEntity], () => {
|
||||
searchResultsY.value = 0
|
||||
})
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ const eventsNotDisplayed = computed(
|
||||
class="relative z-10 group block w-full text-center cursor-pointer"
|
||||
@click="selectDate(date)"
|
||||
>
|
||||
<ClientOnly>
|
||||
<span
|
||||
class="inline-flex w-8 h-8 aspect-square items-center justify-center rounded-full border-2 border-transparent font-bold transition-colors group-hover:border-slate-800"
|
||||
:class="{
|
||||
@@ -82,6 +83,7 @@ const eventsNotDisplayed = computed(
|
||||
>
|
||||
{{ date.day }}
|
||||
</span>
|
||||
</ClientOnly>
|
||||
</button>
|
||||
|
||||
<ul
|
||||
|
||||
14
components/ui/skeleton/Skeleton.vue
Normal file
14
components/ui/skeleton/Skeleton.vue
Normal file
@@ -0,0 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
interface SkeletonProps {
|
||||
class?: HTMLAttributes['class']
|
||||
}
|
||||
|
||||
const props = defineProps<SkeletonProps>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="cn('animate-pulse rounded-md bg-muted', props.class)" />
|
||||
</template>
|
||||
1
components/ui/skeleton/index.ts
Normal file
1
components/ui/skeleton/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default as Skeleton } from './Skeleton.vue'
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
type LeimPeriod,
|
||||
type LeimPeriodShort
|
||||
} from '@/models/Date'
|
||||
import { useSessionStorage, useUrlSearchParams } from '@vueuse/core'
|
||||
import { defineStore } from 'pinia'
|
||||
import { useLocalStorage, useUrlSearchParams } from '@vueuse/core'
|
||||
import { defineStore, skipHydrate } from 'pinia'
|
||||
import { computed, ref, type ComputedRef, type Ref } from 'vue'
|
||||
|
||||
type CalendarViewType = 'month' | 'year' | 'decade' | 'century'
|
||||
@@ -161,7 +161,7 @@ export const useCalendar = defineStore('calendar', () => {
|
||||
}
|
||||
})
|
||||
|
||||
const selectedDate = useSessionStorage<LeimDate>('selected-date', currentLeimDate.value, { deep: true })
|
||||
const selectedDate = useLocalStorage<LeimDate>('selected-date', currentLeimDate.value, { deep: true })
|
||||
|
||||
/**
|
||||
* Check whether the current viewType is active
|
||||
@@ -393,7 +393,7 @@ export const useCalendar = defineStore('calendar', () => {
|
||||
currentDate,
|
||||
currentLeimDate,
|
||||
defaultDate,
|
||||
selectedDate,
|
||||
selectedDate: skipHydrate(selectedDate),
|
||||
selectDate,
|
||||
params,
|
||||
getPeriodOfYear,
|
||||
|
||||
@@ -38,7 +38,6 @@ export const useCalendarEvents = defineStore('calendar-events', () => {
|
||||
eventsAreLoading.value = false
|
||||
}
|
||||
}
|
||||
fetchEvents()
|
||||
|
||||
/**
|
||||
* Determines if the event can appear in the front end
|
||||
|
||||
Reference in New Issue
Block a user