diff --git a/src/app/(frontend)/[locale]/work/[slug]/page.tsx b/src/app/(frontend)/[locale]/work/[slug]/page.tsx index 7fb350d..9ded2be 100644 --- a/src/app/(frontend)/[locale]/work/[slug]/page.tsx +++ b/src/app/(frontend)/[locale]/work/[slug]/page.tsx @@ -6,69 +6,38 @@ import { routing } from '@/i18n/routing'; import ScrollReveal from '@/components/ui/ScrollReveal'; import Button from '@/components/ui/Button'; import CornerBracket from '@/components/icons/CornerBracket'; -import Chip from '@/components/ui/Chip'; const BASE_URL = 'https://letsbe.biz'; // ─── Types ──────────────────────────────────────────────────────────────────── interface Project { - title: string; - subtitle: string; - description: string; - challenge: string; - approach: string; - outcome: string; - techStack: string[]; - tags: string[]; image: string; + techStack: string[]; +} + +// ─── Slug-to-work-key mapping ───────────────────────────────────────────────── + +const SLUG_TO_KEY: Record = { + 'monaco-ocean': 'monaco', + 'port-nimara': 'portNimara', + 'port-amador': 'portAmador', } // ─── Data (will come from Payload CMS) ──────────────────────────────────────── const PROJECTS: Record = { 'monaco-ocean': { - title: 'Monaco Ocean Protection Challenge', - subtitle: 'AI-Powered Judging & Analytics Platform', - description: - "A comprehensive judging and analytics system with advanced AI jury integration for one of the Mediterranean's most prestigious conservation events.", - challenge: - 'The Monaco Ocean Protection Challenge needed a modern platform to manage submissions, coordinate judges across time zones, and provide AI-assisted evaluation of conservation proposals — all while maintaining the prestige and security expected of a Monaco institution.', - approach: - 'We built a custom platform from the ground up using Next.js and a private PostgreSQL infrastructure. The AI jury module uses natural language processing to pre-screen submissions and generate summary reports, while human judges retain full control over final decisions.', - outcome: - "The platform processed over 200 submissions in its first season, reducing judge workload by 40% through AI-assisted pre-screening. The client praised the system's reliability and the elegance of its interface.", - techStack: ['Next.js', 'PostgreSQL', 'OpenAI API', 'Docker', 'Private Cloud'], - tags: ['AI Integration', 'Platform'], image: '/images/monaco_high_res.jpg', + techStack: ['Next.js', 'PostgreSQL', 'OpenAI API', 'Docker', 'Private Cloud'], }, 'port-nimara': { - title: 'Port Nimara', - subtitle: 'Maritime Digital Hub', - description: 'Scalable digital hub for maritime logistics.', - challenge: - 'Port Nimara needed a modern digital presence that could serve as both a marketing website and an operational hub for berth inquiries, event management, and partner communications.', - approach: - 'We designed and developed a performant Nuxt.js application with a headless CMS for content management, integrated with their existing maritime scheduling systems via custom API middleware.', - outcome: - 'The new platform increased online berth inquiries by 3x and provided the port authority with real-time content management capabilities they previously lacked.', - techStack: ['Nuxt.js', 'Directus CMS', 'Node.js', 'Docker'], - tags: ['Website', 'Infrastructure'], image: '/images/anguilla.png', + techStack: ['Nuxt.js', 'Directus CMS', 'Node.js', 'Docker'], }, 'port-amador': { - title: 'Port Amador', - subtitle: 'Premium Nautical Experience', - description: 'Premium digital experience for elite nautical services.', - challenge: - 'Port Amador required a luxury-grade digital experience that matched the exclusivity of their nautical services, with multi-language support and seamless booking integration.', - approach: - 'We crafted a bespoke website with cinematic imagery, smooth animations, and an integrated booking flow. The site was built on modern web technologies with a focus on performance and SEO for the competitive luxury maritime market.', - outcome: - "The redesigned platform elevated Port Amador's digital presence to match their premium positioning, with a 60% improvement in page load times and significantly increased organic traffic.", - techStack: ['Next.js', 'Tailwind CSS', 'Framer Motion', 'Vercel'], - tags: ['Website', 'Infrastructure'], image: '/images/panama.png', + techStack: ['Next.js', 'Tailwind CSS', 'Framer Motion', 'Vercel'], }, }; @@ -83,6 +52,9 @@ export async function generateMetadata({ params }: PageProps): Promise const project = PROJECTS[slug]; if (!project) return {}; + const workKey = SLUG_TO_KEY[slug]; + if (!workKey) return {}; + const t = await getTranslations({ locale, namespace: 'meta.work' }); const path = locale === 'en' ? `/work/${slug}` : `/${locale}/work/${slug}`; @@ -161,12 +133,28 @@ export default async function CaseStudyPage({ params }: Props) { const project = PROJECTS[slug]; if (!project) notFound(); + const workKey = SLUG_TO_KEY[slug]; + if (!workKey) notFound(); + + const t = await getTranslations({ locale, namespace: 'caseStudy' }); + const tw = await getTranslations({ locale, namespace: 'work' }); + + // Get translated content + const title = tw(`projects.${workKey}.title`) + const tags = tw.raw(`projects.${workKey}.tags`) as string[] + const subtitle = t(`projects.${slug}.subtitle`) + const description = t(`projects.${slug}.description`) + const challenge = t(`projects.${slug}.challenge`) + const approach = t(`projects.${slug}.approach`) + const outcome = t(`projects.${slug}.outcome`) + const caseStudyJsonLd = { '@context': 'https://schema.org', '@type': 'CreativeWork', - name: project.title, - description: project.description, + name: title, + description: description, image: `${BASE_URL}${project.image}`, + inLanguage: locale, creator: { '@type': 'Organization', name: 'LetsBe.', @@ -201,7 +189,7 @@ export default async function CaseStudyPage({ params }: Props) { {/* Tags */}
- {project.tags.map((tag) => ( + {tags.map((tag) => (

- {project.title} + {title}

{/* Subtitle */}

- {project.subtitle} + {subtitle}

{/* Description */}

- {project.description} + {description}

@@ -256,10 +244,10 @@ export default async function CaseStudyPage({ params }: Props) {
{/* Divider */} @@ -275,10 +263,10 @@ export default async function CaseStudyPage({ params }: Props) { {/* Divider */} @@ -294,10 +282,10 @@ export default async function CaseStudyPage({ params }: Props) {
@@ -311,7 +299,7 @@ export default async function CaseStudyPage({ params }: Props) {
-

Built with

+

{t('labels.builtWith')}

{project.techStack.map((tech) => (
-

Your Turn

+

{t('labels.yourTurn')}

- Ready to build something like this? + {t('labels.ctaTitle')}

- Every project starts with a conversation. Tell us what you’re working on and - we’ll figure out the best way to bring it to life. + {t('labels.ctaSubtitle')}