datastake-daf 0.6.795 → 0.6.797

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/components/index.js +258 -89
  2. package/dist/pages/index.js +789 -174
  3. package/dist/style/datastake/mapbox-gl.css +330 -0
  4. package/dist/utils/index.js +1 -1
  5. package/package.json +1 -1
  6. package/public/Vegetation/black-default.svg +23 -0
  7. package/public/Vegetation/black.svg +12 -0
  8. package/public/Vegetation/damage-from-insects-default.svg +14 -0
  9. package/public/Vegetation/damage-from-insects.svg +8 -0
  10. package/public/Vegetation/dry-or-dead-default.svg +16 -0
  11. package/public/Vegetation/dry-or-dead.svg +7 -0
  12. package/public/Vegetation/healthy-default.svg +14 -0
  13. package/public/Vegetation/healthy.svg +34 -0
  14. package/public/Vegetation/mosaic-default.svg +17 -0
  15. package/public/Vegetation/mosaic.svg +9 -0
  16. package/public/Vegetation/no-leaves-default.svg +6 -0
  17. package/public/Vegetation/no-leaves.svg +5 -0
  18. package/public/Vegetation/reddish-default.svg +23 -0
  19. package/public/Vegetation/reddish.svg +79 -0
  20. package/public/Vegetation/spider-webs-default.svg +10 -0
  21. package/public/Vegetation/spider-webs.svg +10 -0
  22. package/public/Vegetation/white-default.svg +25 -0
  23. package/public/Vegetation/white.svg +12 -0
  24. package/public/Vegetation/yellowing-default.svg +7 -0
  25. package/public/Vegetation/yellowing.svg +8 -0
  26. package/src/@daf/core/components/Dashboard/Widget/ActivityIndicators/index.jsx +24 -6
  27. package/src/@daf/core/components/Dashboard/Widget/ActivityIndicators/style.js +2 -6
  28. package/src/@daf/core/components/Dashboard/Widget/VegetationWidget/VegetationWidget.stories.jsx +76 -0
  29. package/src/@daf/core/components/Dashboard/Widget/VegetationWidget/config.js +31 -0
  30. package/src/@daf/core/components/Dashboard/Widget/VegetationWidget/index.jsx +137 -0
  31. package/src/@daf/core/components/ViewForm/components/Records/config.js +3 -0
  32. package/src/@daf/pages/Summary/Activities/Monitoring/components/ActivityImagery/index.jsx +12 -10
  33. package/src/@daf/pages/Summary/Activities/Monitoring/components/BiodiversityAndHabitat/helper.js +86 -0
  34. package/src/@daf/pages/Summary/Activities/Monitoring/components/BiodiversityAndHabitat/index.jsx +65 -0
  35. package/src/@daf/pages/Summary/Activities/Monitoring/components/EnvironmentalMetrics/index.jsx +30 -0
  36. package/src/@daf/pages/Summary/Activities/Monitoring/components/MangroveGrowthAndSurvival/components/PlantedSpecies/index.jsx +15 -28
  37. package/src/@daf/pages/Summary/Activities/Monitoring/components/MangroveGrowthAndSurvival/components/SeedlingsHeight/index.jsx +17 -30
  38. package/src/@daf/pages/Summary/Activities/Monitoring/components/MangroveGrowthAndSurvival/components/SurvivalRate/index.jsx +38 -45
  39. package/src/@daf/pages/Summary/Activities/Monitoring/components/MangroveGrowthAndSurvival/index.jsx +87 -8
  40. package/src/@daf/pages/Summary/Activities/Monitoring/config.js +21 -4
  41. package/src/@daf/pages/Summary/Activities/Monitoring/helper.js +7 -1
  42. package/src/@daf/pages/Summary/Activities/Monitoring/index.jsx +31 -8
  43. package/src/@daf/utils/numbers.js +1 -1
  44. package/src/constants/Vegetation.js +15 -0
  45. package/src/index.js +1 -0
@@ -6030,7 +6030,7 @@ const useHeader = ({
6030
6030
  };
6031
6031
 
6032
6032
  const {
6033
- useToken: useToken$9
6033
+ useToken: useToken$a
6034
6034
  } = antd.theme;
6035
6035
  function BreadCrumbs({
6036
6036
  breadcrumbs = [],
@@ -6039,7 +6039,7 @@ function BreadCrumbs({
6039
6039
  const [splitIndex, setSplitIndex] = React.useState(0);
6040
6040
  const {
6041
6041
  token
6042
- } = useToken$9();
6042
+ } = useToken$a();
6043
6043
  const _renderBreadcrumb = (b, i, isLast, noOnClickLast = false) => {
6044
6044
  return /*#__PURE__*/jsxRuntime.jsxs("div", {
6045
6045
  className: "flex breadcrumb-item",
@@ -6204,7 +6204,7 @@ const MultiSelectStyled = styled__default["default"](antd.Select)`
6204
6204
  `;
6205
6205
 
6206
6206
  const {
6207
- useToken: useToken$8
6207
+ useToken: useToken$9
6208
6208
  } = antd.theme;
6209
6209
 
6210
6210
  /**
@@ -6297,7 +6297,7 @@ function Multiselect({
6297
6297
  }) {
6298
6298
  const {
6299
6299
  token
6300
- } = useToken$8();
6300
+ } = useToken$9();
6301
6301
  const [selectValue, setSelectValue] = React.useState(Array.isArray(defaultSelected) ? defaultSelected.length > 0 ? defaultSelected : [] : [defaultSelected]);
6302
6302
  function onSelectChange(value) {
6303
6303
  if (!canUnselectLast && value.length === 0) {
@@ -11194,14 +11194,14 @@ const Style$e = styled__default["default"].div`
11194
11194
  // components/Nodes/NameNode.jsx
11195
11195
  const NAME_CARD_WIDTH = 315;
11196
11196
  const {
11197
- useToken: useToken$7
11197
+ useToken: useToken$8
11198
11198
  } = antd.theme;
11199
11199
  function NameNode({
11200
11200
  data
11201
11201
  }) {
11202
11202
  const {
11203
11203
  token
11204
- } = useToken$7();
11204
+ } = useToken$8();
11205
11205
  const translateFN = typeof data?.t === "function" ? data.t : key => key;
11206
11206
  const isPdf = data?.isPdf;
11207
11207
  return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
@@ -12291,7 +12291,7 @@ const mapDataForChainOfCustody = (data = {}, options = {}, goTo = () => {}) => {
12291
12291
  hardcodedData: PropTypes__default["default"].array
12292
12292
  });
12293
12293
 
12294
- const Container$1 = styled__default["default"].div`
12294
+ const Container$2 = styled__default["default"].div`
12295
12295
  height: ${props => props.height || '300px'};
12296
12296
  width: ${props => props.isPdf ? props.width ? props.width : '1000px' : 'calc(100% - 48px)'};
12297
12297
  `;
@@ -12390,7 +12390,7 @@ const CustomLegend = ({
12390
12390
  };
12391
12391
 
12392
12392
  const {
12393
- useToken: useToken$6
12393
+ useToken: useToken$7
12394
12394
  } = antd.theme;
12395
12395
 
12396
12396
  /**
@@ -12481,7 +12481,7 @@ function LineChart({
12481
12481
  const chartRef = React__default["default"].useRef(null);
12482
12482
  const {
12483
12483
  token
12484
- } = useToken$6();
12484
+ } = useToken$7();
12485
12485
  const {
12486
12486
  legendEnabled,
12487
12487
  legendItems,
@@ -12565,7 +12565,7 @@ function LineChart({
12565
12565
  className: "flex flex-1 flex-column justify-content-center",
12566
12566
  children: [/*#__PURE__*/jsxRuntime.jsx("div", {
12567
12567
  className: "flex justify-content-center",
12568
- children: /*#__PURE__*/jsxRuntime.jsx(Container$1, {
12568
+ children: /*#__PURE__*/jsxRuntime.jsx(Container$2, {
12569
12569
  ref: containerRef,
12570
12570
  height: height,
12571
12571
  isPdf: isPdf,
@@ -14319,7 +14319,7 @@ function AccumulationGraph({
14319
14319
  }
14320
14320
 
14321
14321
  const {
14322
- useToken: useToken$5
14322
+ useToken: useToken$6
14323
14323
  } = antd.theme;
14324
14324
 
14325
14325
  /**
@@ -14411,7 +14411,7 @@ function BarChart({
14411
14411
  const chartRef = React__default["default"].useRef(null);
14412
14412
  const {
14413
14413
  token
14414
- } = useToken$5();
14414
+ } = useToken$6();
14415
14415
  const {
14416
14416
  legendEnabled,
14417
14417
  legendItems,
@@ -14479,7 +14479,7 @@ function BarChart({
14479
14479
  className: "flex flex-1 flex-column justify-content-center",
14480
14480
  children: [/*#__PURE__*/jsxRuntime.jsx("div", {
14481
14481
  className: "flex justify-content-center",
14482
- children: /*#__PURE__*/jsxRuntime.jsx(Container$1, {
14482
+ children: /*#__PURE__*/jsxRuntime.jsx(Container$2, {
14483
14483
  ref: containerRef,
14484
14484
  height: height,
14485
14485
  isPdf: isPdf,
@@ -21388,12 +21388,12 @@ function Geolocation$1({
21388
21388
  }
21389
21389
 
21390
21390
  const {
21391
- useToken: useToken$4
21391
+ useToken: useToken$5
21392
21392
  } = antd.theme;
21393
21393
  function Smart() {
21394
21394
  const {
21395
21395
  token
21396
- } = useToken$4();
21396
+ } = useToken$5();
21397
21397
  const [isOpen, setIsOpen] = React.useState(false);
21398
21398
  return /*#__PURE__*/jsxRuntime.jsxs("div", {
21399
21399
  style: {
@@ -21477,7 +21477,7 @@ function SmartWidget({
21477
21477
  }) {
21478
21478
  const {
21479
21479
  token
21480
- } = useToken$4();
21480
+ } = useToken$5();
21481
21481
  return /*#__PURE__*/jsxRuntime.jsx(Widget, {
21482
21482
  noTitle: true,
21483
21483
  className: "no-p-body p-xs",
@@ -22246,7 +22246,7 @@ FormPopover.propTypes = {
22246
22246
  };
22247
22247
 
22248
22248
  const {
22249
- useToken: useToken$3
22249
+ useToken: useToken$4
22250
22250
  } = antd.theme;
22251
22251
  const disabledTypes = ["dataLink"];
22252
22252
  function Versions({
@@ -22259,7 +22259,7 @@ function Versions({
22259
22259
  }) {
22260
22260
  const {
22261
22261
  token
22262
- } = useToken$3();
22262
+ } = useToken$4();
22263
22263
  const dataSource = React.useMemo(() => {
22264
22264
  if (!versionsDatapoints) {
22265
22265
  return [];
@@ -32166,7 +32166,7 @@ const viewConfig$8 = {
32166
32166
  };
32167
32167
 
32168
32168
  const {
32169
- useToken: useToken$2
32169
+ useToken: useToken$3
32170
32170
  } = antd.theme;
32171
32171
  const MAX_LENGTH = 3;
32172
32172
  function AvatarGroup({
@@ -32177,7 +32177,7 @@ function AvatarGroup({
32177
32177
  const count = items.length === maxLength + 1 ? items.length : maxLength;
32178
32178
  const {
32179
32179
  token
32180
- } = useToken$2();
32180
+ } = useToken$3();
32181
32181
  return /*#__PURE__*/jsxRuntime.jsx(antd.Avatar.Group, {
32182
32182
  max: {
32183
32183
  count: count,
@@ -36180,7 +36180,7 @@ const KeyInformation$2 = ({
36180
36180
  };
36181
36181
 
36182
36182
  const {
36183
- useToken: useToken$1
36183
+ useToken: useToken$2
36184
36184
  } = antd.theme;
36185
36185
  /**
36186
36186
  * RadialBarChart Component
@@ -36241,7 +36241,7 @@ function RadialBarChart({
36241
36241
  const chartRef = React__default["default"].useRef(null);
36242
36242
  const {
36243
36243
  token
36244
- } = useToken$1();
36244
+ } = useToken$2();
36245
36245
  const {
36246
36246
  legendEnabled,
36247
36247
  legendItems,
@@ -36342,7 +36342,7 @@ function RadialBarChart({
36342
36342
  className: "flex flex-1 flex-column justify-content-center",
36343
36343
  children: [/*#__PURE__*/jsxRuntime.jsx("div", {
36344
36344
  className: "flex justify-content-center",
36345
- children: /*#__PURE__*/jsxRuntime.jsx(Container$1, {
36345
+ children: /*#__PURE__*/jsxRuntime.jsx(Container$2, {
36346
36346
  ref: containerRef,
36347
36347
  isPdf: isPdf
36348
36348
  })
@@ -38303,12 +38303,8 @@ const Style$1 = styled__default["default"].div`
38303
38303
  border-left: none;
38304
38304
  border-bottom: none;
38305
38305
 
38306
- /* Add separator line for each item (except items in the last row) */
38307
- /* Items 1-4 (rows 1 and 2) get separator, items 5-6 (last row) don't */
38308
- &:nth-child(1),
38309
- &:nth-child(2),
38310
- &:nth-child(3),
38311
- &:nth-child(4) {
38306
+ /* Add separator line for all items except the last two (last items in each column) */
38307
+ &:not(:nth-last-child(-n+2)) {
38312
38308
  &::after {
38313
38309
  content: '';
38314
38310
  position: absolute;
@@ -38513,12 +38509,18 @@ function Label({
38513
38509
  * @param {string} configItem.type - "empty" | "compliant" | "notCompliant"
38514
38510
  * @param {Function} configItem.onClick - Optional callback for empty type
38515
38511
  * @param {string} configItem.statusIcon - Optional custom icon name for status badge (overrides default)
38512
+ * @param {string} configItem.statusIconColor - Optional custom color for status icon
38513
+ * @param {string} configItem.statusBadgeBackgroundColor - Optional custom background color for status badge
38514
+ * @param {string} configItem.statusBadgeBorderColor - Optional custom border color for status badge
38516
38515
  */
38517
38516
  function renderStatus(configItem) {
38518
38517
  const {
38519
38518
  type,
38520
38519
  onClick,
38521
- statusIcon
38520
+ statusIcon,
38521
+ statusIconColor,
38522
+ statusBadgeBackgroundColor,
38523
+ statusBadgeBorderColor
38522
38524
  } = configItem;
38523
38525
  switch (type) {
38524
38526
  case "empty":
@@ -38534,21 +38536,29 @@ function renderStatus(configItem) {
38534
38536
  case "compliant":
38535
38537
  return /*#__PURE__*/jsxRuntime.jsx(StatusBadge, {
38536
38538
  className: "status-badge compliant border",
38539
+ style: {
38540
+ backgroundColor: statusBadgeBackgroundColor || "#ECFDF3",
38541
+ borderColor: statusBadgeBorderColor || "#A7F3D0"
38542
+ },
38537
38543
  children: /*#__PURE__*/jsxRuntime.jsx(CustomIcon, {
38538
38544
  name: statusIcon || "Check",
38539
38545
  width: 14,
38540
38546
  height: 14,
38541
- color: "#12B76A"
38547
+ color: statusIconColor || "#12B76A"
38542
38548
  })
38543
38549
  });
38544
38550
  case "notCompliant":
38545
38551
  return /*#__PURE__*/jsxRuntime.jsx(StatusBadge, {
38546
38552
  className: "status-badge not-compliant border",
38553
+ style: {
38554
+ backgroundColor: statusBadgeBackgroundColor || "#FEF3F2",
38555
+ borderColor: statusBadgeBorderColor || "#FECACA"
38556
+ },
38547
38557
  children: /*#__PURE__*/jsxRuntime.jsx(CustomIcon, {
38548
38558
  name: statusIcon || "Close",
38549
38559
  width: 14,
38550
38560
  height: 14,
38551
- color: "#D92D20"
38561
+ color: statusIconColor || "#D92D20"
38552
38562
  })
38553
38563
  });
38554
38564
  default:
@@ -39921,6 +39931,195 @@ const StatCard = ({
39921
39931
  });
39922
39932
  };
39923
39933
 
39934
+ const VEGETATION_KEYS = {
39935
+ HEALTHY: "healthy",
39936
+ WHITE_SPOTS: "white",
39937
+ BLACK_SPOTS: "black",
39938
+ REDDISH_SPOTS: "reddish",
39939
+ YELLOWING: "yellowing",
39940
+ MOSAIC: "mosaic",
39941
+ DRY_OR_DEAD: "dryOrDead",
39942
+ NO_LEAVES: "noLeaves",
39943
+ SPIDER_WEBS: "spiderWebs",
39944
+ DAMAGE_FROM_INSECTS: "damageFromInsects"
39945
+ };
39946
+
39947
+ // Mapping from growthObservations keys to VEGETATION_KEYS
39948
+ const GROWTH_OBSERVATIONS_TO_VEGETATION_KEYS = {
39949
+ "white_spots": VEGETATION_KEYS.WHITE_SPOTS,
39950
+ "healthy_leaves": VEGETATION_KEYS.HEALTHY,
39951
+ "yellowing_leaves": VEGETATION_KEYS.YELLOWING,
39952
+ "leaf_mosaic": VEGETATION_KEYS.MOSAIC,
39953
+ "dry_dead_leaves": VEGETATION_KEYS.DRY_OR_DEAD,
39954
+ "no_leaves": VEGETATION_KEYS.NO_LEAVES,
39955
+ "black_spots": VEGETATION_KEYS.BLACK_SPOTS,
39956
+ "reddish_spots": VEGETATION_KEYS.REDDISH_SPOTS,
39957
+ "spider_webs": VEGETATION_KEYS.SPIDER_WEBS,
39958
+ "insect_damage": VEGETATION_KEYS.DAMAGE_FROM_INSECTS
39959
+ };
39960
+ const getVegetationConfig = () => {
39961
+ return [{
39962
+ img: "/Vegetation/healthy.svg",
39963
+ key: VEGETATION_KEYS.HEALTHY,
39964
+ disabled: "/Vegetation/healthy-default.svg"
39965
+ }, {
39966
+ img: "/Vegetation/white.svg",
39967
+ key: VEGETATION_KEYS.WHITE_SPOTS,
39968
+ disabled: "/Vegetation/white-default.svg"
39969
+ }, {
39970
+ img: "/Vegetation/black.svg",
39971
+ key: VEGETATION_KEYS.BLACK_SPOTS,
39972
+ disabled: "/Vegetation/black-default.svg"
39973
+ }, {
39974
+ img: "/Vegetation/reddish.svg",
39975
+ key: VEGETATION_KEYS.REDDISH_SPOTS,
39976
+ disabled: "/Vegetation/reddish-default.svg"
39977
+ }, {
39978
+ img: "/Vegetation/yellowing.svg",
39979
+ key: VEGETATION_KEYS.YELLOWING,
39980
+ disabled: "/Vegetation/yellowing-default.svg"
39981
+ }, {
39982
+ img: "/Vegetation/mosaic.svg",
39983
+ key: VEGETATION_KEYS.MOSAIC,
39984
+ disabled: "/Vegetation/mosaic-default.svg"
39985
+ }, {
39986
+ img: "/Vegetation/dry-or-dead.svg",
39987
+ key: VEGETATION_KEYS.DRY_OR_DEAD,
39988
+ disabled: "/Vegetation/dry-or-dead-default.svg"
39989
+ }, {
39990
+ img: "/Vegetation/no-leaves.svg",
39991
+ key: VEGETATION_KEYS.NO_LEAVES,
39992
+ disabled: "/Vegetation/no-leaves-default.svg"
39993
+ }, {
39994
+ img: "/Vegetation/spider-webs.svg",
39995
+ key: VEGETATION_KEYS.SPIDER_WEBS,
39996
+ disabled: "/Vegetation/spider-webs-default.svg"
39997
+ }, {
39998
+ img: "/Vegetation/damage-from-insects.svg",
39999
+ key: VEGETATION_KEYS.DAMAGE_FROM_INSECTS,
40000
+ disabled: "/Vegetation/damage-from-insects-default.svg"
40001
+ }];
40002
+ };
40003
+
40004
+ function VegetationWidget({
40005
+ title = "Vegetation Health",
40006
+ activeVegetationConditions = [],
40007
+ filterKeys = null,
40008
+ columnsPerRow = null,
40009
+ itemWidth = 140.33,
40010
+ itemHeight = 140,
40011
+ growthObservations = [],
40012
+ t = key => key,
40013
+ ...props
40014
+ }) {
40015
+ let vegetationConfig = getVegetationConfig();
40016
+
40017
+ // Get all VEGETATION_KEYS values before filtering (needed for mapping check)
40018
+ const allVegetationKeys = vegetationConfig.map(item => item.key);
40019
+
40020
+ // Filter to show only specific keys if filterKeys is provided
40021
+ if (filterKeys && Array.isArray(filterKeys)) {
40022
+ vegetationConfig = vegetationConfig.filter(item => filterKeys.includes(item.key));
40023
+ }
40024
+
40025
+ // Map growthObservations to VEGETATION_KEYS
40026
+ // Handle both formats: growthObservations keys (e.g., "yellowing_leaves") and VEGETATION_KEYS (e.g., "yellowing")
40027
+ const mappedGrowthObservations = Array.isArray(growthObservations) ? growthObservations.map(obs => {
40028
+ // First try to map from growthObservations format
40029
+ const mapped = GROWTH_OBSERVATIONS_TO_VEGETATION_KEYS[obs];
40030
+ if (mapped) {
40031
+ return mapped;
40032
+ }
40033
+ // If not mapped, check if it's already a VEGETATION_KEY value
40034
+ if (allVegetationKeys.includes(obs)) {
40035
+ return obs;
40036
+ }
40037
+ // Debug: log unmapped observations
40038
+ if (obs) {
40039
+ console.warn(`VegetationWidget: Unmapped growthObservation "${obs}"`);
40040
+ }
40041
+ return null;
40042
+ }).filter(Boolean) : [];
40043
+ return /*#__PURE__*/jsxRuntime.jsx(Widget, {
40044
+ title: title,
40045
+ className: `with-border-header`,
40046
+ ...props,
40047
+ children: /*#__PURE__*/jsxRuntime.jsx(VegetationWrapper, {
40048
+ $columnsPerRow: columnsPerRow,
40049
+ children: /*#__PURE__*/jsxRuntime.jsx(VegetationContainer, {
40050
+ $columnsPerRow: columnsPerRow,
40051
+ $itemWidth: itemWidth,
40052
+ $itemHeight: itemHeight,
40053
+ children: vegetationConfig.map(item => {
40054
+ // Use colored SVG if the item's key exists in growthObservations (mapped)
40055
+ // Otherwise use default SVG
40056
+ // Also check activeVegetationConditions for backward compatibility
40057
+ const isInGrowthObservations = mappedGrowthObservations.includes(item.key);
40058
+ const isInActiveConditions = activeVegetationConditions.includes(item.key);
40059
+
40060
+ // Use colored SVG if it exists in growthObservations OR activeVegetationConditions
40061
+ const shouldUseColored = isInGrowthObservations || isInActiveConditions;
40062
+
40063
+ // Debug logging for yellowing specifically
40064
+ if (item.key === "yellowing") {
40065
+ console.log("Yellowing debug:", {
40066
+ itemKey: item.key,
40067
+ growthObservations,
40068
+ mappedGrowthObservations,
40069
+ isInGrowthObservations,
40070
+ isInActiveConditions,
40071
+ shouldUseColored,
40072
+ img: item.img,
40073
+ disabled: item.disabled
40074
+ });
40075
+ }
40076
+ return /*#__PURE__*/jsxRuntime.jsx(antd.Tooltip, {
40077
+ title: t(`straatos::${item.key}`),
40078
+ children: /*#__PURE__*/jsxRuntime.jsx("img", {
40079
+ src: shouldUseColored ? item.img : item.disabled,
40080
+ className: `vegetation-item`,
40081
+ alt: item.key
40082
+ }, item.key)
40083
+ }, item.key);
40084
+ })
40085
+ })
40086
+ })
40087
+ });
40088
+ }
40089
+ const VegetationWrapper = styled__default["default"].div`
40090
+ ${props => props.$columnsPerRow ? `
40091
+ overflow-x: auto;
40092
+ width: 100%;
40093
+ ` : ''}
40094
+ `;
40095
+ const VegetationContainer = styled__default["default"].div`
40096
+ display: grid;
40097
+ grid-template-columns: ${props => props.$columnsPerRow ? `repeat(${props.$columnsPerRow}, 1fr)` : `repeat(auto-fit, minmax(${props.$itemWidth}px, 1fr))`};
40098
+ gap: 24px;
40099
+ ${props => props.$columnsPerRow ? `
40100
+ width: 100%;
40101
+ ` : ''}
40102
+
40103
+ .vegetation-item {
40104
+ width: 100%;
40105
+ aspect-ratio: ${props => props.$itemWidth / props.$itemHeight};
40106
+ border-radius: 7px;
40107
+ flex-shrink: 0;
40108
+
40109
+ background-size: cover;
40110
+ background-position: center;
40111
+ background-repeat: no-repeat;
40112
+ }
40113
+
40114
+ .vegetation-item-content {
40115
+ display: flex;
40116
+ align-items: center;
40117
+ height: 100%;
40118
+ color: white;
40119
+ text-align: center;
40120
+ }
40121
+ `;
40122
+
39924
40123
  const RepeatableGroup = ({
39925
40124
  name = null,
39926
40125
  config = {},
@@ -40679,6 +40878,9 @@ class VersionService extends BaseService {
40679
40878
  var VersionService$1 = createLazyService(VersionService);
40680
40879
 
40681
40880
  const getSourcesType = subject => {
40881
+ console.log({
40882
+ subject
40883
+ });
40682
40884
  const typeMapping = {
40683
40885
  locations: "location",
40684
40886
  location: "location",
@@ -40692,7 +40894,8 @@ const getSourcesType = subject => {
40692
40894
  events: "event",
40693
40895
  event: "event",
40694
40896
  activities: "event",
40695
- incidents: "event"
40897
+ incidents: "event",
40898
+ "planting-cycle": "planting-cycle"
40696
40899
  };
40697
40900
  return typeMapping[subject] ?? null;
40698
40901
  };
@@ -41489,7 +41692,7 @@ styled__default["default"](antd.Tabs)`
41489
41692
  });
41490
41693
 
41491
41694
  const {
41492
- useToken
41695
+ useToken: useToken$1
41493
41696
  } = antd.theme;
41494
41697
 
41495
41698
  /**
@@ -41596,7 +41799,7 @@ function ColumnChart({
41596
41799
  const chartRef = React__default["default"].useRef(null);
41597
41800
  const {
41598
41801
  token
41599
- } = useToken();
41802
+ } = useToken$1();
41600
41803
  const {
41601
41804
  legendEnabled,
41602
41805
  legendItems,
@@ -41674,7 +41877,7 @@ function ColumnChart({
41674
41877
  className: "flex flex-1 flex-column justify-content-center",
41675
41878
  children: [/*#__PURE__*/jsxRuntime.jsx("div", {
41676
41879
  className: "flex justify-content-center",
41677
- children: /*#__PURE__*/jsxRuntime.jsx(Container$1, {
41880
+ children: /*#__PURE__*/jsxRuntime.jsx(Container$2, {
41678
41881
  ref: containerRef,
41679
41882
  height: height,
41680
41883
  isPdf: isPdf,
@@ -41689,6 +41892,165 @@ function ColumnChart({
41689
41892
  });
41690
41893
  }
41691
41894
 
41895
+ const {
41896
+ useToken
41897
+ } = antd.theme;
41898
+
41899
+ /**
41900
+ * DonutPie Component
41901
+ *
41902
+ * A reusable and customizable donut (pie) chart built using AntV G2Plot's `Pie` chart.
41903
+ * Designed for displaying part-to-whole relationships, with support for tooltips, statistics, and history.
41904
+ *
41905
+ * Props:
41906
+ * - `data` (Array):
41907
+ * The dataset to visualize. Each item should include the keys defined by `angleField` and `colorField`.
41908
+ * Default: `[]`
41909
+ *
41910
+ * - `angleField` (string):
41911
+ * Key in each data item to be used as the value for the angle.
41912
+ * Default: `"value"`
41913
+ *
41914
+ * - `colorField` (string):
41915
+ * Key in each data item to be used for color grouping.
41916
+ * Default: `"type"`
41917
+ *
41918
+ * - `renderTooltipContent` (function):
41919
+ * Optional callback to render custom tooltip content. Should return an object for your renderTooltip util.
41920
+ * If provided, `tooltipConfig` is also merged into the custom tooltip.
41921
+ *
41922
+ * - `tooltipConfig` (object):
41923
+ * Additional configuration for the tooltip, passed directly to the G2Plot `tooltip` option.
41924
+ *
41925
+ * - `statistic` (object|boolean):
41926
+ * Statistic configuration for the center label. Set to `false` to hide.
41927
+ *
41928
+ * - `color` (string | string[] | function):
41929
+ * Custom color or color function for slices. If not provided, falls back to Ant Design's theme primary color.
41930
+ *
41931
+ * - `history` (Array):
41932
+ * Array of previous datasets to display as small donut pies below the main chart.
41933
+ * Each item should be an object with at least a `data` array and an optional `label`.
41934
+ *
41935
+ * - `height` (number):
41936
+ * Height of the main chart.
41937
+ * Default: `200`
41938
+ *
41939
+ * - `innerRadius` (number):
41940
+ * Inner radius for the donut effect.
41941
+ * Default: `0.78`
41942
+ *
41943
+ * - `radius` (number):
41944
+ * Outer radius for the donut.
41945
+ * Default: `1`
41946
+ */
41947
+
41948
+ function DonutPie({
41949
+ data = [],
41950
+ angleField = "value",
41951
+ colorField = "type",
41952
+ color,
41953
+ height = 200,
41954
+ innerRadius = 0.78,
41955
+ radius = 1,
41956
+ legend = false,
41957
+ label = false,
41958
+ statistic = false,
41959
+ tooltip = true,
41960
+ renderTooltipContent,
41961
+ tooltipConfig = {},
41962
+ meta,
41963
+ animation = false,
41964
+ t = s => s,
41965
+ isPdf = false,
41966
+ legendConfig = {},
41967
+ ...rest
41968
+ }) {
41969
+ const containerRef = React.useRef(null);
41970
+ const chartRef = React.useRef(null);
41971
+ const {
41972
+ token
41973
+ } = useToken();
41974
+ const {
41975
+ legendEnabled,
41976
+ legendItems,
41977
+ legendPosition,
41978
+ legendLayout,
41979
+ legendInteractive,
41980
+ legendStyle
41981
+ } = useLegendConfig({
41982
+ legendConfig,
41983
+ isPdf
41984
+ });
41985
+
41986
+ // Memoize processed data for progress mode
41987
+ const processedData = React.useMemo(() => {
41988
+ if (!data || data.length === 0) {
41989
+ return [{
41990
+ type: "No Data",
41991
+ value: 1
41992
+ }];
41993
+ }
41994
+ return data;
41995
+ }, [data]);
41996
+ React.useEffect(() => {
41997
+ if (!containerRef.current) {
41998
+ return;
41999
+ }
42000
+ const tooltipOption = tooltip && renderTooltipContent ? {
42001
+ customContent: (title, data) => renderTooltip(renderTooltipContent(title, data)),
42002
+ ...tooltipConfig
42003
+ } : tooltip ? tooltipConfig : false;
42004
+ const config = {
42005
+ data: processedData,
42006
+ angleField,
42007
+ colorField,
42008
+ color: color || [token.colorPrimary7, "#E8EDF3"],
42009
+ radius,
42010
+ innerRadius,
42011
+ legend: false,
42012
+ label,
42013
+ statistic,
42014
+ tooltip: tooltipOption,
42015
+ meta,
42016
+ animation,
42017
+ ...rest
42018
+ };
42019
+ if (!chartRef.current) {
42020
+ chartRef.current = new g2plot.Pie(containerRef.current, config);
42021
+ chartRef.current.render();
42022
+ } else {
42023
+ chartRef.current.update(config);
42024
+ }
42025
+ }, [processedData, angleField, colorField, color, radius, innerRadius, legend, label, statistic, tooltip, renderTooltipContent, tooltipConfig, meta, animation, token.colorPrimary7, rest]);
42026
+ React.useEffect(() => {
42027
+ return () => {
42028
+ if (chartRef.current) {
42029
+ chartRef.current.destroy();
42030
+ chartRef.current = null;
42031
+ }
42032
+ };
42033
+ }, []);
42034
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
42035
+ className: "flex flex-1 flex-column justify-content-center",
42036
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
42037
+ className: "flex justify-content-center",
42038
+ children: /*#__PURE__*/jsxRuntime.jsx(Container$2, {
42039
+ ref: containerRef,
42040
+ style: {
42041
+ height
42042
+ },
42043
+ isPdf: isPdf
42044
+ })
42045
+ }), legendEnabled && legendPosition === 'bottom' && /*#__PURE__*/jsxRuntime.jsx(CustomLegend, {
42046
+ items: legendItems,
42047
+ layout: legendLayout,
42048
+ interactive: legendInteractive,
42049
+ style: legendStyle
42050
+ })]
42051
+ });
42052
+ }
42053
+
41692
42054
  styled__default["default"].div`
41693
42055
  .timeline {
41694
42056
  display: flex;
@@ -41872,7 +42234,7 @@ styled__default["default"].div`
41872
42234
  */
41873
42235
  const renderNumber = (val, doubleDigit = false) => {
41874
42236
  if (typeof val !== 'number') {
41875
- return '--';
42237
+ return '-';
41876
42238
  }
41877
42239
  const _string = Number(val).toLocaleString('en-us');
41878
42240
  if (doubleDigit) {
@@ -43132,15 +43494,15 @@ const getKeyIndicatorsRowConfig$3 = ({
43132
43494
  })
43133
43495
  }];
43134
43496
 
43135
- const normalizeUrl = url => url?.endsWith(':') ? url.slice(0, -1) : url;
43136
- const extractFromPhotoDoc = (photoDoc, label, docIndex) => {
43497
+ const normalizeUrl$1 = url => url?.endsWith(':') ? url.slice(0, -1) : url;
43498
+ const extractFromPhotoDoc$1 = (photoDoc, label, docIndex) => {
43137
43499
  const photos = photoDoc?.pictures?.filter(p => p?.url) || (photoDoc?.url ? [photoDoc] : []);
43138
43500
  return photos.map((photo, photoIndex) => ({
43139
- src: normalizeUrl(photo.url),
43501
+ src: normalizeUrl$1(photo.url),
43140
43502
  alt: photo.name || photo.alt || `${label} - Image ${docIndex + 1}-${photoIndex + 1}`
43141
43503
  }));
43142
43504
  };
43143
- const getActivityImages = activityData => {
43505
+ const getActivityImages$1 = activityData => {
43144
43506
  const photoArrays = [{
43145
43507
  data: activityData?.groupPhotos,
43146
43508
  label: 'Group Photo'
@@ -43157,7 +43519,7 @@ const getActivityImages = activityData => {
43157
43519
  return photoArrays.flatMap(({
43158
43520
  data,
43159
43521
  label
43160
- }) => Array.isArray(data) ? data.flatMap((photoDoc, index) => extractFromPhotoDoc(photoDoc, label, index)) : []);
43522
+ }) => Array.isArray(data) ? data.flatMap((photoDoc, index) => extractFromPhotoDoc$1(photoDoc, label, index)) : []);
43161
43523
  };
43162
43524
  const GENDER_COLORS$1 = ['#016C6E', '#00AEB1'];
43163
43525
  const getGenderDistributionData$1 = activityData => {
@@ -43682,7 +44044,7 @@ class NotificationService extends BaseService {
43682
44044
  }
43683
44045
  createLazyService(NotificationService);
43684
44046
 
43685
- const ActivityImagery = ({
44047
+ const ActivityImagery$1 = ({
43686
44048
  activityData,
43687
44049
  loading = false,
43688
44050
  t = s => s
@@ -43691,7 +44053,7 @@ const ActivityImagery = ({
43691
44053
  isCollapsed,
43692
44054
  isNestedSidebarCollapsed
43693
44055
  } = useResizeContext();
43694
- const images = React.useMemo(() => getActivityImages(activityData), [activityData]);
44056
+ const images = React.useMemo(() => getActivityImages$1(activityData), [activityData]);
43695
44057
  return /*#__PURE__*/jsxRuntime.jsx("div", {
43696
44058
  style: {
43697
44059
  maxWidth: "70%",
@@ -43787,7 +44149,7 @@ const RestorationActivitySummary = ({
43787
44149
  title: t("Activity Indicators"),
43788
44150
  className: "small-content"
43789
44151
  }), /*#__PURE__*/jsxRuntime.jsxs("section", {
43790
- children: [/*#__PURE__*/jsxRuntime.jsx(ActivityImagery, {
44152
+ children: [/*#__PURE__*/jsxRuntime.jsx(ActivityImagery$1, {
43791
44153
  activityData: activityData,
43792
44154
  loading: loading,
43793
44155
  t: t
@@ -47745,7 +48107,7 @@ const getKeyIndicatorsRowConfig = ({
47745
48107
  }, {
47746
48108
  label: t('Monitored Area'),
47747
48109
  render: () => /*#__PURE__*/jsxRuntime.jsx("div", {
47748
- children: data?.totalAreaParcelMonitored ? `${data?.totalAreaParcelMonitored} ha` : '0 ha'
48110
+ children: data?.totalAreaParcelMonitored ? `${renderNumber(data?.totalAreaParcelMonitored)} ha` : '0 ha'
47749
48111
  })
47750
48112
  }];
47751
48113
  const getSiteConditionsConfig = ({
@@ -47776,7 +48138,77 @@ const getSiteConditionsConfig = ({
47776
48138
  children: data?.hasDisturbances ? t('Yes') : t('No')
47777
48139
  })
47778
48140
  }];
48141
+ const getEnvironmentalMetricsConfig = ({
48142
+ t,
48143
+ data = {},
48144
+ options
48145
+ }) => [{
48146
+ label: t('Soil Type'),
48147
+ render: () => /*#__PURE__*/jsxRuntime.jsx("div", {
48148
+ children: camelCaseToTitle(data?.soilType) || '-'
48149
+ })
48150
+ }, {
48151
+ label: t('Soil Salinity'),
48152
+ render: () => /*#__PURE__*/jsxRuntime.jsx("div", {
48153
+ children: data?.soilSalinity ? `${renderNumber(data.soilSalinity)} ${data?.soilSalinityUnit || 'dS/m'}` : '-'
48154
+ })
48155
+ }, {
48156
+ label: t('pH Level'),
48157
+ render: () => /*#__PURE__*/jsxRuntime.jsx("div", {
48158
+ children: renderNumber(data?.phLevel) || '-'
48159
+ })
48160
+ }, {
48161
+ label: t('Water Quality'),
48162
+ render: () => /*#__PURE__*/jsxRuntime.jsx("div", {
48163
+ children: findOptions(data?.waterQuality, options?.waterQuality) || '-'
48164
+ })
48165
+ }];
47779
48166
 
48167
+ const normalizeUrl = url => url?.endsWith(':') ? url.slice(0, -1) : url;
48168
+ const extractFromPhotoDoc = (photoDoc, label, docIndex) => {
48169
+ const photos = photoDoc?.pictures?.filter(p => p?.url) || (photoDoc?.url ? [photoDoc] : []);
48170
+ return photos.map((photo, photoIndex) => ({
48171
+ src: normalizeUrl(photo.url),
48172
+ alt: photo.name || photo.alt || `${label} - Image ${docIndex + 1}-${photoIndex + 1}`
48173
+ }));
48174
+ };
48175
+ const getActivityImages = activityData => {
48176
+ const photoArrays = [{
48177
+ data: activityData?.groupPhotos,
48178
+ label: 'Group Photo'
48179
+ }, {
48180
+ data: activityData?.photosStartActivity,
48181
+ label: 'Start of Activity'
48182
+ }, {
48183
+ data: activityData?.photosDuringActivity,
48184
+ label: 'During Activity'
48185
+ }, {
48186
+ data: activityData?.photosEndActivity,
48187
+ label: 'End of Activity'
48188
+ }, {
48189
+ data: activityData?.plotPhotosMonitoring,
48190
+ label: 'Plot Photos Monitoring'
48191
+ }, {
48192
+ data: activityData?.faunaFloraPictures,
48193
+ label: 'Fauna and Flora Photos'
48194
+ }, {
48195
+ data: activityData?.pestPlantPhotos,
48196
+ label: 'Pest Plant Photos'
48197
+ }, {
48198
+ data: activityData?.soilPhotos,
48199
+ label: 'Soil Photos'
48200
+ }, {
48201
+ data: activityData?.otherPictures,
48202
+ label: 'Other Pictures'
48203
+ }, {
48204
+ data: activityData?.damagedPlantPhotos,
48205
+ label: 'Damaged Plant Photos'
48206
+ }];
48207
+ return photoArrays.flatMap(({
48208
+ data,
48209
+ label
48210
+ }) => Array.isArray(data) ? data.flatMap((photoDoc, index) => extractFromPhotoDoc(photoDoc, label, index)) : []);
48211
+ };
47780
48212
  const getIndicatorType = value => {
47781
48213
  if (value === "yes" || value === true) return "compliant";
47782
48214
  if (value === "no" || value === false) return "notCompliant";
@@ -48028,50 +48460,79 @@ const ActivityLocation = ({
48028
48460
  });
48029
48461
  };
48030
48462
 
48031
- const PlantedSpecies = ({
48463
+ const ActivityImagery = ({
48032
48464
  activityData,
48033
48465
  loading = false,
48034
48466
  t = s => s
48035
48467
  }) => {
48036
- const speciesConfig = React.useMemo(() => {
48037
- // Extract planted species from activityData
48038
- // Assuming the data structure might have plantedSpecies array or similar
48039
- const species = activityData?.plantedSpecies || activityData?.mangroveSpecies || [];
48468
+ const {
48469
+ isCollapsed,
48470
+ isNestedSidebarCollapsed
48471
+ } = useResizeContext();
48472
+ const images = React.useMemo(() => getActivityImages(activityData), [activityData]);
48473
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
48474
+ style: {
48475
+ maxWidth: "50%",
48476
+ width: "calc(100% - 405px)"
48477
+ },
48478
+ children: /*#__PURE__*/jsxRuntime.jsx(ImageCarousel, {
48479
+ loading: loading,
48480
+ images: images,
48481
+ title: t("straatos::activity-imagery"),
48482
+ customArrows: true,
48483
+ activeDotColor: "#003435",
48484
+ height: 245
48485
+ }, `${isCollapsed}-${isNestedSidebarCollapsed}`)
48486
+ });
48487
+ };
48040
48488
 
48041
- // If species is an array, map it to config format
48042
- if (Array.isArray(species)) {
48043
- return species.map((speciesItem, index) => {
48044
- const speciesName = typeof speciesItem === 'string' ? speciesItem : speciesItem?.name || speciesItem?.species || `Species ${index + 1}`;
48489
+ const EnvironmentalMetrics = ({
48490
+ activityData,
48491
+ loading = false,
48492
+ t = s => s,
48493
+ options
48494
+ }) => {
48495
+ const environmentalMetricsConfig = React.useMemo(() => getEnvironmentalMetricsConfig({
48496
+ t,
48497
+ data: activityData,
48498
+ options
48499
+ }), [t, activityData]);
48500
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
48501
+ style: {
48502
+ flex: 1
48503
+ },
48504
+ children: /*#__PURE__*/jsxRuntime.jsx(KeyIndicatorsWidget, {
48505
+ loading: loading,
48506
+ config: environmentalMetricsConfig,
48507
+ title: t("straatos::environmental-metrics"),
48508
+ className: "small-content row-content",
48509
+ widgetClassName: "h-w-btn-header"
48510
+ })
48511
+ });
48512
+ };
48045
48513
 
48046
- // Determine if species is selected/planted (you may need to adjust this logic)
48047
- const isSelected = typeof speciesItem === 'object' ? speciesItem?.selected !== false : true;
48514
+ const PlantedSpecies = ({
48515
+ plantedSpecies,
48516
+ mangroveSpecies,
48517
+ loading = false,
48518
+ t = s => s
48519
+ }) => {
48520
+ const speciesConfig = React.useMemo(() => {
48521
+ if (Array.isArray(mangroveSpecies) && mangroveSpecies.length > 0) {
48522
+ return mangroveSpecies.map(species => {
48523
+ const isPlanted = species.value === plantedSpecies;
48048
48524
  return {
48049
- icon: 'Tree',
48050
- label: speciesName,
48051
- type: isSelected ? 'compliant' : 'notCompliant',
48052
- statusIcon: isSelected ? 'Check' : 'Close'
48525
+ label: species.label,
48526
+ type: isPlanted ? 'compliant' : 'notCompliant',
48527
+ statusIcon: isPlanted ? 'Check' : 'Close',
48528
+ statusIconColor: isPlanted ? '#12B76A' : '#6C737F',
48529
+ statusBadgeBackgroundColor: isPlanted ? undefined : '#F9FAFB',
48530
+ statusBadgeBorderColor: isPlanted ? undefined : '#E5E7EB'
48053
48531
  };
48054
48532
  });
48055
48533
  }
48056
-
48057
- // Fallback: if no species data, show default species from image
48058
- return [{
48059
- icon: 'Tree',
48060
- label: 'Rhyzophora sp',
48061
- type: 'compliant',
48062
- statusIcon: 'Check'
48063
- }, {
48064
- icon: 'Tree',
48065
- label: 'Rhyzophora',
48066
- type: 'notCompliant',
48067
- statusIcon: 'Close'
48068
- }, {
48069
- icon: 'Tree',
48070
- label: 'Rhyzophora mangle',
48071
- type: 'notCompliant',
48072
- statusIcon: 'Close'
48073
- }];
48074
- }, [activityData]);
48534
+ return [];
48535
+ }, [plantedSpecies, mangroveSpecies]);
48075
48536
  return /*#__PURE__*/jsxRuntime.jsx(ActivityIndicatorsWidget, {
48076
48537
  title: t("Planted Species"),
48077
48538
  config: speciesConfig,
@@ -48083,76 +48544,89 @@ const PlantedSpecies = ({
48083
48544
  };
48084
48545
 
48085
48546
  const SurvivalRate = ({
48086
- activityData,
48547
+ survivalRate,
48087
48548
  loading = false,
48088
48549
  t = s => s
48089
48550
  }) => {
48090
- React.useMemo(() => {
48091
- // Extract survival rate from activityData
48092
- // Assuming the data might have survivalRate as a percentage (0-100)
48093
- const survivalRate = activityData?.survivalRate || activityData?.mangroveSurvivalRate || 78;
48094
- const survivalPercent = typeof survivalRate === 'number' ? survivalRate : parseFloat(survivalRate) || 78;
48551
+ const survivalData = React.useMemo(() => {
48552
+ if (!survivalRate && survivalRate !== 0) {
48553
+ return [];
48554
+ }
48095
48555
  return [{
48096
48556
  type: t("Survival Rate"),
48097
- value: survivalPercent
48557
+ value: Math.round(survivalRate || 0)
48098
48558
  }, {
48099
48559
  type: t("Non-survival"),
48100
- value: 100 - survivalPercent
48560
+ value: 100 - Math.round(survivalRate || 0)
48101
48561
  }];
48102
- }, [activityData, t]);
48103
- React.useMemo(() => {
48562
+ }, [survivalRate, t]);
48563
+ const renderTooltipContent = React.useMemo(() => {
48104
48564
  return (title, data) => {
48105
- if (!data || data.length === 0) {
48565
+ if (!survivalData || survivalData.length === 0 || !data || data.length === 0) {
48106
48566
  return {
48107
48567
  title: t("Survival Rate"),
48108
48568
  items: [{
48109
- label: t("No Data"),
48569
+ label: t("Not answered"),
48110
48570
  value: '-'
48111
48571
  }]
48112
48572
  };
48113
48573
  }
48114
- const item = data[0];
48115
- const value = item?.value || item?.data?.value || 0;
48116
- const itemType = item?.type || item?.data?.type || t("Survival Rate");
48117
-
48118
- // Determine color based on item type
48119
- const itemColor = itemType === t("Survival Rate") ? '#00AEB1' : '#E8EDF3';
48120
48574
  return {
48121
48575
  title: t("Survival Rate"),
48122
- items: [{
48123
- label: itemType,
48124
- value: `${value.toFixed(1)}%`,
48125
- color: itemColor
48126
- }]
48576
+ items: survivalData.map(item => ({
48577
+ label: item.type,
48578
+ value: item.value + '%',
48579
+ color: item.type === t("Survival Rate") ? '#00AEB1' : '#E8EDF3'
48580
+ }))
48127
48581
  };
48128
48582
  };
48129
- }, [t]);
48130
- React.useMemo(() => {
48131
- return !activityData?.survivalRate && !activityData?.mangroveSurvivalRate;
48132
- }, [activityData]);
48583
+ }, [survivalData, t]);
48584
+ const isEmpty = React.useMemo(() => {
48585
+ return !survivalRate && survivalRate !== 0;
48586
+ }, [survivalRate]);
48587
+ const chartColors = React.useMemo(() => {
48588
+ if (isEmpty) {
48589
+ return ['#E5E7EB', '#F9FAFB'];
48590
+ }
48591
+ return ['#00AEB1', '#E8EDF3'];
48592
+ }, [isEmpty]);
48133
48593
  return /*#__PURE__*/jsxRuntime.jsx(Widget, {
48134
48594
  loading: loading,
48135
48595
  title: t("Survival Rate"),
48136
- className: "with-border-header h-w-btn-header"
48596
+ className: "with-border-header h-w-btn-header",
48597
+ children: /*#__PURE__*/jsxRuntime.jsx(DonutPie, {
48598
+ angleField: "value",
48599
+ color: chartColors,
48600
+ colorField: "type",
48601
+ data: isEmpty ? [] : survivalData,
48602
+ height: 250,
48603
+ innerRadius: 0.78,
48604
+ radius: 1,
48605
+ renderTooltipContent: renderTooltipContent,
48606
+ tooltip: true,
48607
+ tooltipConfig: {
48608
+ showTitle: false
48609
+ }
48610
+ })
48137
48611
  });
48138
48612
  };
48139
48613
 
48140
48614
  const SeedlingsHeight = ({
48141
- activityData,
48615
+ averageHeight,
48616
+ averageHeightUnit,
48142
48617
  loading = false,
48143
48618
  t = s => s
48144
48619
  }) => {
48145
48620
  const heightData = React.useMemo(() => {
48146
48621
  // Extract seedlings height from activityData
48147
48622
  // Assuming the data might have averageHeight, seedlingsHeight, or similar
48148
- const averageHeight = activityData?.averageHeight || activityData?.seedlingsHeight || activityData?.mangroveAverageHeight || 28; // Default from image
48149
-
48150
- const heightValue = typeof averageHeight === 'number' ? averageHeight : parseFloat(averageHeight) || 28;
48623
+ const heightValue = typeof averageHeight === 'number' ? averageHeight : parseFloat(averageHeight) || 0;
48151
48624
  return [{
48152
48625
  label: t("Average Height"),
48153
- value: heightValue
48626
+ value: heightValue,
48627
+ unit: averageHeightUnit
48154
48628
  }];
48155
- }, [activityData, t]);
48629
+ }, [averageHeight, averageHeightUnit, t]);
48156
48630
  const renderTooltipContent = React.useMemo(() => {
48157
48631
  return (title, data) => {
48158
48632
  if (!data || data.length === 0) {
@@ -48165,102 +48639,223 @@ const SeedlingsHeight = ({
48165
48639
  };
48166
48640
  }
48167
48641
  const item = data[0];
48168
- const value = item?.value || item?.data?.value || 0;
48642
+ const rawValue = item?.value || item?.data?.value || 0;
48643
+ const value = Number(rawValue) || 0;
48644
+ const formattedValue = Number(value).toLocaleString('en-us');
48169
48645
  return {
48170
48646
  title: t("Average Height"),
48171
48647
  items: [{
48172
48648
  label: t("Average Height"),
48173
- value: `${value.toFixed(1)}cm`,
48649
+ value: `${formattedValue} ${averageHeightUnit || 'cm'}`,
48174
48650
  color: '#00AEB1'
48175
48651
  }]
48176
48652
  };
48177
48653
  };
48178
- }, [t]);
48654
+ }, [t, averageHeightUnit]);
48179
48655
  const isEmpty = React.useMemo(() => {
48180
- return !activityData?.averageHeight && !activityData?.seedlingsHeight && !activityData?.mangroveAverageHeight;
48181
- }, [activityData]);
48182
- return /*#__PURE__*/jsxRuntime.jsx(Widget, {
48656
+ return !averageHeight && averageHeight !== 0;
48657
+ }, [averageHeight]);
48658
+ return /*#__PURE__*/jsxRuntime.jsxs(Widget, {
48183
48659
  loading: loading,
48184
48660
  title: t("Seedlings Height"),
48185
48661
  className: "with-border-header h-w-btn-header",
48186
- children: /*#__PURE__*/jsxRuntime.jsxs("div", {
48187
- style: {
48188
- display: 'flex',
48189
- flexDirection: 'column',
48190
- minHeight: '250px',
48191
- padding: '20px 0'
48662
+ children: [/*#__PURE__*/jsxRuntime.jsx(ColumnChart, {
48663
+ data: isEmpty ? [] : heightData,
48664
+ xFieldKey: "label",
48665
+ yFieldKey: "value",
48666
+ color: "#00AEB1",
48667
+ animated: true,
48668
+ renderTooltipContent: renderTooltipContent,
48669
+ yAxis: {
48670
+ min: 0,
48671
+ max: 35,
48672
+ tickMethod: () => [0, 5, 10, 15, 20, 25, 30, 35],
48673
+ label: {
48674
+ formatter: v => `${v} ${averageHeightUnit || 'cm'}`
48675
+ }
48192
48676
  },
48193
- children: [/*#__PURE__*/jsxRuntime.jsx(ColumnChart, {
48194
- data: isEmpty ? [] : heightData,
48195
- xFieldKey: "label",
48196
- yFieldKey: "value",
48197
- color: "#00AEB1",
48198
- height: 250,
48199
- animated: true,
48200
- renderTooltipContent: renderTooltipContent,
48201
- yAxis: {
48202
- min: 0,
48203
- max: 35,
48204
- tickMethod: () => [0, 5, 10, 15, 20, 25, 30, 35],
48205
- label: {
48206
- formatter: v => `${v}cm`
48207
- }
48208
- },
48209
- xAxis: {
48210
- label: {
48211
- formatter: () => ''
48212
- }
48213
- },
48214
- tooltipConfig: {
48215
- showTitle: true
48677
+ xAxis: {
48678
+ label: {
48679
+ formatter: () => ''
48216
48680
  }
48217
- }), !isEmpty && /*#__PURE__*/jsxRuntime.jsxs("div", {
48218
- style: {
48219
- marginTop: '16px',
48220
- textAlign: 'center',
48221
- fontSize: '14px',
48222
- color: '#475467',
48223
- fontWeight: 500
48224
- },
48225
- children: [t("Average Height"), ": ", heightData[0]?.value.toFixed(0), "cm"]
48226
- })]
48227
- })
48681
+ },
48682
+ tooltipConfig: {
48683
+ showTitle: true
48684
+ }
48685
+ }), !isEmpty && /*#__PURE__*/jsxRuntime.jsx("div", {
48686
+ style: {
48687
+ marginTop: '16px',
48688
+ textAlign: 'center',
48689
+ fontSize: '14px',
48690
+ color: '#475467',
48691
+ fontWeight: 500
48692
+ }
48693
+ })]
48228
48694
  });
48229
48695
  };
48230
48696
 
48231
- const Container = styled__default["default"].div`
48697
+ const Container$1 = styled__default["default"].div`
48232
48698
  display: grid;
48233
- grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
48699
+ grid-template-columns: repeat(3, 1fr);
48234
48700
  gap: 24px;
48235
48701
  width: 100%;
48702
+ overflow-x: auto;
48703
+
48704
+ > * {
48705
+ min-width: 0;
48706
+ }
48236
48707
 
48237
48708
  @media (max-width: 768px) {
48238
- grid-template-columns: 1fr;
48709
+ grid-template-columns: repeat(3, minmax(200px, 1fr));
48710
+ }
48711
+ `;
48712
+ const VegetationHealthContainer = styled__default["default"].div`
48713
+ display: flex;
48714
+ gap: 24px;
48715
+ width: 100%;
48716
+
48717
+ @media (max-width: 768px) {
48718
+ flex-direction: column;
48239
48719
  }
48240
48720
  `;
48721
+ const VegetationHealthSection = styled__default["default"].section`
48722
+ width: 66%;
48723
+ `;
48241
48724
  const MangroveGrowthAndSurvival = ({
48242
48725
  activityData,
48243
48726
  loading = false,
48244
- t = s => s
48727
+ t = s => s,
48728
+ options
48245
48729
  }) => {
48246
48730
  return /*#__PURE__*/jsxRuntime.jsx(Widget, {
48247
- title: t("Mangrove Growth & Survival"),
48731
+ title: t("Mangrove Growth and Survival"),
48248
48732
  className: "with-border-header h-w-btn-header",
48249
- children: /*#__PURE__*/jsxRuntime.jsx("section", {
48250
- children: /*#__PURE__*/jsxRuntime.jsxs(Container, {
48733
+ children: /*#__PURE__*/jsxRuntime.jsxs("section", {
48734
+ children: [/*#__PURE__*/jsxRuntime.jsxs(Container$1, {
48251
48735
  children: [/*#__PURE__*/jsxRuntime.jsx(PlantedSpecies, {
48252
- activityData: activityData,
48736
+ plantedSpecies: activityData?.plantedSpecies,
48737
+ mangroveSpecies: options?.mangroveSpecies,
48253
48738
  loading: loading,
48254
48739
  t: t
48255
48740
  }), /*#__PURE__*/jsxRuntime.jsx(SurvivalRate, {
48256
- activityData: activityData,
48741
+ survivalRate: activityData?.survivalRate,
48257
48742
  loading: loading,
48258
48743
  t: t
48259
48744
  }), /*#__PURE__*/jsxRuntime.jsx(SeedlingsHeight, {
48260
- activityData: activityData,
48745
+ averageHeight: activityData?.averageHeightValue,
48746
+ averageHeightUnit: activityData?.averageHeightUnit,
48261
48747
  loading: loading,
48262
48748
  t: t
48263
48749
  })]
48750
+ }), /*#__PURE__*/jsxRuntime.jsxs(VegetationHealthContainer, {
48751
+ children: [/*#__PURE__*/jsxRuntime.jsx(VegetationHealthSection, {
48752
+ children: /*#__PURE__*/jsxRuntime.jsx(VegetationWidget, {
48753
+ title: t("Vegetation Health"),
48754
+ vegetationHealthChart: activityData?.growthObservations,
48755
+ growthObservations: activityData?.growthObservations,
48756
+ filterKeys: [VEGETATION_KEYS.HEALTHY, VEGETATION_KEYS.WHITE_SPOTS, VEGETATION_KEYS.BLACK_SPOTS, VEGETATION_KEYS.REDDISH_SPOTS, VEGETATION_KEYS.YELLOWING, VEGETATION_KEYS.MOSAIC, VEGETATION_KEYS.DRY_OR_DEAD, VEGETATION_KEYS.NO_LEAVES],
48757
+ columnsPerRow: 4,
48758
+ itemWidth: 80,
48759
+ itemHeight: 80,
48760
+ activeVegetationConditions: activityData?.vegetationHealthChart?.filter(item => item?.type !== VEGETATION_KEYS.SPIDER_WEBS && item?.type !== VEGETATION_KEYS.DAMAGE_FROM_INSECTS)?.map(item => item?.type) || [],
48761
+ loading: loading,
48762
+ t: t
48763
+ })
48764
+ }), /*#__PURE__*/jsxRuntime.jsx(VegetationWidget, {
48765
+ title: t("Vegetation Health"),
48766
+ growthObservations: activityData?.growthObservations,
48767
+ activeVegetationConditions: activityData?.vegetationHealthChart?.filter(item => item?.type === VEGETATION_KEYS.SPIDER_WEBS || item?.type === VEGETATION_KEYS.DAMAGE_FROM_INSECTS)?.map(item => item?.type) || [],
48768
+ filterKeys: [VEGETATION_KEYS.SPIDER_WEBS, VEGETATION_KEYS.DAMAGE_FROM_INSECTS],
48769
+ columnsPerRow: 1,
48770
+ itemWidth: 210,
48771
+ itemHeight: 105,
48772
+ loading: loading,
48773
+ t: t
48774
+ })]
48775
+ })]
48776
+ })
48777
+ });
48778
+ };
48779
+
48780
+ const FAUNA_KEYS = ['birds', 'juveniles', 'crabs', 'cymbium', 'fish', 'mongooses', 'mollusks', 'monkeys', 'oysters', 'snails', 'caterpillars', 'animal_tracks', 'other'];
48781
+ const INVASIVE_SPECIES_KEYS = ['spiders', 'scaleInsects', 'caterpillars', 'unidentifiedPests', 'other'];
48782
+ const formatFaunaLabel = key => {
48783
+ return key.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
48784
+ };
48785
+ const formatInvasiveSpeciesLabel = key => {
48786
+ return key.replace(/([A-Z])/g, ' $1').split(' ').map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(' ');
48787
+ };
48788
+ const createFaunaIndicatorConfig = (key, faunaPresent, t) => {
48789
+ const isPresent = Array.isArray(faunaPresent) && faunaPresent.includes(key);
48790
+ const label = formatFaunaLabel(key);
48791
+ return {
48792
+ label: t(label),
48793
+ type: isPresent ? 'compliant' : 'notCompliant',
48794
+ statusIcon: isPresent ? 'Check' : 'Close',
48795
+ statusIconColor: isPresent ? '#12B76A' : '#6C737F',
48796
+ statusBadgeBackgroundColor: isPresent ? undefined : '#F9FAFB',
48797
+ statusBadgeBorderColor: isPresent ? undefined : '#E5E7EB'
48798
+ };
48799
+ };
48800
+ const createInvasiveSpeciesIndicatorConfig = (key, invasiveSpecies, hasInvasiveSpecies, t) => {
48801
+ const shouldShowAllAsNotPresent = hasInvasiveSpecies === 'no';
48802
+ const shouldShowRedForPresent = hasInvasiveSpecies === 'yes';
48803
+ const isPresent = !shouldShowAllAsNotPresent && Array.isArray(invasiveSpecies) && invasiveSpecies.includes(key);
48804
+ const isRedBadge = isPresent && shouldShowRedForPresent;
48805
+ const label = formatInvasiveSpeciesLabel(key);
48806
+ return {
48807
+ label: t(label),
48808
+ type: isPresent ? 'compliant' : 'notCompliant',
48809
+ statusIcon: isPresent ? 'Check' : 'Close',
48810
+ statusIconColor: isRedBadge ? '#D92D20' : isPresent ? '#12B76A' : '#6C737F',
48811
+ statusBadgeBackgroundColor: isRedBadge ? '#FEE4E2' : isPresent ? undefined : '#F9FAFB',
48812
+ statusBadgeBorderColor: isRedBadge ? '#FDA29B' : isPresent ? undefined : '#E5E7EB'
48813
+ };
48814
+ };
48815
+ const generateFaunaConfig = (faunaPresent, t) => {
48816
+ return FAUNA_KEYS.map(key => createFaunaIndicatorConfig(key, faunaPresent, t));
48817
+ };
48818
+ const generateInvasiveSpeciesConfig = (invasiveSpecies, hasInvasiveSpecies, t) => {
48819
+ return INVASIVE_SPECIES_KEYS.map(key => createInvasiveSpeciesIndicatorConfig(key, invasiveSpecies, hasInvasiveSpecies, t));
48820
+ };
48821
+
48822
+ const Container = styled__default["default"].div`
48823
+ display: grid;
48824
+ grid-template-columns: 70% 28.5%;
48825
+ gap: 24px;
48826
+ width: 100%;
48827
+ @media (max-width: 768px) {
48828
+ grid-template-columns: 1fr;
48829
+ }
48830
+ `;
48831
+ const BiodiversityAndHabitat = ({
48832
+ faunaPresent = [],
48833
+ invasiveSpecies = [],
48834
+ hasInvasiveSpecies,
48835
+ loading = false,
48836
+ t = s => s
48837
+ }) => {
48838
+ const observedFaunaConfig = React.useMemo(() => generateFaunaConfig(faunaPresent, t), [faunaPresent, t]);
48839
+ const invasiveSpeciesConfig = React.useMemo(() => generateInvasiveSpeciesConfig(invasiveSpecies, hasInvasiveSpecies, t), [invasiveSpecies, hasInvasiveSpecies, t]);
48840
+ return /*#__PURE__*/jsxRuntime.jsx(Widget, {
48841
+ title: t("Biodiversity & Habitat"),
48842
+ className: "with-border-header h-w-btn-header",
48843
+ children: /*#__PURE__*/jsxRuntime.jsx("section", {
48844
+ children: /*#__PURE__*/jsxRuntime.jsxs(Container, {
48845
+ children: [/*#__PURE__*/jsxRuntime.jsx(ActivityIndicatorsWidget, {
48846
+ title: t("Observed Fauna"),
48847
+ config: observedFaunaConfig,
48848
+ loading: loading,
48849
+ widgetClassName: "h-w-btn-header",
48850
+ t: t
48851
+ }), /*#__PURE__*/jsxRuntime.jsx(ActivityIndicatorsWidget, {
48852
+ title: t("Invasive Species"),
48853
+ config: invasiveSpeciesConfig,
48854
+ loading: loading,
48855
+ className: "single-column",
48856
+ widgetClassName: "h-w-btn-header",
48857
+ t: t
48858
+ })]
48264
48859
  })
48265
48860
  })
48266
48861
  });
@@ -48275,7 +48870,8 @@ const MonitoringActivitySummary = ({
48275
48870
  breadcrumbs,
48276
48871
  goBackTo,
48277
48872
  loading,
48278
- t = () => {}
48873
+ t = () => {},
48874
+ options
48279
48875
  }) => {
48280
48876
  const keyIndicatorsConfig = React.useMemo(() => getKeyIndicatorsRowConfig({
48281
48877
  t,
@@ -48290,9 +48886,6 @@ const MonitoringActivitySummary = ({
48290
48886
  t,
48291
48887
  data: activityData
48292
48888
  }), [t, activityData]);
48293
- console.log({
48294
- activityData
48295
- });
48296
48889
  return /*#__PURE__*/jsxRuntime.jsxs(DashboardLayout, {
48297
48890
  header: /*#__PURE__*/jsxRuntime.jsx(DAFHeader, {
48298
48891
  title: 'Monitoring Activity Summary',
@@ -48320,9 +48913,31 @@ const MonitoringActivitySummary = ({
48320
48913
  title: t("straatos::site-conditions"),
48321
48914
  widgetClassName: "h-w-btn-header"
48322
48915
  }), /*#__PURE__*/jsxRuntime.jsx(MangroveGrowthAndSurvival, {
48916
+ options: options,
48323
48917
  activityData: activityData,
48324
48918
  loading: loading,
48325
48919
  t: t
48920
+ }), /*#__PURE__*/jsxRuntime.jsx(BiodiversityAndHabitat, {
48921
+ faunaPresent: activityData?.faunaPresent,
48922
+ invasiveSpecies: activityData?.invasiveSpecies,
48923
+ hasInvasiveSpecies: activityData?.hasInvasiveSpecies,
48924
+ loading: loading,
48925
+ t: t
48926
+ }), /*#__PURE__*/jsxRuntime.jsxs("section", {
48927
+ style: {
48928
+ display: 'flex',
48929
+ gap: '24px'
48930
+ },
48931
+ children: [/*#__PURE__*/jsxRuntime.jsx(EnvironmentalMetrics, {
48932
+ options: options,
48933
+ activityData: activityData,
48934
+ loading: loading,
48935
+ t: t
48936
+ }), /*#__PURE__*/jsxRuntime.jsx(ActivityImagery, {
48937
+ activityData: activityData,
48938
+ loading: loading,
48939
+ t: t
48940
+ })]
48326
48941
  })]
48327
48942
  });
48328
48943
  };