This commit is contained in:
Owen Schwartz 2024-10-13 22:49:29 -04:00
commit b53d093065
No known key found for this signature in database
GPG key ID: 8271FDFFD9E0CCBD
5 changed files with 143 additions and 113 deletions

View file

@ -0,0 +1,87 @@
"use client";
import { Avatar, AvatarFallback } from "@app/components/ui/avatar";
import { Badge } from "@app/components/ui/badge";
import { Button } from "@app/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuTrigger,
} from "@app/components/ui/dropdown-menu";
import Link from "next/link";
type HeaderProps = {
name?: string;
email: string;
orgName: string;
};
export default function Header({ email, orgName, name }: HeaderProps) {
function getInitials() {
if (name) {
const [firstName, lastName] = name.split(" ");
return `${firstName[0]}${lastName[0]}`;
}
return email.substring(0, 2).toUpperCase();
}
return (
<>
<div className="flex items-center justify-between">
<Badge variant="outline" className="text-md font-bold">
{orgName}
</Badge>
<div className="flex items-center">
<div className="flex items-center gap-3">
<span className="text-lg font-medium">
{name || email}
</span>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
className="relative h-10 w-10 rounded-full"
>
<Avatar className="h-10 w-10">
<AvatarFallback>
{getInitials()}
</AvatarFallback>
</Avatar>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent
className="w-56"
align="end"
forceMount
>
<DropdownMenuLabel className="font-normal">
<div className="flex flex-col space-y-1">
{name && (
<p className="text-sm font-medium leading-none">
{name}
</p>
)}
<p className="text-xs leading-none text-muted-foreground">
{email}
</p>
</div>
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuItem>Profile</DropdownMenuItem>
<DropdownMenuItem>Log out</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
</div>
</div>
</div>
</>
);
}

View file

@ -12,12 +12,14 @@ interface TopbarNavProps extends React.HTMLAttributes<HTMLElement> {
icon: React.ReactNode;
}[];
disabled?: boolean;
orgId: string;
}
export function TopbarNav({
className,
items,
disabled = false,
orgId,
...props
}: TopbarNavProps) {
const pathname = usePathname();
@ -34,10 +36,10 @@ export function TopbarNav({
{items.map((item) => (
<Link
key={item.href}
href={item.href}
href={item.href.replace("{orgId}", orgId)}
className={cn(
"px-2 py-3 text-md",
pathname === item.href
pathname === item.href.replace("{orgId}", orgId)
? "border-b-2 border-stone-600 text-stone-600"
: "hover:text-gray-600 text-stone-400",
"whitespace-nowrap",

View file

@ -1,7 +1,9 @@
import { Metadata } from "next";
import { TopbarNav } from "./components/TopbarNav";
import { LayoutGrid, Tent } from "lucide-react";
import { Cog, LayoutGrid, Tent, Users } from "lucide-react";
import Header from "./components/Header";
import { verifySession } from "@app/lib/auth/verifySession";
import { redirect } from "next/navigation";
export const metadata: Metadata = {
title: "Configuration",
@ -11,39 +13,54 @@ export const metadata: Metadata = {
const topNavItems = [
{
title: "Sites",
href: "/configuration/sites",
href: "/{orgId}/sites",
icon: <Tent />,
},
{
title: "Resources",
href: "/configuration/resources",
href: "/{orgId}/resources",
icon: <LayoutGrid />,
},
{
title: "Users",
href: "/{orgId}/users",
icon: <Users />,
},
{
title: "General",
href: "/{orgId}/general",
icon: <Cog />,
},
];
interface ConfigurationLaytoutProps {
children: React.ReactNode;
params: { siteId: string };
params: { orgId: string };
}
export default async function ConfigurationLaytout({
children,
params,
}: ConfigurationLaytoutProps) {
const user = await verifySession();
if (!user) {
redirect("/auth/login");
}
return (
<>
<div className="w-full bg-stone-200 border-b border-stone-300 mb-5 select-none px-3">
<div className="w-full bg-stone-200 border-b border-stone-300 mb-5 select-none sm:px-0 px-3">
<div className="container mx-auto flex flex-col content-between gap-3 pt-2">
<Header
email="mschwartz10612@gmail.com"
orgName="Home Lab 1"
name="Milo Schwartz"
email={user.email}
orgName={params.orgId}
/>
<TopbarNav items={topNavItems} />
<TopbarNav items={topNavItems} orgId={params.orgId}/>
</div>
</div>
<div className="container mx-auto px-3">{children}</div>
<div className="container mx-auto sm:px-0 px-3">{children}</div>
</>
);
}

View file

@ -1,26 +1,30 @@
import React from 'react';
import React from "react";
import { Separator } from "@/components/ui/separator";
import { ProfileForm } from "@app/components/profile-form";
import { CreateSiteForm } from "./components/create-site";
export default function SettingsProfilePage({ params }: { params: { siteId: string } }) {
const isCreateForm = params.siteId === "create";
export default function SettingsProfilePage({
params,
}: {
params: { siteId: string };
}) {
const isCreateForm = params.siteId === "create";
return (
<div className="space-y-6">
<div>
<h3 className="text-lg font-medium">
{isCreateForm ? "Create Site" : "Profile"}
</h3>
<p className="text-sm text-muted-foreground">
{isCreateForm
? "Create a new site for your profile."
: "This is how others will see you on the site."}
</p>
</div>
<Separator />
return (
<div className="space-y-6">
<div>
<h3 className="text-lg font-medium">
{isCreateForm ? "Create Site" : "Profile"}
</h3>
<p className="text-sm text-muted-foreground">
{isCreateForm
? "Create a new site for your profile."
: "This is how others will see you on the site."}
</p>
</div>
<Separator />
{isCreateForm ? <CreateSiteForm /> : <ProfileForm />}
</div>
);
{isCreateForm ? <CreateSiteForm /> : <ProfileForm />}
</div>
);
}

View file

@ -1,80 +0,0 @@
"use client";
import { Avatar, AvatarFallback } from "@app/components/ui/avatar";
import { Badge } from "@app/components/ui/badge";
import { Button } from "@app/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuTrigger,
} from "@app/components/ui/dropdown-menu";
type HeaderProps = {
name?: string;
email: string;
orgName: string;
};
export default function Header({ email, orgName, name }: HeaderProps) {
function getInitials() {
if (name) {
const [firstName, lastName] = name.split(" ");
return `${firstName[0]}${lastName[0]}`;
}
return email.substring(0, 2).toUpperCase();
}
return (
<>
<div className="flex items-center justify-between">
<Badge variant="outline" className="text-md font-bold">{orgName}</Badge>
<div className="flex items-center gap-3">
<span className="text-lg font-medium">{name || email}</span>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
className="relative h-10 w-10 rounded-full"
>
<Avatar className="h-10 w-10">
<AvatarFallback>
{getInitials()}
</AvatarFallback>
</Avatar>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent
className="w-56"
align="end"
forceMount
>
<DropdownMenuLabel className="font-normal">
<div className="flex flex-col space-y-1">
{name && (
<p className="text-sm font-medium leading-none">
{name}
</p>
)}
<p className="text-xs leading-none text-muted-foreground">
{email}
</p>
</div>
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuItem>Profile</DropdownMenuItem>
<DropdownMenuItem>Log out</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
</div>
</div>
</>
);
}