datastake-daf 0.6.826 → 0.6.827

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.
@@ -1,3 +1,28 @@
1
+
2
+ // Custom tooltip labels per field/value
3
+ const FIELD_TOOLTIP_LABELS = {
4
+ aidKitAccessible: {
5
+ compliant: "Available",
6
+ notCompliant: "Not available",
7
+ empty: "No data",
8
+ },
9
+ hsTrainingConfirmation: {
10
+ compliant: "Training delivered",
11
+ notCompliant: "No training",
12
+ empty: "No data",
13
+ },
14
+ duosFormed: {
15
+ compliant: "Duos formed",
16
+ notCompliant: "Not implemented",
17
+ empty: "No data",
18
+ },
19
+ presenceOfChildren: {
20
+ compliant: "None reported",
21
+ notCompliant: "Children present",
22
+ empty: "No data",
23
+ },
24
+ };
25
+
1
26
  const HEALTH_SAFETY_COLORS = {
2
27
  compliant: '#016C6E',
3
28
  notCompliant: '#F97066',
@@ -11,11 +36,6 @@ const getIndicatorType = (value) => {
11
36
  return "empty";
12
37
  };
13
38
 
14
- /**
15
- * Gets health and safety distribution data from activity data
16
- * @param {Object} activityData - Activity data object
17
- * @returns {Object} Distribution object with compliant, notCompliant, and empty counts
18
- */
19
39
  export const getHealthAndSafetyDistributionData = (activityData) => {
20
40
  // Define health and safety indicator fields
21
41
  const indicators = [
@@ -42,23 +62,12 @@ export const getHealthAndSafetyDistributionData = (activityData) => {
42
62
  return distribution;
43
63
  };
44
64
 
45
- /**
46
- * Checks if the health and safety distribution data is empty
47
- * @param {Object} healthAndSafetyDistributionData - Distribution object
48
- * @returns {boolean} True if all values are 0 or empty
49
- */
50
65
  export const isHealthAndSafetyDistributionEmpty = (healthAndSafetyDistributionData) => {
51
66
  return Object.values(healthAndSafetyDistributionData).every(val => !val || val === 0);
52
67
  };
53
68
 
54
- /**
55
- * Calculates pie chart data from health and safety distribution
56
- * @param {Object} healthAndSafetyDistributionData - Distribution object
57
- * @param {Function} t - Translation function
58
- * @returns {Array} Array of pie chart data points with value, percent, color, label, and key
59
- */
60
- export const calculateHealthAndSafetyPieData = (healthAndSafetyDistributionData, t) => {
61
- const total = Object.values(healthAndSafetyDistributionData).reduce((all, val) => all + (val || 0), 0);
69
+ export const calculateHealthAndSafetyPieData = (data, t, selectedField) => {
70
+ const total = Object.values(data).reduce((a, v) => a + (v || 0), 0);
62
71
 
63
72
  const labels = {
64
73
  compliant: t("Available"),
@@ -66,31 +75,27 @@ export const calculateHealthAndSafetyPieData = (healthAndSafetyDistributionData,
66
75
  empty: t("Not answered"),
67
76
  };
68
77
 
69
- return Object.keys(healthAndSafetyDistributionData).map((key) => {
70
- const color = HEALTH_SAFETY_COLORS[key] || '#D9D9D9';
71
-
72
- return {
73
- value: healthAndSafetyDistributionData[key] || 0,
74
- percent: total > 0 ? (healthAndSafetyDistributionData[key] || 0) / total : 0,
75
- color: color,
76
- label: labels[key] || key,
77
- key: key,
78
- };
79
- });
78
+ return Object.keys(data).map((key) => ({
79
+ value: data[key] || 0,
80
+ percent: total > 0 ? (data[key] || 0) / total : 0,
81
+ color: HEALTH_SAFETY_COLORS[key] || '#D9D9D9',
82
+ label: labels[key] || key,
83
+ key,
84
+ keyOfField: selectedField, // <-- ADD THIS
85
+ }));
80
86
  };
81
87
 
82
- /**
83
- * Generates tooltip content for health and safety pie chart
84
- * Shows all statuses with their percentages
85
- * @param {Object} item - The pie chart item being hovered (not used, but kept for compatibility)
86
- * @param {boolean} isEmpty - Whether the distribution is empty
87
- * @param {Object} healthAndSafetyDistributionData - Distribution object
88
- * @param {Function} t - Translation function
89
- * @param {Function} renderTooltipJsx - Function to render tooltip JSX
90
- * @param {string} tooltipTitle - Title to display in the tooltip (defaults to "Health and Safety")
91
- * @returns {JSX.Element|null} Tooltip content or null
92
- */
93
- export const getHealthAndSafetyTooltipChildren = (item, isEmpty, healthAndSafetyDistributionData, t, renderTooltipJsx, tooltipTitle = "Health and Safety") => {
88
+
89
+ export const getHealthAndSafetyTooltipChildren = (
90
+ item,
91
+ isEmpty,
92
+ healthAndSafetyDistributionData,
93
+ t,
94
+ renderTooltipJsx,
95
+ tooltipTitle = "Health and Safety",
96
+ selectedField
97
+ ) => {
98
+
94
99
  // If empty or no data, return null to display nothing
95
100
  if (isEmpty || !Object.keys(healthAndSafetyDistributionData).length) {
96
101
  return null;
@@ -104,10 +109,10 @@ export const getHealthAndSafetyTooltipChildren = (item, isEmpty, healthAndSafety
104
109
  return null;
105
110
  }
106
111
 
107
- const labels = {
112
+ const labels = FIELD_TOOLTIP_LABELS[item?.keyOfField] || {
108
113
  compliant: t("Available"),
109
114
  notCompliant: t("Not available"),
110
- empty: t("Not answered"),
115
+ empty: t("No data"),
111
116
  };
112
117
 
113
118
  // Filter items with values > 0
@@ -54,7 +54,6 @@ const HealthAndSafety = ({
54
54
  getData: customGetData
55
55
  });
56
56
 
57
- // Process the fetched pie chart data
58
57
  // The API returns data in format: [{count: 1, [field]: "null"}, {count: 1, [field]: "no"}, {count: 1, [field]: "yes"}]
59
58
  const healthAndSafetyDistributionData = useMemo(() => {
60
59
  if (!pieChartData) return { compliant: 0, notCompliant: 0, empty: 0 };
@@ -90,7 +89,10 @@ const HealthAndSafety = ({
90
89
  }, [pieChartData, selectedField]);
91
90
 
92
91
  const isEmpty = useMemo(() => isHealthAndSafetyDistributionEmpty(healthAndSafetyDistributionData), [healthAndSafetyDistributionData]);
93
- const pieData = useMemo(() => calculateHealthAndSafetyPieData(healthAndSafetyDistributionData, t), [healthAndSafetyDistributionData, t]);
92
+ const pieData = useMemo(() =>
93
+ calculateHealthAndSafetyPieData(healthAndSafetyDistributionData, t, selectedField),
94
+ [healthAndSafetyDistributionData, t, selectedField]);
95
+
94
96
 
95
97
  // Get the label for the selected field to use as tooltip title
96
98
  const selectedFieldLabel = useMemo(() => {
@@ -99,7 +101,16 @@ const HealthAndSafety = ({
99
101
  }, [selectedField]);
100
102
 
101
103
  const getTooltipChildren = useCallback(
102
- (item) => getHealthAndSafetyTooltipChildren(item, isEmpty, healthAndSafetyDistributionData, t, renderTooltipJsx, selectedFieldLabel),
104
+ (item) =>
105
+ getHealthAndSafetyTooltipChildren(
106
+ item,
107
+ isEmpty,
108
+ healthAndSafetyDistributionData,
109
+ t,
110
+ renderTooltipJsx,
111
+ selectedFieldLabel,
112
+ selectedField
113
+ ),
103
114
  [t, isEmpty, healthAndSafetyDistributionData, selectedFieldLabel],
104
115
  );
105
116
 
@@ -110,8 +121,9 @@ const HealthAndSafety = ({
110
121
  return (
111
122
  <Widget
112
123
  loading={loading || pieChartLoading}
113
- title={<div>{t("Health and Safety")}</div>}
114
- className="with-border-header h-w-btn-header "
124
+ title={<div>{t("Operational Health & Safety")}</div>}
125
+ className="with-border-header h-w-btn-header"
126
+ description={t("Across all activities in this cycle.")}
115
127
  addedHeader={
116
128
  <>
117
129
  <div className="flex-1" />
@@ -15,21 +15,28 @@ const PlantingActivitiesTimeline = ({
15
15
  }) => {
16
16
  const { timeFilter, setTimeFilter, formatDateAxis, processChartDateData } = useTimeFilter({ defaultFilter: 'monthly' });
17
17
 
18
-
18
+
19
19
  const activitiesTimelineData = useMemo(() => {
20
20
  const dataToProcess = (!activitiesTimelineChart || !Array.isArray(activitiesTimelineChart) || activitiesTimelineChart.length === 0)
21
21
  ? []
22
22
  : activitiesTimelineChart;
23
-
23
+
24
24
  // Process data without cumulative calculation (for activities timeline)
25
- return processChartDateData({
25
+ const processedData = processChartDateData({
26
26
  mainData: dataToProcess,
27
27
  isCumulative: false,
28
28
  valueField: 'count',
29
29
  });
30
+
31
+ // Remove trailing periods with 0 jobs (optional: remove all zero if you prefer)
32
+ let lastNonZeroIndex = processedData.length - 1;
33
+ while (lastNonZeroIndex >= 0 && (processedData[lastNonZeroIndex].jobs || 0) === 0) {
34
+ lastNonZeroIndex--;
35
+ }
36
+
37
+ return processedData.slice(0, lastNonZeroIndex + 1);
30
38
  }, [activitiesTimelineChart, processChartDateData]);
31
-
32
- // Calculate max value for Y-axis (default to 100 if all values are 0 or very small)
39
+
33
40
  const maxActivitiesYValue = useMemo(() => {
34
41
  if (!activitiesTimelineData || activitiesTimelineData.length === 0) {
35
42
  return 100;