111 lines
3.6 KiB
TypeScript
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>
|
|
);
|
|
}
|