Merge branch 'code/cleanup' into dev
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -26,3 +26,5 @@ logs
|
||||
# Supabase
|
||||
.branches
|
||||
.temp
|
||||
|
||||
.scannerwork/
|
||||
|
||||
2
app.vue
2
app.vue
@@ -47,7 +47,7 @@ const { isSidebarOpened } = storeToRefs(useUiStore())
|
||||
<Sidebar />
|
||||
|
||||
<div
|
||||
class="wrapper max-h-screen transition-all"
|
||||
class="wrapper max-h-screen transition-all overflow-y-auto"
|
||||
>
|
||||
<NuxtPage />
|
||||
</div>
|
||||
|
||||
70
assets/_content.css
Normal file
70
assets/_content.css
Normal file
@@ -0,0 +1,70 @@
|
||||
.content {
|
||||
> * + * {
|
||||
margin-top: .5em;
|
||||
|
||||
@variant md {
|
||||
margin-top: .75rem;
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: var(--text-3xl);
|
||||
font-weight: var(--font-weight-bold);
|
||||
|
||||
@variant md {
|
||||
font-size: var(--text-4xl);
|
||||
}
|
||||
}
|
||||
h2 {
|
||||
font-size: var(--text-xl);
|
||||
font-weight: var(--font-weight-bold);
|
||||
|
||||
@variant md {
|
||||
font-size: var(--text-2xl);
|
||||
}
|
||||
}
|
||||
h3 {
|
||||
font-size: var(--text-lg);
|
||||
font-weight: var(--font-weight-bold);
|
||||
|
||||
@variant md {
|
||||
font-size: var(--text-xl);
|
||||
}
|
||||
}
|
||||
h4 {
|
||||
font-size: var(--text-md);
|
||||
font-weight: var(--font-weight-bold);
|
||||
|
||||
@variant md {
|
||||
font-size: var(--text-lg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Normal link */
|
||||
p a:not([class]) {
|
||||
color: var(--color-sky-600);
|
||||
text-underline-offset: .25rem;
|
||||
|
||||
&:hover {
|
||||
color: var(--color-sky-500);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@variant dark {
|
||||
color: var(--color-teal-500);
|
||||
|
||||
&:hover {
|
||||
color: var(--color-teal-300);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: square;
|
||||
padding-inline-start: 1.5rem;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin-block: 2rem;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@
|
||||
@import "./_colors.css" layer(theme);
|
||||
@import "./_colors.css" layer(utilities);
|
||||
|
||||
@import "./_content.css";
|
||||
|
||||
/*
|
||||
The default border color has changed to `currentcolor` in Tailwind CSS v4,
|
||||
so we've added these compatibility styles to make sure everything still
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export const searchUnifier = new RegExp(/[^a-zA-Z0-9\-'']/g)
|
||||
export const searchUnifier = new RegExp(/[^a-zA-Z0-9\-']/g)
|
||||
|
||||
export type SearchMode = "characters" | "events" | undefined
|
||||
|
||||
@@ -13,7 +13,7 @@ const { category } = defineProps<{
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "on-delete-category", payload: Category): void
|
||||
"on-delete-category": [payload: Category]
|
||||
}>()
|
||||
|
||||
type RowMode = "edit" | "view"
|
||||
|
||||
@@ -76,14 +76,6 @@ function handleClosing() {
|
||||
</UiAlertDialogDescription>
|
||||
|
||||
<form @submit.prevent="handleAction">
|
||||
<div class="grid grid-cols-2 gap-y-4">
|
||||
<div class="text-red-500 ml-8">
|
||||
<span class="text-sm">
|
||||
<!-- {{ formErrors.message }} -->
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="flex gap-2 justify-between">
|
||||
<UiButton type="button" size="sm" variant="outline" @click="handleClosing">
|
||||
{{ $t('ui.action.back') }}
|
||||
|
||||
@@ -57,13 +57,11 @@ async function handleSubmit() {
|
||||
}
|
||||
|
||||
/**
|
||||
* === Watch for name changes to display above ===
|
||||
* Watch for name changes to display above
|
||||
*/
|
||||
const emit = defineEmits<{
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
(e: "on-changed-name", calendarName: string): void
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
(e: "on-close"): void
|
||||
"on-changed-name": [calendarName: string]
|
||||
"on-close": []
|
||||
}>()
|
||||
|
||||
/** Hook to emit a debounced event for the changed skeleton name */
|
||||
|
||||
@@ -119,14 +119,6 @@ function handleCancel() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="col-span-2">
|
||||
<div class="flex items-center gap-4">
|
||||
<PhTag size="18" weight="fill" />
|
||||
|
||||
<CalendarInputEventCategories v-model="eventSkeleton.secondaryCategories" :placeholder="$t('entity.category.addSecondaries')" />
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="col-span-2 mb-2">
|
||||
<div class="flex items-center gap-4">
|
||||
<PhMapPinArea size="18" weight="fill" />
|
||||
|
||||
@@ -53,13 +53,11 @@ async function handleSubmit() {
|
||||
}
|
||||
|
||||
/**
|
||||
* === Watch for name changes to display above ===
|
||||
* Watch for name changes to display above
|
||||
*/
|
||||
const emit = defineEmits<{
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
(e: "on-changed-name", calendarName: string): void
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
(e: "on-close"): void
|
||||
"on-changed-name": [calendarName: string]
|
||||
"on-close": []
|
||||
}>()
|
||||
|
||||
/** Hook to emit a debounced event for the changed skeleton name */
|
||||
@@ -84,20 +82,6 @@ function handleFormCancel() {
|
||||
{{ $t('entity.calendar.actionDialog.tabs.general.title') }}
|
||||
</div>
|
||||
</UiTabsTrigger>
|
||||
<!-- <UiTabsTrigger value="months" class="font-bold">
|
||||
<div class="flex items-center gap-1">
|
||||
<PhCalendarDots size="18" weight="fill" />
|
||||
|
||||
{{ $t('entity.calendar.actionDialog.tabs.months.title') }}
|
||||
</div>
|
||||
</UiTabsTrigger>
|
||||
<UiTabsTrigger value="today" class="font-bold">
|
||||
<div class="flex items-center gap-1">
|
||||
<PhAlarm size="18" weight="fill" />
|
||||
|
||||
{{ $t('entity.calendar.actionDialog.tabs.today.title') }}
|
||||
</div>
|
||||
</UiTabsTrigger> -->
|
||||
</UiTabsList>
|
||||
<UiTabsContent value="global" class="grid gap-4">
|
||||
<input
|
||||
@@ -127,12 +111,6 @@ function handleFormCancel() {
|
||||
<InputColor id="new-calendar-color" v-model="calendarSkeleton.color" />
|
||||
</div>
|
||||
</UiTabsContent>
|
||||
<!-- <UiTabsContent value="months">
|
||||
<CalendarInputMonthList v-model:model-value="calendarSkeleton.months" />
|
||||
</UiTabsContent>
|
||||
<UiTabsContent value="today">
|
||||
<CalendarInputTodaySelect v-model:model-value="calendarSkeleton.today" :available-months="calendarSkeleton.months"/>
|
||||
</UiTabsContent> -->
|
||||
</UiTabs>
|
||||
|
||||
<footer class="flex justify-end gap-2 mt-6">
|
||||
|
||||
@@ -139,16 +139,6 @@ function handleCancel() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="col-span-2">
|
||||
<div class="flex items-center gap-4">
|
||||
<PhTag size="18" weight="fill" />
|
||||
|
||||
<div class="w-1/2">
|
||||
<CalendarInputEventCategories v-model="eventSkeleton.secondaryCategories" placeholder="Ajouter des catégories secondaires" />
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="col-span-2 mb-2">
|
||||
<div class="flex items-center gap-4">
|
||||
<PhMapPinArea size="18" weight="fill" />
|
||||
|
||||
@@ -35,6 +35,8 @@ const filteredCategories = computed(() =>
|
||||
<UiButton
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
:aria-expanded="isPopoverOpen"
|
||||
aria-controls="event-categories"
|
||||
class="relative w-full max-w-full h-fit justify-between"
|
||||
>
|
||||
<template v-if="!model.length">
|
||||
@@ -54,12 +56,13 @@ const filteredCategories = computed(() =>
|
||||
</UiButton>
|
||||
</UiPopoverTrigger>
|
||||
<UiPopoverContent
|
||||
id="event-categories"
|
||||
align="start"
|
||||
side="bottom"
|
||||
:collision-padding="50"
|
||||
class="w-fit h-[33vh] p-0"
|
||||
>
|
||||
<UiCommand v-model="modelBuffer" v-model:searchTerm="searchTerm" :multiple="true">
|
||||
<UiCommand v-model="modelBuffer" v-model:search-term="searchTerm" :multiple="true">
|
||||
<UiCommandInput :placeholder="$t('entity.category.search')" />
|
||||
<UiCommandEmpty>{{ $t('entity.category.notFoundAny') }}</UiCommandEmpty>
|
||||
<UiCommandList>
|
||||
|
||||
@@ -34,6 +34,8 @@ const filteredCategories = computed(() =>
|
||||
<UiButton
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
:aria-expanded="isPopoverOpen"
|
||||
aria-controls="event-category"
|
||||
class="w-full max-w-full justify-between"
|
||||
>
|
||||
<template v-if="!model">
|
||||
@@ -52,6 +54,7 @@ const filteredCategories = computed(() =>
|
||||
</UiButton>
|
||||
</UiPopoverTrigger>
|
||||
<UiPopoverContent
|
||||
id="event-category"
|
||||
align="start"
|
||||
side="bottom"
|
||||
:collision-padding="50"
|
||||
|
||||
@@ -135,15 +135,6 @@ function handleValueReset() {
|
||||
|
||||
<UiInput v-model="model.year" type="number" />
|
||||
|
||||
<!-- <nav class="flex items-center justify-end gap-2">
|
||||
<UiButton variant="outline" size="icon" class="w-8 h-8" @click="decrementModelMonth()">
|
||||
<PhCaretLeft size="14" />
|
||||
</UiButton>
|
||||
<UiButton variant="outline" size="icon" class="w-8 h-8" @click="incrementModelMonth()">
|
||||
<PhCaretRight size="14" />
|
||||
</UiButton>
|
||||
</nav> -->
|
||||
|
||||
<hr class="col-span-2" >
|
||||
|
||||
<div class="col-span-2">
|
||||
|
||||
@@ -88,7 +88,7 @@ const searchResults = computed<(Character | CalendarEvent)[]>(() => {
|
||||
results = dataToFilter.filter((item) => {
|
||||
// Filter calendar events
|
||||
if (isCalendarEvent(item)) {
|
||||
const queryString = new String(searchQuery.value)
|
||||
const queryString = (searchQuery.value as string)
|
||||
.replace(searchUnifier, "")
|
||||
.toLocaleLowerCase()
|
||||
|
||||
@@ -126,7 +126,7 @@ const searchResults = computed<(Character | CalendarEvent)[]>(() => {
|
||||
|
||||
// Filter characters
|
||||
if (isCharacter(item)) {
|
||||
const queryString = new String(searchQuery.value)
|
||||
const queryString = (searchQuery.value as string)
|
||||
.replace(searchUnifier, "")
|
||||
.toLocaleLowerCase()
|
||||
|
||||
@@ -279,7 +279,6 @@ function handleCategoryUnselect(e: Category) {
|
||||
</UiDialogDescription>
|
||||
</VisuallyHidden>
|
||||
|
||||
<!-- UiDialog header -->
|
||||
<div id="searchForm" class="grid gap-3">
|
||||
<div class="relative w-full h-fit">
|
||||
<UiInput
|
||||
@@ -307,10 +306,6 @@ function handleCategoryUnselect(e: Category) {
|
||||
<UiToggleGroupItem value="events" aria-label="Uniquement les évènements">
|
||||
{{ $t('entity.calendar.event.namePlural') }}
|
||||
</UiToggleGroupItem>
|
||||
<!-- Not used for now -->
|
||||
<!-- <UiToggleGroupItem value="characters" aria-label="Uniquement les personnages">
|
||||
{{ $t('entity.character.namePlural') }}
|
||||
</UiToggleGroupItem> -->
|
||||
</UiToggleGroup>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ const props = defineProps<{
|
||||
}>()
|
||||
|
||||
defineEmits<{
|
||||
(e: "query:date-jump", payload: RPGDate): void
|
||||
"query:date-jump": [payload: RPGDate]
|
||||
}>()
|
||||
|
||||
const { getFormattedDateTitle } = useCalendar()
|
||||
|
||||
@@ -10,7 +10,7 @@ const props = defineProps<{
|
||||
}>()
|
||||
|
||||
defineEmits<{
|
||||
(e: "query:date-jump", payload: RPGDate): void
|
||||
"query:date-jump": [payload: RPGDate]
|
||||
}>()
|
||||
|
||||
const { getRelativeString, defaultDate, getFormattedDateTitle } = useCalendar()
|
||||
|
||||
@@ -13,7 +13,7 @@ const props = defineProps<{
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "on-open-create-dialog", date: RPGDate): void
|
||||
"on-open-create-dialog": [date: RPGDate]
|
||||
}>()
|
||||
|
||||
const calendarTile = ref()
|
||||
|
||||
@@ -24,7 +24,7 @@ const moveCalendarRight = useThrottleFn(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container mt-[10vh] mb-auto" @wheel="handleWheel">
|
||||
<div class="container mx-auto mt-[10vh] mb-auto" @wheel="handleWheel">
|
||||
<div class="grid grid-cols-5 gap-x-8 gap-y-16">
|
||||
<CalendarStateYearlyMonthTile
|
||||
v-for="month in months"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import { PhCompass, PhGlobeHemisphereEast, PhHurricane, PhX } from "@phosphor-icons/vue"
|
||||
import { PhCompass, PhGlobeHemisphereEast, PhHurricane, PhInfo, PhX } from "@phosphor-icons/vue"
|
||||
import type { SidebarMenuActionType, SidebarMenuIcon } from "./SidebarProps";
|
||||
import { cn } from "~/lib/utils";
|
||||
import { breakpointsTailwind } from "@vueuse/core"
|
||||
@@ -40,12 +40,12 @@ const breakpoints = useBreakpoints(
|
||||
<nav
|
||||
ref="sidebarRef"
|
||||
:class="cn(
|
||||
['md:relative md:isolate w-16 py-6 grid gap-4 grid-rows-[1fr_auto] justify-center transition-all'], // Base appearance
|
||||
['md:relative md:isolate w-16 py-6 grid gap-4 grid-rows-[1fr_auto] justify-center md:transition-none'], // Base appearance
|
||||
['after:opacity-50 after:contrast-125 dark:after:opacity-75 dark:after:contrast-175 after:-hue-rotate-60'], // After styling
|
||||
['border-r-[1px] bg-indigo-700 dark:bg-black text-white border-r-indigo-700 dark:border-r-indigo-950 shadow-navbar-light dark:shadow-navbar-dark'], // Colours
|
||||
['max-md:justify-stretch max-md:px-4 max-md:py-4 max-md:absolute max-md:left-0 max-md:inset-0 max-md:z-50 max-md:w-30 max-md:max-w-full'], // Responsive behaviours
|
||||
['max-md:justify-stretch max-md:px-4 max-md:py-4 max-md:absolute max-md:left-0 max-md:inset-0 max-md:z-50 max-md:w-40 max-md:max-w-full max-md:transition-all'], // Responsive behaviours
|
||||
{
|
||||
'max-md:-translate-x-30': !isSidebarOpened,
|
||||
'max-md:-translate-x-40': !isSidebarOpened,
|
||||
'max-md:-translate-x-0 shadow-navbar-dark dark:bg-slate-950': isSidebarOpened
|
||||
}
|
||||
)"
|
||||
@@ -96,6 +96,40 @@ const breakpoints = useBreakpoints(
|
||||
</UiTooltipProvider>
|
||||
</li>
|
||||
|
||||
<li class="max-md:self-start">
|
||||
<UiTooltipProvider :delay-duration="50" :disabled="!breakpoints.md.value">
|
||||
<UiTooltip>
|
||||
<UiTooltipTrigger as-child>
|
||||
<UiButton
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
class="rounded-full max-md:hidden"
|
||||
as-child
|
||||
>
|
||||
<RouterLink to="/about">
|
||||
<PhInfo size="24" weight="fill" />
|
||||
</RouterLink>
|
||||
</UiButton>
|
||||
<RouterLink
|
||||
to="/about"
|
||||
class="md:hidden flex items-center gap-[.6ch] underline-offset-4 hover:underline"
|
||||
>
|
||||
<PhInfo size="22" weight="fill" />
|
||||
|
||||
<span class="text-[.9em]">
|
||||
{{ $t('pages.about.menuLabel') }}
|
||||
</span>
|
||||
</RouterLink>
|
||||
</UiTooltipTrigger>
|
||||
<UiTooltipContent :side="'right'" :side-offset="6">
|
||||
<p>
|
||||
{{ $t('pages.about.menuLabel') }}
|
||||
</p>
|
||||
</UiTooltipContent>
|
||||
</UiTooltip>
|
||||
</UiTooltipProvider>
|
||||
</li>
|
||||
|
||||
<ClientOnly>
|
||||
<li v-for="(item, i) in currentMenu" :key="i">
|
||||
<UiTooltipProvider :delay-duration="50">
|
||||
|
||||
@@ -184,12 +184,6 @@ function pushRoute(to: AvailableRoutes) {
|
||||
<UiDropdownMenuSeparator />
|
||||
|
||||
<template v-if="user">
|
||||
<!-- <UiDropdownMenuItem class="flex gap-[.5ch] items-center rounded-none" @click="pushRoute('/my/settings')">
|
||||
<PhGear size="20" weight="fill" />
|
||||
<span>
|
||||
{{ $t('ui.sidebarMenu.account') }}
|
||||
</span>
|
||||
</UiDropdownMenuItem> -->
|
||||
<UiDropdownMenuItem class="flex gap-[.5ch] items-center rounded-none" @click="handleLogout">
|
||||
<PhSignOut size="20" weight="fill" />
|
||||
<span>
|
||||
|
||||
@@ -10,7 +10,7 @@ const props = defineProps<{
|
||||
}>()
|
||||
|
||||
const emits = defineEmits<{
|
||||
(e: "update:modelValue", payload: string | number): void
|
||||
"update:modelValue": [payload: string | number]
|
||||
}>()
|
||||
|
||||
const modelValue = useVModel(props, "modelValue", emits, {
|
||||
|
||||
@@ -34,5 +34,5 @@ type ToastVariants = VariantProps<typeof toastVariants>
|
||||
export interface ToastProps extends ToastRootProps {
|
||||
class?: HTMLAttributes["class"]
|
||||
variant?: ToastVariants["variant"]
|
||||
onOpenChange?: ((value: boolean) => void) | undefined
|
||||
onOpenChange?: ((value: boolean) => void)
|
||||
}
|
||||
|
||||
@@ -76,14 +76,6 @@ function handleClosing() {
|
||||
</UiAlertDialogDescription>
|
||||
|
||||
<form @submit.prevent="handleAction">
|
||||
<div class="grid grid-cols-2 gap-y-4">
|
||||
<div class="text-red-500 ml-8">
|
||||
<span class="text-sm">
|
||||
<!-- {{ formErrors.message }} -->
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="flex gap-2 justify-between">
|
||||
<UiButton type="button" size="sm" variant="outline" @click="handleClosing">
|
||||
{{ $t('ui.action.back') }}
|
||||
|
||||
@@ -42,10 +42,8 @@ async function handleSubmit() {
|
||||
* === Watch for name changes to display above ===
|
||||
*/
|
||||
const emit = defineEmits<{
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
(e: "on-changed-name", calendarName: string): void
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
(e: "on-close"): void
|
||||
"on-changed-name": [calendarName: string]
|
||||
"on-close": []
|
||||
}>()
|
||||
|
||||
/** Hook to emit a debounced event for the changed skeleton name */
|
||||
|
||||
@@ -54,10 +54,8 @@ async function handleSubmit() {
|
||||
* === Watch for name changes to display above ===
|
||||
*/
|
||||
const emit = defineEmits<{
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
(e: "on-changed-name", calendarName: string): void
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
(e: "on-close"): void
|
||||
"on-changed-name": [calendarName: string]
|
||||
"on-close": []
|
||||
}>()
|
||||
|
||||
/** Hook to emit a debounced event for the changed skeleton name */
|
||||
|
||||
10
content.config.ts
Normal file
10
content.config.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { defineCollection, defineContentConfig } from "@nuxt/content"
|
||||
|
||||
export default defineContentConfig({
|
||||
collections: {
|
||||
sections: defineCollection({
|
||||
type: "page",
|
||||
source: "sections/**/*.md"
|
||||
})
|
||||
}
|
||||
})
|
||||
2
content/sections/en/legal.md
Normal file
2
content/sections/en/legal.md
Normal file
@@ -0,0 +1,2 @@
|
||||
## legal text
|
||||
test
|
||||
108
content/sections/fr/legal.md
Normal file
108
content/sections/fr/legal.md
Normal file
@@ -0,0 +1,108 @@
|
||||
## Mentions légales
|
||||
### Propriétaire du site
|
||||
Alexis Pelé
|
||||
|
||||
**Email** — contact@alexcreates.fr
|
||||
|
||||
**Email de support** — rpg@alexcreates.fr
|
||||
|
||||
### Hébergeur
|
||||
Cloudflare US INC
|
||||
|
||||
**Adresse** — Townsend Street 101 San Francisco, Californie, États-Unis
|
||||
|
||||
-----
|
||||
|
||||
## Conditions Générales d'Utilisation
|
||||
|
||||
**Date d'entrée en vigueur : 5 mai 2025**
|
||||
|
||||
### 1. Acceptation des Conditions
|
||||
|
||||
En accédant à notre application de gestion d'univers de fiction (ci-après dénommée "l'Application"), vous acceptez d'être lié par les présentes Conditions Générales d'Utilisation. Si vous n'acceptez pas ces conditions, veuillez ne pas utiliser l'Application.
|
||||
|
||||
En utilisant notre Application, vous reconnaissez avoir lu, compris et accepté les présentes Conditions Générales d'Utilisation.
|
||||
|
||||
### 2. Description du Service
|
||||
|
||||
L'Application permet aux utilisateurs de créer, gérer et partager des calendriers et des univers de fiction. Les fonctionnalités incluent, sans s'y limiter :
|
||||
- La création de comptes utilisateurs
|
||||
- La conception de calendriers personnalisés
|
||||
- La création et gestion d'univers de fiction
|
||||
- Le partage de contenus avec d'autres utilisateurs
|
||||
|
||||
### 3. Inscription et Compte Utilisateur
|
||||
|
||||
Pour utiliser pleinement l'Application, vous devez créer un compte utilisateur. Vous vous engagez à fournir des informations exactes, complètes et à jour lors de votre inscription.
|
||||
|
||||
Vous êtes responsable du maintien de la confidentialité de vos identifiants de connexion et de toutes les activités qui se produisent sous votre compte. Vous devez nous informer immédiatement de toute utilisation non autorisée de votre compte.
|
||||
|
||||
### 4. Contenus de l'Utilisateur
|
||||
|
||||
#### 4.1 Propriété intellectuelle
|
||||
Vous conservez tous vos droits de propriété intellectuelle sur les contenus que vous créez via l'Application. Cependant, vous nous accordez une licence mondiale, non exclusive, gratuite, transférable et pouvant faire l'objet d'une sous-licence pour utiliser, reproduire, adapter, publier et afficher ces contenus dans le cadre de la fourniture de l'Application et de ses services.
|
||||
|
||||
#### 4.2 Contenus prohibés
|
||||
Vous vous engagez à ne pas créer ou partager de contenus qui :
|
||||
- Violent les droits de propriété intellectuelle d'autrui
|
||||
- Sont illégaux, diffamatoires, obscènes ou offensants
|
||||
- Contiennent des virus ou autres codes malveillants
|
||||
- Harcèlent, intimident ou discriminent d'autres utilisateurs
|
||||
|
||||
### 5. Utilisation de l'Application
|
||||
|
||||
#### 5.1 Utilisation autorisée
|
||||
Vous vous engagez à utiliser l'Application conformément aux présentes conditions, aux lois applicables et aux bonnes pratiques en ligne.
|
||||
|
||||
#### 5.2 Restrictions
|
||||
Il est interdit de :
|
||||
- Utiliser l'Application d'une manière susceptible de l'endommager ou d'en altérer le fonctionnement
|
||||
- Tenter d'accéder sans autorisation aux systèmes ou réseaux connectés à l'Application
|
||||
- Utiliser l'Application pour distribuer des publicités non sollicitées ou du contenu malveillant
|
||||
- Usurper l'identité d'une autre personne ou entité
|
||||
|
||||
### 6. Confidentialité et Données Personnelles
|
||||
|
||||
Le traitement de vos données personnelles est soumis à notre Politique de Confidentialité, disponible séparément. En utilisant l'Application, vous consentez à la collecte et au traitement de vos données conformément à cette politique.
|
||||
|
||||
### 7. Modification et Résiliation
|
||||
|
||||
#### 7.1 Modification du service
|
||||
Nous nous réservons le droit de modifier, suspendre ou interrompre tout aspect de l'Application à tout moment, avec ou sans préavis.
|
||||
|
||||
#### 7.2 Résiliation
|
||||
Nous pouvons résilier ou suspendre votre accès à l'Application immédiatement, sans préavis ni responsabilité, pour toute raison, y compris, sans limitation, si vous enfreignez les présentes conditions.
|
||||
|
||||
### 8. Limitation de Responsabilité
|
||||
|
||||
#### 8.1 Garantie
|
||||
L'Application est fournie "telle quelle" et "selon disponibilité", sans garantie d'aucune sorte, expresse ou implicite.
|
||||
|
||||
#### 8.2 Responsabilité
|
||||
Dans toute la mesure permise par la loi, nous déclinons toute responsabilité pour tout dommage indirect, consécutif, exemplaire, accessoire ou punitif, y compris la perte de profits, même si nous avons été avisés de la possibilité de tels dommages.
|
||||
|
||||
### 9. Dispositions Générales
|
||||
|
||||
Les présentes conditions sont régies par le droit français.
|
||||
|
||||
Tout litige relatif à l'interprétation, l'exécution ou la validité des présentes conditions sera soumis à la compétence exclusive des tribunaux français.
|
||||
|
||||
Ces conditions constituent l'intégralité de l'accord entre vous et nous concernant l'utilisation de l'Application et remplacent tous les accords antérieurs.
|
||||
|
||||
Si une disposition des présentes conditions est jugée invalide ou inapplicable, les autres dispositions resteront en vigueur.
|
||||
|
||||
Vous ne pouvez pas céder vos droits ou obligations en vertu des présentes conditions sans notre consentement écrit préalable.
|
||||
|
||||
Pour toute question concernant ces conditions d'utilisation, veuillez nous contacter à : rpg@alexcreates.fr
|
||||
|
||||
### 10. Cookies & informations personnelles
|
||||
|
||||
L’utilisateur est informé que lors de ses visites sur le site, un cookie peut s’installer automatiquement sur son logiciel de navigation.
|
||||
|
||||
Le cookie est un bloc de données qui ne permet pas d’identifier les utilisateurs mais sert à enregistrer des informations relatives à la navigation de celui-ci sur le site.
|
||||
|
||||
Le paramétrage du logiciel de navigation permet d’informer de la présence de cookie et éventuellement, de la refuser.
|
||||
|
||||
L’utilisateur dispose de l’ensemble des droits susvisés s’agissant des données à caractère personnel communiquées par le biais des cookies dans les conditions indiquées ci-dessus.
|
||||
|
||||
Nous n'utilisons pas de cookie d'analyses, de tracking ou de régies publicitaires. Les cookies présents sur le site sont purement fonctionnels et ne sont pas partagés avec des tiers dans des buts commerciaux. Les cookies de l'application ne permettent pas de vous identifier.
|
||||
@@ -318,6 +318,11 @@ export default defineI18nConfig(() => ({
|
||||
profile: {
|
||||
title: "{user} — My universe",
|
||||
metaTitle: "My universe",
|
||||
},
|
||||
about: {
|
||||
title: "About this app",
|
||||
metaTitle: "About this app",
|
||||
menuLabel: "About",
|
||||
}
|
||||
},
|
||||
breadcrumbs: {
|
||||
@@ -647,6 +652,11 @@ export default defineI18nConfig(() => ({
|
||||
profile: {
|
||||
title: "{user} — Mon univers",
|
||||
metaTitle: "Mon univers",
|
||||
},
|
||||
about: {
|
||||
title: "À propos",
|
||||
metaTitle: "À propos",
|
||||
menuLabel: "À propos",
|
||||
}
|
||||
},
|
||||
breadcrumbs: {
|
||||
|
||||
@@ -12,7 +12,8 @@ export default defineNuxtConfig({
|
||||
"@nuxt/eslint",
|
||||
"shadcn-nuxt",
|
||||
"@nuxtjs/i18n",
|
||||
"@nuxthub/core"
|
||||
"@nuxthub/core",
|
||||
"@nuxt/content",
|
||||
],
|
||||
|
||||
css: ["~/assets/main.css"],
|
||||
@@ -48,7 +49,8 @@ export default defineNuxtConfig({
|
||||
callback: "/my/",
|
||||
exclude: [
|
||||
"/calendars(/*)?",
|
||||
"/explore(/*)?"
|
||||
"/explore(/*)?",
|
||||
"/about(/*)?"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
44
package.json
44
package.json
@@ -14,48 +14,50 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@intlify/message-compiler": "^11.1.3",
|
||||
"@nuxt/eslint": "^1.3.0",
|
||||
"@nuxthub/core": "^0.8.24",
|
||||
"@nuxtjs/i18n": "^9.5.3",
|
||||
"@nuxt/content": "3.5.1",
|
||||
"@nuxt/eslint": "^1.3.1",
|
||||
"@nuxthub/core": "^0.8.27",
|
||||
"@nuxtjs/i18n": "^9.5.4",
|
||||
"@phosphor-icons/vue": "^2.2.1",
|
||||
"@pinia/nuxt": "^0.11.0",
|
||||
"@tailwindcss/vite": "^4.1.4",
|
||||
"@tailwindcss/vite": "^4.1.6",
|
||||
"@vueuse/core": "^13.1.0",
|
||||
"@vueuse/integrations": "^13.1.0",
|
||||
"@vueuse/nuxt": "^13.1.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"lucide-vue-next": "^0.503.0",
|
||||
"lucide-vue-next": "^0.510.0",
|
||||
"luxon": "^3.6.1",
|
||||
"nuxt": "^3.16.2",
|
||||
"nuxt": "^3.17.3",
|
||||
"pinia": "^3.0.2",
|
||||
"radix-vue": "^1.9.17",
|
||||
"shadcn-nuxt": "^2.1.0",
|
||||
"sortablejs": "^1.15.6",
|
||||
"tailwind-merge": "^3.2.0",
|
||||
"tailwind-merge": "^3.3.0",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"vue": "^3.5.13",
|
||||
"vue-router": "^4.5.0",
|
||||
"zod": "^3.24.3"
|
||||
"vue-router": "^4.5.1",
|
||||
"zod": "^3.24.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxtjs/color-mode": "^3.5.2",
|
||||
"@nuxtjs/supabase": "^1.5.0",
|
||||
"@nuxtjs/tailwindcss": "^6.13.2",
|
||||
"@nuxtjs/supabase": "^1.5.1",
|
||||
"@nuxtjs/tailwindcss": "^6.14.0",
|
||||
"@stylistic/eslint-plugin-js": "^4.2.0",
|
||||
"@types/luxon": "^3.6.2",
|
||||
"@typescript-eslint/eslint-plugin": "^8.31.0",
|
||||
"@typescript-eslint/parser": "^8.31.0",
|
||||
"eslint": "^9.25.1",
|
||||
"eslint-config-prettier": "^10.1.2",
|
||||
"eslint-plugin-prettier": "^5.2.6",
|
||||
"eslint-plugin-vue": "^10.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.32.1",
|
||||
"@typescript-eslint/parser": "^8.32.1",
|
||||
"eslint": "^9.26.0",
|
||||
"eslint-config-prettier": "^10.1.5",
|
||||
"eslint-plugin-prettier": "^5.4.0",
|
||||
"eslint-plugin-vue": "^10.1.0",
|
||||
"postcss": "^8.5.3",
|
||||
"prettier": "^3.5.3",
|
||||
"sass": "^1.87.0",
|
||||
"tailwindcss": "^4.1.4",
|
||||
"sass": "^1.88.0",
|
||||
"supabase": "^2.30.4",
|
||||
"tailwindcss": "^4.1.6",
|
||||
"typescript": "^5.8.3",
|
||||
"wrangler": "^4.12.0"
|
||||
"wrangler": "^4.14.4"
|
||||
},
|
||||
"packageManager": "pnpm@9.1.0+sha1.217063ce3fcbf44f3051666f38b810f1ddefee4a"
|
||||
"packageManager": "pnpm@10.10.0"
|
||||
}
|
||||
|
||||
33
pages/about.vue
Normal file
33
pages/about.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<script lang="ts" setup>
|
||||
const { locale } = useI18n()
|
||||
|
||||
const { data: page, refresh } = await useAsyncData(`about-content-${locale}`, () => {
|
||||
return queryCollection("sections").path(`/sections/${locale.value}/legal`).first()
|
||||
})
|
||||
|
||||
watch(locale, () => refresh())
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main class="py-8 px-5 md:px-8 overflow-y-auto">
|
||||
<Head>
|
||||
<Title>{{ $t("pages.about.title") }}</Title>
|
||||
</Head>
|
||||
|
||||
<div class="container max-md:px-0">
|
||||
<Spacing size="lg">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="md:hidden">
|
||||
<SidebarToggle />
|
||||
</div>
|
||||
|
||||
<Heading level="h1">
|
||||
{{ $t("pages.about.title") }}
|
||||
</Heading>
|
||||
</div>
|
||||
|
||||
<ContentRenderer v-if="page" :value="page" class="content" />
|
||||
</Spacing>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
@@ -17,9 +17,15 @@ const isLoading = computed(() => calendarStatus.value === "pending")
|
||||
</Head>
|
||||
|
||||
<Spacing size="lg">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="md:hidden">
|
||||
<SidebarToggle />
|
||||
</div>
|
||||
|
||||
<Heading level="h1">
|
||||
{{ $t("pages.explore.title") }}
|
||||
</Heading>
|
||||
</div>
|
||||
|
||||
<Spacing size="lg">
|
||||
<Heading level="h2">
|
||||
|
||||
5657
pnpm-lock.yaml
generated
5657
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
10
pnpm-workspace.yaml
Normal file
10
pnpm-workspace.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
onlyBuiltDependencies:
|
||||
- '@parcel/watcher'
|
||||
- '@tailwindcss/oxide'
|
||||
- better-sqlite3
|
||||
- esbuild
|
||||
- sharp
|
||||
- supabase
|
||||
- unrs-resolver
|
||||
- vue-demi
|
||||
- workerd
|
||||
@@ -1,5 +1,4 @@
|
||||
import { serverSupabaseClient } from "#supabase/server";
|
||||
// import type { Calendar} from "~/models/CalendarConfig";
|
||||
import type { Calendar} from "~/models/CalendarConfig";
|
||||
import { postCalendarSchema } from "~/models/CalendarConfig";
|
||||
|
||||
@@ -63,7 +62,7 @@ export default defineEventHandler(async (event) => {
|
||||
.insert(bodyData.months as never)
|
||||
|
||||
if (error) throw error
|
||||
} catch (err) {
|
||||
} catch {
|
||||
// If we found an error, rollback the calendar
|
||||
if (calendarId) {
|
||||
await client
|
||||
@@ -89,7 +88,7 @@ export default defineEventHandler(async (event) => {
|
||||
.eq("id", calendarId)
|
||||
.limit(1)
|
||||
.single<Calendar>()
|
||||
} catch (err) {
|
||||
} catch {
|
||||
throw createError({
|
||||
cause: "Serveur",
|
||||
fatal: false,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { serverSupabaseClient } from "#supabase/server";
|
||||
// import type { Calendar} from "~/models/CalendarConfig";
|
||||
import type { World } from "~/models/World";
|
||||
import { postWorldSchema } from "~/models/World";
|
||||
|
||||
@@ -41,7 +40,7 @@ export default defineEventHandler(async (event) => {
|
||||
if (error) throw error
|
||||
|
||||
return data
|
||||
} catch (err) {
|
||||
} catch {
|
||||
throw createError({
|
||||
cause: "Serveur",
|
||||
status: 500,
|
||||
|
||||
@@ -97,7 +97,7 @@ export const useCalendar = defineStore("calendar", () => {
|
||||
/**
|
||||
* Sorted month data using the raw months
|
||||
*/
|
||||
const sortedMonths = computed<CalendarMonth[]>(() => months.value.sort((a, b) => a.position - b.position))
|
||||
const sortedMonths = computed<CalendarMonth[]>(() => months.value.toSorted((a, b) => a.position - b.position))
|
||||
const monthsPerYear = computed<number>(() => months.value.length)
|
||||
const daysPerYear = computed<number>(() => months.value.reduce((acc, o) => acc + o.days, 0))
|
||||
|
||||
@@ -520,7 +520,7 @@ export const useCalendar = defineStore("calendar", () => {
|
||||
years: "xYearsAgoCompact",
|
||||
yearsAndMonths: "xYearsAndMonthsAgoCompact",
|
||||
}
|
||||
let directionKeys: DateDirectionTranslationKeys = pastKeys
|
||||
let directionKeys: DateDirectionTranslationKeys
|
||||
|
||||
// Check whether it's a past or future date
|
||||
if (differenceInDays > 0) {
|
||||
@@ -922,7 +922,6 @@ export const useCalendar = defineStore("calendar", () => {
|
||||
})
|
||||
}
|
||||
|
||||
// Watch for categories changes
|
||||
watch(categories, (n) => {
|
||||
updateAllEventsCategories(n)
|
||||
})
|
||||
|
||||
@@ -126,3 +126,6 @@ skip_nonce_check = false
|
||||
[auth.hook.custom_access_token]
|
||||
enabled = true
|
||||
uri = "pg-functions://postgres/public/custom_access_token_hook"
|
||||
|
||||
[analytics]
|
||||
enabled = false
|
||||
|
||||
@@ -16,7 +16,6 @@ module.exports = {
|
||||
|
||||
theme: {
|
||||
container: {
|
||||
center: true,
|
||||
padding: "2rem",
|
||||
screens: {
|
||||
"2xl": "1400px",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* @returns Result of the test
|
||||
*/
|
||||
export function isDigit(str: string) {
|
||||
return RegExp(/^\d{1}$/g).test(str)
|
||||
return RegExp(/^\d$/g).test(str)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user