aboutsummaryrefslogtreecommitdiff
path: root/modern/src/main/MainPage.js
diff options
context:
space:
mode:
authorAnton Tananaev <anton@traccar.org>2022-05-08 13:16:57 -0700
committerAnton Tananaev <anton@traccar.org>2022-05-08 13:16:57 -0700
commit2cd374bb9fa941d7e2a6fd8aa5079893a158c98f (patch)
treef4ee48130592fed5de25dce7af4ac0cbeb017680 /modern/src/main/MainPage.js
parent2352071211b61c10fa5bf5736baaff7809d18bf0 (diff)
downloadtrackermap-web-2cd374bb9fa941d7e2a6fd8aa5079893a158c98f.tar.gz
trackermap-web-2cd374bb9fa941d7e2a6fd8aa5079893a158c98f.tar.bz2
trackermap-web-2cd374bb9fa941d7e2a6fd8aa5079893a158c98f.zip
Reorganize remaining files
Diffstat (limited to 'modern/src/main/MainPage.js')
-rw-r--r--modern/src/main/MainPage.js213
1 files changed, 213 insertions, 0 deletions
diff --git a/modern/src/main/MainPage.js b/modern/src/main/MainPage.js
new file mode 100644
index 00000000..569978af
--- /dev/null
+++ b/modern/src/main/MainPage.js
@@ -0,0 +1,213 @@
+import React, { useState, useEffect } from 'react';
+import { useHistory } from 'react-router-dom';
+import {
+ makeStyles, Paper, Toolbar, TextField, IconButton, Button,
+} from '@material-ui/core';
+
+import { useTheme } from '@material-ui/core/styles';
+import useMediaQuery from '@material-ui/core/useMediaQuery';
+import AddIcon from '@material-ui/icons/Add';
+import CloseIcon from '@material-ui/icons/Close';
+import ArrowBackIcon from '@material-ui/icons/ArrowBack';
+import ListIcon from '@material-ui/icons/ViewList';
+
+import { useDispatch, useSelector } from 'react-redux';
+import DevicesList from './DevicesList';
+import Map from '../map/core/Map';
+import SelectedDeviceMap from '../map/main/SelectedDeviceMap';
+import AccuracyMap from '../map/main/AccuracyMap';
+import GeofenceMap from '../map/main/GeofenceMap';
+import CurrentPositionsMap from '../map/main/CurrentPositionsMap';
+import CurrentLocationMap from '../map/CurrentLocationMap';
+import BottomMenu from '../common/components/BottomMenu';
+import { useTranslation } from '../common/components/LocalizationProvider';
+import PoiMap from '../map/main/PoiMap';
+import MapPadding from '../map/MapPadding';
+import StatusCard from './StatusCard';
+import { devicesActions } from '../store';
+import DefaultCameraMap from '../map/main/DefaultCameraMap';
+import usePersistedState from '../common/util/usePersistedState';
+import LiveRoutesMap from '../map/main/LiveRoutesMap';
+import { useDeviceReadonly } from '../common/util/permissions';
+
+const useStyles = makeStyles((theme) => ({
+ root: {
+ height: '100%',
+ },
+ sidebar: {
+ display: 'flex',
+ flexDirection: 'column',
+ position: 'absolute',
+ left: 0,
+ top: 0,
+ zIndex: 3,
+ margin: theme.spacing(1.5),
+ width: theme.dimensions.drawerWidthDesktop,
+ bottom: theme.dimensions.bottomBarHeight,
+ transition: 'transform .5s ease',
+ backgroundColor: 'white',
+ [theme.breakpoints.down('sm')]: {
+ width: '100%',
+ margin: 0,
+ },
+ },
+ sidebarCollapsed: {
+ transform: `translateX(-${theme.dimensions.drawerWidthDesktop})`,
+ marginLeft: 0,
+ [theme.breakpoints.down('sm')]: {
+ transform: 'translateX(-100vw)',
+ },
+ },
+ toolbar: {
+ display: 'flex',
+ padding: theme.spacing(0, 1),
+ '& > *': {
+ margin: theme.spacing(0, 1),
+ },
+ },
+ deviceList: {
+ flex: 1,
+ },
+ statusCard: {
+ position: 'fixed',
+ zIndex: 5,
+ [theme.breakpoints.up('sm')]: {
+ left: `calc(50% + ${theme.dimensions.drawerWidthDesktop} / 2)`,
+ bottom: theme.spacing(3),
+ },
+ [theme.breakpoints.down('sm')]: {
+ left: '50%',
+ bottom: theme.spacing(3) + theme.dimensions.bottomBarHeight,
+ },
+ transform: 'translateX(-50%)',
+ },
+ sidebarToggle: {
+ position: 'absolute',
+ left: theme.spacing(1.5),
+ top: theme.spacing(3),
+ borderRadius: '0px',
+ minWidth: 0,
+ [theme.breakpoints.down('sm')]: {
+ left: 0,
+ },
+ },
+ sidebarToggleText: {
+ marginLeft: theme.spacing(1),
+ [theme.breakpoints.only('xs')]: {
+ display: 'none',
+ },
+ },
+ sidebarToggleBg: {
+ backgroundColor: 'white',
+ color: '#777777',
+ '&:hover': {
+ backgroundColor: 'white',
+ },
+ },
+ bottomMenu: {
+ position: 'fixed',
+ left: theme.spacing(1.5),
+ bottom: theme.spacing(1.5),
+ zIndex: 4,
+ width: theme.dimensions.drawerWidthDesktop,
+ },
+}));
+
+const MainPage = () => {
+ const classes = useStyles();
+ const history = useHistory();
+ const dispatch = useDispatch();
+ const theme = useTheme();
+ const t = useTranslation();
+
+ const deviceReadonly = useDeviceReadonly();
+ const isTablet = useMediaQuery(theme.breakpoints.down('sm'));
+ const isPhone = useMediaQuery(theme.breakpoints.down('xs'));
+
+ const [mapLiveRoutes] = usePersistedState('mapLiveRoutes', false);
+
+ const selectedDeviceId = useSelector((state) => state.devices.selectedId);
+
+ const [searchKeyword, setSearchKeyword] = useState('');
+ const [collapsed, setCollapsed] = useState(false);
+
+ const handleClose = () => {
+ setCollapsed(!collapsed);
+ };
+
+ useEffect(() => setCollapsed(isTablet), [isTablet]);
+
+ return (
+ <div className={classes.root}>
+ <Map>
+ {!isTablet && <MapPadding left={parseInt(theme.dimensions.drawerWidthDesktop, 10)} />}
+ <CurrentLocationMap />
+ <GeofenceMap />
+ <AccuracyMap />
+ {mapLiveRoutes && <LiveRoutesMap />}
+ <CurrentPositionsMap />
+ <DefaultCameraMap />
+ <SelectedDeviceMap />
+ <PoiMap />
+ </Map>
+ <Button
+ variant="contained"
+ color={isPhone ? 'secondary' : 'primary'}
+ classes={{ containedPrimary: classes.sidebarToggleBg }}
+ className={classes.sidebarToggle}
+ onClick={handleClose}
+ disableElevation
+ >
+ <ListIcon />
+ <div className={classes.sidebarToggleText}>{t('deviceTitle')}</div>
+ </Button>
+ <Paper square elevation={3} className={`${classes.sidebar} ${collapsed && classes.sidebarCollapsed}`}>
+ <Paper square elevation={3}>
+ <Toolbar className={classes.toolbar} disableGutters>
+ {isTablet && (
+ <IconButton onClick={handleClose}>
+ <ArrowBackIcon />
+ </IconButton>
+ )}
+ <TextField
+ fullWidth
+ name="searchKeyword"
+ value={searchKeyword}
+ autoComplete="searchKeyword"
+ autoFocus
+ onChange={(event) => setSearchKeyword(event.target.value)}
+ placeholder={t('sharedSearchDevices')}
+ variant="filled"
+ />
+ <IconButton onClick={() => history.push('/device')} disabled={deviceReadonly}>
+ <AddIcon />
+ </IconButton>
+ {!isTablet && (
+ <IconButton onClick={handleClose}>
+ <CloseIcon />
+ </IconButton>
+ )}
+ </Toolbar>
+ </Paper>
+ <div className={classes.deviceList}>
+ <DevicesList filter={searchKeyword} />
+ </div>
+ </Paper>
+ {!isPhone && !isTablet && (
+ <div className={classes.bottomMenu}>
+ <BottomMenu />
+ </div>
+ )}
+ {selectedDeviceId && (
+ <div className={classes.statusCard}>
+ <StatusCard
+ deviceId={selectedDeviceId}
+ onClose={() => dispatch(devicesActions.select(null))}
+ />
+ </div>
+ )}
+ </div>
+ );
+};
+
+export default MainPage;