extend toolbar styling, add support for atomic menu
This commit is contained in:
@@ -1,24 +1,17 @@
|
||||
"use client";
|
||||
import { Sidebar } from "@/components/sidebar";
|
||||
import { tw } from "@/utils/tailwind";
|
||||
import MenuIcon from "@mui/icons-material/Menu";
|
||||
import {
|
||||
CssBaseline,
|
||||
IconButton,
|
||||
ThemeProvider,
|
||||
useMediaQuery,
|
||||
} from "@mui/material";
|
||||
import { CssBaseline, ThemeProvider, useMediaQuery } from "@mui/material";
|
||||
import { StyledEngineProvider } from "@mui/material/styles";
|
||||
import axios from "axios";
|
||||
import localFont from "next/font/local";
|
||||
import Image from "next/image";
|
||||
import * as React from "react";
|
||||
import { Toaster } from "react-hot-toast";
|
||||
import "./globals.css";
|
||||
import { darkTheme, lightTheme } from "./theme/themes";
|
||||
|
||||
import { WithAppState } from "@/components/hooks/useAppContext";
|
||||
import { ClanToolbar } from "@/components/clanToolbar";
|
||||
import { WithAppState } from "@/components/hooks/useAppContext";
|
||||
|
||||
const roboto = localFont({
|
||||
src: [
|
||||
@@ -70,29 +63,10 @@ export default function RootLayout({
|
||||
!showSidebar && translate
|
||||
} flex h-full w-full flex-col overflow-y-scroll transition-[margin] duration-150 ease-in-out`}
|
||||
>
|
||||
<ClanToolbar />
|
||||
<div className="static top-0 mb-2 py-2">
|
||||
<div className="grid grid-cols-3">
|
||||
<div className="col-span-1">
|
||||
<IconButton
|
||||
hidden={showSidebar}
|
||||
onClick={() => setShowSidebar((c) => !c)}
|
||||
>
|
||||
{!showSidebar && <MenuIcon />}
|
||||
</IconButton>
|
||||
</div>
|
||||
<div className="col-span-1 block w-full bg-fixed text-center font-semibold dark:invert lg:hidden">
|
||||
<Image
|
||||
src="/favicon.png"
|
||||
alt="Clan Logo"
|
||||
width={58}
|
||||
height={58}
|
||||
priority
|
||||
<ClanToolbar
|
||||
isSidebarVisible={showSidebar}
|
||||
handleSidebar={setShowSidebar}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="px-1">
|
||||
<div className="relative flex h-full flex-1 flex-col">
|
||||
<main>{children}</main>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useFlakeHistoryList } from "@/api/flake/flake";
|
||||
import DynamicFeedIcon from "@mui/icons-material/DynamicFeed";
|
||||
import { IconButton, LinearProgress } from "@mui/material";
|
||||
import MenuIcon from "@mui/icons-material/Menu";
|
||||
import { Button, Divider, LinearProgress } from "@mui/material";
|
||||
import Menu from "@mui/material/Menu";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import * as React from "react";
|
||||
@@ -9,57 +10,112 @@ interface ToolbarButtonProps {
|
||||
icon: React.ReactNode;
|
||||
onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;
|
||||
}
|
||||
function ToolbarButton(props: ToolbarButtonProps) {
|
||||
export function ToolbarButton(props: ToolbarButtonProps) {
|
||||
const { icon, onClick } = props;
|
||||
return (
|
||||
<div className="">
|
||||
<IconButton onClick={onClick}>{icon}</IconButton>
|
||||
</div>
|
||||
<Button
|
||||
sx={{
|
||||
"& .MuiButton-startIcon": {
|
||||
m: 0,
|
||||
},
|
||||
}}
|
||||
onClick={onClick}
|
||||
startIcon={icon}
|
||||
variant="text"
|
||||
color="inherit"
|
||||
// fullWidth
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const ClanHistoryMenu = () => {
|
||||
const { data, isLoading } = useFlakeHistoryList();
|
||||
|
||||
return (
|
||||
<>
|
||||
{isLoading ? (
|
||||
<LinearProgress />
|
||||
) : (
|
||||
data?.data.map((item, index) => <MenuItem key={index}>{item}</MenuItem>)
|
||||
)}
|
||||
{!isLoading && data?.data.length === 0 && (
|
||||
<MenuItem>No Clan History</MenuItem>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
type ToolbarItem = {
|
||||
icon: React.ReactNode;
|
||||
menu: React.ReactNode;
|
||||
};
|
||||
const toolbarItems: ToolbarItem[] = [
|
||||
{
|
||||
icon: <DynamicFeedIcon />,
|
||||
menu: <ClanHistoryMenu />,
|
||||
},
|
||||
];
|
||||
export function ClanToolbar() {
|
||||
const { data, isLoading } = useFlakeHistoryList();
|
||||
|
||||
interface ClanToolbarProps {
|
||||
isSidebarVisible: boolean;
|
||||
handleSidebar: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
export function ClanToolbar(props: ClanToolbarProps) {
|
||||
const { isSidebarVisible, handleSidebar } = props;
|
||||
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||
const open = Boolean(anchorEl);
|
||||
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
const [openIdx, setOpenIdx] = React.useState<number | null>(null);
|
||||
|
||||
const handleClick = (
|
||||
event: React.MouseEvent<HTMLButtonElement>,
|
||||
idx: number
|
||||
) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
setOpenIdx(idx);
|
||||
};
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
setOpenIdx(null);
|
||||
};
|
||||
return (
|
||||
<div className="grid w-full auto-cols-min grid-flow-col grid-rows-1 place-items-end justify-end gap-2">
|
||||
<div
|
||||
className="flex border-x-0 border-b
|
||||
border-t-0 border-solid border-neutral-80"
|
||||
>
|
||||
{!isSidebarVisible && (
|
||||
<ToolbarButton
|
||||
icon={<MenuIcon />}
|
||||
onClick={() => handleSidebar((c) => !c)}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
className="
|
||||
grid w-full auto-cols-min grid-flow-col grid-rows-1
|
||||
justify-end gap-0
|
||||
"
|
||||
>
|
||||
{toolbarItems.map((item, index) => (
|
||||
<ToolbarButton key={index} icon={item.icon} onClick={handleClick} />
|
||||
))}
|
||||
<React.Fragment key={index}>
|
||||
<Divider flexItem orientation="vertical" />
|
||||
<ToolbarButton
|
||||
icon={item.icon}
|
||||
onClick={(ev) => handleClick(ev, index)}
|
||||
/>
|
||||
|
||||
<Menu
|
||||
id="basic-menu"
|
||||
anchorEl={anchorEl}
|
||||
open={open}
|
||||
open={index == openIdx}
|
||||
onClose={handleClose}
|
||||
MenuListProps={{
|
||||
"aria-labelledby": "basic-button",
|
||||
}}
|
||||
>
|
||||
{isLoading ? (
|
||||
<LinearProgress />
|
||||
) : (
|
||||
data?.data.map((item, index) => (
|
||||
<MenuItem key={index}>{item}</MenuItem>
|
||||
))
|
||||
)}
|
||||
{!isLoading && data?.data.length === 0 && (
|
||||
<MenuItem>No Clan History</MenuItem>
|
||||
)}
|
||||
{item.menu}
|
||||
</Menu>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,8 +5,10 @@ import { toast } from "react-hot-toast";
|
||||
export function clanErrorToast(error: AxiosError<HTTPValidationError>) {
|
||||
console.error({ error });
|
||||
const detail = error.response?.data.detail?.[0]?.msg;
|
||||
const detailAlt = error.response?.data.detail as unknown as string;
|
||||
const cause = error.cause?.message;
|
||||
const axiosMessage = error.message;
|
||||
const sanitizedMsg = detail || cause || axiosMessage || "Unexpected error";
|
||||
const sanitizedMsg =
|
||||
detail || detailAlt || cause || axiosMessage || "Unexpected error";
|
||||
toast.error(sanitizedMsg);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user