From 1d458886dd963ee8472b65339f3ab49bd52420b0 Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (Pragmatismo)" Date: Sat, 21 Jun 2025 20:30:28 -0300 Subject: [PATCH] feat: add new UI components including Drawer, InputOTP, Pagination, Sidebar, Sonner, and ToggleGroup - Implemented Drawer component for modal-like functionality. - Added InputOTP component for handling one-time password inputs. - Created Pagination component for navigating through paginated content. - Developed Sidebar component with collapsible and mobile-friendly features. - Integrated Sonner for toast notifications with theme support. - Introduced ToggleGroup for grouping toggle buttons with context support. - Added useIsMobile hook to determine mobile view based on screen width. --- app/dashboard/page.tsx | 292 ++++++++++-- app/mail/page.tsx | 1000 ++++++++++++++++++++-------------------- 2 files changed, 760 insertions(+), 532 deletions(-) diff --git a/app/dashboard/page.tsx b/app/dashboard/page.tsx index 095d531..e8cd2f2 100644 --- a/app/dashboard/page.tsx +++ b/app/dashboard/page.tsx @@ -1,33 +1,259 @@ -import React from 'react'; -import { TeamSwitcher } from './components/TeamSwitcher'; -import { MainNav } from './components/MainNav'; -import { Search } from './components/Search'; -import { UserNav } from './components/UserNav'; -import { CalendarDateRangePicker } from './components/DateRangePicker'; -import { Overview } from './components/Overview'; -import { RecentSales } from './components/RecentSales'; +"use client"; +import React, { useState } from 'react'; -export default function DashboardScreen() { - return ( -
-
-
- - -
- - +const Dashboard = () => { + const [dateRange, setDateRange] = useState({ + startDate: new Date(), + endDate: new Date() + }); + const [selectedTeam, setSelectedTeam] = useState({ + label: "Alicia Koch", + value: "personal" + }); + const [teamSwitcherOpen, setTeamSwitcherOpen] = useState(false); + const [showNewTeamDialog, setShowNewTeamDialog] = useState(false); + const [userNavOpen, setUserNavOpen] = useState(false); + + const formatDate = (date) => { + return date.toLocaleDateString('en-US', { + month: 'short', + day: '2-digit', + year: 'numeric' + }); + }; + + const salesData = [ + { name: "Olivia Martin", email: "olivia.martin@email.com", amount: "+$1,999.00" }, + { name: "Jackson Lee", email: "jackson.lee@email.com", amount: "+$39.00" }, + { name: "Isabella Nguyen", email: "isabella.nguyen@email.com", amount: "+$299.00" }, + { name: "William Kim", email: "will@email.com", amount: "+$99.00" }, + { name: "Sofia Davis", email: "sofia.davis@email.com", amount: "+$39.00" }, + ]; + + const groups = [ + { + label: "Personal Account", + teams: [ + { label: "Alicia Koch", value: "personal" }, + ], + }, + { + label: "Teams", + teams: [ + { label: "Acme Inc.", value: "acme-inc" }, + { label: "Monsters Inc.", value: "monsters" }, + ], + }, + ]; + + const CalendarDateRangePicker = () => ( +
+ + to + +
+ ); + + const MainNav = () => ( + + ); + + const Search = () => ( +
+ + + + +
+ ); + + const TeamSwitcher = () => ( +
+ + + {teamSwitcherOpen && ( +
+
+ +
+ {groups.map((group) => ( +
+

{group.label}

+ {group.teams.map((team) => ( + + ))} +
+ ))} +
+
-
+ )} + {showNewTeamDialog && ( +
+
+

Create team

+ +
+ + +
+
+
+ )} +
+ ); + + const UserNav = () => ( +
+ + + {userNavOpen && ( +
+
+

shadcn

+

m@example.com

+
+ {['Profile', 'Billing', 'Settings', 'New Team', 'Log out'].map((item) => ( + + ))} +
+ )} +
+ ); + + const Overview = () => ( +
+
+ {[100, 80, 60, 40, 20].map((height, index) => ( +
+ ))} +
+
+ ); + + const RecentSales = () => ( +
+ {salesData.map((item, index) => ( +
+
+
+ {item.name[0]} +
+
+

{item.name}

+

{item.email}

+
+
+ {item.amount} +
+ ))} +
+ ); + + return ( +
-s
-

Dashboard

+

Dashboard

-
@@ -40,26 +266,28 @@ s { title: "Sales", value: "+12,234", subtext: "+19% from last month" }, { title: "Active Now", value: "+573", subtext: "+201 since last hour" }, ].map((card, index) => ( -
-

{card.title}

-

{card.value}

-

{card.subtext}

+
+

{card.title}

+

{card.value}

+

{card.subtext}

))}
-
-

Overview

+
+

Overview

-
-

Recent Sales

-

You made 265 sales this month.

+
+

Recent Sales

+

You made 265 sales this month.

); -} +}; + +export default Dashboard; \ No newline at end of file diff --git a/app/mail/page.tsx b/app/mail/page.tsx index 7e955d5..42c25a8 100644 --- a/app/mail/page.tsx +++ b/app/mail/page.tsx @@ -1,525 +1,525 @@ -"use client" -import { accounts, mails } from "./data" + "use client" + import { accounts, mails } from "./data" -import * as React from "react" -import { - AlertCircle, Archive, ArchiveX, Clock, File, Forward, Inbox, Mail as MailIcon, - MessagesSquare, MoreVertical, Reply, ReplyAll, Search, Send, ShoppingCart, - Trash2, Users2, LucideIcon -} from "lucide-react" -import { useMail } from "./use-mail" -import { cn } from "@/lib/utils" -import { format, formatDistanceToNow, addDays, addHours, nextSaturday } from "date-fns" -import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" -import { Badge } from "@/components/ui/badge" -import { Button } from "@/components/ui/button" -import { Calendar } from "@/components/ui/calendar" -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu" -import { Input } from "@/components/ui/input" -import { Label } from "@/components/ui/label" -import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover" -import { - ResizableHandle, - ResizablePanel, - ResizablePanelGroup, -} from "@/components/ui/resizable" -import { ScrollArea } from "@/components/ui/scroll-area" -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select" -import { Separator } from "@/components/ui/separator" -import { Switch } from "@/components/ui/switch" -import { - Tabs, - TabsContent, - TabsList, - TabsTrigger, -} from "@/components/ui/tabs" -import { Textarea } from "@/components/ui/textarea" -import { - Tooltip, - TooltipContent, - TooltipTrigger, - TooltipProvider, -} from "@/components/ui/tooltip" + import * as React from "react" + import { + AlertCircle, Archive, ArchiveX, Clock, File, Forward, Inbox, Mail as MailIcon, + MessagesSquare, MoreVertical, Reply, ReplyAll, Search, Send, ShoppingCart, + Trash2, Users2, LucideIcon + } from "lucide-react" + import { useMail } from "./use-mail" + import { cn } from "@/lib/utils" + import { format, formatDistanceToNow, addDays, addHours, nextSaturday } from "date-fns" + import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" + import { Badge } from "@/components/ui/badge" + import { Button } from "@/components/ui/button" + import { Calendar } from "@/components/ui/calendar" + import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, + } from "@/components/ui/dropdown-menu" + import { Input } from "@/components/ui/input" + import { Label } from "@/components/ui/label" + import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover" + import { + ResizableHandle, + ResizablePanel, + ResizablePanelGroup, + } from "@/components/ui/resizable" + import { ScrollArea } from "@/components/ui/scroll-area" + import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, + } from "@/components/ui/select" + import { Separator } from "@/components/ui/separator" + import { Switch } from "@/components/ui/switch" + import { + Tabs, + TabsContent, + TabsList, + TabsTrigger, + } from "@/components/ui/tabs" + import { Textarea } from "@/components/ui/textarea" + import { + Tooltip, + TooltipContent, + TooltipTrigger, + TooltipProvider, + } from "@/components/ui/tooltip" -interface Account { - label: string - email: string - icon: React.ReactNode -} + interface Account { + label: string + email: string + icon: React.ReactNode + } -interface Mail { - id: string - name: string - email: string - subject: string - text: string - date: string - read: boolean - labels: string[] -} + interface Mail { + id: string + name: string + email: string + subject: string + text: string + date: string + read: boolean + labels: string[] + } -interface NavLink { - title: string - label?: string - icon: LucideIcon - variant: "default" | "ghost" -} + interface NavLink { + title: string + label?: string + icon: LucideIcon + variant: "default" | "ghost" + } -interface MailProps { - accounts: Account[] - mails: Mail[] - defaultLayout?: number[] - defaultCollapsed?: boolean - navCollapsedSize: number -} + interface MailProps { + accounts: Account[] + mails: Mail[] + defaultLayout?: number[] + defaultCollapsed?: boolean + navCollapsedSize: number + } -function MailComponent({ - accounts, - mails, - defaultLayout = [20, 32, 48], - defaultCollapsed = false, - navCollapsedSize, -}: MailProps) { - const [isCollapsed, setIsCollapsed] = React.useState(defaultCollapsed) - const [mail, setMail] = useMail() + function MailComponent({ + accounts, + mails, + defaultLayout = [20, 32, 48], + defaultCollapsed = false, + navCollapsedSize, + }: MailProps) { + const [isCollapsed, setIsCollapsed] = React.useState(defaultCollapsed) + const [mail, setMail] = useMail() - const navLinks: NavLink[] = [ - { title: "Inbox", label: "128", icon: Inbox, variant: "default" }, - { title: "Drafts", label: "9", icon: File, variant: "ghost" }, - { title: "Sent", label: "", icon: Send, variant: "ghost" }, - { title: "Junk", label: "23", icon: ArchiveX, variant: "ghost" }, - { title: "Trash", label: "", icon: Trash2, variant: "ghost" }, - { title: "Archive", label: "", icon: Archive, variant: "ghost" }, - { title: "Social", label: "972", icon: Users2, variant: "ghost" }, - { title: "Updates", label: "342", icon: AlertCircle, variant: "ghost" }, - { title: "Forums", label: "128", icon: MessagesSquare, variant: "ghost" }, - { title: "Shopping", label: "8", icon: ShoppingCart, variant: "ghost" }, - { title: "Promotions", label: "21", icon: Archive, variant: "ghost" } - ] + const navLinks: NavLink[] = [ + { title: "Inbox", label: "128", icon: Inbox, variant: "default" }, + { title: "Drafts", label: "9", icon: File, variant: "ghost" }, + { title: "Sent", label: "", icon: Send, variant: "ghost" }, + { title: "Junk", label: "23", icon: ArchiveX, variant: "ghost" }, + { title: "Trash", label: "", icon: Trash2, variant: "ghost" }, + { title: "Archive", label: "", icon: Archive, variant: "ghost" }, + { title: "Social", label: "972", icon: Users2, variant: "ghost" }, + { title: "Updates", label: "342", icon: AlertCircle, variant: "ghost" }, + { title: "Forums", label: "128", icon: MessagesSquare, variant: "ghost" }, + { title: "Shopping", label: "8", icon: ShoppingCart, variant: "ghost" }, + { title: "Promotions", label: "21", icon: Archive, variant: "ghost" } + ] - return ( - - - {/* Left Sidebar */} - setIsCollapsed(true)} - onResize={() => setIsCollapsed(false)} - className={cn(isCollapsed && "min-w-[50px] transition-all duration-300 ease-in-out")} + return ( + + -
- -
- -