Files
obc-terrassement/lib/content.ts
Claude 15c60a274c feat: préparation Payload CMS — couche d'abstraction contenu
Sépare données et affichage pour basculer vers Payload CMS sans réécrire les composants.

Nouveaux fichiers :
- lib/site-config.ts : source unique de vérité pour toutes les données du site (as const)
- lib/content.ts : couche async entre données et composants (static aujourd'hui, Payload demain)
- types/content.ts : types TypeScript partagés (Service, Realisation, Partner, BlogPost, etc.)
- payload/ : schémas CollectionConfig et GlobalConfig commentés prêts à activer

Données enrichies dans siteConfig :
- partners : ajout du champ desc pour chaque partenaire
- realisations : 6 entrées complètes avec categorie et color
- blogPosts : 6 articles avec slug, titre, extrait, cat, date, readTime

Refactorisations (composants → content layer) :
- Navbar, Footer : importent siteConfig directement (client component)
- app/page.tsx : async, Promise.all sur getServices/getTestimonials/getFAQ/getValues/getPartners/getRealisations
- app/services/page.tsx : getServices() + getSiteConfig()
- app/contact/page.tsx : getSiteConfig() pour phone, email, address, zones
- app/realisations/page.tsx : getRealisations() + getSiteConfig()
- app/partenaires/page.tsx : getPartners()
- app/blog/page.tsx : getBlogPosts()
- app/blog/[slug]/page.tsx : getBlogPost() + getBlogPosts() pour generateStaticParams
- LocalSEOPage.tsx : siteConfig pour services list, phone, address
- 5 pages service (construction-maison, renovation, assainissement, creation-acces, demolition) : getSiteConfig() pour phone
- Pages légales et SEO locales : siteConfig importé pour données dynamiques

Corrections URL :
- Toutes les URLs canoniques obc-maconnerie.fr → obc-terrassement.fr (30+ fichiers)
- layout.tsx : BASE_URL depuis siteConfig.url
- robots.ts, sitemap.ts : BASE_URL depuis siteConfig.url
- api/contact/route.ts : email fallback → obc-terrassement.fr

https://claude.ai/code/session_01Uec4iHjcPwB1pU41idWEdF
2026-02-27 13:05:19 +00:00

86 lines
4.3 KiB
TypeScript

// lib/content.ts
// Couche d'abstraction entre les données et les composants.
//
// AUJOURD'HUI : lit siteConfig (données statiques en JSON)
// DEMAIN : remplacer chaque return par un appel Payload CMS
// Les composants n'ont JAMAIS à changer.
//
// Exemple de migration future :
// - return siteConfig.services
// + return await payload.find({ collection: 'services' }).then(r => r.docs)
import { siteConfig } from "./site-config";
import type {
Service,
Realisation,
Testimonial,
FAQItem,
BlogPost,
Partner,
NavItem,
} from "@/types/content";
// ── Navigation ────────────────────────────────────────────────
export async function getNavItems(): Promise<NavItem[]> {
// FUTURE: return await payload.findGlobal({ slug: 'navigation' })
return [...siteConfig.nav];
}
// ── Config globale ────────────────────────────────────────────
export async function getSiteConfig() {
// FUTURE: return await payload.findGlobal({ slug: 'site-settings' })
return siteConfig;
}
// ── Services ──────────────────────────────────────────────────
export async function getServices(): Promise<Service[]> {
// FUTURE: return await payload.find({ collection: 'services', sort: 'order' }).then(r => r.docs)
return [...siteConfig.services];
}
export async function getServiceBySlug(slug: string): Promise<Service | null> {
// FUTURE: return await payload.find({ collection: 'services', where: { slug: { equals: slug } } }).then(r => r.docs[0] ?? null)
return siteConfig.services.find((s) => s.slug === slug) ?? null;
}
// ── Réalisations ──────────────────────────────────────────────
export async function getRealisations(): Promise<Realisation[]> {
// FUTURE: return await payload.find({ collection: 'realisations', sort: '-publishedAt' }).then(r => r.docs)
return [...siteConfig.realisations];
}
// ── Témoignages ───────────────────────────────────────────────
export async function getTestimonials(): Promise<Testimonial[]> {
// FUTURE: return await payload.find({ collection: 'testimonials', where: { featured: { equals: true } } }).then(r => r.docs)
return [...siteConfig.testimonials];
}
// ── FAQ ───────────────────────────────────────────────────────
export async function getFAQ(): Promise<FAQItem[]> {
// FUTURE: return await payload.find({ collection: 'faq', sort: 'order' }).then(r => r.docs)
return [...siteConfig.faq];
}
// ── Partenaires ───────────────────────────────────────────────
export async function getPartners(): Promise<Partner[]> {
// FUTURE: return await payload.find({ collection: 'partners', sort: 'order' }).then(r => r.docs)
return [...siteConfig.partners];
}
// ── Blog ──────────────────────────────────────────────────────
export async function getBlogPosts(): Promise<BlogPost[]> {
// FUTURE: return await payload.find({ collection: 'articles', where: { status: { equals: 'published' } }, sort: '-publishedAt' }).then(r => r.docs)
return [...siteConfig.blogPosts];
}
export async function getBlogPost(slug: string): Promise<BlogPost | null> {
// FUTURE: return await payload.find({ collection: 'articles', where: { slug: { equals: slug } } }).then(r => r.docs[0] ?? null)
return siteConfig.blogPosts.find((p) => p.slug === slug) ?? null;
}
// ── Valeurs / Piliers ─────────────────────────────────────────
export async function getValues() {
// FUTURE: return await payload.find({ collection: 'values', sort: 'order' }).then(r => r.docs)
return [...siteConfig.values];
}