c6d4c30461
- 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>
43 lines
1.5 KiB
TypeScript
43 lines
1.5 KiB
TypeScript
import { Navigate, Outlet, useLocation, useSearchParams } from 'react-router'
|
||
import { Logo } from '@/components/logo'
|
||
import { useMe } from '@/lib/auth'
|
||
import { safeReturnPath } from '@/lib/return-path'
|
||
import { t } from '@/lib/strings'
|
||
import { paths } from './nav-items'
|
||
|
||
/** Oturum kontrol edilirken gösterilen tam ekran açılış. */
|
||
export function Splash() {
|
||
return (
|
||
<div className="grid min-h-dvh place-items-center" role="status" aria-label={t.common.loading}>
|
||
<Logo size={56} className="animate-pulse" />
|
||
</div>
|
||
)
|
||
}
|
||
|
||
/** Oturum gerektiren sayfalar. Oturum yoksa → /giris?donus=<şimdiki adres> */
|
||
export function RequireAuth() {
|
||
const me = useMe()
|
||
const location = useLocation()
|
||
|
||
if (me.isPending) return <Splash />
|
||
if (!me.data) {
|
||
const back = location.pathname + location.search
|
||
const to = back === '/' ? paths.login : `${paths.login}?donus=${encodeURIComponent(back)}`
|
||
return <Navigate to={to} replace />
|
||
}
|
||
return <Outlet />
|
||
}
|
||
|
||
/**
|
||
* Yalnızca oturumsuzken: giriş/kayıt.
|
||
* Oturum açılınca (giriş/kayıt başarılı olduğunda da) `?donus=` adresine, yoksa panele gönderir.
|
||
* Yönlendirme yalnızca burada yapılır — formlar ayrıca `navigate` çağırmaz (yarış durumu olmasın).
|
||
*/
|
||
export function RequireGuest() {
|
||
const me = useMe()
|
||
const [params] = useSearchParams()
|
||
if (me.isPending) return <Splash />
|
||
if (me.data) return <Navigate to={safeReturnPath(params.get('donus'), paths.dashboard)} replace />
|
||
return <Outlet />
|
||
}
|