feat: add auth setup and login flow
This commit is contained in:
103
src/app/(full-page)/login/page.tsx
Normal file
103
src/app/(full-page)/login/page.tsx
Normal file
@@ -0,0 +1,103 @@
|
||||
'use client';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { useLoginForm } from '@/hooks/useLoginForm';
|
||||
import { Loader2 } from 'lucide-react';
|
||||
import Image from 'next/image';
|
||||
|
||||
export default function LoginPage() {
|
||||
const { register, handleSubmit, errors, isLoading } = useLoginForm();
|
||||
|
||||
return (
|
||||
<main className="grid min-h-screen bg-background text-foreground lg:grid-cols-[1.05fr_0.95fr]">
|
||||
<section className="relative hidden overflow-hidden border-r border-border/60 lg:block">
|
||||
<Image
|
||||
src="/background.png"
|
||||
alt=""
|
||||
fill
|
||||
priority
|
||||
className="object-cover"
|
||||
sizes="55vw"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-background/35" />
|
||||
<div className="absolute inset-x-0 bottom-0 p-10">
|
||||
<div className="max-w-lg space-y-3">
|
||||
<p className="text-sm font-medium uppercase tracking-[0.18em] text-primary">
|
||||
VisionRoad
|
||||
</p>
|
||||
<h1 className="text-4xl font-semibold tracking-normal text-foreground">
|
||||
Road intelligence for faster inspection decisions
|
||||
</h1>
|
||||
<p className="text-sm leading-6 text-muted-foreground">
|
||||
Review projects, uploads, detections, and chainage insights from one secure
|
||||
workspace.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="flex min-h-screen items-center justify-center px-6 py-10">
|
||||
<div className="w-full max-w-sm space-y-7">
|
||||
<header className="space-y-2">
|
||||
<p className="text-sm font-medium text-muted-foreground">VisionRoad</p>
|
||||
<h2 className="text-2xl font-semibold tracking-normal">Sign in</h2>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Use your email and password to continue.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<form className="space-y-5" onSubmit={handleSubmit}>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="email">Email</Label>
|
||||
<Input
|
||||
id="email"
|
||||
type="email"
|
||||
placeholder="admin@visionroad.ai"
|
||||
autoComplete="email"
|
||||
disabled={isLoading}
|
||||
aria-invalid={!!errors.email}
|
||||
{...register('email', {
|
||||
required: 'Email is required',
|
||||
})}
|
||||
/>
|
||||
{errors.email && (
|
||||
<p className="text-sm text-destructive">{errors.email.message}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="password">Password</Label>
|
||||
<Input
|
||||
id="password"
|
||||
type="password"
|
||||
placeholder="Enter password"
|
||||
autoComplete="current-password"
|
||||
disabled={isLoading}
|
||||
aria-invalid={!!errors.password}
|
||||
{...register('password', {
|
||||
required: 'Password is required',
|
||||
})}
|
||||
/>
|
||||
{errors.password && (
|
||||
<p className="text-sm text-destructive">{errors.password.message}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Button type="submit" className="w-full" disabled={isLoading}>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<Loader2 className="size-4 animate-spin" />
|
||||
Signing in
|
||||
</>
|
||||
) : (
|
||||
'Sign in'
|
||||
)}
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user