71 lines
2.3 KiB
TypeScript
71 lines
2.3 KiB
TypeScript
import { useAuth } from '../contexts/AuthContext'
|
|
import { useNavigate } from 'react-router-dom'
|
|
import { useEffect, useState } from 'react'
|
|
import { GoogleSignInButton } from '../components/GoogleSignInButton'
|
|
import { TreeAnimation } from '../components/TreeAnimation'
|
|
import { PageLoader } from '../components/PageLoader'
|
|
|
|
export default function LoginPage() {
|
|
const { user, loading, signInWithGoogle, authError } = useAuth()
|
|
const navigate = useNavigate()
|
|
const [signingIn, setSigningIn] = useState(false)
|
|
const [error, setError] = useState<string | null>(null)
|
|
|
|
useEffect(() => {
|
|
if (loading) return
|
|
if (user) navigate('/write', { replace: true })
|
|
}, [user, loading, navigate])
|
|
|
|
async function handleGoogleSignIn() {
|
|
setError(null)
|
|
setSigningIn(true)
|
|
try {
|
|
await signInWithGoogle()
|
|
} catch (e) {
|
|
setError(e instanceof Error ? e.message : 'Sign-in failed')
|
|
} finally {
|
|
setSigningIn(false)
|
|
}
|
|
}
|
|
|
|
if (loading || signingIn) {
|
|
return <PageLoader />
|
|
}
|
|
|
|
return (
|
|
<div className="lp">
|
|
{/* ── Left: animated tree hero ─────────────────── */}
|
|
<div className="lp__hero">
|
|
<TreeAnimation />
|
|
<div className="lp__hero-words">
|
|
<p className="lp__quote">Grow your gratitude.</p>
|
|
<p className="lp__subquote">One small moment at a time.</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* ── Right: login panel ───────────────────────── */}
|
|
<div className="lp__panel">
|
|
<div className="lp__form">
|
|
<div className="lp__brand">
|
|
<span className="lp__icon" aria-hidden>🌱</span>
|
|
<h1 className="lp__title">Grateful Journal</h1>
|
|
</div>
|
|
|
|
<p className="lp__tagline">
|
|
A private space for gratitude and reflection.<br />
|
|
No feeds. No noise. Just you and your thoughts.
|
|
</p>
|
|
|
|
<div className="lp__actions">
|
|
<GoogleSignInButton loading={signingIn} onClick={handleGoogleSignIn} />
|
|
<p className="lp__privacy">🔒 End-to-end encrypted. We never read your entries.</p>
|
|
{(error || authError) && (
|
|
<p className="lp__error" role="alert">{error || authError}</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|