200 lines
No EOL
4.5 KiB
JavaScript
200 lines
No EOL
4.5 KiB
JavaScript
import React, { useEffect, useRef, useState } from 'react';
|
|
import styled from '@emotion/styled';
|
|
import {
|
|
useLocation,
|
|
useNavigate,
|
|
useParams
|
|
} from 'react-router';
|
|
import { Avatar, Stack } from '@mui/material';
|
|
import { useLocalStore } from '@components';
|
|
|
|
const NavBox = styled(Stack)`
|
|
width: 100%;
|
|
`;
|
|
|
|
const LeftContainer = styled(Stack)`
|
|
display: flex;
|
|
align-items: center;
|
|
flex-direction: row;
|
|
flex-flow: row wrap;
|
|
`;
|
|
|
|
const RightContainer = styled(Stack)`
|
|
display: flex;
|
|
flex-direction: row;
|
|
flex-flow: row wrap;
|
|
`;
|
|
|
|
const NavGroup = styled(Stack)`
|
|
display: flex;
|
|
background: #ffffff
|
|
width: 100%;
|
|
height: 60px;
|
|
padding: 4px;
|
|
justify-content: space-between !important
|
|
`;
|
|
|
|
const Title = styled('p')`
|
|
cursor: pointer;
|
|
`;
|
|
|
|
const Tab = styled('div')`
|
|
position: relative;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: flex-end;
|
|
height: 100%;
|
|
padding: 6px 16px;
|
|
font-size: 20px;
|
|
font-weight: 800;
|
|
color: grey;
|
|
background: none;
|
|
border: none;
|
|
cursor: pointer;
|
|
font-family: "WDXL Lubrifont TC";
|
|
letter-spacing: .05em;
|
|
word-spacing: .2em;
|
|
`;
|
|
|
|
const SlidingIndicator = styled('div')`
|
|
position: absolute;
|
|
bottom: -6px;
|
|
height: 2px;
|
|
background-color: #4D79FF;
|
|
transition: left 0.3s ease, width 0.3s ease;
|
|
`;
|
|
|
|
const Border = styled('div')`
|
|
height: 2px;
|
|
width: 100%;
|
|
background-color: #A8A8A8;
|
|
`;
|
|
|
|
export const NavBar = ({ notifications, disableNav, settings }) => {
|
|
const { pathname } = useLocation();
|
|
const navigate = useNavigate();
|
|
const routeParams = useParams();
|
|
const { user } = useLocalStore();
|
|
|
|
const [indicatorStyle, setIndicatorStyle] = useState({ left: 0, width: 0 });
|
|
const tabRefs = useRef({});
|
|
|
|
const isAdmin = user?.isAdmin;
|
|
|
|
const navItems = [
|
|
{
|
|
name: 'Home',
|
|
id: 'home',
|
|
href: '/',
|
|
matches: ['', 'home']
|
|
},
|
|
{
|
|
name: 'Schedule',
|
|
id: 'schedule',
|
|
href: '/schedule',
|
|
matches: ['schedule']
|
|
},
|
|
{
|
|
name: 'Settings',
|
|
id: 'settings',
|
|
href: '/settings',
|
|
matches: ['settings', 'settings']
|
|
},
|
|
{
|
|
name: 'Administrator Panel',
|
|
id: 'admin',
|
|
href: '/admin',
|
|
matches: ['admin'],
|
|
hidden: !isAdmin
|
|
},
|
|
// Keep this Last (Replaced with the profile icon)
|
|
{
|
|
name: 'Profile',
|
|
id: 'profile',
|
|
href: '/profile',
|
|
matches: ['profile'],
|
|
hidden: true
|
|
}
|
|
];
|
|
|
|
let activeTab = navItems.find((tab) => {
|
|
return tab.matches.some((item) => {
|
|
return item === pathname?.split('/')[1];
|
|
});
|
|
});
|
|
|
|
const onShiftSyncClick = () => {
|
|
navigate('/');
|
|
}
|
|
|
|
const onNavButtonClick = (tab) => {
|
|
activeTab = tab;
|
|
navigate(tab.href);
|
|
};
|
|
|
|
const onUserIconClick = () => {
|
|
navigate('/profile');
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (activeTab?.id && tabRefs.current[activeTab.id]) {
|
|
const el = tabRefs.current[activeTab.id];
|
|
const rect = el.getBoundingClientRect();
|
|
const containerRect = el.parentNode.getBoundingClientRect();
|
|
setIndicatorStyle({
|
|
left: rect.left - containerRect.left,
|
|
width: rect.width
|
|
});
|
|
}
|
|
}, [pathname, activeTab?.id]);
|
|
|
|
return (
|
|
<NavBox direction='column'>
|
|
<NavGroup direction='row'>
|
|
<LeftContainer>
|
|
<Title
|
|
style={{
|
|
color: 'darkgray',
|
|
fontWeight: '400',
|
|
fontSize: '40px',
|
|
fontFamily: "WDXL Lubrifont TC, sans-serif",
|
|
letterSpacing: '.08em'
|
|
}}
|
|
onClick={onShiftSyncClick}
|
|
>
|
|
ShiftSync
|
|
</Title>
|
|
</LeftContainer>
|
|
<RightContainer style={{ position: 'relative' }}>
|
|
{navItems?.map((item) => {
|
|
if (!item?.hidden) {
|
|
return (
|
|
<Tab
|
|
key={item?.id}
|
|
ref={(el) => { tabRefs.current[item.id] = el; }}
|
|
onClick={() => onNavButtonClick(item)}
|
|
>
|
|
{item?.name}
|
|
</Tab>
|
|
);
|
|
}
|
|
return null;
|
|
}).filter((item) => item !== null)}
|
|
<Tab
|
|
key='profile'
|
|
ref={(el) => { tabRefs.current['profile'] = el; }}
|
|
>
|
|
<Avatar
|
|
onClick={() => onUserIconClick()}
|
|
>
|
|
{`${user?.first_name[0]}${user?.last_name[0]}`}
|
|
</Avatar>
|
|
</Tab>
|
|
<SlidingIndicator style={indicatorStyle} />
|
|
</RightContainer>
|
|
</NavGroup>
|
|
<Border />
|
|
</NavBox>
|
|
)
|
|
} |