Add redirect URL when logging in, fix choices for characters not being saved
This commit is contained in:
parent
04534b2530
commit
7021264c11
|
|
@ -4,15 +4,11 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
|
|||
const { loggedIn, fetch, user } = useUserSession();
|
||||
const meta = to.meta;
|
||||
|
||||
await fetch()
|
||||
await fetch();
|
||||
|
||||
if(!!meta.guestsGoesTo && !loggedIn.value)
|
||||
if(meta.requiresAuth && !loggedIn.value)
|
||||
{
|
||||
return navigateTo(meta.guestsGoesTo);
|
||||
}
|
||||
else if(meta.requireAuth && !loggedIn.value)
|
||||
{
|
||||
return abortNavigation({ statusCode: 401, message: 'Unauthorized', });
|
||||
return navigateTo({ name: 'user-login', query: { t: encodeURIComponent(to.path) } });
|
||||
}
|
||||
else if(!!meta.usersGoesTo && loggedIn.value)
|
||||
{
|
||||
|
|
@ -25,13 +21,9 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
|
|||
else if(!!meta.rights)
|
||||
{
|
||||
if(!user.value)
|
||||
{
|
||||
return abortNavigation({ statusCode: 401, message: 'Unauthorized', });
|
||||
}
|
||||
else if(!hasPermissions(user.value.permissions, meta.rights))
|
||||
{
|
||||
return abortNavigation({ statusCode: 401, message: 'Unauthorized', });
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { unifySlug } from '#shared/general.util';
|
|||
import { CampaignSheet } from '#shared/campaign.util';
|
||||
|
||||
definePageMeta({
|
||||
guestsGoesTo: '/user/login',
|
||||
requiresAuth: true,
|
||||
});
|
||||
|
||||
const id = unifySlug(useRoute().params.id ?? '');
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import { Toaster } from '#shared/components.util';
|
||||
|
||||
definePageMeta({
|
||||
guestsGoesTo: '/user/login',
|
||||
requiresAuth: true,
|
||||
});
|
||||
|
||||
const { user, loggedIn } = useUserSession();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { CharacterBuilder } from '#shared/character.util';
|
|||
import { unifySlug } from '#shared/general.util';
|
||||
|
||||
definePageMeta({
|
||||
guestsGoesTo: '/user/login',
|
||||
requiresAuth: true,
|
||||
validState: true,
|
||||
});
|
||||
const id = unifySlug(useRouter().currentRoute.value.params.id ?? "new");
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { Toaster } from '#shared/components.util';
|
|||
import type { CharacterConfig } from '~/types/character';
|
||||
|
||||
definePageMeta({
|
||||
guestsGoesTo: '/user/login',
|
||||
requiresAuth: true,
|
||||
})
|
||||
const { data: characters, error, status } = await useFetch(`/api/character`);
|
||||
const config = characterConfig as CharacterConfig;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { HomebrewBuilder } from '#shared/feature.util';
|
|||
|
||||
|
||||
definePageMeta({
|
||||
guestsGoesTo: '/user/login',
|
||||
requiresAuth: true,
|
||||
});
|
||||
|
||||
const container = useTemplateRef('container');
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import { Toaster } from '#shared/components.util';
|
|||
|
||||
definePageMeta({
|
||||
layout: 'login',
|
||||
guestsGoesTo: '/user/login',
|
||||
requiresAuth: true,
|
||||
});
|
||||
|
||||
const { user } = useUserSession();
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<span class="border border-transparent hover:border-light-35 dark:hover:border-dark-35 p-1 cursor-pointer" @click="() => $router.go(-1)"><Icon icon="radix-icons:arrow-left" class="text-light-50 dark:text-dark-50 w-6 h-6"/></span>
|
||||
<h4 class="text-xl font-bold">Connexion</h4>
|
||||
</div>
|
||||
<form @submit.prevent="() => submit()" class="flex flex-1 flex-col justify-center items-stretch">
|
||||
<form @submit.prevent="submit" class="flex flex-1 flex-col justify-center items-stretch">
|
||||
<TextInput type="text" label="Utilisateur ou email" name="username" autocomplete="username email" v-model="state.usernameOrEmail"/>
|
||||
<TextInput type="password" label="Mot de passe" name="password" autocomplete="current-password" v-model="state.password"/>
|
||||
<Button type="submit" class="border border-light-35 dark:border-dark-35 self-center" :loading="status === 'pending'">Se connecter</Button>
|
||||
|
|
@ -63,7 +63,10 @@ async function submit()
|
|||
{
|
||||
Toaster.clear();
|
||||
Toaster.add({ duration: 10000, content: 'Vous êtes maintenant connecté', timer: true, type: 'success' });
|
||||
useRouter().push({ name: 'user-profile' });
|
||||
|
||||
const router = useRouter();
|
||||
const target = router.currentRoute.value.query?.t as string | undefined;
|
||||
router.push(target ? decodeURIComponent(target) : { name: 'user-profile' });
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { hasPermissions } from "#shared/auth.util";
|
|||
import { Toaster } from '#shared/components.util';
|
||||
|
||||
definePageMeta({
|
||||
guestsGoesTo: '/user/login',
|
||||
requiresAuth: true,
|
||||
})
|
||||
const { user, clear } = useUserSession();
|
||||
const loading = ref<boolean>(false);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ declare module 'vue-router'
|
|||
interface RouteMeta
|
||||
{
|
||||
requiresAuth?: boolean;
|
||||
guestsGoesTo?: string;
|
||||
usersGoesTo?: string;
|
||||
rights?: string[];
|
||||
validState?: boolean;
|
||||
|
|
|
|||
|
|
@ -62,6 +62,9 @@ export default defineEventHandler(async (e) => {
|
|||
|
||||
const abilities = Object.entries(body.data.abilities).filter(e => e[1] !== undefined).map(e => ({ character: id, ability: e[0] as Ability, value: e[1], max: 0 }));
|
||||
if(abilities.length > 0) tx.insert(characterAbilitiesTable).values(abilities).run();
|
||||
|
||||
const choices = Object.entries(body.data.choices).flatMap(e => e[1].map(_e => ({ character: id, id: e[0], choice: _e })));
|
||||
if(choices.length > 0) tx.insert(characterChoicesTable).values(choices).run();
|
||||
});
|
||||
|
||||
setResponseStatus(e, 200);
|
||||
|
|
|
|||
|
|
@ -305,4 +305,8 @@ export class CampaignSheet
|
|||
])
|
||||
];
|
||||
}
|
||||
settings()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -558,6 +558,7 @@ export class CharacterBuilder extends CharacterCompiler
|
|||
private _content?: RedrawableHTML;
|
||||
private _stepsHeader: RedrawableHTML[] = [];
|
||||
private _steps: Array<BuilderTabConstructor> = [];
|
||||
private _currentStep: number = 0;
|
||||
private _helperText!: Text;
|
||||
private id?: string;
|
||||
|
||||
|
|
@ -621,12 +622,20 @@ export class CharacterBuilder extends CharacterCompiler
|
|||
this._content = dom('div', { class: 'flex-1 outline-none max-w-full w-full overflow-y-auto', attributes: { id: 'characterEditorContainer' } });
|
||||
this._container.appendChild(div('flex flex-1 flex-col justify-start items-center px-8 w-full h-full overflow-y-hidden', [
|
||||
div("flex w-full flex-row gap-4 items-center justify-between px-4 bg-light-0 dark:bg-dark-0 z-20", [
|
||||
div('flex flex-row gap-2', [ floater(tooltip(button(icon('radix-icons:pencil-2', { width: 16, height: 16 }), undefined, 'p-1'), 'Notes publics', 'left'), [ publicNotes.dom ], { pinned: true, events: { show: ['click'], hide: [] }, title: 'Notes publics', position: 'bottom-start' }), floater(tooltip(button(icon('radix-icons:eye-none', { width: 16, height: 16 }), undefined, 'p-1'), 'Notes privés', 'right'), [ privateNotes.dom ], { pinned: true, events: { show: ['click'], hide: [] }, title: 'Notes privés', position: 'bottom-start' }) ]), div("flex w-full flex-row gap-4 items-center justify-center relative", this._stepsHeader), div(undefined, [ tooltip(icon("radix-icons:question-mark-circled", { height: 20, width: 20 }), this._helperText, "bottom-end") ]),
|
||||
div('flex flex-row gap-2', [ floater(tooltip(button(icon('radix-icons:pencil-2', { width: 16, height: 16 }), undefined, 'p-1'), 'Notes publics', 'left'), [ publicNotes.dom ], { pinned: true, events: { show: ['click'], hide: [] }, title: 'Notes publics', position: 'bottom-start' }), floater(tooltip(button(icon('radix-icons:eye-none', { width: 16, height: 16 }), undefined, 'p-1'), 'Notes privés', 'right'), [ privateNotes.dom ], { pinned: true, events: { show: ['click'], hide: [] }, title: 'Notes privés', position: 'bottom-start' }) ]), div("flex w-full flex-row gap-4 items-center justify-center relative", this._stepsHeader), div('flex flex-row gap-2', [ tooltip(button(icon("radix-icons:chevron-right", { height: 16, width: 16 }), () => this.next(), 'p-1'), 'Suivant', "bottom"), tooltip(button(icon("radix-icons:paper-plane", { height: 16, width: 16 }), () => this.save(), 'p-1'), 'Enregistrer', "bottom"), tooltip(icon("radix-icons:question-mark-circled", { height: 20, width: 20 }), this._helperText, "bottom-end") ]),
|
||||
]),
|
||||
this._content,
|
||||
]));
|
||||
}
|
||||
display(step: number)
|
||||
previous()
|
||||
{
|
||||
this.display(this._currentStep - 1);
|
||||
}
|
||||
next()
|
||||
{
|
||||
this.display(this._currentStep + 1);
|
||||
}
|
||||
private display(step: number)
|
||||
{
|
||||
if(step < 0 || step >= this._stepsHeader.length)
|
||||
return;
|
||||
|
|
@ -638,15 +647,15 @@ export class CharacterBuilder extends CharacterCompiler
|
|||
Toaster.add({ title: 'Erreur de validation', content: this._steps[i]!.errorMessage, type: 'error', duration: 25000, timer: true })
|
||||
return;
|
||||
}
|
||||
else
|
||||
{}
|
||||
}
|
||||
if(step !== 0 && this._steps.slice(0, step).some(e => !e.validate(this)))
|
||||
return;
|
||||
|
||||
this._stepsHeader.forEach(e => e.setAttribute('data-state', 'inactive'));
|
||||
this._stepsHeader[this._currentStep]!.setAttribute('data-state', 'inactive');
|
||||
this._stepsHeader[step]!.setAttribute('data-state', 'active');
|
||||
|
||||
this._currentStep = step;
|
||||
|
||||
this._content?.replaceChildren(...(new this._steps[step]!(this)).dom);
|
||||
|
||||
this._helperText.textContent = this._steps[step]!.description;
|
||||
|
|
@ -676,7 +685,6 @@ export class CharacterBuilder extends CharacterCompiler
|
|||
}
|
||||
else
|
||||
{
|
||||
//@ts-ignore
|
||||
await useRequestFetch()(`/api/character/${this._character.id}`, {
|
||||
method: 'post',
|
||||
body: this._character,
|
||||
|
|
@ -793,7 +801,7 @@ export class CharacterBuilder extends CharacterCompiler
|
|||
if(choices.length === 0)
|
||||
return;
|
||||
|
||||
const menu = followermenu(element, [ div('px-24 py-6 flex flex-col items-center text-light-100 dark:text-dark-100', choices.map(e => div('flex flex-row items-center', [ text(e.text), div('flex flex-col', Array(e.settings?.amount ?? 1).fill(0).map((_, i) => (
|
||||
const menu = followermenu(element, [ div('px-24 py-6 flex flex-col items-center text-light-100 dark:text-dark-100', choices.map(e => div('flex flex-row items-center', [ text(e.text), div('flex flex-col gap-2', Array(e.settings?.amount ?? 1).fill(0).map((_, i) => (
|
||||
select(e.options.map((_e, _i) => ({ text: _e.text, value: _i })), { defaultValue: this._character.choices![e.id] !== undefined ? this._character.choices![e.id]![i] : undefined, change: (value) => {
|
||||
this._character.choices![e.id] ??= [];
|
||||
this._character.choices![e.id]![i] = value;
|
||||
|
|
@ -862,7 +870,6 @@ class PeoplePicker extends BuilderTab
|
|||
dom("span", { class: "md:text-base text-sm", text: "Privé ?" }),
|
||||
this._visibilityInput,
|
||||
]),
|
||||
button(text('Suivant'), () => this._builder.display(1), 'h-[35px] px-[15px]'),
|
||||
]), div('flex flex-1 gap-4 p-2 overflow-x-auto justify-center', this._options)];
|
||||
|
||||
this.update();
|
||||
|
|
@ -934,7 +941,6 @@ class LevelPicker extends BuilderTab
|
|||
dom("span", { text: "Mana" }),
|
||||
text(() => this._builder.compiled.mana),
|
||||
]),
|
||||
button(text('Suivant'), () => this._builder.display(2), 'h-[35px] px-[15px]'),
|
||||
]), div('flex flex-col flex-1 gap-4 mx-8 my-4', this._options.flatMap(e => [...e]))];
|
||||
|
||||
this.update();
|
||||
|
|
@ -1023,7 +1029,6 @@ class TrainingPicker extends BuilderTab
|
|||
dom("span", { text: "Mana" }),
|
||||
text(() => this._builder.compiled.mana),
|
||||
]),
|
||||
button(text('Suivant'), () => this._builder.display(3), 'h-[35px] px-[15px]'),
|
||||
]), dom('span')
|
||||
]), div('flex flex-1 px-6 overflow-hidden max-w-full', [ this._statContainer ])];
|
||||
|
||||
|
|
@ -1098,7 +1103,6 @@ class AbilityPicker extends BuilderTab
|
|||
dom("span", { class: "md:text-base text-sm", text: "Points restantes" }),
|
||||
this._pointsInput,
|
||||
]),
|
||||
button(text('Suivant'), () => this._builder.display(4), 'h-[35px] px-[15px]'),
|
||||
]), div('flex flex-row flex-wrap justify-center items-center flex-1 gap-12 mx-8 my-4 px-48', this._options)];
|
||||
|
||||
this.update();
|
||||
|
|
@ -1203,7 +1207,6 @@ class AspectPicker extends BuilderTab
|
|||
dom("span", { class: "md:text-base text-sm", text: "Filtrer ?" }),
|
||||
filterSwitch,
|
||||
]),
|
||||
button(text('Enregistrer'), () => this._builder.save(), 'h-[35px] px-[15px]'),
|
||||
]), div('flex flex-row flex-wrap justify-center items-center flex-1 gap-8 mx-8 my-4 px-8', this._options)];
|
||||
|
||||
this.update();
|
||||
|
|
@ -1631,7 +1634,7 @@ export class CharacterSheet
|
|||
div("flex flex-row items-center justify-center gap-4", [
|
||||
div("flex flex-row items-center justify-center gap-2", [ dom("div", { class: 'text-lg font-semibold', text: "Actions" }), proses('a', preview, [ icon('radix-icons:question-mark-circled', { width: 16, height: 16, class: 'text-light-70 dark:text-dark-70' }) ], { href: 'regles/le-combat/actions-en-combat#Actions', class: 'h-4' }) ]),
|
||||
div("flex flex-1 border-t border-dashed border-light-50 dark:border-dark-50"),
|
||||
div('flex flex-row items-center gap-2', [ ...Array(character.action).fill(undefined).map(e => div('border border-dashed border-light-50 dark:border-dark-50 w-5 h-5')), dom('span', { class: 'tracking-tight', text: '/ round' }) ]),
|
||||
div('flex flex-row items-center gap-2', [ ...Array(3).fill(undefined).map(e => div('border border-dashed border-light-50 dark:border-dark-50 w-5 h-5')), dom('span', { class: 'tracking-tight', text: '/ round' }) ]),
|
||||
]),
|
||||
|
||||
div('flex flex-col gap-2', [
|
||||
|
|
@ -1646,7 +1649,7 @@ export class CharacterSheet
|
|||
div("flex flex-row items-center justify-center gap-4", [
|
||||
div("flex flex-row items-center justify-center gap-2", [ dom("div", { class: 'text-lg font-semibold', text: "Réactions" }), proses('a', preview, [ icon('radix-icons:question-mark-circled', { width: 16, height: 16, class: 'text-light-70 dark:text-dark-70' }) ], { href: 'regles/le-combat/actions-en-combat#Réaction', class: 'h-4' }) ]),
|
||||
div("flex flex-1 border-t border-dashed border-light-50 dark:border-dark-50"),
|
||||
div('flex flex-row items-center gap-2', [ ...Array(character.reaction).fill(undefined).map(e => div('border border-dashed border-light-50 dark:border-dark-50 w-5 h-5')), dom('span', { class: 'tracking-tight', text: '/ round' }) ]),
|
||||
div('flex flex-row items-center gap-2', [ ...Array(2).fill(undefined).map(e => div('border border-dashed border-light-50 dark:border-dark-50 w-5 h-5')), dom('span', { class: 'tracking-tight', text: '/ round' }) ]),
|
||||
]),
|
||||
|
||||
div('flex flex-col gap-2', [
|
||||
|
|
@ -1956,18 +1959,15 @@ export class CharacterSheet
|
|||
if(!id) return true;
|
||||
|
||||
const item = config.items[id]!;
|
||||
if(enchant.restrictions?.type && item.category === enchant.restrictions.type)
|
||||
{
|
||||
switch(item.category)
|
||||
{
|
||||
case 'armor':
|
||||
return enchant.restrictions.subtype ? item.type === enchant.restrictions.subtype : true;
|
||||
case 'weapon':
|
||||
return enchant.restrictions.subtype ? item.type.includes(enchant.restrictions.subtype) : true;
|
||||
default: return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
if(!enchant.restrictions)
|
||||
return true;
|
||||
if(enchant.restrictions.includes(item.category))
|
||||
return true;
|
||||
else if(item.category === 'armor' && enchant.restrictions.includes(`armor/${item.type}`))
|
||||
return true;
|
||||
else if(item.category === 'weapon' && item.type.some(e => enchant.restrictions!.includes(`weapon/${e}`)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
const itempower = () => current.item && config.items[current.item.id] !== undefined ? ((config.items[current.item.id]!.powercost ?? 0) + (current.item.enchantments?.reduce((_p, _v) => (config.enchantments[_v]?.power ?? 0) + _p, 0) ?? 0)) : 0;
|
||||
|
|
|
|||
Loading…
Reference in New Issue