Files
rdv/src/routes/admin/post-data-config/set-new-session-form.svelte
2026-01-03 13:21:39 +02:00

112 lines
3.2 KiB
Svelte
Executable File

<script lang="ts">
import Button from "$lib/components/atoms/button.svelte";
import Input from "$lib/components/atoms/input.svelte";
import type { TRPC } from "$lib/trpc/trpc";
import type { ApiPostUser } from "$lib/utils/data.types";
import toast from "svelte-french-toast";
import { onMount } from "svelte";
export let api: TRPC;
export let user: ApiPostUser;
export let onSuccessfulLogin: () => void;
let signingIn = false;
let captchaAnswer = "";
let getNewSessionM = api.apiAuth.getNewSession.createMutation({
onSuccess: (o) => {
signingIn = false;
if (!o.success) {
for (const each of o.errors) {
toast.error(each.message);
}
return;
}
toast.success("Successfully authenticated", {
duration: 1000 * 10,
});
onSuccessfulLogin();
},
onError: (e) => {
console.log(e);
signingIn = false;
toast.error(
"An error occured while authenticating, please try again later",
);
},
});
let captchaImage = "";
let captchaId = "";
let captchaQ = api.apiAuth.getCaptcha.createMutation({
onSuccess: (d) => {
console.log("[=] Captcha Response :: ", JSON.stringify(d, null, 2));
captchaId = d.id;
captchaImage = d.image;
},
onError: (e) => {
toast.error(
"An error occured while loading captcha, please try again later",
);
},
});
$: fetchingCaptcha = $captchaQ.isLoading;
const onFormSubmit = async () => {
if (captchaAnswer.length !== 4) {
toast.error("Captcha answer must be 4 characters long");
return;
}
if ($captchaQ.data?.id) {
signingIn = true;
$getNewSessionM.mutateAsync({
captchaId: $captchaQ.data?.id,
captchaAnswer,
userId: user.id,
});
} else {
toast.error("Captcha not loaded, refresh and try again");
}
};
onMount(() => {
$captchaQ.mutateAsync();
});
</script>
<form
class="flex flex-col gap-4 w-full"
on:submit|preventDefault={onFormSubmit}
>
{#if !fetchingCaptcha}
<img
class="w-64 h-16 rounded-md"
src={`data:image/jpeg;base64,${captchaImage}`}
alt={"Captcha"}
/>
{:else}
<div class="w-64 h-16 rounded-md bg-gray-200 animate-pulse"></div>
{/if}
<div class="gap-2 flex items-center">
<input hidden name="captchaId" value={captchaId} />
<Input
bind:value={captchaAnswer}
name={"captchaAnswer"}
placeholder={"Captcha Answer"}
otherInputOptions={{
required: true,
minLength: 4,
maxLength: 4,
}}
/>
<Button
disabled={signingIn}
text={signingIn ? "Logging in..." : "Login"}
intent={signingIn ? "ghost" : "primary"}
otherOptions={{ type: "submit" }}
/>
</div>
</form>