feat: settings user

This commit is contained in:
Théo 2023-09-22 14:27:20 +02:00
parent 9e43d220d7
commit 3c538499c8
7 changed files with 156 additions and 74 deletions

View file

@ -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();

View file

@ -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,19 +132,22 @@
<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 !"
/>
</div>
<div class="flex flex-col gap-y-2">
<label for="code_file">Fichier</label>
<Input name="code_file" type="file" accept=".py,.js,.ts,.java,.rs,.c" disabled />
<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">

View file

@ -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) => {
return {
success: true
};
default: async ({ request, cookies }) => {
const session = cookies.get('session');
// throw redirect(303, `/dashboard/puzzles/${id}`);
const form = await superValidate(request, settingSchema);
// if (res.ok) {
// const token = res.headers.get('Authorization')?.split(' ')[1];
if (!form.valid) {
return fail(400, { form });
}
// if (!token) throw new Error('No token found');
const res = await fetch(`${API_URL}/user/settings`, {
method: 'POST',
headers: {
Authorization: `Bearer ${session}`
},
body: JSON.stringify(form.data)
});
// event.cookies.set('session', token, {
// path: '/'
// });
if (res.ok) {
return {
form
};
}
// throw redirect(303, '/dashboard');
// }
if (res.status === 400) {
form.errors.pseudo = ['Le pseudo est déjà utilisé'];
// throw redirect(303, '/sign-in');
return fail(400, { form });
}
return fail(500, { form });
}
} satisfies Actions;

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>