diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 6317efa..90b0efc 100755 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,5 +1,6 @@ import type { Metadata } from "next"; import { Sora, IBM_Plex_Mono } from "next/font/google"; +import { ThemeProvider } from "@/components/theme-provider"; import "./globals.css"; const sora = Sora({ @@ -24,9 +25,11 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - + - {children} + + {children} + ); diff --git a/src/components/account-modal.tsx b/src/components/account-modal.tsx new file mode 100755 index 0000000..d34066e --- /dev/null +++ b/src/components/account-modal.tsx @@ -0,0 +1,131 @@ +"use client" + +import * as React from "react" +import { IconCamera } from "@tabler/icons-react" + +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" +import { Button } from "@/components/ui/button" +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { Separator } from "@/components/ui/separator" + +export function AccountModal({ + open, + onOpenChange, +}: { + open: boolean + onOpenChange: (open: boolean) => void +}) { + const [name, setName] = React.useState("Martine Vogel") + const [email, setEmail] = React.useState("martine@compass.io") + const [currentPassword, setCurrentPassword] = React.useState("") + const [newPassword, setNewPassword] = React.useState("") + const [confirmPassword, setConfirmPassword] = React.useState("") + + return ( + + + + Account Settings + + Manage your profile and security settings. + + + +
+
+
+ + + MV + + +
+
+

{name}

+

{email}

+
+
+ + + +
+

Profile

+
+ + setName(e.target.value)} + /> +
+
+ + setEmail(e.target.value)} + /> +
+
+ + + +
+

Change Password

+
+ + setCurrentPassword(e.target.value)} + placeholder="Enter current password" + /> +
+
+ + setNewPassword(e.target.value)} + placeholder="Enter new password" + /> +
+
+ + setConfirmPassword(e.target.value)} + placeholder="Confirm new password" + /> +
+
+
+ + + + + +
+
+ ) +} diff --git a/src/components/command-menu.tsx b/src/components/command-menu.tsx new file mode 100755 index 0000000..ab7dee9 --- /dev/null +++ b/src/components/command-menu.tsx @@ -0,0 +1,86 @@ +"use client" + +import * as React from "react" +import { useRouter } from "next/navigation" +import { useTheme } from "next-themes" +import { + IconDashboard, + IconFolder, + IconFiles, + IconCalendarStats, + IconSun, + IconSearch, +} from "@tabler/icons-react" + +import { + CommandDialog, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, +} from "@/components/ui/command" + +export function CommandMenu({ + open, + setOpen, +}: { + open: boolean + setOpen: (open: boolean) => void +}) { + const router = useRouter() + const { theme, setTheme } = useTheme() + + React.useEffect(() => { + function onKeyDown(e: KeyboardEvent) { + if (e.key === "k" && (e.metaKey || e.ctrlKey)) { + e.preventDefault() + setOpen(!open) + } + } + document.addEventListener("keydown", onKeyDown) + return () => document.removeEventListener("keydown", onKeyDown) + }, [open, setOpen]) + + function runCommand(cmd: () => void) { + setOpen(false) + cmd() + } + + return ( + + + + No results found. + + runCommand(() => router.push("/dashboard"))}> + + Dashboard + + runCommand(() => router.push("/dashboard/projects"))}> + + Projects + + runCommand(() => router.push("/dashboard/files"))}> + + Files + + runCommand(() => router.push("/dashboard/projects/demo-project-1/schedule"))}> + + Schedule + + + + runCommand(() => setTheme(theme === "dark" ? "light" : "dark"))}> + + Toggle theme + + runCommand(() => setOpen(true))}> + + Search files + + + + + ) +} diff --git a/src/components/nav-files.tsx b/src/components/nav-files.tsx index a0300cf..8eabd3a 100755 --- a/src/components/nav-files.tsx +++ b/src/components/nav-files.tsx @@ -54,7 +54,6 @@ export function NavFiles() { - @@ -66,7 +65,7 @@ export function NavFiles() { className={cn( activeView === item.view && pathname?.startsWith("/dashboard/files") && - "bg-sidebar-accent text-sidebar-accent-foreground" + "bg-sidebar-foreground/10 font-medium" )} > + + + + + + + + Back + + + + + + + + + + {projects.length === 0 ? ( + + + + + No projects + + + + ) : ( + projects.map((project) => ( + + + + + + {project.name} + + + + + )) + )} + + + + + ) +} diff --git a/src/components/nav-user.tsx b/src/components/nav-user.tsx index 7c49dc7..aac282e 100755 --- a/src/components/nav-user.tsx +++ b/src/components/nav-user.tsx @@ -1,5 +1,6 @@ "use client" +import * as React from "react" import { IconCreditCard, IconDotsVertical, @@ -28,6 +29,7 @@ import { SidebarMenuItem, useSidebar, } from "@/components/ui/sidebar" +import { AccountModal } from "@/components/account-modal" export function NavUser({ user, @@ -39,6 +41,7 @@ export function NavUser({ } }) { const { isMobile } = useSidebar() + const [accountOpen, setAccountOpen] = React.useState(false) return ( @@ -51,7 +54,7 @@ export function NavUser({ > - CN + MV
{user.name} @@ -72,7 +75,7 @@ export function NavUser({
- CN + MV
{user.name} @@ -84,7 +87,7 @@ export function NavUser({ - + setAccountOpen(true)}> Account @@ -105,6 +108,7 @@ export function NavUser({ + ) } diff --git a/src/components/notifications-popover.tsx b/src/components/notifications-popover.tsx new file mode 100755 index 0000000..00d3211 --- /dev/null +++ b/src/components/notifications-popover.tsx @@ -0,0 +1,85 @@ +"use client" + +import { + IconBell, + IconMessageCircle, + IconAlertCircle, + IconClipboardCheck, + IconClock, +} from "@tabler/icons-react" + +import { Button } from "@/components/ui/button" +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover" + +const notifications = [ + { + icon: IconClipboardCheck, + title: "Task assigned", + description: "You've been assigned to \"Update homepage layout\"", + time: "2m ago", + }, + { + icon: IconMessageCircle, + title: "New comment", + description: "Sarah left a comment on the brand assets file", + time: "15m ago", + }, + { + icon: IconAlertCircle, + title: "Deadline approaching", + description: "\"Q1 Report\" is due tomorrow", + time: "1h ago", + }, + { + icon: IconClock, + title: "Status changed", + description: "\"API Integration\" moved to In Review", + time: "3h ago", + }, +] + +export function NotificationsPopover() { + return ( + + + + + +
+

Notifications

+
+
+ {notifications.map((item) => ( +
+ +
+

{item.title}

+

+ {item.description} +

+

+ {item.time} +

+
+
+ ))} +
+
+ +
+
+
+ ) +} diff --git a/src/components/theme-provider.tsx b/src/components/theme-provider.tsx new file mode 100755 index 0000000..01dd6f4 --- /dev/null +++ b/src/components/theme-provider.tsx @@ -0,0 +1,19 @@ +"use client" + +import { ThemeProvider as NextThemesProvider } from "next-themes" + +export function ThemeProvider({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +}