feat(arayüz): sayfa yönlendirme, korumalı sayfalar ve uygulama iskeleti
- react-router: Türkçe adresler (/defter, /plan, /birikim, ...), 404 sayfası - Korumalı sayfalar: oturum yoksa /giris?donus=..., girişten sonra geri dönüş - Açık yönlendirme koruması (safeReturnPath, 10 test) - İskelet: mobilde 5 öğeli alt menü, masaüstünde sol kenar çubuğu - Diğer sayfası (değerlendirme, raporlar, ayarlar, tema, çıkış) - Arayüz metinleri lib/strings.ts'de toplanmaya başlandı - Tasarım önizlemesi /dev/tasarim (yalnızca geliştirmede) - Düzeltme: çıkışta önbellek temizliği ekranı güncellemiyordu Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import { useState, type FormEvent } from 'react'
|
||||
import { LogIn } from 'lucide-react'
|
||||
import { Link } from 'react-router'
|
||||
import { paths } from '@/components/layout/nav-items'
|
||||
import { Logo } from '@/components/logo'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { useLogin } from '@/lib/auth'
|
||||
import { useDocumentTitle } from '@/lib/use-document-title'
|
||||
|
||||
// GEÇİCİ: Faz 2 – Adım 5'te react-hook-form + zod ile gerçek giriş ekranı gelecek.
|
||||
export function LoginPage() {
|
||||
useDocumentTitle('Giriş')
|
||||
const login = useLogin()
|
||||
const [email, setEmail] = useState('')
|
||||
const [password, setPassword] = useState('')
|
||||
|
||||
const submit = (e: FormEvent) => {
|
||||
e.preventDefault()
|
||||
// Başarılı olunca RequireGuest, ?donus= adresine yönlendirir
|
||||
login.mutate({ email, password, remember_me: true })
|
||||
}
|
||||
|
||||
return (
|
||||
<main className="mx-auto flex min-h-dvh max-w-sm flex-col justify-center gap-6 px-4">
|
||||
<Logo size={56} withText />
|
||||
<form onSubmit={submit} className="flex flex-col gap-3">
|
||||
<input
|
||||
className="h-11 rounded-md border bg-background px-3"
|
||||
type="email"
|
||||
placeholder="E-posta"
|
||||
autoComplete="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
/>
|
||||
<input
|
||||
className="h-11 rounded-md border bg-background px-3"
|
||||
type="password"
|
||||
placeholder="Şifre"
|
||||
autoComplete="current-password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
/>
|
||||
{login.isError && <p className="text-sm text-expense">{login.error.message}</p>}
|
||||
<Button type="submit" size="lg" disabled={login.isPending}>
|
||||
<LogIn /> Giriş
|
||||
</Button>
|
||||
</form>
|
||||
<Link to={paths.register} className="text-center text-sm text-muted-foreground underline">
|
||||
Hesabınız yok mu? Kayıt olun
|
||||
</Link>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
// GEÇİCİ: Adım 5'te kayıt formu (davet kodu dahil).
|
||||
export function RegisterPage() {
|
||||
useDocumentTitle('Kayıt')
|
||||
return (
|
||||
<main className="mx-auto flex min-h-dvh max-w-sm flex-col justify-center gap-6 px-4 text-center">
|
||||
<Logo size={56} withText className="justify-center" />
|
||||
<p className="text-muted-foreground">Kayıt ekranı Faz 2 – Adım 5'te geliştirilecek.</p>
|
||||
<Link to={paths.login} className="text-sm underline">
|
||||
Girişe dön
|
||||
</Link>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user