tasko/app/(platform)/(dashboard)/_components/sidebar.tsx

94 lines
2.5 KiB
TypeScript

'use client';
import Link from 'next/link';
import { Plus } from 'lucide-react';
import { useLocalStorage } from 'usehooks-ts';
import { useOrganizationList, useOrganization } from '@clerk/nextjs';
import { Button } from '@/components/ui/button';
import { Accordion } from '@/components/ui/accordion';
import { Skeleton } from '@/components/ui/skeleton';
import { NavItem, Organization } from './nav-item';
interface SidebarProps {
storageKey?: string;
}
export const Sidebar = ({ storageKey = 't-sidebar-state' }: SidebarProps) => {
const [expanded, setExpanded] = useLocalStorage<Record<string, any>>(
storageKey,
{}
);
const { organization: activeOrganization, isLoaded: isLoadedOrg } =
useOrganization();
const { userMemberships, isLoaded: isLoadedOrgList } = useOrganizationList({
userMemberships: { infinite: true },
});
const defaultAccordionValue: string[] = Object.keys(expanded).reduce(
(acc: string[], key: string) => {
if (expanded[key]) {
acc.push(key);
}
return acc;
},
[]
);
const onExpand = (id: string) => {
setExpanded((curr) => ({
...curr,
[id]: !expanded[id],
}));
};
if (!isLoadedOrgList || !isLoadedOrg || userMemberships.isLoading) {
return (
<>
<div className='mb-2 flex items-center justify-between'>
<Skeleton className='h-10 w-[50%]' />
<Skeleton className='h-10 w-10' />
</div>
<div className='space-y-2'>
<NavItem.Skeleton />
<NavItem.Skeleton />
<NavItem.Skeleton />
</div>
</>
);
}
return (
<>
<div className='mb-1 flex items-center text-xs font-medium'>
<span className='pl-4'>Workspaces</span>
<Button
asChild
type='button'
size='icon'
variant='ghost'
className='ml-auto'
>
<Link href='/select-org'>
<Plus className='h-4 w-4' />
</Link>
</Button>
</div>
<Accordion
type='multiple'
defaultValue={defaultAccordionValue}
className='space-y-2'
>
{userMemberships.data.map(({ organization }) => (
<NavItem
key={organization.id}
isActive={activeOrganization?.id === organization.id}
isExpanded={expanded[organization.id]}
organization={organization as Organization}
onExpand={onExpand}
/>
))}
</Accordion>
</>
);
};