modula-ui 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +36 -0
  2. package/bin/run.js +86 -0
  3. package/package.json +71 -0
  4. package/public/avatars/avatar1.png +0 -0
  5. package/public/avatars/avatar2.png +0 -0
  6. package/public/avatars/avatar3.png +0 -0
  7. package/public/avatars/avatar4.png +0 -0
  8. package/public/avatars/sources.md +34 -0
  9. package/public/file.svg +1 -0
  10. package/public/globe.svg +1 -0
  11. package/public/next.svg +1 -0
  12. package/public/vercel.svg +1 -0
  13. package/public/window.svg +1 -0
  14. package/registry.json +12 -0
  15. package/src/app/favicon.ico +0 -0
  16. package/src/app/globals.css +126 -0
  17. package/src/app/layout.js +29 -0
  18. package/src/app/page.js +50 -0
  19. package/src/app/patterns/page.js +50 -0
  20. package/src/components/CodeCard.jsx +16 -0
  21. package/src/components/CopyButton.jsx +31 -0
  22. package/src/components/Header.jsx +24 -0
  23. package/src/components/Logo.jsx +64 -0
  24. package/src/components/MobileOverlay.jsx +10 -0
  25. package/src/components/PreviewCard.jsx +98 -0
  26. package/src/components/Sidebar.jsx +47 -0
  27. package/src/components/ui/avatar.jsx +47 -0
  28. package/src/components/ui/badge.jsx +44 -0
  29. package/src/components/ui/button.jsx +56 -0
  30. package/src/components/ui/calendar.jsx +178 -0
  31. package/src/components/ui/card.jsx +101 -0
  32. package/src/components/ui/chart.jsx +314 -0
  33. package/src/components/ui/checkbox.jsx +30 -0
  34. package/src/components/ui/dropdown-menu.jsx +223 -0
  35. package/src/components/ui/input.jsx +24 -0
  36. package/src/components/ui/navigation-menu.jsx +152 -0
  37. package/src/components/ui/popover.jsx +47 -0
  38. package/src/components/ui/progress.jsx +29 -0
  39. package/src/components/ui/scroll-area.jsx +51 -0
  40. package/src/components/ui/select.jsx +168 -0
  41. package/src/components/ui/separator.jsx +27 -0
  42. package/src/components/ui/sheet.jsx +140 -0
  43. package/src/components/ui/sidebar.jsx +682 -0
  44. package/src/components/ui/skeleton.jsx +15 -0
  45. package/src/components/ui/slider.jsx +56 -0
  46. package/src/components/ui/tooltip.jsx +55 -0
  47. package/src/data/componentData.js +12 -0
  48. package/src/hooks/use-mobile.js +19 -0
  49. package/src/lib/utils.js +6 -0
  50. package/src/library/components/Alert.jsx +27 -0
  51. package/src/library/components/Badge.jsx +19 -0
  52. package/src/library/components/Button.jsx +31 -0
  53. package/src/library/components/Card.jsx +25 -0
  54. package/src/library/components/Input.jsx +35 -0
  55. package/src/library/components/Modal.jsx +26 -0
  56. package/src/library/components/Textarea.jsx +15 -0
  57. package/src/library/components/Toggle.jsx +16 -0
  58. package/src/library/pages/FitnessPage/FitnessPage.jsx +519 -0
  59. package/src/library/pages/FitnessPage/index.jsx +12 -0
  60. package/src/library/pages/GroupChat/GroupChat.jsx +275 -0
  61. package/src/library/pages/GroupChat/data.js +203 -0
  62. package/src/library/pages/GroupChat/index.jsx +12 -0
  63. package/src/library/pages/ReservationsOverview/ReservationsOverviewPage.jsx +225 -0
  64. package/src/library/pages/ReservationsOverview/index.jsx +12 -0
  65. package/src/library/pages/VideoConference/VideoConferencePage.jsx +334 -0
  66. package/src/library/pages/VideoConference/index.jsx +12 -0
@@ -0,0 +1,519 @@
1
+ import React from "react";
2
+ import {
3
+ Search,
4
+ Bell,
5
+ LayoutDashboard,
6
+ MessageSquare,
7
+ Users,
8
+ BarChart2,
9
+ Dumbbell,
10
+ Settings,
11
+ HelpCircle,
12
+ ChevronLeft,
13
+ MoreHorizontal,
14
+ Calendar as CalendarIcon,
15
+ Filter,
16
+ Check,
17
+ Eye,
18
+ Link as LinkIcon,
19
+ } from "lucide-react";
20
+
21
+ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
22
+ import { Button } from "@/components/ui/button";
23
+ import { Input } from "@/components/ui/input";
24
+ import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
25
+ import { Badge } from "@/components/ui/badge";
26
+ import { Progress } from "@/components/ui/progress";
27
+ import { Checkbox } from "@/components/ui/checkbox";
28
+ import {
29
+ Select,
30
+ SelectContent,
31
+ SelectItem,
32
+ SelectTrigger,
33
+ SelectValue,
34
+ } from "@/components/ui/select";
35
+
36
+ import { ChartContainer, ChartTooltip, ChartTooltipContent } from "@/components/ui/chart";
37
+ import { Pie, PieChart, Label } from "recharts";
38
+
39
+ const chartData = [
40
+ { browser: "chrome", visitors: 70, fill: "var(--color-chrome)" },
41
+ { browser: "safari", visitors: 30, fill: "var(--color-safari)" },
42
+ ]
43
+
44
+ const chartConfig = {
45
+ visitors: {
46
+ label: "Sessions",
47
+ },
48
+ chrome: {
49
+ label: "Completed",
50
+ color: "hsl(217, 91%, 60%)", // Blue-600
51
+ },
52
+ safari: {
53
+ label: "Remaining",
54
+ color: "hsl(210, 40%, 96%)", // Slate-100 (or similar light color for empty part)
55
+ },
56
+ }
57
+
58
+ const FitnessPage = () => {
59
+ return (
60
+ <div className="flex min-h-screen bg-neutral-100 font-sans text-slate-900">
61
+ {/* <Sidebar /> */}
62
+ <main className="flex-1 flex flex-col min-w-0 overflow-hidden">
63
+ <DashboardHeader />
64
+ <div className="flex-1 overflow-auto p-8">
65
+ <div className="mb-8">
66
+ <h1 className="text-2xl font-bold text-gray-900 flex items-center gap-2">
67
+ Good morning, Summer <span className="text-2xl">👋</span>
68
+ </h1>
69
+ <p className="text-sm text-gray-500 mt-1">Saturday, 26 Oct 2024</p>
70
+ </div>
71
+
72
+ <div className="flex gap-4 mb-6">
73
+ <TotalClientCard />
74
+ <TrainingSessionsCard />
75
+ <TrainingSessionsCard />
76
+ </div>
77
+
78
+ <div className="flex gap-6">
79
+ <AppointmentCard />
80
+ <ClientProgressCard />
81
+ {/* <AISuggestionsCard /> */}
82
+ </div>
83
+ </div>
84
+ </main>
85
+ </div>
86
+ );
87
+ };
88
+
89
+ const Sidebar = () => (
90
+ <aside className="w-64 bg-white border-r border-gray-100 flex flex-col hidden md:flex">
91
+ <div className="p-6 flex items-center gap-2">
92
+ <div className="h-8 w-8 bg-blue-500 rounded-full flex items-center justify-center text-white font-bold">
93
+ <Dumbbell size={16} />
94
+ </div>
95
+ <span className="text-xl font-bold tracking-tight">Fitrack</span>
96
+ <Button variant="ghost" size="icon" className="ml-auto h-8 w-8 bg-gray-100 rounded-md">
97
+ <ChevronLeft size={16} />
98
+ </Button>
99
+ </div>
100
+
101
+ <div className="px-4 py-2">
102
+ <p className="text-xs font-semibold text-gray-400 mb-4 px-2">MAIN</p>
103
+ <nav className="space-y-1">
104
+ <NavItem icon={LayoutDashboard} label="Today" active />
105
+ <NavItem icon={MessageSquare} label="Weekly" />
106
+ <NavItem icon={Users} label="Goals" />
107
+ <NavItem icon={BarChart2} label="Activity" />
108
+ <NavItem icon={Dumbbell} label="Trends" />
109
+ <NavItem icon={Dumbbell} label="Settings" />
110
+ </nav>
111
+ </div>
112
+
113
+ <div className="px-4 py-2 mt-auto mb-8">
114
+ <p className="text-xs font-semibold text-gray-400 mb-4 px-2">SUPPORT</p>
115
+ <nav className="space-y-1">
116
+ <NavItem icon={Settings} label="Setting" />
117
+ <NavItem icon={HelpCircle} label="Help" />
118
+ </nav>
119
+ </div>
120
+
121
+ <div className="p-4 border-t border-gray-100">
122
+ <div className="flex items-center gap-3 p-2 rounded-lg hover:bg-gray-50 cursor-pointer">
123
+ <Avatar>
124
+ <AvatarImage src="https://github.com/shadcn.png" />
125
+ <AvatarFallback>SY</AvatarFallback>
126
+ </Avatar>
127
+ <div className="flex-1 min-w-0">
128
+ <p className="text-sm font-medium text-gray-900 truncate">Summer Yuri</p>
129
+ <p className="text-xs text-gray-500 truncate">Trainer</p>
130
+ </div>
131
+ <ChevronLeft className="h-4 w-4 text-gray-400 rotate-270" />
132
+ </div>
133
+ <p className="text-[10px] text-gray-400 mt-4 text-center">
134
+ ©2024 Fitrack. All right reserved.
135
+ </p>
136
+ </div>
137
+ </aside>
138
+ );
139
+
140
+ const DashboardHeader = () => (
141
+ <header className="bg-white border-b border-gray-100 h-16 flex items-center justify-between px-8">
142
+ <div className="flex items-center text-sm text-gray-500">
143
+ <span>Main</span>
144
+ <span className="mx-2">/</span>
145
+ <span className="font-medium text-gray-900">Dashboard</span>
146
+ </div>
147
+
148
+ <div className="flex items-center gap-4">
149
+ <div className="relative w-64">
150
+ <Search className="absolute left-2.5 top-2.5 h-4 w-4 text-gray-400" />
151
+ <Input
152
+ type="search"
153
+ placeholder="Search"
154
+ className="pl-9 bg-gray-50 border-none focus-visible:ring-1"
155
+ />
156
+ <div className="absolute right-2.5 top-2.5 flex items-center gap-1">
157
+ <span className="text-[10px] text-gray-400 border border-gray-200 rounded px-1">⌘/</span>
158
+ </div>
159
+ </div>
160
+ <Button variant="ghost" size="icon" className="text-gray-500">
161
+ <Bell size={20} />
162
+ </Button>
163
+ </div>
164
+ </header>
165
+ );
166
+
167
+ const TotalClientCard = () => (
168
+ <Card className="w-full border-none shadow-sm">
169
+ <CardHeader className="flex flex-row items-center justify-between pb-2">
170
+ <div className="flex items-center gap-2">
171
+ <div className="h-8 w-8 rounded-full bg-cyan-50 flex items-center justify-center text-cyan-500">
172
+ <Users size={16} />
173
+ </div>
174
+ <CardTitle className="text-base font-medium">Total Client</CardTitle>
175
+ </div>
176
+ <Button variant="ghost" size="icon" className="h-8 w-8">
177
+ <MoreHorizontal size={16} />
178
+ </Button>
179
+ </CardHeader>
180
+ <CardContent>
181
+ <div className="flex items-end gap-4 mb-8">
182
+ <span className="text-4xl font-bold">2,000</span>
183
+ <Badge variant="secondary" className="bg-green-50 text-green-600 hover:bg-green-100 mb-1">
184
+ <div className="h-3 w-3 rounded-full bg-green-500 flex items-center justify-center mr-1">
185
+ <Check size={8} className="text-white" />
186
+ </div>
187
+ 25%
188
+ </Badge>
189
+ <span className="text-sm text-gray-500 mb-1">vs last month</span>
190
+ </div>
191
+
192
+ <div className="grid grid-cols-3 gap-8">
193
+ <StatColumn label="Intermediate" value="750" percentage="37.5%" color="bg-blue-200" />
194
+ <StatColumn label="Advanced" value="550" percentage="27.5%" color="bg-blue-600" />
195
+ </div>
196
+ </CardContent>
197
+ </Card>
198
+ );
199
+
200
+ const TrainingSessionsCard = () => (
201
+ <Card className="w-full border-none shadow-sm flex flex-col">
202
+ <CardHeader className="flex flex-row items-center justify-between pb-2">
203
+ <div className="flex items-center gap-2">
204
+ <div className="h-8 w-8 rounded-full bg-cyan-50 flex items-center justify-center text-cyan-500">
205
+ <Dumbbell size={16} />
206
+ </div>
207
+ <CardTitle className="text-base font-medium">
208
+ Number of training sessions
209
+ </CardTitle>
210
+ </div>
211
+ <Select defaultValue="week">
212
+ <SelectTrigger className="w-[100px] h-8 text-xs">
213
+ <SelectValue placeholder="Select" />
214
+ </SelectTrigger>
215
+ <SelectContent>
216
+ <SelectItem value="week">This Week</SelectItem>
217
+ <SelectItem value="month">This Month</SelectItem>
218
+ </SelectContent>
219
+ </Select>
220
+ </CardHeader>
221
+ <CardContent className="flex-1 flex flex-col items-center justify-center pb-6">
222
+ <div className="flex-1 w-full min-h-[200px] flex items-center justify-center relative">
223
+ <ChartContainer
224
+ config={chartConfig}
225
+ className="mx-auto aspect-square max-h-[200px]"
226
+ >
227
+ <PieChart>
228
+ <ChartTooltip
229
+ cursor={false}
230
+ content={<ChartTooltipContent hideLabel />}
231
+ />
232
+ <Pie
233
+ data={chartData}
234
+ dataKey="visitors"
235
+ nameKey="browser"
236
+ innerRadius={60}
237
+ strokeWidth={5}
238
+ >
239
+ <Label
240
+ content={({ viewBox }) => {
241
+ if (viewBox && "cx" in viewBox && "cy" in viewBox) {
242
+ return (
243
+ <text
244
+ x={viewBox.cx}
245
+ y={viewBox.cy}
246
+ textAnchor="middle"
247
+ dominantBaseline="middle"
248
+ >
249
+ <tspan
250
+ x={viewBox.cx}
251
+ y={viewBox.cy}
252
+ className="fill-gray-400 text-xs"
253
+ >
254
+ Total
255
+ </tspan>
256
+ <tspan
257
+ x={viewBox.cx}
258
+ y={(viewBox.cy || 0) + 24}
259
+ className="fill-foreground text-3xl font-bold"
260
+ >
261
+ 16
262
+ </tspan>
263
+ </text>
264
+ );
265
+ }
266
+ }}
267
+ />
268
+ </Pie>
269
+ </PieChart>
270
+ </ChartContainer>
271
+ {/* Floating badge for 70% */}
272
+ <div className="absolute top-1/4 right-1/4 transform translate-x-2 -translate-y-2 bg-white px-2 py-1 rounded-full shadow-sm border text-xs font-bold text-gray-700 z-10">
273
+ 70%
274
+ </div>
275
+ </div>
276
+
277
+ <div className="mt-4 flex items-center gap-2 text-sm">
278
+ <Badge
279
+ variant="secondary"
280
+ className="bg-green-50 text-green-600 hover:bg-green-100"
281
+ >
282
+ <div className="h-3 w-3 rounded-full bg-green-500 flex items-center justify-center mr-1">
283
+ <Check size={8} className="text-white" />
284
+ </div>
285
+ 15%
286
+ </Badge>
287
+ <span className="text-gray-500">vs last week</span>
288
+ </div>
289
+
290
+ <div className="w-full mt-6 space-y-2">
291
+ <div className="flex flex-col justify-between text-xs">
292
+ <span className="flex gap-2">
293
+ <div className="w-2 h-2 rounded-full bg-[var(--color-chrome)]"></div>{" "}
294
+ Weekly session goals
295
+ </span>
296
+ <span className="font-medium text-green-600">
297
+ 20 Sessions
298
+ </span>
299
+ </div>
300
+ <div className="flex justify-between text-xs">
301
+ <span className="flex items-center gap-2">
302
+ <div className="w-2 h-2 rounded-full bg-[var(--color-safari)]"></div>{" "}
303
+ Average sessions per client
304
+ </span>
305
+ <span className="font-medium text-green-600">
306
+ 3 Sessions
307
+ </span>
308
+ </div>
309
+ </div>
310
+ </CardContent>
311
+ </Card>
312
+ );
313
+
314
+ const AppointmentCard = () => (
315
+ <Card className="w-full border-none shadow-sm">
316
+ <CardHeader className="flex flex-row items-center justify-between pb-4">
317
+ <div className="flex items-center gap-2">
318
+ <div className="h-8 w-8 rounded-full bg-cyan-50 flex items-center justify-center text-cyan-500">
319
+ <CalendarIcon size={16} />
320
+ </div>
321
+ <CardTitle className="text-base font-medium">Appointment</CardTitle>
322
+ </div>
323
+ <Button variant="outline" size="sm" className="h-8 text-xs font-normal text-gray-500">
324
+ <CalendarIcon size={12} className="mr-2" />
325
+ 21 Oct 2024 - 27 Oct 2024
326
+ </Button>
327
+ </CardHeader>
328
+ <CardContent>
329
+ {/* Calendar Strip */}
330
+ <div className="flex justify-between mb-6">
331
+ {['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'].map((day, i) => (
332
+ <div key={day} className={`flex flex-col items-center p-2 rounded-lg ${i === 5 ? 'bg-cyan-500 text-white' : 'hover:bg-gray-50'}`}>
333
+ <span className={`text-[10px] ${i === 5 ? 'text-white' : 'text-gray-400'}`}>{day}</span>
334
+ <span className="text-sm font-medium mt-1">{21 + i}</span>
335
+ </div>
336
+ ))}
337
+ </div>
338
+
339
+ <div className="flex items-center gap-2 mb-4">
340
+ <div className="relative flex-1">
341
+ <Search className="absolute left-2.5 top-2.5 h-3 w-3 text-gray-400" />
342
+ <Input placeholder="Search client" className="pl-8 h-9 text-xs bg-white" />
343
+ </div>
344
+ <Button variant="outline" size="sm" className="h-9 px-3">
345
+ <Filter size={14} className="mr-2" /> Filter
346
+ </Button>
347
+ </div>
348
+
349
+ <div className="space-y-3">
350
+ <AppointmentItem name="David Lee" time="08:30 AM" type="Exercise" status="On Schedule" image="https://github.com/shadcn.png" />
351
+ <AppointmentItem name="Sarah Kim" time="03:00 PM" type="Consultation" status="Cancel" image="https://github.com/shadcn.png" />
352
+ <AppointmentItem name="Ihan Dua" time="05:00 PM" type="Exercise" status="On Schedule" image="https://github.com/shadcn.png" />
353
+ </div>
354
+ </CardContent>
355
+ </Card>
356
+ );
357
+
358
+ const ClientProgressCard = () => (
359
+ <Card className="w-full border-none shadow-sm">
360
+ <CardHeader className="flex flex-row items-center justify-between pb-4">
361
+ <div className="flex items-center gap-2">
362
+ <div className="h-8 w-8 rounded-full bg-cyan-50 flex items-center justify-center text-cyan-500">
363
+ <BarChart2 size={16} />
364
+ </div>
365
+ <CardTitle className="text-base font-medium">Client Progress</CardTitle>
366
+ </div>
367
+ <Button variant="ghost" size="icon" className="h-8 w-8">
368
+ <MoreHorizontal size={16} />
369
+ </Button>
370
+ </CardHeader>
371
+ <CardContent>
372
+ <div className="flex bg-gray-50 p-1 rounded-lg mb-6">
373
+ <Button variant="ghost" className="flex-1 bg-white shadow-sm h-8 text-xs font-medium">Weekly Target</Button>
374
+ <Button variant="ghost" className="flex-1 h-8 text-xs text-gray-500">Monthly Target</Button>
375
+ </div>
376
+
377
+ <div className="space-y-6">
378
+ <ProgressItem name="Lucas Kim" status="On Track" value={75} color="bg-blue-600" />
379
+ <ProgressItem name="Sophia Chen" status="Overachieving" value={88} color="bg-cyan-500" />
380
+ <ProgressItem name="Ariana Lee" status="Below the target" value={40} color="bg-pink-500" />
381
+ </div>
382
+ </CardContent>
383
+ </Card>
384
+ );
385
+
386
+ const AISuggestionsCard = () => (
387
+ <Card className="col-span-1 border-none shadow-sm">
388
+ <CardHeader className="flex flex-row items-center justify-between pb-4">
389
+ <div className="flex items-center gap-2">
390
+ <div className="h-8 w-8 rounded-full bg-cyan-50 flex items-center justify-center text-cyan-500">
391
+ <div className="relative">
392
+ <div className="absolute -top-1 -right-1 h-2 w-2 bg-yellow-400 rounded-full animate-pulse"></div>
393
+ <Users size={16} /> {/* Using Users as placeholder for sparkles/AI icon */}
394
+ </div>
395
+ <CardTitle className="text-base font-medium">AI Suggestions</CardTitle>
396
+ </div>
397
+ <Button variant="ghost" size="icon" className="h-8 w-8">
398
+ <MoreHorizontal size={16} />
399
+ </Button>
400
+ </div>
401
+ </CardHeader>
402
+ <CardContent>
403
+ <div className="space-y-4">
404
+ <SuggestionItem
405
+ text={<span>Suggest <span className="text-cyan-600 font-medium">Sarah Kim</span> to incorporate 10 minutes of stretching after each workout for better flexibility.</span>}
406
+ />
407
+ <SuggestionItem
408
+ text={<span>Remind <span className="text-cyan-600 font-medium">Amanda Ros</span> to take short breaks during long cardio sessions to maintain energy levels.</span>}
409
+ />
410
+ <SuggestionItem
411
+ text={<span>Recommend <span className="text-cyan-600 font-medium">Spring Alexander</span> foods like sweet potatoes, oats, and avocado.</span>}
412
+ />
413
+ <SuggestionItem
414
+ text={<span>Encourage <span className="text-cyan-600 font-medium line-through">David Lee</span> to increase protein intake to support muscle recovery.</span>}
415
+ checked
416
+ />
417
+ </div>
418
+ </CardContent>
419
+ </Card>
420
+ );
421
+
422
+ // Helper Components
423
+
424
+ const NavItem = ({ icon: Icon, label, active, badge }) => (
425
+ <div
426
+ className={`flex items-center justify-between px-3 py-2 rounded-lg cursor-pointer group ${active ? "bg-white shadow-sm border border-gray-100" : "hover:bg-gray-50"
427
+ }`}
428
+ >
429
+ <div className="flex items-center gap-3">
430
+ <Icon size={18} className={active ? "text-gray-900" : "text-gray-400 group-hover:text-gray-600"} />
431
+ <span className={`text-sm font-medium ${active ? "text-gray-900" : "text-gray-500 group-hover:text-gray-900"}`}>
432
+ {label}
433
+ </span>
434
+ </div>
435
+ {badge && (
436
+ <span className="bg-gray-100 text-gray-600 text-xs font-medium px-2 py-0.5 rounded-full">
437
+ {badge}
438
+ </span>
439
+ )}
440
+ </div>
441
+ );
442
+
443
+ const StatColumn = ({ label, value, percentage, color }) => (
444
+ <div>
445
+ <div className="flex items-center justify-between mb-2">
446
+ <span className="text-2xl font-bold">{value}</span>
447
+ <Button variant="ghost" size="icon" className="h-6 w-6 text-gray-300">
448
+ <Eye size={14} />
449
+ </Button>
450
+ </div>
451
+ <p className="text-sm text-gray-500 mb-3">{label}</p>
452
+ <div className="flex items-center gap-2">
453
+ <span className="text-sm font-medium">{percentage}</span>
454
+ <div className={`h-2 w-full rounded-full bg-gray-100 overflow-hidden`}>
455
+ <div className={`h-full ${color}`} style={{ width: percentage }}></div>
456
+ </div>
457
+ </div>
458
+ </div>
459
+ );
460
+
461
+ const AppointmentItem = ({ name, time, type, status, image }) => (
462
+ <div className="flex items-center justify-between p-3 border border-gray-100 rounded-xl bg-white">
463
+ <div className="flex items-center gap-3">
464
+ <Avatar className="h-10 w-10">
465
+ <AvatarImage src={image} />
466
+ <AvatarFallback>{name[0]}</AvatarFallback>
467
+ </Avatar>
468
+ <div>
469
+ <p className="text-sm font-semibold text-gray-900">{name}</p>
470
+ <div className="flex items-center gap-2 text-xs text-gray-500">
471
+ <span>{time}</span>
472
+ <span className="h-1 w-1 rounded-full bg-gray-300"></span>
473
+ <span>{type}</span>
474
+ </div>
475
+ </div>
476
+ </div>
477
+ <Badge variant="secondary" className={`font-normal ${status === 'Cancel' ? 'bg-pink-50 text-pink-500' : 'bg-blue-50 text-blue-600'}`}>
478
+ {status}
479
+ </Badge>
480
+ </div>
481
+ );
482
+
483
+ const ProgressItem = ({ name, status, value, color }) => (
484
+ <div>
485
+ <div className="flex items-center justify-between mb-2">
486
+ <div className="flex items-center gap-2">
487
+ <span className="text-sm font-semibold text-gray-900">{name}</span>
488
+ <span className="h-1 w-1 rounded-full bg-gray-300"></span>
489
+ <span className="text-xs text-gray-500">{status}</span>
490
+ </div>
491
+ <div className="flex items-center gap-2">
492
+ <Button variant="ghost" size="icon" className="h-6 w-6 text-gray-400">
493
+ <Eye size={14} />
494
+ </Button>
495
+ <Button variant="ghost" size="icon" className="h-6 w-6 text-gray-400">
496
+ <LinkIcon size={14} />
497
+ </Button>
498
+ </div>
499
+ </div>
500
+ <div className="flex items-center gap-3">
501
+ <Progress value={value} className="h-2" indicatorColor={color} />
502
+ <span className="text-xs font-medium text-gray-500 w-8 text-right">{value}%</span>
503
+ </div>
504
+ </div>
505
+ );
506
+
507
+ const SuggestionItem = ({ text, checked }) => (
508
+ <div className="flex items-start gap-3">
509
+ <Checkbox id="terms" checked={checked} className="mt-1 data-[state=checked]:bg-cyan-500 data-[state=checked]:border-cyan-500" />
510
+ <label
511
+ htmlFor="terms"
512
+ className={`text-sm leading-relaxed ${checked ? 'text-gray-400 line-through' : 'text-gray-600'}`}
513
+ >
514
+ {text}
515
+ </label>
516
+ </div>
517
+ );
518
+
519
+ export default FitnessPage;
@@ -0,0 +1,12 @@
1
+ "use client"
2
+
3
+ import React from 'react'
4
+ import FitnessPage from './FitnessPage'
5
+
6
+ export const FitnessOverview = {
7
+ name: "Fitness Overview",
8
+ code: "",
9
+ preview: (
10
+ <FitnessPage />
11
+ )
12
+ }