"use client"; import React, { useState, useEffect } from 'react'; import { LogIn, X, Lock, Link as LinkIcon, ArrowLeft, Package, MapPin, ShoppingBag, } from 'lucide-react'; import { GoogleOAuthProvider, useGoogleLogin } from '@react-oauth/google'; import { useAuthStore } from '@/store/authStore'; import { setAccessToken, API_BASE_URL } from '@/services/api/client'; interface GoogleAuthModalProps { isOpen: boolean; onClose: () => void; onSuccess?: (customerData: any) => void; } function GoogleIcon({ className = 'w-5 h-5' }: { className?: string }) { return ( ); } function BrandMark() { return (
iFix Kart
); } function GoogleAuthInner({ isOpen, onClose, onSuccess }: GoogleAuthModalProps) { const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [csrfToken, setCsrfToken] = useState(''); const [mode, setMode] = useState<'login' | 'link'>('login'); const [linkEmail, setLinkEmail] = useState(''); const [linkPassword, setLinkPassword] = useState(''); const [tempAuthCode, setTempAuthCode] = useState(''); const setAuth = useAuthStore((state) => state.setAuth); useEffect(() => { if (!isOpen) return; const prev = document.body.style.overflow; document.body.style.overflow = 'hidden'; const array = new Uint32Array(4); if (typeof window !== 'undefined' && window.crypto) { window.crypto.getRandomValues(array); setCsrfToken(Array.from(array, (dec) => dec.toString(16)).join('')); } else { setCsrfToken( Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15) ); } const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); }; document.addEventListener('keydown', onKey); return () => { document.body.style.overflow = prev; document.removeEventListener('keydown', onKey); }; }, [isOpen, onClose]); useEffect(() => { if (isOpen) { setMode('login'); setError(null); setLinkPassword(''); setLoading(false); } }, [isOpen]); const handleAuthCodeSubmit = async (code: string) => { setLoading(true); setError(null); try { const guestSessionId = typeof window !== 'undefined' ? localStorage.getItem('guest_session_id') || undefined : undefined; const res = await fetch(`${API_BASE_URL}/api/v1/customer/auth/google`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest', }, credentials: 'include', body: JSON.stringify({ code, state: csrfToken, guest_session_id: guestSessionId, redirect_uri: 'postmessage', }), }); const data = await res.json(); if (res.status === 409 && data.detail === 'account_linking_required') { setTempAuthCode(code); setLinkEmail(data.email || ''); setMode('link'); return; } if (!res.ok) { throw new Error(data.detail || 'Google authentication failed.'); } setAccessToken(data.access_token); setAuth(data.access_token, { customer_id: data.customer_id, email: data.email, first_name: data.first_name, }); onSuccess?.(data); onClose(); } catch (err: any) { setError(err.message || 'Google authentication failed. Please try again.'); } finally { setLoading(false); } }; const handleLinkAccountSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!linkPassword) { setError('Password is required to link account.'); return; } setLoading(true); setError(null); try { const guestSessionId = typeof window !== 'undefined' ? localStorage.getItem('guest_session_id') || undefined : undefined; const res = await fetch(`${API_BASE_URL}/api/v1/customer/auth/link-google`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest', }, credentials: 'include', body: JSON.stringify({ email: linkEmail, password: linkPassword, code: tempAuthCode, state: csrfToken, guest_session_id: guestSessionId, redirect_uri: 'postmessage', }), }); const data = await res.json(); if (!res.ok) { throw new Error(data.detail || 'Verification failed. Check your password.'); } setAccessToken(data.access_token); setAuth(data.access_token, { customer_id: data.customer_id, email: data.email, first_name: data.first_name, }); onSuccess?.(data); onClose(); } catch (err: any) { setError(err.message || 'Account linking failed.'); } finally { setLoading(false); } }; const googleLogin = useGoogleLogin({ onSuccess: (codeResponse) => { if (codeResponse.code) handleAuthCodeSubmit(codeResponse.code); }, onError: () => { setError('Google Login popup was closed or authentication failed.'); }, flow: 'auth-code', state: csrfToken, }); if (!isOpen) return null; return (
{/* Body */}
{error && (
{error}
)} {mode === 'login' ? ( <>

Welcome to iFixKart

Access your order history, track shipments, and sync your cart seamlessly.

) : (

Existing Account Detected

An account already exists under{' '} {linkEmail}. Enter your password to link Google securely.

setLinkPassword(e.target.value)} required disabled={loading} placeholder="••••••••" className="w-full pl-10 pr-4 py-2.5 bg-[#F8F9FB] border border-gray-200 rounded-lg text-sm text-[#1a1a1a] placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-primary/25 focus:border-primary transition" />
)}
); } export default function GoogleAuthModal(props: GoogleAuthModalProps) { const googleClientId = process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID || ''; if (!props.isOpen) return null; if (!googleClientId) { return (

Google Sign-In Unconfigured

NEXT_PUBLIC_GOOGLE_CLIENT_ID is missing. Add it to .env.local to enable Google Sign-In.

); } return ( ); }