diff --git a/frontend/app/setup/layout.tsx b/frontend/app/setup/layout.tsx index 393f507..d391981 100644 --- a/frontend/app/setup/layout.tsx +++ b/frontend/app/setup/layout.tsx @@ -1,4 +1,5 @@ -import { AppSidebar } from "@/components/app-sidebar"; +import { AppSidebar } from "@/components/sidebar/app-sidebar"; +import { ThemeToggle } from "@/components/theme-toggle"; import { Breadcrumb, BreadcrumbItem, @@ -22,6 +23,7 @@ export default function AppLayout({
+ diff --git a/frontend/components/app-sidebar.tsx b/frontend/components/app-sidebar.tsx deleted file mode 100644 index 73989cb..0000000 --- a/frontend/components/app-sidebar.tsx +++ /dev/null @@ -1,144 +0,0 @@ -"use client"; -import { - Sidebar, - SidebarContent, - SidebarGroup, - SidebarGroupContent, - SidebarGroupLabel, - SidebarMenu, - SidebarMenuButton, - SidebarMenuItem, -} from "@/components/ui/sidebar"; -import { - Calendar, - Home, - Settings, - Sun, - Moon, - LogOut, - Wrench, - FileText, - Bot, - Factory, - Store, -} from "lucide-react"; -import { usePathname } from "next/navigation"; -import { useState } from "react"; -import Image from "next/image"; - -export function AppSidebar() { - const pathname = usePathname(); - const [darkMode, setDarkMode] = useState(false); - const items = [ - { - title: "Dashboard", - url: "#", - icon: Home, - }, - { - title: "SetUp", - url: "#", - icon: Wrench, - }, - { - title: "Management", - url: "#", - icon: Calendar, - }, - { - title: "Work Order Management", - url: "#", - icon: FileText, - }, - { - title: "AI-Chatbot", - url: "#", - icon: Bot, - }, - { - title: "Inventory Management", - url: "#", - icon: Factory, - }, - { - title: "Marketplace", - url: "#", - icon: Store, - }, - { - title: "Settings", - url: "#", - icon: Settings, - }, - ]; - - return ( - - {/* Menu Items */} - - - -
- ForFarm Logo - -

ForFarm

-
-
- - - - {items.map((item) => { - const isActive = pathname === item.url; - - return ( - - - - - {item.title} - - - - ); - })} - - -
-
- - {/* Bottom Section: Theme Toggle & Logout */} -
- {/* Theme Toggle */} - - - {/* Logout Button */} - -
-
- ); -} diff --git a/frontend/components/sidebar/app-sidebar.tsx b/frontend/components/sidebar/app-sidebar.tsx new file mode 100644 index 0000000..a2a1186 --- /dev/null +++ b/frontend/components/sidebar/app-sidebar.tsx @@ -0,0 +1,152 @@ +"use client"; + +import * as React from "react"; +import { + AudioWaveform, + BookOpen, + Bot, + Command, + Frame, + GalleryVerticalEnd, + Map, + PieChart, + Settings2, + SquareTerminal, +} from "lucide-react"; + +import { NavMain } from "./nav-main"; +import { NavProjects } from "./nav-projects"; +import { NavUser } from "./nav-user"; +import { TeamSwitcher } from "./team-switcher"; +import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarRail } from "@/components/ui/sidebar"; + +const data = { + user: { + name: "shadcn", + email: "m@example.com", + avatar: "/avatars/shadcn.jpg", + }, + teams: [ + { + name: "Farm 1", + logo: GalleryVerticalEnd, + plan: "Hatyai", + }, + { + name: "Farm 2", + logo: AudioWaveform, + plan: "Songkla", + }, + { + name: "Farm 3", + logo: Command, + plan: "Layong", + }, + ], + navMain: [ + { + title: "Dashboard", + url: "#", + icon: SquareTerminal, + isActive: true, + items: [ + { + title: "Analytic", + url: "#", + }, + ], + }, + { + title: "AI Chatbot", + url: "#", + icon: Bot, + items: [ + { + title: "Main model", + url: "#", + }, + ], + }, + { + title: "Documentation", + url: "#", + icon: BookOpen, + items: [ + { + title: "Introduction", + url: "#", + }, + { + title: "Get Started", + url: "#", + }, + { + title: "Tutorials", + url: "#", + }, + { + title: "Changelog", + url: "#", + }, + ], + }, + { + title: "Settings", + url: "#", + icon: Settings2, + items: [ + { + title: "General", + url: "#", + }, + { + title: "Team", + url: "#", + }, + { + title: "Billing", + url: "#", + }, + { + title: "Limits", + url: "#", + }, + ], + }, + ], + projects: [ + { + name: "Crops 1", + url: "#", + icon: Frame, + }, + { + name: "Crops 2", + url: "#", + icon: PieChart, + }, + { + name: "Crops 3", + url: "#", + icon: Map, + }, + ], +}; + +export function AppSidebar({ ...props }: React.ComponentProps) { + return ( + + + + + + + + + + + + + + ); +} diff --git a/frontend/components/sidebar/nav-main.tsx b/frontend/components/sidebar/nav-main.tsx new file mode 100644 index 0000000..20ace28 --- /dev/null +++ b/frontend/components/sidebar/nav-main.tsx @@ -0,0 +1,64 @@ +"use client"; + +import { ChevronRight, type LucideIcon } from "lucide-react"; + +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; +import { + SidebarGroup, + SidebarGroupLabel, + SidebarMenu, + SidebarMenuButton, + SidebarMenuItem, + SidebarMenuSub, + SidebarMenuSubButton, + SidebarMenuSubItem, +} from "@/components/ui/sidebar"; + +export function NavMain({ + items, +}: { + items: { + title: string; + url: string; + icon?: LucideIcon; + isActive?: boolean; + items?: { + title: string; + url: string; + }[]; + }[]; +}) { + return ( + + Platform + + {items.map((item) => ( + + + + + {item.icon && } + {item.title} + + + + + + {item.items?.map((subItem) => ( + + + + {subItem.title} + + + + ))} + + + + + ))} + + + ); +} diff --git a/frontend/components/sidebar/nav-projects.tsx b/frontend/components/sidebar/nav-projects.tsx new file mode 100644 index 0000000..921c0d3 --- /dev/null +++ b/frontend/components/sidebar/nav-projects.tsx @@ -0,0 +1,82 @@ +"use client"; + +import { Folder, Forward, MoreHorizontal, Trash2, type LucideIcon } from "lucide-react"; + +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { + SidebarGroup, + SidebarGroupLabel, + SidebarMenu, + SidebarMenuAction, + SidebarMenuButton, + SidebarMenuItem, + useSidebar, +} from "@/components/ui/sidebar"; + +export function NavProjects({ + projects, +}: { + projects: { + name: string; + url: string; + icon: LucideIcon; + }[]; +}) { + const { isMobile } = useSidebar(); + + return ( + + Projects + + {projects.map((item) => ( + + + + + {item.name} + + + + + + + More + + + + + + View Project + + + + Share Project + + + + + Delete Project + + + + + ))} + + + + More + + + + + ); +} diff --git a/frontend/components/sidebar/nav-user.tsx b/frontend/components/sidebar/nav-user.tsx new file mode 100644 index 0000000..3c4561e --- /dev/null +++ b/frontend/components/sidebar/nav-user.tsx @@ -0,0 +1,100 @@ +"use client"; + +import { BadgeCheck, Bell, ChevronsUpDown, CreditCard, LogOut, Sparkles } from "lucide-react"; + +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, useSidebar } from "@/components/ui/sidebar"; + +import { useLogout } from "@/hooks/useLogout"; + +export function NavUser({ + user, +}: { + user: { + name: string; + email: string; + avatar: string; + }; +}) { + const { isMobile } = useSidebar(); + + const logout = useLogout(); + + return ( + + + + + + + + CN + +
+ {user.name} + {user.email} +
+ +
+
+ + +
+ + + CN + +
+ {user.name} + {user.email} +
+
+
+ + + + + Upgrade to Pro + + + + + + + Account + + + + Billing + + + + Notifications + + + + + + Log out + +
+
+
+
+ ); +} diff --git a/frontend/components/sidebar/team-switcher.tsx b/frontend/components/sidebar/team-switcher.tsx new file mode 100644 index 0000000..1c6c043 --- /dev/null +++ b/frontend/components/sidebar/team-switcher.tsx @@ -0,0 +1,74 @@ +"use client"; + +import * as React from "react"; +import { ChevronsUpDown, Plus } from "lucide-react"; + +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, useSidebar } from "@/components/ui/sidebar"; + +export function TeamSwitcher({ + teams, +}: { + teams: { + name: string; + logo: React.ElementType; + plan: string; + }[]; +}) { + const { isMobile } = useSidebar(); + const [activeTeam, setActiveTeam] = React.useState(teams[0]); + + return ( + + + + + +
+ +
+
+ {activeTeam.name} + {activeTeam.plan} +
+ +
+
+ + Teams + {teams.map((team, index) => ( + setActiveTeam(team)} className="gap-2 p-2"> +
+ +
+ {team.name} + ⌘{index + 1} +
+ ))} + + +
+ +
+
Add team
+
+
+
+
+
+ ); +} diff --git a/frontend/components/ui/collapsible.tsx b/frontend/components/ui/collapsible.tsx new file mode 100644 index 0000000..9fa4894 --- /dev/null +++ b/frontend/components/ui/collapsible.tsx @@ -0,0 +1,11 @@ +"use client" + +import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" + +const Collapsible = CollapsiblePrimitive.Root + +const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger + +const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent + +export { Collapsible, CollapsibleTrigger, CollapsibleContent }