diff --git a/src/app/(frontend)/api/configure/route.ts b/src/app/(frontend)/api/configure/route.ts index df85e97..2e70fbe 100644 --- a/src/app/(frontend)/api/configure/route.ts +++ b/src/app/(frontend)/api/configure/route.ts @@ -84,7 +84,7 @@ async function generateBriefWithAI(body: ConfigureRequestBody): Promise const context = buildContext(body); const displayName = body.name.split(' ')[0] || body.name; - const systemPrompt = `You are writing a project brief on behalf of LetsBe Solutions, a digital studio that builds custom websites, custom software, and private digital infrastructure. The company is American-founded and serves businesses on the Côte d'Azur and internationally. + const systemPrompt = `You are writing a project brief on behalf of LetsBe Solutions, a digital studio that builds custom websites, custom software, and private digital infrastructure. The company is American-founded and serves clients internationally. Key facts about LetsBe: - Every project is designed and coded from scratch — no templates, no page builders diff --git a/src/components/configurator/ProgressBar.tsx b/src/components/configurator/ProgressBar.tsx index 86295d8..a5afa1f 100644 --- a/src/components/configurator/ProgressBar.tsx +++ b/src/components/configurator/ProgressBar.tsx @@ -2,6 +2,7 @@ import { motion } from 'framer-motion'; import { cn } from '@/lib/utils'; +import { Check } from 'lucide-react'; interface ProgressBarProps { currentStep: 1 | 2 | 3; @@ -9,31 +10,68 @@ interface ProgressBarProps { className?: string; } +const STEP_LABELS = ['01', '02', '03']; + export default function ProgressBar({ currentStep, className }: ProgressBarProps) { return ( -
- {([1, 2, 3] as const).map((step) => { - const isActive = step <= currentStep; - return ( -
- -
- ); - })} +
+
+ {([1, 2, 3] as const).map((step) => { + const isComplete = step < currentStep; + const isActive = step === currentStep; + const isUpcoming = step > currentStep; + const showFilledLine = step < currentStep; + + return ( +
+ {/* Step circle */} + + {isComplete ? ( + + + + ) : ( + {STEP_LABELS[step - 1]} + )} + + + {/* Connector line — only between steps, fills only when step is complete */} + {step < 3 && ( +
+ +
+ )} +
+ ); + })} +
); } diff --git a/src/components/configurator/StepServices.tsx b/src/components/configurator/StepServices.tsx index cecc854..3857698 100644 --- a/src/components/configurator/StepServices.tsx +++ b/src/components/configurator/StepServices.tsx @@ -27,7 +27,7 @@ const SERVICES: ServiceOption[] = [ const AI_TYPE_IDS = ['teammate', 'customer-facing', 'data-intelligence', 'notsure'] as const; -// ─── Service Card ──────────────────────────────────────────────────────────── +// ─── Service Card (horizontal layout) ──────────────────────────────────────── function ServiceCard({ option, @@ -35,12 +35,14 @@ function ServiceCard({ onToggle, title, description, + index, }: { option: ServiceOption; selected: boolean; onToggle: () => void; title: string; description: string; + index: number; }) { const Icon = option.icon; @@ -48,130 +50,61 @@ function ServiceCard({ -
+ {/* Icon + check badge */} +
- -
- -
-

- {title} -

-

{description}

-
- -
- - - {selected && ( - - - - )} - - -
-
- - ); -} - -// ─── AI Toggle ─────────────────────────────────────────────────────────────── - -function AIToggle({ - enabled, - onToggle, - label, - description, -}: { - enabled: boolean; - onToggle: () => void; - label: string; - description: string; -}) { - return ( -
-
- -
- + {title} +

+

{description}

+
); } @@ -209,19 +142,19 @@ export default function StepServices({ formData, setFormData, onNext }: StepProp const canProceed = formData.services.length > 0; return ( -
+
-
+

{t('step1.title')}

{t('step1.subtitle')}

- {/* Service cards */} -
- {SERVICES.map((option) => ( + {/* Service cards — horizontal grid */} +
+ {SERVICES.map((option, index) => ( toggleService(option.id)} title={t(option.titleKey)} description={t(option.descriptionKey)} + index={index} /> ))} - - {formData.services.length === 0 && ( - - {t('selectService')} - - )} -
- {/* AI Toggle + Type Selection */} -
- +

0} + > + {t('selectService')} +

+ + {/* AI Enhancement */} +
+ {formData.aiEnabled && ( @@ -264,29 +215,21 @@ export default function StepServices({ formData, setFormData, onNext }: StepProp transition={{ duration: 0.3, ease: [0.16, 1, 0.3, 1] }} className="overflow-hidden" > -
+
{AI_TYPE_IDS.map((aiId, index) => ( - toggleAIType(aiId)} - > + toggleAIType(aiId)}> {t(`aiTypes.${aiId}.title`)} ))}
- {formData.aiTypes.length > 0 && ( {formData.aiTypes.map((aiId) => (

@@ -312,13 +255,8 @@ export default function StepServices({ formData, setFormData, onNext }: StepProp

-
diff --git a/src/components/sections/Configurator.tsx b/src/components/sections/Configurator.tsx index 1ae91c2..9427d1e 100644 --- a/src/components/sections/Configurator.tsx +++ b/src/components/sections/Configurator.tsx @@ -131,7 +131,7 @@ export default function Configurator() { transition={{ duration: 0.7, ease: [0.16, 1, 0.3, 1], delay: 0.1 }} className="relative" > -
+
{/* Top-edge accent line */}
- LetsBe. Digital Studio · Côte d'Azur, France + LetsBe Solutions LLC
`,