ShadcnUI Vaults

Back to Blocks

Enterprise Billing & Plans Portal

Unknown Block

UnknownComponent

Enterprise Billing & Plans Portal

Enterprise dashboard for plan management, add-ons, and billing with navigation and analytics.

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

LICENSE

MIT License

Copyright (c) 2025 Aldhaneka

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Shadcn Vaults Project (CC BY-NC 4.0 with Internal Use Exception)

All user-submitted components in the '/blocks' directory are licensed under the Creative Commons Attribution-NonCommercial 4.0 International License (CC BY-NC 4.0),
with the following clarification and exception:

You are free to:
- Share — copy and redistribute the material in any medium or format
- Adapt — remix, transform, and build upon the material

Under these conditions:
- Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made.
- NonCommercial — You may NOT use the material for commercial redistribution, resale, or monetization.

🚫 You MAY NOT:
- Sell or redistribute the components individually or as part of a product (e.g. a UI kit, template marketplace, SaaS component library)
- Offer the components or derivative works in any paid tool, theme pack, or design system

✅ You MAY:
- Use the components in internal company tools, dashboards, or applications that are not sold as products
- Remix or adapt components for private or enterprise projects
- Use them in open-source non-commercial projects

This license encourages sharing, learning, and internal innovation — but prohibits using these components as a basis for monetized products.

Full license text: https://creativecommons.org/licenses/by-nc/4.0/

By submitting a component, contributors agree to these terms.

Contributors

Ramiro Godoy@milogodoy

Review Form Block

Aldhaneka@Aldhanekaa

Project Creator

For questions about licensing, please contact the project maintainers.