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'
|
import YearLayout from './state/yearly/Layout.vue'
|
||||||
|
|
||||||
const { currentConfig } = useCalendar()
|
const { currentConfig } = useCalendar()
|
||||||
const { eventsLoaded, eventsAreLoading } = storeToRefs(useCalendarEvents())
|
const { selectedDate, jumpToDate } = useCalendar()
|
||||||
|
|
||||||
|
const { fetchEvents } = useCalendarEvents()
|
||||||
|
fetchEvents()
|
||||||
|
|
||||||
const currentViewComponent: ComputedRef<Component> = computed<Component>(() => {
|
const currentViewComponent: ComputedRef<Component> = computed<Component>(() => {
|
||||||
switch (currentConfig.viewType) {
|
switch (currentConfig.viewType) {
|
||||||
@@ -28,19 +31,18 @@ const currentViewComponent: ComputedRef<Component> = computed<Component>(() => {
|
|||||||
return CenturyLayout
|
return CenturyLayout
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
jumpToDate(selectedDate)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="h-full grid grid-rows-[auto,1fr]">
|
<div class="h-full grid grid-rows-[auto,1fr]">
|
||||||
<CalendarMenu />
|
<CalendarMenu />
|
||||||
|
|
||||||
<template v-if="eventsAreLoading">
|
<KeepAlive>
|
||||||
<div>
|
<component :is="currentViewComponent" />
|
||||||
Loading
|
</KeepAlive>
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="eventsLoaded">
|
|
||||||
<component :is="currentViewComponent" v-if="eventsLoaded" />
|
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { getRelativeString } from '@/models/Date'
|
import { getRelativeString } from '@/models/Date'
|
||||||
import { useCalendar } from '@/stores/CalendarStore'
|
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
@@ -15,10 +14,19 @@ const dateDifference = computed(() => getRelativeString(defaultDate, selectedDat
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<h1 class="text-2xl font-bold flex items-center gap-1">
|
<ClientOnly>
|
||||||
<PhMapPin size="26" weight="bold" /> {{ mainDateTitle }}
|
<h1 class="text-2xl font-bold flex items-center gap-1">
|
||||||
</h1>
|
<PhMapPin size="26" weight="bold" /> {{ mainDateTitle }}
|
||||||
<h2 class="text-lg italic opacity-75">
|
</h1>
|
||||||
{{ dateDifference }}
|
<h2 class="text-lg italic opacity-75">
|
||||||
</h2>
|
{{ 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>
|
</template>
|
||||||
|
|||||||
@@ -60,8 +60,16 @@ function handleGotoPreviousEventPage(position: 'next' | 'prev' = 'next') {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex gap-2">
|
<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">
|
<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">
|
||||||
<span class="text-sm">{{ currentDate.currentDateTitle }}</span>
|
<ClientOnly>
|
||||||
|
<span>{{ currentDate.currentDateTitle }}</span>
|
||||||
|
|
||||||
|
<template #fallback>
|
||||||
|
<span class="inline-block">
|
||||||
|
<UiSkeleton class="h-[19px] w-full rounded-sm" />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</ClientOnly>
|
||||||
</div>
|
</div>
|
||||||
<div class="border-slate-700 border-x-[1px] border-t-[1px] rounded-t-sm">
|
<div class="border-slate-700 border-x-[1px] border-t-[1px] rounded-t-sm">
|
||||||
<UiTooltipProvider :delay-duration="250">
|
<UiTooltipProvider :delay-duration="250">
|
||||||
|
|||||||
@@ -5,21 +5,30 @@ import { computed } from 'vue'
|
|||||||
|
|
||||||
import { areDatesIdentical } from '@/models/Date'
|
import { areDatesIdentical } from '@/models/Date'
|
||||||
|
|
||||||
const { defaultDate, selectedDate } = storeToRefs(useCalendar())
|
const { defaultDate } = useCalendar()
|
||||||
|
const { selectedDate } = storeToRefs(useCalendar())
|
||||||
const { jumpToDefaultDate, getFormattedDateTitle } = 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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<UiTooltipProvider :delay-duration="250">
|
<UiTooltipProvider :delay-duration="250">
|
||||||
<UiTooltip>
|
<UiTooltip>
|
||||||
<UiTooltipTrigger as-child>
|
<UiTooltipTrigger as-child>
|
||||||
<UiButton size="sm" :disabled="isDefaultDate" @click="jumpToDefaultDate">
|
<ClientOnly>
|
||||||
Aujourd'hui
|
<UiButton size="sm" :disabled="isDefaultDate" @click="jumpToDefaultDate">
|
||||||
</UiButton>
|
Aujourd'hui
|
||||||
|
</UiButton>
|
||||||
|
|
||||||
|
<template #fallback>
|
||||||
|
<UiButton size="sm">
|
||||||
|
Aujourd'hui
|
||||||
|
</UiButton>
|
||||||
|
</template>
|
||||||
|
</ClientOnly>
|
||||||
</UiTooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<UiTooltipContent>
|
<UiTooltipContent>
|
||||||
<p>{{ defaultDateFormatted }}</p>
|
<p>{{ defaultDateFormatted }}</p>
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ whenever(keys.control_period, () => {
|
|||||||
const searchResultsRef = ref<HTMLElement | null>(null)
|
const searchResultsRef = ref<HTMLElement | null>(null)
|
||||||
const { y: searchResultsY } = useScroll(searchResultsRef)
|
const { y: searchResultsY } = useScroll(searchResultsRef)
|
||||||
|
|
||||||
watch(currentPage, () => {
|
watch([currentPage, selectedEntity], () => {
|
||||||
searchResultsY.value = 0
|
searchResultsY.value = 0
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -73,15 +73,17 @@ const eventsNotDisplayed = computed(
|
|||||||
class="relative z-10 group block w-full text-center cursor-pointer"
|
class="relative z-10 group block w-full text-center cursor-pointer"
|
||||||
@click="selectDate(date)"
|
@click="selectDate(date)"
|
||||||
>
|
>
|
||||||
<span
|
<ClientOnly>
|
||||||
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"
|
<span
|
||||||
:class="{
|
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"
|
||||||
'bg-slate-800': isDefaultDate && !isSelectedDate,
|
:class="{
|
||||||
'text-white bg-blue-500': isSelectedDate
|
'bg-slate-800': isDefaultDate && !isSelectedDate,
|
||||||
}"
|
'text-white bg-blue-500': isSelectedDate
|
||||||
>
|
}"
|
||||||
{{ date.day }}
|
>
|
||||||
</span>
|
{{ date.day }}
|
||||||
|
</span>
|
||||||
|
</ClientOnly>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<ul
|
<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 LeimPeriod,
|
||||||
type LeimPeriodShort
|
type LeimPeriodShort
|
||||||
} from '@/models/Date'
|
} from '@/models/Date'
|
||||||
import { useSessionStorage, useUrlSearchParams } from '@vueuse/core'
|
import { useLocalStorage, useUrlSearchParams } from '@vueuse/core'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore, skipHydrate } from 'pinia'
|
||||||
import { computed, ref, type ComputedRef, type Ref } from 'vue'
|
import { computed, ref, type ComputedRef, type Ref } from 'vue'
|
||||||
|
|
||||||
type CalendarViewType = 'month' | 'year' | 'decade' | 'century'
|
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
|
* Check whether the current viewType is active
|
||||||
@@ -393,7 +393,7 @@ export const useCalendar = defineStore('calendar', () => {
|
|||||||
currentDate,
|
currentDate,
|
||||||
currentLeimDate,
|
currentLeimDate,
|
||||||
defaultDate,
|
defaultDate,
|
||||||
selectedDate,
|
selectedDate: skipHydrate(selectedDate),
|
||||||
selectDate,
|
selectDate,
|
||||||
params,
|
params,
|
||||||
getPeriodOfYear,
|
getPeriodOfYear,
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ export const useCalendarEvents = defineStore('calendar-events', () => {
|
|||||||
eventsAreLoading.value = false
|
eventsAreLoading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fetchEvents()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if the event can appear in the front end
|
* Determines if the event can appear in the front end
|
||||||
|
|||||||
Reference in New Issue
Block a user