'use client'; import { ExtensionService } from '@/services/extensionService'; import { Stack, Text, Button, UnstyledButton, TextInput, PasswordInput, Alert, } from '@mantine/core'; import { BiRightArrowAlt } from 'react-icons/bi'; import { MdOutlineAlternateEmail, MdLock } from 'react-icons/md'; import { useAuth } from '@/hooks/useAuth'; import { useForm } from '@mantine/form'; import { useRouter, useSearchParams } from 'next/navigation'; import { useEffect, useState } from 'react'; import { createSembleClient } from '@/services/apiClient'; export default function LoginForm() { const router = useRouter(); const searchParams = useSearchParams(); const { isAuthenticated, refreshAuth } = useAuth(); const [isCheckingAuth, setIsCheckingAuth] = useState(true); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(''); const isExtensionLogin = searchParams.get('extension-login') === 'true'; const client = createSembleClient(); const handleExtensionTokenGeneration = async () => { try { setIsLoading(true); const tokens = await client.generateExtensionTokens(); await ExtensionService.sendTokensToExtension(tokens); setError(''); // Clear the extension tokens requested flag ExtensionService.clearExtensionTokensRequested(); // Redirect to extension success page after successful extension token generation router.push('/extension/auth/complete'); } catch (err: any) { // Clear the flag even on failure ExtensionService.clearExtensionTokensRequested(); // Redirect to extension error page router.push('/extension/auth/error'); } finally { setIsLoading(false); } }; useEffect(() => { if (isAuthenticated) { isExtensionLogin ? handleExtensionTokenGeneration() : router.push('/home'); } else { setIsCheckingAuth(false); } }, [isAuthenticated, isExtensionLogin]); const handleOAuthSubmit = async (e: React.FormEvent) => { e.preventDefault(); // validate form const isValid = form.validateField('handle'); if (!isValid) return; try { setIsLoading(true); setError(''); if (isExtensionLogin) { ExtensionService.setExtensionTokensRequested(); } console.log('HANDLE', form.values.handle.trimEnd()); const { authUrl } = await client.initiateOAuthSignIn({ handle: form.values.handle.trimEnd(), }); window.location.href = authUrl; } catch (err: any) { setError(err.message || 'An error occurred during login'); } finally { setIsLoading(false); } }; const handleAppPasswordSubmit = async (e: React.FormEvent) => { e.preventDefault(); // validate const validation = form.validate(); if (validation.hasErrors) return; try { setIsLoading(true); setError(''); await client.loginWithAppPassword({ identifier: form.values.handle.trimEnd(), appPassword: form.values.appPassword, }); // Refresh auth state to fetch user profile with new tokens (cookies are set automatically) await refreshAuth(); if (isExtensionLogin) { await handleExtensionTokenGeneration(); } else { router.push('/home'); } } catch (err: any) { setError(err.message || 'Invalid credentials'); } finally { setIsLoading(false); } }; const form = useForm({ initialValues: { handle: '', appPassword: '', useAppPassword: false, }, validate: { handle: (value) => (value.trim() ? null : 'Handle is required'), appPassword: (value, values) => values.useAppPassword && value.trim() === '' ? 'App password is required' : null, }, }); if (form.values.useAppPassword) { return (
{ form.setFieldValue('handle', event.currentTarget.value); if (error) setError(''); }} leftSection={} variant="filled" size="lg" w={'100%'} required /> } variant="filled" size="lg" w={'100%'} required /> {error && }
{ form.setFieldValue('useAppPassword', false); setError(''); }} > Use OAuth login
); } return (
{ form.setFieldValue('handle', event.currentTarget.value); if (error) setError(''); }} leftSection={} variant="filled" size="lg" w={'100%'} required /> {error && } Or { form.setFieldValue('useAppPassword', true); setError(''); }} > Use your app password
); }