datastake-daf 0.6.772 → 0.6.773

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,40 +1,151 @@
1
- import React, { useState } from 'react';
2
- import { Widget } from '../../../../../../../../src/index.js';
1
+ import React, { useState, useMemo, useEffect, useCallback } from 'react';
2
+ import { Widget, StickyTable, SearchFilters } from '../../../../../../../../src/index.js';
3
+ import { useWidgetFetch } from '../../../../../../hooks/useWidgetFetch.js';
4
+ import { getColumns } from './config.js';
5
+ import { getRedirectLink } from '../../../../../../../utils.js';
3
6
 
4
- const ACTIVITIES_TAB = 'activities';
5
- const PARTNERS_TAB = 'partners';
6
- const INCIDENTS_TAB = 'incidents';
7
+ // Constants
8
+ export const ACTIVITIES_TAB = 'activities';
9
+ export const PARTNERS_TAB = 'partners';
10
+ export const INCIDENTS_TAB = 'incidents';
7
11
 
12
+ export const DEFAULT_SEARCH_FIELDS = ["name", "datastakeId"];
13
+ const URL_PATTERN = /\/summary\/[^/]+\/(.+)/;
8
14
 
9
- const AssociatedInformation = ({
10
- activityData,
11
- loading = false,
12
- t = (s) => s
15
+ // Configuration
16
+ export const TABS_CONFIG = [
17
+ { label: "straatos::activities", value: ACTIVITIES_TAB },
18
+ { label: "straatos::partners", value: PARTNERS_TAB },
19
+ { label: "straatos::incidents", value: INCIDENTS_TAB, disabled: true },
20
+ ];
21
+
22
+ // Helper functions
23
+ export const getSearchFields = (activeTab) => DEFAULT_SEARCH_FIELDS;
24
+
25
+ export const buildSearchFilter = (search, fields) =>
26
+ search ? { search: { qs: search, fields } } : {};
27
+
28
+ export const extractTypeFromUrl = (url) => {
29
+ const match = url.match(URL_PATTERN);
30
+ if (!match) {
31
+ throw new Error(`Invalid URL format: ${url}`);
32
+ }
33
+ return match[1];
34
+ };
35
+
36
+ export const ensureArray = (data) => Array.isArray(data) ? data : [];
37
+
38
+ const AssociatedInformation = ({
39
+ id,
40
+ navigate,
41
+ getSummaryDetail,
42
+ loading = false,
43
+ projectId,
44
+ basepath = "planting-cycle",
45
+ endpoint = "associated-information",
46
+ tabsConfig = TABS_CONFIG,
47
+ searchFieldsMap = getSearchFields,
48
+ t = (s) => s
13
49
  }) => {
14
50
  const [activeTab, setActiveTab] = useState(ACTIVITIES_TAB);
51
+ const [search, setSearch] = useState('');
52
+
53
+ const searchFields = useMemo(() => searchFieldsMap(activeTab), [activeTab, searchFieldsMap]);
54
+
55
+ const filters = useMemo(() => ({
56
+ type: activeTab,
57
+ ...buildSearchFilter(search, searchFields)
58
+ }), [activeTab, search, searchFields]);
59
+
60
+ const defaultConfig = useMemo(() => ({
61
+ basepath,
62
+ url: `/summary/${id}/${endpoint}`,
63
+ filters,
64
+ stop: !id,
65
+ }), [id, filters, basepath, endpoint]);
66
+
67
+ const customGetData = useMemo(() => {
68
+ if (!getSummaryDetail || !id) return undefined;
69
+
70
+ return (rest) => {
71
+ const { url, filters: restFilters } = rest;
72
+ const type = extractTypeFromUrl(url);
73
+ const params = {
74
+ ...(restFilters || {}),
75
+ type: restFilters?.type || activeTab
76
+ };
77
+ return getSummaryDetail(id, type, params);
78
+ };
79
+ }, [getSummaryDetail, id, activeTab]);
80
+
81
+ const { loading: associatedInformationLoading, data: associatedInformationData, setData } = useWidgetFetch({
82
+ config: defaultConfig,
83
+ getData: customGetData
84
+ });
85
+
86
+ // Reset data and search when tab changes
87
+ useEffect(() => {
88
+ setData([]);
89
+ setSearch('');
90
+ }, [activeTab, setData]);
91
+
92
+ const handleSearch = useCallback((activeFilter, searchValue) => {
93
+ setSearch(searchValue || '');
94
+ }, []);
95
+
96
+ const handleTabChange = useCallback((value) => {
97
+ setActiveTab(value);
98
+ }, []);
99
+
100
+ const columns = useMemo(() => getColumns({
101
+ t,
102
+ activeTab,
103
+ view: activeTab,
104
+ projectId,
105
+ navigate,
106
+ getRedirectLink,
107
+ }), [t, activeTab, projectId, navigate]);
108
+
109
+ const tableDataSource = useMemo(() =>
110
+ ensureArray(associatedInformationData),
111
+ [associatedInformationData]
112
+ );
113
+
114
+ const translatedTabs = useMemo(() =>
115
+ tabsConfig.map(tab => ({ ...tab, label: t(tab.label) })),
116
+ [tabsConfig, t]
117
+ );
15
118
 
16
119
  return (
17
120
  <section>
18
-
19
- <Widget
20
- className="v2-widget no-px h-w-btn-header no-p-body"
121
+ <Widget
122
+ className="v2-widget no-px no-p-body h-w-btn-header with-border-header"
21
123
  title={t("Associated Information")}
22
124
  tabsConfig={{
23
- tabs: [
24
- { label: t("straatos::activities"), value: ACTIVITIES_TAB },
25
- { label: t("straatos::partners"), value: PARTNERS_TAB },
26
- { label: t("straatos::incidents"), value: INCIDENTS_TAB },
27
- ],
125
+ tabs: translatedTabs,
28
126
  value: activeTab,
29
- onChange: (value) => {
30
- setActiveTab(value);
31
- // setData([]);
32
- },
127
+ onChange: handleTabChange,
33
128
  }}
34
129
  >
35
- <div>
36
- </div>
37
- </Widget>
130
+ <div className='mt-6 ml-6 mr-6'>
131
+ <SearchFilters
132
+ t={t}
133
+ showFilter={false}
134
+ hasError={false}
135
+ canClear={true}
136
+ setHasError={() => {}}
137
+ onSearch={handleSearch}
138
+ activeFilters={{ search }}
139
+ />
140
+ </div>
141
+ <div className='mb-6'>
142
+ <StickyTable
143
+ columns={columns}
144
+ dataSource={tableDataSource}
145
+ loading={associatedInformationLoading || loading}
146
+ />
147
+ </div>
148
+ </Widget>
38
149
  </section>
39
150
  );
40
151
  };
@@ -8,7 +8,6 @@ const JobsTimeline = ({
8
8
  t = (s) => s
9
9
  }) => {
10
10
 
11
- console.log('dayJobsTimeline', dayJobsTimeline);
12
11
  const jobsData = Array.isArray(dayJobsTimeline)
13
12
  ? dayJobsTimeline
14
13
  : (dayJobsTimeline?.jobsTimeline || dayJobsTimeline?.jobs || dayJobsTimeline?.timeline || []);
@@ -6,13 +6,12 @@ import CommunityParticipation from './components/CommunityParticipation/index.js
6
6
  import AssociatedInformation from './components/AssociatedInformation/index.jsx';
7
7
  import KeyInformation from './components/KeyInformation/index.jsx';
8
8
 
9
- const PlantingCycleSummary = ({ header, activityData, loading = false, id, t = () => { }, getSummaryDetail }) => {
10
-
9
+ const PlantingCycleSummary = ({ header, activityData, loading = false, id, projectId, t = () => { }, getSummaryDetail, navigate }) => {
11
10
  return (
12
11
  <DashboardLayout
13
12
  header={
14
13
  <Header
15
- title={header?.title || ''}
14
+ title={header?.title + ' Summary' || ''}
16
15
  supportText={header?.supportText || ''}
17
16
  onDownload={header?.onDownload}
18
17
  downloadDisabled={header?.downloadDisabled}
@@ -28,7 +27,7 @@ const PlantingCycleSummary = ({ header, activityData, loading = false, id, t = (
28
27
  <CycleOutcomes id={id} getSummaryDetail={getSummaryDetail} loading={loading} t={t} />
29
28
  <CycleIndicators id={id} getSummaryDetail={getSummaryDetail} loading={loading} t={t} />
30
29
  <CommunityParticipation id={id} getSummaryDetail={getSummaryDetail} loading={loading} t={t} />
31
- <AssociatedInformation id={id} getSummaryDetail={getSummaryDetail} loading={loading} t={t} />
30
+ <AssociatedInformation id={id} projectId={projectId} getSummaryDetail={getSummaryDetail} loading={loading} t={t} navigate={navigate} />
32
31
  </DashboardLayout>
33
32
  )
34
33
  }