diff --git a/server/src/graphql/resolvers.js b/server/src/graphql/resolvers.js index 6c4751011..6e10fe204 100644 --- a/server/src/graphql/resolvers.js +++ b/server/src/graphql/resolvers.js @@ -214,10 +214,9 @@ module.exports = { }) } }) - return filtered } - return scanAreas + return scanAreas.filter((parent) => parent.children.length) } return [] }, diff --git a/src/components/layout/drawer/AreaTile.jsx b/src/components/layout/drawer/AreaTile.jsx new file mode 100644 index 000000000..ad8178ab2 --- /dev/null +++ b/src/components/layout/drawer/AreaTile.jsx @@ -0,0 +1,101 @@ +import React from 'react' +import { Grid, MenuItem, Typography, Checkbox } from '@material-ui/core' +import { useMap } from 'react-leaflet' + +import Utility from '@services/Utility' +import { useStore } from '@hooks/useStore' + +export default function AreaTile({ + name, + feature, + childAreas, + scanAreasZoom, + allAreas, + i, +}) { + const { scanAreas } = useStore((s) => s.filters) + const setAreas = useStore((s) => s.setAreas) + const map = useMap() + + if (!scanAreas) return null + + const hasAll = + childAreas && + childAreas.every((c) => scanAreas.filter.areas.includes(c.properties.name)) + const hasSome = + childAreas && + childAreas.some((c) => scanAreas.filter.areas.includes(c.properties.name)) + const hasManual = childAreas + ? childAreas.some((c) => c.properties.manual) + : feature.properties.manual + + return ( + + { + if (feature?.properties) { + map.flyTo( + feature.properties.center, + feature.properties.zoom || scanAreasZoom, + ) + } + }} + > + + + + {name || feature.properties.name ? ( + Utility.getProperName(name || feature.properties.name) + ) : ( + <>  + )} + + + {!hasManual && ( + + + setAreas( + name + ? childAreas.map((c) => c.properties.name) + : feature.properties.name, + allAreas, + name ? hasSome : false, + ) + } + disabled={!childAreas.length} + /> + + )} + + + + ) +} diff --git a/src/components/layout/drawer/Areas.jsx b/src/components/layout/drawer/Areas.jsx index 97d36b405..d9003acdf 100644 --- a/src/components/layout/drawer/Areas.jsx +++ b/src/components/layout/drawer/Areas.jsx @@ -1,136 +1,83 @@ import React from 'react' import { useQuery } from '@apollo/client' -import { Grid, Paper, MenuItem, Typography, Checkbox } from '@material-ui/core' -import { useMap } from 'react-leaflet' +import { Grid, Button, Paper } from '@material-ui/core' +import { useTranslation } from 'react-i18next' -import Utility from '@services/Utility' import Query from '@services/Query' import { useStore } from '@hooks/useStore' +import AreaTile from './AreaTile' export default function AreaDropDown({ scanAreaMenuHeight, scanAreasZoom }) { const { data, loading, error } = useQuery(Query.scanAreasMenu()) - const map = useMap() - const { scanAreas } = useStore((s) => s.filters) + const { t } = useTranslation() const setAreas = useStore((s) => s.setAreas) + const allAreas = React.useMemo(() => { + if (data?.scanAreasMenu) { + return data.scanAreasMenu.flatMap((parent) => + parent.children.map((child) => child.properties.name), + ) + } + return [] + }, [data]) + if (loading || error) return null return ( - - {data?.scanAreasMenu?.map(({ name, details, children }) => ( - + + + + + {data?.scanAreasMenu?.map(({ name, details, children }) => ( + + {name && ( + + )} + {children.map((feature, i) => ( + + ))} + + ))} + + ) } diff --git a/src/hooks/useStore.js b/src/hooks/useStore.js index 4f2e897f2..7e214920a 100644 --- a/src/hooks/useStore.js +++ b/src/hooks/useStore.js @@ -10,8 +10,19 @@ export const useStore = create( setZoom: (zoom) => set({ zoom }), filters: undefined, setFilters: (filters) => set({ filters }), - setAreas: (area) => { + setAreas: (areas = [], validAreas = [], unselectAll = false) => { const { filters } = get() + const incoming = new Set(Array.isArray(areas) ? areas : [areas]) + const existing = new Set(filters?.scanAreas?.filter?.areas || []) + + incoming.forEach((area) => { + if (existing.has(area) || unselectAll) { + existing.delete(area) + } else { + existing.add(area) + } + }) + if (filters?.scanAreas?.filter?.areas) { set({ filters: { @@ -20,9 +31,9 @@ export const useStore = create( ...filters.scanAreas, filter: { ...filters.scanAreas.filter, - areas: filters.scanAreas.filter.areas.includes(area) - ? filters.scanAreas.filter.areas.filter((a) => a !== area) - : [...filters.scanAreas.filter.areas, area], + areas: [...existing].filter((area) => + validAreas.includes(area), + ), }, }, },