make a user menu links component
All checks were successful
Deploy / deploy (ubuntu-latest, 2.44.0) (push) Successful in 2m16s

This commit is contained in:
Braydon 2024-09-19 21:39:07 -04:00
parent 59c737ce7b
commit 41b7420ec6
11 changed files with 147 additions and 143 deletions

@ -1,18 +1,8 @@
"use client";
import { ReactElement } from "react";
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb";
import { User } from "@/app/types/user/user";
import { useUserContext } from "@/app/provider/user-provider";
import { UserState } from "@/app/store/user-store";
import { Separator } from "@/components/ui/separator";
import UserSettingsHeader from "@/components/dashboard/user/user-settings-header";
/**
* The user billing page.
@ -21,7 +11,7 @@ import { Separator } from "@/components/ui/separator";
*/
const UserBillingPage = (): ReactElement => (
<main className="w-[47rem] p-10 flex flex-col gap-5">
<Header />
<UserSettingsHeader title="Billing" />
{/* Content */}
<div className="flex flex-col gap-5">
@ -30,32 +20,4 @@ const UserBillingPage = (): ReactElement => (
</div>
</main>
);
const Header = (): ReactElement => {
const user: User | undefined = useUserContext(
(state: UserState) => state.user
);
return (
<div className="flex flex-col gap-1.5 select-none">
<h1 className="text-2xl font-bold">Billing</h1>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/dashboard">
Dashboard
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>{user?.username}</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Billing</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</div>
);
};
export default UserBillingPage;

@ -1,22 +1,12 @@
"use client";
import { ReactElement } from "react";
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb";
import { User } from "@/app/types/user/user";
import { useUserContext } from "@/app/provider/user-provider";
import { UserState } from "@/app/store/user-store";
import { Separator } from "@/components/ui/separator";
import AvatarSetting from "@/components/dashboard/user/profile/avatar-setting";
import UsernameSetting from "@/components/dashboard/user/profile/username-setting";
import EmailSetting from "@/components/dashboard/user/profile/email-setting";
import TierSetting from "@/components/dashboard/user/profile/tier-setting";
import UserSettingsHeader from "@/components/dashboard/user/user-settings-header";
/**
* The user profile page.
@ -25,7 +15,7 @@ import TierSetting from "@/components/dashboard/user/profile/tier-setting";
*/
const UserProfilePage = (): ReactElement => (
<main className="w-[47rem] p-10 flex flex-col gap-5">
<Header />
<UserSettingsHeader title="My Profile" />
{/* Content */}
<div className="flex flex-col gap-5">
@ -40,32 +30,4 @@ const UserProfilePage = (): ReactElement => (
</div>
</main>
);
const Header = (): ReactElement => {
const user: User | undefined = useUserContext(
(state: UserState) => state.user
);
return (
<div className="flex flex-col gap-1.5 select-none">
<h1 className="text-2xl font-bold">My Profile</h1>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/dashboard">
Dashboard
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>{user?.username}</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>My Profile</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</div>
);
};
export default UserProfilePage;

@ -1,19 +1,9 @@
"use client";
import { ReactElement } from "react";
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb";
import { User } from "@/app/types/user/user";
import { useUserContext } from "@/app/provider/user-provider";
import { UserState } from "@/app/store/user-store";
import { Separator } from "@/components/ui/separator";
import TFASetting from "@/components/dashboard/user/settings/tfa/tfa-setting";
import UserSettingsHeader from "@/components/dashboard/user/user-settings-header";
/**
* The user settings page.
@ -22,7 +12,7 @@ import TFASetting from "@/components/dashboard/user/settings/tfa/tfa-setting";
*/
const UserSettingsPage = (): ReactElement => (
<main className="w-[47rem] p-10 flex flex-col gap-5">
<Header />
<UserSettingsHeader title="Settings" />
{/* Content */}
<div className="flex flex-col gap-5">
@ -31,32 +21,4 @@ const UserSettingsPage = (): ReactElement => (
</div>
</main>
);
const Header = (): ReactElement => {
const user: User | undefined = useUserContext(
(state: UserState) => state.user
);
return (
<div className="flex flex-col gap-1.5 select-none">
<h1 className="text-2xl font-bold">Settings</h1>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/dashboard">
Dashboard
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>{user?.username}</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Settings</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</div>
);
};
export default UserSettingsPage;

@ -23,7 +23,6 @@ import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.share
import DashboardLoader from "@/components/dashboard/loader";
import { hasFlag } from "@/lib/user";
import { UserFlag } from "@/app/types/user/user-flag";
import EmailVerificationScreen from "@/components/dashboard/user/email-verification-screen";
/**
* The provider that will provide user context to children.

@ -0,0 +1,21 @@
import { ReactElement } from "react";
/**
* A link in the user menu on the dashboard.
*/
export type UserMenuLink = {
/**
* The name of this link.
*/
name: string;
/**
* The icon for this link.
*/
icon: ReactElement;
/**
* The href for this link.
*/
href: string;
};

@ -1,7 +1,7 @@
"use client";
import { ReactElement } from "react";
import { SidebarLink } from "@/app/types/sidebar-link";
import { SidebarLink } from "@/app/types/dashboard/sidebar-link";
import SimpleTooltip from "@/components/simple-tooltip";
import Link from "next/link";
import { cn } from "@/lib/utils";

@ -5,13 +5,13 @@ import Branding from "@/components/branding";
import { Separator } from "@/components/ui/separator";
import Link from "next/link";
import OrganizationSelector from "@/components/dashboard/sidebar/organization-selector";
import Links from "@/components/dashboard/sidebar/links";
import Links from "@/components/dashboard/sidebar/sidebar-links";
import { User } from "@/app/types/user/user";
import { useUserContext } from "@/app/provider/user-provider";
import { UserState } from "@/app/store/user-store";
import { hasFlag } from "@/lib/user";
import { UserFlag } from "@/app/types/user/user-flag";
import UserMenu from "@/components/dashboard/sidebar/user-menu";
import UserMenu from "@/components/dashboard/sidebar/user-menu/user-menu";
/**
* The sidebar to display on the dashboard.

@ -0,0 +1,32 @@
import { userMenuLinks } from "@/components/dashboard/sidebar/user-menu/user-menu";
import Link from "next/link";
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
import { ReactElement } from "react";
import { usePathname } from "next/navigation";
import { cn } from "@/lib/utils";
import { UserMenuLink } from "@/app/types/dashboard/user-menu-link";
const UserMenuLinks = (): ReactElement => {
const path: string = usePathname();
return (
<>
{userMenuLinks.map((link: UserMenuLink, index: number) => {
const active = path.startsWith(link.href);
return (
<Link key={index} href={link.href} draggable={false}>
<DropdownMenuItem
className={cn(
"gap-2.5 cursor-pointer",
active && "opacity-70"
)}
>
<div className="relative w-5 h-5">{link.icon}</div>
<span>{link.name}</span>
</DropdownMenuItem>
</Link>
);
})}
</>
);
};
export default UserMenuLinks;

@ -20,12 +20,31 @@ import {
CreditCardIcon,
UserIcon,
} from "@heroicons/react/24/outline";
import Link from "next/link";
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
import { useRouter } from "next/navigation";
import { Cookies, useCookies } from "next-client-cookies";
import { Session } from "@/app/types/user/session";
import { apiRequest } from "@/lib/api";
import UserMenuLinks from "@/components/dashboard/sidebar/user-menu/user-menu-links";
import { UserMenuLink } from "@/app/types/dashboard/user-menu-link";
export const userMenuLinks: UserMenuLink[] = [
{
name: "Profile",
icon: <UserIcon />,
href: "/dashboard/user/profile",
},
{
name: "Billing",
icon: <CreditCardIcon />,
href: "/dashboard/user/billing",
},
{
name: "Settings",
icon: <Cog6ToothIcon />,
href: "/dashboard/user/settings",
},
];
/**
* The menu to manage the user.
@ -93,24 +112,7 @@ const MyAccount = (): ReactElement => (
My Account
</DropdownMenuLabel>
<DropdownMenuSeparator />
<Link href="/dashboard/user/profile" draggable={false}>
<DropdownMenuItem className="gap-2.5 cursor-pointer">
<UserIcon className="w-5 h-5" />
<span>Profile</span>
</DropdownMenuItem>
</Link>
<Link href="/dashboard/user/billing" draggable={false}>
<DropdownMenuItem className="gap-2.5 cursor-pointer">
<CreditCardIcon className="w-5 h-5" />
<span>Billing</span>
</DropdownMenuItem>
</Link>
<Link href="/dashboard/user/settings" draggable={false}>
<DropdownMenuItem className="gap-2.5 cursor-pointer">
<Cog6ToothIcon className="w-5 h-5" />
<span>Settings</span>
</DropdownMenuItem>
</Link>
<UserMenuLinks />
</DropdownMenuGroup>
);

@ -0,0 +1,64 @@
import { ReactElement } from "react";
import { User } from "@/app/types/user/user";
import { useUserContext } from "@/app/provider/user-provider";
import { UserState } from "@/app/store/user-store";
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { ChevronDownIcon } from "@heroicons/react/24/outline";
import UserMenuLinks from "@/components/dashboard/sidebar/user-menu/user-menu-links";
/**
* The header to display
* on user settings pages.
*
* @param title the title of this header
* @return the header jsx
*/
const UserSettingsHeader = ({ title }: { title: string }): ReactElement => {
const user: User | undefined = useUserContext(
(state: UserState) => state.user
);
return (
<div className="flex flex-col gap-1.5 select-none">
<h1 className="text-2xl font-bold">{title}</h1>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/dashboard">
Dashboard
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<DropdownMenu>
<DropdownMenuTrigger className="flex gap-1.5 items-center">
@{user?.username}
<ChevronDownIcon className="w-3 h-3" />
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<UserMenuLinks />
</DropdownMenuContent>
</DropdownMenu>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>{title}</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</div>
);
};
export default UserSettingsHeader;