datastake-daf 0.6.786 → 0.6.788

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 (22) hide show
  1. package/dist/components/index.js +226 -91
  2. package/dist/pages/index.js +774 -33
  3. package/dist/style/datastake/mapbox-gl.css +330 -0
  4. package/package.json +1 -1
  5. package/src/@daf/core/components/Dashboard/Widget/ActivityIndicators/ActivityIndicators.stories.js +24 -0
  6. package/src/@daf/core/components/Dashboard/Widget/ActivityIndicators/index.jsx +1 -0
  7. package/src/@daf/core/components/Dashboard/Widget/ActivityIndicators/style.js +34 -0
  8. package/src/@daf/core/components/Dashboard/Widget/KeyIndicators/KeyIndicators.stories.js +39 -0
  9. package/src/@daf/core/components/Dashboard/Widget/KeyIndicators/LabelWithIcon.jsx +38 -0
  10. package/src/@daf/core/components/Dashboard/Widget/KeyIndicators/index.jsx +16 -3
  11. package/src/@daf/core/components/Dashboard/Widget/KeyIndicators/style.js +33 -0
  12. package/src/@daf/pages/Summary/Activities/Monitoring/components/ActivityImagery/index.jsx +29 -0
  13. package/src/@daf/pages/Summary/Activities/Monitoring/components/ActivityLocation/index.jsx +94 -0
  14. package/src/@daf/pages/Summary/Activities/Monitoring/components/MangroveGrowthAndSurvival/components/PlantedSpecies/index.jsx +56 -0
  15. package/src/@daf/pages/Summary/Activities/Monitoring/components/MangroveGrowthAndSurvival/components/SeedlingsHeight/index.jsx +121 -0
  16. package/src/@daf/pages/Summary/Activities/Monitoring/components/MangroveGrowthAndSurvival/components/SurvivalRate/index.jsx +94 -0
  17. package/src/@daf/pages/Summary/Activities/Monitoring/components/MangroveGrowthAndSurvival/index.jsx +54 -0
  18. package/src/@daf/pages/Summary/Activities/Monitoring/components/WorkersDistribution/index.jsx +49 -0
  19. package/src/@daf/pages/Summary/Activities/Monitoring/config.js +51 -0
  20. package/src/@daf/pages/Summary/Activities/Monitoring/helper.js +236 -0
  21. package/src/@daf/pages/Summary/Activities/Monitoring/index.jsx +66 -0
  22. package/src/pages.js +1 -0
@@ -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
+
@@ -0,0 +1,51 @@
1
+ import React from "react";
2
+ import { camelCaseToTitle } from "../../../../../utils";
3
+
4
+
5
+
6
+ export const getKeyIndicatorsRowConfig = ({ t, data = {} }) => [
7
+
8
+ {
9
+ label: t('Primary Data Collection'),
10
+ render: () => {
11
+
12
+ return <div className="flex">{'-'}</div>;
13
+ }
14
+ },
15
+ {
16
+ label: t('Monitoring Organization'),
17
+ render: () => <div>{data?.technicalPartner?.name || '-'}</div>
18
+ },
19
+ {
20
+ label: t('Team Members'),
21
+ render: () => <div> {data?.teamMembers?.length || '0'}</div>
22
+ },
23
+ {
24
+ label: t('Monitored Area'),
25
+ render: () => <div>{data?.totalAreaParcelMonitored ? `${data?.totalAreaParcelMonitored} ha` : '0 ha'}</div>
26
+ },
27
+
28
+ ];
29
+
30
+ export const getSiteConditionsConfig = ({ t, data = {} }) => [
31
+ {
32
+ label: t('Season'),
33
+ icon: 'Tree',
34
+ render: () => <div>{camelCaseToTitle(data?.season)|| '-'}</div>
35
+ },
36
+ {
37
+ label: t('Weather conditions'),
38
+ icon: 'Globe',
39
+ render: () => <div>{ camelCaseToTitle(data?.weatherConditions )|| '-'}</div>
40
+ },
41
+ {
42
+ label: t('Tide level'),
43
+ icon: 'WaterDrop',
44
+ render: () => <div>{camelCaseToTitle(data?.tideLevel )|| '-'}</div>
45
+ },
46
+ {
47
+ label: t('Disturbances'),
48
+ icon: 'Lightning',
49
+ render: () => <div>{data?.hasDisturbances ? t('Yes') : t('No')}</div>
50
+ },
51
+ ];