refactor: simplify auth pages
This commit is contained in:
@@ -3,10 +3,9 @@
|
|||||||
import { appController } from '$lib/app/controller';
|
import { appController } from '$lib/app/controller';
|
||||||
import { appState } from '$lib/app/store';
|
import { appState } from '$lib/app/store';
|
||||||
import { Button } from '$lib/components/ui/button/index.js';
|
import { Button } from '$lib/components/ui/button/index.js';
|
||||||
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '$lib/components/ui/card/index.js';
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '$lib/components/ui/card/index.js';
|
||||||
import { Input } from '$lib/components/ui/input/index.js';
|
import { Input } from '$lib/components/ui/input/index.js';
|
||||||
import { Label } from '$lib/components/ui/label/index.js';
|
import { Label } from '$lib/components/ui/label/index.js';
|
||||||
import { ArrowRight } from '@lucide/svelte';
|
|
||||||
|
|
||||||
let { mode = 'login' } = $props<{ mode?: 'login' | 'signup' }>();
|
let { mode = 'login' } = $props<{ mode?: 'login' | 'signup' }>();
|
||||||
|
|
||||||
@@ -14,10 +13,11 @@
|
|||||||
const title = () => (isSignup() ? 'Create your PhoneCam account' : 'Sign in to PhoneCam');
|
const title = () => (isSignup() ? 'Create your PhoneCam account' : 'Sign in to PhoneCam');
|
||||||
const description = () =>
|
const description = () =>
|
||||||
isSignup()
|
isSignup()
|
||||||
? 'Start setting up browser-based monitoring and client viewing in a few steps.'
|
? 'Create an account to finish setting up this browser.'
|
||||||
: 'Return to your live monitoring workspace and pick up where you left off.';
|
: 'Use your account to open the dashboard and continue setup.';
|
||||||
const primaryLabel = () => (isSignup() ? 'Create account' : 'Sign in');
|
const primaryLabel = () => (isSignup() ? 'Create account' : 'Sign in');
|
||||||
const secondaryLabel = () => (isSignup() ? 'I already have an account' : 'Create an account');
|
const secondaryLabel = () => (isSignup() ? 'Sign in instead' : 'Create an account');
|
||||||
|
const secondaryPrompt = () => (isSignup() ? 'Already have an account?' : 'Need an account?');
|
||||||
const secondaryHref = () => (isSignup() ? '/auth/login' : '/auth/signup');
|
const secondaryHref = () => (isSignup() ? '/auth/login' : '/auth/signup');
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
@@ -25,111 +25,86 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="mx-auto flex min-h-full w-full max-w-6xl items-center px-6 py-8 sm:px-10 lg:px-12">
|
<section class="mx-auto flex min-h-full w-full max-w-5xl flex-col px-4 py-8 sm:px-6">
|
||||||
<div class="grid w-full gap-10 lg:grid-cols-[1.05fr_0.95fr] lg:items-center">
|
<nav class="flex items-center border-b border-white/10 pb-4">
|
||||||
<div class="space-y-8">
|
<Button
|
||||||
<div class="inline-flex items-center gap-3 rounded-full border border-white/10 bg-white/5 px-4 py-2 text-[11px] font-medium uppercase tracking-[0.28em] text-sky-100/70">
|
href="/"
|
||||||
<span class="h-2 w-2 rounded-full bg-sky-400 shadow-[0_0_12px_rgba(56,189,248,0.8)]"></span>
|
variant="ghost"
|
||||||
PhoneCam Browser Console
|
class="h-auto rounded-full px-3 text-sm font-semibold text-white hover:bg-white/5 hover:text-sky-200"
|
||||||
</div>
|
>
|
||||||
|
PhoneCam
|
||||||
|
</Button>
|
||||||
|
</nav>
|
||||||
|
|
||||||
<div class="space-y-5">
|
<div class="flex flex-1 items-center justify-center pt-8">
|
||||||
<h1 class="max-w-xl text-4xl font-semibold tracking-[-0.04em] text-white sm:text-5xl lg:text-6xl">
|
<Card variant="glass" class="w-full max-w-md rounded-3xl border-white/10 bg-black/45 backdrop-blur-xl">
|
||||||
Turn any browser into a live security surface.
|
<CardHeader class="space-y-3 px-6 pt-6 text-left sm:px-7 sm:pt-7">
|
||||||
</h1>
|
<p class="text-xs font-semibold uppercase tracking-[0.28em] text-sky-200/80">PhoneCam</p>
|
||||||
<p class="max-w-xl text-base leading-7 text-slate-300 sm:text-lg">
|
|
||||||
Authenticate once, assign this browser as a camera or client, and manage motion alerts, recordings, and live feeds from a single control plane.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid gap-4 border-t border-white/10 pt-6 text-sm text-slate-300 sm:grid-cols-3">
|
|
||||||
<div class="space-y-2">
|
|
||||||
<p class="text-[11px] font-semibold uppercase tracking-[0.24em] text-slate-500">Assign roles</p>
|
|
||||||
<p>Register this browser as a camera station or a client viewer without leaving the web app.</p>
|
|
||||||
</div>
|
|
||||||
<div class="space-y-2">
|
|
||||||
<p class="text-[11px] font-semibold uppercase tracking-[0.24em] text-slate-500">Stay live</p>
|
|
||||||
<p>Watch feeds, monitor connection health, and see motion activity arrive in real time.</p>
|
|
||||||
</div>
|
|
||||||
<div class="space-y-2">
|
|
||||||
<p class="text-[11px] font-semibold uppercase tracking-[0.24em] text-slate-500">Carry context</p>
|
|
||||||
<p>Your saved device and session restore cleanly so returning to the workspace is fast.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Card variant="glass" class="overflow-hidden rounded-[2rem] border-white/10 bg-black/45 backdrop-blur-xl">
|
|
||||||
<div class="absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-sky-400/50 to-transparent"></div>
|
|
||||||
<CardHeader class="gap-5 px-7 pt-7 text-center">
|
|
||||||
<p class="text-[11px] font-semibold uppercase tracking-[0.24em] text-sky-200/80">PhoneCam</p>
|
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<CardTitle class="text-3xl font-semibold tracking-tight text-white">{title()}</CardTitle>
|
<CardTitle class="text-3xl font-semibold tracking-tight text-white">{title()}</CardTitle>
|
||||||
<CardDescription class="text-sm leading-6 text-slate-400">{description()}</CardDescription>
|
<CardDescription class="text-sm leading-6 text-slate-400">{description()}</CardDescription>
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<CardContent class="space-y-4 px-7">
|
<CardContent class="space-y-5 px-6 pb-6 sm:px-7 sm:pb-7">
|
||||||
|
{#if isSignup()}
|
||||||
|
<div id="authNameField" class="space-y-2">
|
||||||
|
<Label for="authName" class="text-sm font-medium text-slate-200">Display name</Label>
|
||||||
|
<Input
|
||||||
|
id="authName"
|
||||||
|
type="text"
|
||||||
|
placeholder="Jane Doe"
|
||||||
|
class="h-11 rounded-2xl border-white/10 bg-white/[0.04] text-sm text-white placeholder:text-slate-500"
|
||||||
|
value={$appState.authForm.name}
|
||||||
|
oninput={(event) => appController.setAuthField('name', (event.currentTarget as HTMLInputElement).value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<Label class="sr-only" for="authEmail">Email</Label>
|
<Label for="authEmail" class="text-sm font-medium text-slate-200">Email</Label>
|
||||||
<Input
|
<Input
|
||||||
id="authEmail"
|
id="authEmail"
|
||||||
type="email"
|
type="email"
|
||||||
placeholder="Email address"
|
placeholder="name@example.com"
|
||||||
class="h-12 rounded-2xl border-white/10 bg-white/[0.04] text-sm text-white placeholder:text-slate-500"
|
class="h-11 rounded-2xl border-white/10 bg-white/[0.04] text-sm text-white placeholder:text-slate-500"
|
||||||
value={$appState.authForm.email}
|
value={$appState.authForm.email}
|
||||||
oninput={(event) => appController.setAuthField('email', (event.currentTarget as HTMLInputElement).value)}
|
oninput={(event) => appController.setAuthField('email', (event.currentTarget as HTMLInputElement).value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<Label class="sr-only" for="authPassword">Password</Label>
|
<Label for="authPassword" class="text-sm font-medium text-slate-200">Password</Label>
|
||||||
<Input
|
<Input
|
||||||
id="authPassword"
|
id="authPassword"
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="Password"
|
placeholder="Enter your password"
|
||||||
class="h-12 rounded-2xl border-white/10 bg-white/[0.04] text-sm text-white placeholder:text-slate-500"
|
class="h-11 rounded-2xl border-white/10 bg-white/[0.04] text-sm text-white placeholder:text-slate-500"
|
||||||
value={$appState.authForm.password}
|
value={$appState.authForm.password}
|
||||||
oninput={(event) => appController.setAuthField('password', (event.currentTarget as HTMLInputElement).value)}
|
oninput={(event) => appController.setAuthField('password', (event.currentTarget as HTMLInputElement).value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if isSignup()}
|
|
||||||
<div id="authNameField" class="space-y-2">
|
|
||||||
<Label class="sr-only" for="authName">Name</Label>
|
|
||||||
<Input
|
|
||||||
id="authName"
|
|
||||||
type="text"
|
|
||||||
placeholder="Display name"
|
|
||||||
class="h-12 rounded-2xl border-white/10 bg-white/[0.04] text-sm text-white placeholder:text-slate-500"
|
|
||||||
value={$appState.authForm.name}
|
|
||||||
oninput={(event) => appController.setAuthField('name', (event.currentTarget as HTMLInputElement).value)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</CardContent>
|
|
||||||
|
|
||||||
<CardFooter class="flex flex-col items-stretch gap-4 px-7 pb-7 pt-2">
|
|
||||||
<Button
|
<Button
|
||||||
id="signInBtn"
|
id="signInBtn"
|
||||||
variant="premium"
|
variant="premium"
|
||||||
class="h-12 w-full rounded-2xl text-base shadow-[0_24px_60px_rgba(37,99,235,0.26)]"
|
class="h-11 w-full rounded-2xl text-sm font-semibold"
|
||||||
onclick={() => appController.submitAuth()}
|
onclick={() => appController.submitAuth()}
|
||||||
>
|
>
|
||||||
{primaryLabel()}
|
{primaryLabel()}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<div class="flex items-center justify-between gap-4 rounded-2xl border border-white/8 bg-white/[0.03] px-4 py-3 text-sm text-slate-400">
|
<div class="border-t border-white/10 pt-4 text-center text-sm text-slate-400">
|
||||||
<span>{isSignup() ? 'Already provisioned?' : 'Need a new workspace?'}</span>
|
<span>{secondaryPrompt()}</span>
|
||||||
<Button
|
<Button
|
||||||
href={secondaryHref()}
|
href={secondaryHref()}
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
class="h-auto rounded-full px-0 text-sm font-medium text-white hover:bg-transparent hover:text-sky-200"
|
class="ml-1 h-auto rounded-full px-2 text-sm font-medium text-white hover:bg-transparent hover:text-sky-200"
|
||||||
>
|
>
|
||||||
{secondaryLabel()}
|
{secondaryLabel()}
|
||||||
<ArrowRight class="ml-2 size-4" />
|
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</CardFooter>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
Reference in New Issue
Block a user