diff options
author | crupest <crupest@outlook.com> | 2023-08-26 21:36:58 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2023-08-26 21:36:58 +0800 |
commit | f5dfd52f6efece2f4cad227044ecf4dd66301bbc (patch) | |
tree | 0d64daae438ac6d95f0848a0b3387134d9528438 /FrontEnd/src/components/AppBar.tsx | |
parent | 4daa84ede781cdf6f424d68c967a17c7e1c79f59 (diff) | |
download | timeline-f5dfd52f6efece2f4cad227044ecf4dd66301bbc.tar.gz timeline-f5dfd52f6efece2f4cad227044ecf4dd66301bbc.tar.bz2 timeline-f5dfd52f6efece2f4cad227044ecf4dd66301bbc.zip |
...
Diffstat (limited to 'FrontEnd/src/components/AppBar.tsx')
-rw-r--r-- | FrontEnd/src/components/AppBar.tsx | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/FrontEnd/src/components/AppBar.tsx b/FrontEnd/src/components/AppBar.tsx new file mode 100644 index 00000000..da3a946f --- /dev/null +++ b/FrontEnd/src/components/AppBar.tsx @@ -0,0 +1,98 @@ +import { useState } from "react"; +import classnames from "classnames"; +import { Link, NavLink } from "react-router-dom"; + +import { I18nText, useC, useMobile } from "./common"; +import { useUser } from "~src/services/user"; + +import TimelineLogo from "./TimelineLogo"; +import { IconButton } from "./button"; +import UserAvatar from "./user/UserAvatar"; + +import "./AppBar.css"; + +function AppBarNavLink({ + link, + className, + label, + onClick, + children, +}: { + link: string; + className?: string; + label?: I18nText; + onClick?: () => void; + children?: React.ReactNode; +}) { + if (label != null && children != null) { + throw new Error("AppBarNavLink: label and children cannot be both set"); + } + + const c = useC(); + + return ( + <NavLink + to={link} + className={({ isActive }) => classnames(className, isActive && "active")} + onClick={onClick} + > + {children != null ? children : c(label)} + </NavLink> + ); +} + +export default function AppBar() { + const isMobile = useMobile(); + + const [isCollapse, setIsCollapse] = useState<boolean>(true); + const collapse = isMobile ? () => setIsCollapse(true) : undefined; + const toggleCollapse = () => setIsCollapse(!isCollapse); + + const user = useUser(); + const hasAdministrationPermission = user && user.hasAdministrationPermission; + + return ( + <nav + className={classnames( + isMobile ? "mobile" : "desktop", + "app-bar", + isCollapse && "collapse", + )} + > + <Link to="/" className="app-bar-brand" onClick={collapse}> + <TimelineLogo className="app-bar-brand-icon" /> + Timeline + </Link> + + <div className="app-bar-link-area"> + <AppBarNavLink + link="/settings" + label="nav.settings" + onClick={collapse} + /> + <AppBarNavLink link="/about" label="nav.about" onClick={collapse} /> + {hasAdministrationPermission && ( + <AppBarNavLink + link="/admin" + label="nav.administration" + onClick={collapse} + /> + )} + </div> + + <div className="app-bar-user-area"> + {user != null ? ( + <AppBarNavLink link="/" className="app-bar-avatar" onClick={collapse}> + <UserAvatar username={user.username} /> + </AppBarNavLink> + ) : ( + <AppBarNavLink link="/login" label="nav.login" onClick={collapse} /> + )} + </div> + + {isMobile && ( + <IconButton icon="list" className="toggler" onClick={toggleCollapse} /> + )} + </nav> + ); +} |