update
This commit is contained in:
parent
94298ec33f
commit
946d144cc9
@ -3,6 +3,22 @@ import { redirect } from "@sveltejs/kit";
|
||||
export const load = async ({ locals }) => {
|
||||
const { pb } = locals;
|
||||
if (pb.authStore.isValid) {
|
||||
redirect(303, "/");
|
||||
throw redirect(303, "/");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
reset: async ({ request, locals }) => {
|
||||
const { pb } = locals;
|
||||
const formData = await request.formData();
|
||||
const email = formData.get("email");
|
||||
|
||||
if (!email) {
|
||||
return { error: "Email is required" };
|
||||
}
|
||||
|
||||
await pb.collection("users").requestPasswordReset(email as string);
|
||||
|
||||
throw redirect(303, "/login");
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,29 +1,51 @@
|
||||
<script lang="ts">
|
||||
import { toast } from "svelte-sonner";
|
||||
import { enhance } from "$app/forms";
|
||||
|
||||
import { pb } from "$lib/pocketbase";
|
||||
import { goto } from "$app/navigation";
|
||||
import SEO from "$lib/components/SEO.svelte";
|
||||
|
||||
let email: string = "";
|
||||
let loading = false;
|
||||
let email: String;
|
||||
let isClicked = false;
|
||||
|
||||
async function resetPassword(event) {
|
||||
event.preventDefault();
|
||||
try {
|
||||
await pb.collection("users").requestPasswordReset(email);
|
||||
toast.success("Password resetted. Check your emails!", {
|
||||
style:
|
||||
"border-radius: 5px; background: #fff; color: #000; border-color: #4B5563; font-size: 15px;",
|
||||
});
|
||||
goto("/login");
|
||||
} catch (err) {
|
||||
toast.error(err, {
|
||||
style:
|
||||
"border-radius: 5px; background: #fff; color: #000; border-color: #4B5563; font-size: 15px;",
|
||||
});
|
||||
}
|
||||
}
|
||||
const submitReset = () => {
|
||||
loading = true;
|
||||
return async ({ result, update }) => {
|
||||
switch (result.type) {
|
||||
case "success":
|
||||
toast.success("Password resetted. Check your emails!", {
|
||||
style:
|
||||
"border-radius: 5px; background: #fff; color: #000; border-color: #4B5563; font-size: 15px;",
|
||||
});
|
||||
await update();
|
||||
break;
|
||||
case "redirect":
|
||||
isClicked = true;
|
||||
toast.success("Password resetted. Check your emails!", {
|
||||
style:
|
||||
"border-radius: 5px; background: #fff; color: #000; border-color: #4B5563; font-size: 15px;",
|
||||
});
|
||||
await update();
|
||||
break;
|
||||
case "failure":
|
||||
toast.error("Invalid credentials", {
|
||||
style:
|
||||
"border-radius: 5px; background: #fff; color: #000; border-color: #4B5563; font-size: 15px;",
|
||||
});
|
||||
await update();
|
||||
break;
|
||||
case "error":
|
||||
toast.error(result.error.message, {
|
||||
style:
|
||||
"border-radius: 5px; background: #fff; color: #000; border-color: #4B5563; font-size: 15px;",
|
||||
});
|
||||
break;
|
||||
default:
|
||||
await update();
|
||||
}
|
||||
loading = false;
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<SEO
|
||||
@ -41,23 +63,39 @@
|
||||
We'll send you an email with a link to reset your password.
|
||||
</p>
|
||||
<form
|
||||
on:submit={resetPassword}
|
||||
action="?/reset"
|
||||
method="POST"
|
||||
use:enhance={submitReset}
|
||||
class="flex flex-col items-center space-y-2 w-5/6 sm:w-full pt-4"
|
||||
>
|
||||
<input
|
||||
class="input input-bordered w-full max-w-lg bg-[#242527] placeholder-gray-400 text-white whitespace-normal ring-2"
|
||||
name="email"
|
||||
class="py-2.5 rounded w-full border border-gray-600 focus:outline-none max-w-lg bg-[#242527] placeholder-gray-400 text-white whitespace-normal"
|
||||
type="email"
|
||||
required={true}
|
||||
required
|
||||
bind:value={email}
|
||||
autocomplete="off"
|
||||
/>
|
||||
<div class="w-full max-w-lg pt-2">
|
||||
<button
|
||||
type="submit"
|
||||
class="py-2.5 font-semibold rounded bg-white text-black w-full"
|
||||
>
|
||||
Request Password Reset
|
||||
</button>
|
||||
<div class="w-full max-w-lg">
|
||||
<div class="w-full max-w-lg pt-2 m-auto pb-5">
|
||||
{#if !loading && !isClicked}
|
||||
<button
|
||||
type="submit"
|
||||
class="cursor-pointer py-2.5 bg-[#fff] border-none sm:hover:bg-gray-300 transition duration-100 btn-md w-full rounded m-auto text-black font-semibold text-[1rem]"
|
||||
>
|
||||
<span> Request Password Reset</span>
|
||||
</button>
|
||||
{:else}
|
||||
<label
|
||||
class="cursor-not-allowed btn bg-[#fff] opacity-[0.5] border border-gray-600 sm:hover:bg-gray-300 transition duration-100 btn-md w-full rounded-md m-auto text-black font-semibold text-[1rem]"
|
||||
>
|
||||
<div class="flex flex-row m-auto items-center">
|
||||
<span class="loading loading-infinity"></span>
|
||||
<span class=" ml-1.5">Resetting</span>
|
||||
</div>
|
||||
</label>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@ -1,8 +1,51 @@
|
||||
import { redirect, error } from "@sveltejs/kit";
|
||||
import { updatePasswordSchema } from "$lib/schemas";
|
||||
import { fail } from "@sveltejs/kit";
|
||||
import { z } from "zod";
|
||||
|
||||
export const load = async ({ locals }) => {
|
||||
const { pb, user } = locals;
|
||||
const { pb } = locals;
|
||||
if (!pb.authStore.isValid) {
|
||||
redirect(303, "/login");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const actions = {
|
||||
updatePassword: async ({ request, locals }) => {
|
||||
const { pb, user } = locals;
|
||||
|
||||
const formData = await request.formData();
|
||||
const postData: Record<string, string> = {};
|
||||
// Build a plain object from the form data.
|
||||
for (const [key, value] of formData.entries()) {
|
||||
if (typeof value === "string") {
|
||||
postData[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// Validate form data using your Zod schema.
|
||||
const cleanedData = updatePasswordSchema.parse(postData);
|
||||
|
||||
await pb.collection("users").update(user?.id, cleanedData);
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
if (error instanceof z.ZodError) {
|
||||
// Map Zod errors to individual error messages.
|
||||
const errors = {
|
||||
errorOldPassword:
|
||||
error.errors?.find((err) => err.path[0] === "oldPassword")?.message || "You're password is wrong",
|
||||
errorPassword:
|
||||
error.errors?.find((err) => err.path[0] === "password")?.message || "",
|
||||
errorPasswordConfirm:
|
||||
error.errors?.find((err) => err.path[0] === "passwordConfirm")?.message || "",
|
||||
};
|
||||
return fail(400, { errors, zodErrors: error.errors });
|
||||
}
|
||||
console.error("Unexpected error during password update:", error);
|
||||
return fail(500, { error: "An unexpected error occurred" });
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,74 +1,36 @@
|
||||
<script ts="lang">
|
||||
import { pb } from "$lib/pocketbase";
|
||||
<script lang="ts">
|
||||
import { enhance } from "$app/forms";
|
||||
import { toast } from "svelte-sonner";
|
||||
|
||||
import Input from "$lib/components/Input.svelte";
|
||||
import { updatePasswordSchema } from "$lib/schemas";
|
||||
import { goto } from "$app/navigation";
|
||||
import { z } from "zod";
|
||||
import SEO from "$lib/components/SEO.svelte";
|
||||
|
||||
let zodErrors = [];
|
||||
export let data;
|
||||
|
||||
let errorOldPassword = "";
|
||||
let errorPassword = "";
|
||||
let errorPasswordConfirm = "";
|
||||
export let form;
|
||||
let loading = false;
|
||||
async function updatePassword(event) {
|
||||
|
||||
const submitUpdatePassword = () => {
|
||||
loading = true;
|
||||
event.preventDefault(); // prevent the default form submission behavior
|
||||
errorOldPassword = "";
|
||||
errorPassword = "";
|
||||
errorPasswordConfirm = "";
|
||||
|
||||
const formData = new FormData(event.target); // create a FormData object from the form
|
||||
const postData = {};
|
||||
|
||||
for (const [key, value] of formData.entries()) {
|
||||
postData[key] = value;
|
||||
}
|
||||
|
||||
try {
|
||||
// Use Zod validation
|
||||
const cleanedData = updatePasswordSchema.parse(postData);
|
||||
await pb.collection("users").update(data?.user?.id, cleanedData);
|
||||
toast.success("Password updated!", {
|
||||
style: "border-radius: 200px; background: #2A2E39; color: #fff;",
|
||||
});
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
// Handle Zod validation errors
|
||||
zodErrors = error.errors;
|
||||
|
||||
errorOldPassword =
|
||||
zodErrors?.find((err) => err.path[0] === "oldPassword")?.message ??
|
||||
"";
|
||||
errorPassword =
|
||||
zodErrors?.find((err) => err.path[0] === "password")?.message ?? "";
|
||||
errorPasswordConfirm =
|
||||
zodErrors?.find((err) => err.path[0] === "passwordConfirm")
|
||||
?.message ?? "";
|
||||
|
||||
return async ({ result, update }) => {
|
||||
if (result.success) {
|
||||
toast.success("Password updated!", {
|
||||
style: "border-radius: 200px; background: #2A2E39; color: #fff;",
|
||||
});
|
||||
} else if (result.error || result.errors) {
|
||||
toast.error("Invalid credentials", {
|
||||
style:
|
||||
"border-radius: 5px; background: #fff; color: #000; border-color: #4B5563; font-size: 15px;",
|
||||
});
|
||||
} else {
|
||||
// Handle other errors
|
||||
console.error("Unexpected error during registration:", error);
|
||||
|
||||
toast.error("An unexpected error occurred", {
|
||||
style:
|
||||
"border-radius: 5px; background: #fff; color: #000; border-color: #4B5563; font-size: 15px;",
|
||||
});
|
||||
}
|
||||
}
|
||||
loading = false;
|
||||
}
|
||||
await update();
|
||||
loading = false;
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<SEO title="Update Password" description="Update your account password" />
|
||||
|
||||
<section
|
||||
class="w-full max-w-3xl sm:max-w-[1400px] overflow-hidden min-h-screen pb-20 pt-5 px-4 lg:px-3"
|
||||
class="flex flex-col items-center min-h-screen w-full max-w-3xl m-auto"
|
||||
>
|
||||
<div class="w-full overflow-hidden m-auto mt-5">
|
||||
<div class="sm:p-0 flex justify-center w-full m-auto overflow-hidden">
|
||||
@ -77,43 +39,49 @@
|
||||
>
|
||||
<main class="w-full">
|
||||
<form
|
||||
on:submit={updatePassword}
|
||||
action="?/updatePassword"
|
||||
method="POST"
|
||||
use:enhance={submitUpdatePassword}
|
||||
class="flex flex-col space-y-2 w-full max-w-lg m-auto"
|
||||
>
|
||||
<h1
|
||||
class="mb-1 text-white text-2xl sm:text-3xl font-bold mb-6 text-center"
|
||||
>
|
||||
Set a new password
|
||||
Reset Your Password
|
||||
</h1>
|
||||
|
||||
<Input
|
||||
id="oldPassword"
|
||||
name="oldPassword"
|
||||
label="Old Password"
|
||||
type="password"
|
||||
required
|
||||
errors={errorOldPassword}
|
||||
errors={form?.errors?.errorOldPassword}
|
||||
/>
|
||||
<Input
|
||||
id="password"
|
||||
name="password"
|
||||
label="New Password"
|
||||
type="password"
|
||||
required
|
||||
errors={errorPassword}
|
||||
errors={form?.errors?.errorPassword}
|
||||
/>
|
||||
<Input
|
||||
id="passwordConfirm"
|
||||
name="passwordConfirm"
|
||||
label="Confirm New Password"
|
||||
type="password"
|
||||
required
|
||||
errors={errorPasswordConfirm}
|
||||
errors={form?.errors?.errorPasswordConfirm}
|
||||
/>
|
||||
|
||||
<div class="w-full max-w-lg pt-3">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn bg-[#fff] text-black font-semibold sm:hover:bg-gray-300 w-full max-w-lg normal-case text-md"
|
||||
>Update Password</button
|
||||
class="py-2.5 cursor-pointer rounded bg-[#fff] text-black font-semibold sm:hover:bg-gray-300 w-full max-w-lg normal-case text-md"
|
||||
>
|
||||
{loading ? "Updating..." : "Update Password"}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</main>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user