datastake-daf 0.6.776 → 0.6.777

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.
@@ -5322,7 +5322,7 @@ const getMetaPlaceholer = (inputMeta, t) => inputMeta.notApplicable ? t("Not app
5322
5322
  * @param {string} [filterCond=null] - Filter condition.
5323
5323
  * @returns {Object[]} - Filtered options.
5324
5324
  */
5325
- function filterOptions(options, filters, formsValue = {}, repeatValues = {}, filterCond = null) {
5325
+ function filterOptions$1(options, filters, formsValue = {}, repeatValues = {}, filterCond = null) {
5326
5326
  const isOrCond = filterCond !== "and";
5327
5327
  const objFilter = {};
5328
5328
  filters.forEach(f => {
@@ -27265,7 +27265,7 @@ const inputTypeComponent = {
27265
27265
  opts = JSON.parse(JSON.stringify(opts));
27266
27266
  opts = opts.map(o => getSelectOptions(o, formsValue));
27267
27267
  if (optionsFilter && Array.isArray(optionsFilter)) {
27268
- opts = filterOptions(opts, optionsFilter, formsValue, repeatValues, filterCond);
27268
+ opts = filterOptions$1(opts, optionsFilter, formsValue, repeatValues, filterCond);
27269
27269
  }
27270
27270
  if (propHasValue(value)) {
27271
27271
  const selectOption = opts.find(o => o.value === value);
@@ -27384,7 +27384,7 @@ const inputTypeComponent = {
27384
27384
  opts = JSON.parse(JSON.stringify(opts));
27385
27385
  opts = opts.map(o => getSelectOptions(o, formsValue));
27386
27386
  if (optionsFilter && Array.isArray(optionsFilter)) {
27387
- opts = filterOptions(opts, optionsFilter, formsValue, repeatValues, filterCond);
27387
+ opts = filterOptions$1(opts, optionsFilter, formsValue, repeatValues, filterCond);
27388
27388
  }
27389
27389
  if (propHasValue(value) && Array.isArray(value) && value.length > 0 && !tags) {
27390
27390
  try {
@@ -43746,9 +43746,10 @@ const calculateHealthAndSafetyPieData = (healthAndSafetyDistributionData, t) =>
43746
43746
  * @param {Object} healthAndSafetyDistributionData - Distribution object
43747
43747
  * @param {Function} t - Translation function
43748
43748
  * @param {Function} renderTooltipJsx - Function to render tooltip JSX
43749
+ * @param {string} tooltipTitle - Title to display in the tooltip (defaults to "Health and Safety")
43749
43750
  * @returns {JSX.Element|null} Tooltip content or null
43750
43751
  */
43751
- const getHealthAndSafetyTooltipChildren = (item, isEmpty, healthAndSafetyDistributionData, t, renderTooltipJsx) => {
43752
+ const getHealthAndSafetyTooltipChildren = (item, isEmpty, healthAndSafetyDistributionData, t, renderTooltipJsx, tooltipTitle = "Health and Safety") => {
43752
43753
  // If empty or no data, return null to display nothing
43753
43754
  if (isEmpty || !Object.keys(healthAndSafetyDistributionData).length) {
43754
43755
  return null;
@@ -43785,25 +43786,39 @@ const getHealthAndSafetyTooltipChildren = (item, isEmpty, healthAndSafetyDistrib
43785
43786
 
43786
43787
  // Show all items with their percentages
43787
43788
  return renderTooltipJsx({
43788
- title: t("Health and Safety"),
43789
+ title: t(tooltipTitle),
43789
43790
  items: itemsWithData
43790
43791
  });
43791
43792
  };
43792
43793
 
43794
+ const filterOptions = [{
43795
+ value: 'aidKitAccessible',
43796
+ label: 'Aid kit availability'
43797
+ }, {
43798
+ value: 'hsTrainingConfirmation',
43799
+ label: 'H&S training delivery'
43800
+ }, {
43801
+ value: 'duosFormed',
43802
+ label: 'Workers safe pairing'
43803
+ }, {
43804
+ value: 'presenceOfChildren',
43805
+ label: 'No children'
43806
+ }];
43793
43807
  const HealthAndSafety = ({
43794
43808
  id,
43795
43809
  getSummaryDetail,
43796
43810
  loading = false,
43797
43811
  t = s => s
43798
43812
  }) => {
43813
+ const [selectedField, setSelectedField] = React.useState('aidKitAccessible');
43799
43814
  const defaultConfig = React.useMemo(() => ({
43800
43815
  basepath: "planting-cycle",
43801
43816
  url: `/summary/${id}/filtered-piechart`,
43802
43817
  filters: {
43803
- field: 'duosFormed'
43818
+ field: selectedField
43804
43819
  },
43805
43820
  stop: !id
43806
- }), [id]);
43821
+ }), [id, selectedField]);
43807
43822
  const customGetData = React.useMemo(() => {
43808
43823
  if (getSummaryDetail && id) {
43809
43824
  return rest => {
@@ -43834,7 +43849,7 @@ const HealthAndSafety = ({
43834
43849
  });
43835
43850
 
43836
43851
  // Process the fetched pie chart data
43837
- // The API returns data in format: [{count: 1, duosFormed: "null"}, {count: 1, duosFormed: "no"}, {count: 1, duosFormed: "yes"}]
43852
+ // The API returns data in format: [{count: 1, [field]: "null"}, {count: 1, [field]: "no"}, {count: 1, [field]: "yes"}]
43838
43853
  const healthAndSafetyDistributionData = React.useMemo(() => {
43839
43854
  if (!pieChartData) return {
43840
43855
  compliant: 0,
@@ -43847,7 +43862,7 @@ const HealthAndSafety = ({
43847
43862
  return pieChartData;
43848
43863
  }
43849
43864
 
43850
- // If it's an array, process it
43865
+ // If it's an array, process it using the selected field
43851
43866
  if (Array.isArray(pieChartData)) {
43852
43867
  const distribution = {
43853
43868
  compliant: 0,
@@ -43855,15 +43870,15 @@ const HealthAndSafety = ({
43855
43870
  empty: 0
43856
43871
  };
43857
43872
  pieChartData.forEach(item => {
43858
- const duosFormedValue = item.duosFormed;
43873
+ const fieldValue = item[selectedField];
43859
43874
  const count = item.count || 0;
43860
43875
 
43861
- // Map duosFormed values to distribution categories
43862
- if (duosFormedValue === "yes" || duosFormedValue === true) {
43876
+ // Map field values to distribution categories
43877
+ if (fieldValue === "yes" || fieldValue === true) {
43863
43878
  distribution.compliant += count;
43864
- } else if (duosFormedValue === "no" || duosFormedValue === false) {
43879
+ } else if (fieldValue === "no" || fieldValue === false) {
43865
43880
  distribution.notCompliant += count;
43866
- } else if (duosFormedValue === "null" || duosFormedValue === null || duosFormedValue === undefined) {
43881
+ } else if (fieldValue === "null" || fieldValue === null || fieldValue === undefined) {
43867
43882
  distribution.empty += count;
43868
43883
  }
43869
43884
  });
@@ -43872,16 +43887,41 @@ const HealthAndSafety = ({
43872
43887
 
43873
43888
  // Fallback: try to extract from activityData-like structure
43874
43889
  return getHealthAndSafetyDistributionData(pieChartData);
43875
- }, [pieChartData]);
43890
+ }, [pieChartData, selectedField]);
43876
43891
  const isEmpty = React.useMemo(() => isHealthAndSafetyDistributionEmpty(healthAndSafetyDistributionData), [healthAndSafetyDistributionData]);
43877
43892
  const pieData = React.useMemo(() => calculateHealthAndSafetyPieData(healthAndSafetyDistributionData, t), [healthAndSafetyDistributionData, t]);
43878
- const getTooltipChildren = React.useCallback(item => getHealthAndSafetyTooltipChildren(item, isEmpty, healthAndSafetyDistributionData, t, renderTooltipJsx), [t, isEmpty, healthAndSafetyDistributionData]);
43893
+
43894
+ // Get the label for the selected field to use as tooltip title
43895
+ const selectedFieldLabel = React.useMemo(() => {
43896
+ const selectedOption = filterOptions.find(opt => opt.value === selectedField);
43897
+ return selectedOption ? selectedOption.label : 'Health and Safety';
43898
+ }, [selectedField]);
43899
+ const getTooltipChildren = React.useCallback(item => getHealthAndSafetyTooltipChildren(item, isEmpty, healthAndSafetyDistributionData, t, renderTooltipJsx, selectedFieldLabel), [t, isEmpty, healthAndSafetyDistributionData, selectedFieldLabel]);
43900
+ const handleFilterChange = React.useCallback(value => {
43901
+ setSelectedField(value);
43902
+ }, []);
43879
43903
  return /*#__PURE__*/jsxRuntime.jsx(Widget, {
43880
43904
  loading: loading || pieChartLoading,
43881
43905
  title: /*#__PURE__*/jsxRuntime.jsx("div", {
43882
43906
  children: t("Health and Safety")
43883
43907
  }),
43884
43908
  className: "with-border-header h-w-btn-header ",
43909
+ addedHeader: /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
43910
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
43911
+ className: "flex-1"
43912
+ }), /*#__PURE__*/jsxRuntime.jsx(antd.Select, {
43913
+ value: selectedField,
43914
+ style: {
43915
+ width: 180
43916
+ },
43917
+ onChange: handleFilterChange,
43918
+ options: filterOptions.map(opt => ({
43919
+ ...opt,
43920
+ label: t(opt.label)
43921
+ })),
43922
+ popupMatchSelectWidth: 180
43923
+ })]
43924
+ }),
43885
43925
  children: /*#__PURE__*/jsxRuntime.jsx("div", {
43886
43926
  style: {
43887
43927
  marginTop: "auto",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "datastake-daf",
3
- "version": "0.6.776",
3
+ "version": "0.6.777",
4
4
  "dependencies": {
5
5
  "@ant-design/icons": "^5.2.5",
6
6
  "@antv/g2": "^5.1.1",
@@ -87,9 +87,10 @@ export const calculateHealthAndSafetyPieData = (healthAndSafetyDistributionData,
87
87
  * @param {Object} healthAndSafetyDistributionData - Distribution object
88
88
  * @param {Function} t - Translation function
89
89
  * @param {Function} renderTooltipJsx - Function to render tooltip JSX
90
+ * @param {string} tooltipTitle - Title to display in the tooltip (defaults to "Health and Safety")
90
91
  * @returns {JSX.Element|null} Tooltip content or null
91
92
  */
92
- export const getHealthAndSafetyTooltipChildren = (item, isEmpty, healthAndSafetyDistributionData, t, renderTooltipJsx) => {
93
+ export const getHealthAndSafetyTooltipChildren = (item, isEmpty, healthAndSafetyDistributionData, t, renderTooltipJsx, tooltipTitle = "Health and Safety") => {
93
94
  // If empty or no data, return null to display nothing
94
95
  if (isEmpty || !Object.keys(healthAndSafetyDistributionData).length) {
95
96
  return null;
@@ -129,7 +130,7 @@ export const getHealthAndSafetyTooltipChildren = (item, isEmpty, healthAndSafety
129
130
 
130
131
  // Show all items with their percentages
131
132
  return renderTooltipJsx({
132
- title: t("Health and Safety"),
133
+ title: t(tooltipTitle),
133
134
  items: itemsWithData,
134
135
  });
135
136
  };
@@ -1,23 +1,33 @@
1
- import React, { useMemo, useCallback } from 'react';
1
+ import React, { useMemo, useCallback, useState } from 'react';
2
2
  import { Widget, PieChart } from '../../../../../../../../index.js';
3
+ import { Select } from 'antd';
3
4
  import { getHealthAndSafetyDistributionData, isHealthAndSafetyDistributionEmpty, calculateHealthAndSafetyPieData, getHealthAndSafetyTooltipChildren } from './helper';
4
5
  import { renderTooltipJsx } from '../../../../../../../../utils';
5
6
  import { useWidgetFetch } from '../../../../../../../hooks/useWidgetFetch.js';
6
7
 
7
- const HealthAndSafety = ({
8
+ const filterOptions = [
9
+ { value: 'aidKitAccessible', label: 'Aid kit availability' },
10
+ { value: 'hsTrainingConfirmation', label: 'H&S training delivery' },
11
+ { value: 'duosFormed', label: 'Workers safe pairing' },
12
+ { value: 'presenceOfChildren', label: 'No children' },
13
+ ];
14
+
15
+ const HealthAndSafety = ({
8
16
  id,
9
17
  getSummaryDetail,
10
- loading = false,
11
- t = (s) => s
18
+ loading = false,
19
+ t = (s) => s
12
20
  }) => {
21
+ const [selectedField, setSelectedField] = useState('aidKitAccessible');
22
+
13
23
  const defaultConfig = useMemo(
14
24
  () => ({
15
25
  basepath: "planting-cycle",
16
26
  url: `/summary/${id}/filtered-piechart`,
17
- filters: { field: 'duosFormed' },
27
+ filters: { field: selectedField },
18
28
  stop: !id,
19
29
  }),
20
- [id],
30
+ [id, selectedField],
21
31
  );
22
32
 
23
33
  const customGetData = useMemo(() => {
@@ -45,53 +55,75 @@ const HealthAndSafety = ({
45
55
  });
46
56
 
47
57
  // Process the fetched pie chart data
48
- // The API returns data in format: [{count: 1, duosFormed: "null"}, {count: 1, duosFormed: "no"}, {count: 1, duosFormed: "yes"}]
58
+ // The API returns data in format: [{count: 1, [field]: "null"}, {count: 1, [field]: "no"}, {count: 1, [field]: "yes"}]
49
59
  const healthAndSafetyDistributionData = useMemo(() => {
50
60
  if (!pieChartData) return { compliant: 0, notCompliant: 0, empty: 0 };
51
-
61
+
52
62
  // If it's already a distribution object
53
63
  if (pieChartData.compliant !== undefined || pieChartData.notCompliant !== undefined) {
54
64
  return pieChartData;
55
65
  }
56
-
57
- // If it's an array, process it
66
+
67
+ // If it's an array, process it using the selected field
58
68
  if (Array.isArray(pieChartData)) {
59
69
  const distribution = { compliant: 0, notCompliant: 0, empty: 0 };
60
-
70
+
61
71
  pieChartData.forEach(item => {
62
- const duosFormedValue = item.duosFormed;
72
+ const fieldValue = item[selectedField];
63
73
  const count = item.count || 0;
64
-
65
- // Map duosFormed values to distribution categories
66
- if (duosFormedValue === "yes" || duosFormedValue === true) {
74
+
75
+ // Map field values to distribution categories
76
+ if (fieldValue === "yes" || fieldValue === true) {
67
77
  distribution.compliant += count;
68
- } else if (duosFormedValue === "no" || duosFormedValue === false) {
78
+ } else if (fieldValue === "no" || fieldValue === false) {
69
79
  distribution.notCompliant += count;
70
- } else if (duosFormedValue === "null" || duosFormedValue === null || duosFormedValue === undefined) {
80
+ } else if (fieldValue === "null" || fieldValue === null || fieldValue === undefined) {
71
81
  distribution.empty += count;
72
82
  }
73
83
  });
74
-
84
+
75
85
  return distribution;
76
86
  }
77
-
87
+
78
88
  // Fallback: try to extract from activityData-like structure
79
89
  return getHealthAndSafetyDistributionData(pieChartData);
80
- }, [pieChartData]);
90
+ }, [pieChartData, selectedField]);
81
91
 
82
92
  const isEmpty = useMemo(() => isHealthAndSafetyDistributionEmpty(healthAndSafetyDistributionData), [healthAndSafetyDistributionData]);
83
93
  const pieData = useMemo(() => calculateHealthAndSafetyPieData(healthAndSafetyDistributionData, t), [healthAndSafetyDistributionData, t]);
84
94
 
95
+ // Get the label for the selected field to use as tooltip title
96
+ const selectedFieldLabel = useMemo(() => {
97
+ const selectedOption = filterOptions.find(opt => opt.value === selectedField);
98
+ return selectedOption ? selectedOption.label : 'Health and Safety';
99
+ }, [selectedField]);
100
+
85
101
  const getTooltipChildren = useCallback(
86
- (item) => getHealthAndSafetyTooltipChildren(item, isEmpty, healthAndSafetyDistributionData, t, renderTooltipJsx),
87
- [t, isEmpty, healthAndSafetyDistributionData],
102
+ (item) => getHealthAndSafetyTooltipChildren(item, isEmpty, healthAndSafetyDistributionData, t, renderTooltipJsx, selectedFieldLabel),
103
+ [t, isEmpty, healthAndSafetyDistributionData, selectedFieldLabel],
88
104
  );
89
105
 
106
+ const handleFilterChange = useCallback((value) => {
107
+ setSelectedField(value);
108
+ }, []);
109
+
90
110
  return (
91
111
  <Widget
92
112
  loading={loading || pieChartLoading}
93
113
  title={<div>{t("Health and Safety")}</div>}
94
114
  className="with-border-header h-w-btn-header "
115
+ addedHeader={
116
+ <>
117
+ <div className="flex-1" />
118
+ <Select
119
+ value={selectedField}
120
+ style={{ width: 180 }}
121
+ onChange={handleFilterChange}
122
+ options={filterOptions.map(opt => ({ ...opt, label: t(opt.label) }))}
123
+ popupMatchSelectWidth={180}
124
+ />
125
+ </>
126
+ }
95
127
  >
96
128
  <div
97
129
  style={{