Updated legal stuff, added floating popup that can be pin and move. Fix character compiler modifier updates not dirtying all dependents.

This commit is contained in:
2025-10-05 23:54:37 +02:00
parent 89c4476ffb
commit b19d2d1b41
21 changed files with 420 additions and 446 deletions

View File

@@ -1,17 +1,8 @@
<script setup lang="ts">
import characterConfig from '#shared/character-config.json';
import { Icon } from '@iconify/vue/dist/iconify.js';
import PreviewA from '~/components/prose/PreviewA.vue';
import { clamp, unifySlug } from '#shared/general.util';
import type { CompiledCharacter, SpellConfig } from '~/types/character';
import { unifySlug } from '#shared/general.util';
import type { CharacterConfig } from '~/types/character';
import { abilityTexts, CharacterCompiler, CharacterSheet, defaultCharacter, elementTexts, spellTypeTexts } from '#shared/character.util';
import { getText } from '#shared/i18n';
import { preview } from '#shared/proses';
import { div, dom, icon, text } from '#shared/dom.util';
import markdown from '#shared/markdown.util';
import { button, foldable } from '#shared/components.util';
import { fullblocker, tooltip } from '~/shared/floating.util';
import { CharacterSheet } from '#shared/character.util';
/*
text-light-red dark:text-dark-red border-light-red dark:border-dark-red bg-light-red dark:bg-dark-red
text-light-blue dark:text-dark-blue border-light-blue dark:border-dark-blue bg-light-blue dark:bg-dark-blue
@@ -43,172 +34,4 @@ onMounted(() => {
<template>
<div ref="container"></div>
<!-- <div v-if="status === 'pending'">
<Head>
<Title>d[any] - Chargement ...</Title>
</Head>
</div>
<div v-else-if="status === 'success' && character && !error">
<Head>
<Title>d[any] - {{ character.name }}</Title>
</Head>
<div class="flex flex-row gap-4 justify-between">
<div></div>
<div class="flex lg:flex-row flex-col gap-6 items-center justify-center">
<div class="flex gap-6 items-center">
<Avatar src="" icon="radix-icons:person" size="large" />
<div class="flex flex-col">
<span class="text-xl font-bold">{{ character.name }}</span>
<span class="text-sm">De {{ character.username }}</span>
</div>
<div class="flex flex-col">
<span class="font-bold">Niveau {{ character.level }}</span>
<span>{{ config.peoples[character.race]?.name ?? 'Peuple inconnu' }}</span>
</div>
</div>
<div class="flex flex-row lg:border-l border-light-30 dark:border-dark-30 py-4 ps-4 gap-8">
<span class="flex flex-row items-center gap-2 text-3xl font-light">PV: <span class="font-bold px-2 border-transparent border cursor-pointer hover:border-light-35 dark:hover:border-dark-35">{{ character.health - character.variables.health }}</span>/ {{ character.health }}</span>
<span class="flex flex-row items-center gap-2 text-3xl font-light">Mana: <span class="font-bold px-2 border-transparent border cursor-pointer hover:border-light-35 dark:hover:border-dark-35">{{ character.mana - character.variables.mana }}</span>/ {{ character.mana }}</span>
</div>
</div>
<div class="self-center">
<Tooltip side="right" message="Modifier" v-if="user && user.id === character.owner"><NuxtLink :to="{ name: 'character-id-edit', params: { id: character.id } }"><Button icon><Icon icon="radix-icons:pencil-2" /></Button></NuxtLink></Tooltip>
</div>
</div>
<div class="flex flex-1 flex-col justify-center gap-4 *:py-2">
<div class="flex flex-row gap-4 items-center border-b border-light-30 dark:border-dark-30 me-4 pe-4 divide-x divide-light-30 dark:divide-dark-30">
<div class="flex relative justify-between ps-4 gap-2">
<div class="flex flex-col items-center"><span class="2xl:text-2xl text-xl font-bold">+{{ character.modifier.strength }}</span><span class="text-sm 2xl:text-base">Force</span></div>
<div class="flex flex-col items-center"><span class="2xl:text-2xl text-xl font-bold">+{{ character.modifier.dexterity }}</span><span class="text-sm 2xl:text-base">Dextérité</span></div>
<div class="flex flex-col items-center"><span class="2xl:text-2xl text-xl font-bold">+{{ character.modifier.constitution }}</span><span class="text-sm 2xl:text-base">Constitution</span></div>
<div class="flex flex-col items-center"><span class="2xl:text-2xl text-xl font-bold">+{{ character.modifier.intelligence }}</span><span class="text-sm 2xl:text-base">Intelligence</span></div>
<div class="flex flex-col items-center"><span class="2xl:text-2xl text-xl font-bold">+{{ character.modifier.curiosity }}</span><span class="text-sm 2xl:text-base">Curiosité</span></div>
<div class="flex flex-col items-center"><span class="2xl:text-2xl text-xl font-bold">+{{ character.modifier.charisma }}</span><span class="text-sm 2xl:text-base">Charisme</span></div>
<div class="flex flex-col items-center"><span class="2xl:text-2xl text-xl font-bold">+{{ character.modifier.psyche }}</span><span class="text-sm 2xl:text-base">Psyché</span></div>
</div>
<div class="flex flex-1 relative ps-4 flex-row items-center justify-between">
<div class="flex flex-col px-2 items-center"><span class="text-2xl font-bold">+{{ character.initiative }}</span><span>Initiative</span></div>
<div class="flex flex-col px-2 items-center"><span class="text-2xl font-bold">{{ character.speed === false ? "Aucun déplacement" : `${character.speed} cases` }}</span><span>Course</span></div>
</div>
<div class="flex flex-1 relative ps-4 flex-row items-center justify-between">
<Icon icon="ph:shield-checkered" class="w-8 h-8" />
<div class="flex flex-col items-center"><span class="2xl:text-2xl text-xl font-bold">{{ clamp(character.defense.static + character.defense.passivedodge + character.defense.passiveparry, 0, character.defense.hardcap) }}</span><span class="text-sm 2xl:text-base">Passive</span></div>
<div class="flex flex-col items-center"><span class="2xl:text-2xl text-xl font-bold">{{ clamp(character.defense.static + character.defense.passivedodge + character.defense.activeparry, 0, character.defense.hardcap) }}</span><span class="text-sm 2xl:text-base">Blocage</span></div>
<div class="flex flex-col items-center"><span class="2xl:text-2xl text-xl font-bold">{{ clamp(character.defense.static + character.defense.activedodge + character.defense.passiveparry, 0, character.defense.hardcap) }}</span><span class="text-sm 2xl:text-base">Esquive</span></div>
</div>
</div>
<div class="flex flex-1 px-8">
<div class="flex flex-col pe-8 gap-4 py-2 w-80 border-r border-light-30 dark:border-dark-30">
<div class="flex flex-col">
<span class="text-lg font-semibold border-b border-light-30 dark:border-dark-30 mb-2">Compétences</span>
<div class="grid grid-cols-3 gap-1">
<div class="flex flex-col px-2 items-center text-sm text-light-70 dark:text-dark-70" v-for="(value, ability) of character.abilities"><span class="font-bold text-base text-light-100 dark:text-dark-100">+{{ value }}</span><span>{{ abilityTexts[ability] }}</span></div>
</div>
</div>
<div class="flex flex-col gap-2">
<span class="text-lg font-semibold border-b border-light-30 dark:border-dark-30">Maitrises</span>
<div class="grid grid-cols-2 gap-x-3 gap-y-1 text-sm">
<PreviewA v-if="character.mastery.strength + character.mastery.dexterity > 0" href="regles/annexes/equipement#Les armes légères" label="Arme légère" />
<PreviewA v-if="character.mastery.strength + character.mastery.dexterity > 0" href="regles/annexes/equipement#Les armes de jet" label="Arme de jet" />
<PreviewA v-if="character.mastery.strength + character.mastery.dexterity > 0" href="regles/annexes/equipement#Les armes naturelles" label="Arme naturelle" />
<PreviewA v-if="character.mastery.strength > 1" href="regles/annexes/equipement#Les armes" label="Arme standard" />
<PreviewA v-if="character.mastery.strength > 1" href="regles/annexes/equipement#Les armes improvisées" label="Arme improvisée" />
<PreviewA v-if="character.mastery.strength > 2" href="regles/annexes/equipement#Les armes lourdes" label="Arme lourde" />
<PreviewA v-if="character.mastery.strength > 3" href="regles/annexes/equipement#Les armes à deux mains" label="Arme à deux mains" />
<PreviewA v-if="character.mastery.dexterity > 0 && character.mastery.strength > 1" href="regles/annexes/equipement#Les armes maniables" label="Arme maniable" />
<PreviewA v-if="character.mastery.dexterity > 1 && character.mastery.strength > 1" href="regles/annexes/equipement#Les armes à projectiles" label="Arme à projectiles" />
<PreviewA v-if="character.mastery.dexterity > 1 && character.mastery.strength > 2" href="regles/annexes/equipement#Les armes longues" label="Arme longue" />
<PreviewA v-if="character.mastery.shield > 0" href="regles/annexes/equipement#Les boucliers" label="Bouclier" />
<PreviewA v-if="character.mastery.shield > 0 && character.mastery.strength > 3" href="regles/annexes/equipement#Les boucliers à deux mains" label="Bouclier à deux mains" />
</div>
<div v-if="character.mastery.armor > 0" class="grid grid-cols-2 gap-x-3 gap-y-1 text-sm">
<PreviewA v-if="character.mastery.armor > 0" href="regles/annexes/equipement#Les armures légères" label="Armure légère" />
<PreviewA v-if="character.mastery.armor > 1" href="regles/annexes/equipement#Les armures" label="Armure standard" />
<PreviewA v-if="character.mastery.armor > 2" href="regles/annexes/equipement#Les armures lourdes" label="Armure lourde" />
</div>
<div class="grid grid-cols-2 gap-x-3 gap-y-1 text-sm">
<span>Précision: <span class="font-bold">{{ character.spellranks.precision }}</span></span>
<span>Savoir: <span class="font-bold">{{ character.spellranks.knowledge }}</span></span>
<span>Instinct: <span class="font-bold">{{ character.spellranks.instinct }}</span></span>
<span>Oeuvres: <span class="font-bold">{{ character.spellranks.arts }}</span></span>
</div>
</div>
</div>
<TabsRoot default-value="features" class="w-[60rem] max-h-full">
<TabsList class="flex flex-row relative px-4 gap-4">
<TabsIndicator class="absolute left-0 h-[3px] bottom-0 w-[--radix-tabs-indicator-size] translate-x-[--radix-tabs-indicator-position] transition-[width,transform] duration-300 bg-accent-blue"></TabsIndicator>
<TabsTrigger value="features" class="px-2 py-1 border-b border-transparent hover:border-accent-blue">Aptitudes</TabsTrigger>
<TabsTrigger value="spells" class="px-2 py-1 border-b border-transparent hover:border-accent-blue" v-if="character.spellslots > 0">Sorts</TabsTrigger>
<TabsTrigger value="inventory" class="px-2 py-1 border-b border-transparent hover:border-accent-blue" v-if="character.capacity !== false">Inventaire</TabsTrigger>
<TabsTrigger value="notes" class="px-2 py-1 border-b border-transparent hover:border-accent-blue">Notes</TabsTrigger>
</TabsList>
<TabsContent value="features" class="overflow-y-auto max-h-full">
<div class="flex flex-1 flex-col ps-8 gap-4 py-4">
<div class="grid grid-cols-3 gap-4">
<div class="flex flex-col col-span-2">
<span class="text-lg font-semibold">Actions</span>
<span class="text-sm text-light-70 dark:text-dark-70">Attaquer - Saisir - Faire chuter - Déplacer - Courir - Pas de coté - Lancer un sort - S'interposer - Se transformer - Utiliser un objet - Anticiper une action - Improviser</span>
<MarkdownRenderer :content="character.lists.action?.map(e => getText(e))?.join('\n')" :properties="{ tags: { a: preview } }" />
</div>
<div class="flex flex-col gap-2">
<div class="flex flex-col">
<span class="text-lg font-semibold">Réactions</span>
<span class="text-sm text-light-70 dark:text-dark-70">Parade - Esquive - Saisir une opportunité - Prendre en tenaille - Intercepter - Désarmer</span>
<MarkdownRenderer :content="character.lists.reaction?.map(e => getText(e))?.join('\n')" :properties="{ tags: { a: preview } }" />
</div>
<div class="flex flex-col">
<span class="text-lg font-semibold">Actions libre</span>
<span class="text-sm text-light-70 dark:text-dark-70">Analyser une situation - Communiquer</span>
<MarkdownRenderer :content="character.lists.freeaction?.map(e => getText(e))?.join('\n')" :properties="{ tags: { a: preview } }" />
</div>
</div>
</div>
<div class="flex flex-col">
<span class="text-lg font-semibold">Aptitudes</span>
<MarkdownRenderer :content="character.lists.passive?.map(e => getText(e))?.map(e => `> ${e}`).join('\n\n')" :properties="{ tags: { a: preview } }" />
</div>
</div>
</TabsContent>
<TabsContent v-if="character.spellslots > 0" value="spells" class="overflow-y-auto max-h-full">
<div class="flex flex-1 flex-col ps-8 gap-4 py-2">
<div class="flex flex-1 justify-between items-baseline px-2"><div></div><div class="flex gap-4 items-baseline"><span class="italic text-light-70 dark:text-dark-70 text-sm">{{ character.variables.spells.length }} / {{ character.spellslots }} sorts maitrisés</span><Button class="!font-normal" @click="openSpellPanel">Modifier</Button></div></div>
<div class="flex flex-col" v-if="[...(character.lists.spells ?? []), ...character.variables.spells].length > 0">
<div class="pb-4 px-2 mt-4 border-b last:border-none border-light-30 dark:border-dark-30 flex flex-col" v-for="spell of [...(character.lists.spells ?? []), ...character.variables.spells].map(e => config.spells.find((f: SpellConfig) => f.id === e)).filter(e => !!e)">
<div class="flex flex-row justify-between">
<span class="text-lg font-bold">{{ spell.name }}</span>
<div class="flex flex-row items-center gap-6">
<div class="flex flex-row text-sm gap-2">
<span v-for="element of spell.elements" :class="elementTexts[element].class" class="border !border-opacity-50 rounded-full !bg-opacity-20 px-2 py-px">{{ elementTexts[element].text }}</span>
</div>
<div class="flex flex-row text-sm gap-1">
<span class="" v-if="spell.rank !== 4">Rang {{ spell.rank }}</span><span v-if="spell.rank !== 4">/</span>
<span class="" v-if="spell.rank !== 4">{{ spellTypeTexts[spell.type] }}</span><span v-if="spell.rank !== 4">/</span>
<span class="">{{ spell.cost }} mana</span><span>/</span>
<span class="capitalize">{{ typeof spell.speed === 'string' ? spell.speed : `${spell.speed} minutes` }}</span>
</div>
</div>
</div>
<MarkdownRenderer :content="spell.effect" />
</div>
</div>
</div>
</TabsContent>
<TabsContent value="inventory" v-if="character.capacity !== false" class="overflow-y-auto max-h-full">
</TabsContent>
<TabsContent value="notes" class="overflow-y-auto max-h-full">
<div class="flex flex-1 flex-col ps-8 gap-4 py-8">
<MarkdownRenderer :content="character.notes" />
</div>
</TabsContent>
</TabsRoot>
</div>
</div>
</div>
<div v-else>
<Head>
<Title>d[any] - Erreur</Title>
</Head>
<div>Erreur de chargement</div>
</div> -->
</template>

View File

@@ -37,8 +37,8 @@
<script setup lang="ts">
import { Content, Editor } from '#shared/content.util';
import { button, loading } from '#shared/components.util';
import { dom, icon, text } from '#shared/dom.util';
import { modal, popper, tooltip } from '#shared/floating.util';
import { dom, icon } from '#shared/dom.util';
import { modal, tooltip } from '#shared/floating.util';
import { Toaster } from '#shared/components.util';
definePageMeta({

View File

@@ -3,8 +3,8 @@
<Title>d[any] - Mentions légales</Title>
</Head>
<div class="flex flex-col max-w-[1200px] p-16">
<ProseH3>Mentions Légales</ProseH3>
<ProseH4>Collecte et Traitement des Données Personnelles</ProseH4>
<h3 class="text-xl font-bold">Mentions Légales</h3>
<h4 class="text-lg font-semibold">Collecte et Traitement des Données Personnelles</h4>
Ce site collecte des données personnelles durant l'inscription et des données anonymes durant la navigation sur
le site dans un but de collecte statistiques.<br />
@@ -12,21 +12,21 @@
suppression de vos données personnelles. <br />
Pour exercer ces droits, vous pouvez vous rendre dans votre profil et selectionner l'option "Supprimer mon
compte" qui garanti une suppression de l'intégralité de vos données personnelles.
compte" qui garanti une suppression de l'intégralité de vos données personnelles.<br /><br />
<ProseH4>Utilisation des Cookies</ProseH4>
<h4 class="text-lg font-semibold">Utilisation des Cookies</h4>
Ce site utilise des cookies uniquement pour maintenir la connexion des utilisateurs et faciliter leur navigation
lors de chaque visite. Aucune information de suivi ou de profilage n'est réalisée. Ces cookies sont essentiels
au fonctionnement du site et ne nécessitent pas de consentement préalable. <br />
Vous pouvez gérer les cookies en configurant les paramètres de votre navigateur, mais la désactivation de ces
cookies pourrait affecter votre expérience de navigation.
cookies pourrait affecter votre expérience de navigation.<br /><br />
<ProseH4>Limitation de Responsabilité</ProseH4>
<h4 class="text-lg font-semibold">Limitation de Responsabilité</h4>
Les informations publiées sur ce site sont fournies à titre indicatif et peuvent contenir des erreurs. <br />
L'éditeur décline toute responsabilité quant à l'usage qui pourrait être fait de ces informations.
L'éditeur décline toute responsabilité quant à l'usage qui pourrait être fait de ces informations.<br /><br />
<ProseH4>Propriété Intellectuelle</ProseH4>
<h4 class="text-lg font-semibold">Propriété Intellectuelle</h4>
Tous les contenus présents sur ce site (textes, images, logos, etc.) sont protégés par les lois en vigueur
sur la propriété intellectuelle. Toute reproduction ou utilisation de ces contenus sans autorisation préalable
est interdite. <br /><br />

View File

@@ -1,53 +0,0 @@
<template>
<Head>
<Title>d[any] - Roadmap</Title>
</Head>
<div class="flex flex-col justify-start p-6">
<ProseH2>Roadmap</ProseH2>
<div class="grid grid-cols-4 gap-x-2 gap-y-4">
<div v-if="loggedIn && user && hasPermissions(user.permissions, ['admin'])" class="flex flex-col gap-2 justify-start">
<ProseH3>Administration</ProseH3>
<Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" checked disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class="text-light-60 dark:text-dark-60 line-through">Dashboard de statistiques</span></Label>
<Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" checked disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class="text-light-60 dark:text-dark-60 line-through">Editeur de permissions</span><ProseTag>prioritaire</ProseTag></Label>
<Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class=" ">Synchro project <-> GIT</span><ProseTag>prioritaire</ProseTag></Label>
<Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class=" ">Versionning automatisé, releases et newsletter</span></Label>
</div>
<div class="flex flex-col gap-2 justify-start">
<ProseH3>Editeur</ProseH3>
<Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" checked disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class="text-light-60 dark:text-dark-60 line-through">Edition de page</span></Label>
<Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" checked disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class="text-light-60 dark:text-dark-60 line-through">Edition riche de page</span></Label>
<Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class=" ">Edition live de page</span></Label>
<Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" checked disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class="text-light-60 dark:text-dark-60 line-through">Raccourcis d'edition</span></Label>
<Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class=" ">Affichage alternatif par page</span></Label>
</div>
<div class="flex flex-col gap-2 justify-start">
<ProseH3>Projet</ProseH3>
<Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" checked disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class="text-light-60 dark:text-dark-60 line-through">Edition du projet</span></Label>
<Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" checked disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class="text-light-60 dark:text-dark-60 line-through">Déplacement des fichiers</span></Label>
<Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class=" ">Configuration de droit du projet</span><ProseTag>prioritaire</ProseTag></Label>
<Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class=" ">Theme par projet</span></Label>
</div>
<div class="flex flex-col gap-2 justify-start">
<ProseH3>Nouvelles features</ProseH3>
<Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class=" ">Historique des modifs</span><ProseTag>prioritaire</ProseTag></Label><!-- Objet release: key hash, timestamp, version, name, description?. Objet edit: key hash, key property, value, timestamp -->
<Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class=" ">Commentaire par page</span></Label><!-- Object comment: key path, key comment_id, position, content, owner, following? -->
<Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class=" ">Type de fichier: Timeline</span></Label><!-- Propriétés: array of (from, (to || ponctual), ((title, content) || dedicated page)) -->
<Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class=" ">Type de fichier: Whiteboard</span></Label><!-- Tableau de données SVG -->
</div>
<div class="flex flex-col gap-2 justify-start">
<ProseH3>Utilisateur</ProseH3>
<Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" checked disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class="text-light-60 dark:text-dark-60 line-through">Validation du compte par mail<ProseTag>prioritaire</ProseTag></span></Label>
<!-- <Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class=" ">Modification de profil</span></Label> -->
<Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class=" ">Image de profil</span></Label>
<Label class="flex flex-row gap-2 items-center"><CheckboxRoot class="border border-light-35 dark:border-dark-35 w-6 h-6 flex justify-center items-center" disabled><CheckboxIndicator><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span class=" ">Préférence d'email</span></Label><!-- New features, newsletter et surveys -->
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { Icon } from '@iconify/vue/dist/iconify.js';
import { hasPermissions } from '~/shared/auth.util';
const { loggedIn, user } = useUserSession();
</script>

45
pages/usage.vue Normal file
View File

@@ -0,0 +1,45 @@
<template>
<Head>
<Title>d[any] - Mentions légales</Title>
</Head>
<div class="flex flex-col max-w-[1200px] p-16">
<h3 class="text-xl font-bold">Conditions Générales d'Utilisation du site d-any.com</h3>
<h4 class="text-lg font-semibold py-2">1. Objet</h4>
Le site d-any.com offre un service en ligne dédié au jeu de rôle comprenant une section de règles officielles maintenues par l'administrateur, une section permettant la création de personnages
publics ou privés et une section de campagnes visant à rassembler plusieurs joueurs pour faire interagir leurs personnages. L'utilisation du site implique l'acceptation pleine et entière des présentes conditions. <br/><br/>
<h4 class="text-lg font-semibold py-2">2. Accès et fonctionnement</h4>
L'accès au site est gratuit. L'interaction entre utilisateurs est strictement limitée aux personnages et joueurs participant à une même campagne partagée. Aucun contact direct ni interaction n'est possible en dehors de cette structure.<br/><br/>
<h4 class="text-lg font-semibold py-2">3. Création et gestion des personnages</h4>
Les utilisateurs peuvent créer des personnages publics, visibles par tous les membres des campagnes partagées, ou privés, visibles uniquement par leur créateur.
Les utilisateurs sont responsables du contenu des personnages qu'ils créent. Ils s'engagent à ne pas créer ou publier des personnages portant atteinte à la dignité, contenant des propos discriminatoires, diffamatoires, obscènes ou illicites.
L'administrateur du site se réserve le droit de supprimer ou masquer tout personnage en infraction avec ces règles.<br/><br/>
<h4 class="text-lg font-semibold py-2">4. Règles du jeu</h4>
Les règles officielles du jeu, rédigées et entretenues par l'administrateur, doivent être respectées par tous les utilisateurs dans la création et le déroulement des campagnes.<br/><br/>
<h4 class="text-lg font-semibold py-2">5. Interaction en campagne</h4>
Les communications et interactions entre joueurs et personnages sont strictement limitées aux campagnes partagées.
Toute interaction dans ces cadres doit respecter les règles de respect, de courtoisie et de fair-play.
Tout comportement abusif, harcèlement, propos haineux ou toute forme de contenu illicite est prohibé et pourra entraîner des sanctions, incluant la suppression de comptes ou personnages.<br/><br/>
<h4 class="text-lg font-semibold py-2">6. Propriété intellectuelle</h4>
Les règles, outils, et contenus hébergés sur le site sont la propriété de l'administrateur ou des auteurs respectifs.
Les personnages créés appartiennent à leurs auteurs, sous réserve du respect des droits d'auteur liés au jeu original et de la charte du site.<br/><br/>
<h4 class="text-lg font-semibold py-2">7. Données personnelles</h4>
Les données collectées se limitent à celles nécessaires au fonctionnement du site. Toute donnée personnelle est traitée conformément à la réglementation en vigueur et peut être modifiée ou supprimée sur demande.<br/><br/>
<h4 class="text-lg font-semibold py-2">8. Responsabilité</h4>
L'administrateur ne pourra être tenu responsable des usages faits par les utilisateurs des personnages publics ou des interactions au sein des campagnes. L'éditeur décline toute responsabilité en cas d'abus
entre joueurs ou de contenu illégal diffusé par un utilisateur.<br/><br/>
<h4 class="text-lg font-semibold py-2">9. Modification des conditions</h4>
Ces conditions peuvent être modifiées à tout moment par l'administrateur. Les utilisateurs seront informés des modifications via le site et l'usage continu vaudra acceptation des nouvelles conditions.<br/><br/>
<h4 class="text-lg font-semibold py-2">10. Droit applicable</h4>
Les présentes conditions sont soumises au droit français. Tout litige sera porté devant les tribunaux compétents.<br/><br/>
<div class="py-32"></div>
</div>
</template>

View File

@@ -20,6 +20,7 @@
<span class="ps-4 flex items-center gap-2" :class="{'text-light-red dark:text-dark-red': !checkedSymbol}"><Icon v-show="!checkedSymbol" icon="radix-icons:cross-2" />Un caractère special</span>
</div>
<TextInput type="password" label="Confirmation du mot de passe" autocomplete="new-password" v-model="confirmPassword" class="w-full md:w-auto"/>
<Label class="pb-2 col-span-2 md:col-span-1 flex flex-row gap-2 items-center"><CheckboxRoot v-model:checked="agreeOnRules" class="border border-light-35 dark:border-dark-35 hover:border-light-50 dark:hover:border-dark-50 w-5 h-5" ><CheckboxIndicator ><Icon icon="radix-icons:check" /></CheckboxIndicator></CheckboxRoot><span>J'ai lu et j'accepte les <NuxtLink class="text-accent-blue cursor-pointer" :to="{ name: 'usage' }" target="_blank">conditions d'utilisation</NuxtLink></span></Label>
<Button type="submit" class="border border-light-35 dark:border-dark-35 max-w-48 w-full order-9 col-span-2 md:col-span-1 m-auto" :loading="status === 'pending'">S'inscrire</Button>
<span class="mt-4 order-10 flex justify-center items-center gap-4 col-span-2 md:col-span-1 m-auto">Vous avez déjà un compte ?<NuxtLink class="text-center block text-sm font-semibold tracking-wide hover:text-accent-blue" :to="{ name: 'user-login' }">Se connecter</NuxtLink></span>
</form>
@@ -30,7 +31,7 @@
import { ZodError } from 'zod/v4';
import { schema, type Registration } from '~/schemas/registration';
import { Icon } from '@iconify/vue/dist/iconify.js';
import { Toaster } from '#shared/components.util';
import { floater, Toaster } from '#shared/components.util';
definePageMeta({
layout: 'login',
@@ -50,6 +51,7 @@ const checkedLower = computed(() => state.password.toUpperCase() !== state.passw
const checkedUpper = computed(() => state.password.toLowerCase() !== state.password);
const checkedDigit = computed(() => /[0-9]/.test(state.password));
const checkedSymbol = computed(() => " !\"#$%&'()*+,-./:;<=>?@[]^_`{|}~".split("").some(e => state.password.includes(e)));
const agreeOnRules = ref<boolean>(false);
const { data: result, status, error, refresh } = await useFetch('/api/auth/register', {
body: state,
@@ -57,7 +59,7 @@ const { data: result, status, error, refresh } = await useFetch('/api/auth/regis
method: 'POST',
watch: false,
ignoreResponseError: true,
})
});
async function submit()
{
@@ -69,6 +71,8 @@ async function submit()
return Toaster.add({ content: 'Veuillez saisir un mot de passe', timer: true, duration: 10000 });
if(state.password !== confirmPassword.value)
return Toaster.add({ content: 'Les deux mots de passe saisis ne correspondent pas', timer: true, duration: 10000 });
if(agreeOnRules.value !== true)
return Toaster.add({ content: 'Veuillez accepter des conditions d\'utilisations pour vous inscrire', timer: true, duration: 10000 });
const data = schema.safeParse(state);