datastake-daf 0.6.826 → 0.6.828

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 +1126 -1239
  2. package/dist/hooks/index.js +14 -12
  3. package/dist/pages/index.js +108 -77
  4. package/dist/services/index.js +5 -1
  5. package/package.json +1 -1
  6. package/src/@daf/core/components/Screens/Admin/AdminTables/EventsTable/helper.js +17 -21
  7. package/src/@daf/core/components/Screens/Admin/AdminTables/EventsTable/index.jsx +5 -3
  8. package/src/@daf/core/components/Screens/Admin/AdminTables/hook.js +0 -3
  9. package/src/@daf/core/components/Screens/Admin/AdminViews/index.jsx +2 -1
  10. package/src/@daf/hooks/useGetQueryParams.js +44 -25
  11. package/src/@daf/hooks/useWidgetFetch.js +1 -1
  12. package/src/@daf/pages/Dashboards/UserDashboard/components/MineSites/index.jsx +3 -1
  13. package/src/@daf/pages/Locations/MineSite/config.js +1 -1
  14. package/src/@daf/pages/Stakeholders/Operators/config.js +1 -1
  15. package/src/@daf/pages/Stakeholders/Workers/config.js +1 -1
  16. package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CommunityParticipation/JobsTimeline/index.jsx +32 -9
  17. package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CycleIndicators/HealthAndSafety/helper.js +48 -43
  18. package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CycleIndicators/HealthAndSafety/index.jsx +17 -5
  19. package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CycleOutcomes/PlantingActivitiesTimeline.jsx +12 -5
  20. package/src/@daf/pages/TablePage/hook.js +7 -2
  21. package/src/@daf/pages/View/index.jsx +1 -1
  22. package/src/@daf/services/LinkedSubjects.js +5 -1
@@ -147,7 +147,7 @@ export const getFilterOptions = (options, t) => {
147
147
  export const formConfig = {
148
148
  namespace: 'OPERATOR',
149
149
  view: ['scoping', 'new'],
150
- scope: 'global',
150
+ scope: 'createOperator',
151
151
  formType: 'operator',
152
152
  }
153
153
 
@@ -137,7 +137,7 @@ export const getFilterOptions = (options, t) => {
137
137
  export const formConfig = {
138
138
  namespace: 'WORKERS',
139
139
  view: ['scoping', 'new'],
140
- scope: 'global',
140
+ scope: 'createWorker',
141
141
  formType: 'worker',
142
142
  }
143
143
 
@@ -20,21 +20,44 @@ const JobsTimeline = ({
20
20
  ? dayJobsTimeline
21
21
  : (dayJobsTimeline?.jobsTimeline || dayJobsTimeline?.jobs || dayJobsTimeline?.timeline || []);
22
22
 
23
+ // const jobsTimelineData = useMemo(() => {
24
+ // // Always process data, even if empty, to generate default date range for x-axis
25
+ // const dataToProcess = (!jobsData || !Array.isArray(jobsData) || jobsData.length === 0)
26
+ // ? []
27
+ // : jobsData;
28
+
29
+ // // Process data without cumulative calculation (for jobs timeline)
30
+ // // Try to find value in total, count, jobs, or value fields
31
+ // return processChartDateData({
32
+ // mainData: dataToProcess,
33
+ // isCumulative: false,
34
+ // valueField: 'total', // Will fallback to count/jobs/value if total doesn't exist
35
+ // });
36
+ // }, [jobsData, processChartDateData]);
37
+
23
38
  const jobsTimelineData = useMemo(() => {
24
- // Always process data, even if empty, to generate default date range for x-axis
25
- const dataToProcess = (!jobsData || !Array.isArray(jobsData) || jobsData.length === 0)
26
- ? []
39
+ // Prepare data first
40
+ const dataToProcess = (!jobsData || !Array.isArray(jobsData) || jobsData.length === 0)
41
+ ? []
27
42
  : jobsData;
28
-
29
- // Process data without cumulative calculation (for jobs timeline)
30
- // Try to find value in total, count, jobs, or value fields
31
- return processChartDateData({
43
+
44
+ // Process data without cumulative calculation
45
+ const processedData = processChartDateData({
32
46
  mainData: dataToProcess,
33
47
  isCumulative: false,
34
- valueField: 'total', // Will fallback to count/jobs/value if total doesn't exist
48
+ valueField: 'total', // fallback handled inside processChartDateData
35
49
  });
50
+
51
+ // Find last index with jobs > 0
52
+ let lastNonZeroIndex = processedData.length - 1;
53
+ while (lastNonZeroIndex >= 0 && (processedData[lastNonZeroIndex].jobs || 0) === 0) {
54
+ lastNonZeroIndex--;
55
+ }
56
+
57
+ // Slice up to last period with data
58
+ return processedData.slice(0, lastNonZeroIndex + 1);
36
59
  }, [jobsData, processChartDateData]);
37
-
60
+
38
61
  const maxYValue = useMemo(() => {
39
62
  if (!jobsTimelineData || jobsTimelineData.length === 0) {
40
63
  return 100;
@@ -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;
@@ -18,6 +18,11 @@ export const useFetchData = ({
18
18
  subject,
19
19
  }) => {
20
20
  const { paginationQuery, searchParams, otherParams, sortBy, sortDir, } = useGetQueryParams({location});
21
+
22
+ const tab = useMemo(() => {
23
+ return activeTab;
24
+ }, [activeTab])
25
+
21
26
  useEffect(() => {
22
27
  const cleanSearchParams = Object.fromEntries(
23
28
  Object.entries(searchParams).filter(([_, value]) => value != null && value !== '')
@@ -37,12 +42,12 @@ export const useFetchData = ({
37
42
  pagination: paginationQuery,
38
43
  ...(Object.keys(otherParams).length > 0 && otherParams ),
39
44
  ...(Object.keys(cleanSearchParams).length > 0 && { search: cleanSearchParams }),
40
- tab: activeTab,
45
+ tab: tab,
41
46
  sortBy: {
42
47
  [sortBy || extendingSortKey || "updatedAt"]: sortDir ? (sortDir === "ascend" ? 1 : -1) : (extendingSortDir || -1),
43
48
  },
44
49
  }, subject)
45
- }, [location.search, activeTab, JSON.stringify(extendingFilters)]);
50
+ }, [location.search, JSON.stringify(extendingFilters)]);
46
51
  }
47
52
 
48
53
  export const useTablePage = ({
@@ -135,7 +135,7 @@ const View = ({
135
135
  "management-location": "location",
136
136
  "management-stakeholder": "stakeholder",
137
137
  "management-event": "event",
138
- "management-incident": "incident",
138
+ "management-document": "document",
139
139
  }
140
140
 
141
141
 
@@ -7,14 +7,18 @@ export const getNamespace = (namespace) => {
7
7
  let _namespace = namespace;
8
8
  switch (namespace) {
9
9
  case "locations":
10
+ case "location":
10
11
  _namespace = "location";
11
12
  break;
12
13
  case "stakeholders":
14
+ case "stakeholder":
13
15
  _namespace = "stakeholder";
14
16
  break;
15
17
  case "documents":
18
+ case "document":
16
19
  _namespace = "document";
17
20
  break;
21
+ case "event":
18
22
  case "nashirikiEvent":
19
23
  case "events":
20
24
  _namespace = "event";
@@ -50,7 +54,7 @@ class LinkedSubjectsService extends BaseService {
50
54
 
51
55
  getOne({ id, signal, namespace, sourceId, source, version }) {
52
56
  return this.apiGet({
53
- url: `/${namespace === "nashirikiEvent" ? "event" : namespace}/${id}`,
57
+ url: `/${getNamespace(namespace)}/${id}`,
54
58
  isApp: true,
55
59
  signal,
56
60
  params: { authorId: sourceId, source, version },