Bible Reader Enhancements: - Add chat icon to each verse for AI explanations - Implement handleVerseChat function with pre-filled contextual messages - Chat opens with message: "Explain in depth this verse [text] from [version], [book] [chapter:verse] and its meaning" - Visible to all users, redirects to login for unauthenticated users - Fix copy message translation from 'bible.copied' to 'copied' Login System Improvements: - Fix redirect parameter handling in login pages - Users are now properly redirected to /bible page after successful login - Preserve redirect URL parameters through login flow - Add Suspense boundaries for useSearchParams compliance - Ensure verse/chapter context is maintained after login Technical Changes: - Add Chat icon import from Material-UI - Implement floating chat event dispatch system - Fix Next.js 15 build warnings with proper Suspense wrapping - Maintain existing UX patterns (visible to all, functional for authenticated users) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
154 lines
4.2 KiB
TypeScript
154 lines
4.2 KiB
TypeScript
'use client'
|
|
|
|
import { useState, Suspense } from 'react'
|
|
import { useRouter, useSearchParams } from 'next/navigation'
|
|
import { useTranslations, useLocale } from 'next-intl'
|
|
import {
|
|
Container,
|
|
Paper,
|
|
Box,
|
|
Typography,
|
|
Tabs,
|
|
Tab,
|
|
Link,
|
|
Card,
|
|
CardContent,
|
|
Divider,
|
|
CircularProgress
|
|
} from '@mui/material'
|
|
import {
|
|
MenuBook,
|
|
Login as LoginIcon,
|
|
PersonAdd
|
|
} from '@mui/icons-material'
|
|
import { LoginForm } from '@/components/auth/login-form'
|
|
import { RegisterForm } from '@/components/auth/register-form'
|
|
|
|
function AuthContent() {
|
|
const [activeTab, setActiveTab] = useState(0)
|
|
const router = useRouter()
|
|
const locale = useLocale()
|
|
const searchParams = useSearchParams()
|
|
const t = useTranslations('auth')
|
|
|
|
const handleAuthSuccess = () => {
|
|
const redirect = searchParams.get('redirect')
|
|
if (redirect) {
|
|
router.push(redirect)
|
|
} else {
|
|
router.push(`/${locale}`)
|
|
}
|
|
}
|
|
|
|
const handleTabChange = (event: React.SyntheticEvent, newValue: number) => {
|
|
setActiveTab(newValue)
|
|
}
|
|
|
|
const getSubtitle = () => {
|
|
if (locale === 'en') {
|
|
return activeTab === 0
|
|
? 'Sign in to continue exploring Scripture'
|
|
: 'Create an account to begin your spiritual journey'
|
|
}
|
|
return activeTab === 0
|
|
? 'Conectează-te pentru a continua explorarea Scripturii'
|
|
: 'Creează un cont pentru a începe călătoria ta spirituală'
|
|
}
|
|
|
|
return (
|
|
<Container maxWidth="sm" sx={{ py: 4, minHeight: '100vh', display: 'flex', alignItems: 'center' }}>
|
|
<Card elevation={8} sx={{ width: '100%', borderRadius: 3 }}>
|
|
<CardContent sx={{ p: 4 }}>
|
|
{/* Header */}
|
|
<Box textAlign="center" mb={4}>
|
|
<Box display="flex" justifyContent="center" mb={2}>
|
|
<MenuBook sx={{ fontSize: 48, color: 'primary.main' }} />
|
|
</Box>
|
|
<Typography variant="h4" component="h1" gutterBottom fontWeight="bold">
|
|
{activeTab === 0 ? t('welcomeBack') : t('joinUs')}
|
|
</Typography>
|
|
<Typography variant="body1" color="text.secondary">
|
|
{getSubtitle()}
|
|
</Typography>
|
|
</Box>
|
|
|
|
<Divider sx={{ mb: 3 }} />
|
|
|
|
{/* Tabs */}
|
|
<Tabs
|
|
value={activeTab}
|
|
onChange={handleTabChange}
|
|
centered
|
|
sx={{
|
|
mb: 3,
|
|
'& .MuiTab-root': {
|
|
minWidth: 120,
|
|
fontWeight: 600
|
|
}
|
|
}}
|
|
TabIndicatorProps={{
|
|
style: { height: 3, borderRadius: 3 }
|
|
}}
|
|
>
|
|
<Tab
|
|
icon={<LoginIcon />}
|
|
iconPosition="start"
|
|
label={t('login')}
|
|
/>
|
|
<Tab
|
|
icon={<PersonAdd />}
|
|
iconPosition="start"
|
|
label={t('register')}
|
|
/>
|
|
</Tabs>
|
|
|
|
{/* Forms */}
|
|
<Box sx={{ minHeight: 300 }}>
|
|
{activeTab === 0 ? (
|
|
<LoginForm onSuccess={handleAuthSuccess} />
|
|
) : (
|
|
<RegisterForm onSuccess={handleAuthSuccess} />
|
|
)}
|
|
</Box>
|
|
|
|
<Divider sx={{ my: 3 }} />
|
|
|
|
{/* Switch Form Link */}
|
|
<Box textAlign="center">
|
|
<Typography variant="body2" color="text.secondary">
|
|
{activeTab === 0 ? t('noAccount') : t('alreadyHaveAccount')}{' '}
|
|
<Link
|
|
component="button"
|
|
variant="body2"
|
|
onClick={() => setActiveTab(activeTab === 0 ? 1 : 0)}
|
|
sx={{
|
|
textDecoration: 'none',
|
|
fontWeight: 600,
|
|
'&:hover': {
|
|
textDecoration: 'underline'
|
|
}
|
|
}}
|
|
>
|
|
{activeTab === 0 ? t('createAccount') : t('login')}
|
|
</Link>
|
|
</Typography>
|
|
</Box>
|
|
</CardContent>
|
|
</Card>
|
|
</Container>
|
|
)
|
|
}
|
|
|
|
export default function AuthPage() {
|
|
return (
|
|
<Suspense fallback={
|
|
<Container maxWidth="sm" sx={{ mt: 8 }}>
|
|
<Box display="flex" justifyContent="center" alignItems="center" minHeight="400px">
|
|
<CircularProgress />
|
|
</Box>
|
|
</Container>
|
|
}>
|
|
<AuthContent />
|
|
</Suspense>
|
|
)
|
|
} |