init
This commit is contained in:
commit
d761a10bf7
102 changed files with 4761 additions and 0 deletions
111
routes/dashboard/+layout.svelte
Normal file
111
routes/dashboard/+layout.svelte
Normal file
|
@ -0,0 +1,111 @@
|
|||
<script lang="ts">
|
||||
import { browser } from '$app/environment';
|
||||
import { page } from '$app/stores';
|
||||
import Navbar from '$lib/components/dashboard/Navbar.svelte';
|
||||
import Showcase from '$lib/components/dashboard/auth/Showcase.svelte';
|
||||
import ProfileContainerPlaceholder from '$lib/components/screens/ProfileContainerPlaceholder.svelte';
|
||||
import { type } from '$lib/models/modal.js';
|
||||
import { modalStore } from '$lib/stores/modal.js';
|
||||
import Loading from '$lib/components/screens/Loading.svelte';
|
||||
|
||||
export let data;
|
||||
|
||||
$: auth =
|
||||
$page.url.pathname.startsWith('/dashboard/login') ||
|
||||
$page.url.pathname.startsWith('/dashboard/register') ||
|
||||
$page.url.pathname.startsWith('/dashboard/logout');
|
||||
|
||||
$: modal = browser && $modalStore?.type != null ? type[$modalStore.type] : null;
|
||||
$: isModal = $modalStore?.visible && modal?.navbarMount === true;
|
||||
|
||||
$: mouseDown = false;
|
||||
|
||||
const dismissModal = () => {
|
||||
mouseDown = false;
|
||||
if ($modalStore?.visible) $modalStore.hideModal();
|
||||
};
|
||||
</script>
|
||||
|
||||
{#if browser}
|
||||
<div class="flex h-full">
|
||||
{#if !auth}
|
||||
<div class="w-full h-full">
|
||||
<div class="h-full" on:mouseup={modal?.navbarMount ? undefined : dismissModal}>
|
||||
<slot />
|
||||
</div>
|
||||
<div
|
||||
class="navbar-container top-0 bottom-0 left-0 right-0 fixed z-40 flex flex-col justify-end items-center gap-4 p-6 overflow-hidden pointer-events-none select-none transition-all"
|
||||
class:!p-0={$modalStore?.visible && modal?.navbarMount}
|
||||
class:sm:!p-6={$modalStore?.visible && modal?.navbarMount}
|
||||
class:!pointer-events-auto={$modalStore?.visible && modal?.navbarMount}
|
||||
on:mousedown|self={() => (mouseDown = true)}
|
||||
on:mouseup|self={() => (mouseDown ? dismissModal() : undefined)}
|
||||
class:!gap-0={isModal}>
|
||||
<Navbar sessionData={data.session?.data} />
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex w-full h-full justify-center items-center">
|
||||
<div
|
||||
class="w-full h-full flex gap-6 xl:gap-[60px] 2xl:gap-[120px] pl-6 xl:pl-[60px] 2xl:pl-[120px] pr-6 items-center justify-center">
|
||||
<div
|
||||
class="flex-shrink-0 w-[400px] lg:max-h-screen px-1 py-6 overflow-x-hidden overflow-y-auto flex flex-col items-center gap-4 md:gap-6">
|
||||
<a class="box-content p-4" href="/">
|
||||
<div class="w-16 h-16 bg-white logo" title="YourSitee logo" />
|
||||
</a>
|
||||
<slot />
|
||||
</div>
|
||||
<div class="showcase w-full h-full max-w-[1920px] max-h-[1440px] hidden lg:block">
|
||||
<Showcase />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
{#if !auth}
|
||||
<ProfileContainerPlaceholder uniqueId={data.session?.data.uniqueId} />
|
||||
{:else}
|
||||
<Loading />
|
||||
{/if}
|
||||
<noscript
|
||||
><div class="absolute top-0 left-0 right-0 bottom-0 bg-dark-app-bg z-50 flex justify-center items-center">
|
||||
<div class="p-8">
|
||||
<p class="text-[32px] font-bold">⚠️ You don't have JavaScript enabled</p>
|
||||
<p class="text-secondary">
|
||||
Unfortunately, <b>JavaScript is required</b> for the dashboard. Enable it and try again.
|
||||
</p>
|
||||
</div>
|
||||
</div></noscript>
|
||||
{/if}
|
||||
|
||||
<style lang="postcss">
|
||||
.navbar-container {
|
||||
animation: pop-up 1.5s cubic-bezier(0.16, 1, 0.3, 1) 1;
|
||||
transition: gap 0.2s linear;
|
||||
}
|
||||
|
||||
@keyframes pop-up {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(3.25%);
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0;
|
||||
transform: translateY(3.25%);
|
||||
}
|
||||
|
||||
100% {
|
||||
}
|
||||
}
|
||||
|
||||
.logo {
|
||||
mask-image: url(/assets/brand/icon.svg);
|
||||
}
|
||||
|
||||
.showcase {
|
||||
height: calc(100vh - 3rem);
|
||||
}
|
||||
</style>
|
||||
|
1
routes/dashboard/+layout.ts
Normal file
1
routes/dashboard/+layout.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export const ssr = true;
|
42
routes/dashboard/login/+page.svelte
Normal file
42
routes/dashboard/login/+page.svelte
Normal file
|
@ -0,0 +1,42 @@
|
|||
<script lang="ts">
|
||||
import InputGroup from '$lib/components/dashboard/elements/InputGroup.svelte';
|
||||
import TextInput from '$lib/components/dashboard/elements/TextInput.svelte';
|
||||
import Panel from '$lib/components/dashboard/auth/Panel.svelte';
|
||||
import constraints from '$lib/constraints';
|
||||
|
||||
export let data;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>YourSitee</title>
|
||||
</svelte:head>
|
||||
|
||||
<Panel
|
||||
title="Welcome back! Log in to continue"
|
||||
links={[
|
||||
{ url: 'register', text: 'Register' },
|
||||
// { url: 'login/recovery', text: 'Forgot password?' },
|
||||
]}
|
||||
button="Sign In">
|
||||
<InputGroup title="Username/Email address" required={true}>
|
||||
<TextInput
|
||||
name="identifier"
|
||||
required
|
||||
placeholder="Provide your username or email"
|
||||
tabindex={1}
|
||||
minlength={1}
|
||||
maxlength={64}
|
||||
value={data.username ?? data.email ?? ''} />
|
||||
</InputGroup>
|
||||
<InputGroup title="Password" required={true}>
|
||||
<TextInput
|
||||
name="password"
|
||||
required
|
||||
placeholder="Password"
|
||||
type="password"
|
||||
tabindex={2}
|
||||
minlength={constraints.password.min}
|
||||
maxlength={constraints.password.max} />
|
||||
</InputGroup>
|
||||
</Panel>
|
||||
|
8
routes/dashboard/login/+page.ts
Normal file
8
routes/dashboard/login/+page.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ url }) => {
|
||||
return {
|
||||
username: url.searchParams.get('un'),
|
||||
email: url.searchParams.get('e'),
|
||||
};
|
||||
};
|
30
routes/dashboard/login/recovery/+page.svelte
Normal file
30
routes/dashboard/login/recovery/+page.svelte
Normal file
|
@ -0,0 +1,30 @@
|
|||
<script lang="ts">
|
||||
import Button from '$lib/components/dashboard/elements/Button.svelte';
|
||||
import InputGroup from '$lib/components/dashboard/elements/InputGroup.svelte';
|
||||
import TextInput from '$lib/components/dashboard/elements/TextInput.svelte';
|
||||
import Back from '$lib/components/dashboard/auth/Back.svelte';
|
||||
import Panel from '$lib/components/dashboard/auth/Panel.svelte';
|
||||
|
||||
export let data;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>YourSitee</title>
|
||||
</svelte:head>
|
||||
|
||||
<Back />
|
||||
{#if !data.code}
|
||||
<Panel
|
||||
title="Forgot your password?"
|
||||
subtitle="No problem at all! Let us send you an email with a recovery link to help you log into your account.">
|
||||
<InputGroup title="Email address"><TextInput name="email" placeholder="you@example.com" required /></InputGroup>
|
||||
<Button>Send recovery link</Button>
|
||||
</Panel>
|
||||
{:else}
|
||||
<Panel title="Create a new password" action="?/new">
|
||||
<InputGroup title="New password"><TextInput name="password" type="password" required /></InputGroup>
|
||||
<InputGroup title="Confirm new password"><TextInput name="password-confirm" type="password" required /></InputGroup>
|
||||
<Button>Set new password</Button>
|
||||
</Panel>
|
||||
{/if}
|
||||
|
62
routes/dashboard/register/+page.svelte
Normal file
62
routes/dashboard/register/+page.svelte
Normal file
|
@ -0,0 +1,62 @@
|
|||
<script lang="ts">
|
||||
import InputGroup from '$lib/components/dashboard/elements/InputGroup.svelte';
|
||||
import TextInput from '$lib/components/dashboard/elements/TextInput.svelte';
|
||||
import Panel from '$lib/components/dashboard/auth/Panel.svelte';
|
||||
import Checkbox from '$lib/components/dashboard/elements/Checkbox.svelte';
|
||||
import constraints from '$lib/constraints.js';
|
||||
|
||||
export let data;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>YourSitee</title>
|
||||
</svelte:head>
|
||||
|
||||
<Panel
|
||||
title="Join thousands of people already using YourSitee"
|
||||
links={[
|
||||
{ url: 'login', text: 'Login' },
|
||||
// { url: 'login/recovery', text: 'Forgot password?' },
|
||||
]}
|
||||
button="Register">
|
||||
<InputGroup title="Username" required={true}>
|
||||
<TextInput
|
||||
name="username"
|
||||
required
|
||||
placeholder="Pick a cool username"
|
||||
minlength={constraints.username.min}
|
||||
maxlength={constraints.username.max}
|
||||
value={data.username ?? ''} />
|
||||
</InputGroup>
|
||||
<InputGroup title="Email address" required={true}>
|
||||
<TextInput
|
||||
name="email"
|
||||
required
|
||||
type="email"
|
||||
placeholder="Provide your email"
|
||||
minlength={constraints.email.min}
|
||||
maxlength={constraints.email.max}
|
||||
value={data.email ?? ''} />
|
||||
</InputGroup>
|
||||
<InputGroup title="Password" required={true}>
|
||||
<TextInput
|
||||
name="password"
|
||||
required
|
||||
placeholder="Password"
|
||||
type="password"
|
||||
minlength={constraints.password.min}
|
||||
maxlength={constraints.password.max} />
|
||||
<TextInput
|
||||
name="password-confirm"
|
||||
required
|
||||
placeholder="Password again"
|
||||
type="password"
|
||||
minlength={constraints.password.min}
|
||||
maxlength={constraints.password.max} />
|
||||
</InputGroup>
|
||||
<Checkbox name="accept" required>
|
||||
By checking this box, I acknowledge that I have read and agree to abide by the <a href="/terms" target="_blank"
|
||||
>Terms of Service</a>
|
||||
and the <a href="/privacy" target="_blank">Privacy Policy</a>.</Checkbox>
|
||||
</Panel>
|
||||
|
8
routes/dashboard/register/+page.ts
Normal file
8
routes/dashboard/register/+page.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ url }) => {
|
||||
return {
|
||||
username: url.searchParams.get('un'),
|
||||
email: url.searchParams.get('e'),
|
||||
};
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue