aboutsummaryrefslogtreecommitdiff
path: root/FrontEnd/src/components/AppBar.tsx
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2023-08-26 21:36:58 +0800
committercrupest <crupest@outlook.com>2023-08-26 21:36:58 +0800
commitf5dfd52f6efece2f4cad227044ecf4dd66301bbc (patch)
tree0d64daae438ac6d95f0848a0b3387134d9528438 /FrontEnd/src/components/AppBar.tsx
parent4daa84ede781cdf6f424d68c967a17c7e1c79f59 (diff)
downloadtimeline-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.tsx98
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>
+ );
+}