'use client'; import { useEffect, useState, useCallback, Suspense } from 'react'; import { useRouter, useSearchParams } from 'next/navigation'; import { httpClient } from '@/app/infra/http/HttpClient'; import { toast } from 'sonner'; import { useTranslation } from 'react-i18next'; import { Loader2, AlertCircle, CheckCircle2, AlertTriangle, } from 'lucide-react'; import { Card, CardContent, CardHeader, CardTitle, CardDescription, } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { LoadingSpinner } from '@/components/ui/loading-spinner'; import langbotIcon from '@/app/assets/langbot-logo.webp'; function SpaceOAuthCallbackContent() { const router = useRouter(); const searchParams = useSearchParams(); const { t } = useTranslation(); const [status, setStatus] = useState< 'loading' | 'confirm' | 'success' | 'error' >('loading'); const [errorMessage, setErrorMessage] = useState(''); const [isBindMode, setIsBindMode] = useState(false); const [code, setCode] = useState(null); const [isProcessing, setIsProcessing] = useState(false); const [localEmail, setLocalEmail] = useState(''); const handleOAuthCallback = useCallback( async (authCode: string) => { try { const response = await httpClient.exchangeSpaceOAuthCode(authCode); localStorage.setItem('token', response.token); if (response.user) { localStorage.setItem('userEmail', response.user); } setStatus('success'); toast.success(t('common.spaceLoginSuccess')); // If wizard state exists, redirect back to wizard instead of home const wizardState = localStorage.getItem('langbot_wizard_state'); const redirectTo = wizardState ? '/wizard' : '/home'; setTimeout(() => { router.push(redirectTo); }, 1000); } catch (err) { setStatus('error'); const errorObj = err as { msg?: string }; const errMsg = (errorObj?.msg || '').toLowerCase(); if (errMsg.includes('account email mismatch')) { setErrorMessage(t('account.spaceEmailMismatch')); } else { setErrorMessage(t('common.spaceLoginFailed')); } } }, [router, t], ); const [bindState, setBindState] = useState(null); const handleBindAccount = useCallback( async (authCode: string, state: string) => { setIsProcessing(true); try { const response = await httpClient.bindSpaceAccount(authCode, state); localStorage.setItem('token', response.token); if (response.user) { localStorage.setItem('userEmail', response.user); } setStatus('success'); toast.success(t('account.bindSpaceSuccess')); setTimeout(() => { router.push('/home'); }, 1000); } catch (err) { setStatus('error'); const errorObj = err as { msg?: string }; const errMsg = (errorObj?.msg || '').toLowerCase(); if (errMsg.includes('account email mismatch')) { setErrorMessage(t('account.spaceEmailMismatch')); } else { setErrorMessage(t('account.bindSpaceFailed')); } } finally { setIsProcessing(false); } }, [router, t], ); useEffect(() => { const authCode = searchParams.get('code'); const error = searchParams.get('error'); const errorDescription = searchParams.get('error_description'); const mode = searchParams.get('mode'); const state = searchParams.get('state'); if (error) { setStatus('error'); setErrorMessage( errorDescription || error || t('common.spaceLoginFailed'), ); return; } if (!authCode) { setStatus('error'); setErrorMessage(t('common.spaceLoginNoCode')); return; } setCode(authCode); if (mode === 'bind') { // Bind mode - verify state (token) exists if (!state) { setStatus('error'); setErrorMessage(t('account.bindSpaceInvalidState')); return; } setBindState(state); setIsBindMode(true); setLocalEmail(localStorage.getItem('userEmail') || ''); setStatus('confirm'); } else { // Normal login/register mode handleOAuthCallback(authCode); } }, [searchParams, handleOAuthCallback, t]); const handleConfirmBind = () => { if (code && bindState) { handleBindAccount(code, bindState); } }; const handleCancelBind = () => { router.push('/home'); }; return (
LangBot {status === 'loading' && t('common.spaceLoginProcessing')} {status === 'confirm' && t('account.bindSpaceConfirmTitle')} {status === 'success' && (isBindMode ? t('account.bindSpaceSuccess') : t('common.spaceLoginSuccess'))} {status === 'error' && (isBindMode ? t('account.bindSpaceFailed') : t('common.spaceLoginError'))} {status === 'loading' && t('common.spaceLoginProcessingDescription')} {status === 'confirm' && t('account.bindSpaceConfirmDescription')} {status === 'success' && t('common.spaceLoginSuccessDescription')} {status === 'error' && errorMessage} {status === 'loading' && } {status === 'confirm' && ( <>

{t('account.bindSpaceWarning', { localEmail: localEmail || '-', })}

)} {status === 'success' && ( )} {status === 'error' && ( <> )}
); } function LoadingFallback() { return (
); } export default function SpaceOAuthCallback() { return ( }> ); }