Files
Account/src/features/authentication/components/AuthenticationSteps/GoogleAuthenticationV2.tsx
Sajad Mirjalili 2a6dd67cb4 fix: ui bugs
2025-11-28 16:15:43 +03:30

129 lines
3.5 KiB
TypeScript

import { useEffect, useRef, useState } from 'react';
import type {
LoginOrSignUpWithGoogleRequest,
LoginResult,
} from '../../types/userTypes';
import type { AuthFactory } from '../../types/authTypes';
import {
generateTokenWithGoogle,
type GenerateTokenResponse,
} from '../../api/identityAPI';
import { loginOrSignUpWithGoogle } from '../../api/authorizationAPI';
import { useApi } from '@/hooks/useApi';
import { useToast } from '@rkheftan/harmony-ui';
import { useTranslation } from 'react-i18next';
import { Box, Button } from '@mui/material';
interface GoogleAuthenticationV2Props {
authFactory: AuthFactory;
onGoogleAuthenticated: (
loginResult: LoginResult,
tokenResponse: GenerateTokenResponse,
) => void;
}
export const GoogleAuthenticationV2 = ({
authFactory,
onGoogleAuthenticated,
}: GoogleAuthenticationV2Props) => {
const toast = useToast();
const { t } = useTranslation('authentication');
const { execute: loginWithGoogleCall } = useApi(loginOrSignUpWithGoogle);
const [isGoogleLoaded, setIsGoogleLoaded] = useState(false);
const googleBtnRef = useRef<HTMLDivElement>(null);
const renderedRef = useRef(false);
const handleCredentialResponse = async (response: any) => {
const idToken = response.credential;
try {
const apiRequest: LoginOrSignUpWithGoogleRequest = {
idToken: idToken,
returnUrl: authFactory.redirectUrl,
};
const res = await loginWithGoogleCall(apiRequest);
if (!res) return;
if (res.success) {
const tokenRes = await generateTokenWithGoogle({
...apiRequest,
client_id: authFactory.clientId,
});
onGoogleAuthenticated(res, tokenRes.data);
} else {
toast({
message: t('loginForm.googleAuthenticationFailed'),
severity: 'error',
});
}
} catch (error) {
toast({
message: t('loginForm.googleAuthenticationFailed'),
severity: 'error',
});
}
};
useEffect(() => {
// Ensure the DOM element exists
if (!googleBtnRef.current || renderedRef.current) return;
// Logic to initialize Google Button
const initializeGoogle = () => {
if (!window.google) return;
setIsGoogleLoaded(true);
google.accounts.id.initialize({
client_id: import.meta.env.VITE_GOOGLE_CLIENT_ID,
callback: handleCredentialResponse,
});
google.accounts.id.renderButton(googleBtnRef.current, {
theme: 'outline', // Matches your MUI 'variant="outlined"'
size: 'large', // Standard button size
type: 'standard', // The standard "Sign in with Google" button
text: 'signin_with', // Text: "Sign in with Google"
shape: 'rectangular', // Matches your MUI button shape
width: '400', // Set a width (Google caps this at 400px)
logo_alignment: 'left',
height: '44',
});
renderedRef.current = true;
};
if (window.google?.accounts) {
initializeGoogle();
} else {
const timer = setInterval(() => {
if (window.google?.accounts) {
initializeGoogle();
clearInterval(timer);
}
}, 500);
return () => clearInterval(timer);
}
}, []);
return (
<>
<Box
sx={{
width: '100%',
display: 'flex',
justifyContent: 'center',
minHeight: 44,
}}
>
{!isGoogleLoaded && <Button variant="outlined" loading />}
<div ref={googleBtnRef} id="google-signin-button"></div>
</Box>
</>
);
};