feat: complete agency site build (Phases 1-7)
Full Next.js 16 + Payload CMS 3.x agency site with:
- Homepage: Hero, TrustBar, Services, Configurator wizard, Process,
Selected Works, Philosophy, CTA Banner
- Sub-pages: /services (3 pillars + AI Layer), /work/[slug] (case
studies), /about (philosophy + story)
- Configurator: 3-step wizard with AI brief generation API
- i18n: Full EN/FR bilingual with next-intl
- Design system: Cormorant Garamond + Inter, celestial blue palette,
glassmorphism nav, Framer Motion animations
- Payload CMS collections: Projects, Services, Submissions, Media
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 20:37:38 +01:00
|
|
|
'use client';
|
|
|
|
|
|
|
|
|
|
import { useTranslations } from 'next-intl';
|
|
|
|
|
import { motion } from 'framer-motion';
|
|
|
|
|
import { Calendar, Mail } from 'lucide-react';
|
|
|
|
|
import AnimatedCheckmark from '@/components/icons/AnimatedCheckmark';
|
|
|
|
|
import Button from '@/components/ui/Button';
|
2026-03-25 20:57:09 +01:00
|
|
|
import CalButton from '@/components/ui/CalButton';
|
feat: complete agency site build (Phases 1-7)
Full Next.js 16 + Payload CMS 3.x agency site with:
- Homepage: Hero, TrustBar, Services, Configurator wizard, Process,
Selected Works, Philosophy, CTA Banner
- Sub-pages: /services (3 pillars + AI Layer), /work/[slug] (case
studies), /about (philosophy + story)
- Configurator: 3-step wizard with AI brief generation API
- i18n: Full EN/FR bilingual with next-intl
- Design system: Cormorant Garamond + Inter, celestial blue palette,
glassmorphism nav, Framer Motion animations
- Payload CMS collections: Projects, Services, Submissions, Media
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 20:37:38 +01:00
|
|
|
import type { WizardFormData } from './WizardContainer';
|
|
|
|
|
|
|
|
|
|
// ─── Brief Renderer ───────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
function renderBrief(brief: string) {
|
|
|
|
|
// Split on double newlines for paragraph blocks
|
|
|
|
|
const blocks = brief.split('\n\n').filter(Boolean);
|
|
|
|
|
|
|
|
|
|
return blocks.map((block, blockIdx) => {
|
|
|
|
|
const lines = block.split('\n').filter(Boolean);
|
|
|
|
|
|
|
|
|
|
// Detect a heading block (starts with **)
|
|
|
|
|
const isSectionHeading =
|
|
|
|
|
lines.length === 1 && lines[0].startsWith('**') && lines[0].endsWith('**');
|
|
|
|
|
|
|
|
|
|
if (isSectionHeading) {
|
|
|
|
|
const text = lines[0].replace(/\*\*/g, '');
|
|
|
|
|
// Top heading is larger
|
|
|
|
|
if (blockIdx === 0) {
|
|
|
|
|
return (
|
|
|
|
|
<p key={blockIdx} className="font-semibold text-sm text-on-surface mb-0.5">
|
|
|
|
|
{text}
|
|
|
|
|
</p>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return (
|
|
|
|
|
<p key={blockIdx} className="font-semibold text-xs text-primary-dark uppercase tracking-label mt-4 mb-1">
|
|
|
|
|
{text}
|
|
|
|
|
</p>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Separator line
|
|
|
|
|
if (lines.length === 1 && lines[0] === '---') {
|
|
|
|
|
return <hr key={blockIdx} className="border-outline-variant/30 my-3" />;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Body paragraph — inline bold rendering
|
|
|
|
|
return (
|
|
|
|
|
<div key={blockIdx} className="text-xs text-outline leading-relaxed">
|
|
|
|
|
{lines.map((line, lineIdx) => {
|
|
|
|
|
// Render **bold** inline
|
|
|
|
|
const parts = line.split(/(\*\*[^*]+\*\*)/g);
|
|
|
|
|
return (
|
|
|
|
|
<p key={lineIdx} className={lineIdx > 0 ? 'mt-1' : ''}>
|
|
|
|
|
{parts.map((part, pIdx) =>
|
|
|
|
|
part.startsWith('**') && part.endsWith('**') ? (
|
|
|
|
|
<strong key={pIdx} className="font-semibold text-on-surface">
|
|
|
|
|
{part.slice(2, -2)}
|
|
|
|
|
</strong>
|
|
|
|
|
) : (
|
|
|
|
|
<span key={pIdx}>{part}</span>
|
|
|
|
|
),
|
|
|
|
|
)}
|
|
|
|
|
</p>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ─── Cal.com Embed / Booking ──────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
function BookingSection() {
|
|
|
|
|
return (
|
2026-03-25 20:57:09 +01:00
|
|
|
<div className="rounded-xl bg-surface-low px-5 py-5 text-center">
|
feat: complete agency site build (Phases 1-7)
Full Next.js 16 + Payload CMS 3.x agency site with:
- Homepage: Hero, TrustBar, Services, Configurator wizard, Process,
Selected Works, Philosophy, CTA Banner
- Sub-pages: /services (3 pillars + AI Layer), /work/[slug] (case
studies), /about (philosophy + story)
- Configurator: 3-step wizard with AI brief generation API
- i18n: Full EN/FR bilingual with next-intl
- Design system: Cormorant Garamond + Inter, celestial blue palette,
glassmorphism nav, Framer Motion animations
- Payload CMS collections: Projects, Services, Submissions, Media
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 20:37:38 +01:00
|
|
|
<div className="flex justify-center mb-3">
|
|
|
|
|
<span className="w-10 h-10 rounded-xl bg-primary/10 flex items-center justify-center">
|
|
|
|
|
<Calendar size={18} strokeWidth={1.5} className="text-primary-dark" />
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
<p className="text-sm font-semibold text-on-surface mb-1">Book a Consultation</p>
|
|
|
|
|
<p className="text-xs text-outline mb-4">30 minutes to discuss your brief with our team</p>
|
2026-03-25 20:57:09 +01:00
|
|
|
<CalButton
|
|
|
|
|
className="inline-flex items-center gap-2 px-6 py-2.5 rounded-lg text-sm font-medium text-white transition-all hover:-translate-y-px active:translate-y-0"
|
|
|
|
|
style={{ background: 'linear-gradient(135deg, #006494, #5BA4D9)' }}
|
feat: complete agency site build (Phases 1-7)
Full Next.js 16 + Payload CMS 3.x agency site with:
- Homepage: Hero, TrustBar, Services, Configurator wizard, Process,
Selected Works, Philosophy, CTA Banner
- Sub-pages: /services (3 pillars + AI Layer), /work/[slug] (case
studies), /about (philosophy + story)
- Configurator: 3-step wizard with AI brief generation API
- i18n: Full EN/FR bilingual with next-intl
- Design system: Cormorant Garamond + Inter, celestial blue palette,
glassmorphism nav, Framer Motion animations
- Payload CMS collections: Projects, Services, Submissions, Media
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 20:37:38 +01:00
|
|
|
>
|
2026-03-25 20:57:09 +01:00
|
|
|
<Calendar size={16} />
|
feat: complete agency site build (Phases 1-7)
Full Next.js 16 + Payload CMS 3.x agency site with:
- Homepage: Hero, TrustBar, Services, Configurator wizard, Process,
Selected Works, Philosophy, CTA Banner
- Sub-pages: /services (3 pillars + AI Layer), /work/[slug] (case
studies), /about (philosophy + story)
- Configurator: 3-step wizard with AI brief generation API
- i18n: Full EN/FR bilingual with next-intl
- Design system: Cormorant Garamond + Inter, celestial blue palette,
glassmorphism nav, Framer Motion animations
- Payload CMS collections: Projects, Services, Submissions, Media
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 20:37:38 +01:00
|
|
|
Book a Call
|
2026-03-25 20:57:09 +01:00
|
|
|
</CalButton>
|
feat: complete agency site build (Phases 1-7)
Full Next.js 16 + Payload CMS 3.x agency site with:
- Homepage: Hero, TrustBar, Services, Configurator wizard, Process,
Selected Works, Philosophy, CTA Banner
- Sub-pages: /services (3 pillars + AI Layer), /work/[slug] (case
studies), /about (philosophy + story)
- Configurator: 3-step wizard with AI brief generation API
- i18n: Full EN/FR bilingual with next-intl
- Design system: Cormorant Garamond + Inter, celestial blue palette,
glassmorphism nav, Framer Motion animations
- Payload CMS collections: Projects, Services, Submissions, Media
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 20:37:38 +01:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ─── Main Component ───────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
interface StepCompleteProps {
|
|
|
|
|
formData: WizardFormData;
|
|
|
|
|
brief: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default function StepComplete({ formData, brief }: StepCompleteProps) {
|
|
|
|
|
const t = useTranslations('configurator');
|
|
|
|
|
|
|
|
|
|
const displayEmail = formData.email || 'your inbox';
|
|
|
|
|
|
|
|
|
|
const containerVariants = {
|
|
|
|
|
hidden: {},
|
|
|
|
|
visible: {
|
|
|
|
|
transition: {
|
|
|
|
|
staggerChildren: 0.12,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const itemVariants = {
|
|
|
|
|
hidden: { opacity: 0, y: 20 },
|
|
|
|
|
visible: {
|
|
|
|
|
opacity: 1,
|
|
|
|
|
y: 0,
|
|
|
|
|
transition: { duration: 0.5, ease: [0.16, 1, 0.3, 1] as const },
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<motion.div
|
|
|
|
|
variants={containerVariants}
|
|
|
|
|
initial="hidden"
|
|
|
|
|
animate="visible"
|
|
|
|
|
className="flex flex-col gap-6"
|
|
|
|
|
>
|
|
|
|
|
{/* Checkmark + heading */}
|
|
|
|
|
<motion.div variants={itemVariants} className="flex flex-col items-center text-center pt-2 pb-1">
|
|
|
|
|
<AnimatedCheckmark size={64} color="#006494" />
|
|
|
|
|
|
|
|
|
|
<h3 className="font-serif text-2xl font-semibold tracking-headline text-on-surface mt-4">
|
|
|
|
|
{t('complete.title')}
|
|
|
|
|
</h3>
|
|
|
|
|
|
|
|
|
|
<div className="flex items-center gap-2 mt-2">
|
|
|
|
|
<Mail size={14} strokeWidth={1.5} className="text-primary flex-shrink-0" />
|
|
|
|
|
<p className="text-sm text-outline">
|
|
|
|
|
{t('complete.subtitle', { email: displayEmail })}
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</motion.div>
|
|
|
|
|
|
|
|
|
|
{/* Brief preview */}
|
|
|
|
|
{brief && (
|
|
|
|
|
<motion.div
|
|
|
|
|
variants={itemVariants}
|
|
|
|
|
className="rounded-xl bg-surface-high border border-outline-variant/40 px-5 py-5 shadow-card"
|
|
|
|
|
>
|
|
|
|
|
<p className="text-xs font-semibold uppercase tracking-label text-outline mb-3">
|
|
|
|
|
Your project brief
|
|
|
|
|
</p>
|
|
|
|
|
<div className="space-y-1 max-h-72 overflow-y-auto pr-1 scrollbar-thin">
|
|
|
|
|
{renderBrief(brief)}
|
|
|
|
|
</div>
|
|
|
|
|
</motion.div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{/* Booking */}
|
|
|
|
|
<motion.div variants={itemVariants}>
|
|
|
|
|
<p className="text-xs font-semibold uppercase tracking-label text-outline mb-3">
|
|
|
|
|
{t('complete.bookTitle')}
|
|
|
|
|
</p>
|
|
|
|
|
<BookingSection />
|
|
|
|
|
</motion.div>
|
|
|
|
|
|
|
|
|
|
{/* Fallback contact */}
|
|
|
|
|
<motion.div variants={itemVariants}>
|
|
|
|
|
<p className="text-center text-xs text-outline">
|
|
|
|
|
Or reach us directly at{' '}
|
|
|
|
|
<a
|
|
|
|
|
href="mailto:hello@letsbe.biz"
|
|
|
|
|
className="text-primary-dark underline underline-offset-2 hover:text-primary transition-colors"
|
|
|
|
|
>
|
|
|
|
|
hello@letsbe.biz
|
|
|
|
|
</a>
|
|
|
|
|
</p>
|
|
|
|
|
</motion.div>
|
|
|
|
|
</motion.div>
|
|
|
|
|
);
|
|
|
|
|
}
|