Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
280 changes: 166 additions & 114 deletions apps/app/components/workspace/sidebar-dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import useToast from "hooks/use-toast";
import userService from "services/user.service";
import authenticationService from "services/authentication.service";
// components
import { Avatar, Loader } from "components/ui";
import { Avatar, Icon, Loader } from "components/ui";
// icons
import { CheckIcon, PlusIcon } from "@heroicons/react/24/outline";
// helpers
Expand All @@ -40,6 +40,19 @@ const userLinks = (workspaceSlug: string, userId: string) => [
},
];

const profileLinks = (workspaceSlug: string, userId: string) => [
{
name: "View profile",
icon: "account_circle",
link: `/${workspaceSlug}/profile/${userId}`,
},
{
name: "Settings",
icon: "settings",
link: `/${workspaceSlug}/me/profile`,
},
];

export const WorkspaceSidebarDropdown = () => {
const router = useRouter();
const { workspaceSlug } = router.query;
Expand Down Expand Up @@ -90,8 +103,8 @@ export const WorkspaceSidebarDropdown = () => {
};

return (
<Menu as="div" className="relative col-span-4 inline-block w-full px-4 pt-4 text-left">
<div className="flex items-center justify-between gap-2">
<div className="inline-flex items-center gap-2 px-4 pt-4">
<Menu as="div" className="relative col-span-4 inline-block w-full text-left">
<Menu.Button className="text-custom-sidebar-text-200 flex w-full items-center rounded-sm text-sm font-medium focus:outline-none">
<div
className={`flex w-full items-center gap-x-2 rounded-sm bg-custom-sidebar-background-80 p-1 ${
Expand All @@ -118,127 +131,166 @@ export const WorkspaceSidebarDropdown = () => {
</div>
</Menu.Button>

{!sidebarCollapse && (
<Link href={`/${workspaceSlug}/profile/${user?.id}`}>
<a>
<div className="flex flex-grow justify-end">
<Avatar user={user} height="28px" width="28px" fontSize="14px" />
</div>
</a>
</Link>
)}
</div>

<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items
className="fixed left-4 z-20 mt-1 flex flex-col w-full max-w-[17rem] origin-top-left rounded-md
border border-custom-sidebar-border-200 bg-custom-sidebar-background-90 shadow-lg outline-none"
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<div className="flex flex-col items-start justify-start gap-3 p-3">
<div className="text-sm text-custom-sidebar-text-200">{user?.email}</div>
<span className="text-sm font-semibold text-custom-sidebar-text-200">Workspace</span>
{workspaces ? (
<div className="flex h-full w-full flex-col items-start justify-start gap-3.5">
{workspaces.length > 0 ? (
workspaces.map((workspace) => (
<Menu.Item key={workspace.id}>
{({ active }) => (
<button
type="button"
onClick={() => handleWorkspaceNavigation(workspace)}
className="flex w-full items-center justify-between gap-1 rounded-md text-sm text-custom-sidebar-text-100"
>
<div className="flex items-center justify-start gap-2.5">
<span className="relative flex h-6 w-6 items-center justify-center rounded bg-gray-700 p-2 text-xs uppercase text-white">
{workspace?.logo && workspace.logo !== "" ? (
<img
src={workspace.logo}
className="absolute top-0 left-0 h-full w-full object-cover rounded"
alt="Workspace Logo"
/>
) : (
workspace?.name?.charAt(0) ?? "..."
)}
<Menu.Items
className="fixed left-4 z-20 mt-1 flex flex-col w-full max-w-[17rem] origin-top-left rounded-md
border border-custom-sidebar-border-200 bg-custom-sidebar-background-90 shadow-lg outline-none"
>
<div className="flex flex-col items-start justify-start gap-3 p-3">
<div className="text-sm text-custom-sidebar-text-200">{user?.email}</div>
<span className="text-sm font-semibold text-custom-sidebar-text-200">Workspace</span>
{workspaces ? (
<div className="flex h-full w-full flex-col items-start justify-start gap-3.5">
{workspaces.length > 0 ? (
workspaces.map((workspace) => (
<Menu.Item key={workspace.id}>
{({ active }) => (
<button
type="button"
onClick={() => handleWorkspaceNavigation(workspace)}
className="flex w-full items-center justify-between gap-1 rounded-md text-sm text-custom-sidebar-text-100"
>
<div className="flex items-center justify-start gap-2.5">
<span className="relative flex h-6 w-6 items-center justify-center rounded bg-gray-700 p-2 text-xs uppercase text-white">
{workspace?.logo && workspace.logo !== "" ? (
<img
src={workspace.logo}
className="absolute top-0 left-0 h-full w-full object-cover rounded"
alt="Workspace Logo"
/>
) : (
workspace?.name?.charAt(0) ?? "..."
)}
</span>

<h5
className={`text-sm ${
workspaceSlug === workspace.slug ? "" : "text-custom-text-200"
}`}
>
{truncateText(workspace.name, 18)}
</h5>
</div>
<span className="p-1">
<CheckIcon
className={`h-3 w-3.5 text-custom-sidebar-text-100 ${
active || workspace.id === activeWorkspace?.id
? "opacity-100"
: "opacity-0"
}`}
/>
</span>
</button>
)}
</Menu.Item>
))
) : (
<p>No workspace found!</p>
)}
<Menu.Item
as="button"
type="button"
onClick={() => {
router.push("/create-workspace");
}}
className="flex w-full items-center gap-1 text-sm text-custom-sidebar-text-200"
>
<PlusIcon className="h-3 w-3" />
Create Workspace
</Menu.Item>
</div>
) : (
<div className="w-full">
<Loader className="space-y-2">
<Loader.Item height="30px" />
<Loader.Item height="30px" />
</Loader>
</div>
)}
</div>
<div className="flex w-full flex-col items-start justify-start gap-2 border-t border-custom-sidebar-border-200 px-3 py-2 text-sm">
{userLinks(workspaceSlug?.toString() ?? "", user?.id ?? "").map((link, index) => (
<Menu.Item
key={index}
as="div"
className="flex w-full items-center justify-start rounded px-2 py-1 text-sm text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-80"
>
<Link href={link.href}>
<a className="w-full">{link.name}</a>
</Link>
</Menu.Item>
))}
</div>
<div className="w-full border-t border-t-custom-sidebar-border-100 px-3 py-2">
<Menu.Item
as="button"
type="button"
className="flex w-full items-center justify-start rounded px-2 py-1 text-sm text-red-600 hover:bg-custom-sidebar-background-80"
onClick={handleSignOut}
>
Sign out
</Menu.Item>
</div>
</Menu.Items>
</Transition>
</Menu>

{!sidebarCollapse && (
<Menu as="div" className="relative flex-shrink-0">
<Menu.Button className="grid place-items-center outline-none">
<Avatar user={user} height="28px" width="28px" fontSize="14px" />
</Menu.Button>

<h5
className={`text-sm ${
workspaceSlug === workspace.slug ? "" : "text-custom-text-200"
}`}
>
{truncateText(workspace.name, 18)}
</h5>
</div>
<span className="p-1">
<CheckIcon
className={`h-3 w-3.5 text-custom-sidebar-text-100 ${
active || workspace.id === activeWorkspace?.id
? "opacity-100"
: "opacity-0"
}`}
/>
</span>
</button>
)}
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items
className="absolute left-0 z-20 mt-1.5 flex flex-col w-52 origin-top-left rounded-md
border border-custom-sidebar-border-200 bg-custom-sidebar-background-90 p-2 divide-y divide-custom-sidebar-border-200 shadow-lg text-xs outline-none"
>
<div className="flex flex-col space-y-2 pb-2">
{profileLinks(workspaceSlug?.toString() ?? "", user?.id ?? "").map(
(link, index) => (
<Menu.Item key={index} as="button" type="button">
<Link href={link.link}>
<a className="flex w-full items-center gap-2 rounded px-2 py-1 hover:bg-custom-sidebar-background-80">
<Icon iconName={link.icon} className="!text-base" />
{link.name}
</a>
</Link>
</Menu.Item>
))
) : (
<p>No workspace found!</p>
)
)}
</div>
<div className="pt-2">
<Menu.Item
as="button"
type="button"
onClick={() => {
router.push("/create-workspace");
}}
className="flex w-full items-center gap-1 text-sm text-custom-sidebar-text-200"
className="flex w-full items-center gap-2 rounded px-2 py-1 hover:bg-custom-sidebar-background-80"
onClick={handleSignOut}
>
<PlusIcon className="h-3 w-3" />
Create Workspace
<Icon iconName="logout" className="!text-base" />
Log out
</Menu.Item>
</div>
) : (
<div className="w-full">
<Loader className="space-y-2">
<Loader.Item height="30px" />
<Loader.Item height="30px" />
</Loader>
</div>
)}
</div>
<div className="flex w-full flex-col items-start justify-start gap-2 border-t border-custom-sidebar-border-200 px-3 py-2 text-sm">
{userLinks(workspaceSlug?.toString() ?? "", user?.id ?? "").map((link, index) => (
<Menu.Item
key={index}
as="div"
className="flex w-full items-center justify-start rounded px-2 py-1 text-sm text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-80"
>
<Link href={link.href}>
<a className="w-full">{link.name}</a>
</Link>
</Menu.Item>
))}
</div>
<div className="w-full border-t border-t-custom-sidebar-border-100 px-3 py-2">
<Menu.Item
as="button"
type="button"
className="flex w-full items-center justify-start rounded px-2 py-1 text-sm text-red-600 hover:bg-custom-sidebar-background-80"
onClick={handleSignOut}
>
Sign out
</Menu.Item>
</div>
</Menu.Items>
</Transition>
</Menu>
</Menu.Items>
</Transition>
</Menu>
)}
</div>
);
};