diff --git a/src/components/map/index.tsx b/src/components/map/index.tsx index c21e5bf91..3c41117a0 100644 --- a/src/components/map/index.tsx +++ b/src/components/map/index.tsx @@ -136,7 +136,7 @@ export const CustomMap: FC = ({ return (
diff --git a/src/components/map/legend/sortable/item.tsx b/src/components/map/legend/sortable/item.tsx index 68b83f32b..8d31b2066 100644 --- a/src/components/map/legend/sortable/item.tsx +++ b/src/components/map/legend/sortable/item.tsx @@ -36,7 +36,7 @@ export const SortableItem: React.FC = ({ 'opacity-0': isDragging, })} style={style} - {...(!sortable?.handle && { + {...(sortable?.handle && { ...listeners, ...attributes, })} diff --git a/src/components/map/legend/sortable/list.tsx b/src/components/map/legend/sortable/list.tsx index f0efd7d36..1af05f9b4 100644 --- a/src/components/map/legend/sortable/list.tsx +++ b/src/components/map/legend/sortable/list.tsx @@ -96,7 +96,7 @@ export const SortableList: React.FC = ({ if (active.id !== over?.id) { const oldIndex = itemsIds.indexOf(active.id); - const newIndex = itemsIds.indexOf(over.id); + const newIndex = itemsIds.indexOf(over?.id); if (onChangeOrder) onChangeOrder(arrayMove(itemsIds, oldIndex, newIndex)); } diff --git a/src/containers/datasets/restoration/overview/hooks.tsx b/src/containers/datasets/restoration/overview/hooks.tsx index 76ed98303..0ce9b79f1 100644 --- a/src/containers/datasets/restoration/overview/hooks.tsx +++ b/src/containers/datasets/restoration/overview/hooks.tsx @@ -1,5 +1,3 @@ -import type { SourceProps, LayerProps } from 'react-map-gl'; - import { useRouter } from 'next/router'; import { numberFormat } from 'lib/format'; diff --git a/src/containers/embedded/map/index.tsx b/src/containers/embedded/map/index.tsx index bc7c85b56..9d1107b2f 100644 --- a/src/containers/embedded/map/index.tsx +++ b/src/containers/embedded/map/index.tsx @@ -120,7 +120,7 @@ const EmbeddedMap = ({ mapId }: { mapId: string }) => { > {() => } -
+
diff --git a/src/containers/map/index.tsx b/src/containers/map/index.tsx index 8a614b4c0..560d3149b 100644 --- a/src/containers/map/index.tsx +++ b/src/containers/map/index.tsx @@ -37,7 +37,6 @@ import Legend from 'containers/map/legend'; import MobileLegend from 'containers/map/mobile/legend'; import RestorationPopup from 'containers/map/restoration-popup'; -import Icon from 'components/icon'; import Map from 'components/map'; import Controls from 'components/map/controls'; import BasemapSettingsControl from 'components/map/controls/basemap-settings'; @@ -53,8 +52,6 @@ import Popup from 'components/popup'; import { breakpoints } from 'styles/styles.config'; import type { RestorationPopUp, PopUpKey, LocationPopUp } from 'types/map'; -import CLOSE_SVG from 'svgs/ui/close.svg?sprite'; - import LayerManager from './layer-manager'; import LocationPopup from './location-pop-up'; @@ -336,7 +333,7 @@ const MapContainer = ({ mapId }: { mapId: string }) => { const pitch = map?.getPitch(); return (
{ onSetCustomPolygon={handleCustomPolygon} /> )} - + { const [activeLayers, setActiveLayers] = useRecoilState(activeLayersAtom); - const guideIsActive = useRecoilValue(activeGuideAtom); const [isOpen, setIsOpen] = useState(false); - const [sortArray, setSortArray] = useState([]); - - const onChangeVisibility = useCallback( - (layer) => { - const layersWithVisibility: ActiveLayers[] = activeLayers.map((l) => { - if (l.id === layer) { - return { ...l, visibility: l.visibility === 'visible' ? 'none' : 'visible' }; - } - if (l.id === 'custom-area') { - return null; - } - return l; - }); - - setActiveLayers(layersWithVisibility); - }, - [activeLayers, setActiveLayers] - ); - - const nationalDashboardLayerName = activeLayers.find((l) => - l.id.includes('mangrove_national_dashboard_layer') - )?.settings?.name; - - const removeLayer = useCallback( - (layer: string) => { - const updatedLayers = activeLayers.filter((l) => { - return l.id !== layer; - }); - setActiveLayers(updatedLayers); - }, - [activeLayers, setActiveLayers] - ); - - const layerName = (label) => { - return LAYERS.find((w) => w.id === label)?.name; - }; const openLegend = useCallback(() => { if (!!activeLayers.length) setIsOpen(true); @@ -81,33 +27,17 @@ const Legend = ({ embedded = false }: { embedded?: boolean }) => { setIsOpen(false); }, []); - const onChangeOrder = useCallback( - (ids: string[]) => { - setSortArray(ids); - const sortedLayers = activeLayers.sort( - (a, b) => sortArray.indexOf(a.id) - sortArray.indexOf(b.id) - ); - setActiveLayers(sortedLayers); - }, - [activeLayers, sortArray, setActiveLayers] - ); - - const onChangeOpacity = useCallback( - (op: number, layer: string) => { - const layersWithOpacity = activeLayers.map((l) => { - if (l.id === layer) { - return { ...l, opacity: op.toString() }; - } - return l; - }); + const handleChangeOrder = useCallback( + (order: string[]) => { + const newLayers = order.map((id) => { + return activeLayers.find((l) => l.id === id); + }) as ActiveLayers[]; - setActiveLayers(layersWithOpacity); + setActiveLayers(newLayers); }, [activeLayers, setActiveLayers] ); - const HELPER_ID = activeLayers[0]?.id; - const contentVariants = { open: { y: '-100%', opacity: 1 }, close: { y: '10%', opacity: 0 }, @@ -139,216 +69,16 @@ const Legend = ({ embedded = false }: { embedded?: boolean }) => { animate={isOpen ? 'open' : 'close'} exit="close" transition={{ type: 'spring', bounce: 0, duration: 0.8 }} - className={cn({ - fixed: true, - 'md:right-[73px]': !embedded, - 'right-7': embedded, - })} + className="absolute md:right-0" > -
-
- +
+
+ {activeLayers.map((l) => { - if (l.id === 'custom-area') return null; - const layerId = Object.keys(MAP_LEGENDS).find((k) => l.id.includes(k)); - const WidgetLegend = MAP_LEGENDS[layerId] as React.ElementType; - - const widgetId = l.id.includes('mangrove_national_dashboard_layer') - ? 'mangrove_national_dashboard' - : l.id; - - const Widget = WIDGETS[widgetId] as React.ElementType; - - const visibility = l.visibility === 'visible'; - - const layerNameToDisplay = layerName(l.id); - if ( - layerNameToDisplay === undefined && - !l.id.includes('mangrove_national_dashboard_layer') - ) - return null; - - const title = - l.id.includes('mangrove_national_dashboard_layer') && - nationalDashboardLayerName - ? `National Dashboard` - : layerNameToDisplay; - - return ( -
-
-
- {!embedded && ( - - )} - -

- {title} -

-
- {!embedded && ( - -
- - - - - - - - - Info layer - - - - - - -
- - - -
- -
-
- - - - -
- -
-
- - - - Opacity - - -
-
- - - - onChangeOpacity(op[0], l.id) - } - /> - -
- - - - - - - - {visibility ? 'Hide' : 'Show'} - - - - - - - - - - - Remove layer - - - -
-
- )} -
- - {WidgetLegend && ( -
- -
- )} -
- ); + return ; })}
diff --git a/src/containers/map/legend/item/index.tsx b/src/containers/map/legend/item/index.tsx new file mode 100644 index 000000000..3211c433b --- /dev/null +++ b/src/containers/map/legend/item/index.tsx @@ -0,0 +1,258 @@ +import { useCallback } from 'react'; + +import cn from 'lib/classnames'; + +import { activeGuideAtom } from 'store/guide'; +import { activeLayersAtom } from 'store/layers'; + +import { useRecoilValue, useRecoilState } from 'recoil'; + +import { MAP_LEGENDS, WIDGETS } from 'containers/datasets'; +import Helper from 'containers/guide/helper'; +import { LAYERS } from 'containers/layers/constants'; +import WidgetWrapper from 'containers/widget'; + +import { Dialog, DialogContent, DialogTrigger, DialogClose } from 'components/dialog'; +import Icon from 'components/icon'; +import { Popover, PopoverContent, PopoverTrigger } from 'components/popover'; +import Slider from 'components/slider'; +import { Tooltip, TooltipContent, TooltipPortal, TooltipTrigger } from 'components/tooltip'; +import type { ActiveLayers } from 'types/layers'; +import type { WidgetSlugType } from 'types/widget'; + +import CLOSE_SVG from 'svgs/legend/close-legend.svg?sprite'; +import DRAG_SVG from 'svgs/legend/drag.svg?sprite'; +import HIDE_SVG from 'svgs/legend/hide.svg?sprite'; +import INFO_SVG from 'svgs/legend/info-legend.svg?sprite'; +import OPACITY_SVG from 'svgs/legend/opacity.svg?sprite'; +import SHOW_SVG from 'svgs/legend/show.svg?sprite'; + +const LegendItem = ({ + id, + embedded = false, + l, +}: { + id: string; + embedded?: boolean; + l: ActiveLayers; +}) => { + const [activeLayers, setActiveLayers] = useRecoilState(activeLayersAtom); + const guideIsActive = useRecoilValue(activeGuideAtom); + + const onChangeVisibility = useCallback( + (layer) => { + const layersWithVisibility: ActiveLayers[] = activeLayers.map((l) => { + if (l.id === layer) { + return { ...l, visibility: l.visibility === 'visible' ? 'none' : 'visible' }; + } + if (l.id === 'custom-area') { + return null; + } + return l; + }); + + setActiveLayers(layersWithVisibility); + }, + [activeLayers, setActiveLayers] + ); + + const nationalDashboardLayerName = activeLayers.find((l) => + l.id.includes('mangrove_national_dashboard_layer') + )?.settings?.name; + + const removeLayer = useCallback( + (layer: string) => { + const updatedLayers = activeLayers.filter((l) => { + return l.id !== layer; + }); + setActiveLayers(updatedLayers); + }, + [activeLayers, setActiveLayers] + ); + + const layerName = (label) => { + return LAYERS.find((w) => w.id === label)?.name; + }; + + const onChangeOpacity = useCallback( + (op: number, layer: string) => { + const layersWithOpacity = activeLayers.map((l) => { + if (l.id === layer) { + return { ...l, opacity: op.toString() }; + } + return l; + }); + + setActiveLayers(layersWithOpacity); + }, + [activeLayers, setActiveLayers] + ); + + const HELPER_ID = activeLayers[0]?.id; + + const layerId = Object.keys(MAP_LEGENDS).find((k) => l.id.includes(k)); + const WidgetLegend = MAP_LEGENDS[layerId] as React.ElementType; + + const widgetId = l.id.includes('mangrove_national_dashboard_layer') + ? 'mangrove_national_dashboard' + : l.id; + + const Widget = WIDGETS[widgetId] as React.ElementType; + + const visibility = l.visibility === 'visible'; + + const layerNameToDisplay = layerName(l.id); + if (layerNameToDisplay === undefined && !l.id.includes('mangrove_national_dashboard_layer')) + return null; + + const title = + l.id.includes('mangrove_national_dashboard_layer') && nationalDashboardLayerName + ? `National Dashboard` + : layerNameToDisplay; + + if (l.id === 'custom-area') return null; + + return ( +
+
+
+ {!embedded && ( + + )} + +

{title}

+
+ {!embedded && ( + +
+ + + + + + + + + Info layer + + + + + + +
+ + + +
+ +
+
+ + + + +
+ +
+
+ + + + Opacity + + +
+
+ + + onChangeOpacity(op[0], l.id)} + /> + +
+ + + + + + + + {visibility ? 'Hide' : 'Show'} + + + + + + + + + + + Remove layer + + + +
+
+ )} +
+ + {WidgetLegend && ( +
+ +
+ )} +
+ ); +}; + +export default LegendItem; diff --git a/src/containers/map/location-pop-up/index.tsx b/src/containers/map/location-pop-up/index.tsx index 6646b9159..d271edf10 100644 --- a/src/containers/map/location-pop-up/index.tsx +++ b/src/containers/map/location-pop-up/index.tsx @@ -139,7 +139,7 @@ const LocationPopUP = ({ {name} - + {type} @@ -159,7 +159,7 @@ const LocationPopUP = ({ {info.protectedArea.ORIG_NAME}
- + Protected area diff --git a/src/containers/navigation/index.tsx b/src/containers/navigation/index.tsx index 7f4bf88a2..cb1cb2bff 100644 --- a/src/containers/navigation/index.tsx +++ b/src/containers/navigation/index.tsx @@ -7,7 +7,7 @@ import News from 'containers/navigation/news'; const HELPER_ID = 'menu-categories'; const AppTools = () => ( -
+
diff --git a/src/containers/navigation/mobile/index.tsx b/src/containers/navigation/mobile/index.tsx index 9f9960f4a..a72f05cd3 100644 --- a/src/containers/navigation/mobile/index.tsx +++ b/src/containers/navigation/mobile/index.tsx @@ -7,7 +7,7 @@ import News from 'containers/navigation/mobile/news'; const NavigationMobile = () => { return (
-
+
diff --git a/src/containers/widget/index.tsx b/src/containers/widget/index.tsx index 4af3c20b8..f080844e5 100644 --- a/src/containers/widget/index.tsx +++ b/src/containers/widget/index.tsx @@ -63,7 +63,7 @@ const WidgetWrapper: FC = (props: WidgetLayoutProps) => { exit="expanded" transition={{ type: 'tween', bounce: 0, duration: 0.6 }} className={cn({ - 'md:h-fit-content z-2 group w-full rounded-4xl border border-[#DADED0] bg-white px-1 py-1 shadow-widget md:ml-[3%] md:ml-0 print:!w-[90%]': + 'md:h-fit-content z-2 group w-full rounded-4xl border border-[#DADED0] bg-white px-1 py-1 shadow-widget print:!w-[90%] md:ml-[3%] md:ml-0': true, '!w-[100%] border-none !p-0 !shadow-none': info, [className]: !!className, diff --git a/src/containers/widgets/index.tsx b/src/containers/widgets/index.tsx index e7e98e2d3..261108f39 100644 --- a/src/containers/widgets/index.tsx +++ b/src/containers/widgets/index.tsx @@ -128,7 +128,7 @@ const WidgetsContainer: React.FC = () => { type="button" data-testid="configure-widgets-button" className={cn({ - 'flex h-8 w-[262px] items-center justify-center rounded-4xl bg-white py-1 px-10 font-sans text-sm font-semibold text-brand-800 shadow-control transition-colors md:ml-0 print:hidden': + 'flex h-8 w-[262px] items-center justify-center rounded-4xl bg-white py-1 px-10 font-sans text-sm font-semibold text-brand-800 shadow-control transition-colors print:hidden md:ml-0': true, })} > diff --git a/src/layouts/widgets/index.tsx b/src/layouts/widgets/index.tsx index 7398ebe8e..35a4cddcf 100644 --- a/src/layouts/widgets/index.tsx +++ b/src/layouts/widgets/index.tsx @@ -1,9 +1,6 @@ import { PropsWithChildren } from 'react'; -import cn from 'lib/classnames'; - import { fullScreenAtom } from 'store/map-settings'; -import { printModeState } from 'store/print-mode'; import { AnimatePresence, motion } from 'framer-motion'; import { useRecoilValue } from 'recoil'; @@ -13,7 +10,6 @@ import LocationWidget from 'containers/location-widget'; const WidgetsLayout = (props: PropsWithChildren) => { const { children } = props; const isFullScreen = useRecoilValue(fullScreenAtom); - const isPrintingMode = useRecoilValue(printModeState); return ( @@ -30,7 +26,7 @@ const WidgetsLayout = (props: PropsWithChildren) => { transition={{ duration: 0.4, }} - className="left-0 h-full w-screen py-14 scrollbar-hide md:absolute md:top-0 md:w-[560px] md:overflow-y-auto md:bg-transparent md:px-4 print:bg-transparent print:px-0" + className="left-0 h-full w-screen py-14 scrollbar-hide print:bg-transparent print:px-0 md:absolute md:top-0 md:w-[560px] md:overflow-y-auto md:bg-transparent md:px-4" > {children} diff --git a/tailwind.config.js b/tailwind.config.js index 2bb029ef4..8239a301b 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -21,9 +21,6 @@ module.exports = { plugins: [animate, forms, lineClamp, typography, scrollBar], theme: { extend: { - screens: { - print: { raw: 'print, (max-width: 1024px)' }, - }, backgroundImage: { rufiji: "url('/images/highlighted-places/rufiji.jpg')", saloum: "url('/images/highlighted-places/saloum.png')",