mirror of
https://github.com/complexcaresolutions/frontend.sensualmoment.de.git
synced 2026-03-17 15:03:54 +00:00
- Project foundation: Next.js 16, Tailwind v4, Google Fonts, payload-contracts - Shared components: Navigation (scroll effect), Footer (Deep Navy), Logo (wordmark), ScrollReveal - Homepage: Hero, AboutPreview, GalleryPreview, Testimonials, Packages, BlogPreview, Contact - Inner pages: ueber-mich, galerie, pakete, journal, journal/[slug], kontakt, faq, impressum, datenschutz, agb - CMS API client (src/lib/api.ts) with tenant-scoped fetch helpers - server.js for Plesk Passenger deployment - Color palette: Dark Wine, Blush, Bordeaux, Deep Navy, Creme, Espresso - Fonts: Playfair Display (headlines), Cormorant Garamond (body), Josefin Sans (UI) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
115 lines
3.1 KiB
TypeScript
115 lines
3.1 KiB
TypeScript
const CMS_URL = process.env.NEXT_PUBLIC_CMS_URL || "https://pl.porwoll.tech"
|
|
const TENANT_ID = process.env.NEXT_PUBLIC_TENANT_ID || "13"
|
|
|
|
interface FetchOptions {
|
|
collection: string
|
|
where?: Record<string, unknown>
|
|
limit?: number
|
|
page?: number
|
|
sort?: string
|
|
depth?: number
|
|
locale?: string
|
|
}
|
|
|
|
export async function fetchFromCMS<T = unknown>({
|
|
collection,
|
|
where = {},
|
|
limit = 100,
|
|
page = 1,
|
|
sort,
|
|
depth = 1,
|
|
locale = "de",
|
|
}: FetchOptions): Promise<{ docs: T[]; totalDocs: number; totalPages: number }> {
|
|
const params = new URLSearchParams()
|
|
params.set("where[tenant][equals]", TENANT_ID)
|
|
params.set("limit", String(limit))
|
|
params.set("page", String(page))
|
|
params.set("depth", String(depth))
|
|
params.set("locale", locale)
|
|
if (sort) params.set("sort", sort)
|
|
|
|
for (const [key, value] of Object.entries(where)) {
|
|
if (typeof value === "object" && value !== null) {
|
|
for (const [op, val] of Object.entries(value as Record<string, unknown>)) {
|
|
params.set("where[" + key + "][" + op + "]", String(val))
|
|
}
|
|
} else {
|
|
params.set("where[" + key + "][equals]", String(value))
|
|
}
|
|
}
|
|
|
|
const url = CMS_URL + "/api/" + collection + "?" + params.toString()
|
|
const res = await fetch(url, { next: { revalidate: 60 } })
|
|
|
|
if (!res.ok) {
|
|
console.error("CMS fetch failed:", url, res.status)
|
|
return { docs: [], totalDocs: 0, totalPages: 0 }
|
|
}
|
|
|
|
return res.json()
|
|
}
|
|
|
|
export async function fetchPage(slug: string) {
|
|
const { docs } = await fetchFromCMS<{ id: number; title: string; layout: unknown[]; slug: string }>({
|
|
collection: "pages",
|
|
where: { slug: { equals: slug } },
|
|
depth: 2,
|
|
})
|
|
return docs[0] || null
|
|
}
|
|
|
|
export async function fetchNavigation() {
|
|
const { docs } = await fetchFromCMS<{ mainMenu: unknown[]; footerMenu: unknown[] }>({
|
|
collection: "navigations",
|
|
depth: 2,
|
|
})
|
|
return docs[0] || null
|
|
}
|
|
|
|
export async function fetchSiteSettings() {
|
|
const { docs } = await fetchFromCMS<Record<string, unknown>>({
|
|
collection: "site-settings",
|
|
depth: 1,
|
|
})
|
|
return docs[0] || null
|
|
}
|
|
|
|
export async function fetchTestimonials() {
|
|
const { docs } = await fetchFromCMS<{ quote: string; author: string; role?: string }>({
|
|
collection: "testimonials",
|
|
where: { isActive: { equals: true } },
|
|
sort: "order",
|
|
})
|
|
return docs
|
|
}
|
|
|
|
export async function fetchFAQs(category?: string) {
|
|
const where: Record<string, unknown> = {}
|
|
if (category) where.category = { equals: category }
|
|
const { docs } = await fetchFromCMS<{ question: string; answer: unknown; category: string }>({
|
|
collection: "faqs",
|
|
where,
|
|
sort: "order",
|
|
limit: 50,
|
|
})
|
|
return docs
|
|
}
|
|
|
|
export async function fetchSocialLinks() {
|
|
const { docs } = await fetchFromCMS<{ platform: string; url: string; label?: string }>({
|
|
collection: "social-links",
|
|
sort: "order",
|
|
})
|
|
return docs
|
|
}
|
|
|
|
export async function fetchPosts(limit = 3) {
|
|
const { docs } = await fetchFromCMS<{ title: string; slug: string; excerpt?: string; coverImage?: unknown; publishedAt?: string }>({
|
|
collection: "posts",
|
|
where: { status: { equals: "published" } },
|
|
sort: "-publishedAt",
|
|
limit,
|
|
depth: 2,
|
|
})
|
|
return docs
|
|
}
|