mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-24 06:31:14 -05:00
feat: Implement all authentication compliance phases
This commit is contained in:
@@ -244,6 +244,7 @@ export function AuthModal({ open, onOpenChange, defaultTab = 'signin' }: AuthMod
|
||||
email: formData.email,
|
||||
password: formData.password,
|
||||
options: {
|
||||
emailRedirectTo: `${window.location.origin}/auth/callback`,
|
||||
data: {
|
||||
username: formData.username,
|
||||
display_name: formData.displayName
|
||||
|
||||
101
src/components/auth/EmailOTPInput.tsx
Normal file
101
src/components/auth/EmailOTPInput.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
import { useState } from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { InputOTP, InputOTPGroup, InputOTPSlot } from '@/components/ui/input-otp';
|
||||
import { Alert, AlertDescription } from '@/components/ui/alert';
|
||||
import { Mail } from 'lucide-react';
|
||||
|
||||
interface EmailOTPInputProps {
|
||||
email: string;
|
||||
onVerify: (code: string) => Promise<void>;
|
||||
onCancel: () => void;
|
||||
onResend: () => Promise<void>;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
export function EmailOTPInput({
|
||||
email,
|
||||
onVerify,
|
||||
onCancel,
|
||||
onResend,
|
||||
loading = false
|
||||
}: EmailOTPInputProps) {
|
||||
const [code, setCode] = useState('');
|
||||
const [resending, setResending] = useState(false);
|
||||
|
||||
const handleVerify = async () => {
|
||||
if (code.length === 6) {
|
||||
await onVerify(code);
|
||||
}
|
||||
};
|
||||
|
||||
const handleResend = async () => {
|
||||
setResending(true);
|
||||
try {
|
||||
await onResend();
|
||||
setCode(''); // Reset code input
|
||||
} finally {
|
||||
setResending(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<Alert>
|
||||
<Mail className="h-4 w-4" />
|
||||
<AlertDescription>
|
||||
We've sent a 6-digit verification code to <strong>{email}</strong>
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<div className="text-sm text-muted-foreground text-center">
|
||||
Enter the 6-digit code
|
||||
</div>
|
||||
|
||||
<InputOTP
|
||||
maxLength={6}
|
||||
value={code}
|
||||
onChange={setCode}
|
||||
disabled={loading}
|
||||
>
|
||||
<InputOTPGroup>
|
||||
<InputOTPSlot index={0} />
|
||||
<InputOTPSlot index={1} />
|
||||
<InputOTPSlot index={2} />
|
||||
<InputOTPSlot index={3} />
|
||||
<InputOTPSlot index={4} />
|
||||
<InputOTPSlot index={5} />
|
||||
</InputOTPGroup>
|
||||
</InputOTP>
|
||||
|
||||
<div className="flex gap-2 w-full">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={onCancel}
|
||||
className="flex-1"
|
||||
disabled={loading || resending}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleVerify}
|
||||
className="flex-1"
|
||||
disabled={code.length !== 6 || loading || resending}
|
||||
>
|
||||
{loading ? 'Verifying...' : 'Verify'}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={handleResend}
|
||||
disabled={loading || resending}
|
||||
className="text-xs"
|
||||
>
|
||||
{resending ? 'Sending...' : "Didn't receive a code? Resend"}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user