added bottom navigator

This commit is contained in:
Carter 2024-11-26 12:17:36 -06:00
parent 3f96724422
commit 7ee06c4e19
4 changed files with 223 additions and 16 deletions

View file

@ -1,10 +1,9 @@
import { Box, Button, Card, CircularProgress, Collapse, darken, Divider, Grid2, IconButton, InputAdornment, List, ListItem, Paper, SxProps, Table, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, TextField, Theme, Typography } from "@mui/material"; import { Box, Card, CircularProgress, Collapse, darken, Divider, Grid2, IconButton, InputAdornment, ListItemButton, Paper, SxProps, Table, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, TextField, Theme, Typography } from "@mui/material";
import { makeStyles } from "@mui/styles"; import { makeStyles } from "@mui/styles";
import { ChevronRight, Close, Search } from "@mui/icons-material" import { ChevronRight, Close, Search } from "@mui/icons-material"
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import React from "react"; import React from "react";
import { useMobile } from "hooks"; import { useMobile } from "hooks";
import { render } from "react-dom";
const useStyles = makeStyles((theme: Theme) => { const useStyles = makeStyles((theme: Theme) => {
// const isMobile = useMobile() // const isMobile = useMobile()
@ -232,7 +231,6 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
{renderTitle()} {renderTitle()}
{setSearchText && searchBar()} {setSearchText && searchBar()}
</Box> </Box>
{rows.map((row, index) => { {rows.map((row, index) => {
return ( return (
<Card className={classes.card} key={"mobile-card-"+index}> <Card className={classes.card} key={"mobile-card-"+index}>
@ -244,17 +242,25 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
{renderGutter(row)} {renderGutter(row)}
</Collapse> </Collapse>
{openGutters.includes(index) && <Divider/>} {openGutters.includes(index) && <Divider/>}
<IconButton <ListItemButton
onClick={() => handleCollapse(index)} sx={{
sx={{ width: "100%",
transform: openGutters.includes(index) ? display: "flex",
'rotate(-90deg)' : 'rotate(90deg)', justifyContent: "center"
transition: 'transform 0.3s ease', }}
width: "100%", onClick={() => handleCollapse(index)}
}}
> >
<ChevronRight/> <IconButton
</IconButton> sx={{
transform: openGutters.includes(index) ?
'rotate(-90deg)' : 'rotate(90deg)',
transition: 'transform 0.3s ease',
alignContent: "center"
}}
>
<ChevronRight/>
</IconButton>
</ListItemButton>
</> </>
} }
</Card> </Card>

View file

@ -0,0 +1,195 @@
import { BottomNavigation, BottomNavigationAction, Box, useTheme } from "@mui/material";
import {
Dashboard as DevicesIcon,
Home,
MoreHoriz,
Security,
//SupervisedUserCircle,
ShowChart as DemoIcon
} from "@mui/icons-material";
import { usePrevious } from "hooks";
import BindaptIcon from "products/Bindapt/BindaptIcon";
import BinsIcon from "products/Bindapt/BinsIcon";
import VentilationIcon from "products/ventilation/VentilationIcon";
import { useGlobalState } from "providers";
import { useCallback, useEffect, useState } from "react";
import { useNavigate, useLocation } from "react-router-dom";
import { IsAdaptiveAgriculture, isBXT, IsMiVent, IsAdCon, IsOmniAir } from "services/whiteLabel";
import FieldsIcon from "products/AgIcons/FieldsIcon";
import NexusSTIcon from "products/Construction/NexusSTIcon";
import OmniAirDeviceIcon from "products/AviationIcons/OmniAirDeviceIcon";
import AirportMapIcon from "products/AviationIcons/AirportMapIcon";
import PlaneIcon from "products/AviationIcons/PlaneIcon";
import JobsiteIcon from "products/Construction/JobSiteIcon";
import { useAuth0 } from "@auth0/auth0-react";
interface Props {
sideIsOpen: boolean;
openSide: () => void;
}
export default function BottomNavigator(props: Props) {
const theme = useTheme();
const { sideIsOpen, openSide } = props;
const navigate = useNavigate();
const location = useLocation();
const prevLocation = usePrevious(location);
const { isAuthenticated } = useAuth0();
const [{ user }] = useGlobalState();
const [route, setRoute] = useState(sideIsOpen ? "side" : "");
const isAdaptive = IsAdaptiveAgriculture();
const isMiVent = IsMiVent();
const isAdCon = IsAdCon();
const isOmni = IsOmniAir();
const reRoute = useCallback(
(path: string) => {
if (path === "") {
if (isAdaptive) {
return "bins";
}
if (isMiVent) {
return "ventilation";
}
return "devices";
}
const deviceRoutes = ["groups", "devices", "demo"];
if (deviceRoutes.find(r => path === r) !== undefined) {
return "devices";
}
const moreRoutes = [
"firmware",
"users",
"docs",
"tutorial",
"hardware",
"data",
"team",
"sandbox"
];
if (moreRoutes.find(r => path === r) !== undefined) {
return "more";
}
return path;
},
[isAdaptive, isMiVent]
);
const autoDetectRoute = useCallback(() => {
let path = location.pathname.split("/")[1];
setRoute(reRoute(path));
}, [location.pathname, reRoute]);
useEffect(() => {
if (!prevLocation || location !== prevLocation) {
autoDetectRoute();
}
}, [location, prevLocation, autoDetectRoute]);
const handleRouteChange = (newRoute: string) => {
if (newRoute === "more") {
openSide();
} else {
navigate(`/${newRoute}`);
setRoute(newRoute);
}
};
const authenticatedNavigation = () => {
return (
<BottomNavigation value={route} onChange={(_, newValue) => handleRouteChange(newValue)}>
{isAdaptive && (
<BottomNavigationAction label="Farm" icon={<FieldsIcon type="light" />} value="fields" />
)}
{isAdaptive && (
<BottomNavigationAction label="Bins" icon={<BinsIcon type="light" />} value="bins" />
)}
{isAdCon && (
<BottomNavigationAction
label="Site Map"
icon={<FieldsIcon type="light" />}
value="constructionsiteMap"
/>
)}
{isOmni && (
<BottomNavigationAction
label="Map"
icon={<AirportMapIcon type="light" />}
value="aviationMap"
/>
)}
{isOmni && (
<BottomNavigationAction
label="Terminals"
icon={<PlaneIcon type="light" />}
value="terminals"
/>
)}
<BottomNavigationAction
label="Devices"
icon={
isAdaptive ? (
<BindaptIcon type="light" />
) : isAdCon ? (
<NexusSTIcon type="light" />
) : isOmni ? (
<OmniAirDeviceIcon type="light" />
) : (
<DevicesIcon />
)
}
value="devices"
/>
{isAdCon && (
<BottomNavigationAction
label="Sites"
icon={<JobsiteIcon type="light" />}
value="jobsites"
/>
)}
{isMiVent && (
<BottomNavigationAction
label="Ventilation"
icon={<VentilationIcon type="light" />}
value="ventilation"
/>
)}
{isBXT() && user.hasFeature("security") && (
<BottomNavigationAction label="Security" icon={<Security />} value="security" />
)}
<BottomNavigationAction label="More" icon={<MoreHoriz />} value="more" />
</BottomNavigation>
);
};
// BXT specific navigation
const unauthenticatedNavigation = () => {
return (
<BottomNavigation value={route} onChange={(_, newValue) => handleRouteChange(newValue)}>
<BottomNavigationAction label="Demo" value="demo" icon={<DemoIcon />} />
<BottomNavigationAction label="Home" icon={<Home />} value="" />
<BottomNavigationAction label="More" icon={<MoreHoriz />} value="more" />
</BottomNavigation>
);
};
return (
<Box
position="fixed"
bottom={0}
width="100vw"
zIndex={theme.zIndex.appBar}
style={{
overflow:
window.location.origin.includes("staging") || window.location.origin.includes("localhost")
? "scroll"
: "visible"
}}>
{isAuthenticated ? authenticatedNavigation() : unauthenticatedNavigation()}
</Box>
);
}

View file

@ -12,7 +12,6 @@ export default function NavigationContainer(props: Props) {
// const { toggleTheme, teams, setTeams } = props; // const { toggleTheme, teams, setTeams } = props;
const { toggleTheme } = props; const { toggleTheme } = props;
const [sideNavigatorOpen, setSideNavigatorOpen] = useState<boolean>(false); const [sideNavigatorOpen, setSideNavigatorOpen] = useState<boolean>(false);
// const isMobile = useMobile();
const openSideNavigator = () => { const openSideNavigator = () => {
setSideNavigatorOpen(true); setSideNavigatorOpen(true);
@ -32,8 +31,11 @@ export default function NavigationContainer(props: Props) {
// teams={teams} // teams={teams}
// setTeams={setTeams} // setTeams={setTeams}
/> />
<Router open={sideNavigatorOpen} onOpen={openSideNavigator} onClose={closeSideMenu} /> <Router
{/* {isMobile && <BottomNavigator openSide={openSideNavigator} sideIsOpen={sideNavigatorOpen} />} */} open={sideNavigatorOpen}
onOpen={openSideNavigator}
onClose={closeSideMenu}
/>
</React.Fragment> </React.Fragment>
); );
} }

View file

@ -6,6 +6,8 @@ import { useAuth0 } from "@auth0/auth0-react";
import Teams from "pages/Teams"; import Teams from "pages/Teams";
import SideNavigator from "./SideNavigator"; import SideNavigator from "./SideNavigator";
import Users from "pages/Users"; import Users from "pages/Users";
import { useMobile } from "hooks";
import BottomNavigator from "./BottomNavigator";
interface Props { interface Props {
open: boolean, open: boolean,
@ -17,6 +19,7 @@ export default function Router(props: Props) {
const {open, onOpen, onClose} = props; const {open, onOpen, onClose} = props;
const { isAuthenticated, loginWithRedirect, isLoading } = useAuth0() const { isAuthenticated, loginWithRedirect, isLoading } = useAuth0()
const isMobile = useMobile()
const hello = () => { const hello = () => {
return ( return (
@ -62,6 +65,7 @@ export default function Router(props: Props) {
<Route path="contact" element={<Contact />} /> <Route path="contact" element={<Contact />} />
<Route path="*" element={<NoPage />} /> */} <Route path="*" element={<NoPage />} /> */}
</Routes> </Routes>
{isMobile && <BottomNavigator openSide={onOpen} sideIsOpen={open} />}
</BrowserRouter> </BrowserRouter>
</Suspense> </Suspense>
) )