datastake-daf 0.6.787 → 0.6.789

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 (62) hide show
  1. package/build/favicon.ico +0 -0
  2. package/build/logo192.png +0 -0
  3. package/build/logo512.png +0 -0
  4. package/build/manifest.json +25 -0
  5. package/build/robots.txt +3 -0
  6. package/dist/components/index.js +588 -729
  7. package/dist/pages/index.js +775 -34
  8. package/dist/services/index.js +1 -10
  9. package/dist/utils/index.js +12 -28
  10. package/package.json +1 -1
  11. package/src/@daf/core/components/Dashboard/Widget/ActivityIndicators/ActivityIndicators.stories.js +24 -0
  12. package/src/@daf/core/components/Dashboard/Widget/ActivityIndicators/index.jsx +1 -0
  13. package/src/@daf/core/components/Dashboard/Widget/ActivityIndicators/style.js +34 -0
  14. package/src/@daf/core/components/Dashboard/Widget/KeyIndicators/KeyIndicators.stories.js +39 -0
  15. package/src/@daf/core/components/Dashboard/Widget/KeyIndicators/LabelWithIcon.jsx +38 -0
  16. package/src/@daf/core/components/Dashboard/Widget/KeyIndicators/index.jsx +16 -3
  17. package/src/@daf/core/components/Dashboard/Widget/KeyIndicators/style.js +33 -0
  18. package/src/@daf/core/components/Screens/Admin/AdminDashboard/components/UserStatistics/TopContributors/hook.js +1 -0
  19. package/src/@daf/core/components/Screens/Admin/AdminDashboard/components/UserStatistics/TopContributors/index.jsx +1 -1
  20. package/src/@daf/core/components/Screens/Admin/AdminDashboard/components/UserStatistics/UserGrowth/hook.js +1 -1
  21. package/src/@daf/core/components/Screens/Admin/AdminDashboard/components/UserStatistics/UserGrowth/index.jsx +1 -1
  22. package/src/@daf/core/components/Screens/Admin/AdminModals/AddUser/index.jsx +1 -0
  23. package/src/@daf/core/components/Screens/Admin/AdminModals/CombineLocation/index.jsx +1 -1
  24. package/src/@daf/core/components/Screens/Admin/AdminModals/NewAccount/index.jsx +1 -1
  25. package/src/@daf/core/components/Screens/Admin/AdminScreens/Dashboard.jsx +2 -2
  26. package/src/@daf/core/components/Screens/Admin/AdminScreens/Location.jsx +5 -5
  27. package/src/@daf/core/components/Screens/Admin/AdminScreens/Subjects.jsx +2 -2
  28. package/src/@daf/core/components/Screens/Admin/AdminTables/LocationTable/index.jsx +5 -23
  29. package/src/@daf/core/components/Screens/Admin/AdminTables/SubjectsTable/columns.js +36 -36
  30. package/src/@daf/core/components/Screens/Admin/AdminTables/SubjectsTable/index.jsx +21 -12
  31. package/src/@daf/core/components/Screens/Admin/AdminViews/components/Users/helper.js +8 -13
  32. package/src/@daf/core/components/Screens/Admin/AdminViews/components/Users/index.jsx +2 -2
  33. package/src/@daf/core/components/Screens/Admin/adminRoutes.js +2 -2
  34. package/src/@daf/pages/Summary/Activities/Monitoring/components/ActivityImagery/index.jsx +29 -0
  35. package/src/@daf/pages/Summary/Activities/Monitoring/components/ActivityLocation/index.jsx +94 -0
  36. package/src/@daf/pages/Summary/Activities/Monitoring/components/MangroveGrowthAndSurvival/components/PlantedSpecies/index.jsx +56 -0
  37. package/src/@daf/pages/Summary/Activities/Monitoring/components/MangroveGrowthAndSurvival/components/SeedlingsHeight/index.jsx +121 -0
  38. package/src/@daf/pages/Summary/Activities/Monitoring/components/MangroveGrowthAndSurvival/components/SurvivalRate/index.jsx +94 -0
  39. package/src/@daf/pages/Summary/Activities/Monitoring/components/MangroveGrowthAndSurvival/index.jsx +54 -0
  40. package/src/@daf/pages/Summary/Activities/Monitoring/components/WorkersDistribution/index.jsx +49 -0
  41. package/src/@daf/pages/Summary/Activities/Monitoring/config.js +51 -0
  42. package/src/@daf/pages/Summary/Activities/Monitoring/helper.js +236 -0
  43. package/src/@daf/pages/Summary/Activities/Monitoring/index.jsx +66 -0
  44. package/src/@daf/pages/Summary/Minesite/components/StakeholderMapping/index.js +1 -1
  45. package/src/@daf/services/AdminService.js +3 -12
  46. package/src/@daf/services/DashboardService.js +1 -2
  47. package/src/@daf/utils/filters.js +89 -89
  48. package/src/constants/locales/en/translation.js +0 -3
  49. package/src/constants/locales/fr/translation.js +1 -1
  50. package/src/constants/locales/sp/translation.js +1 -1
  51. package/src/pages.js +1 -0
  52. package/src/@daf/core/components/Screens/Admin/AdminTables/LocationTable/column.js +0 -224
  53. package/src/@daf/core/components/Screens/Admin/AdminTables/LocationTable/helper.js +0 -65
  54. package/src/@daf/pages/SelfAssesment/components/AssociatedInformationTable/columns.js +0 -180
  55. package/src/@daf/pages/SelfAssesment/components/AssociatedInformationTable/config.js +0 -0
  56. package/src/@daf/pages/SelfAssesment/components/AssociatedInformationTable/index.jsx +0 -27
  57. package/src/@daf/pages/SelfAssesment/components/OrgInformationTable/columns.js +0 -157
  58. package/src/@daf/pages/SelfAssesment/components/OrgInformationTable/config.js +0 -31
  59. package/src/@daf/pages/SelfAssesment/components/OrgInformationTable/index.js +0 -77
  60. package/src/@daf/pages/SelfAssesment/components/ProductionSiteTable/columns.js +0 -117
  61. package/src/@daf/pages/SelfAssesment/components/ProductionSiteTable/index.jsx +0 -54
  62. package/src/@daf/pages/SelfAssesment/index.jsx +0 -0
@@ -2,7 +2,7 @@ import { useState, useMemo } from "react";
2
2
  import { useAdminTable } from "../hook";
3
3
  import AdminTable from "../components/index.jsx";
4
4
  import DAFTable from "../../../../Table/index.jsx";
5
- import { theme, Tag, message } from "antd";
5
+ import { theme, Tag } from "antd";
6
6
  import CustomIcon from "../../../../Icon/CustomIcon.jsx";
7
7
  import {
8
8
  getTabs,
@@ -67,7 +67,7 @@ export default function SubjectsTable({
67
67
  return {
68
68
  category: config.options?.category,
69
69
  country: config.options?.countries,
70
- sources: [],
70
+ sources: [], //TODO: add sources logic and make sure you only show unique sources only once
71
71
  };
72
72
  }, [config.options]);
73
73
 
@@ -113,15 +113,25 @@ export default function SubjectsTable({
113
113
  breadcrumbs={breadcrumbs}
114
114
  >
115
115
  {selectedSubjects.length > 0 && (
116
- <div className="flex flex-row ml-6 mt-5" style={{ flexWrap: "wrap", gap: "8px" }}>
116
+ <div
117
+ className="flex flex-row ml-6 mt-5"
118
+ style={{
119
+ flexWrap: "wrap",
120
+ gap: "8px",
121
+ }}
122
+ >
117
123
  {selectedSubjects.map((account) => (
118
124
  <Tag
119
125
  key={account.userId}
120
126
  className="flex flex-row gap-2 items-center"
121
127
  onClick={() =>
122
- setSelectedSubjects((prev) => prev.filter((a) => a.datastakeId !== account.datastakeId))
128
+ setSelectedSubjects((prev) =>
129
+ prev.filter((a) => a.datastakeId !== account.datastakeId),
130
+ )
123
131
  }
124
- style={{ cursor: "pointer" }}
132
+ style={{
133
+ cursor: "pointer",
134
+ }}
125
135
  >
126
136
  <span>{account.datastakeId}</span>
127
137
  <CustomIcon name="Close" size={10} />
@@ -150,20 +160,19 @@ export default function SubjectsTable({
150
160
  <CombineSubjectsModal
151
161
  isOpen={isCombineModalOpen}
152
162
  t={t}
153
- onClose={() => setIsModalOpen(false)}
163
+ onClose={() => {
164
+ setIsModalOpen(false);
165
+ }}
154
166
  onSuccess={(data) => {
155
167
  setIsModalOpen(false);
156
168
  setLoading(true);
157
- message.success(t("Subjects successfully merged."))
158
169
  if (typeof mergeSubjectsFunction === 'function') {
159
- mergeSubjectsFunction(data).finally(() => {
160
- setSelectedSubjects([]);
161
- fetchData();
162
- });
170
+ mergeSubjectsFunction(data);
171
+ setSelectedSubjects([])
163
172
  }
164
173
  }}
165
174
  selectedSubjects={selectedSubjects}
166
- selectOptions={selectOptions}
175
+ selectOptions={selectOptions || {}}
167
176
  module={module}
168
177
  entity={headerTitle}
169
178
  />
@@ -167,7 +167,10 @@ export const getColumns = ({
167
167
  return cols.filter((v) => v.show);
168
168
  };
169
169
 
170
- export const checkboxConfig = {};
170
+ export const checkboxConfig = {
171
+ name: "Name",
172
+ datastakeId: "ID",
173
+ };
171
174
 
172
175
  export const selectFiltersConfig = {
173
176
  userRole: {
@@ -191,17 +194,9 @@ export const selectFiltersConfig = {
191
194
  };
192
195
 
193
196
  export const filtersConfig = {
194
- search: "",
195
- };
196
-
197
- export const defaultUrlParams = {
198
- search: "",
199
- userRole: null,
200
- status: null,
197
+ name: "",
198
+ datastakeId: "",
201
199
  };
202
200
 
203
- export const defaultTableFilters = {
204
- search: "",
205
- userRole: null,
206
- status: null,
207
- };
201
+ export const defaultUrlParams = {};
202
+ export const defaultTableFilters = {};
@@ -60,10 +60,10 @@ export default function Users({
60
60
  userRole: userRoles.filter((u) => !u.isForAppAdmin),
61
61
  status: accountStatuses,
62
62
  };
63
- }, [userRoles, accountStatuses]);
63
+ }, [userRoles]);
64
64
 
65
65
  const canClearSearch = useMemo(() => {
66
- return !!activeFilters.search || !!activeFilters.userRole || !!activeFilters.status;
66
+ return !!activeFilters.search;
67
67
  }, [activeFilters]);
68
68
 
69
69
  const onDeleteUserClick = useCallback(
@@ -104,7 +104,7 @@ export function getAdminRoutes(config) {
104
104
  ...(typeof useAdminLocationConfig === "function"
105
105
  ? [
106
106
  {
107
- path: "management/subjects/location",
107
+ path: "subjects/location",
108
108
  key: `${APP_PREFIX}_ADMIN_SUBJECTS_LOCATIONS`,
109
109
  exact: true,
110
110
  visible: (user) => userIsAdmin(user),
@@ -115,7 +115,7 @@ export function getAdminRoutes(config) {
115
115
  ...(typeof useAdminSubjectsConfig === "function"
116
116
  ? [
117
117
  {
118
- path: "management/subjects/stakeholder",
118
+ path: "subjects/stakeholder",
119
119
  key: `${APP_PREFIX}_ADMIN_SUBJECTS_STAKEHOLDERS`,
120
120
  exact: true,
121
121
  visible: (user) => userIsAdmin(user),
@@ -0,0 +1,29 @@
1
+ import React, { useMemo } from 'react';
2
+ import { ImageCarousel } from '../../../../../../../../src/index.js';
3
+ import { getActivityImages } from '../../helper';
4
+ import { useResizeContext } from '../../../../../../../../src/context';
5
+
6
+ const ActivityImagery = ({
7
+ activityData,
8
+ loading = false,
9
+ t = (s) => s
10
+ }) => {
11
+ const { isCollapsed, isNestedSidebarCollapsed } = useResizeContext();
12
+ const images = useMemo(() => getActivityImages(activityData), [activityData]);
13
+
14
+ return (
15
+ <div style={{ maxWidth: "70%", width: "calc(100% - 405px)" }}>
16
+ <ImageCarousel
17
+ loading={loading}
18
+ images={images}
19
+ title={t("straatos::activity-imagery")}
20
+ key={`${isCollapsed}-${isNestedSidebarCollapsed}`}
21
+ customArrows={true}
22
+ activeDotColor="#003435"
23
+ />
24
+ </div>
25
+ );
26
+ };
27
+
28
+ export default ActivityImagery;
29
+
@@ -0,0 +1,94 @@
1
+ import React, { useMemo } from 'react';
2
+ import { Widget, MineSiteMap } from '../../../../../../../../src/index.js';
3
+ import { getMapDataFromActivity } from '../../helper';
4
+ import { convertDMS } from '../../../../../../../../src/helpers/Map';
5
+ import CustomIcon from '../../../../../../../../src/@daf/core/components/Icon/CustomIcon.jsx';
6
+
7
+ const ActivityLocation = ({
8
+ activityData,
9
+ loading = false,
10
+ t = (s) => s
11
+ }) => {
12
+ const mapData = useMemo(() => getMapDataFromActivity(activityData, t), [activityData, t]);
13
+
14
+ return (
15
+ <section>
16
+ <Widget
17
+ title={t("Activity Location")}
18
+ className="no-px h-w-btn-header no-pt-body no-p-body no-pb-body"
19
+ style={{ height: '100%', display: 'flex', flexDirection: 'column' }}
20
+ >
21
+ <div style={{ flex: 1, minHeight: 0 }}>
22
+ <MineSiteMap
23
+ loading={loading}
24
+ t={t}
25
+ isSatellite={true}
26
+ app={"straatos"}
27
+ type={'location-territory'}
28
+ showSider={false}
29
+ user={null}
30
+ data={mapData}
31
+ maxZoom={18}
32
+ primaryLink={true}
33
+ style={{ height: '100%', width: '100%' }}
34
+ renderTooltipForLocation={(data) => {
35
+ const coordinates = data.gps?.latitude && data.gps?.longitude
36
+ ? convertDMS(data.gps.latitude, data.gps.longitude)
37
+ : null;
38
+
39
+ if (!coordinates) {
40
+ return [];
41
+ }
42
+
43
+ const isActivityEnd = data.name === t("Activity End") || data.id?.includes('-departure');
44
+ const iconColor = isActivityEnd ? "#FF7A45" : "#016C6E";
45
+
46
+ return [
47
+ {
48
+ label: t("Coordinates"),
49
+
50
+ value: (
51
+ <div style={{ display: 'flex', alignItems: 'center', gap: '6px', flexWrap: 'nowrap' }}>
52
+ {/* Latitude icon (vertical) */}
53
+ <div style={{ display: 'flex', alignItems: 'center' }}>
54
+ <CustomIcon
55
+ name="SpacingHeight"
56
+ width={14}
57
+ height={14}
58
+ color={iconColor}
59
+ />
60
+ <span style={{ fontWeight: 600, marginLeft: '4px' }}>{coordinates[0]}</span>
61
+ </div>
62
+ {/* Longitude icon (horizontal) */}
63
+ <div style={{ display: 'flex', alignItems: 'center' }}>
64
+ <CustomIcon
65
+ name="SpacingWidth"
66
+ width={14}
67
+ height={14}
68
+ color={iconColor}
69
+ />
70
+ <span style={{ fontWeight: 600, marginLeft: '4px' }}>{coordinates[1]}</span>
71
+ </div>
72
+ </div>
73
+ ),
74
+ },
75
+ ];
76
+ }}
77
+ renderTooltipForTerritory={(data) => {
78
+ return [
79
+ {
80
+ label: t("Plot Name"),
81
+ value: data.plotName || data.name || "--",
82
+ },
83
+ ];
84
+ }}
85
+ link={true}
86
+ />
87
+ </div>
88
+ </Widget>
89
+ </section>
90
+ );
91
+ };
92
+
93
+ export default ActivityLocation;
94
+
@@ -0,0 +1,56 @@
1
+ import React, { useMemo } from 'react';
2
+ import { ActivityIndicators } from '../../../../../../../../../../src/index.js';
3
+
4
+ const PlantedSpecies = ({
5
+ activityData,
6
+ loading = false,
7
+ t = (s) => s
8
+ }) => {
9
+ const speciesConfig = useMemo(() => {
10
+ // Extract planted species from activityData
11
+ // Assuming the data structure might have plantedSpecies array or similar
12
+ const species = activityData?.plantedSpecies || activityData?.mangroveSpecies || [];
13
+
14
+ // If species is an array, map it to config format
15
+ if (Array.isArray(species)) {
16
+ return species.map((speciesItem, index) => {
17
+ const speciesName = typeof speciesItem === 'string'
18
+ ? speciesItem
19
+ : speciesItem?.name || speciesItem?.species || `Species ${index + 1}`;
20
+
21
+ // Determine if species is selected/planted (you may need to adjust this logic)
22
+ const isSelected = typeof speciesItem === 'object'
23
+ ? speciesItem?.selected !== false
24
+ : true;
25
+
26
+ return {
27
+ icon: 'Tree',
28
+ label: speciesName,
29
+ type: isSelected ? 'compliant' : 'notCompliant',
30
+ statusIcon: isSelected ? 'Check' : 'Close'
31
+ };
32
+ });
33
+ }
34
+
35
+ // Fallback: if no species data, show default species from image
36
+ return [
37
+ { icon: 'Tree', label: 'Rhyzophora sp', type: 'compliant', statusIcon: 'Check' },
38
+ { icon: 'Tree', label: 'Rhyzophora', type: 'notCompliant', statusIcon: 'Close' },
39
+ { icon: 'Tree', label: 'Rhyzophora mangle', type: 'notCompliant', statusIcon: 'Close' }
40
+ ];
41
+ }, [activityData]);
42
+
43
+ return (
44
+ <ActivityIndicators
45
+ title={t("Planted Species")}
46
+ config={speciesConfig}
47
+ loading={loading}
48
+ widgetClassName="h-w-btn-header"
49
+ t={t}
50
+ className="single-column"
51
+ />
52
+ );
53
+ };
54
+
55
+ export default PlantedSpecies;
56
+
@@ -0,0 +1,121 @@
1
+ import React, { useMemo } from 'react';
2
+ import { Widget, ColumnChart } from '../../../../../../../../../../src/index.js';
3
+
4
+ const SeedlingsHeight = ({
5
+ activityData,
6
+ loading = false,
7
+ t = (s) => s
8
+ }) => {
9
+ const heightData = useMemo(() => {
10
+ // Extract seedlings height from activityData
11
+ // Assuming the data might have averageHeight, seedlingsHeight, or similar
12
+ const averageHeight = activityData?.averageHeight ||
13
+ activityData?.seedlingsHeight ||
14
+ activityData?.mangroveAverageHeight ||
15
+ 28; // Default from image
16
+
17
+ const heightValue = typeof averageHeight === 'number'
18
+ ? averageHeight
19
+ : parseFloat(averageHeight) || 28;
20
+
21
+ return [
22
+ {
23
+ label: t("Average Height"),
24
+ value: heightValue
25
+ }
26
+ ];
27
+ }, [activityData, t]);
28
+
29
+ const renderTooltipContent = useMemo(() => {
30
+ return (title, data) => {
31
+ if (!data || data.length === 0) {
32
+ return {
33
+ title: t("Average Height"),
34
+ items: [
35
+ {
36
+ label: t("No Data"),
37
+ value: '-'
38
+ }
39
+ ]
40
+ };
41
+ }
42
+
43
+ const item = data[0];
44
+ const value = item?.value || item?.data?.value || 0;
45
+
46
+ return {
47
+ title: t("Average Height"),
48
+ items: [
49
+ {
50
+ label: t("Average Height"),
51
+ value: `${value.toFixed(1)}cm`,
52
+ color: '#00AEB1'
53
+ }
54
+ ]
55
+ };
56
+ };
57
+ }, [t]);
58
+
59
+ const isEmpty = useMemo(() => {
60
+ return !activityData?.averageHeight &&
61
+ !activityData?.seedlingsHeight &&
62
+ !activityData?.mangroveAverageHeight;
63
+ }, [activityData]);
64
+
65
+ return (
66
+ <Widget
67
+ loading={loading}
68
+ title={t("Seedlings Height")}
69
+ className="with-border-header h-w-btn-header"
70
+ >
71
+ <div
72
+ style={{
73
+ display: 'flex',
74
+ flexDirection: 'column',
75
+ minHeight: '250px',
76
+ padding: '20px 0'
77
+ }}
78
+ >
79
+ <ColumnChart
80
+ data={isEmpty ? [] : heightData}
81
+ xFieldKey="label"
82
+ yFieldKey="value"
83
+ color="#00AEB1"
84
+ height={250}
85
+ animated={true}
86
+ renderTooltipContent={renderTooltipContent}
87
+ yAxis={{
88
+ min: 0,
89
+ max: 35,
90
+ tickMethod: () => [0, 5, 10, 15, 20, 25, 30, 35],
91
+ label: {
92
+ formatter: (v) => `${v}cm`
93
+ }
94
+ }}
95
+ xAxis={{
96
+ label: {
97
+ formatter: () => ''
98
+ }
99
+ }}
100
+ tooltipConfig={{
101
+ showTitle: true
102
+ }}
103
+ />
104
+ {!isEmpty && (
105
+ <div style={{
106
+ marginTop: '16px',
107
+ textAlign: 'center',
108
+ fontSize: '14px',
109
+ color: '#475467',
110
+ fontWeight: 500
111
+ }}>
112
+ {t("Average Height")}: {heightData[0]?.value.toFixed(0)}cm
113
+ </div>
114
+ )}
115
+ </div>
116
+ </Widget>
117
+ );
118
+ };
119
+
120
+ export default SeedlingsHeight;
121
+
@@ -0,0 +1,94 @@
1
+ import React, { useMemo } from 'react';
2
+ import { Widget, DonutPie } from '../../../../../../../../../../src/index.js';
3
+
4
+ const SurvivalRate = ({
5
+ activityData,
6
+ loading = false,
7
+ t = (s) => s
8
+ }) => {
9
+ const survivalData = useMemo(() => {
10
+ // Extract survival rate from activityData
11
+ // Assuming the data might have survivalRate as a percentage (0-100)
12
+ const survivalRate = activityData?.survivalRate || activityData?.mangroveSurvivalRate || 78;
13
+ const survivalPercent = typeof survivalRate === 'number' ? survivalRate : parseFloat(survivalRate) || 78;
14
+
15
+ return [
16
+ {
17
+ type: t("Survival Rate"),
18
+ value: survivalPercent
19
+ },
20
+ {
21
+ type: t("Non-survival"),
22
+ value: 100 - survivalPercent
23
+ }
24
+ ];
25
+ }, [activityData, t]);
26
+
27
+ const renderTooltipContent = useMemo(() => {
28
+ return (title, data) => {
29
+ if (!data || data.length === 0) {
30
+ return {
31
+ title: t("Survival Rate"),
32
+ items: [
33
+ {
34
+ label: t("No Data"),
35
+ value: '-'
36
+ }
37
+ ]
38
+ };
39
+ }
40
+
41
+ const item = data[0];
42
+ const value = item?.value || item?.data?.value || 0;
43
+ const itemType = item?.type || item?.data?.type || t("Survival Rate");
44
+
45
+ // Determine color based on item type
46
+ const itemColor = itemType === t("Survival Rate") ? '#00AEB1' : '#E8EDF3';
47
+
48
+ return {
49
+ title: t("Survival Rate"),
50
+ items: [
51
+ {
52
+ label: itemType,
53
+ value: `${value.toFixed(1)}%`,
54
+ color: itemColor
55
+ }
56
+ ]
57
+ };
58
+ };
59
+ }, [t]);
60
+
61
+ const isEmpty = useMemo(() => {
62
+ return !activityData?.survivalRate && !activityData?.mangroveSurvivalRate;
63
+ }, [activityData]);
64
+
65
+ return (
66
+ <Widget
67
+ loading={loading}
68
+ title={t("Survival Rate")}
69
+ className="with-border-header h-w-btn-header"
70
+ >
71
+
72
+ {/* <DonutPie
73
+ angleField="value"
74
+ color={[
75
+ '#E8EDF3'
76
+ ]}
77
+ colorField="type"
78
+ data={[]}
79
+ height={200}
80
+ innerRadius={0.78}
81
+ radius={1}
82
+ renderTooltipContent={() => { }}
83
+ tooltip
84
+ tooltipConfig={{
85
+ showTitle: false
86
+ }}
87
+ /> */}
88
+
89
+ </Widget>
90
+ );
91
+ };
92
+
93
+ export default SurvivalRate;
94
+
@@ -0,0 +1,54 @@
1
+ import React from 'react';
2
+ import PlantedSpecies from './components/PlantedSpecies/index.jsx';
3
+ import SurvivalRate from './components/SurvivalRate/index.jsx';
4
+ import SeedlingsHeight from './components/SeedlingsHeight/index.jsx';
5
+ import styled from 'styled-components';
6
+ import { Widget } from '../../../../../../../../src/index.js';
7
+
8
+ const Container = styled.div`
9
+ display: grid;
10
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
11
+ gap: 24px;
12
+ width: 100%;
13
+
14
+ @media (max-width: 768px) {
15
+ grid-template-columns: 1fr;
16
+ }
17
+ `;
18
+
19
+ const MangroveGrowthAndSurvival = ({
20
+ activityData,
21
+ loading = false,
22
+ t = (s) => s
23
+ }) => {
24
+ return (
25
+
26
+ <Widget
27
+ title={t("Mangrove Growth & Survival")}
28
+ className="with-border-header h-w-btn-header"
29
+ >
30
+ <section>
31
+ <Container>
32
+ <PlantedSpecies
33
+ activityData={activityData}
34
+ loading={loading}
35
+ t={t}
36
+ />
37
+ <SurvivalRate
38
+ activityData={activityData}
39
+ loading={loading}
40
+ t={t}
41
+ />
42
+ <SeedlingsHeight
43
+ activityData={activityData}
44
+ loading={loading}
45
+ t={t}
46
+ />
47
+ </Container>
48
+ </section>
49
+ </Widget>
50
+ );
51
+ };
52
+
53
+ export default MangroveGrowthAndSurvival;
54
+
@@ -0,0 +1,49 @@
1
+ import React, { useMemo, useCallback } from 'react';
2
+ import { Widget, PieChart } from '../../../../../../../../src/index.js';
3
+ import { getGenderDistributionData, isGenderDistributionEmpty, calculateGenderPieData, getGenderTooltipChildren } from '../../helper';
4
+ import { renderTooltipJsx } from '../../../../../../../../src/utils';
5
+
6
+ const WorkersDistribution = ({
7
+ activityData,
8
+ loading = false,
9
+ t = (s) => s
10
+ }) => {
11
+ const genderDistributionData = useMemo(() => getGenderDistributionData(activityData), [activityData]);
12
+ const isEmpty = useMemo(() => isGenderDistributionEmpty(genderDistributionData), [genderDistributionData]);
13
+ const pieData = useMemo(() => calculateGenderPieData(genderDistributionData), [genderDistributionData]);
14
+
15
+ const getTooltipChildren = useCallback(
16
+ (item) => getGenderTooltipChildren(item, isEmpty, genderDistributionData, t, renderTooltipJsx),
17
+ [t, isEmpty, genderDistributionData],
18
+ );
19
+
20
+ return (
21
+ <Widget
22
+ loading={loading}
23
+ title={<div>{t("Workers Distribution")}</div>}
24
+ className="with-border-header h-w-btn-header "
25
+ >
26
+ <div
27
+ style={{
28
+ marginTop: "auto",
29
+ marginBottom: "auto",
30
+ }}
31
+ >
32
+ <PieChart
33
+ mouseXOffset={10}
34
+ mouseYOffset={10}
35
+ changeOpacityOnHover={false}
36
+ data={pieData}
37
+ doConstraints={false}
38
+ isPie
39
+ t={t}
40
+ isEmpty={isEmpty}
41
+ getTooltipChildren={getTooltipChildren}
42
+ />
43
+ </div>
44
+ </Widget>
45
+ );
46
+ };
47
+
48
+ export default WorkersDistribution;
49
+