Skip to content

Commit 775d894

Browse files
committed
redesign onboarding
1 parent 304f520 commit 775d894

File tree

1 file changed

+107
-157
lines changed
  • apps/dashboard/app/(main)/onboarding

1 file changed

+107
-157
lines changed

apps/dashboard/app/(main)/onboarding/page.tsx

Lines changed: 107 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,21 @@
11
"use client";
22

33
import {
4-
ArrowRight,
54
ArrowRightIcon,
65
BuildingsIcon,
76
CheckIcon,
87
CodeIcon,
98
GlobeIcon,
109
type Icon,
1110
SparkleIcon,
12-
UsersIcon,
1311
} from "@phosphor-icons/react";
1412
import { useRouter } from "next/navigation";
1513
import { useEffect, useState } from "react";
1614
import { CreateOrganizationDialog } from "@/components/organizations/create-organization-dialog";
17-
import { Badge } from "@/components/ui/badge";
1815
import { Button } from "@/components/ui/button";
19-
import {
20-
Card,
21-
CardContent,
22-
CardDescription,
23-
CardHeader,
24-
CardTitle,
25-
} from "@/components/ui/card";
16+
import { Card } from "@/components/ui/card";
17+
import { EmptyState } from "@/components/empty-state";
18+
import { PageHeader } from "@/app/(main)/websites/_components/page-header";
2619
import { WebsiteDialog } from "@/components/website-dialog";
2720
import { useOrganizations } from "@/hooks/use-organizations";
2821
import { useWebsites } from "@/hooks/use-websites";
@@ -46,7 +39,7 @@ function StepIndicator({
4639
currentStep: number;
4740
}) {
4841
return (
49-
<div className="flex items-center justify-center space-x-2 py-6">
42+
<div className="flex items-center justify-center gap-2 py-8">
5043
{steps.map((step, index) => (
5144
<div className="flex items-center" key={step.id}>
5245
<div
@@ -56,13 +49,15 @@ function StepIndicator({
5649
? "border-primary bg-primary text-primary-foreground"
5750
: index === currentStep
5851
? "border-primary bg-primary/10 text-primary"
59-
: "border-secondary bg-secondary text-secondary-foreground"
52+
: "border-muted bg-card text-muted-foreground"
6053
)}
6154
>
6255
{step.completed ? (
6356
<CheckIcon className="size-4" weight="bold" />
6457
) : (
65-
<span className="font-medium text-xs">{index + 1}</span>
58+
<span className="font-semibold text-xs tabular-nums">
59+
{index + 1}
60+
</span>
6661
)}
6762
</div>
6863
{index < steps.length - 1 && (
@@ -82,129 +77,67 @@ function StepIndicator({
8277
function OnboardingStepCard({
8378
step,
8479
isActive,
85-
isNext,
8680
}: {
8781
step: OnboardingStep;
8882
isActive: boolean;
89-
isNext: boolean;
9083
}) {
9184
return (
9285
<Card
9386
className={cn(
94-
"transition-all duration-300 hover:shadow-md",
87+
"group gap-0 overflow-hidden border bg-card py-0 transition-all duration-300 hover:border-primary",
9588
isActive
96-
? "border-primary/50 bg-primary/5 shadow-sm"
89+
? "border-primary/50"
9790
: step.completed
98-
? "border-primary/20 bg-primary/2"
99-
: "border-muted hover:border-border"
91+
? "border-primary/20"
92+
: "border-muted"
10093
)}
10194
>
102-
<CardHeader className="pb-4">
103-
<div className="flex items-center gap-3">
104-
<div
95+
<div className="flex items-center gap-2.5 px-2.5 py-2.5">
96+
<div
97+
className={cn(
98+
"flex size-7 shrink-0 items-center justify-center rounded bg-accent transition-colors",
99+
isActive || step.completed
100+
? "bg-primary/10"
101+
: "bg-accent"
102+
)}
103+
>
104+
<step.icon
105105
className={cn(
106-
"rounded-lg border p-3 transition-all duration-300",
106+
"size-4 transition-colors",
107107
isActive || step.completed
108-
? "border-accent bg-accent/50"
109-
: "border-muted bg-muted/50"
108+
? "text-primary"
109+
: "text-muted-foreground"
110110
)}
111-
>
112-
<step.icon
113-
className={cn(
114-
"size-6 transition-all duration-300",
115-
isActive || step.completed
116-
? "text-primary"
117-
: "text-muted-foreground"
118-
)}
119-
weight="duotone"
120-
/>
121-
</div>
122-
<div className="flex-1">
123-
<CardTitle className="flex items-center gap-2 text-lg">
124-
{step.title}
125-
{step.completed && (
126-
<Badge
127-
className="bg-primary/10 text-primary"
128-
variant="secondary"
129-
>
130-
<CheckIcon className="mr-1 size-3" />
131-
Done
132-
</Badge>
133-
)}
134-
</CardTitle>
135-
<CardDescription className="mt-1">
136-
{step.description}
137-
</CardDescription>
138-
</div>
111+
weight="bold"
112+
/>
139113
</div>
140-
</CardHeader>
141-
{(isActive || isNext) && step.action && (
142-
<CardContent className="pt-0">
143-
<Button
144-
className={cn(
145-
"w-full rounded transition-all duration-300",
146-
isActive
147-
? "bg-primary hover:bg-primary/90"
148-
: "bg-muted text-muted-foreground hover:bg-muted/80"
149-
)}
150-
disabled={!isActive}
151-
onClick={step.action}
152-
size="sm"
153-
>
154-
{step.actionLabel || "Continue"}
155-
<ArrowRightIcon className="ml-2 size-4" />
156-
</Button>
157-
</CardContent>
158-
)}
159-
</Card>
160-
);
161-
}
162-
163-
function WelcomeSection() {
164-
return (
165-
<div className="mb-8 space-y-4 text-center">
166-
<div className="inline-flex items-center gap-2 rounded-full border border-accent bg-accent/50 px-4 py-2">
167-
<SparkleIcon className="size-4 text-primary" weight="fill" />
168-
<span className="font-medium text-primary text-sm">
169-
Welcome to Databuddy!
170-
</span>
171-
</div>
172-
<h1 className="font-bold text-3xl tracking-tight">
173-
Let's get you started
174-
</h1>
175-
<p className="mx-auto max-w-2xl text-lg text-muted-foreground">
176-
Follow these simple steps to set up your analytics dashboard and start
177-
tracking your website's performance.
178-
</p>
179-
</div>
180-
);
181-
}
182-
183-
function CompletionSection() {
184-
return (
185-
<Card className="border-primary/20 bg-primary/5">
186-
<CardHeader className="text-center">
187-
<div className="mx-auto mb-4 w-fit rounded-full border border-accent bg-accent/50 p-4">
188-
<CheckIcon className="size-8 text-primary" weight="bold" />
114+
<div className="min-w-0 flex-1">
115+
<p className="truncate font-semibold text-base leading-tight">
116+
{step.title}
117+
</p>
118+
<p className="truncate text-muted-foreground text-xs">
119+
{step.description}
120+
</p>
189121
</div>
190-
<CardTitle className="text-xl">All Set!</CardTitle>
191-
<CardDescription className="text-base">
192-
You've successfully completed the onboarding. You're ready to start
193-
tracking analytics!
194-
</CardDescription>
195-
</CardHeader>
196-
<CardContent>
197-
<div className="flex flex-col gap-3 sm:flex-row sm:justify-center">
198-
<Button className="rounded" size="lg">
199-
<GlobeIcon className="mr-2 size-5" />
200-
View My Websites
201-
</Button>
202-
<Button className="rounded" size="lg" variant="outline">
203-
<UsersIcon className="mr-2 size-5" />
204-
Explore Dashboard
205-
</Button>
122+
<div className="shrink-0 text-right text-balance">
123+
{step.completed ? (
124+
<CheckIcon
125+
className="size-4 text-primary"
126+
weight="bold"
127+
aria-label="Completed"
128+
/>
129+
) : isActive && step.action ? (
130+
<Button
131+
className="rounded"
132+
onClick={step.action}
133+
size="sm"
134+
>
135+
{step.actionLabel || "Continue"}
136+
<ArrowRightIcon className="ml-2 size-4" weight="bold" />
137+
</Button>
138+
) : null}
206139
</div>
207-
</CardContent>
140+
</div>
208141
</Card>
209142
);
210143
}
@@ -228,7 +161,7 @@ export default function OnboardingPage() {
228161
id: "organization",
229162
title: "Create Organization",
230163
description: hasOrganization
231-
? "Organization created successfully!"
164+
? "Organization created successfully"
232165
: "Set up your team workspace for collaboration",
233166
icon: BuildingsIcon,
234167
completed: hasOrganization,
@@ -239,7 +172,7 @@ export default function OnboardingPage() {
239172
id: "website",
240173
title: "Add Your Website",
241174
description: hasWebsite
242-
? "Website added successfully!"
175+
? "Website added successfully"
243176
: "Add your first website to start tracking analytics",
244177
icon: GlobeIcon,
245178
completed: hasWebsite,
@@ -251,9 +184,8 @@ export default function OnboardingPage() {
251184
title: "Install Tracking",
252185
description: "Add the tracking script to your website to collect data",
253186
icon: CodeIcon,
254-
completed: false, // This would be determined by actual tracking data
187+
completed: false,
255188
action: () => {
256-
// Navigate to tracking setup
257189
if (websites && websites.length > 0) {
258190
window.location.href = `/websites/${websites[0].id}?tab=tracking-setup`;
259191
}
@@ -275,49 +207,67 @@ export default function OnboardingPage() {
275207
}, [allCompleted, router]);
276208

277209
return (
278-
<div className="container mx-auto max-w-4xl space-y-8 px-4 py-8">
279-
<WelcomeSection />
210+
<div className="flex h-full flex-col">
211+
<PageHeader
212+
description="Follow these steps to set up your analytics dashboard"
213+
icon={<SparkleIcon />}
214+
title="Get Started"
215+
/>
280216

281-
{!allCompleted && (
282-
<>
283-
<StepIndicator currentStep={currentStepIndex} steps={steps} />
217+
<div className="flex-1 overflow-y-auto p-3 sm:p-4 lg:p-6">
218+
<div className="mx-auto max-w-2xl space-y-6">
219+
{!allCompleted && (
220+
<>
221+
<StepIndicator currentStep={currentStepIndex} steps={steps} />
284222

285-
<div className="space-y-6">
286-
{steps.map((step, index) => (
287-
<OnboardingStepCard
288-
isActive={index === currentStepIndex}
289-
isNext={index === currentStepIndex + 1}
290-
key={step.id}
291-
step={step}
292-
/>
293-
))}
294-
</div>
223+
<div className="space-y-3">
224+
{steps.map((step, index) => (
225+
<OnboardingStepCard
226+
isActive={index === currentStepIndex}
227+
key={step.id}
228+
step={step}
229+
/>
230+
))}
231+
</div>
295232

296-
<div className="flex justify-center">
297-
<Button
298-
className="rounded"
299-
onClick={() => {
300-
window.location.href = "/websites";
301-
}}
302-
variant="ghost"
303-
>
304-
Skip for now
305-
<ArrowRight className="ml-2 size-4" />
306-
</Button>
307-
</div>
308-
</>
309-
)}
233+
<div className="flex justify-center pt-4">
234+
<Button
235+
className="rounded"
236+
onClick={() => {
237+
window.location.href = "/websites";
238+
}}
239+
variant="ghost"
240+
>
241+
Skip for now
242+
<ArrowRightIcon className="ml-2 size-4" weight="bold" />
243+
</Button>
244+
</div>
245+
</>
246+
)}
310247

311-
{allCompleted && <CompletionSection />}
248+
{allCompleted && (
249+
<EmptyState
250+
action={{
251+
label: "View My Websites",
252+
onClick: () => {
253+
window.location.href = "/websites";
254+
},
255+
}}
256+
className="h-full"
257+
description="You've successfully completed the onboarding. You're ready to start tracking analytics!"
258+
icon={<CheckIcon weight="bold" />}
259+
showPlusBadge={false}
260+
title="All Set!"
261+
variant="minimal"
262+
/>
263+
)}
264+
</div>
265+
</div>
312266

313267
{/* Dialogs */}
314268
<CreateOrganizationDialog
315269
isOpen={showCreateOrgDialog}
316270
onClose={() => setShowCreateOrgDialog(false)}
317-
onSuccess={() => {
318-
// Stay on onboarding page after creating organization
319-
setShowCreateOrgDialog(false);
320-
}}
321271
/>
322272

323273
<WebsiteDialog

0 commit comments

Comments
 (0)