import { useState } from 'react'; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Separator } from '@/components/ui/separator'; import { Zap, Mail, Lock, User, Eye, EyeOff } from 'lucide-react'; import { supabase } from '@/integrations/supabase/client'; import { useToast } from '@/hooks/use-toast'; import { TurnstileCaptcha } from './TurnstileCaptcha'; import { notificationService } from '@/lib/notificationService'; interface AuthModalProps { open: boolean; onOpenChange: (open: boolean) => void; defaultTab?: 'signin' | 'signup'; } export function AuthModal({ open, onOpenChange, defaultTab = 'signin' }: AuthModalProps) { const { toast } = useToast(); const [loading, setLoading] = useState(false); const [magicLinkLoading, setMagicLinkLoading] = useState(false); const [showPassword, setShowPassword] = useState(false); const [captchaToken, setCaptchaToken] = useState(null); const [captchaKey, setCaptchaKey] = useState(0); const [signInCaptchaToken, setSignInCaptchaToken] = useState(null); const [signInCaptchaKey, setSignInCaptchaKey] = useState(0); const [formData, setFormData] = useState({ email: '', password: '', confirmPassword: '', username: '', displayName: '' }); // Detect iframe environment and make CAPTCHA optional for preview compatibility const isInIframe = window.self !== window.top; const requireCaptcha = !isInIframe; const handleInputChange = (e: React.ChangeEvent) => { setFormData(prev => ({ ...prev, [e.target.name]: e.target.value })); }; const handleSignIn = async (e: React.FormEvent) => { e.preventDefault(); setLoading(true); if (requireCaptcha && !signInCaptchaToken) { toast({ variant: "destructive", title: "CAPTCHA required", description: "Please complete the CAPTCHA verification." }); setLoading(false); return; } const tokenToUse = signInCaptchaToken; setSignInCaptchaToken(null); try { const signInOptions: any = { email: formData.email, password: formData.password, }; if (tokenToUse) { signInOptions.options = { captchaToken: tokenToUse }; } const { error } = await supabase.auth.signInWithPassword(signInOptions); if (error) throw error; toast({ title: "Welcome back!", description: "You've been signed in successfully." }); onOpenChange(false); } catch (error: any) { setSignInCaptchaKey(prev => prev + 1); toast({ variant: "destructive", title: "Sign in failed", description: error.message }); } finally { setLoading(false); } }; const handleSignUp = async (e: React.FormEvent) => { e.preventDefault(); setLoading(true); if (formData.password !== formData.confirmPassword) { toast({ variant: "destructive", title: "Passwords don't match", description: "Please make sure your passwords match." }); setLoading(false); return; } if (formData.password.length < 6) { toast({ variant: "destructive", title: "Password too short", description: "Password must be at least 6 characters long." }); setLoading(false); return; } if (requireCaptcha && !captchaToken) { toast({ variant: "destructive", title: "CAPTCHA required", description: "Please complete the CAPTCHA verification." }); setLoading(false); return; } const tokenToUse = captchaToken; setCaptchaToken(null); try { const signUpOptions: any = { email: formData.email, password: formData.password, options: { data: { username: formData.username, display_name: formData.displayName } } }; if (tokenToUse) { signUpOptions.options.captchaToken = tokenToUse; } const { data, error } = await supabase.auth.signUp(signUpOptions); if (error) throw error; if (data.user) { notificationService.createSubscriber({ subscriberId: data.user.id, email: formData.email, firstName: formData.username, data: { username: formData.username, } }).catch(err => { console.error('Failed to register Novu subscriber:', err); }); } toast({ title: "Welcome to ThrillWiki!", description: "Please check your email to verify your account." }); onOpenChange(false); } catch (error: any) { setCaptchaKey(prev => prev + 1); toast({ variant: "destructive", title: "Sign up failed", description: error.message }); } finally { setLoading(false); } }; const handleMagicLinkSignIn = async (email: string) => { if (!email) { toast({ variant: "destructive", title: "Email required", description: "Please enter your email address to receive a magic link." }); return; } setMagicLinkLoading(true); try { const { error } = await supabase.auth.signInWithOtp({ email, options: { emailRedirectTo: `${window.location.origin}/` } }); if (error) throw error; toast({ title: "Magic link sent!", description: "Check your email for a sign-in link." }); onOpenChange(false); } catch (error: any) { toast({ variant: "destructive", title: "Failed to send magic link", description: error.message }); } finally { setMagicLinkLoading(false); } }; const handleSocialSignIn = async (provider: 'google' | 'discord') => { try { const { error } = await supabase.auth.signInWithOAuth({ provider, options: { redirectTo: `${window.location.origin}/` } }); if (error) throw error; } catch (error: any) { toast({ variant: "destructive", title: "Social sign in failed", description: error.message }); } }; return ( ThrillWiki Join the ultimate theme park community Sign In Sign Up
{requireCaptcha && (
setSignInCaptchaToken(null)} onExpire={() => setSignInCaptchaToken(null)} siteKey={import.meta.env.VITE_TURNSTILE_SITE_KEY} theme="auto" />
)}

Enter your email above and click to receive a sign-in link

Or continue with
{requireCaptcha && (
setCaptchaToken(null)} onExpire={() => setCaptchaToken(null)} siteKey={import.meta.env.VITE_TURNSTILE_SITE_KEY} theme="auto" />
)}

By signing up, you agree to our{' '} Terms {' '}and{' '} Privacy Policy

); }