Files
ndsolutionswebsite/src/pages/[...slug].astro
Daniel S baa639a9b2
Some checks failed
Production Build & Deploy / build-and-deploy (push) Has been cancelled
feat(admin): add demo mode toggle in admin dashboard and rewrite 404 page for missing routes
2026-08-09 22:43:36 +02:00

118 lines
3.9 KiB
Plaintext

---
// src/pages/[...slug].astro
import Layout from '../layouts/Layout.astro';
import { loadWaasConfigs } from '../utils/configLoader';
import { resolveDynamicBinding } from '../utils/dynamicDataBinding';
// Component Registry Import (Zero-Sumpf & Modular)
import HeroSection from '../components/sections/HeroSection.astro';
import BentoGrid from '../components/sections/BentoGrid.astro';
import ContactSection from '../components/sections/ContactSection.astro';
import FallbackSection from '../components/sections/FallbackSection.astro';
// Strikter SSR-Modus für Instant-Updates ohne Re-Build
export const prerender = false;
// 1. Slug aus der URL auslesen
const { slug } = Astro.params;
// 2. Config aus /app/data/site.config.json oder site.config.draft.json laden
const userAgent = Astro.request.headers.get('user-agent') ?? '';
const isDraft = Astro.url.searchParams.get('preview') === 'draft';
const { siteConfig } = loadWaasConfigs(userAgent, isDraft);
// Helper function to resolve dynamic data recursively in settings or objects
function resolveDynamicData(settings: any, dynamicBindings: any, config: any): any {
if (!settings) return settings;
const context = { site: config, ...config };
if (typeof settings === 'string') {
return resolveDynamicBinding(settings, context);
}
if (Array.isArray(settings)) {
return settings.map((item) => resolveDynamicData(item, dynamicBindings, config));
}
if (typeof settings === 'object') {
const resolved: Record<string, any> = {};
for (const [key, value] of Object.entries(settings)) {
resolved[key] = resolveDynamicData(value, dynamicBindings, config);
}
return resolved;
}
return settings;
}
// 3. Normalized Slug-Handling: "/" für Startseite, sonst z.B. "leistungen"
const currentSlug = slug === undefined || slug === '' ? '/' : slug.replace(/\/$/, '');
// 4. Richtige Seite im pages-Array ermitteln (falls vorhanden, sonst Fallback auf Hauptkonfiguration)
const pages = (siteConfig as any).pages || [
{
id: (siteConfig as any).homepage_id || 'home',
slug: '/',
title: siteConfig.siteName,
is_published: true,
sections: siteConfig.sectionsOrder.map((secType: string) => ({
id: secType,
type: secType,
settings: (siteConfig as any)[secType] || {}
}))
}
];
let page = pages.find((p: any) => {
if (currentSlug === '/') {
// Startseiten-Mapping über homepage_id oder Slug "/"
return p.id === (siteConfig as any).homepage_id || p.slug === '/' || p.slug === '';
}
return p.slug === currentSlug || p.slug === `/${currentSlug}`;
});
// 5. Zero-Crash Fallback Guard: Wenn Seite nicht existiert oder nicht veröffentlicht ist -> 404 Status
if (!page || (page.is_published === false && !isDraft)) {
Astro.response.status = 404;
return Astro.rewrite('/404');
}
// 6. Dynamic Component Registry Mapping
const ComponentRegistry: Record<string, any> = {
hero: HeroSection,
bento: BentoGrid,
contact: ContactSection,
HeroSection,
BentoGrid,
ContactSection
};
---
<Layout
title={page.title || siteConfig.siteName || 'N&D IT Solutions'}
description={page.seo?.description || siteConfig.metaDescription || ''}
ogImage={page.seo?.og_image || ''}
>
<main id="main-content" role="main" class="min-h-screen">
{
page.sections && page.sections.length > 0 ? (
page.sections.map((section: any) => {
const Component = ComponentRegistry[section.type] || FallbackSection;
// Löse Platzhalter & DB-Bindings aus /admin/ live auf
const resolvedSettings = resolveDynamicData(
section.settings || {},
section.dynamic_bindings || {},
siteConfig
);
return <Component id={section.id} settings={resolvedSettings} {...resolvedSettings} />;
})
) : (
<FallbackSection message="Diese Seite enthält aktuell noch keine Abschnitte." />
)
}
</main>
</Layout>