feat: settings user
This commit is contained in:
parent
9e43d220d7
commit
3c538499c8
7 changed files with 156 additions and 74 deletions
|
@ -1,26 +1,10 @@
|
|||
import { API_URL } from '$env/static/private';
|
||||
import { error, redirect, type Actions, fail } from '@sveltejs/kit';
|
||||
import { error, redirect, type Actions } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
import type Puzzle from '$lib/components/Puzzle.svelte';
|
||||
import type { Chapter } from '$lib/types';
|
||||
|
||||
import { superValidate } from 'sveltekit-superforms/server';
|
||||
import { z } from 'zod';
|
||||
|
||||
const puzzleSchema = z.object({
|
||||
// answer: z.string().trim(),
|
||||
// answer need to be filled
|
||||
answer: z
|
||||
.string({
|
||||
required_error: 'Réponse manquante'
|
||||
})
|
||||
.refine((val) => val.trim() !== '', {
|
||||
message: 'Réponse manquante'
|
||||
}),
|
||||
file: z.any().optional()
|
||||
});
|
||||
|
||||
export const load = (async ({ parent, fetch, cookies, params: { chapterId, puzzleId } }) => {
|
||||
await parent();
|
||||
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
import { goto } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
|
||||
import { Loader2 } from 'lucide-svelte';
|
||||
|
||||
import { marked, type MarkedOptions } from 'marked';
|
||||
|
||||
import { cn } from '$lib';
|
||||
import { addToast } from '$lib/components/Toaster.svelte';
|
||||
import Button from '$lib/components/ui/Button.svelte';
|
||||
import Input from '$lib/components/ui/Input.svelte';
|
||||
|
@ -17,6 +18,8 @@
|
|||
$: puzzle = data.puzzle;
|
||||
$: chapterId = $page.params.chapterId;
|
||||
|
||||
let submitting = false;
|
||||
|
||||
const renderer = new marked.Renderer();
|
||||
|
||||
renderer.link = (href, title, text) => {
|
||||
|
@ -56,6 +59,8 @@
|
|||
method="POST"
|
||||
enctype="multipart/form-data"
|
||||
use:enhance={async ({ formData, cancel }) => {
|
||||
submitting = true;
|
||||
|
||||
if (formData.get('answer') === '') {
|
||||
addToast({
|
||||
data: {
|
||||
|
@ -112,6 +117,8 @@
|
|||
});
|
||||
}
|
||||
|
||||
submitting = false;
|
||||
|
||||
return async ({ result }) => {
|
||||
if (result.type === 'redirect') {
|
||||
goto(result.location, {
|
||||
|
@ -125,9 +132,7 @@
|
|||
<div class="flex flex-col gap-y-2">
|
||||
<label for="answer">Réponse</label>
|
||||
<textarea
|
||||
class={cn(
|
||||
'flex h-10 w-full rounded-md border border-primary-600 bg-highlight-primary px-3 py-2 text-sm ring-offset-highlight-primary file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted focus:bg-primary-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50'
|
||||
)}
|
||||
class="flex h-10 w-full rounded-md border border-primary-600 bg-highlight-primary px-3 py-2 text-sm ring-offset-highlight-primary file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted focus:bg-primary-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
||||
name="answer"
|
||||
placeholder="CAPTAIN, LOOK !"
|
||||
/>
|
||||
|
@ -137,7 +142,12 @@
|
|||
<Input name="code_file" type="file" accept=".py,.js,.ts,.java,.rs,.c" disabled />
|
||||
</div>
|
||||
</div>
|
||||
<Button class="w-full sm:w-44" variant="brand">Valider</Button>
|
||||
<Button class="w-full sm:w-44" variant="brand" disabled={submitting}>
|
||||
{#if submitting}
|
||||
<Loader2 class="mr-2 h-4 w-4 animate-spin" />
|
||||
{/if}
|
||||
Valider
|
||||
</Button>
|
||||
</form>
|
||||
{:else}
|
||||
<div class="flex flex-col items-center justify-between gap-2 sm:flex-row">
|
||||
|
|
|
@ -1,31 +1,62 @@
|
|||
import type { Actions } from '@sveltejs/kit';
|
||||
import { fail, type Actions } from '@sveltejs/kit';
|
||||
|
||||
import type { PageServerLoad } from './$types';
|
||||
import { z } from 'zod';
|
||||
import { superValidate } from 'sveltekit-superforms/server';
|
||||
import { API_URL } from '$env/static/private';
|
||||
|
||||
export const load = (async ({ parent }) => {
|
||||
const settingSchema = z.object({
|
||||
firstname: z.string({
|
||||
required_error: 'Prénom manquant'
|
||||
}),
|
||||
lastname: z.string({
|
||||
required_error: 'Nom manquant'
|
||||
}),
|
||||
pseudo: z.string({
|
||||
required_error: 'Pseudo manquant'
|
||||
})
|
||||
});
|
||||
|
||||
export const load = (async ({ parent, locals: { user } }) => {
|
||||
await parent();
|
||||
|
||||
const form = await superValidate(user, settingSchema);
|
||||
|
||||
return {
|
||||
form
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
|
||||
export const actions = {
|
||||
default: async (event) => {
|
||||
default: async ({ request, cookies }) => {
|
||||
const session = cookies.get('session');
|
||||
|
||||
const form = await superValidate(request, settingSchema);
|
||||
|
||||
if (!form.valid) {
|
||||
return fail(400, { form });
|
||||
}
|
||||
|
||||
const res = await fetch(`${API_URL}/user/settings`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${session}`
|
||||
},
|
||||
body: JSON.stringify(form.data)
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
return {
|
||||
success: true
|
||||
form
|
||||
};
|
||||
}
|
||||
|
||||
// throw redirect(303, `/dashboard/puzzles/${id}`);
|
||||
if (res.status === 400) {
|
||||
form.errors.pseudo = ['Le pseudo est déjà utilisé'];
|
||||
|
||||
// if (res.ok) {
|
||||
// const token = res.headers.get('Authorization')?.split(' ')[1];
|
||||
return fail(400, { form });
|
||||
}
|
||||
|
||||
// if (!token) throw new Error('No token found');
|
||||
|
||||
// event.cookies.set('session', token, {
|
||||
// path: '/'
|
||||
// });
|
||||
|
||||
// throw redirect(303, '/dashboard');
|
||||
// }
|
||||
|
||||
// throw redirect(303, '/sign-in');
|
||||
return fail(500, { form });
|
||||
}
|
||||
} satisfies Actions;
|
||||
|
|
|
@ -1,17 +1,26 @@
|
|||
<script lang="ts">
|
||||
import { enhance } from '$app/forms';
|
||||
import { page } from '$app/stores';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
import type { ActionData } from './$types';
|
||||
import { Loader2 } from 'lucide-svelte';
|
||||
import { superForm } from 'sveltekit-superforms/client';
|
||||
|
||||
import Button from '$lib/components/ui/Button.svelte';
|
||||
import Input from '$lib/components/ui/Input.svelte';
|
||||
|
||||
import plausible from '$lib/stores/Plausible';
|
||||
|
||||
$: user = $page.data.user;
|
||||
export let data: PageData;
|
||||
|
||||
export let form: ActionData;
|
||||
let submitting = false;
|
||||
|
||||
const { form, errors, enhance } = superForm(data.form, {
|
||||
onSubmit() {
|
||||
submitting = true;
|
||||
},
|
||||
onResult() {
|
||||
submitting = false;
|
||||
}
|
||||
});
|
||||
|
||||
$: optedOut = $plausible;
|
||||
</script>
|
||||
|
@ -22,28 +31,45 @@
|
|||
name="email"
|
||||
type="email"
|
||||
placeholder="philipzcwbarlow@peerat.dev"
|
||||
value={user?.email}
|
||||
value={data.user?.email}
|
||||
disabled
|
||||
/>
|
||||
|
||||
<label for="firstname">Prénom</label>
|
||||
<Input name="firstname" type="text" placeholder="Philip" value={user?.firstname} />
|
||||
<Input
|
||||
name="firstname"
|
||||
type="text"
|
||||
placeholder="Philip"
|
||||
aria-invalid={$errors.firstname ? 'true' : undefined}
|
||||
bind:value={$form.firstname}
|
||||
/>
|
||||
{#if $errors.firstname}
|
||||
<span class="text-sm text-red-500">{$errors.firstname}</span>
|
||||
{/if}
|
||||
|
||||
<label for="lastname">Nom</label>
|
||||
<Input name="lastname" type="text" placeholder="Barlow" value={user?.lastname} />
|
||||
<Input
|
||||
name="lastname"
|
||||
type="text"
|
||||
placeholder="Barlow"
|
||||
aria-invalid={$errors.lastname ? 'true' : undefined}
|
||||
bind:value={$form.lastname}
|
||||
/>
|
||||
{#if $errors.lastname}
|
||||
<span class="text-sm text-red-500">{$errors.lastname}</span>
|
||||
{/if}
|
||||
|
||||
<label for="pseudo"> Nom d'utilisateur </label>
|
||||
<Input name="pseudo" type="text" placeholder="Cypher Wolf" value={user?.pseudo} />
|
||||
|
||||
<label for="description"> Description </label>
|
||||
<Input
|
||||
name="description"
|
||||
placeholder="Je serai le plus grand pirate de l'espace"
|
||||
name="pseudo"
|
||||
type="text"
|
||||
value={user?.description}
|
||||
placeholder="Cypher Wolf"
|
||||
aria-invalid={$errors.pseudo ? 'true' : undefined}
|
||||
bind:value={$form.pseudo}
|
||||
/>
|
||||
|
||||
<!-- TODO -->
|
||||
{#if $errors.pseudo}
|
||||
<span class="text-sm text-red-500">{$errors.pseudo}</span>
|
||||
{/if}
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<label for="optout"> Ne pas me tracer de manière anonyme </label>
|
||||
|
@ -51,17 +77,20 @@
|
|||
class="h-4 w-4"
|
||||
name="optout"
|
||||
type="checkbox"
|
||||
value={optedOut}
|
||||
bind:value={optedOut}
|
||||
on:change={() => plausible.set(!optedOut)}
|
||||
checked={optedOut}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p class="text-sm text-highlight-secondary">
|
||||
Nous utilisons Plausible pour analyser l'utilisation de notre site web de manière anonyme.
|
||||
</p>
|
||||
|
||||
<Button variant="brand">
|
||||
<!-- {isLoading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />} -->
|
||||
<Button variant="brand" disabled={submitting}>
|
||||
{#if submitting}
|
||||
<Loader2 class="mr-2 h-4 w-4 animate-spin" />
|
||||
{/if}
|
||||
Modifier
|
||||
</Button>
|
||||
</form>
|
||||
|
|
|
@ -8,10 +8,14 @@
|
|||
|
||||
import Button from '$lib/components/ui/Button.svelte';
|
||||
import Input from '$lib/components/ui/Input.svelte';
|
||||
import { Loader2 } from 'lucide-svelte';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
const { form, errors, enhance } = superForm(data.form, {
|
||||
onSubmit() {
|
||||
submitting = true;
|
||||
},
|
||||
onResult({ result }) {
|
||||
switch (result.type) {
|
||||
case 'success':
|
||||
|
@ -26,9 +30,12 @@
|
|||
});
|
||||
break;
|
||||
}
|
||||
|
||||
submitting = false;
|
||||
}
|
||||
});
|
||||
|
||||
let submitting = false;
|
||||
let confirmation = false;
|
||||
|
||||
export const snapshot: Snapshot = {
|
||||
|
@ -72,8 +79,10 @@
|
|||
</div>
|
||||
{/if}
|
||||
|
||||
<Button class="mt-2" variant="brand">
|
||||
<!-- {isLoading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />} -->
|
||||
<Button class="mt-2" variant="brand" disabled={submitting}>
|
||||
{#if submitting}
|
||||
<Loader2 class="mr-2 h-4 w-4 animate-spin" />
|
||||
{/if}
|
||||
{confirmation ? 'Modifier' : 'Envoyer le mail'}
|
||||
</Button>
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
import { Loader2 } from 'lucide-svelte';
|
||||
import { superForm } from 'sveltekit-superforms/client';
|
||||
|
||||
import Button from '$lib/components/ui/Button.svelte';
|
||||
|
@ -10,7 +9,16 @@
|
|||
|
||||
export let data: PageData;
|
||||
|
||||
const { form, errors, enhance } = superForm(data.form);
|
||||
const { form, errors, enhance } = superForm(data.form, {
|
||||
onSubmit() {
|
||||
submitting = true;
|
||||
},
|
||||
onResult() {
|
||||
submitting = false;
|
||||
}
|
||||
});
|
||||
|
||||
let submitting = false;
|
||||
</script>
|
||||
|
||||
<div class="flex h-screen w-full">
|
||||
|
@ -32,19 +40,21 @@
|
|||
/>
|
||||
{#if $errors.passwd}<span class="text-sm text-red-500">{$errors.passwd}</span>{/if}
|
||||
|
||||
<Button class="mt-2" variant="brand">
|
||||
<!-- {isLoading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />} -->
|
||||
<Button class="mt-2" variant="brand" disabled={submitting}>
|
||||
{#if submitting}
|
||||
<Loader2 class="mr-2 h-4 w-4 animate-spin" />
|
||||
{/if}
|
||||
Se connecter
|
||||
</Button>
|
||||
|
||||
<ul class="flex justify-between">
|
||||
<li>
|
||||
<a class="text-highlight-secondary hover:text-brand" href="/sign-up">S'inscrire</a>
|
||||
<a class="text-highlight-secondary hover:text-brand" href="/sign-up"> S'inscrire </a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="text-highlight-secondary hover:text-brand" href="/forgot-password"
|
||||
>Mot de passe oublié</a
|
||||
>
|
||||
<a class="text-highlight-secondary hover:text-brand" href="/forgot-password">
|
||||
Mot de passe oublié
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</form>
|
||||
|
|
|
@ -6,10 +6,14 @@
|
|||
|
||||
import Button from '$lib/components/ui/Button.svelte';
|
||||
import Input from '$lib/components/ui/Input.svelte';
|
||||
import { Loader2 } from 'lucide-svelte';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
const { form, errors, enhance } = superForm(data.form, {
|
||||
onSubmit() {
|
||||
submitting = true;
|
||||
},
|
||||
onResult({ result }) {
|
||||
switch (result.type) {
|
||||
case 'success':
|
||||
|
@ -19,9 +23,12 @@
|
|||
confirmation = false;
|
||||
break;
|
||||
}
|
||||
|
||||
submitting = false;
|
||||
}
|
||||
});
|
||||
|
||||
let submitting = false;
|
||||
let confirmation = false;
|
||||
|
||||
export const snapshot: Snapshot = {
|
||||
|
@ -103,8 +110,10 @@
|
|||
</div>
|
||||
{/if}
|
||||
|
||||
<Button class="mt-2" variant="brand">
|
||||
<!-- {isLoading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />} -->
|
||||
<Button class="mt-2" variant="brand" disabled={submitting}>
|
||||
{#if submitting}
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
{/if}
|
||||
{confirmation ? "S'inscrire" : 'Continuer'}
|
||||
</Button>
|
||||
|
||||
|
@ -114,9 +123,9 @@
|
|||
</li>
|
||||
{#if confirmation}
|
||||
<li>
|
||||
<button formaction="?/register" class="text-highlight-secondary hover:text-brand"
|
||||
>Pas reçu ?</button
|
||||
>
|
||||
<button formaction="?/register" class="text-highlight-secondary hover:text-brand">
|
||||
Pas reçu ?
|
||||
</button>
|
||||
</li>
|
||||
{/if}
|
||||
</ul>
|
||||
|
|
Loading…
Add table
Reference in a new issue