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