Skip to content

Commit

Permalink
✨ Add Sidebar to new frontend (fastapi#587)
Browse files Browse the repository at this point in the history
  • Loading branch information
alejsdev authored Jan 29, 2024
1 parent 5836c76 commit 1a27bdf
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 0 deletions.
48 changes: 48 additions & 0 deletions src/new-frontend/src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from 'react';

import { Box, Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerOverlay, Flex, IconButton, Image, useDisclosure } from '@chakra-ui/react';
import { FiMenu } from 'react-icons/fi';

import Logo from "../assets/images/fastapi-logo.png";
import SidebarItems from './SidebarItems';
import UserInfo from './UserInfo';


const Sidebar: React.FC = () => {
const { isOpen, onOpen, onClose } = useDisclosure();

return (
<>
{/* Mobile */}
<IconButton onClick={onOpen} display={{ base: 'flex', md: 'none' }} aria-label="Open Menu" position="absolute" fontSize='20px' m={4} icon={<FiMenu />} />
<Drawer isOpen={isOpen} placement="left" onClose={onClose}>
<DrawerOverlay />
<DrawerContent bg="gray.100" maxW="250px">
<DrawerCloseButton />
<DrawerBody py={8}>
<Flex flexDir="column" justify="space-between" h="100%">
<Box>
<Image src={Logo} alt="Logo" />
<SidebarItems />
</Box>
<UserInfo />
</Flex>
</DrawerBody>
</DrawerContent>
</Drawer>

{/* Desktop */}
<Box bg="white" p={3} h="100vh" position="sticky" top="0" display={{ base: 'none', md: 'flex' }}>
<Flex flexDir="column" justify="space-between" bg="gray.100" p={6} borderRadius={12}>
<Box>
<Image src={Logo} alt="Logo" w="180px" maxW="2xs" />
<SidebarItems />
</Box>
<UserInfo />
</Flex>
</Box>
</>
);
}

export default Sidebar;
37 changes: 37 additions & 0 deletions src/new-frontend/src/components/SidebarItems.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';

import { Flex, Icon, Text } from '@chakra-ui/react';
import { FiBriefcase, FiHome, FiLogOut, FiUser, FiUsers } from 'react-icons/fi';
import { Link } from 'react-router-dom';

const items = [
{ icon: FiHome, title: 'Dashboard', path: "/" },
{ icon: FiUser, title: 'Profile', path: "/profile" },
{ icon: FiBriefcase, title: 'Items', path: "/items" },
{ icon: FiUsers, title: 'Admin', path: "/admin" },
{ icon: FiLogOut, title: 'Log out' }
];

const SidebarItems: React.FC = () => {
const listItems = items.map((item) => (
<Flex w="100%" p={2} key={item.title} _hover={{
background: "gray.200",
borderRadius: "12px",
}}>
<Link to={item.path || "/"}>
<Flex color="teal.500" gap={4}>
<Icon as={item.icon} alignSelf="center" />
<Text>{item.title}</Text>
</Flex>
</Link>
</Flex>
));

return (
<>
{listItems}
</>
);
};

export default SidebarItems;
40 changes: 40 additions & 0 deletions src/new-frontend/src/components/UserInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React, { useEffect, useState } from 'react';

import { Avatar, Flex, Skeleton, Text } from '@chakra-ui/react';
import { FaUserAstronaut } from 'react-icons/fa';

import { UserOut, UsersService } from '../client';

const UserInfo: React.FC = () => {
const [userData, setUserData] = useState<UserOut>();

useEffect(() => {
const fetchUserData = async () => {
try {
const userResponse = await UsersService.readUserMe();
setUserData(userResponse);
} catch (error) {
// TODO: Handle error to give feedback to the user
console.error(error);
}
};
fetchUserData();
}, []);

return (
<>
{userData ? (
<Flex gap={2} maxW="180px">
<Avatar icon={<FaUserAstronaut fontSize="18px" />} size='sm' alignSelf="center" />
{/* TODO: Conditional tooltip based on email length */}
<Text color='gray' alignSelf={"center"} noOfLines={1} fontSize="14px">{userData.email}</Text>
</Flex>
) :
<Skeleton height='20px' />
}
</>
);

}

export default UserInfo;
14 changes: 14 additions & 0 deletions src/new-frontend/src/pages/Layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Sidebar from '../components/Sidebar';

import { Flex } from '@chakra-ui/react';

const Layout = ({ children }: { children: React.ReactNode }) => {
return (
<Flex maxW="large" h="auto" position="relative">
<Sidebar />
{children}
</Flex>
);
};

export default Layout;

0 comments on commit 1a27bdf

Please sign in to comment.