Merge pull request #36 from AlexisNP/features/i18n
This commit is contained in:
4
app.vue
4
app.vue
@@ -5,14 +5,10 @@ useHead({
|
|||||||
titleTemplate: (titleChunk) => {
|
titleTemplate: (titleChunk) => {
|
||||||
return titleChunk ? `${titleChunk} — TTTools` : "TTTools";
|
return titleChunk ? `${titleChunk} — TTTools` : "TTTools";
|
||||||
},
|
},
|
||||||
htmlAttrs: {
|
|
||||||
lang: "fr"
|
|
||||||
},
|
|
||||||
meta: [
|
meta: [
|
||||||
{ name: "charset", content: "UTF-8" },
|
{ name: "charset", content: "UTF-8" },
|
||||||
{ name: "viewport", content: "width=device-width, initial-scale=1.0" },
|
{ name: "viewport", content: "width=device-width, initial-scale=1.0" },
|
||||||
{ name: "author", content: "Alexis Pelé" },
|
{ name: "author", content: "Alexis Pelé" },
|
||||||
{ name: "description", content: "Tools destined to players and game master, helping them visualize their worlds better." },
|
|
||||||
{ name: "generator", content: "Nuxt" },
|
{ name: "generator", content: "Nuxt" },
|
||||||
{ name: "msapplication-TileColor", content: "00aba9" },
|
{ name: "msapplication-TileColor", content: "00aba9" },
|
||||||
{ name: "theme-color", content: "00aba9" },
|
{ name: "theme-color", content: "00aba9" },
|
||||||
|
|||||||
@@ -29,10 +29,8 @@ const eventDetails = ref<HTMLElement>()
|
|||||||
|
|
||||||
const emit = defineEmits(["query:close-popover"])
|
const emit = defineEmits(["query:close-popover"])
|
||||||
|
|
||||||
const dateDifference: string = getRelativeString(defaultDate, props.event.startDate)
|
const dateDifference = computed<string>(() => getRelativeString(defaultDate, props.event.startDate))
|
||||||
const dateDuration: string | null = props.event.endDate
|
const dateDuration = computed<string | null>(() => props.event.endDate ? getRelativeString(props.event.startDate, props.event.endDate, "compact") : null)
|
||||||
? getRelativeString(props.event.startDate, props.event.endDate, "compact")
|
|
||||||
: null
|
|
||||||
|
|
||||||
function handleJumpToDate(date: RPGDate) {
|
function handleJumpToDate(date: RPGDate) {
|
||||||
jumpToDate(date)
|
jumpToDate(date)
|
||||||
@@ -87,8 +85,14 @@ function deployDeleteModal() {
|
|||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<p class="font-semibold">
|
<p class="font-semibold">
|
||||||
Du {{ getFormattedDateTitle(event.startDate, true) }} au
|
{{
|
||||||
{{ getFormattedDateTitle(event.endDate, true) }}
|
$t('entity.calendar.date.fromTo',
|
||||||
|
{
|
||||||
|
startDate: getFormattedDateTitle(event.startDate, true),
|
||||||
|
endDate: getFormattedDateTitle(event.endDate, true)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}}
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
@@ -105,7 +109,8 @@ function deployDeleteModal() {
|
|||||||
</p>
|
</p>
|
||||||
<template v-if="dateDuration">
|
<template v-if="dateDuration">
|
||||||
<p class="text-sm italic dark:opacity-75 flex items-center gap-1">
|
<p class="text-sm italic dark:opacity-75 flex items-center gap-1">
|
||||||
<PhHourglassMedium size="16" weight="fill" /> Pendant {{ dateDuration }}
|
<PhHourglassMedium size="16" weight="fill" />
|
||||||
|
{{ $t('entity.calendar.date.while', { duration: dateDuration } )}}
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
@@ -146,8 +151,8 @@ function deployDeleteModal() {
|
|||||||
<UiCommand>
|
<UiCommand>
|
||||||
<UiCommandList>
|
<UiCommandList>
|
||||||
<UiCommandGroup>
|
<UiCommandGroup>
|
||||||
<UiCommandItem value="edit-event" @select="deployEditModal"> Modifier </UiCommandItem>
|
<UiCommandItem value="edit-event" @select="deployEditModal"> {{ $t('ui.action.edit') }} </UiCommandItem>
|
||||||
<UiCommandItem value="delete-event" @select="deployDeleteModal"> Supprimer </UiCommandItem>
|
<UiCommandItem value="delete-event" @select="deployDeleteModal"> {{ $t('ui.action.delete') }} </UiCommandItem>
|
||||||
</UiCommandGroup>
|
</UiCommandGroup>
|
||||||
</UiCommandList>
|
</UiCommandList>
|
||||||
</UiCommand>
|
</UiCommand>
|
||||||
@@ -162,7 +167,7 @@ function deployDeleteModal() {
|
|||||||
title="Naviguer au début"
|
title="Naviguer au début"
|
||||||
@click="handleJumpToDate(event.startDate!)"
|
@click="handleJumpToDate(event.startDate!)"
|
||||||
>
|
>
|
||||||
<PhHourglassHigh size="16" weight="fill" /> Début
|
<PhHourglassHigh size="16" weight="fill" /> {{ $t('entity.calendar.event.isStart') }}
|
||||||
</button>
|
</button>
|
||||||
</UiBadge>
|
</UiBadge>
|
||||||
<UiBadge class="hover:bg-indigo-400 dark:hover:bg-slate-300" as-child title="Naviguer à la fin">
|
<UiBadge class="hover:bg-indigo-400 dark:hover:bg-slate-300" as-child title="Naviguer à la fin">
|
||||||
@@ -171,7 +176,7 @@ function deployDeleteModal() {
|
|||||||
title="Naviguer à la fin"
|
title="Naviguer à la fin"
|
||||||
@click="handleJumpToDate(event.endDate!)"
|
@click="handleJumpToDate(event.endDate!)"
|
||||||
>
|
>
|
||||||
<PhHourglassLow size="16" weight="fill" /> Fin
|
<PhHourglassLow size="16" weight="fill" /> {{ $t('entity.calendar.event.isEnd') }}
|
||||||
</button>
|
</button>
|
||||||
</UiBadge>
|
</UiBadge>
|
||||||
</nav>
|
</nav>
|
||||||
@@ -180,11 +185,13 @@ function deployDeleteModal() {
|
|||||||
<UiTooltip>
|
<UiTooltip>
|
||||||
<UiTooltipTrigger as-child>
|
<UiTooltipTrigger as-child>
|
||||||
<UiBadge class="absolute -top-2 right-2 flex gap-1">
|
<UiBadge class="absolute -top-2 right-2 flex gap-1">
|
||||||
<PhEye size="16" weight="fill" /> Évènement privé
|
<PhEye size="16" weight="fill" /> {{ $t('entity.calendar.event.isHidden') }}
|
||||||
</UiBadge>
|
</UiBadge>
|
||||||
</UiTooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<UiTooltipContent>
|
<UiTooltipContent>
|
||||||
<p>Cet évènement est uniquement visible pour vous</p>
|
<p>
|
||||||
|
{{ $t('entity.calendar.event.hiddenTooltip') }}
|
||||||
|
</p>
|
||||||
</UiTooltipContent>
|
</UiTooltipContent>
|
||||||
</UiTooltip>
|
</UiTooltip>
|
||||||
</UiTooltipProvider>
|
</UiTooltipProvider>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ const { revealAdvancedSearch } = useCalendar()
|
|||||||
<li>
|
<li>
|
||||||
<UiButton search-slash @click="revealAdvancedSearch()">
|
<UiButton search-slash @click="revealAdvancedSearch()">
|
||||||
<PhMagnifyingGlass size="20" weight="light" />
|
<PhMagnifyingGlass size="20" weight="light" />
|
||||||
Recherche avancée
|
{{ $t('entity.advancedSearch.title') }}
|
||||||
</UiButton>
|
</UiButton>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import {
|
|||||||
PhCaretRight
|
PhCaretRight
|
||||||
} from "@phosphor-icons/vue"
|
} from "@phosphor-icons/vue"
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
interface DirectionLabels {
|
interface DirectionLabels {
|
||||||
pastFar: string
|
pastFar: string
|
||||||
pastNear: string
|
pastNear: string
|
||||||
@@ -23,35 +25,35 @@ const activeDirectionLabels: ComputedRef<DirectionLabels> = computed(() => {
|
|||||||
switch (currentConfig.viewType) {
|
switch (currentConfig.viewType) {
|
||||||
case "month":
|
case "month":
|
||||||
return {
|
return {
|
||||||
pastFar: "Année précédente",
|
pastFar: t("entity.calendar.years.prevSingular"),
|
||||||
pastNear: "Mois précédent",
|
pastNear: t("entity.calendar.months.prevSingular"),
|
||||||
futureNear: "Mois suivant",
|
futureNear: t("entity.calendar.months.nextSingular"),
|
||||||
futureFar: "Année suivante"
|
futureFar: t("entity.calendar.years.nextSingular")
|
||||||
}
|
}
|
||||||
|
|
||||||
case "year":
|
case "year":
|
||||||
return {
|
return {
|
||||||
pastFar: "Décennie précédente",
|
pastFar: t("entity.calendar.decades.prevSingular"),
|
||||||
pastNear: "Année précédente",
|
pastNear: t("entity.calendar.years.prevSingular"),
|
||||||
futureNear: "Année suivante",
|
futureNear: t("entity.calendar.years.nextSingular"),
|
||||||
futureFar: "Décennie suivante"
|
futureFar: t("entity.calendar.decades.nextSingular")
|
||||||
}
|
}
|
||||||
|
|
||||||
case "decade":
|
case "decade":
|
||||||
return {
|
return {
|
||||||
pastFar: "Siècle précédent",
|
pastFar: t("entity.calendar.centuries.prevSingular"),
|
||||||
pastNear: "Décennie précédente",
|
pastNear: t("entity.calendar.decades.prevSingular"),
|
||||||
futureNear: "Décennie suivante",
|
futureNear: t("entity.calendar.decades.nextSingular"),
|
||||||
futureFar: "Siècle suivant"
|
futureFar: t("entity.calendar.centuries.nextSingular")
|
||||||
}
|
}
|
||||||
|
|
||||||
case "century":
|
case "century":
|
||||||
default:
|
default:
|
||||||
return {
|
return {
|
||||||
pastFar: "Millénaire précédent",
|
pastFar: t("entity.calendar.millenias.prevSingular"),
|
||||||
pastNear: "Siècle précédent",
|
pastNear: t("entity.calendar.centuries.prevSingular"),
|
||||||
futureNear: "Siècle suivant",
|
futureNear: t("entity.calendar.centuries.nextSingular"),
|
||||||
futureFar: "Millénaire suivant"
|
futureFar: t("entity.calendar.millenias.nextSingular")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -87,7 +87,9 @@ function handleGotoPreviousEventPage(position: "next" | "prev" = "next") {
|
|||||||
</UiButton>
|
</UiButton>
|
||||||
</UiTooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<UiTooltipContent>
|
<UiTooltipContent>
|
||||||
<p>Précédente page à évènements</p>
|
<p>
|
||||||
|
{{ $t('entity.calendar.event.prevPage') }}
|
||||||
|
</p>
|
||||||
</UiTooltipContent>
|
</UiTooltipContent>
|
||||||
</UiTooltip>
|
</UiTooltip>
|
||||||
</UiTooltipProvider>
|
</UiTooltipProvider>
|
||||||
@@ -106,7 +108,9 @@ function handleGotoPreviousEventPage(position: "next" | "prev" = "next") {
|
|||||||
</UiButton>
|
</UiButton>
|
||||||
</UiTooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<UiTooltipContent>
|
<UiTooltipContent>
|
||||||
<p>Prochaine page à évènements</p>
|
<p>
|
||||||
|
{{ $t('entity.calendar.event.nextPage') }}
|
||||||
|
</p>
|
||||||
</UiTooltipContent>
|
</UiTooltipContent>
|
||||||
</UiTooltip>
|
</UiTooltip>
|
||||||
</UiTooltipProvider>
|
</UiTooltipProvider>
|
||||||
|
|||||||
@@ -14,17 +14,9 @@ const isDefaultDate: ComputedRef<boolean> = computed<boolean>(() => areDatesIden
|
|||||||
<UiTooltipProvider :delay-duration="250">
|
<UiTooltipProvider :delay-duration="250">
|
||||||
<UiTooltip>
|
<UiTooltip>
|
||||||
<UiTooltipTrigger as-child>
|
<UiTooltipTrigger as-child>
|
||||||
<ClientOnly>
|
<UiButton size="sm" :disabled="isDefaultDate" @click="jumpToDefaultDate">
|
||||||
<UiButton size="sm" :disabled="isDefaultDate" @click="jumpToDefaultDate">
|
{{ $t('entity.calendar.date.today') }}
|
||||||
Aujourd'hui
|
</UiButton>
|
||||||
</UiButton>
|
|
||||||
|
|
||||||
<template #fallback>
|
|
||||||
<UiButton size="sm">
|
|
||||||
Aujourd'hui
|
|
||||||
</UiButton>
|
|
||||||
</template>
|
|
||||||
</ClientOnly>
|
|
||||||
</UiTooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<UiTooltipContent>
|
<UiTooltipContent>
|
||||||
<p>{{ defaultDateFormatted }}</p>
|
<p>{{ defaultDateFormatted }}</p>
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ const viewTypeTitle = computed(() => getViewTypeTitle(currentConfig.viewType))
|
|||||||
</UiButton>
|
</UiButton>
|
||||||
</UiDropdownMenuTrigger>
|
</UiDropdownMenuTrigger>
|
||||||
<UiDropdownMenuContent :side="'bottom'" :collision-padding="30">
|
<UiDropdownMenuContent :side="'bottom'" :collision-padding="30">
|
||||||
<UiDropdownMenuLabel>Mode d'affichage</UiDropdownMenuLabel>
|
<UiDropdownMenuLabel>
|
||||||
|
{{ $t('ui.displayMode') }}
|
||||||
|
</UiDropdownMenuLabel>
|
||||||
<UiDropdownMenuSeparator />
|
<UiDropdownMenuSeparator />
|
||||||
<UiDropdownMenuItem
|
<UiDropdownMenuItem
|
||||||
v-for="option in viewTypeOptions"
|
v-for="option in viewTypeOptions"
|
||||||
|
|||||||
@@ -30,7 +30,9 @@ function handleClose() {
|
|||||||
<span v-if="calendarSkeletonName">
|
<span v-if="calendarSkeletonName">
|
||||||
{{ calendarSkeletonName }}
|
{{ calendarSkeletonName }}
|
||||||
</span>
|
</span>
|
||||||
<span v-else>Nouveau calendrier</span>
|
<span v-else>
|
||||||
|
{{ $t('entity.calendar.createDialog.title') }}
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</UiAlertDialogTitle>
|
</UiAlertDialogTitle>
|
||||||
|
|
||||||
|
|||||||
@@ -53,10 +53,12 @@ function handleClosing() {
|
|||||||
@interact-outside="handleClosing"
|
@interact-outside="handleClosing"
|
||||||
@pointer-down-outside="handleClosing"
|
@pointer-down-outside="handleClosing"
|
||||||
>
|
>
|
||||||
<UiAlertDialogTitle> Êtes-vous sûr de supprimer ce calendrier ?</UiAlertDialogTitle>
|
<UiAlertDialogTitle>
|
||||||
|
{{ $t('entity.calendar.deleteDialog.title') }}
|
||||||
|
</UiAlertDialogTitle>
|
||||||
|
|
||||||
<UiAlertDialogDescription>
|
<UiAlertDialogDescription>
|
||||||
Les évènements ne seront plus accessibles et vous ne pourrez plus récupérer les données !
|
{{ $t('entity.calendar.deleteDialog.subtitle') }}
|
||||||
</UiAlertDialogDescription>
|
</UiAlertDialogDescription>
|
||||||
|
|
||||||
<form @submit.prevent="handleAction">
|
<form @submit.prevent="handleAction">
|
||||||
@@ -70,13 +72,13 @@ function handleClosing() {
|
|||||||
|
|
||||||
<footer class="flex gap-2 justify-between">
|
<footer class="flex gap-2 justify-between">
|
||||||
<UiButton type="button" size="sm" variant="outline" @click="handleClosing">
|
<UiButton type="button" size="sm" variant="outline" @click="handleClosing">
|
||||||
Retour
|
{{ $t('ui.action.back') }}
|
||||||
</UiButton>
|
</UiButton>
|
||||||
|
|
||||||
<div class="flex gap-2 justify-end">
|
<div class="flex gap-2 justify-end">
|
||||||
<Transition name="fade-delay">
|
<Transition name="fade-delay">
|
||||||
<UiButton v-if="isLoading" type="button" size="sm" variant="destructive">
|
<UiButton v-if="isLoading" type="button" size="sm" variant="destructive">
|
||||||
Annuler
|
{{ $t('ui.action.cancel') }}
|
||||||
</UiButton>
|
</UiButton>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
|
||||||
@@ -85,7 +87,7 @@ function handleClosing() {
|
|||||||
<PhCircleNotch v-if="isLoading" size="20" class="animate-spin"/>
|
<PhCircleNotch v-if="isLoading" size="20" class="animate-spin"/>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
|
||||||
Supprimer "{{ calendar?.name }}"
|
{{ $t('entity.deleteOne', { entity: calendar?.name }) }}
|
||||||
</UiButton>
|
</UiButton>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@@ -78,19 +78,22 @@ function handleFormCancel() {
|
|||||||
<UiTabsTrigger value="global" class="font-bold">
|
<UiTabsTrigger value="global" class="font-bold">
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
<PhWrench size="18" weight="fill" />
|
<PhWrench size="18" weight="fill" />
|
||||||
Général
|
|
||||||
|
{{ $t('entity.calendar.createDialog.tabs.general.title') }}
|
||||||
</div>
|
</div>
|
||||||
</UiTabsTrigger>
|
</UiTabsTrigger>
|
||||||
<UiTabsTrigger value="months" class="font-bold">
|
<UiTabsTrigger value="months" class="font-bold">
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
<PhCalendarDots size="18" weight="fill" />
|
<PhCalendarDots size="18" weight="fill" />
|
||||||
Mois de l'année
|
|
||||||
|
{{ $t('entity.calendar.createDialog.tabs.months.title') }}
|
||||||
</div>
|
</div>
|
||||||
</UiTabsTrigger>
|
</UiTabsTrigger>
|
||||||
<UiTabsTrigger value="today" class="font-bold">
|
<UiTabsTrigger value="today" class="font-bold">
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
<PhAlarm size="18" weight="fill" />
|
<PhAlarm size="18" weight="fill" />
|
||||||
Aujourd'hui
|
|
||||||
|
{{ $t('entity.calendar.createDialog.tabs.today.title') }}
|
||||||
</div>
|
</div>
|
||||||
</UiTabsTrigger>
|
</UiTabsTrigger>
|
||||||
</UiTabsList>
|
</UiTabsList>
|
||||||
@@ -116,7 +119,7 @@ function handleFormCancel() {
|
|||||||
|
|
||||||
<footer class="flex justify-end gap-2 mt-6">
|
<footer class="flex justify-end gap-2 mt-6">
|
||||||
<UiButton type="button" variant="destructive" @click="handleFormCancel">
|
<UiButton type="button" variant="destructive" @click="handleFormCancel">
|
||||||
Annuler
|
{{ $t('ui.action.cancel') }}
|
||||||
</UiButton>
|
</UiButton>
|
||||||
|
|
||||||
<UiButton type="submit" :disabled="!validSkeleton || isCreatingCalendar">
|
<UiButton type="submit" :disabled="!validSkeleton || isCreatingCalendar">
|
||||||
@@ -124,7 +127,7 @@ function handleFormCancel() {
|
|||||||
<PhCircleNotch v-if="isCreatingCalendar" size="20" class="opacity-50 animate-spin"/>
|
<PhCircleNotch v-if="isCreatingCalendar" size="20" class="opacity-50 animate-spin"/>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
|
||||||
Créer
|
{{ $t('ui.action.save') }}
|
||||||
</UiButton>
|
</UiButton>
|
||||||
</footer>
|
</footer>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ function handleCancel() {
|
|||||||
type="text"
|
type="text"
|
||||||
name="new-event-title"
|
name="new-event-title"
|
||||||
required
|
required
|
||||||
placeholder="Titre de l'évènement"
|
:placeholder="$t('entity.calendar.event.title')"
|
||||||
class="w-full -my-1 py-1 -mx-1 px-1 text-lg border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600"
|
class="w-full -my-1 py-1 -mx-1 px-1 text-lg border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
@@ -113,8 +113,7 @@ function handleCancel() {
|
|||||||
id="new-event-description"
|
id="new-event-description"
|
||||||
v-model="eventSkeleton.description"
|
v-model="eventSkeleton.description"
|
||||||
name="new-event-description"
|
name="new-event-description"
|
||||||
placeholder="Ajouter une description"
|
:placeholder="$t('entity.addDescription')" class="w-full -my-1 py-1 -mx-1 px-1 min-h-24 max-h-36 text-sm border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600"
|
||||||
class="w-full -my-1 py-1 -mx-1 px-1 min-h-24 max-h-36 text-sm border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -124,7 +123,7 @@ function handleCancel() {
|
|||||||
|
|
||||||
<CalendarInputRPGDate
|
<CalendarInputRPGDate
|
||||||
v-model:model-value="eventSkeleton.startDate"
|
v-model:model-value="eventSkeleton.startDate"
|
||||||
placeholder="Date de début"
|
:placeholder="$t('entity.calendar.date.start')"
|
||||||
:initial-date="props.date"
|
:initial-date="props.date"
|
||||||
:required="true"
|
:required="true"
|
||||||
/>
|
/>
|
||||||
@@ -133,7 +132,7 @@ function handleCancel() {
|
|||||||
|
|
||||||
<CalendarInputRPGDate
|
<CalendarInputRPGDate
|
||||||
v-model:model-value="eventSkeleton.endDate"
|
v-model:model-value="eventSkeleton.endDate"
|
||||||
placeholder="Date de fin"
|
:placeholder="$t('entity.calendar.date.end')"
|
||||||
:initial-date="props.date"
|
:initial-date="props.date"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -143,7 +142,7 @@ function handleCancel() {
|
|||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<PhTag size="18" weight="fill" />
|
<PhTag size="18" weight="fill" />
|
||||||
|
|
||||||
<CalendarInputEventCategory v-model="eventSkeleton.category" placeholder="Ajouter une catégorie principale" />
|
<CalendarInputEventCategory v-model="eventSkeleton.category" :placeholder="$t('entity.category.addPrimary')" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -151,7 +150,7 @@ function handleCancel() {
|
|||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<PhTag size="18" weight="fill" />
|
<PhTag size="18" weight="fill" />
|
||||||
|
|
||||||
<CalendarInputEventCategories v-model="eventSkeleton.secondaryCategories" placeholder="Ajouter des catégories secondaires" />
|
<CalendarInputEventCategories v-model="eventSkeleton.secondaryCategories" :placeholder="$t('entity.category.addSecondaries')" />
|
||||||
</div>
|
</div>
|
||||||
</div> -->
|
</div> -->
|
||||||
|
|
||||||
@@ -164,7 +163,7 @@ function handleCancel() {
|
|||||||
v-model="eventSkeleton.location"
|
v-model="eventSkeleton.location"
|
||||||
type="text"
|
type="text"
|
||||||
name="new-event-location"
|
name="new-event-location"
|
||||||
placeholder="Ajouter un endroit"
|
:placeholder="$t('entity.calendar.event.addLocation')"
|
||||||
class="w-full -my-1 py-2 px-2 text-sm border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600">
|
class="w-full -my-1 py-2 px-2 text-sm border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -178,10 +177,10 @@ function handleCancel() {
|
|||||||
<UiSwitch id="new-event-visibility" v-model:checked="eventSkeleton.hidden" />
|
<UiSwitch id="new-event-visibility" v-model:checked="eventSkeleton.hidden" />
|
||||||
<UiLabel for="new-event-visibility">
|
<UiLabel for="new-event-visibility">
|
||||||
<template v-if="!eventSkeleton.hidden">
|
<template v-if="!eventSkeleton.hidden">
|
||||||
Évènement visible
|
{{ $t('entity.calendar.event.isPublic') }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
Évènement caché
|
{{ $t('entity.calendar.event.isHidden') }}
|
||||||
</template>
|
</template>
|
||||||
</UiLabel>
|
</UiLabel>
|
||||||
</div>
|
</div>
|
||||||
@@ -197,7 +196,7 @@ function handleCancel() {
|
|||||||
<div class="flex gap-2 justify-end">
|
<div class="flex gap-2 justify-end">
|
||||||
<Transition name="fade-delay">
|
<Transition name="fade-delay">
|
||||||
<UiButton v-if="isLoading" type="button" size="sm" variant="destructive" @click.prevent="handleCancel">
|
<UiButton v-if="isLoading" type="button" size="sm" variant="destructive" @click.prevent="handleCancel">
|
||||||
Annuler
|
{{ $t('ui.action.cancel') }}
|
||||||
</UiButton>
|
</UiButton>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
|
||||||
@@ -206,7 +205,7 @@ function handleCancel() {
|
|||||||
<PhCircleNotch v-if="isLoading" size="20" class="opacity-50 animate-spin"/>
|
<PhCircleNotch v-if="isLoading" size="20" class="opacity-50 animate-spin"/>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
|
||||||
Sauvegarder
|
{{ $t('ui.action.save') }}
|
||||||
</UiButton>
|
</UiButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -69,10 +69,10 @@ function handleCancel(): void {
|
|||||||
@interact-outside="handleClosing"
|
@interact-outside="handleClosing"
|
||||||
@pointer-down-outside="handleClosing"
|
@pointer-down-outside="handleClosing"
|
||||||
>
|
>
|
||||||
<UiAlertDialogTitle> Supprimer l'évènement</UiAlertDialogTitle>
|
<UiAlertDialogTitle>{{ $t('entity.calendar.event.deleteDialog.title') }}</UiAlertDialogTitle>
|
||||||
|
|
||||||
<UiAlertDialogDescription>
|
<UiAlertDialogDescription>
|
||||||
Les données associés à cet évènement seront supprimées et vous ne pourrez plus les récupérer !
|
{{ $t('entity.calendar.event.deleteDialog.subtitle') }}
|
||||||
</UiAlertDialogDescription>
|
</UiAlertDialogDescription>
|
||||||
|
|
||||||
<form @submit.prevent="handleAction">
|
<form @submit.prevent="handleAction">
|
||||||
@@ -86,13 +86,13 @@ function handleCancel(): void {
|
|||||||
|
|
||||||
<footer class="flex gap-2 justify-between">
|
<footer class="flex gap-2 justify-between">
|
||||||
<UiButton type="button" size="sm" variant="outline" @click="() => isDeleteEventModalOpen = false">
|
<UiButton type="button" size="sm" variant="outline" @click="() => isDeleteEventModalOpen = false">
|
||||||
Retour
|
{{ $t('ui.action.back') }}
|
||||||
</UiButton>
|
</UiButton>
|
||||||
|
|
||||||
<div class="flex gap-2 justify-end">
|
<div class="flex gap-2 justify-end">
|
||||||
<Transition name="fade-delay">
|
<Transition name="fade-delay">
|
||||||
<UiButton v-if="isLoading" type="button" size="sm" variant="destructive" @click.prevent="handleCancel">
|
<UiButton v-if="isLoading" type="button" size="sm" variant="destructive" @click.prevent="handleCancel">
|
||||||
Annuler
|
{{ $t('ui.action.cancel') }}
|
||||||
</UiButton>
|
</UiButton>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ function handleCancel(): void {
|
|||||||
<PhCircleNotch v-if="isLoading" size="20" class="animate-spin"/>
|
<PhCircleNotch v-if="isLoading" size="20" class="animate-spin"/>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
|
||||||
Supprimer
|
{{ $t('ui.action.delete') }}
|
||||||
</UiButton>
|
</UiButton>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@@ -70,10 +70,12 @@ function handleCancel() {
|
|||||||
@pointer-down-outside="(e) => e.preventDefault()"
|
@pointer-down-outside="(e) => e.preventDefault()"
|
||||||
>
|
>
|
||||||
<header class="pl-8 grid gap-y-2">
|
<header class="pl-8 grid gap-y-2">
|
||||||
<UiDialogTitle> Modifier l'évènement</UiDialogTitle>
|
<UiDialogTitle>
|
||||||
|
{{ $t('entity.calendar.event.editDialog.title') }}
|
||||||
|
</UiDialogTitle>
|
||||||
|
|
||||||
<UiDialogDescription>
|
<UiDialogDescription>
|
||||||
Mettre à jour les données de l'évènement
|
{{ $t('entity.calendar.event.editDialog.subtitle') }}
|
||||||
</UiDialogDescription>
|
</UiDialogDescription>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
@@ -89,7 +91,7 @@ function handleCancel() {
|
|||||||
type="text"
|
type="text"
|
||||||
name="new-event-title"
|
name="new-event-title"
|
||||||
required
|
required
|
||||||
placeholder="Titre de l'évènement"
|
:placeholder="$t('entity.calendar.event.title')"
|
||||||
class="w-full -my-1 py-1 -mx-1 px-1 text-lg border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600"
|
class="w-full -my-1 py-1 -mx-1 px-1 text-lg border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
@@ -100,7 +102,7 @@ function handleCancel() {
|
|||||||
id="new-event-description"
|
id="new-event-description"
|
||||||
v-model="eventSkeleton.description"
|
v-model="eventSkeleton.description"
|
||||||
name="new-event-description"
|
name="new-event-description"
|
||||||
placeholder="Ajouter une description"
|
:placeholder="$t('entity.addDescription')"
|
||||||
class="w-full -my-1 py-1 -mx-1 px-1 min-h-24 max-h-36 text-sm border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600"
|
class="w-full -my-1 py-1 -mx-1 px-1 min-h-24 max-h-36 text-sm border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -111,7 +113,7 @@ function handleCancel() {
|
|||||||
|
|
||||||
<CalendarInputRPGDate
|
<CalendarInputRPGDate
|
||||||
v-model:model-value="eventSkeleton.startDate"
|
v-model:model-value="eventSkeleton.startDate"
|
||||||
placeholder="Date de début"
|
:placeholder="$t('entity.calendar.date.start')"
|
||||||
:initial-date="lastActiveEvent?.startDate"
|
:initial-date="lastActiveEvent?.startDate"
|
||||||
:required="true"
|
:required="true"
|
||||||
/>
|
/>
|
||||||
@@ -120,7 +122,7 @@ function handleCancel() {
|
|||||||
|
|
||||||
<CalendarInputRPGDate
|
<CalendarInputRPGDate
|
||||||
v-model:model-value="eventSkeleton.endDate"
|
v-model:model-value="eventSkeleton.endDate"
|
||||||
placeholder="Date de fin"
|
:placeholder="$t('entity.calendar.date.end')"
|
||||||
:initial-date="lastActiveEvent?.endDate"
|
:initial-date="lastActiveEvent?.endDate"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -141,7 +143,7 @@ function handleCancel() {
|
|||||||
<PhTag size="18" weight="fill" />
|
<PhTag size="18" weight="fill" />
|
||||||
|
|
||||||
<div class="w-1/2">
|
<div class="w-1/2">
|
||||||
<CalendarInputEventCategories v-model="eventSkeleton.secondaryCategories" placeholder="Ajouter des catégories secondaires" />
|
<CalendarInputEventCategories v-model="eventSkeleton.secondaryCategories" :placeholder="Ajouter des catégories secondaires" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div> -->
|
</div> -->
|
||||||
@@ -155,7 +157,7 @@ function handleCancel() {
|
|||||||
v-model="eventSkeleton.location"
|
v-model="eventSkeleton.location"
|
||||||
type="text"
|
type="text"
|
||||||
name="new-event-location"
|
name="new-event-location"
|
||||||
placeholder="Ajouter un endroit"
|
:placeholder="$t('entity.calendar.event.addLocation')"
|
||||||
class="w-full -my-1 py-2 px-2 text-sm border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600">
|
class="w-full -my-1 py-2 px-2 text-sm border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -169,10 +171,10 @@ function handleCancel() {
|
|||||||
<UiSwitch id="new-event-visibility" v-model:checked="eventSkeleton.hidden" />
|
<UiSwitch id="new-event-visibility" v-model:checked="eventSkeleton.hidden" />
|
||||||
<UiLabel for="new-event-visibility">
|
<UiLabel for="new-event-visibility">
|
||||||
<template v-if="!eventSkeleton.hidden">
|
<template v-if="!eventSkeleton.hidden">
|
||||||
Évènement visible par tous
|
{{ $t('entity.calendar.event.isPublic') }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
Évènement caché
|
{{ $t('entity.calendar.event.isHidden') }}
|
||||||
</template>
|
</template>
|
||||||
</UiLabel>
|
</UiLabel>
|
||||||
</div>
|
</div>
|
||||||
@@ -189,7 +191,7 @@ function handleCancel() {
|
|||||||
<footer class="flex gap-2 justify-end">
|
<footer class="flex gap-2 justify-end">
|
||||||
<Transition name="fade-delay">
|
<Transition name="fade-delay">
|
||||||
<UiButton v-if="isLoading" type="button" size="sm" variant="destructive" @click.prevent="handleCancel">
|
<UiButton v-if="isLoading" type="button" size="sm" variant="destructive" @click.prevent="handleCancel">
|
||||||
Annuler
|
{{ $t('ui.action.cancel') }}
|
||||||
</UiButton>
|
</UiButton>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
|
||||||
@@ -198,7 +200,7 @@ function handleCancel() {
|
|||||||
<PhCircleNotch v-if="isLoading" size="20" class="animate-spin"/>
|
<PhCircleNotch v-if="isLoading" size="20" class="animate-spin"/>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
|
||||||
Enregistrer
|
{{ $t('ui.action.save') }}
|
||||||
</UiButton>
|
</UiButton>
|
||||||
</footer>
|
</footer>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -60,8 +60,8 @@ const filteredCategories = computed(() =>
|
|||||||
class="w-fit h-[33vh] p-0"
|
class="w-fit h-[33vh] p-0"
|
||||||
>
|
>
|
||||||
<UiCommand v-model="modelBuffer" v-model:searchTerm="searchTerm" :multiple="true">
|
<UiCommand v-model="modelBuffer" v-model:searchTerm="searchTerm" :multiple="true">
|
||||||
<UiCommandInput placeholder="Rechercher les catégories" />
|
<UiCommandInput :placeholder="$t('entity.category.search')" />
|
||||||
<UiCommandEmpty>Aucune catégorie trouvée.</UiCommandEmpty>
|
<UiCommandEmpty>{{ $t('entity.category.notFoundAny') }}</UiCommandEmpty>
|
||||||
<UiCommandList>
|
<UiCommandList>
|
||||||
<UiCommandGroup>
|
<UiCommandGroup>
|
||||||
<UiCommandItem
|
<UiCommandItem
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ const filteredCategories = computed(() =>
|
|||||||
class="w-fit h-[33vh] p-0"
|
class="w-fit h-[33vh] p-0"
|
||||||
>
|
>
|
||||||
<UiCommand v-model="model" v-model:searchTerm="searchTerm">
|
<UiCommand v-model="model" v-model:searchTerm="searchTerm">
|
||||||
<UiCommandInput placeholder="Rechercher les catégories" />
|
<UiCommandInput :placeholder="$t('entity.category.search')" />
|
||||||
<UiCommandEmpty>Aucune catégorie trouvée.</UiCommandEmpty>
|
<UiCommandEmpty>{{ $t('entity.category.notFoundAny') }}</UiCommandEmpty>
|
||||||
<UiCommandList>
|
<UiCommandList>
|
||||||
<UiCommandGroup>
|
<UiCommandGroup>
|
||||||
<UiCommandItem
|
<UiCommandItem
|
||||||
|
|||||||
@@ -67,10 +67,28 @@ useSortable(monthSortableList, model.value, { animation: 150, handle: ".handle"
|
|||||||
<template>
|
<template>
|
||||||
<div class="grid md:grid-cols-12 gap-4 items-center">
|
<div class="grid md:grid-cols-12 gap-4 items-center">
|
||||||
<div class="md:col-start-2 md:col-span-5">
|
<div class="md:col-start-2 md:col-span-5">
|
||||||
<UiInput id="new-month-name" ref="monthNameRef" v-model="monthName" type="text" name="newMonthName" placeholder="Nom du mois" :class="cn({ 'border-red-600': monthNameIsTaken })"/>
|
<UiInput
|
||||||
|
id="new-month-name"
|
||||||
|
ref="monthNameRef"
|
||||||
|
v-model="monthName"
|
||||||
|
type="text"
|
||||||
|
name="newMonthName"
|
||||||
|
:placeholder="$t('entity.calendar.months.inputName')"
|
||||||
|
:class="cn({ 'border-red-600': monthNameIsTaken })"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="md:col-span-5">
|
<div class="md:col-span-5">
|
||||||
<UiInput id="new-month-days" ref="monthDaysRef" v-model="monthDays" type="number" name="newMonthName" placeholder="Nombre de jours" min="0" step="1" class="invalid:border-red-600" />
|
<UiInput
|
||||||
|
id="new-month-days"
|
||||||
|
ref="monthDaysRef"
|
||||||
|
v-model="monthDays"
|
||||||
|
type="number"
|
||||||
|
name="newMonthName"
|
||||||
|
:placeholder="$t('entity.calendar.months.daysNb')"
|
||||||
|
min="0"
|
||||||
|
step="1"
|
||||||
|
class="invalid:border-red-600"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="md:col-span-1">
|
<div class="md:col-span-1">
|
||||||
<UiButton size="icon" class="rounded-full h-8 w-8" :disabled="!validNewMonth" @click.prevent="addMonthToModel">
|
<UiButton size="icon" class="rounded-full h-8 w-8" :disabled="!validNewMonth" @click.prevent="addMonthToModel">
|
||||||
@@ -78,7 +96,10 @@ useSortable(monthSortableList, model.value, { animation: 150, handle: ".handle"
|
|||||||
</UiButton>
|
</UiButton>
|
||||||
</div>
|
</div>
|
||||||
<div class="md:col-span-full">
|
<div class="md:col-span-full">
|
||||||
<div class="border-[1px] dark:border-slate-800 p-4 rounded-sm max-h-80 overflow-y-auto" :class="model.length ? 'md:grid md:grid-cols-12 md:gap-4 md:items-center' : ''">
|
<div
|
||||||
|
class="border-[1px] dark:border-slate-800 p-4 rounded-sm max-h-80 overflow-y-auto"
|
||||||
|
:class="model.length ? 'md:grid md:grid-cols-12 md:gap-4 md:items-center' : ''"
|
||||||
|
>
|
||||||
<div v-if="model.length" class="hidden md:block col-span-1">
|
<div v-if="model.length" class="hidden md:block col-span-1">
|
||||||
<ul class="grid gap-y-4 justify-center">
|
<ul class="grid gap-y-4 justify-center">
|
||||||
<li v-for="(m, i) in model" :key="`num-${m.name}`">
|
<li v-for="(m, i) in model" :key="`num-${m.name}`">
|
||||||
@@ -88,6 +109,7 @@ useSortable(monthSortableList, model.value, { animation: 150, handle: ".handle"
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="md:col-span-11">
|
<div class="md:col-span-11">
|
||||||
<ul ref="monthSortableList" class="grid gap-y-2" :class="model.length ? 'visible' : 'absolute invisible'">
|
<ul ref="monthSortableList" class="grid gap-y-2" :class="model.length ? 'visible' : 'absolute invisible'">
|
||||||
<template v-if="model.length">
|
<template v-if="model.length">
|
||||||
@@ -102,12 +124,23 @@ useSortable(monthSortableList, model.value, { animation: 150, handle: ".handle"
|
|||||||
{{ m.name }}
|
{{ m.name }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="md:col-span-2">
|
<div class="md:col-span-2">
|
||||||
<UiInput :id="`month-days-n${i}`" v-model="m.days" class="bg-transparent border-none" type="number" :name="`monthDays-n${i}`" placeholder="Nombre de jours" min="0" />
|
<UiInput
|
||||||
|
:id="`month-days-n${i}`"
|
||||||
|
v-model="m.days"
|
||||||
|
class="bg-transparent border-none"
|
||||||
|
type="number"
|
||||||
|
:name="`monthDays-n${i}`"
|
||||||
|
:placeholder="$t('entity.calendar.months.daysNb')"
|
||||||
|
min="0"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="md:col-span-1">
|
<div class="md:col-span-1">
|
||||||
jour(s)
|
{{ $t('entity.calendar.months.daysMaybePlural') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="md:col-start-12">
|
<div class="md:col-start-12">
|
||||||
<UiTooltipProvider>
|
<UiTooltipProvider>
|
||||||
<UiTooltip>
|
<UiTooltip>
|
||||||
@@ -117,7 +150,9 @@ useSortable(monthSortableList, model.value, { animation: 150, handle: ".handle"
|
|||||||
</UiButton>
|
</UiButton>
|
||||||
</UiTooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<UiTooltipContent>
|
<UiTooltipContent>
|
||||||
<p>Supprimer {{ m.name }} du calendrier</p>
|
<p>
|
||||||
|
{{ $t('entity.calendar.months.deleteOne', { month: m.name }) }}
|
||||||
|
</p>
|
||||||
</UiTooltipContent>
|
</UiTooltipContent>
|
||||||
</UiTooltip>
|
</UiTooltip>
|
||||||
</UiTooltipProvider>
|
</UiTooltipProvider>
|
||||||
@@ -127,7 +162,9 @@ useSortable(monthSortableList, model.value, { animation: 150, handle: ".handle"
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="!model.length">
|
<template v-if="!model.length">
|
||||||
<p class="col-span-12 text-lg text-center italic opacity-50">Aucun mois pour l'instant</p>
|
<p class="col-span-12 text-lg text-center italic opacity-50">
|
||||||
|
{{ $t('entity.calendar.months.none') }}
|
||||||
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ watch(model.value, (n, _o) => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex gap-2 items-stretch">
|
<div class="flex gap-2 items-stretch">
|
||||||
<UiInput id="new-month-current-day" v-model="model.day" type="number" name="newMonthCurrentDay" placeholder="Jour" min="1" step="1" class="invalid:border-red-600" />
|
<UiInput id="new-month-current-day" v-model="model.day" type="number" name="newMonthCurrentDay" :placeholder="$t('entity.calendar.months.daysNameSingular')" min="1" step="1" class="invalid:border-red-600" />
|
||||||
|
|
||||||
<UiDropdownMenu>
|
<UiDropdownMenu>
|
||||||
<UiDropdownMenuTrigger as-child :disabled="props.availableMonths.length < 1">
|
<UiDropdownMenuTrigger as-child :disabled="props.availableMonths.length < 1">
|
||||||
@@ -41,18 +41,20 @@ watch(model.value, (n, _o) => {
|
|||||||
<PhCalendarBlank size="18" weight="fill" />
|
<PhCalendarBlank size="18" weight="fill" />
|
||||||
|
|
||||||
<template v-if="props.availableMonths.length < 1">
|
<template v-if="props.availableMonths.length < 1">
|
||||||
Aucun mois disponible
|
{{ $t('entity.calendar.months.noneAvailable') }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="model.month && typeof model.month === 'number'">
|
<template v-else-if="model.month && typeof model.month === 'number'">
|
||||||
{{ props.availableMonths[model.month - 1].name }}
|
{{ props.availableMonths[model.month - 1].name }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
Choisir le mois
|
{{ $t('entity.calendar.months.chooseOne') }}
|
||||||
</template>
|
</template>
|
||||||
</UiButton>
|
</UiButton>
|
||||||
</UiDropdownMenuTrigger>
|
</UiDropdownMenuTrigger>
|
||||||
<UiDropdownMenuContent :side="'bottom'" :collision-padding="30">
|
<UiDropdownMenuContent :side="'bottom'" :collision-padding="30">
|
||||||
<UiDropdownMenuLabel>Mois disponibles</UiDropdownMenuLabel>
|
<UiDropdownMenuLabel>
|
||||||
|
{{ $t('entity.calendar.months.available') }}
|
||||||
|
</UiDropdownMenuLabel>
|
||||||
<UiDropdownMenuSeparator />
|
<UiDropdownMenuSeparator />
|
||||||
<UiDropdownMenuItem
|
<UiDropdownMenuItem
|
||||||
v-for="m in props.availableMonths"
|
v-for="m in props.availableMonths"
|
||||||
@@ -64,6 +66,6 @@ watch(model.value, (n, _o) => {
|
|||||||
</UiDropdownMenuContent>
|
</UiDropdownMenuContent>
|
||||||
</UiDropdownMenu>
|
</UiDropdownMenu>
|
||||||
|
|
||||||
<UiInput id="new-month-current-day" v-model="model.year" type="number" name="newMonthCurrentYear" placeholder="Année" step="1" class="invalid:border-red-600" />
|
<UiInput id="new-month-current-day" v-model="model.year" type="number" name="newMonthCurrentYear" :placeholder="$t('entity.calendar.years.nameSingular')" step="1" class="invalid:border-red-600" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -241,11 +241,11 @@ function handleCategorySelect(e: (Category)) {
|
|||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<VisuallyHidden>
|
<VisuallyHidden>
|
||||||
<UiDialogTitle> Recherche avancée </UiDialogTitle>
|
<UiDialogTitle> {{ $t('entity.advancedSearch.title') }} </UiDialogTitle>
|
||||||
</VisuallyHidden>
|
</VisuallyHidden>
|
||||||
<VisuallyHidden>
|
<VisuallyHidden>
|
||||||
<UiDialogDescription>
|
<UiDialogDescription>
|
||||||
Rechercher les données disponibles sur le calendrier
|
{{ $t('entity.advancedSearch.title') }}
|
||||||
</UiDialogDescription>
|
</UiDialogDescription>
|
||||||
</VisuallyHidden>
|
</VisuallyHidden>
|
||||||
|
|
||||||
@@ -256,7 +256,7 @@ function handleCategorySelect(e: (Category)) {
|
|||||||
id="search"
|
id="search"
|
||||||
v-model:model-value="searchQuery"
|
v-model:model-value="searchQuery"
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Rechercher le calendrier"
|
:placeholder="$t('entity.advancedSearch.ctaPlaceholder')"
|
||||||
class="pl-10 py-6 text-lg"
|
class="pl-10 py-6 text-lg"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
/>
|
/>
|
||||||
@@ -274,10 +274,10 @@ function handleCategorySelect(e: (Category)) {
|
|||||||
@update:model-value="handleEntitySwitch()"
|
@update:model-value="handleEntitySwitch()"
|
||||||
>
|
>
|
||||||
<UiToggleGroupItem value="events" aria-label="Uniquement les évènements">
|
<UiToggleGroupItem value="events" aria-label="Uniquement les évènements">
|
||||||
Évènements
|
{{ $t('entity.calendar.event.namePlural') }}
|
||||||
</UiToggleGroupItem>
|
</UiToggleGroupItem>
|
||||||
<UiToggleGroupItem value="characters" aria-label="Uniquement les personnages">
|
<UiToggleGroupItem value="characters" aria-label="Uniquement les personnages">
|
||||||
Personnages
|
{{ $t('entity.character.namePlural') }}
|
||||||
</UiToggleGroupItem>
|
</UiToggleGroupItem>
|
||||||
</UiToggleGroup>
|
</UiToggleGroup>
|
||||||
</div>
|
</div>
|
||||||
@@ -298,7 +298,7 @@ function handleCategorySelect(e: (Category)) {
|
|||||||
class="w-full"
|
class="w-full"
|
||||||
>
|
>
|
||||||
<ComboboxAnchor as-child>
|
<ComboboxAnchor as-child>
|
||||||
<ComboboxInput placeholder="Catégories" as-child>
|
<ComboboxInput :placeholder="$t('entity.category.namePlural')" as-child>
|
||||||
<UiTagsInputInput
|
<UiTagsInputInput
|
||||||
class="w-full px-3"
|
class="w-full px-3"
|
||||||
:class="selectedCategories.length > 0 ? 'mt-2' : ''"
|
:class="selectedCategories.length > 0 ? 'mt-2' : ''"
|
||||||
@@ -341,7 +341,7 @@ function handleCategorySelect(e: (Category)) {
|
|||||||
</UiButton>
|
</UiButton>
|
||||||
</UiTooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<UiTooltipContent>
|
<UiTooltipContent>
|
||||||
<p>Plus ancien</p>
|
<p>{{ $t('entity.advancedSearch.older') }}</p>
|
||||||
</UiTooltipContent>
|
</UiTooltipContent>
|
||||||
</UiTooltip>
|
</UiTooltip>
|
||||||
</UiTooltipProvider>
|
</UiTooltipProvider>
|
||||||
@@ -358,7 +358,7 @@ function handleCategorySelect(e: (Category)) {
|
|||||||
</UiButton>
|
</UiButton>
|
||||||
</UiTooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<UiTooltipContent>
|
<UiTooltipContent>
|
||||||
<p>Plus récent</p>
|
<p>{{ $t('entity.advancedSearch.newer') }}</p>
|
||||||
</UiTooltipContent>
|
</UiTooltipContent>
|
||||||
</UiTooltip>
|
</UiTooltip>
|
||||||
</UiTooltipProvider>
|
</UiTooltipProvider>
|
||||||
|
|||||||
@@ -16,9 +16,7 @@ defineEmits<{
|
|||||||
const { getRelativeString, defaultDate, getFormattedDateTitle } = useCalendar()
|
const { getRelativeString, defaultDate, getFormattedDateTitle } = useCalendar()
|
||||||
|
|
||||||
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 = computed<string | null>(() => props.event.endDate ? getRelativeString(props.event.startDate, props.event.endDate, "compact") : null)
|
||||||
? getRelativeString(props.event.startDate, props.event.endDate, "compact")
|
|
||||||
: null
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -53,8 +51,14 @@ const dateDuration: string | null = props.event.endDate
|
|||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<p class="font-semibold text-sm opacity-75">
|
<p class="font-semibold text-sm opacity-75">
|
||||||
Du {{ getFormattedDateTitle(event.startDate, true) }} au
|
{{
|
||||||
{{ getFormattedDateTitle(event.endDate, true) }}
|
$t('entity.calendar.date.fromTo',
|
||||||
|
{
|
||||||
|
startDate: getFormattedDateTitle(event.startDate, true),
|
||||||
|
endDate: getFormattedDateTitle(event.endDate, true)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}}
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
<div v-if="event.hidden" class="flex justify-end">
|
<div v-if="event.hidden" class="flex justify-end">
|
||||||
@@ -62,11 +66,13 @@ const dateDuration: string | null = props.event.endDate
|
|||||||
<UiTooltip>
|
<UiTooltip>
|
||||||
<UiTooltipTrigger as-child>
|
<UiTooltipTrigger as-child>
|
||||||
<UiBadge class="flex gap-1">
|
<UiBadge class="flex gap-1">
|
||||||
<PhEye size="16" weight="fill" /> Évènement privé
|
<PhEye size="16" weight="fill" /> {{ $t('entity.calendar.event.isHidden') }}
|
||||||
</UiBadge>
|
</UiBadge>
|
||||||
</UiTooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<UiTooltipContent>
|
<UiTooltipContent>
|
||||||
<p>Cet évènement est uniquement visible pour vous</p>
|
<p>
|
||||||
|
{{ $t('entity.calendar.event.hiddenTooltip') }}
|
||||||
|
</p>
|
||||||
</UiTooltipContent>
|
</UiTooltipContent>
|
||||||
</UiTooltip>
|
</UiTooltip>
|
||||||
</UiTooltipProvider>
|
</UiTooltipProvider>
|
||||||
@@ -84,7 +90,7 @@ const dateDuration: string | null = props.event.endDate
|
|||||||
</p>
|
</p>
|
||||||
<template v-if="dateDuration">
|
<template v-if="dateDuration">
|
||||||
<p class="w-fit text-sm italic opacity-75 flex items-center gap-1">
|
<p class="w-fit text-sm italic opacity-75 flex items-center gap-1">
|
||||||
<PhHourglassMedium size="16" weight="fill" /> Pendant {{ dateDuration }}
|
<PhHourglassMedium size="16" weight="fill" /> {{ $t('entity.calendar.date.while', { duration: dateDuration } )}}
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -34,7 +34,9 @@ function handleMenuItemAction(actionType: SidebarMenuActionType) {
|
|||||||
</UiButton>
|
</UiButton>
|
||||||
</UiTooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<UiTooltipContent :side="'right'" :side-offset="6">
|
<UiTooltipContent :side="'right'" :side-offset="6">
|
||||||
<p>Mondes</p>
|
<p>
|
||||||
|
{{ $t('entity.world.namePlural') }}
|
||||||
|
</p>
|
||||||
</UiTooltipContent>
|
</UiTooltipContent>
|
||||||
</UiTooltip>
|
</UiTooltip>
|
||||||
</UiTooltipProvider>
|
</UiTooltipProvider>
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ const user = useSupabaseUser()
|
|||||||
const userMeta = computed(() => user.value?.user_metadata)
|
const userMeta = computed(() => user.value?.user_metadata)
|
||||||
const profileUrl: string = `${useRequestURL().origin}/my/`
|
const profileUrl: string = `${useRequestURL().origin}/my/`
|
||||||
|
|
||||||
|
const { locale, setLocale } = useI18n()
|
||||||
|
|
||||||
const menuOpened = ref<boolean>(false)
|
const menuOpened = ref<boolean>(false)
|
||||||
|
|
||||||
function closeMenu() {
|
function closeMenu() {
|
||||||
@@ -64,103 +66,140 @@ function pushRoute(to: AvailableRoutes) {
|
|||||||
:alt="userMeta?.full_name"
|
:alt="userMeta?.full_name"
|
||||||
referrerpolicy="no-referrer"
|
referrerpolicy="no-referrer"
|
||||||
/>
|
/>
|
||||||
<UiAvatarFallback>Me</UiAvatarFallback>
|
<UiAvatarFallback>
|
||||||
|
{{ $t('ui.sidebarMenu.avatarFallback') }}
|
||||||
|
</UiAvatarFallback>
|
||||||
</UiAvatar>
|
</UiAvatar>
|
||||||
<UiButton v-else variant="outline" size="icon">
|
<UiButton v-else variant="outline" size="icon">
|
||||||
<PhUserCircle size="18" />
|
<PhUserCircle size="18" />
|
||||||
</UiButton>
|
</UiButton>
|
||||||
</UiDropdownMenuTrigger>
|
</UiDropdownMenuTrigger>
|
||||||
<UiDropdownMenuContent class="w-fit p-0" :align="'start'" :side="'top'" :side-offset="10" :align-offset="25" :collision-padding="40">
|
|
||||||
|
|
||||||
|
<UiDropdownMenuContent class="w-72 p-0" :align="'start'" :side="'top'" :side-offset="10" :align-offset="25" :collision-padding="40">
|
||||||
<template v-if="user">
|
<template v-if="user">
|
||||||
<p class="p-2 text-xs opacity-75">Connecté en tant que {{ user?.email }}</p>
|
<p class="p-2 text-[.7em] opacity-75">
|
||||||
|
{{ $t('ui.greeting', { user: user?.email }) }}
|
||||||
|
</p>
|
||||||
|
|
||||||
<UiDropdownMenuItem class="flex gap-[.5ch] items-center rounded-none" @click="pushRoute('/my')">
|
<UiDropdownMenuItem class="flex gap-[.5ch] items-center rounded-none" @click="pushRoute('/my')">
|
||||||
<PhGlobeHemisphereWest size="20" weight="fill" />
|
<PhGlobeHemisphereWest size="20" weight="fill" />
|
||||||
<span>Mondes</span>
|
<span>
|
||||||
|
{{ $t('entity.world.namePlural') }}
|
||||||
|
</span>
|
||||||
</UiDropdownMenuItem>
|
</UiDropdownMenuItem>
|
||||||
|
|
||||||
<UiDropdownMenuSeparator />
|
<UiDropdownMenuSeparator />
|
||||||
|
</template>
|
||||||
|
|
||||||
<UiDropdownMenuSub>
|
<UiDropdownMenuSub>
|
||||||
<UiDropdownMenuSubTrigger class="p-0 rounded-none">
|
<UiDropdownMenuSubTrigger class="p-0 rounded-none">
|
||||||
<UiDropdownMenuItem class="flex gap-[.5ch] items-center pointer-events-none">
|
<UiDropdownMenuItem class="flex gap-[.5ch] items-center pointer-events-none">
|
||||||
<PhPalette size="20" weight="fill" />
|
<PhPalette size="20" weight="fill" />
|
||||||
<span>Apparence</span>
|
<span>
|
||||||
|
{{ $t('ui.sidebarMenu.appearance') }}
|
||||||
|
</span>
|
||||||
|
</UiDropdownMenuItem>
|
||||||
|
</UiDropdownMenuSubTrigger>
|
||||||
|
<UiDropdownMenuPortal>
|
||||||
|
<UiDropdownMenuSubContent>
|
||||||
|
<UiDropdownMenuItem
|
||||||
|
class="flex gap-[.5ch] items-center rounded-none transition-colors"
|
||||||
|
:class="cn({ 'text-emerald-600': $colorMode.preference === 'dark' })"
|
||||||
|
@select.prevent="$colorMode.preference = 'dark'"
|
||||||
|
>
|
||||||
|
<PhCheckCircle v-if="$colorMode.preference === 'dark'" size="20" weight="fill" />
|
||||||
|
<PhMoon v-else size="20" />
|
||||||
|
|
||||||
|
<span>
|
||||||
|
{{ $t('ui.dark') }}
|
||||||
|
</span>
|
||||||
</UiDropdownMenuItem>
|
</UiDropdownMenuItem>
|
||||||
</UiDropdownMenuSubTrigger>
|
<UiDropdownMenuItem
|
||||||
<UiDropdownMenuPortal>
|
class="flex gap-[.5ch] items-center rounded-none transition-colors"
|
||||||
|
:class="cn({ 'text-emerald-600': $colorMode.preference === 'light' })"
|
||||||
|
@select.prevent="$colorMode.preference = 'light'"
|
||||||
|
>
|
||||||
|
<PhCheckCircle v-if="$colorMode.preference === 'light'" size="20" weight="fill" />
|
||||||
|
<PhSun v-else size="20" />
|
||||||
|
|
||||||
|
<span>
|
||||||
|
{{ $t('ui.light') }}
|
||||||
|
</span>
|
||||||
|
</UiDropdownMenuItem>
|
||||||
|
<UiDropdownMenuItem
|
||||||
|
class="flex gap-[.5ch] items-center rounded-none transition-colors"
|
||||||
|
:class="cn({ 'text-emerald-600': $colorMode.preference === 'system' })"
|
||||||
|
@select.prevent="$colorMode.preference = 'system'"
|
||||||
|
>
|
||||||
|
<PhCheckCircle v-if="$colorMode.preference === 'system'" size="20" weight="fill" />
|
||||||
|
<PhLaptop v-else size="20" />
|
||||||
|
|
||||||
|
<span>
|
||||||
|
{{ $t('ui.system') }}
|
||||||
|
</span>
|
||||||
|
</UiDropdownMenuItem>
|
||||||
|
</UiDropdownMenuSubContent>
|
||||||
|
</UiDropdownMenuPortal>
|
||||||
|
</UiDropdownMenuSub>
|
||||||
|
|
||||||
|
<UiDropdownMenuSub>
|
||||||
|
<UiDropdownMenuSubTrigger class="p-0 rounded-none">
|
||||||
|
<UiDropdownMenuItem class="flex gap-[.5ch] items-center pointer-events-none">
|
||||||
|
<PhTranslate size="20" />
|
||||||
|
<span>
|
||||||
|
{{ $t('ui.sidebarMenu.language') }}
|
||||||
|
</span>
|
||||||
|
</UiDropdownMenuItem>
|
||||||
|
</UiDropdownMenuSubTrigger>
|
||||||
|
<UiDropdownMenuPortal>
|
||||||
|
<UiDropdownMenuSubContent>
|
||||||
<UiDropdownMenuSubContent>
|
<UiDropdownMenuSubContent>
|
||||||
<UiDropdownMenuItem
|
<UiDropdownMenuItem
|
||||||
class="flex gap-[.5ch] items-center rounded-none"
|
class="flex gap-[.5ch] items-center rounded-none transition-colors"
|
||||||
:class="cn({ 'text-emerald-600': $colorMode.preference === 'dark' })"
|
:class="cn({ 'text-emerald-600': locale === 'fr' })"
|
||||||
@select.prevent="$colorMode.preference = 'dark'"
|
@select.prevent="setLocale('fr')"
|
||||||
>
|
>
|
||||||
<PhCheckCircle v-if="$colorMode.preference === 'dark'" size="20" weight="fill" />
|
<PhCheckCircle v-if="locale === 'fr'" size="20" weight="fill" />
|
||||||
<PhMoon v-else size="20" />
|
<img v-else src="/images/flag-fr.png" width="20" alt="" loading="eager">
|
||||||
<span>Sombre</span>
|
<span>Français</span>
|
||||||
</UiDropdownMenuItem>
|
</UiDropdownMenuItem>
|
||||||
<UiDropdownMenuItem
|
<UiDropdownMenuItem
|
||||||
class="flex gap-[.5ch] items-center rounded-none"
|
class="flex gap-[.5ch] items-center rounded-none transition-colors"
|
||||||
:class="cn({ 'text-emerald-600': $colorMode.preference === 'light' })"
|
:class="cn({ 'text-emerald-600': locale === 'en' })"
|
||||||
@select.prevent="$colorMode.preference = 'light'"
|
@select.prevent="setLocale('en')"
|
||||||
>
|
>
|
||||||
<PhCheckCircle v-if="$colorMode.preference === 'light'" size="20" weight="fill" />
|
<PhCheckCircle v-if="locale === 'en'" size="20" weight="fill" />
|
||||||
<PhSun v-else size="20" />
|
<img v-else src="/images/flag-uk.png" width="20" alt="" loading="eager">
|
||||||
<span>Clair</span>
|
<span>English</span>
|
||||||
</UiDropdownMenuItem>
|
|
||||||
<UiDropdownMenuItem
|
|
||||||
class="flex gap-[.5ch] items-center rounded-none"
|
|
||||||
:class="cn({ 'text-emerald-600': $colorMode.preference === 'system' })"
|
|
||||||
@select.prevent="$colorMode.preference = 'system'"
|
|
||||||
>
|
|
||||||
<PhCheckCircle v-if="$colorMode.preference === 'system'" size="20" weight="fill" />
|
|
||||||
<PhLaptop v-else size="20" />
|
|
||||||
<span>Système</span>
|
|
||||||
</UiDropdownMenuItem>
|
</UiDropdownMenuItem>
|
||||||
</UiDropdownMenuSubContent>
|
</UiDropdownMenuSubContent>
|
||||||
</UiDropdownMenuPortal>
|
</UiDropdownMenuSubContent>
|
||||||
</UiDropdownMenuSub>
|
</UiDropdownMenuPortal>
|
||||||
|
</UiDropdownMenuSub>
|
||||||
|
|
||||||
<UiDropdownMenuSub>
|
<UiDropdownMenuSeparator />
|
||||||
<UiDropdownMenuSubTrigger class="p-0 rounded-none">
|
|
||||||
<UiDropdownMenuItem class="flex gap-[.5ch] items-center pointer-events-none">
|
|
||||||
<PhTranslate size="20" />
|
|
||||||
<span>Langage</span>
|
|
||||||
</UiDropdownMenuItem>
|
|
||||||
</UiDropdownMenuSubTrigger>
|
|
||||||
<UiDropdownMenuPortal>
|
|
||||||
<UiDropdownMenuSubContent>
|
|
||||||
<UiDropdownMenuSubContent>
|
|
||||||
<UiDropdownMenuItem class="flex gap-[.5ch] items-center rounded-none">
|
|
||||||
<span>Français</span>
|
|
||||||
</UiDropdownMenuItem>
|
|
||||||
<UiDropdownMenuItem class="flex gap-[.5ch] items-center rounded-none">
|
|
||||||
<span>English</span>
|
|
||||||
</UiDropdownMenuItem>
|
|
||||||
</UiDropdownMenuSubContent>
|
|
||||||
</UiDropdownMenuSubContent>
|
|
||||||
</UiDropdownMenuPortal>
|
|
||||||
</UiDropdownMenuSub>
|
|
||||||
|
|
||||||
<UiDropdownMenuSeparator />
|
|
||||||
|
|
||||||
|
<template v-if="user">
|
||||||
<UiDropdownMenuItem class="flex gap-[.5ch] items-center rounded-none" @click="pushRoute('/my/settings')">
|
<UiDropdownMenuItem class="flex gap-[.5ch] items-center rounded-none" @click="pushRoute('/my/settings')">
|
||||||
<PhGear size="20" weight="fill" />
|
<PhGear size="20" weight="fill" />
|
||||||
<span>Compte</span>
|
<span>
|
||||||
|
{{ $t('ui.sidebarMenu.account') }}
|
||||||
|
</span>
|
||||||
</UiDropdownMenuItem>
|
</UiDropdownMenuItem>
|
||||||
<UiDropdownMenuItem class="flex gap-[.5ch] items-center rounded-none" @click="handleLogout">
|
<UiDropdownMenuItem class="flex gap-[.5ch] items-center rounded-none" @click="handleLogout">
|
||||||
<PhSignOut size="20" weight="fill" />
|
<PhSignOut size="20" weight="fill" />
|
||||||
<span>Déconnexion</span>
|
<span>
|
||||||
|
{{ $t('ui.sidebarMenu.logout') }}
|
||||||
|
</span>
|
||||||
</UiDropdownMenuItem>
|
</UiDropdownMenuItem>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else>
|
<UiDropdownMenuItem v-if="!user" class="flex gap-[.5ch] items-center rounded-none" @click="handleGoogleLogin">
|
||||||
<UiDropdownMenuItem class="flex gap-[.5ch] items-center rounded-none" @click="handleGoogleLogin">
|
<PhGear size="20" weight="fill" />
|
||||||
<PhGear size="20" weight="fill" />
|
<span>
|
||||||
<span>Connexion</span>
|
{{ $t('ui.sidebarMenu.login') }}
|
||||||
</UiDropdownMenuItem>
|
</span>
|
||||||
</template>
|
</UiDropdownMenuItem>
|
||||||
</UiDropdownMenuContent>
|
</UiDropdownMenuContent>
|
||||||
</UiDropdownMenu>
|
</UiDropdownMenu>
|
||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
|
|||||||
340
i18n.config.ts
Normal file
340
i18n.config.ts
Normal file
@@ -0,0 +1,340 @@
|
|||||||
|
export default defineI18nConfig(() => ({
|
||||||
|
legacy: false,
|
||||||
|
availableLocales: ["fr", "en"],
|
||||||
|
fallbackLocale: "fr",
|
||||||
|
messages: {
|
||||||
|
en: {
|
||||||
|
head: {
|
||||||
|
title: "Fantasy calendars for TTRPGs",
|
||||||
|
description: "Tools for players and game masters to help them visualize fantasy worlds better.",
|
||||||
|
},
|
||||||
|
ui: {
|
||||||
|
action: {
|
||||||
|
back: "Back",
|
||||||
|
cancel: "Cancel",
|
||||||
|
save: "Save",
|
||||||
|
delete: "Delete",
|
||||||
|
edit: "Edit",
|
||||||
|
},
|
||||||
|
greeting: "Connected as {user}",
|
||||||
|
sidebarMenu: {
|
||||||
|
appearance: "Appearance",
|
||||||
|
language: "Language",
|
||||||
|
account: "Account",
|
||||||
|
login: "Log in",
|
||||||
|
logout: "Log out",
|
||||||
|
avatarFallback: "Profile",
|
||||||
|
},
|
||||||
|
dark: "Dark",
|
||||||
|
light: "Light",
|
||||||
|
system: "System",
|
||||||
|
displayMode: "Display mode"
|
||||||
|
},
|
||||||
|
common: {
|
||||||
|
title: "Title"
|
||||||
|
},
|
||||||
|
entity: {
|
||||||
|
category: {
|
||||||
|
nameSingular: "Category",
|
||||||
|
namePlural: "Categories",
|
||||||
|
search: "Search categories",
|
||||||
|
notFoundAny: "No categories found.",
|
||||||
|
addPrimary: "Add a primary category",
|
||||||
|
addSecondaries: "Add secondary categories"
|
||||||
|
},
|
||||||
|
addDescription: "Add a description",
|
||||||
|
deleteOne: "Delete \"{entity}\"",
|
||||||
|
advancedSearch: {
|
||||||
|
title: "Advanced search",
|
||||||
|
subtitle: "Search through calendar and world data",
|
||||||
|
older: "Older",
|
||||||
|
newer: "Newer",
|
||||||
|
ctaPlaceholder: "Search an event, characters…"
|
||||||
|
},
|
||||||
|
world: {
|
||||||
|
nameSingular: "World",
|
||||||
|
namePlural: "Worlds",
|
||||||
|
},
|
||||||
|
calendar: {
|
||||||
|
nameSingular: "Calendar",
|
||||||
|
namePlural: "Calendars",
|
||||||
|
addSingle: "Add a calendar",
|
||||||
|
notFoundForWorld: "No calendar for this world… yet !",
|
||||||
|
isLoading: "Calendar is loading…",
|
||||||
|
date: {
|
||||||
|
start: "Start date",
|
||||||
|
end: "End date",
|
||||||
|
afterTomorrow: "In 2 days",
|
||||||
|
tomorrow: "Tomorrow",
|
||||||
|
today: "Today",
|
||||||
|
yesterday: "Yesterday",
|
||||||
|
beforeYesterday: "2 days ago",
|
||||||
|
fromTo: "From {startDate} to {endDate}",
|
||||||
|
while: "During {duration}",
|
||||||
|
xDaysNext: "In {days} days",
|
||||||
|
xMonthsNext: "In {months} month(s)",
|
||||||
|
xYearsNext: "In {years} year(s)",
|
||||||
|
xYearsAndMonthsNext: "In {years} year(s) and {months} month(s)",
|
||||||
|
xDaysNextCompact: "{days} days",
|
||||||
|
xMonthsNextCompact: "{months} month(s)",
|
||||||
|
xYearsNextCompact: "{years} year(s)",
|
||||||
|
xYearsAndMonthsNextCompact: "{years} year(s) and {months} month(s)",
|
||||||
|
xDaysAgo: "{days} days ago",
|
||||||
|
xMonthsAgo: "{months} month(s) ago",
|
||||||
|
xYearsAgo: "{years} year(s) ago",
|
||||||
|
xYearsAndMonthsAgo: "{years} year(s) and {months} month(s) ago",
|
||||||
|
xDaysAgoCompact: "{days} days",
|
||||||
|
xMonthsAgoCompact: "{months} month(s)",
|
||||||
|
xYearsAgoCompact: "{years} year(s)",
|
||||||
|
xYearsAndMonthsAgoCompact: "{years} year(s) and {months} month(s)",
|
||||||
|
},
|
||||||
|
event: {
|
||||||
|
nameSingular: "Event",
|
||||||
|
namePlural: "Events",
|
||||||
|
title: "Event title",
|
||||||
|
isStart: "Start",
|
||||||
|
isEnd: "End",
|
||||||
|
isHidden: "Hidden event",
|
||||||
|
isPublic: "Public event",
|
||||||
|
hiddenTooltip: "This event is visible only to game masters.",
|
||||||
|
addLocation: "Add a place",
|
||||||
|
prevPage: "Previous page with events",
|
||||||
|
nextPage: "Next page with events",
|
||||||
|
editDialog: {
|
||||||
|
title: "Edit event",
|
||||||
|
subtitle: "Update event data",
|
||||||
|
},
|
||||||
|
deleteDialog: {
|
||||||
|
title: "Delete this event",
|
||||||
|
subtitle: "Data associated with this event will be lost and you won't be able to retrieve it !",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
createDialog: {
|
||||||
|
title: "New calendar",
|
||||||
|
tabs: {
|
||||||
|
general: {
|
||||||
|
title: "General",
|
||||||
|
},
|
||||||
|
months: {
|
||||||
|
title: "Months",
|
||||||
|
},
|
||||||
|
today: {
|
||||||
|
title: "Today",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteDialog: {
|
||||||
|
title: "Are you sure you want to delete this calendar ?",
|
||||||
|
subtitle: "Its events won't be accessible anymore and you won't be able to retrieve the deleted data !",
|
||||||
|
},
|
||||||
|
millennia: {
|
||||||
|
nameSingular: "Millennia",
|
||||||
|
nextSingular: "Next millennia",
|
||||||
|
prevSingular: "Last millennia",
|
||||||
|
},
|
||||||
|
centuries: {
|
||||||
|
nameSingular: "Century",
|
||||||
|
nextSingular: "Next century",
|
||||||
|
prevSingular: "Last century",
|
||||||
|
},
|
||||||
|
decades: {
|
||||||
|
nameSingular: "Decade",
|
||||||
|
nextSingular: "Next decade",
|
||||||
|
prevSingular: "Last decade",
|
||||||
|
},
|
||||||
|
years: {
|
||||||
|
nameSingular: "Year",
|
||||||
|
nextSingular: "Next year",
|
||||||
|
prevSingular: "Last year",
|
||||||
|
},
|
||||||
|
months: {
|
||||||
|
nameSingular: "Month",
|
||||||
|
nextSingular: "Next month",
|
||||||
|
prevSingular: "Last month",
|
||||||
|
inputName: "Month's name",
|
||||||
|
daysNb: "Number of days",
|
||||||
|
daysNameSingular: "Day",
|
||||||
|
daysNamePlural: "Days",
|
||||||
|
daysMaybePlural: "day(s)",
|
||||||
|
available: "Months available",
|
||||||
|
none: "No months for now",
|
||||||
|
noneAvailable: "No months available",
|
||||||
|
chooseOne: "Choose a month",
|
||||||
|
deleteOne: "Remove {month} from this calendar"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
character: {
|
||||||
|
nameSingular: "Character",
|
||||||
|
namePlural: "Characters",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fr: {
|
||||||
|
head: {
|
||||||
|
title: "Calendriers fantasies pour JDR",
|
||||||
|
description: "Outils destinés aux joueurs et maîtres de jeux pour visualiser plus facilement leurs univers.",
|
||||||
|
},
|
||||||
|
ui: {
|
||||||
|
action: {
|
||||||
|
back: "Retour",
|
||||||
|
cancel: "Annuler",
|
||||||
|
save: "Sauvegarder",
|
||||||
|
delete: "Supprimer",
|
||||||
|
edit: "Modifier",
|
||||||
|
},
|
||||||
|
greeting: "Connecté en tant que {user}",
|
||||||
|
sidebarMenu: {
|
||||||
|
appearance: "Apparence",
|
||||||
|
language: "Langue",
|
||||||
|
account: "Compte",
|
||||||
|
login: "Connexion",
|
||||||
|
logout: "Déconnexion",
|
||||||
|
avatarFallback: "Profil",
|
||||||
|
},
|
||||||
|
dark: "Sombre",
|
||||||
|
light: "Clair",
|
||||||
|
system: "Système",
|
||||||
|
displayMode: "Mode d'affichage",
|
||||||
|
},
|
||||||
|
common: {
|
||||||
|
title: "Titre"
|
||||||
|
},
|
||||||
|
entity: {
|
||||||
|
category: {
|
||||||
|
nameSingular: "Catégorie",
|
||||||
|
namePlural: "Catégories",
|
||||||
|
search: "Rechercher les catégories",
|
||||||
|
notFoundAny: "Aucune catégorie trouvée.",
|
||||||
|
addPrimary: "Ajouter une catégorie principale",
|
||||||
|
addSecondaries: "Ajouter des catégories secondaires"
|
||||||
|
},
|
||||||
|
addDescription: "Ajouter une description",
|
||||||
|
deleteOne: "Supprimer \"{entity}\"",
|
||||||
|
advancedSearch: {
|
||||||
|
title: "Recherche avancée",
|
||||||
|
subtitle: "Rechercher les données disponibles sur le calendrier",
|
||||||
|
older: "Plus ancien",
|
||||||
|
newer: "Plus récent",
|
||||||
|
ctaPlaceholder: "Rechercher un évènement, personnage…"
|
||||||
|
},
|
||||||
|
world: {
|
||||||
|
nameSingular: "Monde",
|
||||||
|
namePlural: "Mondes",
|
||||||
|
},
|
||||||
|
calendar: {
|
||||||
|
nameSingular: "Calendriers",
|
||||||
|
namePlural: "Calendrier",
|
||||||
|
addSingle: "Ajouter un calendrier",
|
||||||
|
notFoundForWorld: "Aucun calendrier pour ce monde… pour l'instant !",
|
||||||
|
isLoading: "Chargement du calendrier…",
|
||||||
|
date: {
|
||||||
|
start: "Date de début",
|
||||||
|
end: "Date de fin",
|
||||||
|
afterTomorrow: "Après-demain",
|
||||||
|
tomorrow: "Demain",
|
||||||
|
today: "Aujourd'hui",
|
||||||
|
yesterday: "Hier",
|
||||||
|
beforeYesterday: "Avant-hier",
|
||||||
|
fromTo: "Du {startDate} au {endDate}",
|
||||||
|
while: "Pendant {duration}",
|
||||||
|
xDaysNext: "Dans {days} jours",
|
||||||
|
xMonthsNext: "Dans {months} mois",
|
||||||
|
xYearsNext: "Dans {years} an(s)",
|
||||||
|
xYearsAndMonthsNext: "Dans {years} an(s) et {months} mois",
|
||||||
|
xDaysNextCompact: "{days} jours",
|
||||||
|
xMonthsNextCompact: "{months} mois",
|
||||||
|
xYearsNextCompact: "{years} an(s)",
|
||||||
|
xYearsAndMonthsNextCompact: "{years} an(s) et {months} mois",
|
||||||
|
xDaysAgo: "Il y a {days} jours",
|
||||||
|
xMonthsAgo: "Il y a {months} mois",
|
||||||
|
xYearsAgo: "Il y a {years} an(s)",
|
||||||
|
xYearsAndMonthsAgo: "Il y a {years} an(s) et {months} mois",
|
||||||
|
xDaysAgoCompact: "{days} jours",
|
||||||
|
xMonthsAgoCompact: "{months} mois",
|
||||||
|
xYearsAgoCompact: "{years} an(s)",
|
||||||
|
xYearsAndMonthsAgoCompact: "{years} an(s) et {months} mois",
|
||||||
|
},
|
||||||
|
event: {
|
||||||
|
nameSingular: "Évènement",
|
||||||
|
namePlural: "Évènements",
|
||||||
|
title: "Titre de l'évènement",
|
||||||
|
isStart: "Début",
|
||||||
|
isEnd: "Fin",
|
||||||
|
isHidden: "Évènement privé",
|
||||||
|
isPublic: "Évènement public",
|
||||||
|
hiddenTooltip: "Cet évènement est uniquement visible pour les maîtres du jeu.",
|
||||||
|
addLocation: "Ajouter un endroit",
|
||||||
|
prevPage: "Précédente page à évènements",
|
||||||
|
nextPage: "Prochaine page à évènements",
|
||||||
|
editDialog: {
|
||||||
|
title: "Modifier l'évènement",
|
||||||
|
subtitle: "Mettre à jour les données de l'évènement",
|
||||||
|
},
|
||||||
|
deleteDialog: {
|
||||||
|
title: "Supprimer l'évènement",
|
||||||
|
subtitle: "Les données associés à cet évènement seront supprimées et vous ne pourrez plus les récupérer !",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
createDialog: {
|
||||||
|
title: "Nouveau calendrier",
|
||||||
|
tabs: {
|
||||||
|
general: {
|
||||||
|
title: "Général",
|
||||||
|
},
|
||||||
|
months: {
|
||||||
|
title: "Mois de l'année",
|
||||||
|
},
|
||||||
|
today: {
|
||||||
|
title: "Aujourd'hui",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteDialog: {
|
||||||
|
title: "Êtes-vous sûr de supprimer ce calendrier ?",
|
||||||
|
subtitle: "Les évènements ne seront plus accessibles et vous ne pourrez plus récupérer les données !",
|
||||||
|
},
|
||||||
|
millennia: {
|
||||||
|
nameSingular: "Millénaire",
|
||||||
|
nextSingular: "Millénaire suivant",
|
||||||
|
prevSingular: "Millénaire précédent",
|
||||||
|
},
|
||||||
|
centuries: {
|
||||||
|
nameSingular: "Siècle",
|
||||||
|
nextSingular: "Siècle suivant",
|
||||||
|
prevSingular: "Siècle précédent",
|
||||||
|
},
|
||||||
|
decades: {
|
||||||
|
nameSingular: "Décennie",
|
||||||
|
nextSingular: "Décennie suivante",
|
||||||
|
prevSingular: "Décennie précédente",
|
||||||
|
},
|
||||||
|
years: {
|
||||||
|
nameSingular: "Année",
|
||||||
|
nextSingular: "Année suivante",
|
||||||
|
prevSingular: "Année précédente",
|
||||||
|
},
|
||||||
|
months: {
|
||||||
|
nameSingular: "Mois",
|
||||||
|
nextSingular: "Mois suivant",
|
||||||
|
prevSingular: "Mois précédent",
|
||||||
|
inputName: "Nom du mois",
|
||||||
|
daysNb: "Nombre de jours",
|
||||||
|
daysNameSingular: "Jour",
|
||||||
|
daysNamePlural: "Jours",
|
||||||
|
daysMaybePlural: "jour(s)",
|
||||||
|
Singular: "Année",
|
||||||
|
available: "Mois disponibles",
|
||||||
|
none: "Aucun mois pour l'instant",
|
||||||
|
noneAvailable: "Aucun mois disponible",
|
||||||
|
chooseOne: "Choisir un mois",
|
||||||
|
deleteOne: "Supprimer {month} du calendrier"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
character: {
|
||||||
|
nameSingular: "Personnage",
|
||||||
|
namePlural: "Personnages",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
@@ -9,10 +9,21 @@ export default defineNuxtConfig({
|
|||||||
"@nuxtjs/tailwindcss",
|
"@nuxtjs/tailwindcss",
|
||||||
"@nuxtjs/color-mode",
|
"@nuxtjs/color-mode",
|
||||||
"@nuxt/eslint",
|
"@nuxt/eslint",
|
||||||
"shadcn-nuxt"
|
"shadcn-nuxt",
|
||||||
|
"@nuxtjs/i18n"
|
||||||
],
|
],
|
||||||
css: ["~/assets/main.css"],
|
css: ["~/assets/main.css"],
|
||||||
|
|
||||||
|
i18n: {
|
||||||
|
vueI18n: "./i18n.config.ts",
|
||||||
|
detectBrowserLanguage: {
|
||||||
|
useCookie: true,
|
||||||
|
cookieKey: "tttools_lang",
|
||||||
|
redirectOn: "all",
|
||||||
|
alwaysRedirect: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
supabase: {
|
supabase: {
|
||||||
redirectOptions: {
|
redirectOptions: {
|
||||||
login: "/",
|
login: "/",
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nuxt/eslint": "^0.3.12",
|
"@nuxt/eslint": "^0.3.12",
|
||||||
|
"@nuxtjs/i18n": "^8.5.1",
|
||||||
"@phosphor-icons/vue": "^2.2.1",
|
"@phosphor-icons/vue": "^2.2.1",
|
||||||
"@pinia/nuxt": "^0.5.1",
|
"@pinia/nuxt": "^0.5.1",
|
||||||
"@vueuse/core": "^10.9.0",
|
"@vueuse/core": "^10.9.0",
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
useHead({
|
useHead({
|
||||||
title: "TTTools — Calendriers de JDR",
|
|
||||||
titleTemplate: null
|
titleTemplate: null
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<main class="p-8">
|
<main class="p-8">
|
||||||
|
<Head>
|
||||||
|
<Title>
|
||||||
|
TTTools — {{ $t('head.title') }}
|
||||||
|
</Title>
|
||||||
|
<Meta name="description" :content="$t('head.description')" />
|
||||||
|
</Head>
|
||||||
|
|
||||||
<Heading>TTTools</Heading>
|
<Heading>TTTools</Heading>
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -23,27 +23,27 @@ const { data: catData, pending: catPending } = await useLazyFetch("/api/calendar
|
|||||||
|
|
||||||
const cal = computed<Calendar>(() => calendarData?.value?.data as Calendar)
|
const cal = computed<Calendar>(() => calendarData?.value?.data as Calendar)
|
||||||
const categories = computed<Category[]>(() => catData?.value?.data as Category[])
|
const categories = computed<Category[]>(() => catData?.value?.data as Category[])
|
||||||
|
|
||||||
if (cal.value) {
|
|
||||||
useHead({
|
|
||||||
title: cal.value.name
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(cal, (n) => {
|
|
||||||
useHead({
|
|
||||||
title: n.name
|
|
||||||
})
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="calPending || catPending" class="h-full w-full grid place-items-center">
|
<div v-if="calPending || catPending" class="h-full w-full grid place-items-center">
|
||||||
|
<Head>
|
||||||
|
<Title>{{ $t("entity.calendar.nameSingular") }}</Title>
|
||||||
|
</Head>
|
||||||
|
|
||||||
<div class="grid gap-2 justify-items-center opacity-50">
|
<div class="grid gap-2 justify-items-center opacity-50">
|
||||||
<p>Chargement du calendrier</p>
|
<p>
|
||||||
|
{{ $t('entity.calendar.isLoading') }}
|
||||||
|
</p>
|
||||||
<PhCircleNotch size="50" class="animate-spin"/>
|
<PhCircleNotch size="50" class="animate-spin"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Calendar v-else-if="cal && categories" :calendar-data="cal" :categories />
|
<div v-else-if="cal && categories" class="h-full w-full">
|
||||||
|
<Head>
|
||||||
|
<Title>{{ cal.name }}</Title>
|
||||||
|
</Head>
|
||||||
|
|
||||||
|
<Calendar :calendar-data="cal" :categories />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -2,10 +2,6 @@
|
|||||||
import type { RealtimeChannel } from "@supabase/supabase-js"
|
import type { RealtimeChannel } from "@supabase/supabase-js"
|
||||||
import type { World } from "~/models/World";
|
import type { World } from "~/models/World";
|
||||||
|
|
||||||
useHead({
|
|
||||||
title: "Mondes"
|
|
||||||
})
|
|
||||||
|
|
||||||
const supabase = useSupabaseClient()
|
const supabase = useSupabaseClient()
|
||||||
|
|
||||||
const { data: res } = await useFetch("/api/worlds/query")
|
const { data: res } = await useFetch("/api/worlds/query")
|
||||||
@@ -85,12 +81,16 @@ onUnmounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<main class="p-8 after:fill-red-400">
|
<main class="p-8 after:fill-red-400">
|
||||||
|
<Head>
|
||||||
|
<Title>{{ $t("entity.world.namePlural") }}</Title>
|
||||||
|
</Head>
|
||||||
|
|
||||||
<Heading>{{ user?.user_metadata.full_name }}</Heading>
|
<Heading>{{ user?.user_metadata.full_name }}</Heading>
|
||||||
|
|
||||||
<section v-if="worlds" class="mt-4">
|
<section v-if="worlds" class="mt-4">
|
||||||
<h2 class="mb-4 text-lg font-bold">
|
<h2 class="mb-4 text-lg font-bold">
|
||||||
Mondes
|
{{ $t('entity.world.namePlural') }}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<ul class="grid lg:grid-cols-2 gap-2">
|
<ul class="grid lg:grid-cols-2 gap-2">
|
||||||
|
|||||||
@@ -12,20 +12,6 @@ const { data: res, pending } = await useFetch("/api/worlds/query", { query: { id
|
|||||||
|
|
||||||
const world = ref<World>(res.value?.data as World)
|
const world = ref<World>(res.value?.data as World)
|
||||||
|
|
||||||
if (world.value) {
|
|
||||||
useHead({
|
|
||||||
title: world.value.name
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(world, (n) => {
|
|
||||||
if (n) {
|
|
||||||
useHead({
|
|
||||||
title: n.name
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, { deep: true })
|
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
middleware: ["auth-guard"]
|
middleware: ["auth-guard"]
|
||||||
})
|
})
|
||||||
@@ -116,9 +102,17 @@ function hideDeleteModal() {
|
|||||||
<template>
|
<template>
|
||||||
<main class="p-8">
|
<main class="p-8">
|
||||||
<template v-if="pending">
|
<template v-if="pending">
|
||||||
|
<Head>
|
||||||
|
<Title>{{ $t("entity.world.namePlural") }}</Title>
|
||||||
|
</Head>
|
||||||
|
|
||||||
<Heading>Chargement...</Heading>
|
<Heading>Chargement...</Heading>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="world">
|
<template v-else-if="world">
|
||||||
|
<Head>
|
||||||
|
<Title>{{ world.name }}</Title>
|
||||||
|
</Head>
|
||||||
|
|
||||||
<header class="lg:w-1/2 mb-8">
|
<header class="lg:w-1/2 mb-8">
|
||||||
<Spacing>
|
<Spacing>
|
||||||
<Heading>{{ world.name }}</Heading>
|
<Heading>{{ world.name }}</Heading>
|
||||||
@@ -130,7 +124,9 @@ function hideDeleteModal() {
|
|||||||
<section>
|
<section>
|
||||||
<Spacing size="lg">
|
<Spacing size="lg">
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
<Heading>Calendriers</Heading>
|
<Heading>
|
||||||
|
{{ $t('entity.calendar.namePlural') }}
|
||||||
|
</Heading>
|
||||||
|
|
||||||
<UiTooltipProvider :delay-duration="250">
|
<UiTooltipProvider :delay-duration="250">
|
||||||
<UiTooltip>
|
<UiTooltip>
|
||||||
@@ -140,7 +136,9 @@ function hideDeleteModal() {
|
|||||||
</UiButton>
|
</UiButton>
|
||||||
</UiTooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<UiTooltipContent :side-offset="10">
|
<UiTooltipContent :side-offset="10">
|
||||||
<p>Ajouter un calendrier</p>
|
<p>
|
||||||
|
{{ $t('entity.calendar.addSingle') }}
|
||||||
|
</p>
|
||||||
</UiTooltipContent>
|
</UiTooltipContent>
|
||||||
</UiTooltip>
|
</UiTooltip>
|
||||||
</UiTooltipProvider>
|
</UiTooltipProvider>
|
||||||
@@ -168,7 +166,7 @@ function hideDeleteModal() {
|
|||||||
</ul>
|
</ul>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<p class="pl-6 opacity-75 italic">
|
<p class="pl-6 opacity-75 italic">
|
||||||
Aucun calendrier pour ce monde
|
{{ $t('entity.calendar.notFoundForWorld') }}
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</Spacing>
|
</Spacing>
|
||||||
|
|||||||
599
pnpm-lock.yaml
generated
599
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
BIN
public/images/flag-fr.png
Normal file
BIN
public/images/flag-fr.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
BIN
public/images/flag-uk.png
Normal file
BIN
public/images/flag-uk.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
@@ -24,7 +24,16 @@ type CalendarCurrentDate = {
|
|||||||
currentDateTitle: ComputedRef<string>
|
currentDateTitle: ComputedRef<string>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DateDirectionTranslationKeys = {
|
||||||
|
days: string
|
||||||
|
months: string
|
||||||
|
years: string
|
||||||
|
yearsAndMonths: string
|
||||||
|
}
|
||||||
|
|
||||||
export const useCalendar = defineStore("calendar", () => {
|
export const useCalendar = defineStore("calendar", () => {
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static calendar config
|
* Static calendar config
|
||||||
*/
|
*/
|
||||||
@@ -326,7 +335,7 @@ export const useCalendar = defineStore("calendar", () => {
|
|||||||
function getViewTypeTitle(viewType: CalendarViewType): string {
|
function getViewTypeTitle(viewType: CalendarViewType): string {
|
||||||
switch (viewType) {
|
switch (viewType) {
|
||||||
case "year":
|
case "year":
|
||||||
return "Année"
|
return t("entity.calendar.years.nameSingular")
|
||||||
|
|
||||||
case "decade":
|
case "decade":
|
||||||
return "Décennie"
|
return "Décennie"
|
||||||
@@ -336,7 +345,7 @@ export const useCalendar = defineStore("calendar", () => {
|
|||||||
|
|
||||||
case "month":
|
case "month":
|
||||||
default:
|
default:
|
||||||
return "Mois"
|
return t("entity.calendar.months.nameSingular")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -481,7 +490,31 @@ export const useCalendar = defineStore("calendar", () => {
|
|||||||
const differenceInDays: number = getDifferenceInDays(baseDate, relativeDate)
|
const differenceInDays: number = getDifferenceInDays(baseDate, relativeDate)
|
||||||
let output: string = ""
|
let output: string = ""
|
||||||
let direction: "past" | "present" | "future" = "present"
|
let direction: "past" | "present" | "future" = "present"
|
||||||
let directionPrefix: string = ""
|
const futureKeys: DateDirectionTranslationKeys = {
|
||||||
|
days: "xDaysNext",
|
||||||
|
months: "xMonthsNext",
|
||||||
|
years: "xYearsNext",
|
||||||
|
yearsAndMonths: "xYearsAndMonthsNext",
|
||||||
|
}
|
||||||
|
const futureKeysCompact: DateDirectionTranslationKeys = {
|
||||||
|
days: "xDaysNextCompact",
|
||||||
|
months: "xMonthsNextCompact",
|
||||||
|
years: "xYearsNextCompact",
|
||||||
|
yearsAndMonths: "xYearsAndMonthsNextCompact",
|
||||||
|
}
|
||||||
|
const pastKeys: DateDirectionTranslationKeys = {
|
||||||
|
days: "xDaysAgo",
|
||||||
|
months: "xMonthsAgo",
|
||||||
|
years: "xYearsAgo",
|
||||||
|
yearsAndMonths: "xYearsAndMonthsAgo",
|
||||||
|
}
|
||||||
|
const pastKeysCompact: DateDirectionTranslationKeys = {
|
||||||
|
days: "xDaysAgoCompact",
|
||||||
|
months: "xMonthsAgoCompact",
|
||||||
|
years: "xYearsAgoCompact",
|
||||||
|
yearsAndMonths: "xYearsAndMonthsAgoCompact",
|
||||||
|
}
|
||||||
|
let directionKeys: DateDirectionTranslationKeys = pastKeys
|
||||||
|
|
||||||
// Check whether it's a past or future date
|
// Check whether it's a past or future date
|
||||||
if (differenceInDays > 0) {
|
if (differenceInDays > 0) {
|
||||||
@@ -491,31 +524,36 @@ export const useCalendar = defineStore("calendar", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (formatting === "complex") {
|
if (formatting === "complex") {
|
||||||
// Handle if it's the same date
|
// Handle if it's the same date
|
||||||
if (direction === "present") {
|
if (direction === "present") {
|
||||||
return "Aujourd'hui"
|
return t("entity.calendar.date.today")
|
||||||
}
|
}
|
||||||
if (differenceInDays === -2) {
|
if (differenceInDays === -2) {
|
||||||
return "Avant-hier"
|
return t("entity.calendar.date.beforeYesterday")
|
||||||
}
|
}
|
||||||
if (differenceInDays === -1) {
|
if (differenceInDays === -1) {
|
||||||
return "Hier"
|
return t("entity.calendar.date.yesterday")
|
||||||
}
|
}
|
||||||
if (differenceInDays === 1) {
|
if (differenceInDays === 1) {
|
||||||
return "Demain"
|
return t("entity.calendar.date.tomorrow")
|
||||||
}
|
}
|
||||||
if (differenceInDays === 2) {
|
if (differenceInDays === 2) {
|
||||||
return "Après-demain"
|
return t("entity.calendar.date.afterTomorrow")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get relevant prefix for the string
|
// Get relevant prefix for the string
|
||||||
if (direction === "future") {
|
if (direction === "future") {
|
||||||
directionPrefix = "Dans "
|
directionKeys = futureKeys
|
||||||
} else if (direction === "past") {
|
} else {
|
||||||
directionPrefix = "Il y a "
|
directionKeys = pastKeys
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Get relevant prefix for the string (without the prefix)
|
||||||
|
if (direction === "future") {
|
||||||
|
directionKeys = futureKeysCompact
|
||||||
|
} else {
|
||||||
|
directionKeys = pastKeysCompact
|
||||||
}
|
}
|
||||||
|
|
||||||
output += directionPrefix
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const isSameMonth = baseDate.month === relativeDate.month
|
const isSameMonth = baseDate.month === relativeDate.month
|
||||||
@@ -544,11 +582,7 @@ export const useCalendar = defineStore("calendar", () => {
|
|||||||
if (isSameMonth && isSameYear) {
|
if (isSameMonth && isSameYear) {
|
||||||
dateAcc.day = futureDate.day - datePivot.day
|
dateAcc.day = futureDate.day - datePivot.day
|
||||||
|
|
||||||
if (dateAcc.day === 1) {
|
output = t(`entity.calendar.date.${directionKeys.days}`, { days: dateAcc.day })
|
||||||
output += ` ${dateAcc.day} jour`
|
|
||||||
} else {
|
|
||||||
output += ` ${dateAcc.day} jours`
|
|
||||||
}
|
|
||||||
|
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
@@ -557,7 +591,7 @@ export const useCalendar = defineStore("calendar", () => {
|
|||||||
else if (isSameYear) {
|
else if (isSameYear) {
|
||||||
dateAcc.month = futureDate.month - datePivot.month
|
dateAcc.month = futureDate.month - datePivot.month
|
||||||
|
|
||||||
output += ` ${dateAcc.month} mois`
|
output = t(`entity.calendar.date.${directionKeys.months}`, { months: dateAcc.month })
|
||||||
|
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
@@ -600,13 +634,13 @@ export const useCalendar = defineStore("calendar", () => {
|
|||||||
const remainderMonths = dateAcc.month % monthsPerYear.value
|
const remainderMonths = dateAcc.month % monthsPerYear.value
|
||||||
|
|
||||||
if (computedYear >= 1 && remainderMonths) {
|
if (computedYear >= 1 && remainderMonths) {
|
||||||
output += ` ${computedYear} an(s) et ${remainderMonths} mois`
|
output = t(`entity.calendar.date.${directionKeys.yearsAndMonths}`, { years: computedYear, months: remainderMonths })
|
||||||
}
|
}
|
||||||
else if (computedYear >= 1 && !remainderMonths) {
|
else if (computedYear >= 1 && !remainderMonths) {
|
||||||
output += ` ${computedYear} an(s)`;
|
output = t(`entity.calendar.date.${directionKeys.years}`, { years: computedYear })
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
output += ` ${remainderMonths} mois`
|
output = t(`entity.calendar.date.${directionKeys.months}`, { months: remainderMonths })
|
||||||
}
|
}
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|||||||
Reference in New Issue
Block a user