Typo fixes, add spell range to sheet and remove useContent

This commit is contained in:
Clément Pons 2025-10-21 17:49:21 +02:00
parent 25bd165f1d
commit 73b0fdf3f5
16 changed files with 15 additions and 85 deletions

View File

@ -1,64 +0,0 @@
import { Content } from '~/shared/content.util';
import type { ExploreContent, ContentComposable, TreeItem } from '~/types/content';
const useContentState = () => useState<ExploreContent[]>('content', () => []);
export function useContent(): ContentComposable {
const contentState = useContentState();
return {
content: contentState,
tree: computed(() => {
const arr: TreeItem[] = [];
for(const element of contentState.value)
{
addChild(arr, element);
}
return arr;
}),
fetch,
get,
}
}
async function fetch(force: boolean = false) {
const content = useContentState();
if(content.value.length === 0 || force)
content.value = await useRequestFetch()('/api/file/overview');
}
async function get(path: string, force: boolean = false): Promise<ExploreContent | undefined> {
const content = useContentState()
const value = content.value;
const item = value.find(e => e.path === path);
if(item && !item.content)
{
item.content = await useRequestFetch()(`/api/file/content/${encodeURIComponent(path)}`);
}
content.value = value;
return item;
}
function addChild(arr: TreeItem[], e: ExploreContent): void {
const parent = arr.find(f => e.path.startsWith(f.path));
if(parent)
{
if(!parent.children)
parent.children = [];
addChild(parent.children, e);
}
else
{
arr.push({ ...e });
arr.sort((a, b) => {
if(a.order !== b.order)
return a.order - b.order;
return a.title.localeCompare(b.title);
});
}
}

BIN
db.sqlite

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -60,7 +60,6 @@ import { link } from '#shared/components.util';
const open = ref(false); const open = ref(false);
const { loggedIn, user } = useUserSession(); const { loggedIn, user } = useUserSession();
const { fetch } = useContent();
await fetch(false); await fetch(false);
@ -82,7 +81,6 @@ const tree = new TreeDOM((item, depth) => {
], { class: ['flex flex-1 items-center hover:border-accent-blue hover:text-accent-purple max-w-full'], attributes: { 'data-private': item.private }, active: 'text-accent-blue' }, item.path ? { name: 'explore-path', params: { path: item.path } } : undefined )]); ], { class: ['flex flex-1 items-center hover:border-accent-blue hover:text-accent-purple max-w-full'], attributes: { 'data-private': item.private }, active: 'text-accent-blue' }, item.path ? { name: 'explore-path', params: { path: item.path } } : undefined )]);
}, (item) => item.navigable); }, (item) => item.navigable);
(path.value?.split('/').map((e, i, a) => a.slice(0, i).join('/')) ?? []).forEach(e => tree.toggle(tree.tree.search('path', e)[0], true)); (path.value?.split('/').map((e, i, a) => a.slice(0, i).join('/')) ?? []).forEach(e => tree.toggle(tree.tree.search('path', e)[0], true));
const treeParent = useTemplateRef('treeParent');
const unmount = useRouter().afterEach((to, from, failure) => { const unmount = useRouter().afterEach((to, from, failure) => {
if(failure) if(failure)
@ -95,6 +93,7 @@ watch(route, () => {
open.value = false; open.value = false;
}); });
const treeParent = useTemplateRef('treeParent');
onMounted(() => { onMounted(() => {
if(treeParent.value) if(treeParent.value)
treeParent.value.appendChild(tree.container); treeParent.value.appendChild(tree.container);

View File

@ -2,13 +2,9 @@ import { hasPermissions } from "#shared/auth.util";
export default defineNuxtRouteMiddleware(async (to, from) => { export default defineNuxtRouteMiddleware(async (to, from) => {
const { loggedIn, fetch, user } = useUserSession(); const { loggedIn, fetch, user } = useUserSession();
const { fetch: fetchContent } = useContent();
const meta = to.meta; const meta = to.meta;
if(await fetch()) await fetch()
{
fetchContent(true);
}
if(!!meta.guestsGoesTo && !loggedIn.value) if(!!meta.guestsGoesTo && !loggedIn.value)
{ {
@ -34,7 +30,7 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
} }
else if(!hasPermissions(user.value.permissions, meta.rights)) else if(!hasPermissions(user.value.permissions, meta.rights))
{ {
return abortNavigation({ statusCode: 401, message: 'Unauthorized', }); return abortNavigation({ statusCode: 401, message: 'Unauthorized', });
} }
} }

View File

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { CharacterBuilder } from '#shared/character.util'; import { CharacterBuilder } from '#shared/character.util';
import { unifySlug } from '~/shared/general.util'; import { unifySlug } from '#shared/general.util';
definePageMeta({ definePageMeta({
guestsGoesTo: '/user/login', guestsGoesTo: '/user/login',

View File

@ -3,6 +3,7 @@ import characterConfig from '#shared/character-config.json';
import { unifySlug } from '#shared/general.util'; import { unifySlug } from '#shared/general.util';
import type { CharacterConfig } from '~/types/character'; import type { CharacterConfig } from '~/types/character';
import { CharacterSheet } from '#shared/character.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-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 text-light-blue dark:text-dark-blue border-light-blue dark:border-dark-blue bg-light-blue dark:bg-dark-blue
@ -26,7 +27,7 @@ onMounted(() => {
if(container.value && id) if(container.value && id)
{ {
const character = new CharacterSheet(id, user); const character = new CharacterSheet(id, user);
container.value.replaceWith(character.container); container.value.appendChild(character.container);
} }
}); });
}); });

View File

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { HomebrewBuilder } from '~/shared/feature.util'; import { HomebrewBuilder } from '#shared/feature.util';
definePageMeta({ definePageMeta({

View File

@ -41,8 +41,6 @@ const { data: result, status, error, refresh } = await useFetch('/api/auth/login
ignoreResponseError: true, ignoreResponseError: true,
}) })
const toastMessage = ref('');
async function submit() async function submit()
{ {
if(state.usernameOrEmail === "") if(state.usernameOrEmail === "")
@ -65,7 +63,7 @@ async function submit()
{ {
Toaster.clear(); Toaster.clear();
Toaster.add({ duration: 10000, content: 'Vous êtes maintenant connecté', timer: true, type: 'success' }); Toaster.add({ duration: 10000, content: 'Vous êtes maintenant connecté', timer: true, type: 'success' });
await navigateTo('/user/profile'); useRouter().push({ name: 'user-profile' });
} }
} }
else else

View File

@ -1,5 +1,5 @@
import useDatabase from '~/composables/useDatabase'; import useDatabase from '~/composables/useDatabase';
import { hasPermissions } from '~/shared/auth.util'; import { hasPermissions } from '#shared/auth.util';
export default defineEventHandler(async (e) => { export default defineEventHandler(async (e) => {
const session = await getUserSession(e); const session = await getUserSession(e);

View File

@ -1,8 +1,8 @@
import { eq, SQL, type Operators } from 'drizzle-orm'; import { eq, SQL, type Operators } from 'drizzle-orm';
import useDatabase from '~/composables/useDatabase'; import useDatabase from '~/composables/useDatabase';
import { characterTable, userPermissionsTable } from '~/db/schema'; import { characterTable, userPermissionsTable } from '~/db/schema';
import { hasPermissions } from '~/shared/auth.util'; import { hasPermissions } from '#shared/auth.util';
import { group } from '~/shared/general.util'; import { group } from '#shared/general.util';
import type { Character, MainStat, TrainingLevel } from '~/types/character'; import type { Character, MainStat, TrainingLevel } from '~/types/character';
export default defineEventHandler(async (e) => { export default defineEventHandler(async (e) => {

View File

@ -1,6 +1,6 @@
import useDatabase from '~/composables/useDatabase'; import useDatabase from '~/composables/useDatabase';
import { characterTable } from '~/db/schema'; import { characterTable } from '~/db/schema';
import { group } from '~/shared/general.util'; import { group } from '#shared/general.util';
import type { Character, CharacterVariables, Level, MainStat, TrainingLevel } from '~/types/character'; import type { Character, CharacterVariables, Level, MainStat, TrainingLevel } from '~/types/character';
export default defineEventHandler(async (e) => { export default defineEventHandler(async (e) => {

View File

@ -1,7 +1,7 @@
import { eq } from 'drizzle-orm'; import { eq } from 'drizzle-orm';
import useDatabase from '~/composables/useDatabase'; import useDatabase from '~/composables/useDatabase';
import { characterTable } from '~/db/schema'; import { characterTable } from '~/db/schema';
import { CharacterVariablesValidation } from '~/shared/character.util'; import { CharacterVariablesValidation } from '#shared/character.util';
import type { CharacterVariables } from '~/types/character'; import type { CharacterVariables } from '~/types/character';
export default defineEventHandler(async (e) => { export default defineEventHandler(async (e) => {

View File

@ -17,7 +17,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue'; import { computed } from 'vue';
import Bun from 'bun'; import Bun from 'bun';
import { format } from '~/shared/general.util'; import { format } from '#shared/general.util';
const { id, userId, username, timestamp } = defineProps<{ const { id, userId, username, timestamp } = defineProps<{
id: number id: number

View File

@ -1563,7 +1563,7 @@ export class CharacterSheet
div('flex flex-row items-center gap-4', [ dom('span', { class: 'font-semibold text-lg', text: e.spell.name ?? 'Inconnu' }), div('flex-1 border-b border-dashed border-light-50 dark:border-dark-50'), dom('span', { class: 'text-light-70 dark:text-dark-70', text: `${e.spell.cost ?? 0} mana` }) ]), div('flex flex-row items-center gap-4', [ dom('span', { class: 'font-semibold text-lg', text: e.spell.name ?? 'Inconnu' }), div('flex-1 border-b border-dashed border-light-50 dark:border-dark-50'), dom('span', { class: 'text-light-70 dark:text-dark-70', text: `${e.spell.cost ?? 0} mana` }) ]),
div('flex flex-row justify-between items-center gap-2 text-light-70 dark:text-dark-70', [ div('flex flex-row justify-between items-center gap-2 text-light-70 dark:text-dark-70', [
div('flex flex-row gap-2', [ span('flex flex-row', e.spell.rank === 4 ? 'Sort unique' : `Sort ${e.spell.type === 'instinct' ? 'd\'instinct' : e.spell.type === 'knowledge' ? 'de savoir' : 'de précision'} de rang ${e.spell.rank}`), ...(e.spell.elements ?? []).map(elementDom) ]), div('flex flex-row gap-2', [ span('flex flex-row', e.spell.rank === 4 ? 'Sort unique' : `Sort ${e.spell.type === 'instinct' ? 'd\'instinct' : e.spell.type === 'knowledge' ? 'de savoir' : 'de précision'} de rang ${e.spell.rank}`), ...(e.spell.elements ?? []).map(elementDom) ]),
div('flex flex-row gap-2', [ e.spell.concentration ? proses('a', preview, [span('italic text-sm', 'concentration')], { href: '' }) : undefined, span(undefined, typeof e.spell.speed === 'number' ? `${e.spell.speed} minute${e.spell.speed > 1 ? 's' : ''}` : e.spell.speed) ]) div('flex flex-row gap-4 items-center', [ e.spell.concentration ? proses('a', preview, [span('italic text-sm', 'concentration')], { href: '' }) : undefined, span(undefined, typeof e.spell.range === 'number' && e.spell.range > 0 ? `${e.spell.range} case${e.spell.range > 1 ? 's' : ''}` : e.spell.range === 0 ? 'toucher' : 'personnel'), span(undefined, typeof e.spell.speed === 'number' ? `${e.spell.speed} minute${e.spell.speed > 1 ? 's' : ''}` : e.spell.speed) ])
]), ]),
div('flex flex-row ps-4 p-1 border-l-4 border-light-35 dark:border-dark-35', [ markdown(e.spell.description) ]), div('flex flex-row ps-4 p-1 border-l-4 border-light-35 dark:border-dark-35', [ markdown(e.spell.description) ]),
]) : undefined })); ]) : undefined }));