294 lines
9.1 KiB
TypeScript
294 lines
9.1 KiB
TypeScript
import fs from 'fs';
|
||
import path from 'path';
|
||
import { detectDeviceType } from './deviceDetect';
|
||
export interface UIComponent {
|
||
id: string; // Eindeutige ID (z.B. uuid / timestamp)
|
||
slotId: string; // Platz-ID (z.B. 'hero-badge-slot', 'hero-actions-slot', 'bento-slot-1')
|
||
orderIndex?: number; // Position / Reihenfolge auf dem Platz
|
||
type: 'button' | 'badge' | 'text' | 'card' | 'accordion' | 'stat-box' | 'testimonial' | 'cta-box';
|
||
content: string;
|
||
link?: string;
|
||
animation0?: string; // e.g. 'spring-fade', 'hover-bounce', 'pulse-glow'
|
||
style?: 'primary' | 'secondary' | 'outline' | 'glass';
|
||
}
|
||
|
||
export interface SectionConfig {
|
||
id: string;
|
||
type: 'hero' | 'bento' | 'contact' | 'custom';
|
||
title?: string;
|
||
subtitle?: string;
|
||
badge?: string;
|
||
animation?: string;
|
||
elements?: UIComponent[];
|
||
}
|
||
|
||
export interface SiteConfig {
|
||
siteName: string;
|
||
metaDescription: string;
|
||
header?: {
|
||
brandName?: string;
|
||
brandHighlight?: string;
|
||
ctaText?: string;
|
||
ctaLink?: string;
|
||
showThemeToggle?: boolean;
|
||
glassEffect?: boolean;
|
||
};
|
||
footer?: {
|
||
brandDescription?: string;
|
||
copyrightText?: string;
|
||
showLegalLinks?: boolean;
|
||
};
|
||
hero: {
|
||
badge: string;
|
||
title: string;
|
||
subtitle: string;
|
||
ctaPrimaryText: string;
|
||
ctaPrimaryLink: string;
|
||
ctaSecondaryText: string;
|
||
ctaSecondaryLink: string;
|
||
animation?: string;
|
||
elements?: UIComponent[];
|
||
};
|
||
bento: {
|
||
sectionTitle: string;
|
||
sectionSubtitle: string;
|
||
animation?: string;
|
||
cards: Array<{
|
||
id: string;
|
||
title: string;
|
||
description: string;
|
||
colSpan?: number;
|
||
badge?: string;
|
||
icon?: string;
|
||
animation?: string;
|
||
}>;
|
||
};
|
||
contact: {
|
||
title: string;
|
||
subtitle: string;
|
||
recipientEmail: string;
|
||
phone?: string;
|
||
address?: string;
|
||
};
|
||
sectionsOrder: string[];
|
||
sectionsDetails?: SectionConfig[];
|
||
}
|
||
|
||
export interface ThemeConfig {
|
||
activePreset: string;
|
||
glassBlur?: string; // 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'
|
||
glassOpacity?: number; // 0.1 to 0.9
|
||
glassBorderRadius?: string; // 'rounded-lg' | 'rounded-xl' | 'rounded-2xl'
|
||
customColors?: {
|
||
bg?: string;
|
||
accent?: string;
|
||
};
|
||
}
|
||
|
||
export interface SmtpConfig {
|
||
host: string;
|
||
port: number;
|
||
secure: boolean;
|
||
user: string;
|
||
pass: string;
|
||
fromName: string;
|
||
fromEmail: string;
|
||
isConfigured: boolean;
|
||
}
|
||
|
||
export const FALLBACK_SITE_CONFIG: SiteConfig = {
|
||
siteName: 'N&D IT Solutions',
|
||
metaDescription: 'High-Performance Webdesign & Digital Solutions - 100% DSGVO-konform.',
|
||
header: {
|
||
brandName: 'N&D',
|
||
brandHighlight: 'i-t SOLUTIONS',
|
||
ctaText: 'Erstgespräch buchen',
|
||
ctaLink: '#contact',
|
||
showThemeToggle: true,
|
||
glassEffect: true
|
||
},
|
||
footer: {
|
||
brandDescription: 'Ihr Partner für professionelles Webdesign, Website-Entwicklung und lokale SEO für Kleinbetriebe & KMU.',
|
||
copyrightText: 'N&D i-t SOLUTIONS. Alle Rechte vorbehalten.',
|
||
showLegalLinks: true
|
||
},
|
||
hero: {
|
||
badge: ' Waas Enterprise Baukastensystem',
|
||
title: 'Maßgeschneiderte Webseiten. Digital im Griff.',
|
||
subtitle: 'Wir entwickeln blitzschnelle, DSGVO-konforme High-End Webseiten für Ihr Unternehmen zum monatlichen Festpreis – inklusive Wartung & Hosting.',
|
||
ctaPrimaryText: 'Projekt anfragen',
|
||
ctaPrimaryLink: '#contact',
|
||
ctaSecondaryText: 'Mehr erfahren',
|
||
ctaSecondaryLink: '#services',
|
||
elements: [
|
||
{ id: 'el-1', slotId: 'hero-badge-slot', type: 'badge', content: 'WaaS Engine' },
|
||
{ id: 'el-2', slotId: 'hero-actions-slot', type: 'button', content: 'Neuer Button', link: '#contact', animation0: 'spring-fade', style: 'primary' }
|
||
]
|
||
},
|
||
bento: {
|
||
sectionTitle: 'High-End Features & Leistung',
|
||
sectionSubtitle: 'Modernste Technologie & Höchster Datenschutz vereint.',
|
||
cards: [
|
||
{
|
||
id: 'card-1',
|
||
title: 'Ultra Fast SSR',
|
||
description: 'Sub-100ms Ladezeiten dank Astro Hybrid SSR Architecture. Google Core Web Vitals > 95%.',
|
||
colSpan: 2,
|
||
badge: 'Performance',
|
||
icon: 'zap'
|
||
},
|
||
{
|
||
id: 'card-2',
|
||
title: '100% DSGVO-Sicher',
|
||
description: 'Keine Cookies, keine Tracking-Skripte, Zero Third-Party Requests.',
|
||
colSpan: 1,
|
||
badge: 'Datenschutz',
|
||
icon: 'shield'
|
||
},
|
||
{
|
||
id: 'card-3',
|
||
title: 'Liquid Glass UI',
|
||
description: 'Moderne Ästhetik mit matte Boxen, Aurora Glows und physikalischen Kanten-Effekten.',
|
||
colSpan: 1,
|
||
badge: 'Design',
|
||
icon: 'layers'
|
||
},
|
||
{
|
||
id: 'card-4',
|
||
title: 'Sorgenfrei-Paket',
|
||
description: 'Hosting, SSL, Wartung und regelmäßige Inhalts-Updates komplett inklusive.',
|
||
colSpan: 2,
|
||
badge: 'Full-Service',
|
||
icon: 'check'
|
||
}
|
||
]
|
||
},
|
||
contact: {
|
||
title: 'Bereit für Ihr Projekt?',
|
||
subtitle: 'Schreiben Sie uns direkt. Wir antworten innerhalb von 24 Stunden persönlich.',
|
||
recipientEmail: 'kontakt@ndsolutions.de',
|
||
phone: '+49 (0) 123 456789',
|
||
address: 'Deutschland'
|
||
},
|
||
sectionsOrder: ['hero', 'bento', 'contact'],
|
||
sectionsDetails: [
|
||
{ id: 'hero', type: 'hero', title: 'Hero Sektion', elements: [ { id: 'el-1', slotId: 'hero-badge-slot', type: 'badge', content: 'WaaS Engine' } ] },
|
||
{ id: 'bento', type: 'bento', title: 'Bento Grid', elements: [] },
|
||
{ id: 'contact', type: 'contact', title: 'Contact Section', elements: [] }
|
||
],
|
||
site_info: {
|
||
title: 'N&D IT Solutions',
|
||
homepage_id: 'page_home'
|
||
},
|
||
pages: [
|
||
{
|
||
id: 'page_home',
|
||
slug: '/',
|
||
title: 'Startseite (Hauptseite)',
|
||
is_published: true,
|
||
sections: [
|
||
{ id: 'hero', type: 'HeroSection', settings: {} },
|
||
{ id: 'bento', type: 'BentoGrid', settings: {} },
|
||
{ id: 'contact', type: 'ContactSection', settings: {} }
|
||
]
|
||
},
|
||
{
|
||
id: 'page_templates',
|
||
slug: '/templates',
|
||
title: 'Templates & Design-Muster',
|
||
is_published: true,
|
||
sections: [
|
||
{ id: 'hero_templates', type: 'HeroSection', settings: { title: 'Templates', subtitle: 'Unsere fertigen Design-Vorlagen' } }
|
||
]
|
||
},
|
||
{
|
||
id: 'page_privacy',
|
||
slug: '/datenschutz',
|
||
title: 'Datenschutzerklärung',
|
||
is_published: true,
|
||
sections: [
|
||
{ id: 'privacy_content', type: 'HeroSection', settings: { title: 'Datenschutz', subtitle: '100% DSGVO-konforme Datenverarbeitung.' } }
|
||
]
|
||
}
|
||
]
|
||
};
|
||
|
||
|
||
export const FALLBACK_THEME_CONFIG: ThemeConfig = {
|
||
activePreset: 'corporateDark'
|
||
};
|
||
|
||
export const FALLBACK_SMTP_CONFIG: SmtpConfig = {
|
||
host: 'smtp.placeholder.local',
|
||
port: 587,
|
||
secure: false,
|
||
user: 'placeholder@domain.de',
|
||
pass: '****',
|
||
fromName: 'N&D IT Solutions System',
|
||
fromEmail: 'noreply@ndsolutions.de',
|
||
isConfigured: false
|
||
};
|
||
|
||
function readJsonFile<T>(filePath: string, fallback: T): T {
|
||
try {
|
||
if (!fs.existsSync(filePath)) {
|
||
return fallback;
|
||
}
|
||
const content = fs.readFileSync(filePath, 'utf-8');
|
||
if (!content.trim()) {
|
||
return fallback;
|
||
}
|
||
const parsed = JSON.parse(content);
|
||
return { ...fallback, ...parsed };
|
||
} catch (error) {
|
||
console.warn(`[WaaS ConfigLoader] Warning loading ${filePath}, using fallback defaults.`, error);
|
||
return fallback;
|
||
}
|
||
}
|
||
|
||
export function loadWaasConfigs(userAgent: string = '', isDraft: boolean = false) {
|
||
const dataDir = process.env.DATA_DIR || path.join(process.cwd(), 'app', 'data');
|
||
const device = detectDeviceType(userAgent);
|
||
|
||
const draftSitePath = path.join(dataDir, 'site.config.draft.json');
|
||
const deviceSitePath = path.join(dataDir, `site.${device}.config.json`);
|
||
const genericSitePath = path.join(dataDir, 'site.config.json');
|
||
|
||
let sitePath = genericSitePath;
|
||
if (isDraft && fs.existsSync(draftSitePath)) {
|
||
sitePath = draftSitePath;
|
||
} else if (fs.existsSync(deviceSitePath)) {
|
||
sitePath = deviceSitePath;
|
||
}
|
||
|
||
const deviceThemePath = path.join(dataDir, `theme.${device}.config.json`);
|
||
const genericThemePath = path.join(dataDir, 'theme.config.json');
|
||
const themePath = fs.existsSync(deviceThemePath) ? deviceThemePath : genericThemePath;
|
||
|
||
const deviceSmtpPath = path.join(dataDir, `smtp.${device}.config.json`);
|
||
const genericSmtpPath = path.join(dataDir, 'smtp.config.json');
|
||
const smtpPath = fs.existsSync(deviceSmtpPath) ? deviceSmtpPath : genericSmtpPath;
|
||
|
||
const rawSite = readJsonFile<Partial<SiteConfig>>(sitePath, FALLBACK_SITE_CONFIG);
|
||
const siteConfig: SiteConfig = {
|
||
...FALLBACK_SITE_CONFIG,
|
||
...rawSite,
|
||
hero: { ...FALLBACK_SITE_CONFIG.hero, ...(rawSite.hero || {}) },
|
||
bento: { ...FALLBACK_SITE_CONFIG.bento, ...(rawSite.bento || {}) },
|
||
contact: { ...FALLBACK_SITE_CONFIG.contact, ...(rawSite.contact || {}) },
|
||
pages: (rawSite as any).pages && (rawSite as any).pages.length > 0 ? (rawSite as any).pages : (FALLBACK_SITE_CONFIG as any).pages,
|
||
site_info: { ...(FALLBACK_SITE_CONFIG as any).site_info, ...((rawSite as any).site_info || {}) }
|
||
};
|
||
|
||
|
||
const themeConfig = readJsonFile<ThemeConfig>(themePath, FALLBACK_THEME_CONFIG);
|
||
const smtpConfig = readJsonFile<SmtpConfig>(smtpPath, FALLBACK_SMTP_CONFIG);
|
||
|
||
return { siteConfig, themeConfig, smtpConfig };
|
||
}
|
||
|
||
export function getSiteConfig(isDraft: boolean = false) {
|
||
return loadWaasConfigs('', isDraft).siteConfig;
|
||
}
|
||
|