112 lines
3.2 KiB
Svelte
Executable File
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>
|