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
This commit is contained in:
Alexis
2024-05-16 22:58:19 +02:00
parent 49e523485b
commit 67f5a270af
28 changed files with 247 additions and 303 deletions

View File

@@ -2,8 +2,6 @@
import { useCalendar } from '@/stores/CalendarStore'
import { computed, type Component, type ComputedRef } from 'vue'
import CalendarMenu from './CalendarMenu.vue'
import MonthlyLayout from './state/monthly/Layout.vue'
import CenturyLayout from './state/centennially/Layout.vue'
import DecadeLayout from './state/decennially/Layout.vue'

View File

@@ -1,14 +1,14 @@
<script lang="ts" setup>
import { ref } from 'vue'
import { cn } from '@/lib/utils'
import { areDatesIdentical, type LeimDate } from '@/models/Date'
import { areDatesIdentical, type RPGDate } from '@/models/Date'
import type { CalendarEvent } from '@/models/Events'
import type { CalendarEvent } from '~/models/CalendarEvent'
import CalendarEventDetails from './CalendarEventDetails.vue'
const props = defineProps<{
event: CalendarEvent
tileDate: LeimDate
tileDate: RPGDate
}>()
const spansMultipleDays = Boolean(props.event.startDate && props.event.endDate)

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { getRelativeString, type LeimDate } from '@/models/Date'
import { getRelativeString, type RPGDate } from '@/models/Date'
import type { CalendarEvent } from '@/models/Events'
import { useCalendar } from '@/stores/CalendarStore'
import { useCalendarEvents } from '@/stores/EventStore'
@@ -32,7 +32,7 @@ const dateDuration: string | null = props.event.endDate
? getRelativeString(props.event.startDate, props.event.endDate, 'compact')
: null
function handleJumpToDate(date: LeimDate) {
function handleJumpToDate(date: RPGDate) {
jumpToDate(date)
emit('query:close-popover')
}

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { daysPerMonth, monthsPerYear, type LeimDate } from '@/models/Date'
import { daysPerMonth, monthsPerYear, type RPGDate } from '@/models/Date'
import { useCalendar } from '@/stores/CalendarStore'
import { useCalendarEvents } from '@/stores/EventStore'
@@ -9,7 +9,7 @@ const { currentDate, currentConfig, jumpToDate } = useCalendar()
const { getRelativeEventFromDate } = useCalendarEvents()
function handleGotoPreviousEventPage(position: 'next' | 'prev' = 'next') {
let fromDate: LeimDate
let fromDate: RPGDate
const toDay = position === 'next' ? daysPerMonth : 1
const toMonth = position === 'next' ? monthsPerYear : 0

View File

@@ -2,11 +2,15 @@
const route = useRoute()
const worldId = route.params.id
const { data: calendar } = await useLazyFetch(`/api/calendars/query?world_id=${worldId}`)
const { months } = storeToRefs(useCalendar())
const { data: res } = await useLazyFetch(`/api/calendars/query?world_id=${worldId}`)
if (res.value?.data?.months) {
months.value = res.value?.data?.months
}
</script>
<template>
<pre>
{{ calendar }}
</pre>
<Calendar />
</template>

View File

@@ -5,13 +5,13 @@ import {
type Character,
type CharacterCategory
} from '@/models/Characters'
import type { LeimDateOrder } from '@/models/Date'
import type { RPGDateOrder } from '@/models/Date'
import {
calendarEventCategories,
isCalendarEvent,
type CalendarEvent,
type CalendarEventCategory
} from '@/models/Events'
} from '~/models/CalendarEvent'
import { useCharacters } from '@/stores/CharacterStore'
import { useCalendarEvents } from '@/stores/EventStore'
import { capitalize } from '@/utils/Strings'
@@ -41,7 +41,7 @@ const searchQuery = ref<string>('')
const selectedEntity = useStorage('se', 'events' as SearchMode)
// Order
const selectedOrder = ref<LeimDateOrder>('asc')
const selectedOrder = ref<RPGDateOrder>('asc')
function setOrderAsc() {
selectedOrder.value = 'asc'
resetPage()

View File

@@ -1,6 +1,6 @@
<script lang="ts" setup>
import type { Character } from '@/models/Characters'
import type { LeimDate } from '@/models/Date'
import type { RPGDate } from '@/models/Date'
import { useCalendar } from '@/stores/CalendarStore'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
@@ -12,7 +12,7 @@ defineProps<{
}>()
defineEmits<{
(e: 'query:date-jump', payload: LeimDate): void
(e: 'query:date-jump', payload: RPGDate): void
}>()
const { getFormattedDateTitle } = useCalendar()

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { getRelativeString, type LeimDate } from '@/models/Date'
import { getRelativeString, type RPGDate } from '@/models/Date'
import type { CalendarEvent } from '@/models/Events'
import { useCalendar } from '@/stores/CalendarStore'
@@ -12,7 +12,7 @@ const props = defineProps<{
}>()
defineEmits<{
(e: 'query:date-jump', payload: LeimDate): void
(e: 'query:date-jump', payload: RPGDate): void
}>()
const { defaultDate, getFormattedDateTitle } = useCalendar()

View File

@@ -1,7 +1,7 @@
<script lang="ts" setup>
import { isCharacter, type Character } from '@/models/Characters'
import { compareDates, type LeimDate, type LeimDateOrder } from '@/models/Date'
import { isCalendarEvent, type CalendarEvent } from '@/models/Events'
import { compareDates, type RPGDate, type RPGDateOrder } from '@/models/Date'
import { isCalendarEvent, type CalendarEvent } from '~/models/CalendarEvent'
import { useCalendar } from '@/stores/CalendarStore'
import { computed } from 'vue'
import type { SearchMode } from '../../SearchMode'
@@ -12,7 +12,7 @@ import EventCallout from './EventCallout.vue'
const props = defineProps<{
results: (Character | CalendarEvent)[]
currentEntity: SearchMode
order: LeimDateOrder
order: RPGDateOrder
startAt: number
endAt: number
limit?: number
@@ -22,7 +22,7 @@ const emit = defineEmits(['jumpedToDate'])
const { jumpToDate } = useCalendar()
function handleJumpToDate(date?: LeimDate) {
function handleJumpToDate(date?: RPGDate) {
if (!date) return
jumpToDate(date)
@@ -32,8 +32,8 @@ function handleJumpToDate(date?: LeimDate) {
// Initial sorting of the results
const sortedResults = computed(() => {
return [...props.results].sort((a, b) => {
let firstDate: LeimDate
let secondDate: LeimDate
let firstDate: RPGDate
let secondDate: RPGDate
if (isCalendarEvent(a)) {
firstDate = a.startDate

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { areDatesIdentical, type LeimDate } from '@/models/Date'
import { areDatesIdentical, type RPGDate } from '@/models/Date'
import { useCalendar } from '@/stores/CalendarStore'
import { useCalendarEvents } from '@/stores/EventStore'
import { useElementBounding } from '@vueuse/core'
@@ -7,10 +7,10 @@ import { storeToRefs } from 'pinia'
import { computed, ref, type ComputedRef } from 'vue'
import CalendarEventButton from '../../CalendarEvent.vue'
import type { CalendarEvent } from '@/models/Events'
import type { CalendarEvent } from '~/models/CalendarEvent'
const props = defineProps<{
date: LeimDate
date: RPGDate
faded?: boolean
}>()

View File

@@ -1,38 +1,9 @@
<script lang="ts" setup>
import type { LeimDate } from '@/models/Date'
import { useCalendar } from '@/stores/CalendarStore'
import { useThrottleFn } from '@vueuse/core'
import DayTile from './DayTile.vue'
const { staticConfig, currentDate, decrementMonth, incrementMonth } = useCalendar()
const daysPerMonth = staticConfig.daysPerMonth
function getNextMonthDate(day: number): LeimDate {
let nextDay = day
let nextMonth = currentDate.currentMonth + 1
let nextYear = currentDate.currentYear
let nextPeriod = currentDate.currentPeriod
// If the new value would exceed the max number of month per year
if (nextMonth >= staticConfig.monthsPerYear) {
nextMonth = 0
// Increment the year
nextYear++
}
if (nextYear >= 0) {
nextPeriod = 'nante'
}
return {
day: nextDay,
month: nextMonth,
year: nextYear,
period: nextPeriod
}
}
const { currentDate, decrementMonth, incrementMonth } = useCalendar()
const { currentMonthData } = storeToRefs(useCalendar())
function handleWheel(e: WheelEvent) {
const isMovingUp = e.deltaY < 0
@@ -54,8 +25,8 @@ const moveCalendarRight = useThrottleFn(() => {
<template>
<div class="grid grid-cols-10" @wheel="handleWheel">
<DayTile
v-for="day in daysPerMonth"
<CalendarStateMonthlyDayTile
v-for="day in currentMonthData.days"
:key="day"
:date="{
day: day,
@@ -63,11 +34,5 @@ const moveCalendarRight = useThrottleFn(() => {
year: currentDate.currentYear
}"
/>
<DayTile
v-for="nextMonthDay in 8"
:key="nextMonthDay"
faded
:date="getNextMonthDate(nextMonthDay)"
/>
</div>
</template>

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { areDatesIdentical, type LeimDate } from '@/models/Date'
import { areDatesIdentical, type RPGDate } from '@/models/Date'
import { useCalendar } from '@/stores/CalendarStore'
import { useCalendarEvents } from '@/stores/EventStore'
import { storeToRefs } from 'pinia'
@@ -14,7 +14,7 @@ const props = defineProps<{
dayNumber: number
}>()
const tileDate: ComputedRef<LeimDate> = computed(() => {
const tileDate: ComputedRef<RPGDate> = computed(() => {
return {
day: props.dayNumber,
month: props.monthNumber,

View File

@@ -2,9 +2,8 @@
import { useCalendar } from '@/stores/CalendarStore'
import { useThrottleFn } from '@vueuse/core'
import MonthTile from './MonthTile.vue'
const { staticConfig, decrementYear, incrementYear } = useCalendar()
const { decrementYear, incrementYear } = useCalendar()
const { sortedMonths: months } = storeToRefs(useCalendar())
function handleWheel(e: WheelEvent) {
const isMovingUp = e.deltaY < 0
@@ -27,10 +26,10 @@ const moveCalendarRight = useThrottleFn(() => {
<template>
<div class="container mt-[10vh] mb-auto" @wheel="handleWheel">
<div class="grid grid-cols-5 gap-x-8 gap-y-16">
<MonthTile
v-for="month in staticConfig.monthsPerYear"
:key="month"
:month-number="month - 1"
<CalendarStateYearlyMonthTile
v-for="month in months"
:key="month.id"
:month
/>
</div>
</div>

View File

@@ -1,27 +1,21 @@
<script lang="ts" setup>
import { useCalendar } from '@/stores/CalendarStore'
import type { CalendarMonth } from '~/models/CalendarMonth';
import DayTile from './DayTile.vue'
const { staticConfig, getMonthName } = useCalendar()
const props = defineProps<{
monthNumber: number
defineProps<{
month: CalendarMonth
}>()
const tileMonthName: string = getMonthName(props.monthNumber)
</script>
<template>
<div>
<div class="font-medium">
{{ tileMonthName }}
{{ month.name }}
</div>
<div class="grid grid-cols-7">
<DayTile
v-for="day in staticConfig.daysPerMonth"
<CalendarStateYearlyDayTile
v-for="day in month.days"
:key="day"
:month-number="monthNumber"
:month-number="month.position"
:day-number="day"
/>
</div>

View File

@@ -1,6 +1,12 @@
import type { CalendarEvent } from "./CalendarEvent"
import type { CalendarMonth } from "./CalendarMonth"
export interface CalendarConfig {
months: string[]
monthsPerYear: number
months: CalendarMonth[]
daysPerMonth: number
// todayDate: any
}
export interface Calendar extends CalendarConfig {
id: number
events: CalendarEvent[]
}

18
models/CalendarEvent.ts Normal file
View File

@@ -0,0 +1,18 @@
import type { Category } from './Category'
import type { RPGDate } from './Date'
export interface CalendarEvent {
id: number
title: string
startDate: RPGDate
endDate?: RPGDate
description?: string
category?: Category
hidden?: boolean
wiki?: string
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function isCalendarEvent(object: any): object is CalendarEvent {
return 'startDate' in object
}

6
models/CalendarMonth.ts Normal file
View File

@@ -0,0 +1,6 @@
export interface CalendarMonth {
id: number
days: number,
name: string,
position: number,
}

4
models/Category.ts Normal file
View File

@@ -0,0 +1,4 @@
export interface Category {
id: number
name: string
}

View File

@@ -1,10 +1,10 @@
import type { LeimDate } from './Date'
import type { RPGDate } from './Date'
export interface Character {
name: string
description?: string
birth?: LeimDate
death?: LeimDate
birth?: RPGDate
death?: RPGDate
hiddenBirth?: boolean
hiddenDeath?: boolean
category?: CharacterCategory

View File

@@ -1,13 +1,13 @@
export interface LeimDate {
export interface RPGDate {
day: number
month: number
year: number
period?: LeimPeriod
period?: RPGPeriod
}
export type LeimPeriod = 'ante' | 'nante'
export type LeimPeriodShort = 'A.R' | 'N.R'
export type LeimDateOrder = 'asc' | 'desc'
export type RPGPeriod = 'ante' | 'nante'
export type RPGPeriodShort = 'A.R' | 'N.R'
export type RPGDateOrder = 'asc' | 'desc'
export const monthsPerYear: number = 10
export const daysPerYear: number = 320
@@ -21,7 +21,7 @@ export const daysPerWeek: number = 6
* @param date2 Second date
* @returns True if the dates are identical
*/
export function areDatesIdentical(date1: LeimDate, date2: LeimDate): boolean {
export function areDatesIdentical(date1: RPGDate, date2: RPGDate): boolean {
return convertDateToDays({ ...date1 }) === convertDateToDays({ ...date2 })
}
@@ -32,7 +32,7 @@ export function areDatesIdentical(date1: LeimDate, date2: LeimDate): boolean {
* @param date2 Second date
* @returns 1 means the first date comes before the second, -1 means the second comes before the first, and 0 if they're identical
*/
export function compareDates(a: LeimDate, b: LeimDate, order: LeimDateOrder = 'desc'): number {
export function compareDates(a: RPGDate, b: RPGDate, order: RPGDateOrder = 'desc'): number {
// Reverses the order if specified
const orderFactor: number = order === 'desc' ? 1 : -1
@@ -58,13 +58,13 @@ export function compareDates(a: LeimDate, b: LeimDate, order: LeimDateOrder = 'd
}
/**
* Converts a LeimDate to its equivalent in days
* Converts a RPGDate to its equivalent in days
*
* @todo Handle negative dates
* @param dateToConvert The date object
* @returns How many days does it represent
*/
export function convertDateToDays(dateToConvert: LeimDate): number {
export function convertDateToDays(dateToConvert: RPGDate): number {
let numberOfDays: number = dateToConvert.day
numberOfDays = numberOfDays + dateToConvert.month * daysPerMonth
@@ -79,7 +79,7 @@ export function convertDateToDays(dateToConvert: LeimDate): number {
* @param relativeDate The year to compare it to
* @returns The number of days separating the two dates (both positive and negative numbers)
*/
export function getDifferenceInDays(baseDate: LeimDate, relativeDate: LeimDate): number {
export function getDifferenceInDays(baseDate: RPGDate, relativeDate: RPGDate): number {
return convertDateToDays(relativeDate) - convertDateToDays(baseDate)
}
@@ -91,8 +91,8 @@ export function getDifferenceInDays(baseDate: LeimDate, relativeDate: LeimDate):
* @returns A string with info on how the relative date differs to the base date
*/
export function getRelativeString(
baseDate: LeimDate,
relativeDate: LeimDate,
baseDate: RPGDate,
relativeDate: RPGDate,
formatting: 'compact' | 'complex' = 'complex'
): string {
const differenceInDays: number = getDifferenceInDays(baseDate, relativeDate)
@@ -177,11 +177,11 @@ export function getRelativeString(
return output
}
// export function getRelativeDate(baseDate: LeimDate, relativeDate: LeimDate) {
// export function getRelativeDate(baseDate: RPGDate, relativeDate: RPGDate) {
// let newDay: number
// let newMonth: number
// let newYear: number
// let newPeriod: LeimPeriod
// let newPeriod: RPGPeriod
// const differenceInDays = getDifferenceInDays(baseDate, relativeDate)

View File

@@ -1,39 +0,0 @@
import type { LeimDate } from './Date'
export interface CalendarEvent {
title: string
startDate: LeimDate
endDate?: LeimDate
description?: string
category?: CalendarEventCategory
secondaryCategories?: CalendarEventCategory[]
hidden?: boolean
wiki?: string
}
export const calendarEventCategories = [
'naissance',
'mort',
'catastrophe',
'législation',
'catastrophe naturelle',
'inauguration',
'religion',
'invention',
'science',
'bénédiction',
'joueurs',
'découverte',
'exploration',
'construction',
'arcanologie',
'criminalité',
'scandale',
'commerce'
] as const
export type CalendarEventCategory = (typeof calendarEventCategories)[number]
export function isCalendarEvent(object: any): object is CalendarEvent {
return 'startDate' in object
}

View File

@@ -11,21 +11,5 @@ const sidebarMenu: MenuItem[] = []
<template>
<main class="h-full grid grid-cols-[auto_1fr]">
<Sidebar :menu-items="sidebarMenu" is-home />
<div class="h-full grid place-items-center">
<UiCard class="w-1/3 min-w-72 hover:bg-sky-950 focus-within:outline-sky-900" link="/calendar">
<UiCardHeader>
<UiCardTitle>Calendrier</UiCardTitle>
<UiCardDescription>
<UiBadge class="mix-blend-luminosity font-bold bg-gray-600" variant="secondary">
chronologie
</UiBadge>
</UiCardDescription>
</UiCardHeader>
<UiCardContent>
Chronologie complète de Léïm, rassemblant les évènements et personnages clés du monde
</UiCardContent>
</UiCard>
</div>
</main>
</template>

View File

@@ -1,5 +1,6 @@
import { serverSupabaseClient } from "#supabase/server";
import { z } from 'zod'
import type { Calendar } from "~/models/CalendarConfig";
const querySchema = z.object({
world_id: z.number({ coerce: true }).positive().int()
@@ -13,11 +14,21 @@ export default defineEventHandler(async (event) => {
.from('world_calendars')
.select(`
id,
months,
days_per_year,
events (*)
months:calendar_months (*),
events:calendar_events (
id,
title,
description,
hidden,
startDate:start_date,
endDate:end_date,
wiki,
category:calendar_events_category (*)
)
`)
.eq('world_id', query.world_id)
.limit(1)
.single<Calendar>()
return output
})

View File

@@ -10,7 +10,7 @@ export default defineEventHandler(async (event) => {
const query = await getValidatedQuery(event, querySchema.parse)
const output = client
.from('events')
.from('calendar_events')
.select(`
id,
title,

View File

@@ -1,26 +1,13 @@
import {
monthsPerYear,
daysPerWeek,
daysPerMonth,
daysPerYear,
type LeimDate,
type LeimPeriod,
type LeimPeriodShort
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 CalendarStaticConfig = {
months: string[]
monthsPerYear: number
daysPerYear: number
daysPerMonth: number
daysPerWeek: number
}
type CalendarCurrentConfig = {
viewType: CalendarViewType
}
@@ -30,8 +17,6 @@ type CalendarCurrentDate = {
currentMonth: ComputedRef<number>
currentMonthName: ComputedRef<string>
currentYear: ComputedRef<number>
currentPeriod: Ref<LeimPeriod>
currentPeriodAbbr: Ref<LeimPeriodShort>
currentDateTitle: ComputedRef<string>
}
@@ -43,27 +28,10 @@ export const useCalendar = defineStore('calendar', () => {
/**
* Month list
*/
const months: string[] = [
'Jalen',
'Malsen',
'Verlys',
'Nalys',
'Verdore',
'Sidore',
'Lyllion',
'Rion',
'Farene',
'Dalvene'
]
// Assign the static config
const staticConfig: CalendarStaticConfig = {
months,
monthsPerYear,
daysPerYear,
daysPerMonth,
daysPerWeek
}
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'
@@ -79,7 +47,7 @@ export const useCalendar = defineStore('calendar', () => {
const defaultDay: number = 23
const defaultMonth: number = 8
const defaultYear: number = 3209
const defaultDate: ComputedRef<LeimDate> = computed(() => {
const defaultDate: ComputedRef<RPGDate> = computed(() => {
return {
day: defaultDay,
month: defaultMonth,
@@ -104,6 +72,9 @@ export const useCalendar = defineStore('calendar', () => {
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))
@@ -111,12 +82,6 @@ export const useCalendar = defineStore('calendar', () => {
return Number(params.year)
})
// Get period from currentYear
const currentPeriod = computed<LeimPeriod>(() => getPeriodOfYear(currentYear.value).long)
const currentPeriodAbbr = computed<LeimPeriodShort>(
() => getPeriodOfYear(currentYear.value).short
)
const currentDateTitle = computed<string>(() => {
switch (currentConfig.value.viewType) {
case 'month':
@@ -124,17 +89,16 @@ export const useCalendar = defineStore('calendar', () => {
day: currentDate.currentDay.value,
month: currentDate.currentMonth.value,
year: currentDate.currentYear.value,
period: currentDate.currentPeriod.value
})
case 'year':
return `Année ${currentYear.value} ${currentPeriodAbbr.value}`
return `Année ${currentYear.value}`
case 'decade':
return `Années ${currentYear.value} ${getPeriodOfYear(currentYear.value).short} - ${currentYear.value + 10} ${getPeriodOfYear(currentYear.value + 10).short}`
return `Années ${currentYear.value} - ${currentYear.value + 10}`
case 'century':
return `Années ${currentYear.value} ${getPeriodOfYear(currentYear.value).short} - ${currentYear.value + 100} ${getPeriodOfYear(currentYear.value + 100).short}`
return `Années ${currentYear.value} - ${currentYear.value + 100}`
default:
return 'Date inconnue'
@@ -147,21 +111,18 @@ export const useCalendar = defineStore('calendar', () => {
currentMonth,
currentMonthName,
currentYear,
currentPeriod,
currentPeriodAbbr,
currentDateTitle
}
const currentLeimDate = computed<LeimDate>(() => {
const currentRPGDate = computed<RPGDate>(() => {
return {
day: currentDate.currentDay.value,
month: currentDate.currentMonth.value,
year: currentDate.currentYear.value,
period: currentDate.currentPeriod.value
}
})
const selectedDate = useLocalStorage<LeimDate>('selected-date', currentLeimDate.value, { deep: true })
const selectedDate = useLocalStorage<RPGDate>('selected-date', currentRPGDate.value, { deep: true })
/**
* Check whether the current viewType is active
@@ -192,7 +153,7 @@ export const useCalendar = defineStore('calendar', () => {
let newValue = Number(params.month) + 1
// If the new value would exceed the max number of month per year
if (newValue >= staticConfig.monthsPerYear) {
if (newValue >= monthsPerYear.value) {
newValue = 0
// Increment the year
incrementYear()
@@ -209,7 +170,7 @@ export const useCalendar = defineStore('calendar', () => {
// If the new value would go below 0
if (newValue < 0) {
newValue = staticConfig.monthsPerYear - 1
newValue = monthsPerYear.value - 1
// Decrement the year
decrementYear()
}
@@ -227,7 +188,7 @@ export const useCalendar = defineStore('calendar', () => {
const target: number = monthNumber - 1
if (target < 0) {
return monthsPerYear - 1
return monthsPerYear.value - 1
}
return target
@@ -242,7 +203,7 @@ export const useCalendar = defineStore('calendar', () => {
function getNextMonth(monthNumber: number): number {
const target: number = monthNumber + 1
if (target + 1 >= monthsPerYear) {
if (target + 1 >= monthsPerYear.value) {
return 0
}
@@ -254,7 +215,7 @@ export const useCalendar = defineStore('calendar', () => {
*/
function setMonth(target: number): void {
// If the target is outside the month bounds
if (target < 0 || target >= staticConfig.monthsPerYear) {
if (target < 0 || target >= monthsPerYear.value) {
return
}
@@ -279,23 +240,6 @@ export const useCalendar = defineStore('calendar', () => {
params.year = newValue.toString()
}
/**
* From a given year, returns a set of LeimPeriod identifier
*
* This is used in range use-cases
*
* @param year The year to display
* @returns An object containing both short and long LeimPeriod
*/
function getPeriodOfYear(year: string | number): { long: LeimPeriod; short: LeimPeriodShort } {
const numYear = year as number
return {
long: numYear >= 0 ? 'nante' : 'ante',
short: numYear >= 0 ? 'N.R' : 'A.R'
}
}
/**
* Get the formatted month name given its index
*
@@ -304,7 +248,7 @@ export const useCalendar = defineStore('calendar', () => {
*/
function getMonthName(monthNumber: number): string {
const index = Number(monthNumber)
return staticConfig.months[index]
return sortedMonths.value[index].name
}
/**
@@ -340,18 +284,18 @@ export const useCalendar = defineStore('calendar', () => {
}
/**
* From a LeimDate, returns the legible date title
* 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: LeimDate, showNumber?: boolean): string {
function getFormattedDateTitle(date: RPGDate, showNumber?: boolean): string {
if (showNumber) {
return `${date.day} ${getMonthName(date.month)} ${date.year} ${getPeriodOfYear(date.year).short}`
return `${date.day} ${getMonthName(date.month)} ${date.year}`
}
return `${getMonthName(date.month)} ${date.year} ${getPeriodOfYear(date.year).short}`
return `${getMonthName(date.month)} ${date.year}`
}
/**
@@ -359,7 +303,7 @@ export const useCalendar = defineStore('calendar', () => {
*
* @param date Target date
*/
function jumpToDate(date: LeimDate): void {
function jumpToDate(date: RPGDate): void {
params.day = date.day.toString()
params.month = date.month.toString()
params.year = date.year.toString()
@@ -376,7 +320,7 @@ export const useCalendar = defineStore('calendar', () => {
/**
* Jump the calendar to the default date
*/
function selectDate(date: LeimDate): void {
function selectDate(date: RPGDate): void {
selectedDate.value = date
}
@@ -387,16 +331,19 @@ export const useCalendar = defineStore('calendar', () => {
}
return {
staticConfig,
months,
sortedMonths,
daysPerYear,
monthsPerYear,
viewTypeOptions,
currentConfig,
currentDate,
currentLeimDate,
currentRPGDate,
currentMonthData,
defaultDate,
selectedDate: skipHydrate(selectedDate),
selectDate,
params,
getPeriodOfYear,
incrementMonth,
decrementMonth,
setMonth,

View File

@@ -1,5 +1,5 @@
import { compareDates, convertDateToDays, daysPerMonth, type LeimDate } from '@/models/Date'
import type { CalendarEvent } from '@/models/Events'
import { compareDates, convertDateToDays, daysPerMonth, type RPGDate } from '@/models/Date'
import type { CalendarEvent } from '@/models/CalendarEvent'
import { defineStore } from 'pinia'
import { ref, watch, type Ref } from 'vue'
import { useCalendar } from './CalendarStore'
@@ -119,8 +119,8 @@ export const useCalendarEvents = defineStore('calendar-events', () => {
event: CalendarEvent,
position: 'next' | 'prev' = 'next',
initialIsEnd: boolean = false
): { event: CalendarEvent; targetDate: LeimDate } {
let dateToParse: LeimDate // Day value of the date that the user interacted with
): { event: CalendarEvent; targetDate: RPGDate } {
let dateToParse: RPGDate // Day value of the date that the user interacted with
if (initialIsEnd && event.endDate) {
dateToParse = event.endDate
@@ -132,9 +132,9 @@ export const useCalendarEvents = defineStore('calendar-events', () => {
}
function getRelativeEventFromDate(
date: LeimDate,
date: RPGDate,
position: 'next' | 'prev' = 'next'
): { event: CalendarEvent; targetDate: LeimDate } {
): { event: CalendarEvent; targetDate: RPGDate } {
const pivotValue = convertDateToDays(date)
let t: { eventData: CalendarEvent; distance: number; targetKey: 'startDate' | 'endDate' }[] = []

View File

@@ -47,33 +47,41 @@ comment on table public.worlds is 'Worlds belonging to a single user ; a game ma
-- World Calendars
create table public.world_calendars (
id bigint generated by default as identity primary key,
months text array,
days_per_year int not null,
world_id bigint references public.worlds on delete cascade not null
);
comment on table public.world_calendars is 'Calendar settings and configuration attached to a single world.';
-- Calendar Months
create table public.calendar_months (
id bigint generated by default as identity primary key,
name text not null,
days int not null,
position int not null,
calendar_id bigint references public.world_calendars on delete cascade not null
);
comment on table public.calendar_months is 'A calendar month.';
-- Event categories
create table public.events_category (
create table public.calendar_events_category (
id bigint generated by default as identity primary key,
name text not null,
unique (name)
);
comment on table public.events_category is 'Categories describing events';
comment on table public.calendar_events_category is 'Categories describing events';
-- Events
create table public.events (
create table public.calendar_events (
id bigint generated by default as identity primary key,
title text not null,
description text,
start_date json not null,
end_date json,
category bigint references public.events_category on delete cascade,
category bigint references public.calendar_events_category on delete cascade,
hidden boolean,
wiki text,
calendar_id bigint references public.world_calendars on delete cascade not null
);
comment on table public.events is 'Events linked to a world';
comment on table public.calendar_events is 'Events linked to a world';
-- Character categories
create table public.characters_category (
@@ -121,11 +129,12 @@ alter table public.users enable row level security;
alter table public.user_roles enable row level security;
alter table public.role_permissions enable row level security;
alter table public.worlds enable row level security;
alter table public.world_calendars enable row level security;
alter table public.events_category enable row level security;
alter table public.characters_category enable row level security;
alter table public.characters enable row level security;
alter table public.events enable row level security;
alter table public.world_calendars enable row level security;
alter table public.calendar_months enable row level security;
alter table public.calendar_events enable row level security;
alter table public.calendar_events_category enable row level security;
-- User policies
create policy "Allow logged-in read access" on public.users for select using ( auth.role() = 'authenticated' );
@@ -158,23 +167,43 @@ create policy "Allow individual update access for GMs" on public.world_calendars
)
);
-- Month policies
create policy "Allow individual read access for GMs" on public.calendar_months for select using (
exists (
select 1 from world_calendars
where world_calendars.id = calendar_months.calendar_id
)
);
create policy "Allow individual insert access for GMs" on public.calendar_months for insert with check (
exists (
select 1 from world_calendars
where world_calendars.id = calendar_months.calendar_id
)
);
create policy "Allow individual update access for GMs" on public.calendar_months for update with check (
exists (
select 1 from world_calendars
where world_calendars.id = calendar_months.calendar_id
)
);
-- Event policies
create policy "Allow individual read access for GMs" on public.events for select using (
create policy "Allow individual read access for GMs" on public.calendar_events for select using (
exists (
select 1 from world_calendars
where world_calendars.id = events.calendar_id
where world_calendars.id = calendar_events.calendar_id
)
);
create policy "Allow individual insert access for GMs" on public.events for insert with check (
create policy "Allow individual insert access for GMs" on public.calendar_events for insert with check (
exists (
select 1 from world_calendars
where world_calendars.id = events.calendar_id
where world_calendars.id = calendar_events.calendar_id
)
);
create policy "Allow individual update access for GMs" on public.events for update with check (
create policy "Allow individual update access for GMs" on public.calendar_events for update with check (
exists (
select 1 from world_calendars
where world_calendars.id = events.calendar_id
where world_calendars.id = calendar_events.calendar_id
)
);
@@ -198,6 +227,10 @@ create policy "Allow individual update access for GMs" on public.characters for
)
);
-- Categories are public to view but not to insert
create policy "Allow logged-in read access" on public.calendar_events_category for select using ( auth.role() = 'authenticated' );
create policy "Allow logged-in read access" on public.characters_category for select using ( auth.role() = 'authenticated' );
-- Send "previous data" on change
alter table public.users replica identity full;

View File

@@ -2,24 +2,24 @@ insert into public.role_permissions (role, permission) values ('sa', 'events.see
insert into public.role_permissions (role, permission) values ('sa', 'users.ban');
-- Event categories
insert into public.events_category (name) values ('naissance');
insert into public.events_category (name) values ('mort');
insert into public.events_category (name) values ('catastrophe');
insert into public.events_category (name) values ('catastrophe naturelle');
insert into public.events_category (name) values ('inauguration');
insert into public.events_category (name) values ('religion');
insert into public.events_category (name) values ('invention');
insert into public.events_category (name) values ('science');
insert into public.events_category (name) values ('bénédiction');
insert into public.events_category (name) values ('joueurs');
insert into public.events_category (name) values ('découverte');
insert into public.events_category (name) values ('exploration');
insert into public.events_category (name) values ('construction');
insert into public.events_category (name) values ('arcanologie');
insert into public.events_category (name) values ('criminalité');
insert into public.events_category (name) values ('scandale');
insert into public.events_category (name) values ('commerce');
insert into public.events_category (name) values ('législation');
insert into public.calendar_events_category (name) values ('naissance');
insert into public.calendar_events_category (name) values ('mort');
insert into public.calendar_events_category (name) values ('catastrophe');
insert into public.calendar_events_category (name) values ('catastrophe naturelle');
insert into public.calendar_events_category (name) values ('inauguration');
insert into public.calendar_events_category (name) values ('religion');
insert into public.calendar_events_category (name) values ('invention');
insert into public.calendar_events_category (name) values ('science');
insert into public.calendar_events_category (name) values ('bénédiction');
insert into public.calendar_events_category (name) values ('joueurs');
insert into public.calendar_events_category (name) values ('découverte');
insert into public.calendar_events_category (name) values ('exploration');
insert into public.calendar_events_category (name) values ('construction');
insert into public.calendar_events_category (name) values ('arcanologie');
insert into public.calendar_events_category (name) values ('criminalité');
insert into public.calendar_events_category (name) values ('scandale');
insert into public.calendar_events_category (name) values ('commerce');
insert into public.calendar_events_category (name) values ('législation');
-- Character categories
insert into public.characters_category (name) values ('joueur');
@@ -39,10 +39,24 @@ insert into public.characters_category (name) values ('commerçant');
insert into public.worlds (name, description, color) values ('Léïm', 'Monde d''aventures et d''intrigues med-fan', 'black');
-- Worlds' calendars
insert into public.world_calendars (world_id, months, days_per_year) values (1, ARRAY['Jalen', 'Malsen', 'Verlys', 'Nalys', 'Verdore', 'Sidore', 'Lyllion', 'Rion', 'Farene', 'Dalvene'], 320);
insert into public.world_calendars (world_id) values (1);
-- Calendar's months
insert into public.calendar_months (calendar_id, name, days, position) values (1, 'Jalen', 32, 1);
insert into public.calendar_months (calendar_id, name, days, position) values (1, 'Malsen', 32, 2);
insert into public.calendar_months (calendar_id, name, days, position) values (1, 'Verlys', 32, 3);
insert into public.calendar_months (calendar_id, name, days, position) values (1, 'Nalys', 32, 4);
insert into public.calendar_months (calendar_id, name, days, position) values (1, 'Verdore', 32, 5);
insert into public.calendar_months (calendar_id, name, days, position) values (1, 'Sidore', 32, 6);
insert into public.calendar_months (calendar_id, name, days, position) values (1, 'Lyllion', 32, 7);
insert into public.calendar_months (calendar_id, name, days, position) values (1, 'Rion', 32, 8);
insert into public.calendar_months (calendar_id, name, days, position) values (1, 'Farene', 32, 9);
insert into public.calendar_months (calendar_id, name, days, position) values (1, 'Dalvene', 32, 10);
insert into public.calendar_months (calendar_id, name, days, position) values (1, 'Testos', 32, 11);
insert into public.calendar_months (calendar_id, name, days, position) values (1, 'Jalen2 le meilleur', 32, 12);
-- Events
insert into public.events (title, description, start_date, category, hidden, wiki, calendar_id) values (
insert into public.calendar_events (title, description, start_date, category, hidden, wiki, calendar_id) values (
'Laurdieu devient la première cité de l''empire de Kaliatos',
'L''empire de Kaliatos établi sa capitale dans la cité de Laurdieu, qui connaitra une prospérité nouvelle au sein d''Aldys.',
'{ "day": 3, "month": 4, "year": -1932 }',
@@ -51,7 +65,7 @@ insert into public.events (title, description, start_date, category, hidden, wik
'https://alexcreates.fr/leim/index.php/Laurdieu',
1
);
insert into public.events (title, description, start_date, category, hidden, wiki, calendar_id) values (
insert into public.calendar_events (title, description, start_date, category, hidden, wiki, calendar_id) values (
'Apparition d''Asménys',
'La défunte chanteuse Asménys apparaît à un barde pendant son jeune public, démarrant la religion des Prêtresses d''Asménys.',
'{ "day": 19, "month": 7, "year": -1358 }',
@@ -60,7 +74,7 @@ insert into public.events (title, description, start_date, category, hidden, wik
'https://alexcreates.fr/leim/index.php/Pr%C3%AAtresses_d%27Asm%C3%A9nys',
1
);
insert into public.events (title, description, start_date, end_date, category, hidden, wiki, calendar_id) values (
insert into public.calendar_events (title, description, start_date, end_date, category, hidden, wiki, calendar_id) values (
'La Rupture',
'Les Abysses se déversent à la surface de Léim, à travers plusieurs brèches. Plusieurs hordes de démons se rapprochent des villes, et ce qu''on appellera l''Âge des Abysses commencent alors sur la planète entière.',
'{ "day": 26, "month": 5, "year": -756 }',
@@ -70,7 +84,7 @@ insert into public.events (title, description, start_date, end_date, category, h
'https://alexcreates.fr/leim/index.php/Seconde_Rupture',
1
);
insert into public.events (title, description, start_date, end_date, category, hidden, wiki, calendar_id) values (
insert into public.calendar_events (title, description, start_date, end_date, category, hidden, wiki, calendar_id) values (
'Marche du sang',
'L''empereur de Kaliatos ordonne personnellement la traque de Jorhas Kirendre pour connivence avec les démons. Plusieurs bataillons sont affectés à la chasse de Jorhas, qui se terminera par son incarcération ainsi que la mort de plusieurs centaines de soldats.',
'{ "day": 18, "month": 9, "year": -420 }',
@@ -80,7 +94,7 @@ insert into public.events (title, description, start_date, end_date, category, h
'https://alexcreates.fr/leim/index.php/Jorhas_Kirendre',
1
);
insert into public.events (title, description, start_date, category, hidden, wiki, calendar_id) values (
insert into public.calendar_events (title, description, start_date, category, hidden, wiki, calendar_id) values (
'Exécution de Tyhos',
'Le léviathan Tyhos rend l''âme après un combat de plusieurs années contre Lystos, le dieu du Soleil.',
'{ "day": 1, "month": 0, "year": 0 }',
@@ -89,14 +103,14 @@ insert into public.events (title, description, start_date, category, hidden, wik
'https://alexcreates.fr/leim/index.php/Tyhos',
1
);
insert into public.events (title, start_date, category, wiki, calendar_id) values (
insert into public.calendar_events (title, start_date, category, wiki, calendar_id) values (
'Traité de Kadel',
'{ "day": 29, "month": 4, "year": 100 }',
5,
'https://alexcreates.fr/leim/index.php/Alliance_Kald%C3%A9lienne#Trait%C3%A9_de_Kadel',
1
);
insert into public.events (title, description, start_date, category, hidden, wiki, calendar_id) values (
insert into public.calendar_events (title, description, start_date, category, hidden, wiki, calendar_id) values (
'Découverte des Plaines de Poussières',
'Les troupes de la reconquête aldienne explorent le littoral d''une immense étendue grise et inerte.',
'{ "day": 17, "month": 7, "year": 305 }',