// 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...}> } /> ) }