reachy_mini_minder / frontend /src /registry /OnboardingProgress.tsx
Boopster's picture
feat: Introduce an onboarding review step and remove the initial welcome step from the onboarding flow.
fb88636
"use client";
import { Check, User, Pill, Users, PartyPopper, ClipboardCheck } from "lucide-react";
interface OnboardingProgressProps {
currentStep: "name" | "medications" | "contacts" | "review" | "complete";
}
const steps = [
{ id: "name", label: "Your Name", icon: User },
{ id: "medications", label: "Medications", icon: Pill },
{ id: "contacts", label: "Contacts", icon: Users },
{ id: "review", label: "Review", icon: ClipboardCheck },
{ id: "complete", label: "All Set!", icon: Check },
];
function getStepStatus(stepId: string, currentStep: string): "completed" | "current" | "upcoming" {
const stepIndex = steps.findIndex((s) => s.id === stepId);
const currentIndex = steps.findIndex((s) => s.id === currentStep);
if (stepIndex < currentIndex) return "completed";
if (stepIndex === currentIndex) return "current";
return "upcoming";
}
export function OnboardingProgress({ currentStep }: OnboardingProgressProps) {
return (
<div
className="flex flex-col items-center justify-center h-full w-full px-12 py-16"
>
{/* Header */}
<div className="flex items-center gap-6 mb-16">
<div
className="relative w-20 h-20 rounded-2xl flex items-center justify-center
bg-gradient-to-br from-cta/25 to-cta/10
border border-cta/30"
>
<PartyPopper className="w-10 h-10 text-cta" />
</div>
<div>
<h3 className="text-4xl font-bold tracking-tight text-primary">Getting Started</h3>
<p className="text-xl text-muted mt-2">Let&apos;s set up your care companion</p>
</div>
</div>
{/* Progress Steps */}
<div className="flex items-center justify-center gap-4">
{steps.map((step, index) => {
const status = getStepStatus(step.id, currentStep);
const Icon = step.icon;
return (
<div key={step.id} className="flex items-center">
{/* Step Circle */}
<div className="flex flex-col items-center gap-4">
<div
className={`
relative w-20 h-20 rounded-full flex items-center justify-center
transition-all duration-500 ease-out
${status === "completed"
? "bg-accent-cyan text-gray-900 scale-100"
: status === "current"
? "bg-cta text-gray-900 scale-110 shadow-[0_0_30px_rgba(179,156,208,0.5)]"
: "bg-surface-overlay text-muted scale-90 opacity-50"
}
`}
>
{status === "completed" ? (
<Check className="w-10 h-10" />
) : (
<Icon className="w-9 h-9" />
)}
{/* Pulse animation for current step */}
{status === "current" && (
<span className="absolute inset-0 rounded-full border-2 border-cta animate-ping opacity-30" />
)}
</div>
{/* Label */}
<span
className={`
text-lg font-semibold uppercase tracking-wide
transition-all duration-300
${status === "current" ? "text-cta" : status === "completed" ? "text-accent-cyan" : "text-muted opacity-50"}
`}
>
{step.label}
</span>
</div>
{/* Connector Line */}
{index < steps.length - 1 && (
<div
className={`
w-16 h-1 mx-4 rounded-full transition-all duration-500
${getStepStatus(steps[index + 1].id, currentStep) !== "upcoming"
? "bg-accent-cyan"
: "bg-surface-overlay opacity-30"
}
`}
/>
)}
</div>
);
})}
</div>
</div>
);
}