datastake-daf 0.6.846 → 0.6.847
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/build/favicon.ico +0 -0
- package/build/logo192.png +0 -0
- package/build/logo512.png +0 -0
- package/build/manifest.json +25 -0
- package/build/robots.txt +3 -0
- package/dist/components/index.js +58 -16
- package/dist/hooks/index.js +10 -12
- package/dist/pages/index.js +4543 -4120
- package/dist/style/datastake/mapbox-gl.css +330 -0
- package/dist/utils/index.js +1 -9
- package/package.json +1 -1
- package/src/@daf/core/components/Screens/Admin/AdminModals/NewUser/index.jsx +1 -1
- package/src/@daf/core/components/Screens/Admin/AdminTables/AccountTable/helper.js +77 -59
- package/src/@daf/core/components/Screens/Admin/AdminViews/index.jsx +8 -1
- package/src/@daf/hooks/useSources.js +4 -6
- package/src/@daf/hooks/useWidgetFetch.js +40 -34
- package/src/@daf/pages/Dashboards/ConflictManagement/components/RisksWidget/components/IncidentsTime/config.js +0 -3
- package/src/@daf/pages/Dashboards/ConflictManagement/components/RisksWidget/components/IncidentsTime/hook.js +4 -69
- package/src/@daf/pages/Dashboards/ConflictManagement/components/RisksWidget/components/IncidentsTime/index.js +92 -29
- package/src/@daf/pages/Dashboards/ConflictManagement/components/RisksWidget/components/ProblemSolver/hook.js +34 -59
- package/src/@daf/pages/Dashboards/ConflictManagement/components/RisksWidget/components/ProblemSolver/index.js +69 -36
- package/src/@daf/pages/Dashboards/ConflictManagement/components/RisksWidget/components/TerritorialDistribution/index.js +75 -50
- package/src/@daf/pages/Dashboards/ConflictManagement/index.js +11 -11
- package/src/@daf/pages/Dashboards/SupplyChain/components/ChartsContainer/components/GenderDistribution/index.js +51 -46
- package/src/@daf/pages/Dashboards/SupplyChain/components/ChartsContainer/components/Identification/hook.js +20 -20
- package/src/@daf/pages/Dashboards/SupplyChain/components/ChartsContainer/components/Identification/index.js +2 -26
- package/src/@daf/pages/Dashboards/SupplyChain/index.jsx +1 -0
- package/src/@daf/pages/Dashboards/UserDashboard/components/DataChainOfCustody/index.jsx +1 -2
- package/src/@daf/pages/Dashboards/UserDashboard/index.jsx +0 -1
- package/src/@daf/pages/Dashboards/helper.js +20 -25
- package/src/@daf/utils/timeFilterUtils.js +250 -233
- package/src/constants/locales/fr/translation.js +0 -9
- package/src/constants/locales/sp/translation.js +0 -1
- package/src/@daf/pages/Dashboards/ConflictManagement/components/RisksWidget/components/TerritorialDistribution/hook.js +0 -56
|
@@ -2,251 +2,268 @@ import dayjs from 'dayjs';
|
|
|
2
2
|
import { capitalize } from '../../helpers/StringHelper.js';
|
|
3
3
|
import { renderNumber } from './numbers.js';
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* Formats a date based on the time filter
|
|
7
|
-
* @param {dayjs.Dayjs} date - The date to format
|
|
8
|
-
* @param {boolean} breakLine - Whether to add a line break (for tooltips)
|
|
9
|
-
* @param {string} timeFilter - The time filter ('daily', 'weekly', 'monthly', 'yearly')
|
|
10
|
-
* @returns {string} Formatted date string
|
|
11
|
-
*/
|
|
12
5
|
export const getFormatDate = (date, breakLine = false, timeFilter = 'monthly') => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
6
|
+
switch (timeFilter) {
|
|
7
|
+
case "daily":
|
|
8
|
+
return date.format("DD/MM");
|
|
9
|
+
case "weekly":
|
|
10
|
+
return `W${renderNumber(date.week())}`;
|
|
11
|
+
case "yearly":
|
|
12
|
+
return date.format("YYYY");
|
|
13
|
+
default:
|
|
14
|
+
// Monthly format: "Dec 24", "Jan 25", etc.
|
|
15
|
+
return breakLine
|
|
16
|
+
? `${capitalize(date.format("MMM"))}\n${date.format("YY")}`
|
|
17
|
+
: `${capitalize(date.format("MMM"))} ${date.format("YY")}`;
|
|
18
|
+
}
|
|
26
19
|
};
|
|
27
20
|
|
|
28
|
-
/**
|
|
29
|
-
* Gets the time quantity string for dayjs operations
|
|
30
|
-
* @param {string} timeFilter - The time filter ('daily', 'weekly', 'monthly', 'yearly')
|
|
31
|
-
* @returns {string} Time quantity string ('days', 'weeks', 'months', 'years')
|
|
32
|
-
*/
|
|
33
21
|
export const getTimeQuantity = (timeFilter = 'monthly') => {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
22
|
+
switch (timeFilter) {
|
|
23
|
+
case "daily":
|
|
24
|
+
return "days";
|
|
25
|
+
case "weekly":
|
|
26
|
+
return "weeks";
|
|
27
|
+
case "yearly":
|
|
28
|
+
return "years";
|
|
29
|
+
default:
|
|
30
|
+
return "months";
|
|
31
|
+
}
|
|
44
32
|
};
|
|
45
33
|
|
|
46
|
-
/**
|
|
47
|
-
* Gets previous cumulative score from data before start date
|
|
48
|
-
* @param {Array} dates - Array of data objects with date field
|
|
49
|
-
* @param {dayjs.Dayjs} startDate - The start date
|
|
50
|
-
* @param {string} timeFilter - The time filter
|
|
51
|
-
* @param {string} valueField - The field name to extract value from (default: 'total')
|
|
52
|
-
* @returns {Object} Object with hasPreviousData, previousCumulativeScore, previousMaxScore
|
|
53
|
-
*/
|
|
54
34
|
export const getPreviousGraphData = (dates, startDate, timeFilter, valueField = 'total') => {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
35
|
+
let previousCumulativeScore = 0;
|
|
36
|
+
let previousMaxScore = 0;
|
|
37
|
+
let hasPreviousData = false;
|
|
38
|
+
|
|
39
|
+
dates.forEach((d) => {
|
|
40
|
+
const date = dayjs(d.date, "YYYY-MM-DD");
|
|
41
|
+
if (!date.isValid()) return;
|
|
42
|
+
|
|
43
|
+
let isBeforeStart = false;
|
|
44
|
+
switch (timeFilter) {
|
|
45
|
+
case "daily":
|
|
46
|
+
isBeforeStart = date.isBefore(startDate, 'day');
|
|
47
|
+
break;
|
|
48
|
+
case "weekly":
|
|
49
|
+
isBeforeStart = date.isBefore(startDate, 'week');
|
|
50
|
+
break;
|
|
51
|
+
case "yearly":
|
|
52
|
+
isBeforeStart = date.isBefore(startDate, 'year');
|
|
53
|
+
break;
|
|
54
|
+
default:
|
|
55
|
+
isBeforeStart = date.isBefore(startDate, 'month');
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (isBeforeStart) {
|
|
60
|
+
hasPreviousData = true;
|
|
61
|
+
const value = Number(d[valueField] || d.count || d.jobs || d.value || 0) || 0;
|
|
62
|
+
previousCumulativeScore += value;
|
|
63
|
+
previousMaxScore = Math.max(previousMaxScore, value);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
hasPreviousData,
|
|
69
|
+
previousCumulativeScore,
|
|
70
|
+
previousMaxScore,
|
|
71
|
+
};
|
|
92
72
|
};
|
|
93
73
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
* @param {boolean} params.isCumulative - Whether to calculate cumulative values (default: false)
|
|
101
|
-
* @param {string} params.valueField - Field name to extract value from (default: 'total', also checks 'count', 'jobs', 'value')
|
|
102
|
-
* @returns {Array} Processed chart data array
|
|
103
|
-
*/
|
|
104
|
-
export const processChartDateData = ({
|
|
105
|
-
mainData,
|
|
106
|
-
timeFilter: filter,
|
|
107
|
-
filters = {},
|
|
108
|
-
isCumulative = false,
|
|
109
|
-
valueField = 'total'
|
|
74
|
+
export const processChartDateData = ({
|
|
75
|
+
mainData,
|
|
76
|
+
timeFilter: filter,
|
|
77
|
+
filters = {},
|
|
78
|
+
isCumulative = false,
|
|
79
|
+
valueField = 'total'
|
|
110
80
|
}) => {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
81
|
+
const timeQuantity = getTimeQuantity(filter);
|
|
82
|
+
const dates = mainData || [];
|
|
83
|
+
const isEmpty = !mainData || !Array.isArray(mainData) || mainData.length === 0;
|
|
84
|
+
|
|
85
|
+
const _data = [];
|
|
86
|
+
|
|
87
|
+
// Derive date range from actual data if no filters provided and data exists
|
|
88
|
+
let end, start;
|
|
89
|
+
|
|
90
|
+
if (filters?.timeframe?.endDate) {
|
|
91
|
+
end = filters.timeframe.endDate;
|
|
92
|
+
} else if (!isEmpty) {
|
|
93
|
+
// Find the latest date in the data
|
|
94
|
+
const sortedDates = dates
|
|
95
|
+
.map(d => dayjs(d.date, "YYYY-MM-DD"))
|
|
96
|
+
.filter(d => d.isValid())
|
|
97
|
+
.sort((a, b) => b.valueOf() - a.valueOf());
|
|
98
|
+
end = sortedDates.length > 0 ? sortedDates[0] : dayjs();
|
|
99
|
+
} else {
|
|
100
|
+
end = dayjs();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (filters?.timeframe?.startDate) {
|
|
104
|
+
start = filters.timeframe.startDate;
|
|
105
|
+
} else if (!isEmpty) {
|
|
106
|
+
// Find the earliest date in the data
|
|
107
|
+
const sortedDates = dates
|
|
108
|
+
.map(d => dayjs(d.date, "YYYY-MM-DD"))
|
|
109
|
+
.filter(d => d.isValid())
|
|
110
|
+
.sort((a, b) => a.valueOf() - b.valueOf());
|
|
111
|
+
start = sortedDates.length > 0 ? sortedDates[0] : dayjs().add(-12, timeQuantity);
|
|
112
|
+
|
|
113
|
+
// For daily filter, limit to last 14 days to avoid overcrowded x-axis
|
|
114
|
+
if (filter === "daily" && end) {
|
|
115
|
+
const maxDailyStart = end.subtract(13, 'days'); // 14 days total including end date
|
|
116
|
+
if (start.isBefore(maxDailyStart)) {
|
|
117
|
+
start = maxDailyStart;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
} else {
|
|
121
|
+
start = dayjs().add(-12, timeQuantity);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Normalize start and end to period boundaries
|
|
125
|
+
if (filter === "daily") {
|
|
126
|
+
start = start.startOf('day');
|
|
127
|
+
end = end.startOf('day');
|
|
128
|
+
} else if (filter === "weekly") {
|
|
129
|
+
start = start.startOf('week');
|
|
130
|
+
end = end.startOf('week');
|
|
131
|
+
} else if (filter === "yearly") {
|
|
132
|
+
start = start.startOf('year');
|
|
133
|
+
end = end.startOf('year');
|
|
134
|
+
} else {
|
|
135
|
+
start = start.startOf('month');
|
|
136
|
+
end = end.startOf('month');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Ensure minimum number of periods to fill the x-axis properly
|
|
140
|
+
const getMinPeriods = (f) => {
|
|
141
|
+
switch (f) {
|
|
142
|
+
case "daily": return 14; // At least 14 days
|
|
143
|
+
case "weekly": return 8; // At least 8 weeks
|
|
144
|
+
case "yearly": return 5; // At least 5 years
|
|
145
|
+
default: return 12; // At least 12 months
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
const minPeriods = getMinPeriods(filter);
|
|
149
|
+
const periodsDiff = end.diff(start, timeQuantity);
|
|
150
|
+
|
|
151
|
+
if (periodsDiff < minPeriods - 1) {
|
|
152
|
+
const periodsToAdd = minPeriods - 1 - periodsDiff;
|
|
153
|
+
start = start.subtract(periodsToAdd, timeQuantity);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
let i = 0;
|
|
157
|
+
let cumulativeScore = 0;
|
|
158
|
+
|
|
159
|
+
// Calculate initial cumulative value if needed
|
|
160
|
+
if (isCumulative) {
|
|
161
|
+
const { hasPreviousData, previousCumulativeScore } = getPreviousGraphData(
|
|
162
|
+
dates,
|
|
163
|
+
start,
|
|
164
|
+
filter,
|
|
165
|
+
valueField
|
|
166
|
+
);
|
|
167
|
+
cumulativeScore = hasPreviousData ? previousCumulativeScore : 0;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Get the period unit for comparison
|
|
171
|
+
const getPeriodUnit = (f) => {
|
|
172
|
+
switch (f) {
|
|
173
|
+
case "daily": return "day";
|
|
174
|
+
case "weekly": return "week";
|
|
175
|
+
case "yearly": return "year";
|
|
176
|
+
default: return "month";
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
const periodUnit = getPeriodUnit(filter);
|
|
180
|
+
|
|
181
|
+
// Loop until we reach the end date
|
|
182
|
+
let currentDate = start.clone();
|
|
183
|
+
while (currentDate.isBefore(end) || currentDate.isSame(end, periodUnit)) {
|
|
184
|
+
// Filter data points that fall within this period
|
|
185
|
+
const score = isEmpty ? 0 : dates
|
|
186
|
+
.filter((d) => {
|
|
187
|
+
if (!d.date) return false;
|
|
188
|
+
switch (filter) {
|
|
189
|
+
case "daily":
|
|
190
|
+
return d.date === currentDate.format("YYYY-MM-DD");
|
|
191
|
+
case "weekly":
|
|
192
|
+
return dayjs(d.date, "YYYY-MM-DD").week() === currentDate.week() &&
|
|
193
|
+
dayjs(d.date, "YYYY-MM-DD").year() === currentDate.year();
|
|
194
|
+
case "yearly":
|
|
195
|
+
return dayjs(d.date, "YYYY-MM-DD").year() === currentDate.year();
|
|
196
|
+
default:
|
|
197
|
+
return (
|
|
198
|
+
dayjs(d.date, "YYYY-MM-DD").format("YYYY-MM") ===
|
|
199
|
+
currentDate.format("YYYY-MM")
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
})
|
|
203
|
+
.reduce((a, b) => {
|
|
204
|
+
const value = Number(b[valueField] || b.count || b.jobs || b.value || 0) || 0;
|
|
205
|
+
return a + value;
|
|
206
|
+
}, 0);
|
|
207
|
+
|
|
208
|
+
if (isCumulative) {
|
|
209
|
+
cumulativeScore += score;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
_data.push({
|
|
213
|
+
date: getFormatDate(currentDate, false, filter),
|
|
214
|
+
value: isCumulative ? cumulativeScore : score,
|
|
215
|
+
period: score, // Period value for tooltip
|
|
216
|
+
jobs: score, // For compatibility with jobs field
|
|
217
|
+
month: currentDate.format('YYYY-MM-DD'), // For compatibility
|
|
218
|
+
key: i,
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
currentDate = currentDate.add(1, timeQuantity);
|
|
222
|
+
i++;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return _data;
|
|
204
226
|
};
|
|
205
227
|
|
|
206
|
-
/**
|
|
207
|
-
* Formats date axis labels, checking if already formatted
|
|
208
|
-
* @param {string} label - The label to format
|
|
209
|
-
* @param {Function} getFormatDateFn - Function to format dates
|
|
210
|
-
* @returns {string} Formatted date string
|
|
211
|
-
*/
|
|
212
228
|
export const formatDateAxis = (label, getFormatDateFn) => {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
229
|
+
if (!label) return label;
|
|
230
|
+
|
|
231
|
+
// Check if label is already in the correct format (MMM YY, DD/MM, W#, or YYYY)
|
|
232
|
+
// If it matches our format patterns, return as-is
|
|
233
|
+
if (typeof label === 'string') {
|
|
234
|
+
// Check for MMM YY format (e.g., "Dec 24", "Jan 25")
|
|
235
|
+
if (/^[A-Z][a-z]{2} \d{2}$/.test(label)) {
|
|
236
|
+
return label;
|
|
237
|
+
}
|
|
238
|
+
// Check for DD/MM format (e.g., "03/11")
|
|
239
|
+
if (/^\d{2}\/\d{2}$/.test(label)) {
|
|
240
|
+
return label;
|
|
241
|
+
}
|
|
242
|
+
// Check for W# format (e.g., "W1", "W12")
|
|
243
|
+
if (/^W\d+$/.test(label)) {
|
|
244
|
+
return label;
|
|
245
|
+
}
|
|
246
|
+
// Check for YYYY format (e.g., "2024", "2025")
|
|
247
|
+
if (/^\d{4}$/.test(label)) {
|
|
248
|
+
return label;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Otherwise, try to parse and format it
|
|
253
|
+
let date = dayjs(label);
|
|
254
|
+
|
|
255
|
+
// If first attempt fails, try parsing as ISO date string
|
|
256
|
+
if (!date.isValid() && typeof label === 'string') {
|
|
257
|
+
date = dayjs(label, ['YYYY-MM-DD', 'YYYY-MM', 'YYYY', 'MMM YY', 'MMM YYYY', 'DD/MM'], true);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// If it's a valid date, format it using getFormatDate
|
|
261
|
+
if (date.isValid() && getFormatDateFn) {
|
|
262
|
+
return getFormatDateFn(date, false);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Return as-is if we can't parse it
|
|
266
|
+
return label;
|
|
251
267
|
};
|
|
252
268
|
|
|
269
|
+
|
|
@@ -162,9 +162,6 @@ const fr = {
|
|
|
162
162
|
"under-development": "Under development",
|
|
163
163
|
"under-development-description": "Our team is actively building this feature. It will be available in an upcoming release.",
|
|
164
164
|
"Confirm new subject": "Confirmer nouveau sujet",
|
|
165
|
-
"registration":"Enregistrement",
|
|
166
|
-
"scrutiny":"Contrôle",
|
|
167
|
-
"Organisation Policies" : "Politiques Organisationnelles",
|
|
168
165
|
affirmations: {
|
|
169
166
|
"subject-created-successfully": "Sujet créé avec succès.",
|
|
170
167
|
"information-saved-successfully": "Information sauvegardée avec succès.",
|
|
@@ -2192,12 +2189,6 @@ const fr = {
|
|
|
2192
2189
|
"last-active": "Dernière Activité",
|
|
2193
2190
|
"key-indicators": "Indicateurs Clés",
|
|
2194
2191
|
},
|
|
2195
|
-
"Armed Groups": "Groupes Armés",
|
|
2196
|
-
"Identified Armed Groups":"Groupes Armés Identifiés",
|
|
2197
|
-
"Reported Incidents": "Incidents Signalés",
|
|
2198
|
-
"Conflict Map":"Carte des Conflits",
|
|
2199
|
-
"Conflict Management": "Gestion des Conflits"
|
|
2200
|
-
|
|
2201
2192
|
};
|
|
2202
2193
|
|
|
2203
2194
|
export default fr;
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
|
-
import { getColors } from './config.js';
|
|
3
|
-
import { useWidgetFetch } from '../../../../../../../hooks/useWidgetFetch.js';
|
|
4
|
-
|
|
5
|
-
export const useTerritorialDistribution = ({
|
|
6
|
-
category,
|
|
7
|
-
selectedRange,
|
|
8
|
-
selectedPartners,
|
|
9
|
-
theme,
|
|
10
|
-
}) => {
|
|
11
|
-
const colors = getColors(theme);
|
|
12
|
-
|
|
13
|
-
const defaultFetchConfig = useMemo(
|
|
14
|
-
() => ({
|
|
15
|
-
url: "/territorial-distribution",
|
|
16
|
-
basepath: "dashboard/conflict-management",
|
|
17
|
-
filters: {
|
|
18
|
-
category,
|
|
19
|
-
period: selectedRange,
|
|
20
|
-
sources: selectedPartners?.partners || [],
|
|
21
|
-
},
|
|
22
|
-
defaultData: {},
|
|
23
|
-
stop: selectedPartners?.loading,
|
|
24
|
-
}),
|
|
25
|
-
[category, selectedRange, selectedPartners],
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
const { data, loading } = useWidgetFetch({ config: defaultFetchConfig });
|
|
29
|
-
|
|
30
|
-
const pieData = useMemo(() => {
|
|
31
|
-
if (!data || Array.isArray(data)) return [];
|
|
32
|
-
const all = Object.keys(data);
|
|
33
|
-
const totalEvents = all.reduce((acc, key) => acc + (data[key]?.events?.length || 0), 0);
|
|
34
|
-
|
|
35
|
-
return all
|
|
36
|
-
.sort((a, b) => (data[b]?.events?.length || 0) - (data[a]?.events?.length || 0))
|
|
37
|
-
.map((key, index) => {
|
|
38
|
-
const item = data[key];
|
|
39
|
-
return {
|
|
40
|
-
value: item?.events?.length,
|
|
41
|
-
label: item?.locationData?.name,
|
|
42
|
-
locationData: item?.locationData,
|
|
43
|
-
color: colors[index % colors.length],
|
|
44
|
-
percent: totalEvents ? (item?.events?.length / totalEvents) : 0,
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
}, [data, colors]);
|
|
48
|
-
|
|
49
|
-
const isEmpty = !pieData.length;
|
|
50
|
-
|
|
51
|
-
return {
|
|
52
|
-
pieData,
|
|
53
|
-
loading,
|
|
54
|
-
isEmpty,
|
|
55
|
-
}
|
|
56
|
-
}
|