diff options
Diffstat (limited to 'src/main/MainPage.jsx')
-rw-r--r-- | src/main/MainPage.jsx | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/src/main/MainPage.jsx b/src/main/MainPage.jsx new file mode 100644 index 00000000..8369ba97 --- /dev/null +++ b/src/main/MainPage.jsx @@ -0,0 +1,160 @@ +import React, { + useState, useCallback, useEffect, +} from 'react'; +import { Paper } from '@mui/material'; +import { makeStyles } from '@mui/styles'; +import { useTheme } from '@mui/material/styles'; +import useMediaQuery from '@mui/material/useMediaQuery'; +import { useDispatch, useSelector } from 'react-redux'; +import DeviceList from './DeviceList'; +import BottomMenu from '../common/components/BottomMenu'; +import StatusCard from '../common/components/StatusCard'; +import { devicesActions } from '../store'; +import usePersistedState from '../common/util/usePersistedState'; +import EventsDrawer from './EventsDrawer'; +import useFilter from './useFilter'; +import MainToolbar from './MainToolbar'; +import MainMap from './MainMap'; +import { useAttributePreference } from '../common/util/preferences'; + +const useStyles = makeStyles((theme) => ({ + root: { + height: '100%', + }, + sidebar: { + pointerEvents: 'none', + display: 'flex', + flexDirection: 'column', + [theme.breakpoints.up('md')]: { + position: 'fixed', + left: 0, + top: 0, + height: `calc(100% - ${theme.spacing(3)})`, + width: theme.dimensions.drawerWidthDesktop, + margin: theme.spacing(1.5), + zIndex: 3, + }, + [theme.breakpoints.down('md')]: { + height: '100%', + width: '100%', + }, + }, + header: { + pointerEvents: 'auto', + zIndex: 6, + }, + footer: { + pointerEvents: 'auto', + zIndex: 5, + }, + middle: { + flex: 1, + display: 'grid', + }, + contentMap: { + pointerEvents: 'auto', + gridArea: '1 / 1', + }, + contentList: { + pointerEvents: 'auto', + gridArea: '1 / 1', + zIndex: 4, + }, +})); + +const MainPage = () => { + const classes = useStyles(); + const dispatch = useDispatch(); + const theme = useTheme(); + + const desktop = useMediaQuery(theme.breakpoints.up('md')); + + const mapOnSelect = useAttributePreference('mapOnSelect', true); + + const selectedDeviceId = useSelector((state) => state.devices.selectedId); + const positions = useSelector((state) => state.session.positions); + const [filteredPositions, setFilteredPositions] = useState([]); + const selectedPosition = filteredPositions.find((position) => selectedDeviceId && position.deviceId === selectedDeviceId); + + const [filteredDevices, setFilteredDevices] = useState([]); + + const [keyword, setKeyword] = useState(''); + const [filter, setFilter] = usePersistedState('filter', { + statuses: [], + groups: [], + }); + const [filterSort, setFilterSort] = usePersistedState('filterSort', ''); + const [filterMap, setFilterMap] = usePersistedState('filterMap', false); + + const [devicesOpen, setDevicesOpen] = useState(desktop); + const [eventsOpen, setEventsOpen] = useState(false); + + const onEventsClick = useCallback(() => setEventsOpen(true), [setEventsOpen]); + + useEffect(() => { + if (!desktop && mapOnSelect && selectedDeviceId) { + setDevicesOpen(false); + } + }, [desktop, mapOnSelect, selectedDeviceId]); + + useFilter(keyword, filter, filterSort, filterMap, positions, setFilteredDevices, setFilteredPositions); + + return ( + <div className={classes.root}> + {desktop && ( + <MainMap + filteredPositions={filteredPositions} + selectedPosition={selectedPosition} + onEventsClick={onEventsClick} + /> + )} + <div className={classes.sidebar}> + <Paper square elevation={3} className={classes.header}> + <MainToolbar + filteredDevices={filteredDevices} + devicesOpen={devicesOpen} + setDevicesOpen={setDevicesOpen} + keyword={keyword} + setKeyword={setKeyword} + filter={filter} + setFilter={setFilter} + filterSort={filterSort} + setFilterSort={setFilterSort} + filterMap={filterMap} + setFilterMap={setFilterMap} + /> + </Paper> + <div className={classes.middle}> + {!desktop && ( + <div className={classes.contentMap}> + <MainMap + filteredPositions={filteredPositions} + selectedPosition={selectedPosition} + onEventsClick={onEventsClick} + /> + </div> + )} + <Paper square className={classes.contentList} style={devicesOpen ? {} : { visibility: 'hidden' }}> + <DeviceList devices={filteredDevices} /> + </Paper> + </div> + {desktop && ( + <div className={classes.footer}> + <BottomMenu /> + </div> + )} + </div> + <EventsDrawer open={eventsOpen} onClose={() => setEventsOpen(false)} /> + {selectedDeviceId && ( + <StatusCard + deviceId={selectedDeviceId} + position={selectedPosition} + onClose={() => dispatch(devicesActions.selectId(null))} + desktopPadding={theme.dimensions.drawerWidthDesktop} + /> + )} + </div> + ); +}; + +export default MainPage; |