import { useEffect, useState } from 'react'; import { GitHubIcon } from '../ReactIcons/GitHubIcon.tsx'; import Cookies from 'js-cookie'; import { TOKEN_COOKIE_NAME } from '../../lib/jwt'; import { httpGet } from '../../lib/http'; import { Spinner } from '../ReactIcons/Spinner.tsx'; type GitHubButtonProps = { isDisabled?: boolean; setIsDisabled?: (isDisabled: boolean) => void; }; const GITHUB_REDIRECT_AT = 'githubRedirectAt'; const GITHUB_LAST_PAGE = 'githubLastPage'; export function GitHubButton(props: GitHubButtonProps) { const { isDisabled, setIsDisabled } = props; const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(''); useEffect(() => { const urlParams = new URLSearchParams(window.location.search); const code = urlParams.get('code'); const state = urlParams.get('state'); const provider = urlParams.get('provider'); if (!code || !state || provider !== 'github') { return; } setIsLoading(true); setIsDisabled?.(true); httpGet<{ token: string }>( `${import.meta.env.PUBLIC_API_URL}/v1-github-callback${ window.location.search }`, ) .then(({ response, error }) => { if (!response?.token) { const errMessage = error?.message || 'Something went wrong.'; setError(errMessage); setIsLoading(false); setIsDisabled?.(false); return; } let redirectUrl = '/'; const gitHubRedirectAt = localStorage.getItem(GITHUB_REDIRECT_AT); const lastPageBeforeGithub = localStorage.getItem(GITHUB_LAST_PAGE); // If the social redirect is there and less than 30 seconds old // redirect to the page that user was on before they clicked the github login button if (gitHubRedirectAt && lastPageBeforeGithub) { const socialRedirectAtTime = parseInt(gitHubRedirectAt, 10); const now = Date.now(); const timeSinceRedirect = now - socialRedirectAtTime; if (timeSinceRedirect < 30 * 1000) { redirectUrl = lastPageBeforeGithub; } } const authRedirectUrl = localStorage.getItem('authRedirect'); if (authRedirectUrl) { localStorage.removeItem('authRedirect'); redirectUrl = authRedirectUrl; } localStorage.removeItem(GITHUB_REDIRECT_AT); localStorage.removeItem(GITHUB_LAST_PAGE); Cookies.set(TOKEN_COOKIE_NAME, response.token, { path: '/', expires: 30, domain: import.meta.env.DEV ? 'localhost' : '.roadmap.sh', }); window.location.href = redirectUrl; }) .catch((err) => { setError('Something went wrong. Please try again later.'); setIsLoading(false); setIsDisabled?.(false); }); }, []); const handleClick = async () => { setIsLoading(true); setIsDisabled?.(true); const { response, error } = await httpGet<{ loginUrl: string }>( `${import.meta.env.PUBLIC_API_URL}/v1-github-login`, ); if (error || !response?.loginUrl) { setError( error?.message || 'Something went wrong. Please try again later.', ); setIsLoading(false); setIsDisabled?.(false); return; } // For non authentication pages, we want to redirect back to the page // the user was on before they clicked the social login button if (!['/login', '/signup'].includes(window.location.pathname)) { const pagePath = ['/respond-invite', '/befriend'].includes( window.location.pathname, ) ? window.location.pathname + window.location.search : window.location.pathname; localStorage.setItem(GITHUB_REDIRECT_AT, Date.now().toString()); localStorage.setItem(GITHUB_LAST_PAGE, pagePath); } window.location.href = response.loginUrl; }; return ( <> {error && (

{error}

)} ); }