Profile: Redirect to current page instead of "/" when logging in/out or changing/creating profile

This commit is contained in:
2024-12-14 15:55:17 +01:00
parent 218e105815
commit dcd1444ba7
2 changed files with 60 additions and 47 deletions

View File

@ -118,6 +118,8 @@
<div class="flex flex-col gap-2 p-2"> <div class="flex flex-col gap-2 p-2">
<h4 class="h4 select-none">Enter Username and Password</h4> <h4 class="h4 select-none">Enter Username and Password</h4>
<form method="POST" class="contents"> <form method="POST" class="contents">
<!-- Supply the pathname so the form can redirect to the current page. -->
<input type="hidden" name="redirect_url" value={$page.url.pathname} />
<Input name="username" placeholder="Username" required> <Input name="username" placeholder="Username" required>
<UserIcon /> <UserIcon />
</Input> </Input>
@ -144,6 +146,8 @@
<div class="flex flex-col gap-2 p-2"> <div class="flex flex-col gap-2 p-2">
<h4 class="h4 select-none">Edit Profile</h4> <h4 class="h4 select-none">Edit Profile</h4>
<form method="POST" enctype="multipart/form-data" class="contents"> <form method="POST" enctype="multipart/form-data" class="contents">
<!-- Supply the pathname so the form can redirect to the current page. -->
<input type="hidden" name="redirect_url" value={$page.url.pathname} />
<input type="hidden" name="id" value={data.user.id} /> <input type="hidden" name="id" value={data.user.id} />
<Input name="username" value={data.user.username} placeholder="Username"><UserIcon /></Input <Input name="username" value={data.user.username} placeholder="Username"><UserIcon /></Input
> >
@ -179,15 +183,15 @@
padding="p-2" padding="p-2"
> >
<svelte:fragment slot="lead"> <svelte:fragment slot="lead">
<!-- Navigation drawer --> <div class="flex gap-2">
<div class="lg:hidden"> <!-- Navigation drawer -->
<Button color="primary" onclick={menu_drawer}> <div class="lg:hidden">
<MenuDrawerIcon /> <Button color="primary" onclick={menu_drawer}>
</Button> <MenuDrawerIcon />
</div> </Button>
</div>
<!-- Site logo --> <!-- Site logo -->
<div class="ml-2 lg:ml-0">
<Button href="/" color="primary"><span class="text-xl font-bold">Formula 11</span></Button> <Button href="/" color="primary"><span class="text-xl font-bold">Formula 11</span></Button>
</div> </div>
</svelte:fragment> </svelte:fragment>
@ -202,26 +206,30 @@
</div> </div>
<svelte:fragment slot="trail"> <svelte:fragment slot="trail">
<!-- Data drawer --> <div class="flex gap-2">
<Button <!-- Data drawer -->
color="primary" <Button
onclick={data_drawer} color="primary"
activate={$page.url.pathname.startsWith("/data")}>Data</Button onclick={data_drawer}
> activate={$page.url.pathname.startsWith("/data")}>Data</Button
>
<!-- Login/Profile drawer --> {#if !data.user}
{#if !data.user} <!-- Login drawer -->
<Button color="primary" onclick={login_drawer}>Login</Button> <Button color="primary" onclick={login_drawer}>Login</Button>
{:else} {:else}
<Avatar <!-- Profile drawer -->
id="user_avatar_preview" <Avatar
src={data.user.avatar_url} id="user_avatar_preview"
rounded="rounded-full" src={data.user.avatar_url}
width="w-10" rounded="rounded-full"
onclick={profile_drawer} width="w-10"
cursor="cursor-pointer" background="bg-primary-50"
/> onclick={profile_drawer}
{/if} cursor="cursor-pointer"
/>
{/if}
</div>
</svelte:fragment> </svelte:fragment>
</AppBar> </AppBar>
</nav> </nav>

View File

@ -1,13 +1,14 @@
import { form_data_clean, form_data_ensure_keys, form_data_get_and_remove_id } from "$lib/form"; import { form_data_clean, form_data_ensure_keys, form_data_get_and_remove_id } from "$lib/form";
import { error, redirect } from "@sveltejs/kit"; import { error, redirect } from "@sveltejs/kit";
import type { Actions } from "./$types"; import type { Actions } from "./$types";
import type { User } from "$lib/schema";
export const actions = { export const actions = {
create_profile: async ({ request, locals }) => { create_profile: async ({ request, locals }): Promise<void> => {
const data = form_data_clean(await request.formData()); const data: FormData = form_data_clean(await request.formData());
form_data_ensure_keys(data, ["username", "password"]); form_data_ensure_keys(data, ["username", "password", "redirect_url"]);
// TODO: Errrr passwordConfirm... How to integrate it into the unified login-/register-UI? // Confirm password lol
const record = await locals.pb.collection("users").create({ const record = await locals.pb.collection("users").create({
username: data.get("username")?.toString(), username: data.get("username")?.toString(),
password: data.get("password")?.toString(), password: data.get("password")?.toString(),
@ -20,46 +21,50 @@ export const actions = {
.collection("users") .collection("users")
.authWithPassword(data.get("username")?.toString(), data.get("password")?.toString()); .authWithPassword(data.get("username")?.toString(), data.get("password")?.toString());
redirect(303, "/"); redirect(303, data.get("redirect_url")?.toString() ?? "/");
}, },
// TODO: PocketBase API rule: Only the active user should be able to modify itself // TODO: PocketBase API rule: Only the active user should be able to modify itself
update_profile: async ({ request, locals }) => { update_profile: async ({ request, locals }): Promise<void> => {
const data = form_data_clean(await request.formData()); const data: FormData = form_data_clean(await request.formData());
const id = form_data_get_and_remove_id(data); form_data_ensure_keys(data, ["redirect_url"]);
const id: string = form_data_get_and_remove_id(data);
const record = await locals.pb.collection("users").update(id, data); const record: User = await locals.pb.collection("users").update(id, data);
redirect(303, "/"); redirect(303, data.get("redirect_url")?.toString() ?? "/");
}, },
login: async ({ request, locals }) => { login: async ({ request, locals }) => {
if (locals.user) { if (locals.user) {
console.log("Already logged in!"); error(400, "Already logged in!");
return;
} }
const data = form_data_clean(await request.formData()); const data: FormData = form_data_clean(await request.formData());
form_data_ensure_keys(data, ["username", "password"]); form_data_ensure_keys(data, ["username", "password", "redirect_url"]);
try { try {
await locals.pb await locals.pb
.collection("users") .collection("users")
.authWithPassword(data.get("username")?.toString(), data.get("password")?.toString()); .authWithPassword(data.get("username")?.toString(), data.get("password")?.toString());
} catch (err) { } catch (err) {
console.log(`Failed to login: ${err}`);
error(400, "Failed to login!"); error(400, "Failed to login!");
} }
// TODO: Would be better to redirect to previous page somehow... redirect(303, data.get("redirect_url")?.toString() ?? "/");
redirect(303, "/");
}, },
logout: async ({ locals }) => { logout: async ({ request, locals }) => {
if (!locals.user) {
error(400, "Not logged in!");
}
const data: FormData = form_data_clean(await request.formData());
form_data_ensure_keys(data, ["redirect_url"]);
locals.pb.authStore.clear(); locals.pb.authStore.clear();
locals.user = undefined; locals.user = undefined;
// TODO: Would be better to redirect to previous page somehow... redirect(303, data.get("redirect_url")?.toString() ?? "/");
redirect(303, "/");
}, },
} satisfies Actions; } satisfies Actions;