Refactor made changes to file structures
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import { useRecipe, Button, Stack, Text, Flex } from "@chakra-ui/react"
|
||||
import UserAvatarMenu from "./UserAvatarMenu.jsx";
|
||||
import { NavLink } from "react-router-dom";
|
||||
|
||||
// Import the asset properly so Vite can bundle it for any server
|
||||
// import defaultAvatar from "@/assets/user_profile.svg";
|
||||
|
||||
// TODO: Pull this dynamically from an Auth Context later!
|
||||
const placeholderUser = {
|
||||
name: "Princess Zelda",
|
||||
email: "zelda.royal@hyrule.gov",
|
||||
// avatar: defaultAvatar
|
||||
}
|
||||
|
||||
// Accept a 'user' prop now, fallback to placeholder if empty
|
||||
export default function Header({ user = placeholderUser }) {
|
||||
const recipe = useRecipe({ key: "header" });
|
||||
const styles = recipe();
|
||||
|
||||
return (
|
||||
<Flex css={styles} justify="space-between" align="center" width="100%">
|
||||
{/* Home Link Logo */}
|
||||
<Button as={NavLink} to="/home" color="color" variant="plain" textStyle="5xl" fontWeight="bold">
|
||||
VDAP
|
||||
</Button>
|
||||
|
||||
{/* User Profile Section */}
|
||||
<Flex align="center" gap={3} pr={6}>
|
||||
<Stack gap="0" textAlign="right" cursor="default">
|
||||
<Text color="color" fontWeight="bold" textStyle="lg">{user.name}</Text>
|
||||
<Text color="fg.muted" textStyle="sm">{user.email}</Text>
|
||||
</Stack>
|
||||
<UserAvatarMenu
|
||||
name={user.name}
|
||||
avatar={user.avatar}
|
||||
/>
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import { useSlotRecipe, Box, Button, IconButton } from "@chakra-ui/react";
|
||||
import { ColorModeButton } from "@/components/ui/color-mode.jsx";
|
||||
import { useState } from "react";
|
||||
import { NavLink } from "react-router-dom";
|
||||
import Tooltip from "../ui/Tooltip.jsx";
|
||||
import { Mountain, House, Earth, MapPin, ShieldUser, Menu } from 'lucide-react';
|
||||
|
||||
const SIDEBAR_DEFAULT_BUTTONS = [
|
||||
{ icon: House, name: "Home", url: "/home" },
|
||||
{ icon: Earth, name: "Global Map", url: "/global-map" },
|
||||
{ icon: MapPin, name: "Regional Map", url: "/regional-map" },
|
||||
{ icon: Mountain, name: "Volcano", url: "/volcano" },
|
||||
{ icon: ShieldUser, name: "Admin", url: "/admin" } // TODO remove in the future as default should not have admin
|
||||
];
|
||||
|
||||
export default function Sidebar() {
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
const recipe = useSlotRecipe({ key: "sidebar" });
|
||||
const styles = recipe();
|
||||
|
||||
// TODO we will need to call buttons here by authorized user, for now we update the visible buttons as simply the default buttons
|
||||
const visibleButtons = SIDEBAR_DEFAULT_BUTTONS;
|
||||
|
||||
const toggleSidebar = () => setIsOpen((prev) => !prev);
|
||||
|
||||
return (
|
||||
<Box css={styles.root} width={isOpen ? "210px" : "71px"} transition="width 0.4s ease" position="relative" display="flex" flexDirection="column" gap={2}
|
||||
>
|
||||
{/* Menu Trigger */}
|
||||
<IconButton aria-label="Toggle Sidebar" variant="plain" size="md" onClick={toggleSidebar} width="54px" alignSelf="flex-start"
|
||||
>
|
||||
<Menu />
|
||||
</IconButton>
|
||||
|
||||
{/* Navigation Buttons */}
|
||||
{visibleButtons.map((button) => {
|
||||
const Icon = button.icon;
|
||||
return (
|
||||
<Tooltip key={button.name} content={button.name} sidebarIsOpen={isOpen}>
|
||||
<Button
|
||||
as={NavLink}
|
||||
to={button.url}
|
||||
css={styles.buttons}
|
||||
justifyContent="flex-start"
|
||||
width="100%"
|
||||
overflow="hidden" // Prevents text popout on collapse
|
||||
>
|
||||
<Icon style={{ flexShrink: 0 }} /> {/* Prevents icon from squishing */}
|
||||
|
||||
{/* Cleaned conditional transition styling */}
|
||||
<Box
|
||||
as="span"
|
||||
ml={isOpen ? 3 : 0}
|
||||
opacity={isOpen ? 1 : 0}
|
||||
visibility={isOpen ? "visible" : "hidden"} // Prevents phantom width calculations and overflow into canvas
|
||||
transition="opacity 0.3s ease, visibility 0.3s ease, margin 0.3s ease"
|
||||
whiteSpace="nowrap"
|
||||
>
|
||||
{button.name}
|
||||
</Box>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* Theme Toggler */}
|
||||
<ColorModeButton
|
||||
position="absolute"
|
||||
bottom="4"
|
||||
left="4"
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Avatar, Menu, Portal, Box } from "@chakra-ui/react";
|
||||
import { NavLink } from "react-router-dom";
|
||||
|
||||
|
||||
export default function UserAvatarMenu({ name, avatar }) {
|
||||
return (
|
||||
<Menu.Root>
|
||||
<Menu.Trigger focusRing="none">
|
||||
<Box
|
||||
rounded="full"
|
||||
tabIndex={0}
|
||||
_hover={{ boxShadow: "0 0 0 2px rgb(102, 122, 182)" }}
|
||||
cursor="pointer"
|
||||
>
|
||||
<Avatar.Root shape="full">
|
||||
<Avatar.Fallback name={name} />
|
||||
<Avatar.Image src={avatar} />
|
||||
</Avatar.Root>
|
||||
</Box>
|
||||
</Menu.Trigger>
|
||||
<Portal>
|
||||
{/* zIndex: overlay = 1300 */}
|
||||
<Menu.Positioner zIndex="overlay">
|
||||
<Menu.Content>
|
||||
<Menu.Item value="settings" as={NavLink} to={"/settings"}>
|
||||
Settings
|
||||
</Menu.Item>
|
||||
<Menu.Item value="logout" onClick={() => console.log("Log out triggered")}>
|
||||
Logout
|
||||
</Menu.Item>
|
||||
</Menu.Content>
|
||||
</Menu.Positioner>
|
||||
</Portal>
|
||||
</Menu.Root>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user