datastake-daf 0.6.763 → 0.6.765
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.
- package/dist/components/index.js +45 -19
- package/dist/hooks/index.js +1 -1
- package/dist/layouts/index.js +36 -11
- package/dist/pages/index.js +1974 -999
- package/dist/services/index.js +1 -21
- package/dist/style/datastake/mapbox-gl.css +330 -0
- package/package.json +1 -1
- package/src/@daf/core/components/Screens/TableScreen/TablePageWithTabs/index.jsx +9 -4
- package/src/@daf/core/components/Table/index.jsx +2 -2
- package/src/@daf/core/components/UI/KeyIndicatorNavigateLabel/index.jsx +29 -0
- package/src/@daf/hooks/useFilters.js +1 -1
- package/src/@daf/layouts/AppLayout/components/MobileDrawer/index.js +4 -2
- package/src/@daf/layouts/AppLayout/components/UserDropdown/index.js +23 -2
- package/src/@daf/layouts/AppLayout/index.jsx +2 -0
- package/src/@daf/pages/Dashboards/SupplyChain/components/ChartsContainer/components/GenderDistribution/config.js +7 -6
- package/src/@daf/pages/Dashboards/SupplyChain/components/ChartsContainer/components/GenderDistribution/index.js +2 -1
- package/src/@daf/pages/Dashboards/SupplyChain/components/KeyIndicators/config.js +29 -53
- package/src/@daf/pages/Dashboards/SupplyChain/index.jsx +2 -2
- package/src/@daf/pages/Dashboards/UserDashboard/components/KeyIndicators/config.js +36 -70
- package/src/@daf/pages/Documents/index.jsx +9 -13
- package/src/@daf/pages/Events/Activities/index.jsx +8 -21
- package/src/@daf/pages/Events/Incidents/index.jsx +8 -21
- package/src/@daf/pages/Events/index.jsx +8 -20
- package/src/@daf/pages/Locations/MineSite/index.jsx +8 -21
- package/src/@daf/pages/Locations/index.jsx +9 -12
- package/src/@daf/pages/Partners/columns.js +421 -0
- package/src/@daf/pages/Partners/config.js +32 -0
- package/src/@daf/pages/Partners/create.jsx +145 -0
- package/src/@daf/pages/Partners/edit.jsx +98 -0
- package/src/@daf/pages/Partners/hook.js +153 -0
- package/src/@daf/pages/Partners/index.jsx +233 -8
- package/src/@daf/pages/Stakeholders/Operators/index.jsx +8 -22
- package/src/@daf/pages/Stakeholders/Workers/index.jsx +8 -21
- package/src/@daf/pages/Stakeholders/index.jsx +9 -10
- package/src/@daf/pages/Summary/Activities/PlantingCycle/config.js +40 -0
- package/src/@daf/pages/Summary/Activities/PlantingCycle/helper.js +122 -0
- package/src/@daf/pages/Summary/Activities/PlantingCycle/index.jsx +46 -0
- package/src/@daf/pages/Summary/Activities/Restoration/config.js +1 -1
- package/src/@daf/pages/hook.js +34 -0
- package/src/@daf/services/PartnerService.js +1 -16
- package/src/index.js +1 -1
- package/src/pages.js +2 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { useCallback, useState } from "react";
|
|
2
|
+
import PartnerService from "../../services/PartnerService.js";
|
|
3
|
+
import { message } from "antd";
|
|
4
|
+
|
|
5
|
+
export const usePartnersActions = ({
|
|
6
|
+
activeTab,
|
|
7
|
+
filters,
|
|
8
|
+
setTotalRequests,
|
|
9
|
+
t = () => {},
|
|
10
|
+
}) => {
|
|
11
|
+
const [loading, setLoading] = useState(false);
|
|
12
|
+
const [data, setData] = useState([]);
|
|
13
|
+
const [requestDataFetch, setRequestDataFetch] = useState(false);
|
|
14
|
+
const [initFetchDone, setInitFetchDone] = useState(false);
|
|
15
|
+
|
|
16
|
+
const fetchData = useCallback(async () => {
|
|
17
|
+
setLoading(true);
|
|
18
|
+
setData([]);
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
const { data } = await PartnerService.get(activeTab, {
|
|
22
|
+
...filters,
|
|
23
|
+
type: activeTab,
|
|
24
|
+
});
|
|
25
|
+
setData(data);
|
|
26
|
+
setTotalRequests(data?.meta?.total || 0);
|
|
27
|
+
} catch (err) {
|
|
28
|
+
console.log(err);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
setLoading(false);
|
|
32
|
+
|
|
33
|
+
if (!initFetchDone) {
|
|
34
|
+
setInitFetchDone(true);
|
|
35
|
+
}
|
|
36
|
+
}, [activeTab, filters, initFetchDone, setLoading, setTotalRequests, setData, setInitFetchDone]);
|
|
37
|
+
|
|
38
|
+
const accept = useCallback(
|
|
39
|
+
async (id) => {
|
|
40
|
+
setLoading(true);
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
await PartnerService.accept(id);
|
|
44
|
+
setRequestDataFetch(true);
|
|
45
|
+
} catch (err) {
|
|
46
|
+
console.log(err);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
setLoading(false);
|
|
50
|
+
},
|
|
51
|
+
[setLoading],
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const decline = useCallback(
|
|
55
|
+
async (id) => {
|
|
56
|
+
setLoading(true);
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
await PartnerService.decline(id);
|
|
60
|
+
setRequestDataFetch(true);
|
|
61
|
+
} catch (err) {
|
|
62
|
+
console.log(err);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
setLoading(false);
|
|
66
|
+
},
|
|
67
|
+
[setLoading],
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const activate = useCallback(
|
|
71
|
+
async (id) => {
|
|
72
|
+
setLoading(true);
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
await PartnerService.activate(id);
|
|
76
|
+
setRequestDataFetch(true);
|
|
77
|
+
} catch (err) {
|
|
78
|
+
console.log(err);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
setLoading(false);
|
|
82
|
+
},
|
|
83
|
+
[setLoading],
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const suspend = useCallback(
|
|
87
|
+
async (id) => {
|
|
88
|
+
setLoading(true);
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
await PartnerService.suspend(id);
|
|
92
|
+
message.success(t("Partner suspended successfully"));
|
|
93
|
+
setRequestDataFetch(true);
|
|
94
|
+
} catch (err) {
|
|
95
|
+
console.log(err);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
setLoading(false);
|
|
99
|
+
},
|
|
100
|
+
[setLoading],
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
const resendInvite = useCallback(
|
|
104
|
+
async (id) => {
|
|
105
|
+
setLoading(true);
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
await PartnerService.resendInvite(id);
|
|
109
|
+
await fetchData();
|
|
110
|
+
} catch (err) {
|
|
111
|
+
console.log(err);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
setLoading(false);
|
|
115
|
+
},
|
|
116
|
+
[fetchData, setLoading],
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
const block = useCallback(
|
|
120
|
+
async (id) => {
|
|
121
|
+
setLoading(true);
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
await PartnerService.block(id);
|
|
125
|
+
await fetchData();
|
|
126
|
+
} catch (err) {
|
|
127
|
+
console.log(err);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
setLoading(false);
|
|
131
|
+
},
|
|
132
|
+
[fetchData, setLoading],
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
loading,
|
|
137
|
+
setLoading,
|
|
138
|
+
data,
|
|
139
|
+
setData,
|
|
140
|
+
requestDataFetch,
|
|
141
|
+
setRequestDataFetch,
|
|
142
|
+
fetchData,
|
|
143
|
+
accept,
|
|
144
|
+
decline,
|
|
145
|
+
activate,
|
|
146
|
+
suspend,
|
|
147
|
+
resendInvite,
|
|
148
|
+
block,
|
|
149
|
+
setTotalRequests,
|
|
150
|
+
initFetchDone,
|
|
151
|
+
setInitFetchDone,
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -1,11 +1,236 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React, { useState, useMemo, useEffect, useCallback } from 'react'
|
|
2
|
+
import { Modal } from 'antd';
|
|
3
|
+
import { usePartnersActions } from './hook.js';
|
|
4
|
+
import { getColumns } from './columns.js';
|
|
5
|
+
import TablePageWithTabs from '../../core/components/Screens/TableScreen/TablePageWithTabs/index.jsx';
|
|
6
|
+
import { checkboxConfig, selectFiltersConfig, filtersConfig } from './config.js';
|
|
7
|
+
import Create from './create.jsx';
|
|
8
|
+
import { useGetQueryParams } from '../../hooks/useGetQueryParams.js';
|
|
9
|
+
import ModalHeader from '../../core/components/Header/ModalHeader/index.jsx';
|
|
10
|
+
import Edit from './edit.jsx';
|
|
2
11
|
|
|
3
|
-
const
|
|
12
|
+
const PartnersTable = ({
|
|
13
|
+
t = () => {},
|
|
14
|
+
goTo = () => {},
|
|
15
|
+
user = {},
|
|
16
|
+
options = {},
|
|
17
|
+
getRedirectLink = () => {},
|
|
18
|
+
theme = {},
|
|
19
|
+
isMobile,
|
|
20
|
+
APP,
|
|
21
|
+
location,
|
|
22
|
+
breadcrumbs = [],
|
|
23
|
+
getApiBaseUrl = () => {},
|
|
24
|
+
getAppHeader = () => {},
|
|
25
|
+
query = {},
|
|
26
|
+
ajaxForms = {},
|
|
27
|
+
changeAjaxForms = () => {},
|
|
28
|
+
ajaxOptions = {},
|
|
29
|
+
changeAjaxOptions = () => {},
|
|
30
|
+
applications = [],
|
|
31
|
+
extendingFilters = {},
|
|
32
|
+
searchLocationParams,
|
|
33
|
+
}) => {
|
|
34
|
+
const [totalRequests, setTotalRequests] = useState(0);
|
|
35
|
+
const [selectOptions, setSelectOptions] = useState();
|
|
36
|
+
const [activeTab, setActiveTab] = useState();
|
|
37
|
+
const [pendingEditId, setPendingEditId] = useState(null);
|
|
38
|
+
const [openModal, setOpenModal] = useState(false);
|
|
39
|
+
|
|
40
|
+
const tabs = useMemo(() => [
|
|
41
|
+
{ label: t("List"), key: "partners" },
|
|
42
|
+
{ label: (
|
|
43
|
+
<div className="tab-cont">
|
|
44
|
+
<div className="flex flex-column justify-content-center">
|
|
45
|
+
{t('Requests')}
|
|
46
|
+
</div>
|
|
47
|
+
{typeof totalRequests === 'number' ? (
|
|
48
|
+
<div className="flex flex-column justify-content-center">
|
|
49
|
+
<div className="bubble">
|
|
50
|
+
<div className="flex flex-column justify-content-center">
|
|
51
|
+
{totalRequests}
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
) : null}
|
|
56
|
+
</div>
|
|
57
|
+
),
|
|
58
|
+
key: "requests"
|
|
59
|
+
},
|
|
60
|
+
], [t, totalRequests]);
|
|
61
|
+
|
|
62
|
+
const { paginationQuery, searchParams, otherParams, sortBy, sortDir, } = useGetQueryParams({location});
|
|
63
|
+
|
|
64
|
+
const filters = useMemo(() => {
|
|
65
|
+
const cleanSearchParams = Object.fromEntries(
|
|
66
|
+
Object.entries(searchParams).filter(([_, value]) => value != null && value !== '')
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
pagination: paginationQuery,
|
|
71
|
+
...(Object.keys(otherParams).length > 0 && otherParams ),
|
|
72
|
+
...(Object.keys(cleanSearchParams).length > 0 && { search: cleanSearchParams }),
|
|
73
|
+
tab: activeTab,
|
|
74
|
+
sortBy: {
|
|
75
|
+
[sortBy || "updatedAt"]: sortDir ? (sortDir === "ascend" ? 1 : -1) : -1,
|
|
76
|
+
},
|
|
77
|
+
...extendingFilters,
|
|
78
|
+
}
|
|
79
|
+
}, [location.search, activeTab, JSON.stringify(extendingFilters)]);
|
|
80
|
+
|
|
81
|
+
const {
|
|
82
|
+
loading,
|
|
83
|
+
data,
|
|
84
|
+
requestDataFetch,
|
|
85
|
+
fetchData,
|
|
86
|
+
accept,
|
|
87
|
+
decline,
|
|
88
|
+
activate,
|
|
89
|
+
suspend,
|
|
90
|
+
resendInvite,
|
|
91
|
+
block,
|
|
92
|
+
setRequestDataFetch,
|
|
93
|
+
initFetchDone,
|
|
94
|
+
setInitFetchDone,
|
|
95
|
+
} = usePartnersActions({
|
|
96
|
+
activeTab,
|
|
97
|
+
filters,
|
|
98
|
+
setTotalRequests,
|
|
99
|
+
t,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const columns = useMemo(() => getColumns({
|
|
103
|
+
t,
|
|
104
|
+
accept,
|
|
105
|
+
decline,
|
|
106
|
+
suspend,
|
|
107
|
+
resendInvite,
|
|
108
|
+
activate,
|
|
109
|
+
activeTab,
|
|
110
|
+
selectOptions,
|
|
111
|
+
block,
|
|
112
|
+
setOpen: setOpenModal,
|
|
113
|
+
}), [t, accept, decline, suspend, resendInvite, activate, activeTab, selectOptions, block, setOpenModal]);
|
|
114
|
+
|
|
115
|
+
const handleActiveTabChange = useCallback((value) => {
|
|
116
|
+
setActiveTab(value);
|
|
117
|
+
}, []);
|
|
118
|
+
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
if (requestDataFetch) {
|
|
121
|
+
fetchData();
|
|
122
|
+
setRequestDataFetch(false);
|
|
123
|
+
}
|
|
124
|
+
}, [requestDataFetch, fetchData, setRequestDataFetch]);
|
|
125
|
+
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
if (searchLocationParams.has("datastakeId") && !pendingEditId) {
|
|
128
|
+
setPendingEditId(searchLocationParams.get("datastakeId"));
|
|
129
|
+
}
|
|
130
|
+
}, [searchLocationParams, pendingEditId]);
|
|
131
|
+
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
if (pendingEditId) {
|
|
134
|
+
const partner = data.find((partner) => partner.datastakeId === pendingEditId);
|
|
135
|
+
if (partner) {
|
|
136
|
+
setOpenModal(partner);
|
|
137
|
+
setPendingEditId(null);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}, [data, pendingEditId]);
|
|
141
|
+
|
|
142
|
+
useEffect(() => {
|
|
143
|
+
fetchData();
|
|
144
|
+
}, [filters]);
|
|
145
|
+
|
|
146
|
+
const headerTooltip = useMemo(() => ({
|
|
147
|
+
title: t("Partners"),
|
|
148
|
+
content: (
|
|
149
|
+
<div className="max-w-250">
|
|
150
|
+
{t(
|
|
151
|
+
"Partners are organisations sharing their information with you, or receiving your information.",
|
|
152
|
+
)}
|
|
153
|
+
<br />
|
|
154
|
+
{t("Only authorised users can create partnerships.")}
|
|
155
|
+
</div>
|
|
156
|
+
),
|
|
157
|
+
}), [t]);
|
|
158
|
+
|
|
159
|
+
const drawerTooltip = useMemo(() => ({
|
|
160
|
+
content: (
|
|
161
|
+
<div className="max-w-250">
|
|
162
|
+
{t("Source: This partner will share information with you.")},
|
|
163
|
+
<br />
|
|
164
|
+
{t("Client: You will share information with this partner.")},
|
|
165
|
+
<br />
|
|
166
|
+
{t("Exchange: You will both share information with each other.")}
|
|
167
|
+
</div>
|
|
168
|
+
),
|
|
169
|
+
}), [t]);
|
|
170
|
+
|
|
4
171
|
return (
|
|
5
|
-
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
172
|
+
<>
|
|
173
|
+
<TablePageWithTabs
|
|
174
|
+
t={t}
|
|
175
|
+
tabs={tabs}
|
|
176
|
+
title={t("Partners")}
|
|
177
|
+
breadCrumbs={breadcrumbs}
|
|
178
|
+
location={location}
|
|
179
|
+
loading={loading}
|
|
180
|
+
goTo={goTo}
|
|
181
|
+
defaultActiveTab={"partners"}
|
|
182
|
+
columns={columns}
|
|
183
|
+
data={data}
|
|
184
|
+
checkboxConfig={checkboxConfig}
|
|
185
|
+
APP={APP}
|
|
186
|
+
getApiBaseUrl={getApiBaseUrl}
|
|
187
|
+
selectOptions={selectOptions}
|
|
188
|
+
selectFiltersConfig={selectFiltersConfig}
|
|
189
|
+
getRedirectLink={getRedirectLink}
|
|
190
|
+
filtersConfig={filtersConfig}
|
|
191
|
+
isMobile={isMobile}
|
|
192
|
+
view="partners"
|
|
193
|
+
getActiveTab={handleActiveTabChange}
|
|
194
|
+
headerTooltip={headerTooltip}
|
|
195
|
+
drawerTitle={t("Create Partner")}
|
|
196
|
+
drawerTooltip={drawerTooltip}
|
|
197
|
+
>
|
|
198
|
+
{({onDrawerClose}) => (
|
|
199
|
+
<Create
|
|
200
|
+
query={query}
|
|
201
|
+
goTo={goTo}
|
|
202
|
+
user={user}
|
|
203
|
+
t={t}
|
|
204
|
+
ajaxForms={ajaxForms}
|
|
205
|
+
changeAjaxForms={changeAjaxForms}
|
|
206
|
+
ajaxOptions={ajaxOptions}
|
|
207
|
+
changeAjaxOptions={changeAjaxOptions}
|
|
208
|
+
onClose={onDrawerClose}
|
|
209
|
+
fetchData={() => setRequestDataFetch(true)}
|
|
210
|
+
APP={APP}
|
|
211
|
+
getAppHeader={getAppHeader}
|
|
212
|
+
getApiBaseUrl={getApiBaseUrl}
|
|
213
|
+
/>
|
|
214
|
+
)}
|
|
215
|
+
</TablePageWithTabs>
|
|
216
|
+
<Modal
|
|
217
|
+
open={!!openModal}
|
|
218
|
+
onCancel={() => setOpenModal(false)}
|
|
219
|
+
footer={null}
|
|
220
|
+
title={<ModalHeader title={t("Edit Settings")} />}
|
|
221
|
+
>
|
|
222
|
+
{openModal ? (
|
|
223
|
+
<Edit
|
|
224
|
+
partner={openModal}
|
|
225
|
+
fetchData={() => setRequestDataFetch(true)}
|
|
226
|
+
onClose={() => setOpenModal(false)}
|
|
227
|
+
t={t}
|
|
228
|
+
/>
|
|
229
|
+
) : null}
|
|
230
|
+
</Modal>
|
|
231
|
+
<input id="myInput" hidden />
|
|
232
|
+
</>
|
|
233
|
+
)
|
|
234
|
+
}
|
|
10
235
|
|
|
11
|
-
export default
|
|
236
|
+
export default PartnersTable
|
|
@@ -5,6 +5,7 @@ import { checkboxConfig, getFiltersConfig, filtersConfig, getFilterOptions } fro
|
|
|
5
5
|
import { useGetQueryParams } from '../../../hooks/useGetQueryParams.js';
|
|
6
6
|
import StakeholdersCreate from './create.jsx';
|
|
7
7
|
import { displayMessage } from '../../../../helpers/messages.js';
|
|
8
|
+
import { useFetchData } from '../../hook.js';
|
|
8
9
|
|
|
9
10
|
const OperatorsTable = ({
|
|
10
11
|
t = () => {},
|
|
@@ -53,28 +54,13 @@ const OperatorsTable = ({
|
|
|
53
54
|
applications,
|
|
54
55
|
}), [t, goTo, user, options, activeTab, getRedirectLink, theme, data, applications]);
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
}, [otherParams, extendingFilters])
|
|
65
|
-
|
|
66
|
-
useEffect(() => {
|
|
67
|
-
getData({
|
|
68
|
-
pagination: paginationQuery,
|
|
69
|
-
...(Object.keys(searchParams).length > 0 && { search: searchParams }),
|
|
70
|
-
...otherParams,
|
|
71
|
-
tab: activeTab,
|
|
72
|
-
sortBy: {
|
|
73
|
-
[sortBy || "updatedAt"]: sortDir ? (sortDir === "ascend" ? 1 : -1) : -1,
|
|
74
|
-
},
|
|
75
|
-
...extendingFilters
|
|
76
|
-
}, 'operators')
|
|
77
|
-
}, [location.search, activeTab, JSON.stringify(extendingFilters)]);
|
|
57
|
+
useFetchData({
|
|
58
|
+
location,
|
|
59
|
+
getData,
|
|
60
|
+
activeTab,
|
|
61
|
+
extendingFilters,
|
|
62
|
+
subject: 'operators',
|
|
63
|
+
})
|
|
78
64
|
|
|
79
65
|
const selectFiltersConfig = useMemo(() => {
|
|
80
66
|
return getFiltersConfig({t});
|
|
@@ -5,6 +5,7 @@ import { checkboxConfig, getFiltersConfig, filtersConfig, getFilterOptions } fro
|
|
|
5
5
|
import { useGetQueryParams } from '../../../hooks/useGetQueryParams.js';
|
|
6
6
|
import StakeholdersCreate from './create.jsx';
|
|
7
7
|
import { displayMessage } from '../../../../helpers/messages.js';
|
|
8
|
+
import { useFetchData } from '../../hook.js';
|
|
8
9
|
|
|
9
10
|
const WorkersTable = ({
|
|
10
11
|
t = () => {},
|
|
@@ -53,27 +54,13 @@ const WorkersTable = ({
|
|
|
53
54
|
applications,
|
|
54
55
|
}), [t, goTo, user, options, activeTab, getRedirectLink, theme, data, applications]);
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}, [otherParams, extendingFilters])
|
|
64
|
-
|
|
65
|
-
useEffect(() => {
|
|
66
|
-
getData({
|
|
67
|
-
pagination: paginationQuery,
|
|
68
|
-
...(Object.keys(searchParams).length > 0 && { search: searchParams }),
|
|
69
|
-
...otherParams,
|
|
70
|
-
tab: activeTab,
|
|
71
|
-
sortBy: {
|
|
72
|
-
[sortBy || "updatedAt"]: sortDir ? (sortDir === "ascend" ? 1 : -1) : -1,
|
|
73
|
-
},
|
|
74
|
-
...extendingFilters
|
|
75
|
-
}, 'workers')
|
|
76
|
-
}, [location.search, activeTab, JSON.stringify(extendingFilters)]);
|
|
57
|
+
useFetchData({
|
|
58
|
+
location,
|
|
59
|
+
getData,
|
|
60
|
+
activeTab,
|
|
61
|
+
extendingFilters,
|
|
62
|
+
subject: 'workers',
|
|
63
|
+
})
|
|
77
64
|
|
|
78
65
|
const selectFiltersConfig = useMemo(() => {
|
|
79
66
|
return getFiltersConfig({t});
|
|
@@ -6,6 +6,7 @@ import { useGetQueryParams } from '../../hooks/useGetQueryParams.js';
|
|
|
6
6
|
import StakeholdersCreate from './create.jsx';
|
|
7
7
|
import { displayMessage } from '../../../helpers/messages.js';
|
|
8
8
|
import DAFHeader from '../../core/components/Header/index.jsx';
|
|
9
|
+
import { useFetchData } from '../hook.js';
|
|
9
10
|
|
|
10
11
|
const StakeholdersTable = ({
|
|
11
12
|
t = () => {},
|
|
@@ -36,6 +37,7 @@ const StakeholdersTable = ({
|
|
|
36
37
|
applications = [],
|
|
37
38
|
subjectClear = () => {},
|
|
38
39
|
breadcrumbs = [],
|
|
40
|
+
extendingFilters = {},
|
|
39
41
|
}) => {
|
|
40
42
|
const [selectOptions, setSelectOptions] = useState();
|
|
41
43
|
const [activeTab, setActiveTab] = useState("own");
|
|
@@ -51,16 +53,13 @@ const StakeholdersTable = ({
|
|
|
51
53
|
applications,
|
|
52
54
|
}), [t, goTo, user, options, activeTab, getRedirectLink, theme, applications]);
|
|
53
55
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
tab: activeTab,
|
|
62
|
-
}, 'stakeholders')
|
|
63
|
-
}, [paginationQuery, otherParams, searchParams, activeTab]);
|
|
56
|
+
useFetchData({
|
|
57
|
+
location,
|
|
58
|
+
getData,
|
|
59
|
+
activeTab,
|
|
60
|
+
extendingFilters,
|
|
61
|
+
subject: 'stakeholders',
|
|
62
|
+
})
|
|
64
63
|
|
|
65
64
|
const selectFiltersConfig = useMemo(() => {
|
|
66
65
|
return getFiltersConfig({t});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
export const getKeyIndicatorsRowConfig = ({ t, data = {} }) => [
|
|
4
|
+
{
|
|
5
|
+
label: t('Region'),
|
|
6
|
+
render: () => {
|
|
7
|
+
// const region = data?.region;
|
|
8
|
+
return <div>{ '-'}</div>;
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
label: t('Associated Plots'),
|
|
13
|
+
render: () => {
|
|
14
|
+
// const plotsCount = data?.associatedPlotsCount || '0';
|
|
15
|
+
return <div>{'0'}</div>
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
label: t('Implementation Partners'),
|
|
20
|
+
render: () => {
|
|
21
|
+
// const partnersCount = data?.partnersCount || '0';
|
|
22
|
+
return <div>{'0'}</div>
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
label: t('Total Activities'),
|
|
27
|
+
render: () => {
|
|
28
|
+
// const activitiesCount = data?.activitiesCount || '0';
|
|
29
|
+
return <div>{'0'}</div>
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
label: t('Information Sources'),
|
|
34
|
+
render: () => {
|
|
35
|
+
// const sourcesCount = data?.informationSourcesCount || '0';
|
|
36
|
+
return <div>{'0'}</div>
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import L from "leaflet";
|
|
2
|
+
|
|
3
|
+
export const getMapDataFromActivity = (activityData, t) => {
|
|
4
|
+
const location = activityData?.location;
|
|
5
|
+
const perimeter = location?.perimeter;
|
|
6
|
+
|
|
7
|
+
const area = Array.isArray(perimeter) && perimeter.length > 0
|
|
8
|
+
? perimeter
|
|
9
|
+
.filter((coord) => Array.isArray(coord) && coord.length >= 2)
|
|
10
|
+
.map((coord) => {
|
|
11
|
+
const first = typeof coord[0] === 'number' ? coord[0] : parseFloat(coord[0]);
|
|
12
|
+
const second = typeof coord[1] === 'number' ? coord[1] : parseFloat(coord[1]);
|
|
13
|
+
|
|
14
|
+
if (isNaN(first) || isNaN(second) || !isFinite(first) || !isFinite(second)) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Try both formats and use Leaflet to validate
|
|
19
|
+
// First try as [lat, lng]
|
|
20
|
+
try {
|
|
21
|
+
const latLng1 = L.latLng(first, second);
|
|
22
|
+
if (latLng1.lat >= -90 && latLng1.lat <= 90 &&
|
|
23
|
+
latLng1.lng >= -180 && latLng1.lng <= 180) {
|
|
24
|
+
return [latLng1.lat, latLng1.lng];
|
|
25
|
+
}
|
|
26
|
+
} catch (e) {
|
|
27
|
+
// Not valid as [lat, lng], try swapping
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Try as [lng, lat] (GeoJSON format) - swap them
|
|
31
|
+
try {
|
|
32
|
+
const latLng2 = L.latLng(second, first);
|
|
33
|
+
if (latLng2.lat >= -90 && latLng2.lat <= 90 &&
|
|
34
|
+
latLng2.lng >= -180 && latLng2.lng <= 180) {
|
|
35
|
+
return [latLng2.lat, latLng2.lng];
|
|
36
|
+
}
|
|
37
|
+
} catch (e) {
|
|
38
|
+
// Invalid coordinates
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return null;
|
|
42
|
+
})
|
|
43
|
+
.filter((coord) => coord !== null)
|
|
44
|
+
: null;
|
|
45
|
+
|
|
46
|
+
const mapData = [];
|
|
47
|
+
const baseColor = '#15FFFFB2';
|
|
48
|
+
const locationName = location?.name || activityData?.name || t("Activity Location");
|
|
49
|
+
const datastakeId = location?.datastakeId || activityData?.datastakeId;
|
|
50
|
+
|
|
51
|
+
// Helper to validate coordinates
|
|
52
|
+
const isValidCoordinate = (coord) => {
|
|
53
|
+
const num = typeof coord === 'number' ? coord : parseFloat(coord);
|
|
54
|
+
return !isNaN(num) && isFinite(num);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// Entry 1: Perimeter polygon (independent - show if it exists)
|
|
58
|
+
if (area && area.length >= 3) {
|
|
59
|
+
mapData.push({
|
|
60
|
+
_id: {},
|
|
61
|
+
id: `${activityData?.id || activityData?.datastakeId || 'perimeter'}-perimeter`,
|
|
62
|
+
area: area,
|
|
63
|
+
color: baseColor,
|
|
64
|
+
name: locationName,
|
|
65
|
+
plotName: locationName,
|
|
66
|
+
territoryTitle: t("Associated Plot"),
|
|
67
|
+
subTitle: t("Activity Location"),
|
|
68
|
+
type: t("Activity Location"),
|
|
69
|
+
datastakeId: datastakeId,
|
|
70
|
+
sources: null,
|
|
71
|
+
link: null,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Entry 2: Arrival marker (independent - show if it exists)
|
|
76
|
+
const arrivalLat = activityData?.locationCheckArrival?.latitude;
|
|
77
|
+
const arrivalLng = activityData?.locationCheckArrival?.longitude;
|
|
78
|
+
if (isValidCoordinate(arrivalLat) && isValidCoordinate(arrivalLng)) {
|
|
79
|
+
mapData.push({
|
|
80
|
+
_id: {},
|
|
81
|
+
id: `${activityData?.id || activityData?.datastakeId || 'arrival'}-arrival`,
|
|
82
|
+
area: area && area.length >= 3 ? area : null,
|
|
83
|
+
color: baseColor,
|
|
84
|
+
gps: {
|
|
85
|
+
latitude: typeof arrivalLat === 'number' ? arrivalLat : parseFloat(arrivalLat),
|
|
86
|
+
longitude: typeof arrivalLng === 'number' ? arrivalLng : parseFloat(arrivalLng),
|
|
87
|
+
},
|
|
88
|
+
name: t("Activity Start"),
|
|
89
|
+
plotName: locationName,
|
|
90
|
+
territoryTitle: t("Associated Plot"),
|
|
91
|
+
datastakeId: `${datastakeId}-arrival`,
|
|
92
|
+
sources: null,
|
|
93
|
+
link: null,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Entry 3: Departure marker (independent - show if it exists)
|
|
98
|
+
const departureLat = activityData?.locationCheckDeparture?.latitude;
|
|
99
|
+
const departureLng = activityData?.locationCheckDeparture?.longitude;
|
|
100
|
+
if (isValidCoordinate(departureLat) && isValidCoordinate(departureLng)) {
|
|
101
|
+
mapData.push({
|
|
102
|
+
_id: {},
|
|
103
|
+
id: `${activityData?.id || activityData?.datastakeId || 'departure'}-departure`,
|
|
104
|
+
area: area && area.length >= 3 ? area : null,
|
|
105
|
+
color: baseColor,
|
|
106
|
+
gps: {
|
|
107
|
+
latitude: typeof departureLat === 'number' ? departureLat : parseFloat(departureLat),
|
|
108
|
+
longitude: typeof departureLng === 'number' ? departureLng : parseFloat(departureLng),
|
|
109
|
+
},
|
|
110
|
+
name: t("Activity End"),
|
|
111
|
+
plotName: locationName,
|
|
112
|
+
territoryTitle: t("Associated Plot"),
|
|
113
|
+
datastakeId: `${datastakeId}-departure`,
|
|
114
|
+
markerColor: "#FF7A45",
|
|
115
|
+
sources: null,
|
|
116
|
+
link: null,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return mapData;
|
|
121
|
+
};
|
|
122
|
+
|