Skip to content

Commit 084cc40

Browse files
authored
Separate Layout (#1)
1 parent 7e39918 commit 084cc40

File tree

7 files changed

+222
-152
lines changed

7 files changed

+222
-152
lines changed

.storybook/main.js

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ module.exports = {
1919
...config.resolve.alias,
2020
'@emotion/core': toPath('node_modules/@emotion/react'),
2121
'emotion-theming': toPath('node_modules/@emotion/react'),
22+
'@geomatico/geocomponents': toPath('node_modules/@geomatico/geocomponents/dist'),
2223
}
2324
}
2425
};

src/components/Layout.js

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import React, {useState} from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
import styled from '@mui/styles/styled';
5+
import useMediaQuery from '@mui/material/useMediaQuery';
6+
import Box from '@mui/material/Box';
7+
8+
import ResponsiveHeader from '@geomatico/geocomponents/ResponsiveHeader';
9+
import SidePanel from '@geomatico/geocomponents/SidePanel';
10+
11+
import {WIDESCREEN_STEP, DRAWER_WIDTH} from '../config';
12+
13+
const MainContent = styled(Box, {
14+
shouldForwardProp: (prop) => prop !== 'leftDrawer'
15+
})(({theme, leftDrawer}) => ({
16+
flexGrow: 1,
17+
padding: 0,
18+
position: 'absolute',
19+
top: theme.mixins.toolbar.minHeight,
20+
bottom: 0,
21+
right: 0,
22+
left: leftDrawer ? DRAWER_WIDTH : 0
23+
}));
24+
25+
const Layout = ({mainContent, sidePanelContent}) => {
26+
const widescreen = useMediaQuery(`(min-width: ${WIDESCREEN_STEP})`, {noSsr: true});
27+
const [isSidePanelOpen, setIsSidePanelOpen] = useState(true);
28+
29+
const handleClose = () => setIsSidePanelOpen(!isSidePanelOpen);
30+
return (
31+
<>
32+
<ResponsiveHeader
33+
onStartIconClick={widescreen ? undefined : handleClose}
34+
title='ROMA CITÁ APERTA'
35+
>
36+
</ResponsiveHeader>
37+
<SidePanel
38+
drawerWidth={DRAWER_WIDTH}
39+
anchor='left'
40+
isOpen={isSidePanelOpen}
41+
onClose={handleClose}
42+
widescreen={widescreen}
43+
>
44+
{sidePanelContent}
45+
</SidePanel>
46+
<MainContent leftDrawer={isSidePanelOpen && widescreen}>
47+
{mainContent}
48+
</MainContent>
49+
</>
50+
);
51+
};
52+
53+
Layout.propTypes = {
54+
sidePanelContent: PropTypes.element.isRequired,
55+
mainContent: PropTypes.element.isRequired
56+
};
57+
58+
export default Layout;

src/components/MainContent.js

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import React, {useEffect, useMemo, useState} from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
import Map from '@geomatico/geocomponents/Map';
5+
6+
import {INITIAL_VIEWPORT, LAYERS} from '../config';
7+
import styled from '@mui/styles/styled';
8+
import {Popup} from 'react-map-gl';
9+
10+
import PopupInfo from '../components/PopupInfo';
11+
import {useDispatch, useSelector} from 'react-redux';
12+
import {getFeatures} from '../modules/api/selectors';
13+
import {apiGetFeatures} from '../modules/api/actions';
14+
15+
const CustomPopup = styled(Popup)({
16+
'& .mapboxgl-popup-content': {
17+
padding: 0
18+
}
19+
});
20+
21+
const MainContent = ({mapStyle}) => {
22+
const [viewport, setViewport] = useState(INITIAL_VIEWPORT);
23+
const [featureClicked, setFeatureClicked] = useState(undefined);
24+
const dispatch = useDispatch();
25+
const data = useSelector(getFeatures);
26+
const sources = useMemo (() => ({
27+
data: {
28+
type: 'geojson',
29+
data: data
30+
},
31+
quartieri: {
32+
type: 'geojson',
33+
data: 'carto/quartieri-roma.geojson'
34+
}
35+
})
36+
);
37+
const layers = useMemo (() => LAYERS, []);
38+
useEffect(() => {
39+
dispatch(apiGetFeatures());
40+
}, []);
41+
const onViewportChange = (viewport) =>
42+
setViewport({
43+
...viewport
44+
});
45+
const handleOnClick = (e) => setFeatureClicked(e.features && e.features[0]);
46+
return <Map
47+
mapStyle={mapStyle}
48+
viewport={viewport}
49+
onViewportChange={onViewportChange}
50+
sources={sources}
51+
layers={layers}
52+
interactiveLayerIds={layers.map(({id}) => id)}
53+
onClick={handleOnClick}
54+
// mapboxAccessToken={process.env.MAPBOX_ACCESS_TOKEN} // Token necesario para ver datos de mapbox o usar mapbox-gl-js v2 (react-map-gl 6)
55+
>
56+
{
57+
featureClicked &&
58+
<CustomPopup
59+
longitude={featureClicked.geometry.coordinates[0]}
60+
latitude={featureClicked.geometry.coordinates[1]}
61+
anchor="bottom"
62+
closeButton={false}
63+
>
64+
<PopupInfo
65+
name={featureClicked.properties.name}
66+
style={featureClicked.properties.style}
67+
author={featureClicked.properties.author}
68+
description={featureClicked.properties.description}
69+
price={featureClicked.properties.price}
70+
other={featureClicked.properties.other}
71+
image={featureClicked.properties.image}
72+
plan={featureClicked.properties.plan}
73+
/>
74+
</CustomPopup>
75+
}
76+
</Map>;
77+
};
78+
79+
MainContent.propTypes = {
80+
mapStyle: PropTypes.string.isRequired
81+
};
82+
83+
export default MainContent;

src/components/SidePanelContent.js

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
import Box from '@mui/material/Box';
5+
import Stack from '@mui/material/Stack';
6+
7+
import BaseMapList from '@geomatico/geocomponents/BaseMapList';
8+
import MapLegend from '@geomatico/geocomponents/MapLegend';
9+
10+
import SectionTitle from './SectionTitle';
11+
12+
import {LEGEND, MAPSTYLES} from '../config';
13+
14+
const SidePanelContent = ({mapStyle, onMapStyleChanged}) => {
15+
return <Stack justifyContent='space-between' sx={{height: '93.5vh'}}>
16+
<Box>
17+
<Box mb={2}>
18+
<SectionTitle titleKey="Estilo Mapa Base"/>
19+
<BaseMapList
20+
styles={MAPSTYLES}
21+
selectedStyleUrl={mapStyle}
22+
onStyleChange={onMapStyleChanged}
23+
typographyStyleProps={{fontSize: 14}}
24+
/>
25+
</Box>
26+
<Box mb={2}>
27+
<SectionTitle titleKey="Leyenda"/>
28+
<MapLegend fields={LEGEND}
29+
sx={{
30+
'& .MapLegend-swatch': {
31+
margin: '0px 8px 0px 0px',
32+
width: 20,
33+
},
34+
'& .MapLegend-text': {
35+
fontSize: 14
36+
}}
37+
}
38+
/>
39+
</Box>
40+
</Box>
41+
</Stack>;
42+
};
43+
44+
SidePanelContent.propTypes = {
45+
mapStyle: PropTypes.string.isRequired,
46+
onMapStyleChanged: PropTypes.func.isRequired
47+
};
48+
49+
export default SidePanelContent;

src/config.js

+10-9
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,15 @@ export const LEGEND = [
113113
},
114114
];
115115
export const LAYERS = [
116+
{
117+
id: 'quartieri',
118+
source: 'quartieri',
119+
type: 'line',
120+
paint: {
121+
'line-color': '#000',
122+
'line-width': 2
123+
}
124+
},
116125
{
117126
id: 'data',
118127
source: 'data',
@@ -131,13 +140,5 @@ export const LAYERS = [
131140
]
132141
}
133142
},
134-
/*{
135-
id: 'quartieri',
136-
source: 'quartieri',
137-
type: 'line',
138-
paint: {
139-
'line-color': '#000',
140-
'line-width': 2
141-
}
142-
}*/
143+
143144
];

src/routes/routes.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import React from 'react';
22
import {HashRouter, Routes, Route} from 'react-router-dom';
3-
import Viewer from '../views/Home';
3+
import Home from '../views/Home';
44

55
const AppRoutes = () =>
66
<HashRouter>
77
<Routes>
8-
<Route exact path='/' element={<Viewer/>}/>
8+
<Route exact path='/' element={<Home/>}/>
99
</Routes>
1010
</HashRouter>;
1111

0 commit comments

Comments
 (0)