Skip to content

Commit 5485bda

Browse files
committed
Added map selector
1 parent 18ed279 commit 5485bda

4 files changed

Lines changed: 138 additions & 10 deletions

File tree

Eplant/views/WorldEFP/MapContainer.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import GeneDistributionChart from '../eFP/Viewer/GeneDistributionChart'
1414
import Legend from '../eFP/Viewer/legend'
1515

1616
import MapMarker from './MapMarker'
17+
import MapTypeSelector from './MapTypeSelector'
1718
import { WorldEFPData, WorldEFPState } from './types'
1819

1920
interface MapContainerProps {
@@ -48,7 +49,7 @@ const MapContainer = ({ activeData, state, setState }: MapContainerProps) => {
4849
defaultZoom={2}
4950
mapId={import.meta.env.VITE_MAP_ID}
5051
streetViewControl={false}
51-
mapTypeId={'roadmap'}
52+
mapTypeId={state.mapTypeId}
5253
mapTypeControl={false}
5354
onDragend={hangleDragEnd}
5455
onZoomChanged={handleZoom}
@@ -75,6 +76,22 @@ const MapContainer = ({ activeData, state, setState }: MapContainerProps) => {
7576
></MapMarker>
7677
)
7778
})}
79+
<Box
80+
sx={(theme) => ({
81+
position: 'absolute',
82+
left: theme.spacing(2),
83+
top: theme.spacing(2),
84+
zIndex: 10,
85+
display: 'flex',
86+
flexDirection: 'column',
87+
gap: theme.spacing(1),
88+
})}
89+
>
90+
<MapTypeSelector
91+
mapTypeId={state.mapTypeId}
92+
onSelect={(mapTypeId) => setState({ ...state, mapTypeId })}
93+
/>
94+
</Box>
7895
<Box
7996
sx={(theme) => ({
8097
position: 'absolute',
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import { useState } from 'react'
2+
3+
import MapIcon from '@mui/icons-material/Map'
4+
import { Box, Button, Collapse } from '@mui/material'
5+
import { alpha } from '@mui/material/styles'
6+
7+
import { WorldEFPState } from './types'
8+
9+
const MAP_TYPES = ['roadmap', 'satellite', 'hybrid', 'terrain'] as const
10+
11+
type MapTypeSelectorProps = {
12+
mapTypeId: WorldEFPState['mapTypeId']
13+
onSelect: (mapTypeId: WorldEFPState['mapTypeId']) => void
14+
}
15+
16+
const MapTypeSelector = ({ mapTypeId, onSelect }: MapTypeSelectorProps) => {
17+
const [isOpen, setIsOpen] = useState(false)
18+
19+
const handleMapTypeSelect = (nextType: WorldEFPState['mapTypeId']) => {
20+
onSelect(nextType)
21+
setIsOpen(false)
22+
}
23+
24+
const formatMapTypeLabel = (type: WorldEFPState['mapTypeId']) =>
25+
type.charAt(0).toUpperCase() + type.slice(1)
26+
27+
return (
28+
<Box
29+
sx={(theme) => ({
30+
width: isOpen ? theme.spacing(15) : theme.spacing(5),
31+
borderRadius: theme.spacing(1),
32+
backgroundColor: alpha(theme.palette.background.active, 0.7),
33+
boxShadow: '0 8px 24px rgba(0, 0, 0, 0.18)',
34+
border: `1px solid ${alpha(theme.palette.background.active, 0.7)}`,
35+
backdropFilter: 'blur(8px)',
36+
WebkitBackdropFilter: 'blur(8px)',
37+
overflow: 'hidden',
38+
transition: 'width 220ms ease, box-shadow 220ms ease',
39+
})}
40+
>
41+
<Button
42+
variant='text'
43+
onClick={() => setIsOpen((open) => !open)}
44+
sx={(theme) => ({
45+
width: '100%',
46+
justifyContent: 'flex-start',
47+
textTransform: 'none',
48+
color: theme.palette.text.primary,
49+
padding: theme.spacing(1),
50+
'&:hover': {
51+
backgroundColor: alpha(theme.palette.background.active, 0.85),
52+
},
53+
})}
54+
>
55+
<MapIcon fontSize='small' />
56+
<Box
57+
sx={(theme) => ({
58+
marginLeft: theme.spacing(1),
59+
opacity: isOpen ? 1 : 0,
60+
maxWidth: isOpen ? theme.spacing(12) : 0,
61+
overflow: 'hidden',
62+
whiteSpace: 'nowrap',
63+
transition: 'opacity 200ms ease, max-width 220ms ease',
64+
})}
65+
>
66+
{formatMapTypeLabel(mapTypeId)}
67+
</Box>
68+
</Button>
69+
<Collapse in={isOpen} timeout={200} unmountOnExit>
70+
<Box
71+
sx={(theme) => ({
72+
display: 'flex',
73+
flexDirection: 'column',
74+
gap: theme.spacing(0.5),
75+
padding: theme.spacing(0.5, 1, 1),
76+
})}
77+
>
78+
{MAP_TYPES.map((type) => (
79+
<Button
80+
key={type}
81+
variant='text'
82+
onClick={() => handleMapTypeSelect(type)}
83+
sx={(theme) => ({
84+
justifyContent: 'flex-start',
85+
textTransform: 'none',
86+
color: theme.palette.text.primary,
87+
padding: theme.spacing(0.5, 1),
88+
'&:hover': {
89+
backgroundColor: alpha(
90+
theme.palette.background.active,
91+
0.45
92+
),
93+
},
94+
...(mapTypeId === type && {
95+
fontWeight: 600,
96+
backgroundColor: alpha(
97+
theme.palette.background.active,
98+
0.6
99+
),
100+
borderRadius: theme.spacing(0.75),
101+
'&:hover': {
102+
backgroundColor: alpha(
103+
theme.palette.background.active,
104+
0.7
105+
),
106+
},
107+
}),
108+
})}
109+
>
110+
{formatMapTypeLabel(type)}
111+
</Button>
112+
))}
113+
</Box>
114+
</Collapse>
115+
</Box>
116+
)
117+
}
118+
119+
export default MapTypeSelector

Eplant/views/WorldEFP/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { StateAction, ViewMetadata } from '@eplant/View'
2+
import { Map } from '@mui/icons-material'
23
import BuildRoundedIcon from '@mui/icons-material/BuildRounded'
34
import ColorLensIcon from '@mui/icons-material/ColorLens'
4-
import MasksIcon from '@mui/icons-material/Masks'
55

66
import WorldEFPIcon from './icon'
77
import { WorldEFPData, WorldEFPState } from './types'

Eplant/views/WorldEFP/types.tsx

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,3 @@ export interface WorldEFPMicroArrayData {
4040
values: { [key: string]: number }
4141
code: string
4242
}
43-
44-
export type WorldEFPAction =
45-
| { type: 'toggle-color-mode' }
46-
| { type: 'toggle-masking' }
47-
| { type: 'toggle-mask-modal' }
48-
| { type: 'set-mask-threshold'; threshold: number }
49-
| { type: 'set-map-position'; position: Coordinates }
50-
| { type: 'set-map-zoom'; zoom: number }

0 commit comments

Comments
 (0)