"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 (
{/* Header */}
{mode === 'link' ? (
) : (
)}
{mode === 'link' ? 'Link Google Account' : 'Customer Sign In'}
{/* Body */}
{error && (
{error}
)}
{mode === 'login' ? (
<>
Welcome to iFixKart
Access your order history, track shipments, and sync your cart
seamlessly.
{[
{ icon: Package, label: 'Orders' },
{ icon: MapPin, label: 'Addresses' },
{ icon: ShoppingBag, label: 'Cart sync' },
].map(({ icon: Icon, label }) => (
-
{label}
))}
>
) : (
)}
);
}
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 (
);
}