// DynamicRouter.tsx
import React from 'react'
import PageTitle from '@/components/shared/PageTitle'
import { Routes, Route, Navigate, useLocation } from 'react-router-dom'
import { mapCustomComponentRoutes, mapDynamicRoutes } from './dynamicRouteLoader'
import { useDynamicRoutes } from './dynamicRoutesContext'
import { useComponents } from '@/contexts/ComponentContext'
import ProtectedRoute from '@/components/route/ProtectedRoute'
import PermissionGuard from '@/components/route/PermissionGuard'
import PageContainer from '@/components/template/PageContainer'
import { ROUTES_ENUM } from './route.constant'
import { hasSubdomain } from '@/utils/subdomain'
// AccessDenied ve NotFound'u dinamiklikten çıkarıyoruz
const AccessDenied = React.lazy(() => import('@/views/AccessDenied'))
const NotFound = React.lazy(() => import('@/views/NotFound'))
const DatabaseSetup = React.lazy(() => import('@/views/setup/DatabaseSetup'))
/**
* Physical views set their own title; this only fills the gap for routes whose
* component is compiled at runtime. `fallback` sayesinde kendi başlığını
* bildiren bir bileşen buradaki başlığı her zaman yener — eskiden bu, Helmet'in
* "sonra mount olan kazanır" davranışından geliyordu.
*/
const RouteTitle = ({ title }: { title?: string }) =>
title ? : null
const RootRedirect = () => {
const location = useLocation()
const searchParams = new URLSearchParams(location.search)
const isPasswordResetLink = searchParams.has('userId') && searchParams.has('resetToken')
return (
)
}
const LegacyPasswordResetRedirect = () => {
const location = useLocation()
return
}
const LegacyEmailConfirmationRedirect = () => {
const location = useLocation()
return
}
export const DynamicRouter: React.FC = () => {
const { routes, loading, error } = useDynamicRoutes()
const { components, registeredComponents, renderComponent, isComponentRegistered } =
useComponents()
const location = useLocation()
const dynamicRoutes = React.useMemo(() => {
const customComponentRoutes = mapCustomComponentRoutes(components)
const claimedPaths = new Set(customComponentRoutes.map((route) => route.path))
// Ayni yolu iki route paylasirsa custom component kazanir: bir ekranin fiziksel
// sayfadan runtime bilesene devri (ve bileseni pasife alarak geri donusu) yalnizca
// Custom Components ekranindan yonetilir, rota kaydini silmeyi gerektirmez.
return [
...mapDynamicRoutes(routes).filter((route) => !claimedPaths.has(route.path)),
...customComponentRoutes,
]
}, [routes, components])
// /setup path'inde loading bekleme — setup route her zaman erişilebilir olmalı.
// bootstrapFailed durumu Layouts'ta, layout seçilmeden önce ele alınır.
const isSetupPath = location.pathname === ROUTES_ENUM.setup
if (loading && !isSetupPath) return
Loading...
if (error && !isSetupPath) return Hata: {error}
return (
{/* ADMIN */}
}>
{dynamicRoutes
.filter((r) => r.routeType === 'protected')
.map((route) => {
const Component = route.getComponent(
registeredComponents,
renderComponent,
isComponentRegistered,
)
return (
Loading {route.path}...}>
}
/>
)
})}
{/* admin default */}
} />
{/* admin access denied (statik) */}
Loading...}>
}
/>
{/* admin not found (statik) */}
Loading...}>
}
/>
{/* Auth/Public dinamik rotalar */}
{dynamicRoutes
.filter((r) =>
hasSubdomain() ? r.routeType === 'authenticated' : r.routeType !== 'protected',
)
.map((route) => {
const Component = route.getComponent(
registeredComponents,
renderComponent,
isComponentRegistered,
)
return (
Loading {route.path}...}>
>
}
/>
)
})}
{/* root redirect */}
} />
} />
} />
{/* public access denied (statik) */}
Loading...}>
}
/>
{/* public not found (statik) */}
Loading...}>
}
/>
{/* İlk kurulum — veritabanı mevcut değilse gösterilir */}
Loading...}>
}
/>
)
}