11"use client" ;
22
33import {
4- ArrowRight ,
54 ArrowRightIcon ,
65 BuildingsIcon ,
76 CheckIcon ,
87 CodeIcon ,
98 GlobeIcon ,
109 type Icon ,
1110 SparkleIcon ,
12- UsersIcon ,
1311} from "@phosphor-icons/react" ;
1412import { useRouter } from "next/navigation" ;
1513import { useEffect , useState } from "react" ;
1614import { CreateOrganizationDialog } from "@/components/organizations/create-organization-dialog" ;
17- import { Badge } from "@/components/ui/badge" ;
1815import { 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" ;
2619import { WebsiteDialog } from "@/components/website-dialog" ;
2720import { useOrganizations } from "@/hooks/use-organizations" ;
2821import { 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({
8277function 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