UMBRA/frontend/src/components/auth/LockScreen.tsx

111 lines
3.6 KiB
TypeScript

import { useState, FormEvent } from 'react';
import { useNavigate } from 'react-router-dom';
import { toast } from 'sonner';
import { Lock } from 'lucide-react';
import { useAuth } from '@/hooks/useAuth';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
export default function LockScreen() {
const navigate = useNavigate();
const { authStatus, login, setup, isLoginPending, isSetupPending } = useAuth();
const [pin, setPin] = useState('');
const [confirmPin, setConfirmPin] = useState('');
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
if (authStatus?.setup_required) {
if (pin !== confirmPin) {
toast.error('PINs do not match');
return;
}
if (pin.length < 4) {
toast.error('PIN must be at least 4 characters');
return;
}
try {
await setup(pin);
toast.success('PIN created successfully');
navigate('/dashboard');
} catch (error: any) {
toast.error(error.response?.data?.detail || 'Failed to create PIN');
}
} else {
try {
await login(pin);
navigate('/dashboard');
} catch (error: any) {
toast.error(error.response?.data?.detail || 'Invalid PIN');
setPin('');
}
}
};
const isSetup = authStatus?.setup_required;
return (
<div className="flex min-h-screen items-center justify-center bg-background p-4">
<Card className="w-full max-w-md">
<CardHeader className="space-y-4 text-center">
<div className="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-accent/10">
<Lock className="h-8 w-8 text-accent" />
</div>
<CardTitle className="text-2xl">
{isSetup ? 'Welcome to UMBRA' : 'Enter PIN'}
</CardTitle>
<CardDescription>
{isSetup
? 'Create a PIN to secure your account'
: 'Enter your PIN to access your dashboard'}
</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleSubmit} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="pin">{isSetup ? 'Create PIN' : 'PIN'}</Label>
<Input
id="pin"
type="password"
value={pin}
onChange={(e) => setPin(e.target.value)}
placeholder="Enter PIN"
required
autoFocus
className="text-center text-lg tracking-widest"
/>
</div>
{isSetup && (
<div className="space-y-2">
<Label htmlFor="confirm-pin">Confirm PIN</Label>
<Input
id="confirm-pin"
type="password"
value={confirmPin}
onChange={(e) => setConfirmPin(e.target.value)}
placeholder="Confirm PIN"
required
className="text-center text-lg tracking-widest"
/>
</div>
)}
<Button
type="submit"
className="w-full"
disabled={isLoginPending || isSetupPending}
>
{isLoginPending || isSetupPending
? 'Please wait...'
: isSetup
? 'Create PIN'
: 'Unlock'}
</Button>
</form>
</CardContent>
</Card>
</div>
);
}