Files
leim-tools/stores/CalendarStore.ts
Alexis 67f5a270af Huge refactor for backend and client
This is barely functionnal, but at least it can display some data without crashing
Most other functionnalities other than displaying events are broken, and so are the relative date operations, they need to be fixed asap
2024-05-16 22:58:19 +02:00

365 lines
8.5 KiB
TypeScript

import {
type RPGDate,
} from '@/models/Date'
import { useLocalStorage, useUrlSearchParams } from '@vueuse/core'
import { defineStore, skipHydrate } from 'pinia'
import { computed, ref, type ComputedRef, type Ref } from 'vue'
import type { CalendarMonth } from '~/models/CalendarMonth'
type CalendarViewType = 'month' | 'year' | 'decade' | 'century'
type CalendarCurrentConfig = {
viewType: CalendarViewType
}
type CalendarCurrentDate = {
currentDay: ComputedRef<number>
currentMonth: ComputedRef<number>
currentMonthName: ComputedRef<string>
currentYear: ComputedRef<number>
currentDateTitle: ComputedRef<string>
}
export const useCalendar = defineStore('calendar', () => {
/**
* Static calendar config
* This shouldn't change
*/
/**
* Month list
*/
const months: Ref<CalendarMonth[]> = ref<CalendarMonth[]>([])
const sortedMonths = computed<CalendarMonth[]>(() => months.value.sort((a, b) => a.position - b.position))
const monthsPerYear = computed(() => months.value.length)
const daysPerYear = computed(() => months.value.reduce((acc, o) => acc + o.days, 0))
const currentConfig: Ref<CalendarCurrentConfig> = ref({
viewType: 'month'
})
const viewTypeOptions: Set<CalendarViewType> = new Set<CalendarViewType>([
'month',
'year',
'decade',
'century'
])
// Default date settings (current day in the world)
const defaultDay: number = 23
const defaultMonth: number = 8
const defaultYear: number = 3209
const defaultDate: ComputedRef<RPGDate> = computed(() => {
return {
day: defaultDay,
month: defaultMonth,
year: defaultYear
}
})
// Get date from URL params
const params = useUrlSearchParams('history', {
write: false,
initialValue: {
day: defaultDate.value.day.toString(),
month: defaultDate.value.month.toString(),
year: defaultDate.value.year.toString()
}
})
const currentDay = computed<number>(() => {
return Number(params.day)
})
const currentMonth = computed<number>(() => {
return Number(params.month)
})
const currentMonthData = computed<CalendarMonth>(() => {
return sortedMonths.value[currentMonth.value]
})
// Gets the label from currentMonth index
const currentMonthName = computed<string>(() => getMonthName(currentMonth.value))
const currentYear = computed<number>(() => {
return Number(params.year)
})
const currentDateTitle = computed<string>(() => {
switch (currentConfig.value.viewType) {
case 'month':
return getFormattedDateTitle({
day: currentDate.currentDay.value,
month: currentDate.currentMonth.value,
year: currentDate.currentYear.value,
})
case 'year':
return `Année ${currentYear.value}`
case 'decade':
return `Années ${currentYear.value} - ${currentYear.value + 10}`
case 'century':
return `Années ${currentYear.value} - ${currentYear.value + 100}`
default:
return 'Date inconnue'
}
})
// Create base config
const currentDate: CalendarCurrentDate = {
currentDay,
currentMonth,
currentMonthName,
currentYear,
currentDateTitle
}
const currentRPGDate = computed<RPGDate>(() => {
return {
day: currentDate.currentDay.value,
month: currentDate.currentMonth.value,
year: currentDate.currentYear.value,
}
})
const selectedDate = useLocalStorage<RPGDate>('selected-date', currentRPGDate.value, { deep: true })
/**
* Check whether the current viewType is active
*/
const isCurrentScreenActive = computed<boolean>(() => {
switch (currentConfig.value.viewType) {
case 'month':
return (
defaultDate.value.month === currentDate.currentMonth.value &&
defaultDate.value.year === currentDate.currentYear.value
)
case 'year':
case 'decade':
case 'century':
return defaultDate.value.year === currentDate.currentYear.value
default:
return false
}
})
/**
* Moves the current date forward one month
*/
function incrementMonth(): void {
let newValue = Number(params.month) + 1
// If the new value would exceed the max number of month per year
if (newValue >= monthsPerYear.value) {
newValue = 0
// Increment the year
incrementYear()
}
params.month = newValue.toString()
}
/**
* Moves the current date backward one month
*/
function decrementMonth(): void {
let newValue = Number(params.month) - 1
// If the new value would go below 0
if (newValue < 0) {
newValue = monthsPerYear.value - 1
// Decrement the year
decrementYear()
}
params.month = newValue.toString()
}
/**
* Get the previous month number
*
* @param monthNumber Initial month
* @returns The previous month number in the year
*/
function getPreviousMonth(monthNumber: number): number {
const target: number = monthNumber - 1
if (target < 0) {
return monthsPerYear.value - 1
}
return target
}
/**
* Get the following month number
*
* @param monthNumber Initial month
* @returns The next month number in the year
*/
function getNextMonth(monthNumber: number): number {
const target: number = monthNumber + 1
if (target + 1 >= monthsPerYear.value) {
return 0
}
return target
}
/**
* Moves the current date to a particular month
*/
function setMonth(target: number): void {
// If the target is outside the month bounds
if (target < 0 || target >= monthsPerYear.value) {
return
}
params.month = target.toString()
}
/**
* Moves the current date forward one year
*/
function incrementYear(inc: number = 1): void {
const newValue = Number(params.year) + inc
params.year = newValue.toString()
}
/**
* Moves the current date backward one year
*/
function decrementYear(inc: number = 1): void {
const newValue = Number(params.year) - inc
params.year = newValue.toString()
}
/**
* Get the formatted month name given its index
*
* @param monthNumber Index of the month
* @returns Formatted month name
*/
function getMonthName(monthNumber: number): string {
const index = Number(monthNumber)
return sortedMonths.value[index].name
}
/**
* Switches the active viewType
*
* @param viewType Target viewType
*/
function setViewType(viewType: CalendarViewType): void {
currentConfig.value.viewType = viewType
}
/**
* Gets the formatted viewType title
*
* @param viewType Target viewType
* @returns Formatted mode title
*/
function getViewTypeTitle(viewType: CalendarViewType): string {
switch (viewType) {
case 'year':
return 'Année'
case 'decade':
return 'Décennie'
case 'century':
return 'Siècle'
case 'month':
default:
return 'Mois'
}
}
/**
* From a RPGDate, returns the legible date title
*
* @param date Date target
* @param showNumber Should the date show the day number
* @returns Formatted date name
*/
function getFormattedDateTitle(date: RPGDate, showNumber?: boolean): string {
if (showNumber) {
return `${date.day} ${getMonthName(date.month)} ${date.year}`
}
return `${getMonthName(date.month)} ${date.year}`
}
/**
* Jumps the calendar to the given date
*
* @param date Target date
*/
function jumpToDate(date: RPGDate): void {
params.day = date.day.toString()
params.month = date.month.toString()
params.year = date.year.toString()
selectDate(date)
}
/**
* Jump the calendar to the default date
*/
function jumpToDefaultDate(): void {
jumpToDate(defaultDate.value)
}
/**
* Jump the calendar to the default date
*/
function selectDate(date: RPGDate): void {
selectedDate.value = date
}
const isAdvancedSearchOpen: Ref<boolean> = ref<boolean>(false)
function revealAdvancedSearch() {
isAdvancedSearchOpen.value = true
}
return {
months,
sortedMonths,
daysPerYear,
monthsPerYear,
viewTypeOptions,
currentConfig,
currentDate,
currentRPGDate,
currentMonthData,
defaultDate,
selectedDate: skipHydrate(selectedDate),
selectDate,
params,
incrementMonth,
decrementMonth,
setMonth,
getPreviousMonth,
getNextMonth,
incrementYear,
decrementYear,
jumpToDate,
jumpToDefaultDate,
getFormattedDateTitle,
getMonthName,
setViewType,
getViewTypeTitle,
isCurrentScreenActive,
isAdvancedSearchOpen,
revealAdvancedSearch
}
})