Preview
Full width desktop view
Code
bills-8.tsx
1"use client";
2
3import React, { useState, useEffect } from "react";
4import {
5 Home,
6 User,
7 Settings,
8 LogOut,
9 Menu,
10 X,
11 ChevronLeft,
12 ChevronRight,
13 BarChart3,
14 FileText,
15 Bell,
16 Search,
17 HelpCircle,
18 CreditCard,
19 Package,
20 Plus,
21 Check,
22 Crown,
23 Zap,
24 Building,
25 Calendar,
26 DollarSign,
27 TrendingUp,
28 AlertCircle,
29 Download,
30 Filter,
31} from "lucide-react";
32import { Button } from "@/components/ui/button";
33import { Card } from "@/components/ui/card";
34import { Badge } from "@/components/ui/badge";
35import { Separator } from "@/components/ui/separator";
36import { Switch } from "@/components/ui/switch";
37import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
38
39interface NavigationItem {
40 id: string;
41 name: string;
42 icon: React.ComponentType<{ className?: string }>;
43 href: string;
44 badge?: string;
45}
46
47interface SidebarProps {
48 className?: string;
49}
50
51interface Plan {
52 id: string;
53 name: string;
54 description: string;
55 price: {
56 monthly: number;
57 yearly: number;
58 };
59 features: string[];
60 isPopular?: boolean;
61 icon: React.ComponentType<{ className?: string }>;
62 color: string;
63}
64
65interface AddOn {
66 id: string;
67 name: string;
68 description: string;
69 price: {
70 monthly: number;
71 yearly: number;
72 };
73 icon: React.ComponentType<{ className?: string }>;
74}
75
76interface Bill {
77 id: string;
78 description: string;
79 amount: number;
80 dueDate: string;
81 status: "paid" | "pending" | "overdue";
82 type: "plan" | "addon";
83}
84
85const navigationItems: NavigationItem[] = [
86 { id: "dashboard", name: "Dashboard", icon: Home, href: "/dashboard" },
87 {
88 id: "billing",
89 name: "Billing & Plans",
90 icon: CreditCard,
91 href: "/billing",
92 badge: "2",
93 },
94 { id: "analytics", name: "Analytics", icon: BarChart3, href: "/analytics" },
95 {
96 id: "documents",
97 name: "Documents",
98 icon: FileText,
99 href: "/documents",
100 badge: "3",
101 },
102 {
103 id: "notifications",
104 name: "Notifications",
105 icon: Bell,
106 href: "/notifications",
107 badge: "12",
108 },
109 { id: "profile", name: "Profile", icon: User, href: "/profile" },
110 { id: "settings", name: "Settings", icon: Settings, href: "/settings" },
111 { id: "help", name: "Help & Support", icon: HelpCircle, href: "/help" },
112];
113
114const plans: Plan[] = [
115 {
116 id: "starter",
117 name: "Starter",
118 description: "Perfect for small teams getting started",
119 price: { monthly: 29, yearly: 290 },
120 features: [
121 "Up to 5 team members",
122 "10GB storage",
123 "Basic analytics",
124 "Email support",
125 "Standard integrations",
126 ],
127 icon: Zap,
128 color: "blue",
129 },
130 {
131 id: "professional",
132 name: "Professional",
133 description: "Advanced features for growing businesses",
134 price: { monthly: 99, yearly: 990 },
135 features: [
136 "Up to 25 team members",
137 "100GB storage",
138 "Advanced analytics",
139 "Priority support",
140 "Custom integrations",
141 "API access",
142 "Advanced security",
143 ],
144 isPopular: true,
145 icon: Crown,
146 color: "purple",
147 },
148 {
149 id: "enterprise",
150 name: "Enterprise",
151 description: "Complete solution for large organizations",
152 price: { monthly: 299, yearly: 2990 },
153 features: [
154 "Unlimited team members",
155 "Unlimited storage",
156 "Custom analytics",
157 "24/7 dedicated support",
158 "White-label options",
159 "Custom development",
160 "SLA guarantee",
161 "Advanced compliance",
162 ],
163 icon: Building,
164 color: "emerald",
165 },
166];
167
168const addOns: AddOn[] = [
169 {
170 id: "extra-storage",
171 name: "Extra Storage",
172 description: "Additional 100GB storage per month",
173 price: { monthly: 15, yearly: 150 },
174 icon: Package,
175 },
176 {
177 id: "premium-support",
178 name: "Premium Support",
179 description: "24/7 phone and chat support",
180 price: { monthly: 25, yearly: 250 },
181 icon: HelpCircle,
182 },
183 {
184 id: "advanced-analytics",
185 name: "Advanced Analytics",
186 description: "Custom reports and data insights",
187 price: { monthly: 35, yearly: 350 },
188 icon: TrendingUp,
189 },
190];
191
192function Sidebar({ className = "" }: SidebarProps) {
193 const [isOpen, setIsOpen] = useState(false);
194 const [isCollapsed, setIsCollapsed] = useState(false);
195 const [activeItem, setActiveItem] = useState("billing");
196
197 useEffect(() => {
198 const handleResize = () => {
199 if (window.innerWidth >= 768) {
200 setIsOpen(true);
201 } else {
202 setIsOpen(false);
203 }
204 };
205
206 handleResize();
207 window.addEventListener("resize", handleResize);
208 return () => window.removeEventListener("resize", handleResize);
209 }, []);
210
211 const toggleSidebar = () => setIsOpen(!isOpen);
212 const toggleCollapse = () => setIsCollapsed(!isCollapsed);
213
214 const handleItemClick = (itemId: string) => {
215 setActiveItem(itemId);
216 if (window.innerWidth < 768) {
217 setIsOpen(false);
218 }
219 };
220
221 return (
222 <>
223 <button
224 onClick={toggleSidebar}
225 className="fixed top-6 left-6 z-50 p-3 rounded-lg bg-background shadow-md border border-border md:hidden hover:bg-accent transition-all duration-200"
226 aria-label="Toggle sidebar"
227 >
228 {isOpen ? (
229 <X className="h-5 w-5 text-foreground" />
230 ) : (
231 <Menu className="h-5 w-5 text-foreground" />
232 )}
233 </button>
234
235 {isOpen && (
236 <div
237 className="fixed inset-0 bg-black/40 backdrop-blur-sm z-30 md:hidden transition-opacity duration-300"
238 onClick={toggleSidebar}
239 />
240 )}
241
242 <div
243 className={`
244 fixed top-0 left-0 h-full bg-background border-r border-border z-40 transition-all duration-300 ease-in-out flex flex-col
245 ${isOpen ? "translate-x-0" : "-translate-x-full"}
246 ${isCollapsed ? "w-20" : "w-72"}
247 md:translate-x-0 md:static md:z-auto
248 ${className}
249 `}
250 >
251 <div className="flex items-center justify-between p-5 border-b border-border bg-muted/30">
252 {!isCollapsed && (
253 <div className="flex items-center space-x-2.5">
254 <div className="w-9 h-9 bg-primary rounded-lg flex items-center justify-center shadow-sm">
255 <span className="text-primary-foreground font-bold text-base">
256 B
257 </span>
258 </div>
259 <div className="flex flex-col">
260 <span className="font-semibold text-foreground text-base">
261 BizCorp
262 </span>
263 <span className="text-xs text-muted-foreground">
264 Admin Dashboard
265 </span>
266 </div>
267 </div>
268 )}
269
270 {isCollapsed && (
271 <div className="w-9 h-9 bg-primary rounded-lg flex items-center justify-center mx-auto shadow-sm">
272 <span className="text-primary-foreground font-bold text-base">
273 B
274 </span>
275 </div>
276 )}
277
278 <button
279 onClick={toggleCollapse}
280 className="hidden md:flex p-1.5 rounded-md hover:bg-accent transition-all duration-200"
281 aria-label={isCollapsed ? "Expand sidebar" : "Collapse sidebar"}
282 >
283 {isCollapsed ? (
284 <ChevronRight className="h-4 w-4 text-muted-foreground" />
285 ) : (
286 <ChevronLeft className="h-4 w-4 text-muted-foreground" />
287 )}
288 </button>
289 </div>
290
291 {!isCollapsed && (
292 <div className="px-4 py-3">
293 <div className="relative">
294 <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground" />
295 <input
296 type="text"
297 placeholder="Search..."
298 className="w-full pl-9 pr-4 py-2 bg-muted border border-border rounded-md text-sm placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:border-transparent transition-all duration-200"
299 />
300 </div>
301 </div>
302 )}
303
304 <nav className="flex-1 px-3 py-2 overflow-y-auto">
305 <ul className="space-y-0.5">
306 {navigationItems.map((item) => {
307 const Icon = item.icon;
308 const isActive = activeItem === item.id;
309
310 return (
311 <li key={item.id}>
312 <button
313 onClick={() => handleItemClick(item.id)}
314 className={`
315 w-full flex items-center space-x-2.5 px-3 py-2.5 rounded-md text-left transition-all duration-200 group relative
316 ${
317 isActive
318 ? "bg-primary/10 text-primary"
319 : "text-muted-foreground hover:bg-accent hover:text-foreground"
320 }
321 ${isCollapsed ? "justify-center px-2" : ""}
322 `}
323 title={isCollapsed ? item.name : undefined}
324 >
325 <div className="flex items-center justify-center min-w-[24px]">
326 <Icon
327 className={`
328 h-4.5 w-4.5 flex-shrink-0
329 ${
330 isActive
331 ? "text-primary"
332 : "text-muted-foreground group-hover:text-foreground"
333 }
334 `}
335 />
336 </div>
337
338 {!isCollapsed && (
339 <div className="flex items-center justify-between w-full">
340 <span
341 className={`text-sm ${
342 isActive ? "font-medium" : "font-normal"
343 }`}
344 >
345 {item.name}
346 </span>
347 {item.badge && (
348 <Badge
349 variant={isActive ? "default" : "secondary"}
350 className="text-xs"
351 >
352 {item.badge}
353 </Badge>
354 )}
355 </div>
356 )}
357
358 {isCollapsed && item.badge && (
359 <div className="absolute top-1 right-1 w-4 h-4 flex items-center justify-center rounded-full bg-primary border border-background">
360 <span className="text-[10px] font-medium text-primary-foreground">
361 {parseInt(item.badge) > 9 ? "9+" : item.badge}
362 </span>
363 </div>
364 )}
365 </button>
366 </li>
367 );
368 })}
369 </ul>
370 </nav>
371
372 <div className="mt-auto border-t border-border">
373 <div
374 className={`border-b border-border bg-muted/30 ${
375 isCollapsed ? "py-3 px-2" : "p-3"
376 }`}
377 >
378 {!isCollapsed ? (
379 <div className="flex items-center px-3 py-2 rounded-md bg-background hover:bg-accent transition-colors duration-200">
380 <div className="w-8 h-8 bg-muted rounded-full flex items-center justify-center">
381 <span className="text-foreground font-medium text-sm">
382 JD
383 </span>
384 </div>
385 <div className="flex-1 min-w-0 ml-2.5">
386 <p className="text-sm font-medium text-foreground truncate">
387 John Doe
388 </p>
389 <p className="text-xs text-muted-foreground truncate">
390 Admin
391 </p>
392 </div>
393 <div
394 className="w-2 h-2 bg-green-500 rounded-full ml-2"
395 title="Online"
396 />
397 </div>
398 ) : (
399 <div className="flex justify-center">
400 <div className="relative">
401 <div className="w-9 h-9 bg-muted rounded-full flex items-center justify-center">
402 <span className="text-foreground font-medium text-sm">
403 JD
404 </span>
405 </div>
406 <div className="absolute -bottom-1 -right-1 w-3 h-3 bg-green-500 rounded-full border-2 border-background" />
407 </div>
408 </div>
409 )}
410 </div>
411
412 <div className="p-3">
413 <button
414 onClick={() => handleItemClick("logout")}
415 className={`
416 w-full flex items-center rounded-md text-left transition-all duration-200 group
417 text-destructive hover:bg-destructive/10
418 ${
419 isCollapsed
420 ? "justify-center p-2.5"
421 : "space-x-2.5 px-3 py-2.5"
422 }
423 `}
424 title={isCollapsed ? "Logout" : undefined}
425 >
426 <div className="flex items-center justify-center min-w-[24px]">
427 <LogOut className="h-4.5 w-4.5 flex-shrink-0" />
428 </div>
429
430 {!isCollapsed && <span className="text-sm">Logout</span>}
431 </button>
432 </div>
433 </div>
434 </div>
435 </>
436 );
437}
438
439function CustomerAdminDashboard() {
440 const [selectedPlan, setSelectedPlan] = useState<string>("professional");
441 const [selectedAddOns, setSelectedAddOns] = useState<string[]>([
442 "premium-support",
443 ]);
444 const [isYearly, setIsYearly] = useState(false);
445 const [isCollapsed, setIsCollapsed] = useState(false);
446
447 const currentPlan = plans.find((p) => p.id === selectedPlan);
448
449 const bills: Bill[] = [
450 {
451 id: "1",
452 description: `${currentPlan?.name} Plan - ${
453 isYearly ? "Annual" : "Monthly"
454 }`,
455 amount: isYearly
456 ? currentPlan?.price.yearly || 0
457 : currentPlan?.price.monthly || 0,
458 dueDate: "2024-02-15",
459 status: "pending",
460 type: "plan",
461 },
462 ...selectedAddOns.map((addonId, index) => {
463 const addon = addOns.find((a) => a.id === addonId);
464 return {
465 id: `addon-${index}`,
466 description: `${addon?.name} - ${isYearly ? "Annual" : "Monthly"}`,
467 amount: isYearly ? addon?.price.yearly || 0 : addon?.price.monthly || 0,
468 dueDate: "2024-02-15",
469 status: "pending" as const,
470 type: "addon" as const,
471 };
472 }),
473 {
474 id: "2",
475 description: "Professional Plan - Monthly (Previous)",
476 amount: 99,
477 dueDate: "2024-01-15",
478 status: "paid",
479 type: "plan",
480 },
481 ];
482
483 const totalAmount = bills
484 .filter((bill) => bill.status === "pending")
485 .reduce((sum, bill) => sum + bill.amount, 0);
486
487 const handlePlanSelect = (planId: string) => {
488 setSelectedPlan(planId);
489 };
490
491 const handleAddOnToggle = (addonId: string) => {
492 setSelectedAddOns((prev) =>
493 prev.includes(addonId)
494 ? prev.filter((id) => id !== addonId)
495 : [...prev, addonId]
496 );
497 };
498
499 const getStatusColor = (status: string) => {
500 switch (status) {
501 case "paid":
502 return "bg-green-100 text-green-800 border-green-200";
503 case "pending":
504 return "bg-yellow-100 text-yellow-800 border-yellow-200";
505 case "overdue":
506 return "bg-red-100 text-red-800 border-red-200";
507 default:
508 return "bg-gray-100 text-gray-800 border-gray-200";
509 }
510 };
511
512 return (
513 <div className="flex h-screen bg-background">
514 <Sidebar />
515
516 <div
517 className={`flex-1 transition-all duration-300 ${
518 isCollapsed ? "ml-20" : "ml-72"
519 } overflow-auto`}
520 >
521 <div className="p-8">
522 <div className="mb-8">
523 <h1 className="text-3xl font-bold text-foreground mb-2">
524 Billing & Plans
525 </h1>
526 <p className="text-muted-foreground">
527 Manage your subscription plans and billing information
528 </p>
529 </div>
530
531 <Tabs defaultValue="plans" className="space-y-6">
532 <TabsList className="grid w-full grid-cols-3 max-w-md">
533 <TabsTrigger value="plans">Plans</TabsTrigger>
534 <TabsTrigger value="addons">Add-ons</TabsTrigger>
535 <TabsTrigger value="billing">Billing</TabsTrigger>
536 </TabsList>
537
538 <TabsContent value="plans" className="space-y-6">
539 <Card className="p-6">
540 <div className="flex items-center justify-between mb-6">
541 <h2 className="text-xl font-semibold">Choose Your Plan</h2>
542 <div className="flex items-center space-x-3">
543 <span
544 className={`text-sm ${
545 !isYearly ? "text-foreground" : "text-muted-foreground"
546 }`}
547 >
548 Monthly
549 </span>
550 <Switch checked={isYearly} onCheckedChange={setIsYearly} />
551 <span
552 className={`text-sm ${
553 isYearly ? "text-foreground" : "text-muted-foreground"
554 }`}
555 >
556 Yearly
557 </span>
558 {isYearly && (
559 <Badge variant="secondary" className="ml-2">
560 Save 20%
561 </Badge>
562 )}
563 </div>
564 </div>
565
566 <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
567 {plans.map((plan) => {
568 const Icon = plan.icon;
569 const isSelected = selectedPlan === plan.id;
570
571 return (
572 <Card
573 key={plan.id}
574 className={`relative p-6 cursor-pointer transition-all hover:shadow-lg ${
575 isSelected ? "ring-2 ring-primary border-primary" : ""
576 } ${plan.isPopular ? "border-primary/50" : ""}`}
577 onClick={() => handlePlanSelect(plan.id)}
578 >
579 {plan.isPopular && (
580 <Badge className="absolute -top-3 left-1/2 transform -translate-x-1/2">
581 Most Popular
582 </Badge>
583 )}
584
585 <div className="text-center mb-4">
586 <div
587 className={`w-12 h-12 mx-auto mb-3 rounded-lg bg-${plan.color}-100 flex items-center justify-center`}
588 >
589 <Icon
590 className={`h-6 w-6 text-${plan.color}-600`}
591 />
592 </div>
593 <h3 className="text-lg font-semibold">{plan.name}</h3>
594 <p className="text-sm text-muted-foreground mt-1">
595 {plan.description}
596 </p>
597 </div>
598
599 <div className="text-center mb-6">
600 <div className="text-3xl font-bold">
601 ${isYearly ? plan.price.yearly : plan.price.monthly}
602 </div>
603 <div className="text-sm text-muted-foreground">
604 per {isYearly ? "year" : "month"}
605 </div>
606 {isYearly && (
607 <div className="text-sm text-green-600 mt-1">
608 Save $
609 {plan.price.monthly * 12 - plan.price.yearly}/year
610 </div>
611 )}
612 </div>
613
614 <ul className="space-y-2 mb-6">
615 {plan.features.map((feature, index) => (
616 <li
617 key={index}
618 className="flex items-center text-sm"
619 >
620 <Check className="h-4 w-4 text-green-500 mr-2 flex-shrink-0" />
621 {feature}
622 </li>
623 ))}
624 </ul>
625
626 <Button
627 className="w-full"
628 variant={isSelected ? "default" : "outline"}
629 >
630 {isSelected ? "Current Plan" : "Select Plan"}
631 </Button>
632 </Card>
633 );
634 })}
635 </div>
636 </Card>
637 </TabsContent>
638
639 <TabsContent value="addons" className="space-y-6">
640 <Card className="p-6">
641 <h2 className="text-xl font-semibold mb-6">
642 Available Add-ons
643 </h2>
644
645 <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
646 {addOns.map((addon) => {
647 const Icon = addon.icon;
648 const isSelected = selectedAddOns.includes(addon.id);
649
650 return (
651 <Card
652 key={addon.id}
653 className={`p-6 cursor-pointer transition-all hover:shadow-md ${
654 isSelected ? "ring-2 ring-primary border-primary" : ""
655 }`}
656 onClick={() => handleAddOnToggle(addon.id)}
657 >
658 <div className="flex items-start justify-between mb-4">
659 <div className="w-10 h-10 rounded-lg bg-muted flex items-center justify-center">
660 <Icon className="h-5 w-5 text-foreground" />
661 </div>
662 <Switch
663 checked={isSelected}
664 onCheckedChange={() => handleAddOnToggle(addon.id)}
665 />
666 </div>
667
668 <h3 className="font-semibold mb-2">{addon.name}</h3>
669 <p className="text-sm text-muted-foreground mb-4">
670 {addon.description}
671 </p>
672
673 <div className="text-lg font-bold">
674 ${isYearly ? addon.price.yearly : addon.price.monthly}
675 <span className="text-sm font-normal text-muted-foreground">
676 /{isYearly ? "year" : "month"}
677 </span>
678 </div>
679 </Card>
680 );
681 })}
682 </div>
683 </Card>
684 </TabsContent>
685
686 <TabsContent value="billing" className="space-y-6">
687 <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
688 <div className="lg:col-span-2">
689 <Card className="p-6">
690 <div className="flex items-center justify-between mb-6">
691 <h2 className="text-xl font-semibold">Current Bills</h2>
692 <div className="flex space-x-2">
693 <Button variant="outline" size="sm">
694 <Filter className="h-4 w-4 mr-2" />
695 Filter
696 </Button>
697 <Button variant="outline" size="sm">
698 <Download className="h-4 w-4 mr-2" />
699 Export
700 </Button>
701 </div>
702 </div>
703
704 <div className="space-y-4">
705 {bills.map((bill) => (
706 <div
707 key={bill.id}
708 className="flex items-center justify-between p-4 border border-border rounded-lg"
709 >
710 <div className="flex items-center space-x-4">
711 <div
712 className={`w-10 h-10 rounded-lg flex items-center justify-center ${
713 bill.type === "plan"
714 ? "bg-primary/10"
715 : "bg-secondary/10"
716 }`}
717 >
718 {bill.type === "plan" ? (
719 <CreditCard className="h-5 w-5 text-primary" />
720 ) : (
721 <Package className="h-5 w-5 text-secondary-foreground" />
722 )}
723 </div>
724 <div>
725 <h3 className="font-medium">
726 {bill.description}
727 </h3>
728 <p className="text-sm text-muted-foreground">
729 Due: {bill.dueDate}
730 </p>
731 </div>
732 </div>
733
734 <div className="flex items-center space-x-4">
735 <div className="text-right">
736 <div className="font-semibold">
737 ${bill.amount}
738 </div>
739 <Badge
740 variant="outline"
741 className={`text-xs ${getStatusColor(
742 bill.status
743 )}`}
744 >
745 {bill.status}
746 </Badge>
747 </div>
748 {bill.status === "pending" && (
749 <Button size="sm">Pay Now</Button>
750 )}
751 </div>
752 </div>
753 ))}
754 </div>
755 </Card>
756 </div>
757
758 <div className="space-y-6">
759 <Card className="p-6">
760 <h3 className="font-semibold mb-4">Billing Summary</h3>
761 <div className="space-y-3">
762 <div className="flex justify-between">
763 <span className="text-muted-foreground">
764 Current Plan
765 </span>
766 <span className="font-medium">{currentPlan?.name}</span>
767 </div>
768 <div className="flex justify-between">
769 <span className="text-muted-foreground">
770 Billing Cycle
771 </span>
772 <span className="font-medium">
773 {isYearly ? "Yearly" : "Monthly"}
774 </span>
775 </div>
776 <div className="flex justify-between">
777 <span className="text-muted-foreground">
778 Active Add-ons
779 </span>
780 <span className="font-medium">
781 {selectedAddOns.length}
782 </span>
783 </div>
784 <Separator />
785 <div className="flex justify-between text-lg font-semibold">
786 <span>Total Due</span>
787 <span>${totalAmount}</span>
788 </div>
789 </div>
790
791 <Button className="w-full mt-4">
792 <CreditCard className="h-4 w-4 mr-2" />
793 Pay ${totalAmount}
794 </Button>
795 </Card>
796
797 <Card className="p-6">
798 <h3 className="font-semibold mb-4">Quick Actions</h3>
799 <div className="space-y-3">
800 <Button
801 variant="outline"
802 className="w-full justify-start"
803 >
804 <FileText className="h-4 w-4 mr-2" />
805 Download Invoice
806 </Button>
807 <Button
808 variant="outline"
809 className="w-full justify-start"
810 >
811 <Settings className="h-4 w-4 mr-2" />
812 Payment Methods
813 </Button>
814 <Button
815 variant="outline"
816 className="w-full justify-start"
817 >
818 <Calendar className="h-4 w-4 mr-2" />
819 Billing History
820 </Button>
821 </div>
822 </Card>
823
824 <Card className="p-6 bg-muted/50">
825 <div className="flex items-start space-x-3">
826 <AlertCircle className="h-5 w-5 text-amber-500 mt-0.5" />
827 <div>
828 <h4 className="font-medium text-sm">
829 Payment Reminder
830 </h4>
831 <p className="text-xs text-muted-foreground mt-1">
832 Your next payment of ${totalAmount} is due on February
833 15, 2024.
834 </p>
835 </div>
836 </div>
837 </Card>
838 </div>
839 </div>
840 </TabsContent>
841 </Tabs>
842 </div>
843 </div>
844 </div>
845 );
846}
847
848export default CustomerAdminDashboard;
Dependencies
External Libraries
lucide-reactreact
Shadcn/UI Components
badgebuttoncardseparatorswitchtabs