datastake-daf 0.6.767 → 0.6.769

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 (79) hide show
  1. package/dist/components/index.js +1007 -730
  2. package/dist/layouts/index.js +495 -459
  3. package/dist/pages/index.js +7914 -6836
  4. package/dist/style/datastake/mapbox-gl.css +330 -0
  5. package/dist/utils/index.js +481 -457
  6. package/package.json +1 -1
  7. package/src/@daf/core/components/Charts/ColumnChart/index.jsx +10 -0
  8. package/src/@daf/core/components/Charts/LineChart/index.jsx +14 -0
  9. package/src/@daf/core/components/Dashboard/Map/ChainIcon/Markers/StakeholderMarker.js +5 -2
  10. package/src/@daf/core/components/Dashboard/Map/ChainIcon/index.js +67 -27
  11. package/src/@daf/core/components/Dashboard/Map/hook.js +26 -32
  12. package/src/@daf/core/components/Dashboard/Widget/ActivityIndicators/index.jsx +2 -0
  13. package/src/@daf/core/components/Dashboard/Widget/StatCard/StatCard.stories.js +226 -0
  14. package/src/@daf/core/components/Dashboard/Widget/StatCard/index.js +103 -0
  15. package/src/@daf/core/components/Dashboard/Widget/StatCard/style.js +83 -0
  16. package/src/@daf/core/components/Icon/configs/Down.js +8 -0
  17. package/src/@daf/core/components/Icon/configs/Up.js +8 -0
  18. package/src/@daf/core/components/Icon/configs/index.js +4 -0
  19. package/src/@daf/core/components/Icon/configs/partnerIcon.js +1 -1
  20. package/src/@daf/core/components/Screens/BaseScreen/index.jsx +1 -1
  21. package/src/@daf/core/components/Screens/TableScreen/TablePageWithTabs/index.jsx +1 -1
  22. package/src/@daf/core/components/Sidenav/Menu.jsx +4 -4
  23. package/src/@daf/core/components/UI/MissingTagButton/index.jsx +36 -0
  24. package/src/@daf/pages/Dashboards/SupplyChain/components/SupplyChainMap/index.js +0 -2
  25. package/src/@daf/pages/Documents/config.js +0 -10
  26. package/src/@daf/pages/Documents/index.jsx +51 -108
  27. package/src/@daf/pages/Events/Activities/config.js +1 -11
  28. package/src/@daf/pages/Events/Activities/index.jsx +47 -105
  29. package/src/@daf/pages/Events/Incidents/config.js +1 -11
  30. package/src/@daf/pages/Events/Incidents/index.jsx +47 -105
  31. package/src/@daf/pages/Events/config.js +18 -34
  32. package/src/@daf/pages/Events/index.jsx +49 -111
  33. package/src/@daf/pages/Locations/MineSite/config.js +0 -10
  34. package/src/@daf/pages/Locations/MineSite/index.jsx +47 -105
  35. package/src/@daf/pages/Locations/config.js +4 -16
  36. package/src/@daf/pages/Locations/index.jsx +53 -110
  37. package/src/@daf/pages/Stakeholders/Operators/config.js +0 -10
  38. package/src/@daf/pages/Stakeholders/Operators/index.jsx +47 -105
  39. package/src/@daf/pages/Stakeholders/Workers/config.js +0 -10
  40. package/src/@daf/pages/Stakeholders/Workers/index.jsx +47 -105
  41. package/src/@daf/pages/Stakeholders/config.js +3 -15
  42. package/src/@daf/pages/Stakeholders/index.jsx +53 -109
  43. package/src/@daf/pages/Summary/Activities/PlantingCycle/components/AssociatedInformation/index.jsx +43 -0
  44. package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CommunityParticipation/CommunityStats/helper.js +60 -0
  45. package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CommunityParticipation/CommunityStats/index.jsx +36 -0
  46. package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CommunityParticipation/GenderDistribution/helper.js +117 -0
  47. package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CommunityParticipation/GenderDistribution/index.jsx +49 -0
  48. package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CommunityParticipation/JobsTimeline/index.jsx +212 -0
  49. package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CommunityParticipation/index.jsx +72 -0
  50. package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CycleIndicators/CyclePartners/helper.js +91 -0
  51. package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CycleIndicators/CyclePartners/index.jsx +50 -0
  52. package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CycleIndicators/HealthAndSafety/helper.js +134 -0
  53. package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CycleIndicators/HealthAndSafety/index.jsx +49 -0
  54. package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CycleIndicators/index.jsx +112 -0
  55. package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CycleOutcomes/index.jsx +498 -0
  56. package/src/@daf/pages/Summary/Activities/PlantingCycle/components/KeyInformation/index.jsx +49 -0
  57. package/src/@daf/pages/Summary/Activities/PlantingCycle/components/PlantingLocations/index.jsx +120 -0
  58. package/src/@daf/pages/Summary/Activities/PlantingCycle/config.js +5 -10
  59. package/src/@daf/pages/Summary/Activities/PlantingCycle/helper.js +218 -0
  60. package/src/@daf/pages/Summary/Activities/PlantingCycle/index.jsx +22 -32
  61. package/src/@daf/pages/Summary/Activities/Restoration/components/ActivityImagery/index.jsx +29 -0
  62. package/src/@daf/pages/Summary/Activities/Restoration/components/ActivityLocation/index.jsx +94 -0
  63. package/src/@daf/pages/Summary/Activities/Restoration/components/WorkersDistribution/index.jsx +49 -0
  64. package/src/@daf/pages/Summary/Activities/Restoration/index.jsx +16 -138
  65. package/src/@daf/pages/TablePage/config.js +78 -0
  66. package/src/@daf/{core/components/Screens/TableScreen/TableWithTabsAndCreate → pages/TablePage}/create.jsx +6 -5
  67. package/src/@daf/pages/TablePage/hook.js +123 -0
  68. package/src/@daf/pages/TablePage/index.jsx +142 -0
  69. package/src/index.js +2 -0
  70. package/src/@daf/core/components/Screens/TableScreen/TableWithTabsAndCreate/index.jsx +0 -115
  71. package/src/@daf/pages/Documents/create.jsx +0 -105
  72. package/src/@daf/pages/Events/Activities/create.jsx +0 -104
  73. package/src/@daf/pages/Events/Incidents/create.jsx +0 -104
  74. package/src/@daf/pages/Events/create.jsx +0 -104
  75. package/src/@daf/pages/Locations/MineSite/create.jsx +0 -104
  76. package/src/@daf/pages/Locations/create.jsx +0 -104
  77. package/src/@daf/pages/Stakeholders/Operators/create.jsx +0 -104
  78. package/src/@daf/pages/Stakeholders/Workers/create.jsx +0 -104
  79. package/src/@daf/pages/Stakeholders/create.jsx +0 -105
@@ -0,0 +1,120 @@
1
+ import React, { useMemo } from 'react';
2
+ import { Widget, MineSiteMap } from '../../../../../../../../src/index.js';
3
+ import { useWidgetFetch } from '../../../../../../hooks/useWidgetFetch.js';
4
+
5
+ const PlantingLocations = ({
6
+ id,
7
+ getSummaryDetail,
8
+ loading = false,
9
+ t = (s) => s
10
+ }) => {
11
+ const defaultConfig = useMemo(
12
+ () => ({
13
+ basepath: "planting-cycle",
14
+ url: `/summary/${id}/locations`,
15
+ stop: !id,
16
+ }),
17
+ [id],
18
+ );
19
+
20
+ const customGetData = useMemo(() => {
21
+ if (getSummaryDetail && id) {
22
+ return ({ url, params = {} }) => {
23
+ const match = url.match(/\/summary\/[^/]+\/(.+)/);
24
+ if (match) {
25
+ const [, type] = match;
26
+ return getSummaryDetail(id, type, params);
27
+ }
28
+ throw new Error(`Invalid URL format: ${url}`);
29
+ };
30
+ }
31
+ return undefined;
32
+ }, [getSummaryDetail, id]);
33
+
34
+ const { loading: plantingLocationsLoading, data: plantingLocationsData } = useWidgetFetch({
35
+ config: defaultConfig,
36
+ getData: customGetData
37
+ });
38
+
39
+
40
+ const mappedData = useMemo(() => {
41
+ if (!plantingLocationsData || !plantingLocationsData.events) {
42
+ return [];
43
+ }
44
+
45
+ const { locations = [], events } = plantingLocationsData;
46
+
47
+ // Filter events that have valid GPS coordinates
48
+ const eventsWithGPS = events.filter(event =>
49
+ event.locationCheckArrival &&
50
+ event.locationCheckArrival.latitude &&
51
+ event.locationCheckArrival.longitude
52
+ );
53
+
54
+ return eventsWithGPS.map((event, index) => {
55
+ const locationCheckArrival = event.locationCheckArrival;
56
+
57
+ const matchingLocation = locations.find(location =>
58
+ locationCheckArrival.name === location.name ||
59
+ locationCheckArrival._id === location.id ||
60
+ location.id === locationCheckArrival._id
61
+ ) || locations[0];
62
+
63
+
64
+ const area = matchingLocation?.perimeter ? matchingLocation.perimeter.map(coord =>
65
+ Array.isArray(coord) && coord.length >= 2
66
+ ? [coord[1], coord[0]]
67
+ : coord
68
+ ) : [];
69
+
70
+
71
+ const gps = {
72
+ latitude: locationCheckArrival.latitude,
73
+ longitude: locationCheckArrival.longitude
74
+ };
75
+
76
+
77
+ const color = "#15FFFFB2"
78
+
79
+ return {
80
+ _id: locationCheckArrival._id || event._id || {},
81
+ area: area,
82
+ color: color,
83
+ datastakeId: `LOC-${String(index + 1).padStart(9, '0')}`,
84
+ gps: gps,
85
+ id: matchingLocation?.id || locationCheckArrival._id || `event-${index}`,
86
+ name: locationCheckArrival.name || matchingLocation?.name || `Event ${index + 1}`,
87
+ sources: 1,
88
+ subTitle: locationCheckArrival.name || matchingLocation?.name || 'Planting Location',
89
+ type: 'Planting Location'
90
+ };
91
+ });
92
+ }, [plantingLocationsData]);
93
+
94
+ return (
95
+ <section>
96
+ <Widget
97
+ title={t("Planting Locations")}
98
+ className="no-px h-w-btn-header no-pt-body no-p-body no-pb-body"
99
+ style={{ height: '100%', display: 'flex', flexDirection: 'column' }}
100
+ >
101
+ <MineSiteMap
102
+ data={mappedData}
103
+ link
104
+ style={{ height: '100%', width: '100%' }}
105
+ maxZoom={18}
106
+ isSatellite={true}
107
+ onClickLink={() => { }}
108
+ onFilterChange={() => { }}
109
+ primaryLink
110
+ renderTooltip={() => { }}
111
+ renderTooltipTags={() => { }}
112
+ type="location-territory"
113
+ />
114
+ </Widget>
115
+ </section>
116
+ );
117
+ };
118
+
119
+ export default PlantingLocations;
120
+
@@ -4,36 +4,31 @@ export const getKeyIndicatorsRowConfig = ({ t, data = {} }) => [
4
4
  {
5
5
  label: t('Region'),
6
6
  render: () => {
7
- // const region = data?.region;
8
- return <div>{ '-'}</div>;
7
+ return <div>{ data?.region || '-'}</div>;
9
8
  }
10
9
  },
11
10
  {
12
11
  label: t('Associated Plots'),
13
12
  render: () => {
14
- // const plotsCount = data?.associatedPlotsCount || '0';
15
- return <div>{'0'}</div>
13
+ return <div>{data?.associatedPlotsCount || '0'}</div>
16
14
  }
17
15
  },
18
16
  {
19
17
  label: t('Implementation Partners'),
20
18
  render: () => {
21
- // const partnersCount = data?.partnersCount || '0';
22
- return <div>{'0'}</div>
19
+ return <div>{data?.partnersCount || '0'}</div>
23
20
  }
24
21
  },
25
22
  {
26
23
  label: t('Total Activities'),
27
24
  render: () => {
28
- // const activitiesCount = data?.activitiesCount || '0';
29
- return <div>{'0'}</div>
25
+ return <div>{data?.activitiesCount || '0'}</div>
30
26
  }
31
27
  },
32
28
  {
33
29
  label: t('Information Sources'),
34
30
  render: () => {
35
- // const sourcesCount = data?.informationSourcesCount || '0';
36
- return <div>{'0'}</div>
31
+ return <div>{data?.informationSourcesCount || '0'}</div>
37
32
  }
38
33
  },
39
34
  ];
@@ -120,3 +120,221 @@ export const getMapDataFromActivity = (activityData, t) => {
120
120
  return mapData;
121
121
  };
122
122
 
123
+ const PARTNER_COLORS = ['#016C6E', '#00AEB1', '#FF7A45', '#52C41A', '#1890FF', '#722ED1', '#FA8C16', '#EB2F96'];
124
+
125
+ export const getPartnersDistributionData = (activityData) => {
126
+ // Handle object format: { "Partner 1": count1, "Partner 2": count2 }
127
+ if (activityData?.partnersDistribution && typeof activityData.partnersDistribution === 'object') {
128
+ return activityData.partnersDistribution;
129
+ }
130
+
131
+ if (Array.isArray(activityData?.partners)) {
132
+ const distribution = {};
133
+ activityData.partners.forEach(partner => {
134
+ const name = partner?.name || partner?.nickName || partner?.label || 'Unknown';
135
+ const count = partner?.count || partner?.value || 1;
136
+ distribution[name] = (distribution[name] || 0) + count;
137
+ });
138
+ return distribution;
139
+ }
140
+
141
+ // Default empty object
142
+ return {};
143
+ };
144
+
145
+ export const isPartnersDistributionEmpty = (partnersDistributionData) => {
146
+ return Object.values(partnersDistributionData).every(val => !val || val === 0);
147
+ };
148
+
149
+ export const calculatePartnersPieData = (partnersDistributionData) => {
150
+ const total = Object.values(partnersDistributionData).reduce((all, val) => all + (val || 0), 0);
151
+
152
+ return Object.keys(partnersDistributionData).map((key, index) => {
153
+ const color = PARTNER_COLORS[index % PARTNER_COLORS.length];
154
+
155
+ return {
156
+ value: partnersDistributionData[key] || 0,
157
+ percent: total > 0 ? (partnersDistributionData[key] || 0) / total : 0,
158
+ color: color,
159
+ label: key,
160
+ key: key,
161
+ };
162
+ });
163
+ };
164
+
165
+ export const getPartnersTooltipChildren = (item, isEmpty, partnersDistributionData, t, renderTooltipJsx) => {
166
+ if (isEmpty) {
167
+ if (!Object.keys(partnersDistributionData).length) {
168
+ return null;
169
+ }
170
+
171
+ return renderTooltipJsx({
172
+ title: t("Partners"),
173
+ items: Object.keys(partnersDistributionData).map((k) => ({
174
+ label: k,
175
+ value: 0,
176
+ })),
177
+ });
178
+ }
179
+
180
+ return renderTooltipJsx({
181
+ title: t("Partners"),
182
+ items: [
183
+ {
184
+ color: item.color,
185
+ label: item.label,
186
+ value: `${item.value || 0}`,
187
+ },
188
+ ],
189
+ });
190
+ };
191
+
192
+ const HEALTH_SAFETY_COLORS = {
193
+ compliant: '#52C41A',
194
+ notCompliant: '#FF4D4F',
195
+ empty: '#D9D9D9',
196
+ };
197
+
198
+ const getIndicatorType = (value) => {
199
+ if (value === "yes" || value === true) return "compliant";
200
+ if (value === "no" || value === false) return "notCompliant";
201
+ if (value === null || value === undefined) return "empty";
202
+ return "empty";
203
+ };
204
+
205
+ export const getHealthAndSafetyDistributionData = (activityData) => {
206
+ // Define health and safety indicator fields
207
+ const indicators = [
208
+ { field: 'aidKitAccessible', label: 'Aid kit availability' },
209
+ { field: 'hsTrainingConfirmation', label: 'H&S training delivery' },
210
+ { field: 'duosFormed', label: 'Workers safe pairing' },
211
+ { field: 'presenceOfChildren', label: 'No children' },
212
+ { field: 'focalPointPresent', label: 'Security presence' },
213
+ { field: 'relayPresent', label: 'Relay presence' },
214
+ ];
215
+
216
+ const distribution = {
217
+ compliant: 0,
218
+ notCompliant: 0,
219
+ empty: 0,
220
+ };
221
+
222
+ indicators.forEach(({ field }) => {
223
+ const value = activityData?.[field];
224
+ const type = getIndicatorType(value);
225
+ distribution[type] = (distribution[type] || 0) + 1;
226
+ });
227
+
228
+ return distribution;
229
+ };
230
+
231
+ export const isHealthAndSafetyDistributionEmpty = (healthAndSafetyDistributionData) => {
232
+ return Object.values(healthAndSafetyDistributionData).every(val => !val || val === 0);
233
+ };
234
+
235
+ export const calculateHealthAndSafetyPieData = (healthAndSafetyDistributionData, t) => {
236
+ const total = Object.values(healthAndSafetyDistributionData).reduce((all, val) => all + (val || 0), 0);
237
+
238
+ const labels = {
239
+ compliant: t("Compliant"),
240
+ notCompliant: t("Not Compliant"),
241
+ empty: t("Not Set"),
242
+ };
243
+
244
+ return Object.keys(healthAndSafetyDistributionData).map((key) => {
245
+ const color = HEALTH_SAFETY_COLORS[key] || '#D9D9D9';
246
+
247
+ return {
248
+ value: healthAndSafetyDistributionData[key] || 0,
249
+ percent: total > 0 ? (healthAndSafetyDistributionData[key] || 0) / total : 0,
250
+ color: color,
251
+ label: labels[key] || key,
252
+ key: key,
253
+ };
254
+ });
255
+ };
256
+
257
+ export const getHealthAndSafetyTooltipChildren = (item, isEmpty, healthAndSafetyDistributionData, t, renderTooltipJsx) => {
258
+ if (isEmpty) {
259
+ if (!Object.keys(healthAndSafetyDistributionData).length) {
260
+ return null;
261
+ }
262
+
263
+ return renderTooltipJsx({
264
+ title: t("Health and Safety"),
265
+ items: Object.keys(healthAndSafetyDistributionData).map((k) => ({
266
+ label: k === 'compliant' ? t("Compliant") : k === 'notCompliant' ? t("Not Compliant") : t("Not Set"),
267
+ value: 0,
268
+ })),
269
+ });
270
+ }
271
+
272
+ return renderTooltipJsx({
273
+ title: t("Health and Safety"),
274
+ items: [
275
+ {
276
+ color: item.color,
277
+ label: item.label,
278
+ value: `${item.value || 0}`,
279
+ },
280
+ ],
281
+ });
282
+ };
283
+
284
+ /**
285
+ * Calculates stat change object for StatCard component based on current and previous values
286
+ * @param {Object} data - Object with current and previous values
287
+ * @param {number} data.current - Current value
288
+ * @param {number} data.previous - Previous value
289
+ * @param {Object} options - Optional configuration
290
+ * @param {string} options.tooltipText - Custom tooltip text
291
+ * @param {string} options.format - Format type: 'percentage' (default) or 'absolute'
292
+ * @param {number} options.decimalPlaces - Number of decimal places for percentage (default: 1)
293
+ * @returns {Object|null} Change object for StatCard or null if data is invalid
294
+ */
295
+ export const calculateStatChange = (data, options = {}) => {
296
+ if (!data || typeof data !== 'object') {
297
+ return null;
298
+ }
299
+
300
+ const { current, previous } = data;
301
+
302
+ // Validate that both values are numbers
303
+ if (typeof current !== 'number' || typeof previous !== 'number') {
304
+ return null;
305
+ }
306
+
307
+ // If previous is 0, we can't calculate percentage change
308
+ if (previous === 0) {
309
+ return null;
310
+ }
311
+
312
+ const {
313
+ tooltipText,
314
+ format = 'percentage',
315
+ decimalPlaces = 1,
316
+ } = options;
317
+
318
+ // Calculate the difference
319
+ const difference = current - previous;
320
+ const isPositive = difference >= 0;
321
+ const direction = isPositive ? 'up' : 'down';
322
+
323
+ // Format the value
324
+ let value;
325
+ if (format === 'absolute') {
326
+ // Show absolute difference
327
+ value = Math.abs(difference).toLocaleString();
328
+ } else {
329
+ // Show percentage change
330
+ const percentageChange = (Math.abs(difference) / previous) * 100;
331
+ value = `${percentageChange.toFixed(decimalPlaces)}%`;
332
+ }
333
+
334
+ return {
335
+ value,
336
+ direction,
337
+ tooltipText: tooltipText || undefined,
338
+ };
339
+ };
340
+
@@ -1,44 +1,34 @@
1
- import { useMemo } from 'react';
2
- import { DashboardLayout, Header, KeyIndicators, MineSiteMap, Widget } from '../../../../../../src/index.js'
3
- import { getKeyIndicatorsRowConfig } from './config';
1
+ import { DashboardLayout, Header } from '../../../../../../src/index.js'
2
+ import PlantingLocations from './components/PlantingLocations/index.jsx';
3
+ import CycleOutcomes from './components/CycleOutcomes/index.jsx';
4
+ import CycleIndicators from './components/CycleIndicators/index.jsx';
5
+ import CommunityParticipation from './components/CommunityParticipation/index.jsx';
6
+ import AssociatedInformation from './components/AssociatedInformation/index.jsx';
7
+ import KeyInformation from './components/KeyInformation/index.jsx';
4
8
 
5
- const PlantingCycleSummary = ({ activityData, supportText, onDownload, downloadDisabled, actionButtons, breadcrumbs, goBackTo, loading, t = () => { } }) => {
6
- const keyIndicatorsConfig = useMemo(() => getKeyIndicatorsRowConfig({ t, data: {} }), [t]);
9
+ const PlantingCycleSummary = ({ header, activityData, loading = false, id, t = () => { }, getSummaryDetail }) => {
7
10
 
8
11
  return (
9
12
  <DashboardLayout
10
13
  header={
11
14
  <Header
12
- title={'Planting Cycle Summary'}
13
- supportText={supportText || ''}
14
- onDownload={onDownload}
15
- downloadDisabled={downloadDisabled}
16
- actionButtons={actionButtons}
17
- breadcrumbs={breadcrumbs}
18
- goBackTo={goBackTo}
19
- loading={loading}
15
+ title={header?.title || ''}
16
+ supportText={header?.supportText || ''}
17
+ onDownload={header?.onDownload}
18
+ downloadDisabled={header?.downloadDisabled}
19
+ actionButtons={header?.actionButtons}
20
+ breadcrumbs={header?.breadcrumbs}
21
+ goBackTo={header?.goBackTo}
22
+ loading={header?.loading}
20
23
  />
21
24
  }
22
25
  >
23
- <section>
24
- <KeyIndicators title={t("Key Information")} config={keyIndicatorsConfig} loading={loading} />
25
- </section>
26
-
27
- <section>
28
- <Widget
29
- title={t("Planting Locations")}
30
- className="no-px h-w-btn-header no-pt-body no-p-body no-pb-body"
31
- style={{ height: '100%', display: 'flex', flexDirection: 'column' }}
32
- >
33
- <MineSiteMap
34
- loading={loading}
35
- t={t}
36
- isSatellite
37
- data={[]}
38
- />
39
- </Widget>
40
-
41
- </section>
26
+ <KeyInformation id={id} t={t} getSummaryDetail={getSummaryDetail} loading={loading} />
27
+ <PlantingLocations id={id} getSummaryDetail={getSummaryDetail} loading={loading} t={t} />
28
+ <CycleOutcomes id={id} getSummaryDetail={getSummaryDetail} loading={loading} t={t} />
29
+ <CycleIndicators id={id} getSummaryDetail={getSummaryDetail} loading={loading} t={t} />
30
+ <CommunityParticipation id={id} getSummaryDetail={getSummaryDetail} loading={loading} t={t} />
31
+ <AssociatedInformation id={id} getSummaryDetail={getSummaryDetail} loading={loading} t={t} />
42
32
  </DashboardLayout>
43
33
  )
44
34
  }
@@ -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,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
+