🎨 style: adjust sidebar for mobile
This commit is contained in:
parent
3b1f03bcb6
commit
e05e2c63c2
@ -1,6 +1,6 @@
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { NavLink, useNavigate, useParams } from 'react-router-dom';
|
||||
import { Organization } from 'gql-client';
|
||||
import { Organization, User } from 'gql-client';
|
||||
|
||||
import { Option } from '@material-tailwind/react';
|
||||
import { useDisconnect } from 'wagmi';
|
||||
@ -12,11 +12,16 @@ import {
|
||||
FolderIcon,
|
||||
GlobeIcon,
|
||||
LifeBuoyIcon,
|
||||
LogoutIcon,
|
||||
QuestionMarkRoundIcon,
|
||||
SettingsSlidersIcon,
|
||||
} from 'components/shared/CustomIcon';
|
||||
import { Tabs } from 'components/shared/Tabs';
|
||||
import { Logo } from 'components/Logo';
|
||||
import { Avatar } from 'components/shared/Avatar';
|
||||
import { formatAddress } from 'utils/format';
|
||||
import { getInitials } from 'utils/geInitials';
|
||||
import { Button } from 'components/shared/Button';
|
||||
|
||||
export const Sidebar = () => {
|
||||
const { orgSlug } = useParams();
|
||||
@ -24,6 +29,17 @@ export const Sidebar = () => {
|
||||
const client = useGQLClient();
|
||||
const { disconnect } = useDisconnect();
|
||||
|
||||
const [user, setUser] = useState<User>();
|
||||
|
||||
const fetchUser = useCallback(async () => {
|
||||
const { user } = await client.getUser();
|
||||
setUser(user);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
fetchUser();
|
||||
}, []);
|
||||
|
||||
const [selectedOrgSlug, setSelectedOrgSlug] = useState(orgSlug);
|
||||
const [organizations, setOrganizations] = useState<Organization[]>([]);
|
||||
|
||||
@ -43,39 +59,21 @@ export const Sidebar = () => {
|
||||
}, [disconnect, navigate]);
|
||||
|
||||
return (
|
||||
<nav className="lg:flex hidden flex-col h-full px-6 py-8 gap-9">
|
||||
<Logo orgSlug={orgSlug} />
|
||||
{/* Switch organization */}
|
||||
<div className="flex flex-1 flex-col gap-4">
|
||||
<AsyncSelect
|
||||
containerProps={{ className: 'h-14 border-none' }}
|
||||
labelProps={{ className: 'before:border-none after:border-none' }}
|
||||
className="bg-white rounded-lg shadow border-none"
|
||||
value={selectedOrgSlug}
|
||||
onChange={(value) => {
|
||||
setSelectedOrgSlug(value!);
|
||||
navigate(`/${value}`);
|
||||
}}
|
||||
selected={(_, index) => (
|
||||
<div className="flex items-center space-x-3">
|
||||
<img
|
||||
src="/logo.svg"
|
||||
alt="Application Logo"
|
||||
className="h-8 w-8 rounded-lg"
|
||||
/>
|
||||
<div>
|
||||
<div className="text-sm font-semibold">
|
||||
{organizations[index!]?.name}
|
||||
</div>
|
||||
<div className="text-xs text-gray-500">Organization</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
arrow={<ChevronGrabberHorizontal className="h-4 w-4 text-gray-500" />}
|
||||
>
|
||||
{/* // TODO: Show label organization and manage in option */}
|
||||
{organizations.map((org) => (
|
||||
<Option key={org.id} value={org.slug}>
|
||||
<nav className="h-full w-[320px] lg:flex hidden flex-col">
|
||||
<div className="flex flex-col h-full pt-8 pb-0 px-6 lg:pb-8 gap-9">
|
||||
<Logo orgSlug={orgSlug} />
|
||||
{/* Switch organization */}
|
||||
<div className="flex flex-1 flex-col gap-4">
|
||||
<AsyncSelect
|
||||
containerProps={{ className: 'h-14 border-none' }}
|
||||
labelProps={{ className: 'before:border-none after:border-none' }}
|
||||
className="bg-white rounded-lg shadow border-none"
|
||||
value={selectedOrgSlug}
|
||||
onChange={(value) => {
|
||||
setSelectedOrgSlug(value!);
|
||||
navigate(`/${value}`);
|
||||
}}
|
||||
selected={(_, index) => (
|
||||
<div className="flex items-center space-x-3">
|
||||
<img
|
||||
src="/logo.svg"
|
||||
@ -83,50 +81,100 @@ export const Sidebar = () => {
|
||||
className="h-8 w-8 rounded-lg"
|
||||
/>
|
||||
<div>
|
||||
<div className="text-sm font-semibold">{org.name}</div>
|
||||
<div className="text-sm font-semibold">
|
||||
{organizations[index!]?.name}
|
||||
</div>
|
||||
<div className="text-xs text-gray-500">Organization</div>
|
||||
</div>
|
||||
</div>
|
||||
</Option>
|
||||
))}
|
||||
</AsyncSelect>
|
||||
<Tabs defaultValue="Projects" orientation="vertical">
|
||||
<Tabs.List>
|
||||
{[
|
||||
{ title: 'Projects', url: `/${orgSlug}/`, icon: <FolderIcon /> },
|
||||
{
|
||||
title: 'Settings',
|
||||
url: `/${orgSlug}/settings`,
|
||||
icon: <SettingsSlidersIcon />,
|
||||
},
|
||||
].map(({ title, icon, url }, index) => (
|
||||
<NavLink to={url} key={index}>
|
||||
<Tabs.Trigger icon={icon} value={title}>
|
||||
{title}
|
||||
</Tabs.Trigger>
|
||||
</NavLink>
|
||||
)}
|
||||
arrow={
|
||||
<ChevronGrabberHorizontal className="h-4 w-4 text-gray-500" />
|
||||
}
|
||||
>
|
||||
{/* // TODO: Show label organization and manage in option */}
|
||||
{organizations.map((org) => (
|
||||
<Option key={org.id} value={org.slug}>
|
||||
<div className="flex items-center space-x-3">
|
||||
<img
|
||||
src="/logo.svg"
|
||||
alt="Application Logo"
|
||||
className="h-8 w-8 rounded-lg"
|
||||
/>
|
||||
<div>
|
||||
<div className="text-sm font-semibold">{org.name}</div>
|
||||
<div className="text-xs text-gray-500">Organization</div>
|
||||
</div>
|
||||
</div>
|
||||
</Option>
|
||||
))}
|
||||
</Tabs.List>
|
||||
</Tabs>
|
||||
</AsyncSelect>
|
||||
<Tabs defaultValue="Projects" orientation="vertical">
|
||||
<Tabs.List>
|
||||
{[
|
||||
{
|
||||
title: 'Projects',
|
||||
url: `/${orgSlug}/`,
|
||||
icon: <FolderIcon />,
|
||||
},
|
||||
{
|
||||
title: 'Settings',
|
||||
url: `/${orgSlug}/settings`,
|
||||
icon: <SettingsSlidersIcon />,
|
||||
},
|
||||
].map(({ title, icon, url }, index) => (
|
||||
<NavLink to={url} key={index}>
|
||||
<Tabs.Trigger icon={icon} value={title}>
|
||||
{title}
|
||||
</Tabs.Trigger>
|
||||
</NavLink>
|
||||
))}
|
||||
</Tabs.List>
|
||||
</Tabs>
|
||||
</div>
|
||||
{/* Bottom navigation */}
|
||||
<div className="flex flex-col gap-5 justify-end">
|
||||
<Tabs defaultValue="Projects" orientation="vertical">
|
||||
{/* // TODO: use proper link buttons */}
|
||||
<Tabs.List>
|
||||
<Tabs.Trigger
|
||||
icon={<GlobeIcon />}
|
||||
value=""
|
||||
className="hidden lg:flex"
|
||||
>
|
||||
<a className="cursor-pointer" onClick={handleLogOut}>
|
||||
Log Out
|
||||
</a>
|
||||
</Tabs.Trigger>
|
||||
<Tabs.Trigger icon={<QuestionMarkRoundIcon />} value="">
|
||||
<a className="cursor-pointer">Documentation</a>
|
||||
</Tabs.Trigger>
|
||||
<Tabs.Trigger icon={<LifeBuoyIcon />} value="">
|
||||
<a className="cursor-pointer">Support</a>
|
||||
</Tabs.Trigger>
|
||||
</Tabs.List>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
{/* Bottom navigation */}
|
||||
<div className="flex flex-col justify-end">
|
||||
<Tabs defaultValue="Projects" orientation="vertical">
|
||||
{/* // TODO: use proper link buttons */}
|
||||
<Tabs.List>
|
||||
<Tabs.Trigger icon={<GlobeIcon />} value="">
|
||||
<a className="cursor-pointer" onClick={handleLogOut}>
|
||||
Log Out
|
||||
</a>
|
||||
</Tabs.Trigger>
|
||||
<Tabs.Trigger icon={<QuestionMarkRoundIcon />} value="">
|
||||
<a className="cursor-pointer">Documentation</a>
|
||||
</Tabs.Trigger>
|
||||
<Tabs.Trigger icon={<LifeBuoyIcon />} value="">
|
||||
<a className="cursor-pointer">Support</a>
|
||||
</Tabs.Trigger>
|
||||
</Tabs.List>
|
||||
</Tabs>
|
||||
<div className="shadow-card-sm py-4 pl-4 pr-2 flex lg:hidden items-center border-t border-border-separator/[0.06]">
|
||||
{user?.name && (
|
||||
<div className="flex items-center flex-1 gap-3">
|
||||
<Avatar
|
||||
size={44}
|
||||
initials={getInitials(formatAddress(user.name))}
|
||||
/>
|
||||
<p className="text-sm tracking-[-0.006em] text-elements-high-em">
|
||||
{formatAddress(user.name)}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="text-elements-low-em"
|
||||
onClick={handleLogOut}
|
||||
>
|
||||
<LogoutIcon />
|
||||
</Button>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user