Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
1de1bbe
[TM-3058] start up connection for ANR plot geometry
cesarLima1 Mar 19, 2026
d69c8c1
[TM-3058] add new ANR tab in polygon sidebar
egrojMonroy Mar 19, 2026
9e7f2ee
[TM-3058] add workflow with buttons
egrojMonroy Mar 19, 2026
8533652
[TM-3058] Refactor PolygonDrawer and AnrMonitoringPlots components fo…
dottyy Mar 19, 2026
432c59a
[TM-3058] add commentary box
diego-morales-flores-1996 Mar 19, 2026
d0bb2e4
[TM-3058] Implement AnrMonitoringPlots component with visibility togg…
dottyy Mar 19, 2026
8574121
[TM-3058] Merge branch 'feat/TM-3058-upload-ANR-plot' of https://gith…
diego-morales-flores-1996 Mar 19, 2026
df6c148
[TM-3058] Merge branch 'epic/TM-3056-ANR-PLOT' into feat/TM-3058-uplo…
cesarLima1 Mar 19, 2026
ad0d10c
[TM-3058] update ANR icon
diego-morales-flores-1996 Mar 20, 2026
c0b440e
[TM-3058] Merge branch 'feat/TM-3058-upload-ANR-plot' of https://gith…
diego-morales-flores-1996 Mar 20, 2026
d626849
[TM-3058] use anr connection in component related
cesarLima1 Mar 20, 2026
d2d431d
[TM-3059] add layer on map with geojson data
egrojMonroy Mar 20, 2026
c14f21e
[TM-3059] fix error when opening ANR option
cesarLima1 Mar 23, 2026
84b2c13
[TM-3122] start adding anr plots in PD
cesarLima1 Mar 23, 2026
1c9cb34
[TM-3122] Merge branch 'staging' of https://github.com/wri/wri-terram…
diego-morales-flores-1996 Mar 23, 2026
eb5e5e3
[TM-3122] Merge branch 'staging' of https://github.com/wri/wri-terram…
diego-morales-flores-1996 Mar 23, 2026
c358046
[TM-3122] update overview side map are style
diego-morales-flores-1996 Mar 23, 2026
7697d3c
[TM-3122] update overview side map are style
diego-morales-flores-1996 Mar 23, 2026
1692192
[TM-3122] update overview side map are style
diego-morales-flores-1996 Mar 23, 2026
2cdae12
[TM-3122] disable buttons for non approved
egrojMonroy Mar 23, 2026
ca7a74e
[TM-3122] Merge branch 'feat/TM-3122-anr-plots-pd' of https://github.…
egrojMonroy Mar 23, 2026
877df43
[TM-3122] Enhance AttributeInformation component with new download bu…
dottyy Mar 23, 2026
5a3b8cf
[TM-3058] Merge branch 'epic/TM-3056-ANR-PLOT' into feat/TM-3058-uplo…
egrojMonroy Mar 23, 2026
3a4133a
[TM-3156] Add ButtonGroups (#2097)
diego-morales-flores-1996 Mar 19, 2026
0980aff
[TM-3077] add panel component (#2093)
diego-morales-flores-1996 Mar 19, 2026
fd725a5
[TM-3077] tm design components panel (#2098)
diego-morales-flores-1996 Mar 20, 2026
10e4142
[TM-3143] update the tree species title (#2100)
LimberHope Mar 20, 2026
44cb2db
[TM-3172] Update cancel button functionality in ReportingTaskHeader t…
Marcolr-dev Mar 20, 2026
71412cf
[TM-3150] remove save changes button (#2103)
LimberHope Mar 20, 2026
9ae0a18
[TM-3153] Modal content card (#2101)
diego-morales-flores-1996 Mar 22, 2026
ea06048
Release/Zesty Zircon Hotfix 2026-03-23 (#2108) (#2109)
LimberHope Mar 23, 2026
27239c3
[TM-3130] Refactor icon imports and add new icons for Restoration & L…
dottyy Mar 23, 2026
e5438b9
Merge feat/TM-3058-upload-ANR-plot into feat/TM-3059-ANR-rendering
egrojMonroy Mar 23, 2026
cee92cb
[TM-3122] Merge branch 'feat/TM-3122-anr-plots-pd' of https://github.…
egrojMonroy Mar 23, 2026
814718e
Merge feat/TM-3059-ANR-rendering into feat/TM-3122-anr-plots-pd
egrojMonroy Mar 23, 2026
3f97314
[TM-3122] Restore ANRIcon.tsx (required by merged icon barrel)
egrojMonroy Mar 23, 2026
aef0751
[TM-3122] set grey color to layer
egrojMonroy Mar 24, 2026
b2e3bcb
[TM-3058] remove comment
egrojMonroy Mar 24, 2026
ec91efd
[TM-3059] remove comments
egrojMonroy Mar 24, 2026
da3b88c
[TM-3122] change styles
egrojMonroy Mar 24, 2026
d96a7f9
[TM-3122] code improvements
cesarLima1 Mar 25, 2026
b5a6f65
[TM-3058] changes null, uuids
egrojMonroy Mar 25, 2026
6234869
Merge branch 'feat/TM-3058-upload-ANR-plot' into feat/TM-3059-ANR-ren…
egrojMonroy Mar 26, 2026
261b428
[TM-3059] Merge branch 'epic/TM-3056-ANR-PLOT' into feat/TM-3059-ANR-…
egrojMonroy Mar 26, 2026
6a3d495
[TM-3059] share mutable state and change some methods
egrojMonroy Mar 26, 2026
034e0f5
[TM-3122] Merge branch 'feat/TM-3059-ANR-rendering' into feat/TM-3122…
cesarLima1 Mar 26, 2026
e3de867
[TM-3122] Merge branch 'feat/TM-3059-ANR-rendering' into feat/TM-3122…
cesarLima1 Mar 26, 2026
138944f
[TM-3122] fix the null check
egrojMonroy Mar 26, 2026
e43b5a4
[TM-3122] Merge branch 'epic/TM-3056-ANR-PLOT' into feat/TM-3122-anr-…
cesarLima1 Mar 26, 2026
d6f7af4
[TM-3122] Merge branch 'epic/TM-3056-ANR-PLOT' into feat/TM-3122-anr-…
cesarLima1 Mar 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Divider } from "@mui/material";
import { useT } from "@transifex/react";
import { isEmpty } from "lodash";
import { Dispatch, SetStateAction, useCallback, useEffect, useRef, useState } from "react";
import { Dispatch, SetStateAction, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { When } from "react-if";

import Accordion from "@/components/elements/Accordion/Accordion";
Expand All @@ -23,6 +23,7 @@ import { useOnUnmount } from "@/hooks/useOnMount";
import { useValueChanged } from "@/hooks/useValueChanged";
import ApiSlice from "@/store/apiSlice";
import Log from "@/utils/log";
import { isSitePolygonEligibleForAnrMonitoringPlots } from "@/utils/sitePolygonAnrEligibility";

import AuditLogTable from "../../../AuditLogTab/components/AuditLogTable";
import CommentarySection from "../CommentarySection/CommentarySection";
Expand Down Expand Up @@ -75,6 +76,10 @@ const PolygonDrawer = ({
const sitePolygonRefresh = context?.reloadSiteData;
const openEditNewPolygon = contextMapArea?.isUserDrawingEnabled;
const selectedPolygon = sitePolygonData?.find((item: SitePolygonLightDto) => item?.polygonUuid === polygonSelected);
const anrPlotsEligible = useMemo(
() => isSitePolygonEligibleForAnrMonitoringPlots(selectedPolygon),
[selectedPolygon]
);
const anrMapOverlay = useAnrMapOverlayOptional();
const { statusSelectedPolygon, setStatusSelectedPolygon, setShouldRefetchValidation } = contextMapArea;
const { showLoader, hideLoader } = useLoading();
Expand Down Expand Up @@ -136,8 +141,46 @@ const PolygonDrawer = ({
});

useEffect(() => {
setActiveTab(initialTopTab);
}, [polygonSelected, initialTopTab]);
const eligible = isSitePolygonEligibleForAnrMonitoringPlots(selectedPolygon);
const safeTab = initialTopTab === "anrMonitoringPlots" && !eligible ? "attributes" : initialTopTab;
setActiveTab(safeTab);
}, [polygonSelected, initialTopTab, selectedPolygon]);

useEffect(() => {
if (!isSitePolygonEligibleForAnrMonitoringPlots(selectedPolygon) && activeTab === "anrMonitoringPlots") {
setActiveTab("attributes");
}
}, [selectedPolygon, activeTab]);

useEffect(() => {
if (anrMapOverlay == null) {
return;
}
if (!isOpenPolygonDrawer) {
anrMapOverlay.resetAnrMapOverlay();
prevActiveTabForAnrRef.current = null;
return;
}
anrMapOverlay.setDrawerOpen(true);
const onAnrTab = activeTab === "anrMonitoringPlots" && anrPlotsEligible;
anrMapOverlay.setAnrTabActive(onAnrTab);

if (selectedPolygon?.uuid != null && selectedPolygon.uuid !== "") {
anrMapOverlay.syncDrawerSelection({
sitePolygonUuid: selectedPolygon.uuid,
geometryPolygonUuid: polygonSelected
});
}

if (onAnrTab && prevActiveTabForAnrRef.current !== "anrMonitoringPlots") {
anrMapOverlay.setShowPlotsOnMap(true);
}
prevActiveTabForAnrRef.current = activeTab;
}, [anrMapOverlay, activeTab, anrPlotsEligible, isOpenPolygonDrawer, polygonSelected, selectedPolygon?.uuid]);

useOnUnmount(() => {
anrMapOverlayRef.current?.resetAnrMapOverlay();
});

useEffect(() => {
if (anrMapOverlay == null) {
Expand Down Expand Up @@ -248,13 +291,15 @@ const PolygonDrawer = ({
>
<span className="text-12">{t("Polygon Status")}</span>
</Button>
<Button
variant={`${activeTab === "anrMonitoringPlots" ? "white-toggle" : "transparent-toggle"}`}
onClick={() => setActiveTab("anrMonitoringPlots")}
className="px-3 py-1 lg:px-2.5 lg:py-1"
>
<span className="text-12">{t("ANR Monitoring Plots")}</span>
</Button>
{anrPlotsEligible ? (
<Button
variant={`${activeTab === "anrMonitoringPlots" ? "white-toggle" : "transparent-toggle"}`}
onClick={() => setActiveTab("anrMonitoringPlots")}
className="px-3 py-1 lg:px-2.5 lg:py-1"
>
<span className="text-12">{t("ANR Monitoring Plots")}</span>
</Button>
) : null}
</div>
{activeTab === "polygonStatus" ? (
<div className="flex max-h-max flex-[1_1_0] flex-col gap-6 overflow-auto pr-2.5">
Expand Down Expand Up @@ -295,9 +340,9 @@ const PolygonDrawer = ({
</>
)}
</div>
) : activeTab === "anrMonitoringPlots" ? (
) : activeTab === "anrMonitoringPlots" && anrPlotsEligible ? (
<div className="flex max-h-max flex-[1_1_0] flex-col gap-6 overflow-auto pr-2.5">
<AnrMonitoringPlots sitePolygonUuid={selectedPolygon?.uuid} />
<AnrMonitoringPlots sitePolygonUuid={selectedPolygon?.uuid ?? ""} />
</div>
) : (
<div ref={wrapperRef} className="flex max-h-max flex-[1_1_0] flex-col gap-6 overflow-auto pr-2.5">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import { useModalContext } from "@/context/modal.provider";
import { useNotificationContext } from "@/context/notification.provider";
import ApiSlice from "@/store/apiSlice";
import Log from "@/utils/log";

function getAnrPlotGeometryErrorMessage(error: unknown, fallback: string): string {
if (error != null && typeof error === "object" && "message" in error) {
try {
Expand All @@ -33,7 +32,10 @@ function getAnrPlotGeometryErrorMessage(error: unknown, fallback: string): strin
return fallback;
}

const AnrMonitoringPlots: FC<{ sitePolygonUuid?: string }> = ({ sitePolygonUuid }) => {
const AnrMonitoringPlots: FC<{
sitePolygonUuid: string;
dataFetchEnabled?: boolean;
}> = ({ sitePolygonUuid, dataFetchEnabled = true }) => {
const t = useT();
const { openModal, closeModal } = useModalContext();
const { openNotification } = useNotificationContext();
Expand All @@ -46,7 +48,7 @@ const AnrMonitoringPlots: FC<{ sitePolygonUuid?: string }> = ({ sitePolygonUuid

const [, { data: anrPlotGeometry, isLoading }] = useAnrPlotGeometry({
sitePolygonUuid,
enabled: sitePolygonUuid != null
enabled: sitePolygonUuid !== "" && dataFetchEnabled
});

const hasAnrPlotGeometry = anrPlotGeometry?.geojson?.features != null;
Expand Down Expand Up @@ -175,6 +177,21 @@ const AnrMonitoringPlots: FC<{ sitePolygonUuid?: string }> = ({ sitePolygonUuid
);
}

if (!dataFetchEnabled) {
return (
<div className="flex flex-col gap-3">
<Text variant="text-14" className="text-darkCustom">
{t("ANR Monitoring Plots")}
</Text>
<Text variant="text-12" className="text-gray-500">
{t(
"ANR monitoring plots are only available for approved polygons that include Assisted Natural Regeneration as a restoration practice."
)}
</Text>
</div>
);
}

if (isLoading || isUploading) {
return (
<div className="flex items-center justify-center p-4">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ import { useMapAreaContext } from "@/context/mapArea.provider";
import { useModalContext } from "@/context/modal.provider";
import { useSitePolygonData } from "@/context/sitePolygon.provider";
import { usePolygonsPagination } from "@/hooks/usePolygonsPagination";
import { ANRIcon } from "@/redesignComponents/foundations/Icons";
import { AssistedNaturalRegenIcon } from "@/redesignComponents/foundations/Icons";
import { OptionValue } from "@/types/common";
import Log from "@/utils/log";
import { isSitePolygonEligibleForAnrMonitoringPlots } from "@/utils/sitePolygonAnrEligibility";

import PolygonDrawer, { PolygonDrawerTopTab } from "./PolygonDrawer/PolygonDrawer";
import PolygonItem from "./PolygonItem";
Expand Down Expand Up @@ -204,106 +205,117 @@ const Polygons = (props: IPolygonProps) => {
);

const polygonMenuItems = useCallback(
(item: any) => [
{
id: "1",
render: () => (
<div className="flex w-full items-center gap-2">
<Icon name={IconNames.POLYGON} className="h-6 w-6" />
<Text variant="text-12-bold">Edit Polygon</Text>
</div>
),
onClick: () => {
setDrawerInitialTopTab("attributes");
setSelectedPolygon(item);
flyToPolygonBounds(item);
setPolygonFromMap({ isOpen: true, uuid: item.uuid, source: "menu" });
setIsOpenPolygonDrawer(true);
setSelectedPolygonsInCheckbox([]);
}
},
{
id: "2",
render: () => (
<div className="flex items-center gap-2">
<Icon name={IconNames.SEARCH_PA} className="h-6 w-6" />
<Text variant="text-12-bold">Zoom to</Text>
</div>
),
onClick: () => {
flyToPolygonBounds(item);
}
},
{
id: "3",
render: () => (
<div className="flex items-center gap-2">
<Icon name={IconNames.DOWNLOAD_PA} className="h-6 w-6" />
<Text variant="text-12-bold">Download</Text>
</div>
),
onClick: () => {
downloadGeoJsonPolygon(item);
}
},
{
id: "4",
render: () => (
<div className="flex items-center gap-2">
<Icon name={IconNames.COMMENT} className="h-6 w-6" />
<Text variant="text-12-bold">Comment</Text>
</div>
),
onClick: () => {
setDrawerInitialTopTab("attributes");
setSelectedPolygon(item);
flyToPolygonBounds(item);
setPolygonFromMap({ isOpen: true, uuid: item.uuid, source: "menu" });
setIsOpenPolygonDrawer(true);
setSelectedPolygonsInCheckbox([]);
}
},
{
id: "5",
render: () => (
<div className="flex items-center gap-2">
<Icon name={IconNames.TRASH_PA} className="h-5 w-5" />
<Text variant="text-12-bold">Delete Polygon</Text>
</div>
),
onClick: () => {
openFormModalHandlerConfirm(item);
}
},
{
id: "6",
render: () => <div className="h-[1px] w-full bg-grey-750" />,
MenuItemVariant: MENU_ITEM_VARIANT_DIVIDER
},
{
id: "7",
render: () => (
<div className="flex w-full items-center gap-2">
<ANRIcon className="h-5 w-5" />
<Text variant="text-12-bold">{t("ANR Monitoring Plots")}</Text>
</div>
),
onClick: () => {
setDrawerInitialTopTab("anrMonitoringPlots");
setSelectedPolygon(item);
flyToPolygonBounds(item);
setPolygonFromMap({ isOpen: true, uuid: item.uuid, source: "menu" });
setIsOpenPolygonDrawer(true);
setSelectedPolygonsInCheckbox([]);
(item: IPolygonItem) => {
const siteRow = sitePolygonData?.find(p => p.polygonUuid === item.uuid);
const anrEligible = isSitePolygonEligibleForAnrMonitoringPlots(siteRow);
const baseItems = [
{
id: "1",
render: () => (
<div className="flex w-full items-center gap-2">
<Icon name={IconNames.POLYGON} className="h-6 w-6" />
<Text variant="text-12-bold">Edit Polygon</Text>
</div>
),
onClick: () => {
setDrawerInitialTopTab("attributes");
setSelectedPolygon(item);
flyToPolygonBounds(item);
setPolygonFromMap({ isOpen: true, uuid: item.uuid, source: "menu" });
setIsOpenPolygonDrawer(true);
setSelectedPolygonsInCheckbox([]);
}
},
{
id: "2",
render: () => (
<div className="flex items-center gap-2">
<Icon name={IconNames.SEARCH_PA} className="h-6 w-6" />
<Text variant="text-12-bold">Zoom to</Text>
</div>
),
onClick: () => {
flyToPolygonBounds(item);
}
},
{
id: "3",
render: () => (
<div className="flex items-center gap-2">
<Icon name={IconNames.DOWNLOAD_PA} className="h-6 w-6" />
<Text variant="text-12-bold">Download</Text>
</div>
),
onClick: () => {
downloadGeoJsonPolygon(item);
}
},
{
id: "4",
render: () => (
<div className="flex items-center gap-2">
<Icon name={IconNames.COMMENT} className="h-6 w-6" />
<Text variant="text-12-bold">Comment</Text>
</div>
),
onClick: () => {
setDrawerInitialTopTab("attributes");
setSelectedPolygon(item);
flyToPolygonBounds(item);
setPolygonFromMap({ isOpen: true, uuid: item.uuid, source: "menu" });
setIsOpenPolygonDrawer(true);
setSelectedPolygonsInCheckbox([]);
}
},
{
id: "5",
render: () => (
<div className="flex items-center gap-2">
<Icon name={IconNames.TRASH_PA} className="h-5 w-5" />
<Text variant="text-12-bold">Delete Polygon</Text>
</div>
),
onClick: () => {
openFormModalHandlerConfirm(item);
}
}
];
if (!anrEligible) {
return baseItems;
}
],
return [
...baseItems,
{
id: "6",
render: () => <div className="h-[1px] w-full bg-grey-750" />,
MenuItemVariant: MENU_ITEM_VARIANT_DIVIDER
},
{
id: "7",
render: () => (
<div className="flex w-full items-center gap-2">
<AssistedNaturalRegenIcon boxSize={5} />
<Text variant="text-12-bold">{t("ANR Monitoring Plots")}</Text>
</div>
),
onClick: () => {
setDrawerInitialTopTab("anrMonitoringPlots");
setSelectedPolygon(item);
flyToPolygonBounds(item);
setPolygonFromMap({ isOpen: true, uuid: item.uuid, source: "menu" });
setIsOpenPolygonDrawer(true);
setSelectedPolygonsInCheckbox([]);
}
}
];
},
[
downloadGeoJsonPolygon,
flyToPolygonBounds,
setPolygonFromMap,
setSelectedPolygonsInCheckbox,
openFormModalHandlerConfirm,
sitePolygonData,
t
]
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const AnrPlotMapPopup = ({ plotId, areaM2, select, onClose }: AnrPlotMapP
const t = useT();

return (
<div className="shadow-md relative w-[240px] rounded border-t-[5px] border-t-[rgb(195,110,95)] bg-white px-3 pb-3 pt-2">
<div className="border-t-gray-700 shadow-md relative w-[240px] rounded border-t-[5px] bg-white px-3 pb-3 pt-2">
<button
type="button"
onClick={onClose}
Expand Down
Loading
Loading