Prashikshak / Web /src /components /TwoFactorSetup.tsx
Abhisingh-18's picture
Initial commit: Prashikshak - disaster management training platform
9a92a42
Raw
History Blame Contribute Delete
4.78 kB
import { useState } from 'react';
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { AlertCircle, CheckCircle2, Loader2, QrCode } from 'lucide-react';
import authApi from '@/api/auth.api';
interface TwoFactorSetupProps {
onComplete?: () => void;
}
export default function TwoFactorSetup({ onComplete }: TwoFactorSetupProps) {
const [step, setStep] = useState<'initial' | 'setup' | 'verify' | 'success'>('initial');
const [qrCode, setQrCode] = useState<string>('');
const [otp, setOtp] = useState<string>('');
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const startSetup = async () => {
setIsLoading(true);
setError(null);
try {
const data = await authApi.setup2FA();
setQrCode(data.qrCode);
setStep('setup');
} catch (err: any) {
setError(err.response?.data?.message || "Failed to start 2FA setup.");
} finally {
setIsLoading(false);
}
};
const verifySetup = async () => {
if (!otp) return;
setIsLoading(true);
setError(null);
try {
await authApi.verify2FA(otp);
setStep('success');
} catch (err: any) {
setError(err.response?.data?.message || "Invalid OTP. Please try again.");
} finally {
setIsLoading(false);
}
};
const handleComplete = () => {
if (onComplete) {
onComplete();
} else {
setStep('initial');
}
};
return (
<Card className="w-full max-w-md mx-auto">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<QrCode className="w-5 h-5" />
Two-Factor Authentication
</CardTitle>
<CardDescription>
Secure your account with Google Authenticator.
</CardDescription>
</CardHeader>
<CardContent>
{step === 'initial' && (
<div className="space-y-4">
<p className="text-sm text-muted-foreground">
Two-factor authentication adds an extra layer of security to your account.
Once enabled, you'll need to enter a code from your Google Authenticator app when logging in.
</p>
<Button onClick={startSetup} disabled={isLoading} className="w-full">
{isLoading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
Setup / Reset 2FA
</Button>
{error && <p className="text-sm text-red-500 mt-2">{error}</p>}
</div>
)}
{step === 'setup' && (
<div className="space-y-6">
<div className="flex flex-col items-center justify-center p-4 border rounded-lg bg-white">
<img src={qrCode} alt="2FA QR Code" className="w-48 h-48" />
</div>
<div className="space-y-2">
<Label>1. Scan QR Code</Label>
<p className="text-xs text-muted-foreground">
Open Google Authenticator and scan the QR code above.
</p>
</div>
<div className="space-y-2">
<Label>2. Enter Code</Label>
<Input
placeholder="Enter 6-digit code"
value={otp}
onChange={(e) => setOtp(e.target.value)}
maxLength={6}
/>
</div>
{error && (
<div className="flex items-center gap-2 text-sm text-red-500">
<AlertCircle className="w-4 h-4" />
{error}
</div>
)}
<Button onClick={verifySetup} disabled={isLoading || otp.length !== 6} className="w-full">
{isLoading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
Verify & Enable
</Button>
</div>
)}
{step === 'success' && (
<div className="flex flex-col items-center justify-center py-6 space-y-4 text-center">
<div className="w-12 h-12 rounded-full bg-green-100 flex items-center justify-center text-green-600">
<CheckCircle2 className="w-6 h-6" />
</div>
<div className="space-y-1">
<h3 className="font-medium">2FA Enabled Successfully</h3>
<p className="text-sm text-muted-foreground">
Your account is now secured with two-factor authentication.
</p>
</div>
<Button variant="outline" onClick={handleComplete} className="w-full">
Done
</Button>
</div>
)}
</CardContent>
</Card>
);
}