2024-01-10 15:26:45 +00:00
|
|
|
<script lang="ts">
|
2024-01-11 11:59:52 +00:00
|
|
|
import { Input, Button, Spinner, Checkbox } from "flowbite-svelte";
|
2024-04-14 14:36:32 +00:00
|
|
|
import { type User } from "../types/user";
|
2024-01-11 11:59:52 +00:00
|
|
|
import { currentPage, currentUser, startup } from "../storage/localStore";
|
2024-01-11 00:00:43 +00:00
|
|
|
import toast from "svelte-french-toast";
|
|
|
|
import { Page } from "../consts/pages";
|
2024-01-11 14:55:56 +00:00
|
|
|
import { EyeSlashSolid, EyeSolid } from "flowbite-svelte-icons";
|
2024-01-10 15:26:45 +00:00
|
|
|
|
|
|
|
let loading = false;
|
|
|
|
let username = "";
|
|
|
|
let password = "";
|
2024-01-11 11:59:52 +00:00
|
|
|
let saveCredentials = false;
|
2024-01-11 14:55:56 +00:00
|
|
|
let showPassword = false;
|
2024-01-10 15:26:45 +00:00
|
|
|
|
|
|
|
const processLogin = async () => {
|
|
|
|
loading = true;
|
2024-01-18 13:10:47 +00:00
|
|
|
const loginPromise = new Promise<void>((res, rej) => {
|
|
|
|
window.addEventListener(
|
|
|
|
"login-result",
|
|
|
|
(e) => {
|
|
|
|
const customEvent = e as CustomEvent;
|
|
|
|
const resultData = customEvent.detail;
|
|
|
|
const wasSuccessful = "user" in resultData;
|
2024-01-11 00:00:43 +00:00
|
|
|
|
2024-01-18 13:10:47 +00:00
|
|
|
if (!wasSuccessful) {
|
|
|
|
/* const errorResult = resultData as Error;
|
|
|
|
toast.error(errorResult.message, {
|
|
|
|
position: "bottom-center",
|
|
|
|
className:
|
|
|
|
"dark:!bg-gray-800 border-1 dark:!border-gray-700 dark:!text-gray-100",
|
|
|
|
duration: 1500,
|
|
|
|
}); */
|
|
|
|
rej();
|
|
|
|
loading = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const userResult = resultData.user as User;
|
|
|
|
currentUser.set(userResult);
|
|
|
|
currentPage.set(Page.Launch);
|
|
|
|
res();
|
|
|
|
toast.success(`Welcome back, ${userResult.name}!`, {
|
2024-01-11 00:00:43 +00:00
|
|
|
position: "bottom-center",
|
|
|
|
className:
|
|
|
|
"dark:!bg-gray-800 border-1 dark:!border-gray-700 dark:!text-gray-100",
|
2024-04-14 14:36:32 +00:00
|
|
|
duration: 3000
|
2024-01-11 00:00:43 +00:00
|
|
|
});
|
2024-01-18 13:10:47 +00:00
|
|
|
},
|
|
|
|
{ once: true }
|
|
|
|
);
|
|
|
|
window.dispatchEvent(
|
|
|
|
new CustomEvent("login-attempt", {
|
2024-04-14 14:36:32 +00:00
|
|
|
detail: { username, password, saveCredentials }
|
2024-01-18 13:10:47 +00:00
|
|
|
})
|
|
|
|
);
|
|
|
|
});
|
|
|
|
toast.promise(
|
|
|
|
loginPromise,
|
|
|
|
{
|
|
|
|
loading: "Logging in...",
|
|
|
|
success: "Successfully logged in!",
|
2024-04-14 14:36:32 +00:00
|
|
|
error: "Invalid Username or Password!"
|
2024-01-11 00:00:43 +00:00
|
|
|
},
|
2024-01-18 13:10:47 +00:00
|
|
|
{
|
|
|
|
position: "bottom-center",
|
|
|
|
className:
|
|
|
|
"dark:!bg-gray-800 border-1 dark:!border-gray-700 dark:!text-gray-100",
|
2024-04-14 14:36:32 +00:00
|
|
|
duration: 3000
|
2024-01-18 13:10:47 +00:00
|
|
|
}
|
2024-01-11 00:00:43 +00:00
|
|
|
);
|
2024-01-10 15:26:45 +00:00
|
|
|
};
|
2024-01-11 11:59:52 +00:00
|
|
|
|
|
|
|
const tryAutoLogin = async () => {
|
|
|
|
loading = true;
|
2024-01-18 13:10:47 +00:00
|
|
|
const loginPromise = new Promise<void>((res, rej) => {
|
|
|
|
window.addEventListener(
|
|
|
|
"login-result",
|
|
|
|
(e) => {
|
|
|
|
const customEvent = e as CustomEvent;
|
|
|
|
const resultData = customEvent.detail;
|
|
|
|
const isGuest = "guest" in resultData;
|
|
|
|
const wasSuccessful = "user" in resultData;
|
|
|
|
if (isGuest) {
|
|
|
|
currentPage.set(Page.Launch);
|
|
|
|
res();
|
|
|
|
toast.success(`Logged in as Guest`, {
|
|
|
|
position: "bottom-center",
|
|
|
|
className:
|
|
|
|
"dark:!bg-gray-800 border-1 dark:!border-gray-700 dark:!text-gray-100",
|
2024-04-14 14:36:32 +00:00
|
|
|
duration: 3000
|
2024-01-18 13:10:47 +00:00
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!wasSuccessful) {
|
|
|
|
loading = false;
|
|
|
|
rej();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const userResult = resultData.user as User;
|
|
|
|
currentUser.set(userResult);
|
2024-01-11 11:59:52 +00:00
|
|
|
currentPage.set(Page.Launch);
|
2024-01-18 13:10:47 +00:00
|
|
|
res();
|
|
|
|
toast.success(`Welcome back, ${userResult.name}!`, {
|
2024-01-11 11:59:52 +00:00
|
|
|
position: "bottom-center",
|
|
|
|
className:
|
|
|
|
"dark:!bg-gray-800 border-1 dark:!border-gray-700 dark:!text-gray-100",
|
2024-04-14 14:36:32 +00:00
|
|
|
duration: 3000
|
2024-01-11 11:59:52 +00:00
|
|
|
});
|
|
|
|
loading = false;
|
2024-01-18 13:10:47 +00:00
|
|
|
},
|
|
|
|
{ once: true }
|
|
|
|
);
|
|
|
|
window.dispatchEvent(new CustomEvent("autologin-attempt"));
|
|
|
|
});
|
|
|
|
toast.promise(
|
|
|
|
loginPromise,
|
|
|
|
{
|
|
|
|
loading: "Logging in...",
|
|
|
|
success: "Successfully logged in!",
|
2024-04-14 14:36:32 +00:00
|
|
|
error: "Failed to login."
|
2024-01-11 11:59:52 +00:00
|
|
|
},
|
2024-01-18 13:10:47 +00:00
|
|
|
{
|
|
|
|
position: "bottom-center",
|
|
|
|
className:
|
|
|
|
"dark:!bg-gray-800 border-1 dark:!border-gray-700 dark:!text-gray-100",
|
2024-04-14 14:36:32 +00:00
|
|
|
duration: 3000
|
2024-01-18 13:10:47 +00:00
|
|
|
}
|
2024-01-11 11:59:52 +00:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const proceedAsGuest = () => {
|
|
|
|
window.dispatchEvent(new CustomEvent("guest-login"));
|
|
|
|
currentPage.set(Page.Launch);
|
|
|
|
toast.success(`Logged in as Guest`, {
|
|
|
|
position: "bottom-center",
|
|
|
|
className:
|
|
|
|
"dark:!bg-gray-800 border-1 dark:!border-gray-700 dark:!text-gray-100",
|
2024-04-14 14:36:32 +00:00
|
|
|
duration: 3000
|
2024-01-11 11:59:52 +00:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2024-01-18 13:10:47 +00:00
|
|
|
const shouldAutologin = async () => {
|
|
|
|
const shouldAutologin = await new Promise<boolean>((res) => {
|
|
|
|
window.addEventListener("autologin-result", (e) => {
|
|
|
|
const customEvent = e as CustomEvent;
|
|
|
|
const resultData = customEvent.detail;
|
|
|
|
res(resultData);
|
|
|
|
});
|
|
|
|
window.dispatchEvent(new CustomEvent("autologin-active"));
|
|
|
|
});
|
|
|
|
return shouldAutologin;
|
|
|
|
};
|
|
|
|
|
|
|
|
(async () => {
|
|
|
|
if (!$startup) {
|
|
|
|
startup.set(true);
|
|
|
|
if (await shouldAutologin()) tryAutoLogin();
|
|
|
|
}
|
|
|
|
})();
|
2024-01-10 15:26:45 +00:00
|
|
|
</script>
|
|
|
|
|
2024-01-11 11:59:52 +00:00
|
|
|
<main
|
|
|
|
class="h-[265px] my-auto flex flex-col justify-center items-center p-5 animate-fadeIn opacity-0"
|
|
|
|
>
|
2024-01-10 15:26:45 +00:00
|
|
|
<div
|
2024-01-11 11:59:52 +00:00
|
|
|
class="container flex flex-col items-center justify-center gap-3 rounded-lg p-3"
|
2024-01-10 15:26:45 +00:00
|
|
|
>
|
|
|
|
<Input
|
|
|
|
type="text"
|
|
|
|
placeholder="Username"
|
|
|
|
size="md"
|
2024-01-25 11:04:43 +00:00
|
|
|
class="animate-sideIn"
|
2024-01-10 15:26:45 +00:00
|
|
|
disabled={loading}
|
|
|
|
bind:value={username}
|
|
|
|
/>
|
|
|
|
<Input
|
2024-01-11 14:55:56 +00:00
|
|
|
type={showPassword ? "text" : "password"}
|
2024-01-10 15:26:45 +00:00
|
|
|
placeholder="Password"
|
|
|
|
size="md"
|
2024-01-25 11:04:43 +00:00
|
|
|
class="animate-lsideIn"
|
2024-01-10 15:26:45 +00:00
|
|
|
disabled={loading}
|
|
|
|
bind:value={password}
|
2024-01-11 14:55:56 +00:00
|
|
|
>
|
|
|
|
<Button
|
|
|
|
slot="right"
|
|
|
|
color="none"
|
|
|
|
class="!outline-none !ring-0 !p-0 !m-0 !bg-transparent !border-none"
|
|
|
|
on:click={() => (showPassword = !showPassword)}
|
|
|
|
>
|
|
|
|
{#if showPassword}
|
|
|
|
<EyeSolid class="outline-none border-none" />
|
|
|
|
{:else}
|
|
|
|
<EyeSlashSolid class="outline-none border-none" />
|
|
|
|
{/if}
|
|
|
|
</Button>
|
|
|
|
</Input>
|
2024-01-12 11:09:28 +00:00
|
|
|
<Checkbox bind:checked={saveCredentials} disabled={loading}
|
|
|
|
>Save credentials</Checkbox
|
|
|
|
>
|
2024-01-19 14:04:58 +00:00
|
|
|
<div class="flex flex-col justify-center items-center gap-2 mt-1">
|
2024-01-10 15:26:45 +00:00
|
|
|
<Button
|
2024-01-25 09:23:03 +00:00
|
|
|
class="active:scale-95 transition-transform duration-75"
|
2024-01-10 15:26:45 +00:00
|
|
|
color="light"
|
|
|
|
disabled={loading}
|
|
|
|
on:click={processLogin}
|
|
|
|
>
|
|
|
|
{#if loading}
|
|
|
|
<Spinner size={"5"} color="white"></Spinner>
|
|
|
|
{:else}
|
|
|
|
Login
|
|
|
|
{/if}
|
|
|
|
</Button>
|
|
|
|
<Button
|
2024-01-11 11:59:52 +00:00
|
|
|
class="!bg-transparent font-light border-none dark:text-gray-700 hover:!bg-gray-700/15 ring-primary active:ring-2 focus:ring-2 active:scale-95 transition-transform duration-75"
|
2024-01-10 15:26:45 +00:00
|
|
|
color="none"
|
2024-01-11 00:00:43 +00:00
|
|
|
disabled={loading}
|
2024-01-11 11:59:52 +00:00
|
|
|
on:click={proceedAsGuest}>Continue without login</Button
|
2024-01-10 15:26:45 +00:00
|
|
|
>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</main>
|