diff --git a/app/hooks/map/constants.tsx b/app/hooks/map/constants.tsx
index b1b2d2e050..91cd0faa40 100644
--- a/app/hooks/map/constants.tsx
+++ b/app/hooks/map/constants.tsx
@@ -65,7 +65,7 @@ export const COLORS = {
include: '#03E7D1',
exclude: '#FF472E',
available: '#FFCA42',
- cost: ['#FFBFB7', '#C21701'],
+ cost: ['#3C1002', '#FF440A'],
frequency: ['#0C2C32', '#006D83', '#008B8C', '#0BC6C2'],
compare: {
'#1F1F1F': ['00'],
@@ -182,21 +182,26 @@ export const LEGEND_LAYERS = {
}),
// WDPA
- 'wdpa-preview': () => ({
- id: 'wdpa-preview',
- name: 'Protected areas preview',
- icon: (
-
- ),
- settingsManager: {
- opacity: true,
- visibility: true,
- },
- }),
+ 'wdpa-preview': (options: { onChangeVisibility: () => void }) => {
+ const { onChangeVisibility } = options;
+
+ return {
+ id: 'wdpa-preview',
+ name: 'Protected areas preview',
+ icon: (
+
+ ),
+ settingsManager: {
+ opacity: true,
+ visibility: true,
+ },
+ onChangeVisibility,
+ };
+ },
'wdpa-percentage': () => ({
id: 'wdpa-percentage',
name: 'Protected areas',
@@ -245,22 +250,20 @@ export const LEGEND_LAYERS = {
}) => {
const { items, onChangeVisibility } = options;
- return items.map(({ name, id, color }) => {
- return {
- id,
- name,
- type: 'basic' as LegendItemType,
- icon: ,
- settingsManager: {
- opacity: true,
- visibility: true,
- },
- items: [],
- onChangeVisibility: () => {
- onChangeVisibility?.(id);
- },
- };
- });
+ return items.map(({ name, id, color }) => ({
+ id,
+ name,
+ type: 'basic' as LegendItemType,
+ icon: ,
+ settingsManager: {
+ opacity: true,
+ visibility: true,
+ },
+ items: [],
+ onChangeVisibility: () => {
+ onChangeVisibility?.(id);
+ },
+ }));
},
'features-preview': (options: UseLegend['options']) => {
@@ -363,12 +366,15 @@ export const LEGEND_LAYERS = {
// };
},
// !this config aims to replace the original cost config
- 'cost-surface': (options: { items: { min: number; max: number; name: string }[] }) => {
- const { items } = options;
+ 'cost-surface': (options: {
+ costSurface: { name: string; min: number; max: number };
+ onChangeVisibility: () => void;
+ }) => {
+ const { costSurface, onChangeVisibility } = options;
- return items.map(({ name, min, max }) => ({
- id: `cost-surface-${name}`,
- name,
+ return {
+ id: 'cost-surface',
+ name: costSurface.name,
type: 'gradient' as LegendItemType,
settingsManager: {
opacity: true,
@@ -377,34 +383,15 @@ export const LEGEND_LAYERS = {
items: [
{
color: COLORS.cost[0],
- value: `${min === max ? 0 : min}`,
+ value: `${costSurface.min === costSurface.max ? 0 : costSurface.min}`,
},
{
color: COLORS.cost[1],
- value: `${max}`,
+ value: `${costSurface.max}`,
},
],
- }));
-
- // return {
- // id: 'cost-surface',
- // name: 'Cost Surface',
- // type: 'gradient',
- // settingsManager: {
- // opacity: true,
- // visibility: true,
- // },
- // items: [
- // {
- // color: COLORS.cost[0],
- // value: `${min === max ? 0 : min}`,
- // },
- // {
- // color: COLORS.cost[1],
- // value: `${max}`,
- // },
- // ],
- // };
+ onChangeVisibility,
+ };
},
cost: (options) => {
const {
diff --git a/app/layout/project/sidebar/project/inventory-panel/features/index.tsx b/app/layout/project/sidebar/project/inventory-panel/features/index.tsx
index 4be2fc53db..c1973c35cc 100644
--- a/app/layout/project/sidebar/project/inventory-panel/features/index.tsx
+++ b/app/layout/project/sidebar/project/inventory-panel/features/index.tsx
@@ -8,7 +8,10 @@ import {
setLayerSettings,
} from 'store/slices/projects/[id]';
+import chroma from 'chroma-js';
+
import { useAllFeatures } from 'hooks/features';
+import { COLORS } from 'hooks/map/constants';
import ActionsMenu from 'layout/project/sidebar/project/inventory-panel/features/actions-menu';
import FeaturesBulkActionMenu from 'layout/project/sidebar/project/inventory-panel/features/bulk-action-menu';
@@ -31,9 +34,11 @@ const FEATURES_TABLE_COLUMNS = [
const InventoryPanelFeatures = ({ noData: noDataMessage }: { noData: string }): JSX.Element => {
const dispatch = useAppDispatch();
- const { selectedFeatures: visibleFeatures, search } = useAppSelector(
- (state) => state['/projects/[id]']
- );
+ const {
+ selectedFeatures: visibleFeatures,
+ search,
+ layerSettings,
+ } = useAppSelector((state) => state['/projects/[id]']);
const [filters, setFilters] = useState[1]>({
sort: FEATURES_TABLE_COLUMNS[0].name,
@@ -49,14 +54,23 @@ const InventoryPanelFeatures = ({ noData: noDataMessage }: { noData: string }):
search,
},
{
- select: ({ data }) =>
- data?.map((feature) => ({
- id: feature.id,
- name: feature.featureClassName,
- scenarios: feature.scenarioUsageCount,
- tag: feature.tag,
- isCustom: feature.isCustom,
- })),
+ select: ({ data }) => {
+ return data?.map((feature, index) => {
+ const color =
+ data.length > COLORS['features-preview'].ramp.length
+ ? chroma.scale(COLORS['features-preview'].ramp).colors(data.length)[index]
+ : COLORS['features-preview'].ramp[index];
+
+ return {
+ id: feature.id,
+ name: feature.featureClassName,
+ scenarios: feature.scenarioUsageCount,
+ tag: feature.tag,
+ isCustom: feature.isCustom,
+ color,
+ };
+ });
+ },
placeholderData: { data: [] },
keepPreviousData: true,
}
@@ -108,23 +122,27 @@ const InventoryPanelFeatures = ({ noData: noDataMessage }: { noData: string }):
}
dispatch(setVisibleFeatures(newSelectedFeatures));
+ const selectedFeature = allFeaturesQuery.data.find(({ id }) => featureId === id);
+ const { color } = selectedFeature || {};
+
dispatch(
setLayerSettings({
id: featureId,
settings: {
visibility: !isIncluded,
+ color,
},
})
);
},
- [dispatch, visibleFeatures]
+ [dispatch, visibleFeatures, allFeaturesQuery.data]
);
const displayBulkActions = selectedFeaturesIds.length > 0;
const data: DataItem[] = allFeaturesQuery.data?.map((feature) => ({
...feature,
- isVisibleOnMap: visibleFeatures.includes(feature.id),
+ isVisibleOnMap: layerSettings[feature.id]?.visibility ?? false,
}));
return (
diff --git a/app/layout/projects/show/map/legend/hooks/index.ts b/app/layout/projects/show/map/legend/hooks/index.ts
index 9b13a9b432..5b100fda92 100644
--- a/app/layout/projects/show/map/legend/hooks/index.ts
+++ b/app/layout/projects/show/map/legend/hooks/index.ts
@@ -11,12 +11,17 @@ import { COLORS, LEGEND_LAYERS } from 'hooks/map/constants';
import { useProjectWDPAs } from 'hooks/wdpa';
import { Feature } from 'types/api/feature';
+import { WDPA } from 'types/api/wdpa';
export const useCostSurfaceLegend = () => {
const { selectedCostSurfaces } = useAppSelector((state) => state['/projects/[id]']);
const { query } = useRouter();
- const { pid } = query as { pid: string };
+ const { pid } = query as { pid: string; sid: string };
+
+ const dispatch = useAppDispatch();
+ const { layerSettings } = useAppSelector((state) => state['/projects/[id]']);
+ // TODO: pending on API to provide the cost surfaces associated to the project.
const costSurfaceQuery = useProjectCostSurfaces(
pid,
{},
@@ -25,31 +30,35 @@ export const useCostSurfaceLegend = () => {
}
);
- // todo: uncomment when API is ready
- // return LEGEND_LAYERS['cost-surface']({
- // items: costSurfaceQuery.data?.map(({ name, min = 1, max = 8 }) => ({ name, min, max })) || [],
- // });
-
return LEGEND_LAYERS['cost-surface']({
- items: [
- { name: 'Cost Surface 2', min: 1, max: 22 },
- { name: 'Cost Surface 4', min: 1, max: 11 },
- { name: 'Cost Surface 5', min: 1, max: 5 },
- ],
+ costSurface: { name: 'Cost Surface 4', min: 1, max: 11 },
+ onChangeVisibility: () => {
+ dispatch(
+ setLayerSettings({
+ id: 'cost-surface',
+ settings: {
+ visibility: !layerSettings['cost-surface']?.visibility,
+ },
+ })
+ );
+ },
});
};
export const useConservationAreasLegend = () => {
const { query } = useRouter();
const { pid } = query as { pid: string };
- const { selectedWDPAs } = useAppSelector((state) => state['/projects/[id]']);
+ const dispatch = useAppDispatch();
+ const { layerSettings } = useAppSelector((state) => state['/projects/[id]']);
const protectedAreaQuery = useProjectWDPAs(
pid,
- {},
- { select: (data) => data.filter(({ id }) => selectedWDPAs.includes(id)) }
+ {}
+ // { select: (data) => data.map(({ }) => )}
);
+ console.log({ data: protectedAreaQuery?.data });
+
// todo: uncomment when API is ready
// return LEGEND_LAYERS['designated-areas']({
// items: protectedAreaQuery.data?.map(({ id }) => ({ name: id })) || [],
@@ -61,7 +70,16 @@ export const useConservationAreasLegend = () => {
{ name: 'WDPA 2', id: '2' },
{ name: 'WDPA 3', id: '3' },
],
- onChangeVisibility: () => {},
+ onChangeVisibility: (WDPAId: WDPA['id']) => {
+ dispatch(
+ setLayerSettings({
+ id: WDPAId,
+ settings: {
+ visibility: !layerSettings[WDPAId]?.visibility,
+ },
+ })
+ );
+ },
});
};
@@ -106,7 +124,7 @@ export const useFeatureAbundanceLegend = () => {
});
};
-export const useFeatureLegend = () => {
+export const useFeaturesLegend = () => {
const { selectedFeatures } = useAppSelector((state) => state['/projects/[id]']);
const { query } = useRouter();
const { pid } = query as { pid: string };
@@ -114,7 +132,7 @@ export const useFeatureLegend = () => {
const dispatch = useAppDispatch();
const projectFeaturesQuery = useAllFeatures(
pid,
- {},
+ { sort: 'feature_class_name' },
{
select: ({ data }) => data,
}
@@ -149,11 +167,14 @@ export const useFeatureLegend = () => {
}
dispatch(setSelectedFeatures(newSelectedFeatures));
+ const { color } = items.find(({ id }) => id === featureId) || {};
+
dispatch(
setLayerSettings({
id: featureId,
settings: {
visibility: !isIncluded,
+ color,
},
})
);
@@ -169,7 +190,7 @@ export const useInventoryLegend = () => {
subgroups: [
{
name: 'Cost Surface',
- layers: useCostSurfaceLegend(),
+ layers: [useCostSurfaceLegend()],
},
],
},
@@ -178,21 +199,17 @@ export const useInventoryLegend = () => {
subgroups: [
{
name: 'Conservation Areas',
- layers: useConservationAreasLegend(),
- },
- {
- name: 'Conservation Areas 2',
- layers: useConservationAreasLegend(),
+ layers: [useConservationAreasLegend()],
},
],
},
{
name: 'Features (Continuous)',
- layers: useFeatureAbundanceLegend(),
+ layers: [useFeatureAbundanceLegend()],
},
{
name: 'Features (Binary)',
- layers: useFeatureLegend(),
+ layers: useFeaturesLegend(),
},
];
};
diff --git a/app/layout/scenarios/edit/map/legend/hooks/index.ts b/app/layout/scenarios/edit/map/legend/hooks/index.ts
index 45b99a9a7a..6956469d96 100644
--- a/app/layout/scenarios/edit/map/legend/hooks/index.ts
+++ b/app/layout/scenarios/edit/map/legend/hooks/index.ts
@@ -19,23 +19,32 @@ import { WDPA } from 'types/api/wdpa';
export const useCostSurfaceLegend = () => {
const { query } = useRouter();
const { pid, sid } = query as { pid: string; sid: string };
- const { selectedCostSurfaces } = useAppSelector((state) => state[`/scenarios/${sid}/edit`]);
- const costSurfaceQuery = useProjectCostSurfaces(
- pid,
- {},
- {
- select: (data) => data.filter((cs) => selectedCostSurfaces.includes(cs.id)),
- }
- );
+ const dispatch = useAppDispatch();
+ const scenarioSlice = getScenarioEditSlice(sid);
+ const { setLayerSettings } = scenarioSlice.actions;
+ const { layerSettings } = useAppSelector((state) => state[`/scenarios/${sid}/edit`]);
- // todo: uncomment when API is ready
- // return LEGEND_LAYERS['cost-surface']({
- // items: costSurfaceQuery.data?.map(({ name, min = 1, max = 8 }) => ({ name, min, max })) || [],
- // });
+ // const costSurfaceQuery = useProjectCostSurfaces(
+ // pid,
+ // {},
+ // {
+ // select: (data) => data.filter((cs) => selectedCostSurfaces.includes(cs.id)),
+ // }
+ // );
return LEGEND_LAYERS['cost-surface']({
- items: [{ name: 'Cost Surface 2', min: 1, max: 22 }],
+ costSurface: { name: 'Cost Surface 2', min: 1, max: 22 },
+ onChangeVisibility: () => {
+ dispatch(
+ setLayerSettings({
+ id: 'cost-surface',
+ settings: {
+ visibility: !layerSettings['cost-surface']?.visibility,
+ },
+ })
+ );
+ },
});
};
@@ -257,6 +266,29 @@ export const useLockAvailableLegend = () => {
});
};
+export const useWDPAPreviewLegend = () => {
+ const { query } = useRouter();
+ const { sid } = query as { sid: string };
+
+ const dispatch = useAppDispatch();
+ const scenarioSlice = getScenarioEditSlice(sid);
+ const { setLayerSettings } = scenarioSlice.actions;
+ const { layerSettings } = useAppSelector((state) => state[`/scenarios/${sid}/edit`]);
+
+ return LEGEND_LAYERS['wdpa-preview']({
+ onChangeVisibility: () => {
+ dispatch(
+ setLayerSettings({
+ id: 'wdpa-preview',
+ settings: {
+ visibility: !layerSettings['wdpa-preview']?.visibility,
+ },
+ })
+ );
+ },
+ });
+};
+
export const useFrequencyLegend = () => {
const { query } = useRouter();
const { sid } = query as { sid: string };
@@ -315,22 +347,18 @@ export const useScenarioLegend = () => {
return [
{
name: 'Planning Grid',
- subgroups: [
- {
- name: 'Planning Grid',
- layers: [
- LEGEND_LAYERS['pugrid'](),
- useLockInLegend(),
- useLockOutLegend(),
- useLockAvailableLegend(),
- ],
- },
- {
- name: 'Features',
- layers: [LEGEND_LAYERS['wdpa-preview'](), useFrequencyLegend(), useSolutionsLegend()],
- },
+ layers: [
+ LEGEND_LAYERS['pugrid'](),
+ useCostSurfaceLegend(),
+ useLockInLegend(),
+ useLockOutLegend(),
+ useLockAvailableLegend(),
],
},
+ {
+ name: 'Features',
+ layers: [useWDPAPreviewLegend(), useFrequencyLegend(), useSolutionsLegend()],
+ },
{
name: 'Designated Areas',
subgroups: [