First draft of function that handles seeing previous / next events
This commit is contained in:
@@ -1,11 +1,11 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { areDatesIdentical, type LeimDate } from '@/models/Date'
|
||||||
|
|
||||||
import { Popover, PopoverTrigger } from '@/components/ui/popover'
|
import { Popover, PopoverTrigger } from '@/components/ui/popover'
|
||||||
import type { CalendarEvent } from '@/models/Events'
|
import type { CalendarEvent } from '@/models/Events'
|
||||||
|
|
||||||
import CalendarEventDetails from './CalendarEventDetails.vue'
|
import CalendarEventDetails from './CalendarEventDetails.vue'
|
||||||
import { areDatesIdentical, type LeimDate } from '@/models/Date'
|
|
||||||
import { ref } from 'vue'
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
event: CalendarEvent
|
event: CalendarEvent
|
||||||
|
|||||||
@@ -2,12 +2,21 @@
|
|||||||
import { getRelativeString, type LeimDate } from '@/models/Date'
|
import { getRelativeString, type LeimDate } from '@/models/Date'
|
||||||
import type { CalendarEvent } from '@/models/Events'
|
import type { CalendarEvent } from '@/models/Events'
|
||||||
import { useCalendar } from '@/stores/CalendarStore'
|
import { useCalendar } from '@/stores/CalendarStore'
|
||||||
|
import { useCalendarEvents } from '@/stores/EventStore'
|
||||||
|
|
||||||
import { PhHourglassMedium, PhAlarm, PhHourglassHigh, PhHourglassLow } from '@phosphor-icons/vue'
|
import {
|
||||||
|
PhHourglassMedium,
|
||||||
|
PhAlarm,
|
||||||
|
PhHourglassHigh,
|
||||||
|
PhHourglassLow,
|
||||||
|
PhArrowBendDoubleUpLeft,
|
||||||
|
PhArrowBendDoubleUpRight
|
||||||
|
} from '@phosphor-icons/vue'
|
||||||
import { Badge } from '@/components/ui/badge'
|
import { Badge } from '@/components/ui/badge'
|
||||||
import { PopoverContent } from '@/components/ui/popover'
|
import { PopoverContent } from '@/components/ui/popover'
|
||||||
|
|
||||||
const { defaultDate, getFormattedDateTitle, jumpToDate } = useCalendar()
|
const { defaultDate, getFormattedDateTitle, jumpToDate } = useCalendar()
|
||||||
|
const { getRelativeEvent } = useCalendarEvents()
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
event: CalendarEvent
|
event: CalendarEvent
|
||||||
@@ -16,7 +25,9 @@ const props = defineProps<{
|
|||||||
isEndEvent?: boolean
|
isEndEvent?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits(['query:close-popover'])
|
const emit = defineEmits<{
|
||||||
|
(e: 'query:close-popover'): void
|
||||||
|
}>()
|
||||||
|
|
||||||
const dateDifference: string = getRelativeString(defaultDate, props.event.startDate)
|
const dateDifference: string = getRelativeString(defaultDate, props.event.startDate)
|
||||||
const dateDuration: string | null = props.event.endDate
|
const dateDuration: string | null = props.event.endDate
|
||||||
@@ -27,6 +38,16 @@ function handleJumpToDate(date: LeimDate) {
|
|||||||
jumpToDate(date)
|
jumpToDate(date)
|
||||||
emit('query:close-popover')
|
emit('query:close-popover')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleGotoRelativeEvent(position: 'next' | 'prev' = 'next') {
|
||||||
|
try {
|
||||||
|
const { targetDate } = getRelativeEvent(props.event, position, props.isEndEvent)
|
||||||
|
|
||||||
|
handleJumpToDate(targetDate)
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -123,11 +144,36 @@ function handleJumpToDate(date: LeimDate) {
|
|||||||
</button>
|
</button>
|
||||||
</Badge>
|
</Badge>
|
||||||
<Badge class="hover:opacity-100 hover:bg-slate-300" as-child title="Naviguer à la fin">
|
<Badge class="hover:opacity-100 hover:bg-slate-300" as-child title="Naviguer à la fin">
|
||||||
<button class="flex gap-1" @click="handleJumpToDate(event.endDate!)">
|
<button
|
||||||
|
class="flex gap-1"
|
||||||
|
@click="handleJumpToDate(event.endDate!)"
|
||||||
|
title="Naviguer à la fin"
|
||||||
|
>
|
||||||
<PhHourglassLow size="16" weight="fill" /> Fin
|
<PhHourglassLow size="16" weight="fill" /> Fin
|
||||||
</button>
|
</button>
|
||||||
</Badge>
|
</Badge>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
<nav class="mt-2 flex gap-2">
|
||||||
|
<Badge class="hover:opacity-100 hover:bg-slate-300" as-child>
|
||||||
|
<button
|
||||||
|
class="flex gap-1"
|
||||||
|
@click="handleGotoRelativeEvent('prev')"
|
||||||
|
title="Évènement précédent"
|
||||||
|
>
|
||||||
|
<PhArrowBendDoubleUpLeft size="16" weight="fill" /> Précédent
|
||||||
|
</button>
|
||||||
|
</Badge>
|
||||||
|
<Badge class="hover:opacity-100 hover:bg-slate-300" as-child title="Naviguer à la fin">
|
||||||
|
<button
|
||||||
|
class="flex gap-1"
|
||||||
|
@click="handleGotoRelativeEvent('next')"
|
||||||
|
title="Évènement suivant"
|
||||||
|
>
|
||||||
|
<PhArrowBendDoubleUpRight size="16" weight="fill" /> Suivant
|
||||||
|
</button>
|
||||||
|
</Badge>
|
||||||
|
</nav>
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { computed, type ComputedRef } from 'vue'
|
||||||
import { useCalendar } from '@/stores/CalendarStore'
|
import { useCalendar } from '@/stores/CalendarStore'
|
||||||
|
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
||||||
@@ -9,7 +10,6 @@ import {
|
|||||||
PhCaretRight
|
PhCaretRight
|
||||||
} from '@phosphor-icons/vue'
|
} from '@phosphor-icons/vue'
|
||||||
import Button from '../ui/button/Button.vue'
|
import Button from '../ui/button/Button.vue'
|
||||||
import { computed, type ComputedRef } from 'vue'
|
|
||||||
|
|
||||||
interface DirectionLabels {
|
interface DirectionLabels {
|
||||||
pastFar: string
|
pastFar: string
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { initialEvents } from '@/data/Events'
|
import { initialEvents } from '@/data/Events'
|
||||||
import { compareDates, convertDateToDays, daysPerMonth } from '@/models/Date'
|
import { compareDates, convertDateToDays, daysPerMonth, type LeimDate } from '@/models/Date'
|
||||||
import type { CalendarEvent } from '@/models/Events'
|
import type { CalendarEvent } from '@/models/Events'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { ref, watch, type Ref } from 'vue'
|
import { ref, watch, type Ref } from 'vue'
|
||||||
@@ -108,5 +108,97 @@ export const useCalendarEvents = defineStore('calendar-events', () => {
|
|||||||
return allEvents.filter((event) => shouldEventBeDisplayed(event))
|
return allEvents.filter((event) => shouldEventBeDisplayed(event))
|
||||||
}
|
}
|
||||||
|
|
||||||
return { allEvents, currentEvents }
|
/**
|
||||||
|
* From a base event, gets the next or previous in the timeline
|
||||||
|
* @todo **This should probably be extracted to function FIRST with dates only, as the initialIsEnd param is only used at the beggining to establish a pivot**
|
||||||
|
*
|
||||||
|
* @param event The event at a given position in the data
|
||||||
|
* @param position Whether we should get the next or previous event
|
||||||
|
* @returns The next event in chronological order
|
||||||
|
*/
|
||||||
|
function getRelativeEvent(
|
||||||
|
event: CalendarEvent,
|
||||||
|
position: 'next' | 'prev' = 'next',
|
||||||
|
initialIsEnd: boolean = false
|
||||||
|
): { event: CalendarEvent; targetDate: LeimDate } {
|
||||||
|
let eventPivotValue: number // Day value of the date that the user interacted with
|
||||||
|
|
||||||
|
if (initialIsEnd && event.endDate) {
|
||||||
|
eventPivotValue = convertDateToDays(event.endDate)
|
||||||
|
} else {
|
||||||
|
eventPivotValue = convertDateToDays(event.startDate)
|
||||||
|
}
|
||||||
|
|
||||||
|
const t: { eventData: CalendarEvent; distance: number; targetKey: 'startDate' | 'endDate' }[] =
|
||||||
|
[]
|
||||||
|
let eventPivotIndex: number | null = null // Pivot index to save
|
||||||
|
let realPositon: number = 0
|
||||||
|
|
||||||
|
// Loop over all event once to convert the structure to a usable one
|
||||||
|
for (let i = 0; i < allEvents.length; i++) {
|
||||||
|
const e: CalendarEvent = allEvents[i]
|
||||||
|
// Estimate distance from pivot
|
||||||
|
const startDateDays: number = convertDateToDays(e.startDate)
|
||||||
|
const startDistance: number = startDateDays - eventPivotValue
|
||||||
|
|
||||||
|
// Push startDate to comparator array
|
||||||
|
t.push({
|
||||||
|
eventData: e,
|
||||||
|
distance: startDistance,
|
||||||
|
targetKey: 'startDate'
|
||||||
|
})
|
||||||
|
|
||||||
|
// If the distance from initial pivot is 0, this is our target index
|
||||||
|
if (startDistance === 0) {
|
||||||
|
eventPivotIndex = realPositon
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the same things for endDate
|
||||||
|
if (e.endDate) {
|
||||||
|
realPositon++
|
||||||
|
const endDateDays: number = convertDateToDays(e.endDate)
|
||||||
|
const endDistance: number = endDateDays - eventPivotValue
|
||||||
|
|
||||||
|
// Push optional endDate to comparator array
|
||||||
|
t.push({
|
||||||
|
eventData: e,
|
||||||
|
distance: endDistance,
|
||||||
|
targetKey: 'endDate'
|
||||||
|
})
|
||||||
|
|
||||||
|
// Same as above, but with the optional end distance
|
||||||
|
if (endDistance === 0) {
|
||||||
|
eventPivotIndex = realPositon
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
realPositon++
|
||||||
|
|
||||||
|
// Optimization possible with index skipping (once we find the pivot index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If SOMEHOW we can't find the pivot index
|
||||||
|
if (eventPivotIndex === null) {
|
||||||
|
throw new Error("Impossible de trouver l'évènement initial.")
|
||||||
|
}
|
||||||
|
|
||||||
|
let returnEventIndex: number | null = null // Output event index
|
||||||
|
if (position === 'next') {
|
||||||
|
returnEventIndex = eventPivotIndex + 1
|
||||||
|
} else {
|
||||||
|
returnEventIndex = eventPivotIndex - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!t[returnEventIndex])
|
||||||
|
throw new Error(
|
||||||
|
"Aucun évènement trouvé ; Peut-être l'évènement se situe au début ou à la fin du calendrier ?"
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
event: t[returnEventIndex].eventData,
|
||||||
|
targetDate: t[returnEventIndex].eventData[t[returnEventIndex].targetKey]!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { allEvents, currentEvents, getRelativeEvent }
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user