portfolio-page/src/app/AppRouter.tsx

92 lines
2.9 KiB
TypeScript

import { lazy, Suspense, useEffect } from 'react';
import { BrowserRouter as Router, Routes, Route, Navigate, useLocation } from 'react-router-dom';
import '../scss/App.scss';
import Navbar from '../components/layout/Navigation';
import Footer from '../components/layout/Footer';
import BackToTopButton from '../components/BackToTopButton';
import { useLanguage } from '../contexts/LanguageContext';
const HomePage = lazy(() => import('../pages/HomePage'));
const LandingPage = lazy(() => import('../pages/LandingPage'));
const AuditPage = lazy(() => import('../pages/AuditPage'));
const QuickcheckPage = lazy(() => import('../pages/QuickcheckPage'));
const ImprintPage = lazy(() => import('../pages/ImprintPage'));
const PrivacyPolicy = lazy(() => import('../pages/PrivacyPolicy'));
function LegacyLanguageRedirect() {
const { setLanguage } = useLanguage();
const location = useLocation();
const legacyLanguage = location.pathname.startsWith('/en') ? 'en' : 'de';
const targetPathname = location.pathname.replace(/^\/(de|en)(?=\/|$)/, '') || '/';
useEffect(() => {
setLanguage(legacyLanguage);
}, [legacyLanguage, setLanguage]);
return (
<Navigate
to={{ pathname: targetPathname, search: location.search, hash: location.hash }}
replace
/>
);
}
function AppShell() {
const location = useLocation();
const { texts } = useLanguage();
useEffect(() => {
const hash = location.hash.substring(1);
if (hash) {
setTimeout(() => {
const element = document.getElementById(hash);
if (element) {
element.scrollIntoView({ behavior: 'smooth' });
}
}, 100);
}
}, [location.hash]);
return (
<div className="app">
<a href="#main-content" className="skip-link">
{texts.accessibility.skipLinks.skipToHero}
</a>
<Navbar />
<main id="main-content" className="app__main">
<Suspense fallback={<p role="status" className="sr-only">Loading</p>}>
<Routes>
{/* Legacy locale-prefixed URLs → clean URLs */}
<Route path="/de/*" element={<LegacyLanguageRedirect />} />
<Route path="/en/*" element={<LegacyLanguageRedirect />} />
{/* Canonical, language-neutral routes */}
<Route path="/" element={<LandingPage />} />
<Route path="/technical" element={<HomePage />} />
<Route path="/audit" element={<AuditPage />} />
<Route path="/schnellcheck" element={<QuickcheckPage />} />
{/* Shared pages (noindex, language-independent) */}
<Route path="/imprint" element={<ImprintPage />} />
<Route path="/privacy-policy" element={<PrivacyPolicy />} />
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
</Suspense>
</main>
<Footer />
<BackToTopButton />
</div>
);
}
function AppRouter() {
return (
<Router>
<AppShell />
</Router>
);
}
export default AppRouter;