ptechcore_ui 0.0.0
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/eslint.config.js +28 -0
- package/index.html +78 -0
- package/package.json +42 -0
- package/postcss.config.js +6 -0
- package/src/App.tsx +156 -0
- package/src/assets/imgs/login_illustration.png +0 -0
- package/src/components/common/Buttons.tsx +39 -0
- package/src/components/common/Cards.tsx +18 -0
- package/src/components/common/FDrawer.tsx +2448 -0
- package/src/components/common/FDrawer.types.ts +191 -0
- package/src/components/common/Inputs.tsx +409 -0
- package/src/components/common/Modals.tsx +41 -0
- package/src/components/common/Navigations.tsx +0 -0
- package/src/components/common/Toast.tsx +0 -0
- package/src/components/demo/ToastDemo.tsx +73 -0
- package/src/components/layout/Header.tsx +202 -0
- package/src/components/layout/ModernDoubleSidebarLayout.tsx +727 -0
- package/src/components/layout/PrivateLayout.tsx +52 -0
- package/src/components/layout/Sidebar.tsx +182 -0
- package/src/components/ui/Toast.tsx +93 -0
- package/src/contexts/SessionContext.tsx +77 -0
- package/src/contexts/ThemeContext.tsx +58 -0
- package/src/contexts/ToastContext.tsx +94 -0
- package/src/index.css +3 -0
- package/src/main.tsx +10 -0
- package/src/models/Organization.ts +47 -0
- package/src/models/Plan.ts +42 -0
- package/src/models/User.ts +23 -0
- package/src/pages/Analytics.tsx +101 -0
- package/src/pages/CreateOrganization.tsx +215 -0
- package/src/pages/Dashboard.tsx +15 -0
- package/src/pages/Home.tsx +12 -0
- package/src/pages/Profile.tsx +313 -0
- package/src/pages/Settings.tsx +382 -0
- package/src/pages/Team.tsx +180 -0
- package/src/pages/auth/Login.tsx +140 -0
- package/src/pages/auth/Register.tsx +302 -0
- package/src/pages/organizations/DetailEntity.tsx +1002 -0
- package/src/pages/organizations/DetailOrganizations.tsx +1629 -0
- package/src/pages/organizations/ListOrganizations.tsx +270 -0
- package/src/pages/pricings/CartPlan.tsx +486 -0
- package/src/pages/pricings/ListPricing.tsx +321 -0
- package/src/pages/users/CreateUser.tsx +450 -0
- package/src/pages/users/ListUsers.tsx +0 -0
- package/src/services/AuthServices.ts +94 -0
- package/src/services/OrganizationServices.ts +61 -0
- package/src/services/PlanSubscriptionServices.tsx +137 -0
- package/src/services/UserServices.ts +36 -0
- package/src/services/api.ts +64 -0
- package/src/styles/theme.ts +383 -0
- package/src/utils/utils.ts +48 -0
- package/src/vite-env.d.ts +1 -0
- package/tailwind.config.js +158 -0
- package/tsconfig.app.json +24 -0
- package/tsconfig.json +7 -0
- package/tsconfig.node.json +22 -0
- package/vite.config.ts +10 -0
|
@@ -0,0 +1,2448 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import React, { useEffect, useMemo, useRef, useState, ReactNode } from 'react';
|
|
3
|
+
import {
|
|
4
|
+
FDrawerProps,
|
|
5
|
+
FooterSummaryProps,
|
|
6
|
+
DropdownActionsMenuProps,
|
|
7
|
+
TableCollapseSimpleProps,
|
|
8
|
+
FTableProps,
|
|
9
|
+
DynamicTableProps,
|
|
10
|
+
ReponseDetail,
|
|
11
|
+
FDrawerHeader,
|
|
12
|
+
Filter,
|
|
13
|
+
ActionItem
|
|
14
|
+
} from './FDrawer.types';
|
|
15
|
+
// import ALL_FORMS from '../../modules/admin/crm/views/forms/allform';
|
|
16
|
+
import { addressIpApi, authenticated_header } from '../../globals/api';
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
import {
|
|
20
|
+
bouttonDrawerAdd,
|
|
21
|
+
activeBouttonDrawerAdd,
|
|
22
|
+
activeBouttonDrawerFilter,
|
|
23
|
+
activeBouttonDrawerSearch,
|
|
24
|
+
bouttonDrawerFilter,
|
|
25
|
+
bouttonDrawerSearch,
|
|
26
|
+
bouttonDrawerValidateSearch,
|
|
27
|
+
activebouttonDrawerIssuePayment,
|
|
28
|
+
bouttonDrawerIssuePayment,
|
|
29
|
+
bouttonDrawerCreateTemplate,
|
|
30
|
+
activebouttonDrawerCreateTemplate,
|
|
31
|
+
activebouttonDrawerNewEntry,
|
|
32
|
+
bouttonDrawerNewEntry,
|
|
33
|
+
activebouttonDrawerReceivePayment,
|
|
34
|
+
bouttonDrawerReceivePayment,
|
|
35
|
+
activebouttonDrawerInputTemplate,
|
|
36
|
+
bouttonDrawerInputTemplate,
|
|
37
|
+
activeBouttonDrawerImportation_cancel,
|
|
38
|
+
activeBouttonDrawerImportation,
|
|
39
|
+
bouttonDrawerImportation_cancel,
|
|
40
|
+
bouttonDrawerImportation,
|
|
41
|
+
activebouttonDrawerExcelExport,
|
|
42
|
+
bouttonDrawerexcelExport,
|
|
43
|
+
bouttonDrawerCancel,
|
|
44
|
+
activebouttonDrawerCancel,
|
|
45
|
+
|
|
46
|
+
bouttonDrawerPrevisualisation,
|
|
47
|
+
activebouttonDrawerPrevisualisation,
|
|
48
|
+
bouttonDrawerPrinter,
|
|
49
|
+
activebouttonDrawerPrinter,
|
|
50
|
+
bouttonDrawerSubmit,
|
|
51
|
+
activebouttonDrawerSubmit,
|
|
52
|
+
bouttonDrawerAttachement,
|
|
53
|
+
activebouttonDrawerAttachement,
|
|
54
|
+
bouttonDrawerMessagerie,
|
|
55
|
+
activebouttonDrawerMessagerie,
|
|
56
|
+
bouttonDrawerEnregistrer,
|
|
57
|
+
activebouttonDrawerEnregistrer,
|
|
58
|
+
activebouttonDrawerExcelImport,
|
|
59
|
+
bouttonDrawerexcelImport,
|
|
60
|
+
table_com_icon,
|
|
61
|
+
table_com_icon2,
|
|
62
|
+
activebouttonDrawerConsult,
|
|
63
|
+
bouttonDrawerConsult,
|
|
64
|
+
bouttonDrawerattachHaving,
|
|
65
|
+
activebouttonDrawerAttachHaving,
|
|
66
|
+
bouttonDrawerAttachLight,
|
|
67
|
+
activebouttonDrawerAttachLight
|
|
68
|
+
} from "../../assets/images/ExportImage";
|
|
69
|
+
import { useLoading } from '../../globals/globals_loading';
|
|
70
|
+
import { Link, useLocation, useNavigate, useSearchParams } from 'react-router-dom';
|
|
71
|
+
import { useCenter } from '../footer/Footer';
|
|
72
|
+
import { DICTIONNARY, useLanguage } from '../../globals/dictionnary';
|
|
73
|
+
import { FilterPagination } from '../pagination';
|
|
74
|
+
import { DATETIME } from '../../utils/dates';
|
|
75
|
+
import { CustomSelector } from '../CustomSelector';
|
|
76
|
+
import { nodata_illus } from '../../assets/images/ExportImage';
|
|
77
|
+
import { NewButton } from '../buttons/buttons';
|
|
78
|
+
import { useDownloadExcel } from 'react-export-table-to-excel';
|
|
79
|
+
import { FModal, ModelTemplapleSimpleV1 } from '../modal/ModalGlobalTemplate';
|
|
80
|
+
import { CommunicationHistoryComponent } from '../CommunicationHistory';
|
|
81
|
+
import { Attachments } from '../attachment/Attachment';
|
|
82
|
+
import { DynamicTable, TableBasic, TableCollapseSimple, TableWithCheckbox } from './fTables';
|
|
83
|
+
import { CheckboxInput } from '../form-inputs/FormInputs';
|
|
84
|
+
import { LuSearch, LuSearchX, LuPlusCircle } from 'react-icons/lu';
|
|
85
|
+
import { sep_mil } from '../../modules/admin/recovery/views/constants/choices_handle';
|
|
86
|
+
import { FDropdown } from './fUI';
|
|
87
|
+
import { IoCloseCircleSharp } from 'react-icons/io5';
|
|
88
|
+
import { PiColumnsFill } from 'react-icons/pi';
|
|
89
|
+
import { CustomFieldset } from '../custom-card/CustomCard';
|
|
90
|
+
import { CiBank } from 'react-icons/ci';
|
|
91
|
+
import { ExcelImportModal } from './ExcelImportModal';
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
export const FDrawer: React.FC<FDrawerProps> = (props) => {
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
// ---------------------------------CUSTOM HOOKS------------------------------
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
|
|
103
|
+
const navigate = useNavigate();
|
|
104
|
+
const [searchParams] = useSearchParams();
|
|
105
|
+
const location = useLocation();
|
|
106
|
+
|
|
107
|
+
const allParams = Object.fromEntries([...searchParams]);
|
|
108
|
+
const { center, dateRange, changeRange, financialYear, dateSystem } = useCenter();
|
|
109
|
+
const { language } = useLanguage();
|
|
110
|
+
const { setIsLoadingCancelable } = useLoading()
|
|
111
|
+
|
|
112
|
+
// ---------------------------------------------------------------------------
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
|
|
115
|
+
// ---------------------------------------------------------------------------
|
|
116
|
+
// ---------------------------------REFS--------------------------------------
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
|
|
119
|
+
const champsRef = useRef([]);
|
|
120
|
+
const champsRef2 = useRef([]);
|
|
121
|
+
const searchSelect = useRef();
|
|
122
|
+
const btnsContainer = useRef();
|
|
123
|
+
const sweetAlertRef = useRef();
|
|
124
|
+
const tableRefExportExcel = useRef(null);
|
|
125
|
+
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
// ---------------------------------DEFAULT PROPS-----------------------------
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
|
|
137
|
+
const selected = props.selected ?? []
|
|
138
|
+
|
|
139
|
+
const maxText = props.maxText ?? 75
|
|
140
|
+
|
|
141
|
+
const type = props.type ?? "table"
|
|
142
|
+
|
|
143
|
+
const noFilter = props.noFilter ?? false
|
|
144
|
+
|
|
145
|
+
const noSearch = props.noSearch ?? false
|
|
146
|
+
const canExport = props.canExport ?? false
|
|
147
|
+
|
|
148
|
+
const table_type = props.table_type ?? "basic"
|
|
149
|
+
|
|
150
|
+
const rerender = props.toggle ?? "";
|
|
151
|
+
|
|
152
|
+
const headers = props.headers ?? [];
|
|
153
|
+
|
|
154
|
+
const totalHeaders = props.totalHeaders ?? [];
|
|
155
|
+
|
|
156
|
+
const totalMainHeaders = props.totalMainHeaders ?? [];
|
|
157
|
+
|
|
158
|
+
const btnsList = props.btnsList ?? [];
|
|
159
|
+
|
|
160
|
+
const infinite_scroll = props.infinite_scroll ?? false;
|
|
161
|
+
|
|
162
|
+
const title_ = (props.title && typeof (props.title) === "string") ? props.title as string : props.title_;
|
|
163
|
+
|
|
164
|
+
// ---------------------------------------------------------------------------
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
const [showPeriodModal, setShowPeriodModal] = useState(false);
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
// ---------------------------------STATES-----------------------------------
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
|
|
177
|
+
const [lineSelected, setLineSelected] = useState<string>('')
|
|
178
|
+
const [showContent, setShowContent] = useState<Record<string, boolean>>({});
|
|
179
|
+
const [showModalComment, setShowModalComment] = useState<boolean>(false);
|
|
180
|
+
const [secondInfoComment, setSecondInfoComment] = useState<string>("");
|
|
181
|
+
const [comment, setComment] = useState<any>(false);
|
|
182
|
+
const [showLeadForm, setShowLeadForm] = useState<boolean>(false);
|
|
183
|
+
const [isSorting, setIsSorting] = useState<string | undefined>(props.orderByDefault);
|
|
184
|
+
const [data, setData] = useState<any[]>([]);
|
|
185
|
+
const [dataFilters, setDataFilters] = useState<any[]>([]);
|
|
186
|
+
const [noFiltres, setNoFiltres] = useState<boolean>(false);
|
|
187
|
+
const [showFiltres, setShowFiltres] = useState<boolean>(false);
|
|
188
|
+
const [showRecherche, setShowRecherche] = useState<boolean>(false);
|
|
189
|
+
const [showFR, setShowFR] = useState<string>("");
|
|
190
|
+
const [filtres, setFiltres] = useState<Filter[]>([]);
|
|
191
|
+
const [csv, setCsv] = useState<string>("");
|
|
192
|
+
const [legends, setLegends] = useState<any[]>([]);
|
|
193
|
+
const [listFiltres, setListFiltres] = useState<any[]>([]);
|
|
194
|
+
const [loading, setLoading] = useState<boolean>(true);
|
|
195
|
+
const [loadingIS, setLoadingIS] = useState<boolean>(true);
|
|
196
|
+
const [loading2, setLoading2] = useState<boolean>(true);
|
|
197
|
+
const [queryURL, setQueryURL] = useState<string>('');
|
|
198
|
+
const [frontqueryURL, setFrontQueryURL] = useState<string>('');
|
|
199
|
+
const [showCommunication, setShowCommunication] = useState<boolean>(false);
|
|
200
|
+
const [showAttachments, setShowAttachments] = useState<boolean>(false);
|
|
201
|
+
const [showImportExcel, setShowImportExcel] = useState<boolean>(false);
|
|
202
|
+
const [attachments, setAttachments] = useState<any[]>([])
|
|
203
|
+
const [search, setSearch] = useState<string>('');
|
|
204
|
+
const [selectedItems, setSelectedItems] = useState<string[]>([]);
|
|
205
|
+
const [btnAdd, setBtnAdd] = useState<boolean>(true);
|
|
206
|
+
const [reponseDetail, setReponseDetail] = useState<ReponseDetail>({
|
|
207
|
+
total_pages: null,
|
|
208
|
+
previous: null,
|
|
209
|
+
next: null,
|
|
210
|
+
current_page: null,
|
|
211
|
+
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
const makeFilters = (): Record<string, string> => {
|
|
215
|
+
const newFilters = headers.reduce<Record<string, string>>((acc, item) => {
|
|
216
|
+
if (item.formule) {
|
|
217
|
+
acc[`${item.search_name}__icontains`] = ""
|
|
218
|
+
return acc
|
|
219
|
+
} else {
|
|
220
|
+
acc[`${item.key}__icontains`] = ""
|
|
221
|
+
return acc
|
|
222
|
+
}
|
|
223
|
+
}, {})
|
|
224
|
+
return newFilters
|
|
225
|
+
}
|
|
226
|
+
const preFilters = (headers.length) > 0 ? makeFilters() : {}
|
|
227
|
+
|
|
228
|
+
// Définir les filtres initiaux en fonction de la présence de paramètres dans l'URL
|
|
229
|
+
const [filters, setFilters] = useState<Record<string, any>>(() => {
|
|
230
|
+
if (Object.keys(allParams).length > 0) {
|
|
231
|
+
return allParams; // Si des paramètres existent, on les utilise comme filtres
|
|
232
|
+
} else {
|
|
233
|
+
return {
|
|
234
|
+
...preFilters,
|
|
235
|
+
center_id: center?.id ?? null,
|
|
236
|
+
order_by: props.orderByDefault ?? "id",
|
|
237
|
+
page: 1
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
const [filtersMemo, setFiltersMemo] = useState<Record<string, any>>({
|
|
243
|
+
...preFilters,
|
|
244
|
+
center_id: center?.id ?? null,
|
|
245
|
+
order_by: props.orderByDefault ?? "id",
|
|
246
|
+
page: 1
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
// ---------------------------------------------------------------------------
|
|
250
|
+
// ---------------------------------------------------------------------------
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
// ---------------------------------------------------------------------------
|
|
256
|
+
// ---------------------------------CONSTANTES--------------------------------
|
|
257
|
+
// ---------------------------------------------------------------------------
|
|
258
|
+
|
|
259
|
+
const drawerActions = {
|
|
260
|
+
"add": {
|
|
261
|
+
icon: [bouttonDrawerAdd, activeBouttonDrawerAdd],
|
|
262
|
+
label: DICTIONNARY.Add[language]
|
|
263
|
+
},
|
|
264
|
+
"create-template": {
|
|
265
|
+
icon: [bouttonDrawerCreateTemplate, activebouttonDrawerCreateTemplate],
|
|
266
|
+
label: DICTIONNARY.CréerUnModèleDeSaisie[language]
|
|
267
|
+
},
|
|
268
|
+
"issue-payment": {
|
|
269
|
+
icon: [bouttonDrawerIssuePayment, activebouttonDrawerIssuePayment],
|
|
270
|
+
label: DICTIONNARY.EmettreUnRéglement[language]
|
|
271
|
+
},
|
|
272
|
+
"receive-payment": {
|
|
273
|
+
icon: [bouttonDrawerReceivePayment, activebouttonDrawerReceivePayment],
|
|
274
|
+
label: DICTIONNARY.RecevoirUnRéglement[language]
|
|
275
|
+
},
|
|
276
|
+
"input-template": {
|
|
277
|
+
icon: [bouttonDrawerInputTemplate, activebouttonDrawerInputTemplate],
|
|
278
|
+
label: DICTIONNARY.SélectionnerUnModèleDeSaisie[language]
|
|
279
|
+
},
|
|
280
|
+
"import-new-report": {
|
|
281
|
+
icon: [bouttonDrawerImportation, activeBouttonDrawerImportation],
|
|
282
|
+
label: DICTIONNARY.ImportReport[language]
|
|
283
|
+
},
|
|
284
|
+
"import-cancel-new-report": {
|
|
285
|
+
icon: [bouttonDrawerImportation_cancel, activeBouttonDrawerImportation_cancel],
|
|
286
|
+
label: DICTIONNARY.CancelImportReport[language]
|
|
287
|
+
},
|
|
288
|
+
"cancel": {
|
|
289
|
+
icon: [bouttonDrawerCancel, activebouttonDrawerCancel],
|
|
290
|
+
label: DICTIONNARY.Cancel[language]
|
|
291
|
+
},
|
|
292
|
+
// "edit": {
|
|
293
|
+
// icon: [bouttonDrawerEdit, activebouttonDrawerEdit],
|
|
294
|
+
// label: DICTIONNARY.Edit[language]
|
|
295
|
+
// },
|
|
296
|
+
"previsualisation": {
|
|
297
|
+
icon: [bouttonDrawerPrevisualisation, activebouttonDrawerPrevisualisation],
|
|
298
|
+
label: DICTIONNARY.Previews[language]
|
|
299
|
+
},
|
|
300
|
+
"submit": {
|
|
301
|
+
icon: [bouttonDrawerSubmit, activebouttonDrawerSubmit],
|
|
302
|
+
label: DICTIONNARY.Soumettre[language]
|
|
303
|
+
},
|
|
304
|
+
"send": {
|
|
305
|
+
icon: [<RiMailSendFill />],
|
|
306
|
+
label: DICTIONNARY.Send[language]
|
|
307
|
+
},
|
|
308
|
+
"new-entry": {
|
|
309
|
+
icon: [bouttonDrawerNewEntry, activebouttonDrawerNewEntry],
|
|
310
|
+
label: DICTIONNARY.NouvelleSaisie[language]
|
|
311
|
+
},
|
|
312
|
+
"print": {
|
|
313
|
+
icon: [bouttonDrawerPrinter, activebouttonDrawerPrinter],
|
|
314
|
+
label: DICTIONNARY.Print[language]
|
|
315
|
+
},
|
|
316
|
+
"mark-as-signed": {
|
|
317
|
+
icon: [<FaFileSignature />],
|
|
318
|
+
label: DICTIONNARY.MarkAsSigned[language]
|
|
319
|
+
},
|
|
320
|
+
"closed": {
|
|
321
|
+
icon: [<FaStamp />],
|
|
322
|
+
label: DICTIONNARY.Closing[language]
|
|
323
|
+
},
|
|
324
|
+
"export-excel": {
|
|
325
|
+
icon: [<FaFileExport />],
|
|
326
|
+
label: DICTIONNARY.ExportExcel[language]
|
|
327
|
+
},
|
|
328
|
+
"save": {
|
|
329
|
+
icon: [bouttonDrawerEnregistrer, activebouttonDrawerEnregistrer],
|
|
330
|
+
label: DICTIONNARY.Save[language]
|
|
331
|
+
},
|
|
332
|
+
"attach-having": {
|
|
333
|
+
icon: [bouttonDrawerattachHaving, activebouttonDrawerAttachHaving],
|
|
334
|
+
label: DICTIONNARY.LinkCreditMemoInvoices[language]
|
|
335
|
+
},
|
|
336
|
+
"attach-having-transfer": {
|
|
337
|
+
icon: [bouttonDrawerAttachLight, activebouttonDrawerAttachLight],
|
|
338
|
+
label: DICTIONNARY.LinkingInvoicesToTheAccounts[language]
|
|
339
|
+
},
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// ---------------------------------------------------------------------------
|
|
343
|
+
// ---------------------------------------------------------------------------
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
// ---------------------------------------------------------------------------
|
|
349
|
+
// ---------------------------------FONCTIONS---------------------------------
|
|
350
|
+
// ---------------------------------------------------------------------------
|
|
351
|
+
|
|
352
|
+
const toggleContent = (propertyCode) => {
|
|
353
|
+
setShowContent((prevShowContent) => {
|
|
354
|
+
const newShowContent = {
|
|
355
|
+
...prevShowContent,
|
|
356
|
+
[propertyCode]: !prevShowContent[propertyCode],
|
|
357
|
+
};
|
|
358
|
+
return newShowContent;
|
|
359
|
+
});
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
const handleFilterChange = (event) => {
|
|
363
|
+
const { name, value } = event.target;
|
|
364
|
+
setFilters({ ...filters, [name]: value });
|
|
365
|
+
}
|
|
366
|
+
const handleFilterFilterChange = (event) => {
|
|
367
|
+
const { name, value } = event.target;
|
|
368
|
+
setFilters({ ...filters, search_type: 'filter', [name]: value });
|
|
369
|
+
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const handleRemoveItem = (itemToRemove) => {
|
|
373
|
+
setSelectedItems(prevItems => prevItems.filter(item => item !== itemToRemove));
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
const handleSelectedItem = (event) => {
|
|
377
|
+
const selectedItem = event.target.value;
|
|
378
|
+
setSelectedItems(prevItems => {
|
|
379
|
+
if (!prevItems.includes(selectedItem)) {
|
|
380
|
+
return [...prevItems, selectedItem];
|
|
381
|
+
}
|
|
382
|
+
return prevItems;
|
|
383
|
+
});
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
const handleClick = (value) => {
|
|
387
|
+
if (showFR === value) {
|
|
388
|
+
setShowFR('')
|
|
389
|
+
} else {
|
|
390
|
+
setShowFR(value);
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
const getDataFilter = async () => {
|
|
395
|
+
if (props.api) {
|
|
396
|
+
setLoading(true)
|
|
397
|
+
try {
|
|
398
|
+
const response = await fetch(queryURL, {
|
|
399
|
+
method: 'GET',
|
|
400
|
+
headers: authenticated_header()
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
if (!response.ok) {
|
|
404
|
+
throw new Error(`HTTP ERROR! STATUS: ${response.status}`);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const data = await response.json();
|
|
408
|
+
setReponseDetail(data)
|
|
409
|
+
setDataFilters(data.results)
|
|
410
|
+
setLoading(false)
|
|
411
|
+
} catch (error) {
|
|
412
|
+
console.error('ERROR FETCHING DATA', error);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
const getData = async () => {
|
|
418
|
+
if (props.api) {
|
|
419
|
+
setLoading2(true)
|
|
420
|
+
try {
|
|
421
|
+
const response = await fetch(`${addressIpApi}${props.api}?all=true¢er_id=${center?.id ?? null}&date_system=${dateSystem ? DATETIME.formatYYYYMMDD(dateSystem) : `${Date().getFullYear()}-12-31`}&year=${financialYear ?? new Date().getFullYear()}${props.additional_params ?? ''}`, {
|
|
422
|
+
method: 'GET',
|
|
423
|
+
headers: authenticated_header()
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
if (!response.ok) {
|
|
427
|
+
throw new Error('Error fetching data');
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
const data = await response.json();
|
|
431
|
+
setData(data.data)
|
|
432
|
+
const listFilter = []
|
|
433
|
+
for (let idx = 0; idx < headers.length; idx++) {
|
|
434
|
+
if (headers[idx].filterable) {
|
|
435
|
+
listFilter.push(data.data.map(item => ({ id: item.id, name: headers[idx].formule ? headers[idx].formule(item) : item[`${headers[idx].key}`] })))
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
setListFiltres(listFilter)
|
|
439
|
+
setLoading2(false)
|
|
440
|
+
|
|
441
|
+
} catch (error) {
|
|
442
|
+
console.error('Error fetching data:', error);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
const deleteData = async (id) => {
|
|
448
|
+
|
|
449
|
+
const answer = await sweetAlertRef.current.afficherConfirmation(
|
|
450
|
+
'Voulez-vous supprimer ce prospect?',
|
|
451
|
+
'Oui',
|
|
452
|
+
'Annuler'
|
|
453
|
+
);
|
|
454
|
+
|
|
455
|
+
if (answer) {
|
|
456
|
+
try {
|
|
457
|
+
await axios.delete(`${addressIpApi}/crm/lead-genuis/prospects/${id}`, {
|
|
458
|
+
headers: authenticated_header()
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
sweetAlertRef.current.afficherAlerte('success', 'prospect supprimé.');
|
|
462
|
+
getData();
|
|
463
|
+
|
|
464
|
+
} catch (error) {
|
|
465
|
+
sweetAlertRef.current.afficherAlerte('error', 'Une erreur est survenue lors de la suppression');
|
|
466
|
+
console.error("Error saving fund call:", error);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
const markascomplete = async (item) => {
|
|
472
|
+
const answer = await sweetAlertRef.current.afficherConfirmation(
|
|
473
|
+
'Voulez-vous achevez la procedure de ce prospect?',
|
|
474
|
+
'Oui',
|
|
475
|
+
'Annuler'
|
|
476
|
+
);
|
|
477
|
+
|
|
478
|
+
if (answer) {
|
|
479
|
+
if (item.qualified && !item.completed) {
|
|
480
|
+
fetch(
|
|
481
|
+
`${addressIpApi}/crm/lead-genuis/prospects/${item.id}/markascomplete/`,
|
|
482
|
+
{
|
|
483
|
+
method: "PUT",
|
|
484
|
+
headers: authenticated_header(),
|
|
485
|
+
body: JSON.stringify({
|
|
486
|
+
lead_id: item.id,
|
|
487
|
+
}),
|
|
488
|
+
}
|
|
489
|
+
)
|
|
490
|
+
.then((response) => response.json())
|
|
491
|
+
.then((rep_data) => {
|
|
492
|
+
if (rep_data.success) {
|
|
493
|
+
sweetAlertRef.current.afficherAlerte('success', 'procedure achevée.');
|
|
494
|
+
const dup_data = [...data]
|
|
495
|
+
const itemIndex = dup_data.findIndex((o) => o.id === item.id)
|
|
496
|
+
if (itemIndex >= 0) {
|
|
497
|
+
dup_data[itemIndex].completed = true
|
|
498
|
+
}
|
|
499
|
+
setData(dup_data)
|
|
500
|
+
} else {
|
|
501
|
+
sweetAlertRef.current.afficherAlerte('error', `une erreur est survenue. Veuillez reessayer`);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
})
|
|
506
|
+
.catch((error) => {
|
|
507
|
+
console.error("Error:", error);
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
} else {
|
|
511
|
+
sweetAlertRef.current.afficherAlerte('error', `veuillez achevez la qualification`);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
const exportDateToExcelFile = async () => {
|
|
519
|
+
console.log('billing data.xlsx');
|
|
520
|
+
|
|
521
|
+
try {
|
|
522
|
+
|
|
523
|
+
const params = new URLSearchParams({...filters,export:'true'}).toString();
|
|
524
|
+
const QueryURL= `${addressIpApi}${props.api}?${params}&date_system=${dateSystem ? DATETIME.formatYYYYMMDD(dateSystem) : `${Date().getFullYear()}-12-31`}&year=${financialYear ?? new Date().getFullYear()}${props.additional_params ?? ''}`;
|
|
525
|
+
setIsLoadingCancelable(true);
|
|
526
|
+
|
|
527
|
+
// ${params}
|
|
528
|
+
const response = await axios.get(QueryURL,
|
|
529
|
+
{
|
|
530
|
+
headers: authenticated_header(),
|
|
531
|
+
|
|
532
|
+
responseType: 'blob',
|
|
533
|
+
}
|
|
534
|
+
);
|
|
535
|
+
setIsLoadingCancelable(false);
|
|
536
|
+
|
|
537
|
+
const url = window.URL.createObjectURL(new Blob([response.data]));
|
|
538
|
+
const link = document.createElement("a");
|
|
539
|
+
link.href = url;
|
|
540
|
+
link.download = "data.xlsx";
|
|
541
|
+
document.body.appendChild(link);
|
|
542
|
+
|
|
543
|
+
link.click();
|
|
544
|
+
|
|
545
|
+
document.body.removeChild(link);
|
|
546
|
+
window.URL.revokeObjectURL(url);
|
|
547
|
+
} catch (error) {
|
|
548
|
+
console.error('Error downloading the file:', error);
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
const getUniqueValue = (dataz) => {
|
|
553
|
+
const seen = new Set();
|
|
554
|
+
return dataz.filter(data => {
|
|
555
|
+
const duplicate = seen.has(data.name);
|
|
556
|
+
seen.add(data.name);
|
|
557
|
+
return !duplicate;
|
|
558
|
+
});
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
const { onDownload } = useDownloadExcel({
|
|
562
|
+
currentTableRef: tableRefExportExcel.current,
|
|
563
|
+
filename: props.title,
|
|
564
|
+
sheet: "pradium-tech"
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
const getAttachments = async () => {
|
|
568
|
+
try {
|
|
569
|
+
const response = await axios.get(`${addressIpApi}/attachment/attachments/?center_id=${center.id}&global_code=${props.globalCode}`);
|
|
570
|
+
setAttachments(response.data);
|
|
571
|
+
} catch (error) {
|
|
572
|
+
console.error("Error fetching data d:", error.message);
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
const getNextPage = async () => {
|
|
577
|
+
if (props.api) {
|
|
578
|
+
setLoadingIS(true)
|
|
579
|
+
try {
|
|
580
|
+
const response = await fetch(reponseDetail.paginate.next, {
|
|
581
|
+
method: 'GET',
|
|
582
|
+
headers: authenticated_header()
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
if (!response.ok) {
|
|
586
|
+
throw new Error(`HTTP ERROR! STATUS: ${response.status}`);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
const data = await response.json();
|
|
590
|
+
setReponseDetail(data)
|
|
591
|
+
const newData = dataFilters.concat(data.results)
|
|
592
|
+
setDataFilters(newData)
|
|
593
|
+
setLoadingIS(false)
|
|
594
|
+
} catch (error) {
|
|
595
|
+
console.error('ERROR FETCHING DATA', error);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
};
|
|
599
|
+
|
|
600
|
+
const handleScroll = () => {
|
|
601
|
+
const { scrollTop, clientHeight, scrollHeight } =
|
|
602
|
+
document.documentElement;
|
|
603
|
+
|
|
604
|
+
if (scrollTop + clientHeight >= scrollHeight) {
|
|
605
|
+
getNextPage()
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
|
|
609
|
+
// ---------------------------------------------------------------------------
|
|
610
|
+
// ---------------------------------------------------------------------------
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
|
|
615
|
+
// ---------------------------------------------------------------------------
|
|
616
|
+
// ---------------------------------EFFECTS-----------------------------------
|
|
617
|
+
// ---------------------------------------------------------------------------
|
|
618
|
+
|
|
619
|
+
useEffect(() => {
|
|
620
|
+
const handleClickOutside = (event) => {
|
|
621
|
+
if (!event.target.classList.contains("selected")) {
|
|
622
|
+
setLineSelected('');
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
|
|
626
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
627
|
+
|
|
628
|
+
return () => {
|
|
629
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
630
|
+
};
|
|
631
|
+
}, []);
|
|
632
|
+
|
|
633
|
+
useEffect(() => {
|
|
634
|
+
const params = new URLSearchParams(filters).toString();
|
|
635
|
+
setQueryURL(`${addressIpApi}${props.api}?${params}&date_system=${dateSystem ? DATETIME.formatYYYYMMDD(dateSystem) : `${Date().getFullYear()}-12-31`}&year=${financialYear ?? new Date().getFullYear()}${props.additional_params ?? ''}`);
|
|
636
|
+
setFrontQueryURL(`${params}&date_system=${dateSystem ? DATETIME.formatYYYYMMDD(dateSystem) : `${Date().getFullYear()}-12-31`}&year=${financialYear ?? new Date().getFullYear()}${props.additional_params ?? ''}`);
|
|
637
|
+
const urlWithoutParams = location.pathname;
|
|
638
|
+
navigate(`${urlWithoutParams}?${params}`)
|
|
639
|
+
}, [filters]);
|
|
640
|
+
|
|
641
|
+
useEffect(() => {
|
|
642
|
+
getData();
|
|
643
|
+
}, [center, rerender]);
|
|
644
|
+
|
|
645
|
+
useEffect(() => {
|
|
646
|
+
getDataFilter();
|
|
647
|
+
}, [center, queryURL, rerender]);
|
|
648
|
+
|
|
649
|
+
useEffect(() => {
|
|
650
|
+
const columns = []
|
|
651
|
+
headers.forEach(item1 => item1.filterable && columns.push({ label: item1.name, type: item1.type, key: item1.search_name ? item1.search_name : item1.key }))
|
|
652
|
+
setFiltres(columns)
|
|
653
|
+
props.btn_add !== undefined && setBtnAdd(props.btn_add)
|
|
654
|
+
}, [])
|
|
655
|
+
|
|
656
|
+
useEffect(() => {
|
|
657
|
+
props.hasAttach && getAttachments();
|
|
658
|
+
}, []);
|
|
659
|
+
|
|
660
|
+
useEffect(() => {
|
|
661
|
+
if (infinite_scroll) {
|
|
662
|
+
window.addEventListener("scroll", handleScroll);
|
|
663
|
+
|
|
664
|
+
return () => window.removeEventListener("scroll", handleScroll);
|
|
665
|
+
}
|
|
666
|
+
}, []);
|
|
667
|
+
|
|
668
|
+
const memoizedAttachments = useMemo(() => {
|
|
669
|
+
if (attachments.length > 0) {
|
|
670
|
+
return <Attachments reload={props.reloadAttachment ?? null} data={attachments} global_code={props.globalCode} />;
|
|
671
|
+
}
|
|
672
|
+
return null;
|
|
673
|
+
}, [attachments, props.globalCode, props.reloadAttachment]);
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
|
|
677
|
+
|
|
678
|
+
// ---------------------------------------------------------------------------
|
|
679
|
+
// ---------------------------------------------------------------------------
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
return (
|
|
683
|
+
<>
|
|
684
|
+
<section
|
|
685
|
+
id={props.id}
|
|
686
|
+
className={`fdrawer-container flex-col ${props.inWorkspace && "in-workspace"} ${props.wTotalCard && "w-total-card"} ${props.wMenu && "w-menu"}`}
|
|
687
|
+
style={{
|
|
688
|
+
height: props.height && ""
|
|
689
|
+
}}
|
|
690
|
+
>
|
|
691
|
+
<div className="wise-main-content main fcustom-main d-flex flex-row col">
|
|
692
|
+
<div className='wise-body card-global-green h-100 col flex-col'>
|
|
693
|
+
<div className={`card-header change-background-color-header-gray ${props.noTitle ? "d-none" : "flex-between"}`}>
|
|
694
|
+
<h4 className='title general-title mb-0'>
|
|
695
|
+
{props.title}
|
|
696
|
+
</h4>
|
|
697
|
+
|
|
698
|
+
<div className="flex-row gap-4 align-center">
|
|
699
|
+
{props.sideTitle}
|
|
700
|
+
|
|
701
|
+
{props.wReturn && <IoCloseCircleSharp className='icon rem-15' role='button' onClick={() => navigate(props.wReturn)} />}
|
|
702
|
+
</div>
|
|
703
|
+
</div>
|
|
704
|
+
<div className={`wise-card card-body gap-2 flex-col`}>
|
|
705
|
+
|
|
706
|
+
|
|
707
|
+
<div className='h-100 d-flex flex-column overflow-hidden'>
|
|
708
|
+
<div className='row flex-grow-1 flex-shrink-1 flex-basis-0 d-flex drawer-main-content'>
|
|
709
|
+
{
|
|
710
|
+
type !== "any" ? (
|
|
711
|
+
<>
|
|
712
|
+
<div className={`col`}>
|
|
713
|
+
|
|
714
|
+
<div className='table-custom custom-list-journal-body-table'>
|
|
715
|
+
<div className={`table-responsive type-table ${props.inWorkspace && "in-workspace"} ${props.wTotalCard && "w-total-card"} ${props.wMenu && "w-menu"}`}>
|
|
716
|
+
{
|
|
717
|
+
table_type === "collapse-simple" && (
|
|
718
|
+
<TableCollapseSimple
|
|
719
|
+
arch={props.arch}
|
|
720
|
+
secondElements={props.secondElements}
|
|
721
|
+
triggerActions={props.triggerActions}
|
|
722
|
+
actions={props.actions}
|
|
723
|
+
dataFilters={dataFilters}
|
|
724
|
+
loading={loading}
|
|
725
|
+
loading2={loading2}
|
|
726
|
+
maxText={maxText}
|
|
727
|
+
data={data}
|
|
728
|
+
headers={headers}
|
|
729
|
+
totalHeaders={totalHeaders}
|
|
730
|
+
totalMainHeaders={totalMainHeaders}
|
|
731
|
+
filters={filters}
|
|
732
|
+
setFilters={setFilters}
|
|
733
|
+
setComment={setComment}
|
|
734
|
+
setSecondInfoComment={setSecondInfoComment}
|
|
735
|
+
setShowModalComment={setShowModalComment}
|
|
736
|
+
showContent={showContent}
|
|
737
|
+
setShowContent={setShowContent}
|
|
738
|
+
lineSelected={lineSelected}
|
|
739
|
+
setLineSelected={setLineSelected}
|
|
740
|
+
isSorting={isSorting}
|
|
741
|
+
setIsSorting={setIsSorting}
|
|
742
|
+
/>
|
|
743
|
+
)
|
|
744
|
+
}
|
|
745
|
+
{
|
|
746
|
+
table_type === "with-checkbox" && (
|
|
747
|
+
<TableWithCheckbox
|
|
748
|
+
selected={selected}
|
|
749
|
+
actions={props.actions}
|
|
750
|
+
dataFilters={dataFilters}
|
|
751
|
+
loading={loading}
|
|
752
|
+
maxText={maxText}
|
|
753
|
+
data={data}
|
|
754
|
+
headers={headers}
|
|
755
|
+
totalHeaders={totalHeaders}
|
|
756
|
+
filters={filters}
|
|
757
|
+
setFilters={setFilters}
|
|
758
|
+
setComment={setComment}
|
|
759
|
+
setSecondInfoComment={setSecondInfoComment}
|
|
760
|
+
setShowModalComment={setShowModalComment}
|
|
761
|
+
lineSelected={lineSelected}
|
|
762
|
+
setLineSelected={setLineSelected}
|
|
763
|
+
isSorting={isSorting}
|
|
764
|
+
setIsSorting={setIsSorting}
|
|
765
|
+
/>
|
|
766
|
+
)
|
|
767
|
+
}
|
|
768
|
+
{
|
|
769
|
+
table_type === "basic" && (
|
|
770
|
+
<TableBasic
|
|
771
|
+
dataFilters={dataFilters}
|
|
772
|
+
actions={props.actions}
|
|
773
|
+
loading={loading}
|
|
774
|
+
maxText={maxText}
|
|
775
|
+
data={data}
|
|
776
|
+
headers={headers}
|
|
777
|
+
totalHeaders={totalHeaders}
|
|
778
|
+
filters={filters}
|
|
779
|
+
setFilters={setFilters}
|
|
780
|
+
setComment={setComment}
|
|
781
|
+
setSecondInfoComment={setSecondInfoComment}
|
|
782
|
+
setShowModalComment={setShowModalComment}
|
|
783
|
+
lineSelected={lineSelected}
|
|
784
|
+
setLineSelected={setLineSelected}
|
|
785
|
+
isSorting={isSorting}
|
|
786
|
+
setIsSorting={setIsSorting}
|
|
787
|
+
/>
|
|
788
|
+
)
|
|
789
|
+
}
|
|
790
|
+
</div>
|
|
791
|
+
</div>
|
|
792
|
+
|
|
793
|
+
</div>
|
|
794
|
+
|
|
795
|
+
<div className={`w-100 ${props.noPagination ? "d-none" : "flex-between align-end"}`}>
|
|
796
|
+
{
|
|
797
|
+
dataFilters.length > 0 ? <FilterPagination filters={[filters, setFilters]} reponseDetail={reponseDetail} setQueryURL={setQueryURL} frontqueryURL={frontqueryURL} /> : <div className=""></div>
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
{
|
|
801
|
+
props.summary ? <FooterSummary colonnes={props.summary.colonnes} rows={props.summary.rows} param={data} /> : <div className=""></div>
|
|
802
|
+
}
|
|
803
|
+
</div>
|
|
804
|
+
</>
|
|
805
|
+
) : (
|
|
806
|
+
<>
|
|
807
|
+
<div className={` ${!showAttachments ? " d-flex flex-col w-100 flex-fill" : "d-none"}`}>
|
|
808
|
+
{props.children}
|
|
809
|
+
</div>
|
|
810
|
+
<div className={`${showAttachments ? " d-flex flex-col w-100 flex-fill" : "d-none"}`}>
|
|
811
|
+
{memoizedAttachments}
|
|
812
|
+
</div>
|
|
813
|
+
|
|
814
|
+
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
</>
|
|
818
|
+
|
|
819
|
+
)
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
|
|
823
|
+
</div>
|
|
824
|
+
|
|
825
|
+
|
|
826
|
+
</div>
|
|
827
|
+
|
|
828
|
+
|
|
829
|
+
|
|
830
|
+
</div>
|
|
831
|
+
</div>
|
|
832
|
+
|
|
833
|
+
{showFR === "f" && (
|
|
834
|
+
<>
|
|
835
|
+
<div className={`param-bar flex-col gap-2 ${showFR === "f" ? "showFiltres" : "hideFiltres"}`}>
|
|
836
|
+
<div className='card-global-green col flex-col'>
|
|
837
|
+
<div className={`card-header change-background-color-header-gray`}>
|
|
838
|
+
<h4 className='title general-title mb-0'>
|
|
839
|
+
<img className='icon spe-img2' src={activeBouttonDrawerFilter} alt="icon" />
|
|
840
|
+
{DICTIONNARY.Filtres[language]}
|
|
841
|
+
</h4>
|
|
842
|
+
</div>
|
|
843
|
+
{
|
|
844
|
+
loading2 ? (
|
|
845
|
+
<div className='bg-white radius-1 flex-center col'>
|
|
846
|
+
<div className="text-center">...chargement</div>
|
|
847
|
+
</div>
|
|
848
|
+
) : data.length > 0 && filtres.length > 0 ? (
|
|
849
|
+
<div className='card-body col p-2'>
|
|
850
|
+
<div className="w-100 justify-end">
|
|
851
|
+
<NewButton
|
|
852
|
+
type="custom"
|
|
853
|
+
icon={<IoMdRefresh className='icon rem-15' />}
|
|
854
|
+
title={DICTIONNARY.ViderTousLesChamps[language]}
|
|
855
|
+
onclick={() => {
|
|
856
|
+
champsRef.current.forEach(item => {
|
|
857
|
+
if (item) {
|
|
858
|
+
item.triggerClick()
|
|
859
|
+
}
|
|
860
|
+
})
|
|
861
|
+
champsRef2.current.forEach(item => {
|
|
862
|
+
if (item) {
|
|
863
|
+
item.value = ""
|
|
864
|
+
}
|
|
865
|
+
})
|
|
866
|
+
setFilters(filtersMemo)
|
|
867
|
+
}}
|
|
868
|
+
/>
|
|
869
|
+
</div>
|
|
870
|
+
<div className={`w-100`}>
|
|
871
|
+
{
|
|
872
|
+
filtres.map((item, idx) => (
|
|
873
|
+
<div className="fcontent" key={item.key}>
|
|
874
|
+
{
|
|
875
|
+
item.type === "list" ? (
|
|
876
|
+
<div className="ligne-input mb-1" key={item.key}>
|
|
877
|
+
<label htmlFor="">
|
|
878
|
+
{item.label}
|
|
879
|
+
</label>
|
|
880
|
+
<CustomSelector
|
|
881
|
+
ref={(el) => (champsRef.current[idx] = el)}
|
|
882
|
+
optionsInitial={
|
|
883
|
+
item.filter_options
|
|
884
|
+
? item.filter_options.map(item2 => ({
|
|
885
|
+
id: item2.value,
|
|
886
|
+
value: item2.value,
|
|
887
|
+
label: item2.label
|
|
888
|
+
}))
|
|
889
|
+
: getUniqueValue(listFiltres[idx]).map(item2 => ({
|
|
890
|
+
id: item2.name,
|
|
891
|
+
value: item2.name,
|
|
892
|
+
label: item2.name
|
|
893
|
+
}))
|
|
894
|
+
}
|
|
895
|
+
onSelect={(selectedValue) => {
|
|
896
|
+
const newCle = `${item.key}__exact`
|
|
897
|
+
const copy = {
|
|
898
|
+
...filters,
|
|
899
|
+
search_type: 'filter',
|
|
900
|
+
}
|
|
901
|
+
copy[`${newCle}`] = selectedValue
|
|
902
|
+
setFilters(copy)
|
|
903
|
+
}}
|
|
904
|
+
placeholder={DICTIONNARY.Select[language]}
|
|
905
|
+
loading={null}
|
|
906
|
+
/>
|
|
907
|
+
{/* <select name="" id="">
|
|
908
|
+
{props.lists && props.lists[item.label].map((option, opt_index)=> (
|
|
909
|
+
<option key={`2543Trr${option}ezr${item.label}`} value={opt_index}>{option}</option>
|
|
910
|
+
))}
|
|
911
|
+
</select> */}
|
|
912
|
+
</div>
|
|
913
|
+
) : item.type === "amount" ? (
|
|
914
|
+
<div className="ligne-input mb-1" key={item.key}>
|
|
915
|
+
<label htmlFor="">{item.label}</label>
|
|
916
|
+
<div className="col d-flex flex-row">
|
|
917
|
+
<input type="number" className='col percent-input' placeholder='min'
|
|
918
|
+
ref={(el) => (champsRef2.current[idx] = el)}
|
|
919
|
+
onChange={(e) => {
|
|
920
|
+
const newCle = `${item.key}__gte`
|
|
921
|
+
const copy = {
|
|
922
|
+
...filters,
|
|
923
|
+
search_type: 'filter',
|
|
924
|
+
}
|
|
925
|
+
copy[`${newCle}`] = e.target.value
|
|
926
|
+
setFilters(copy)
|
|
927
|
+
}} />
|
|
928
|
+
<div className="mx-1">-</div>
|
|
929
|
+
<input type="number" className='col percent-input' placeholder='max'
|
|
930
|
+
ref={(el) => (champsRef2.current[idx] = el)}
|
|
931
|
+
onChange={(e) => {
|
|
932
|
+
const newCle = `${item.key}__lte`
|
|
933
|
+
const copy = {
|
|
934
|
+
...filters,
|
|
935
|
+
search_type: 'filter',
|
|
936
|
+
}
|
|
937
|
+
copy[`${newCle}`] = e.target.value
|
|
938
|
+
setFilters(copy)
|
|
939
|
+
}} />
|
|
940
|
+
</div>
|
|
941
|
+
</div>
|
|
942
|
+
) : item.type === "percent" ? (
|
|
943
|
+
<div className="ligne-input mb-1" key={item.key}>
|
|
944
|
+
<label htmlFor="">{item.label}</label>
|
|
945
|
+
<div className="col d-flex flex-row">
|
|
946
|
+
<input type="number" className='col percent-input' placeholder='min' />
|
|
947
|
+
<div className="mx-1">-</div>
|
|
948
|
+
<input type="number" className='col percent-input' placeholder='max' />
|
|
949
|
+
</div>
|
|
950
|
+
</div>
|
|
951
|
+
) : item.type === "date" ? (
|
|
952
|
+
<div className="ligne-input mb-1" key={item.key}>
|
|
953
|
+
<label htmlFor="">{item.label}</label>
|
|
954
|
+
<div className="col d-flex flex-row">
|
|
955
|
+
<input type="date" className='col'
|
|
956
|
+
ref={(el) => (champsRef2.current[idx] = el)}
|
|
957
|
+
onChange={(e) => {
|
|
958
|
+
const newCle = `${item.key}__gte`
|
|
959
|
+
const copy = {
|
|
960
|
+
...filters,
|
|
961
|
+
search_type: 'filter',
|
|
962
|
+
}
|
|
963
|
+
copy[`${newCle}`] = e.target.value
|
|
964
|
+
setFilters(copy)
|
|
965
|
+
}}
|
|
966
|
+
/>
|
|
967
|
+
<div className="mx-1">-</div>
|
|
968
|
+
<input type="date" className='col'
|
|
969
|
+
ref={(el) => (champsRef2.current[idx] = el)}
|
|
970
|
+
onChange={(e) => {
|
|
971
|
+
const newCle = `${item.key}__lte`
|
|
972
|
+
const copy = {
|
|
973
|
+
...filters,
|
|
974
|
+
search_type: 'filter',
|
|
975
|
+
}
|
|
976
|
+
copy[`${newCle}`] = e.target.value
|
|
977
|
+
setFilters(copy)
|
|
978
|
+
}} />
|
|
979
|
+
</div>
|
|
980
|
+
</div>
|
|
981
|
+
) : item.type === "number" ? (
|
|
982
|
+
<div className="ligne-input mb-1" key={item.key}>
|
|
983
|
+
<label htmlFor="">{item.label}</label>
|
|
984
|
+
<div className="col d-flex flex-row">
|
|
985
|
+
<input type="number" className='col percent-input' placeholder='min'
|
|
986
|
+
ref={(el) => (champsRef2.current[idx] = el)}
|
|
987
|
+
onChange={(e) => {
|
|
988
|
+
const newCle = `${item.key}__gte`
|
|
989
|
+
const copy = {
|
|
990
|
+
...filters,
|
|
991
|
+
search_type: 'filter',
|
|
992
|
+
}
|
|
993
|
+
copy[`${newCle}`] = e.target.value
|
|
994
|
+
setFilters(copy)
|
|
995
|
+
}} />
|
|
996
|
+
<div className="mx-1">-</div>
|
|
997
|
+
<input type="number" className='col percent-input' placeholder='max'
|
|
998
|
+
ref={(el) => (champsRef2.current[idx] = el)}
|
|
999
|
+
onChange={(e) => {
|
|
1000
|
+
const newCle = `${item.key}__lte`
|
|
1001
|
+
const copy = {
|
|
1002
|
+
...filters,
|
|
1003
|
+
search_type: 'filter',
|
|
1004
|
+
}
|
|
1005
|
+
copy[`${newCle}`] = e.target.value
|
|
1006
|
+
setFilters(copy)
|
|
1007
|
+
}} />
|
|
1008
|
+
</div>
|
|
1009
|
+
</div>
|
|
1010
|
+
) : item.type === "checkbox" ? (
|
|
1011
|
+
<div className="ligne-input mb-1" key={item.key}>
|
|
1012
|
+
<input type="checkbox" className='col' />
|
|
1013
|
+
<label htmlFor="">{item.label}</label>
|
|
1014
|
+
</div>
|
|
1015
|
+
) : (
|
|
1016
|
+
<div className="ligne-input mb-1" key={item.key}>
|
|
1017
|
+
<label htmlFor="">{item.label}</label>
|
|
1018
|
+
<CustomSelector
|
|
1019
|
+
ref={(el) => (champsRef.current[idx] = el)}
|
|
1020
|
+
defaultSelectedValue={csv}
|
|
1021
|
+
optionsInitial={getUniqueValue(listFiltres[idx]).map(item2 => ({
|
|
1022
|
+
id: item2.key,
|
|
1023
|
+
value: item2.name,
|
|
1024
|
+
label: item2.name
|
|
1025
|
+
}))}
|
|
1026
|
+
onSelect={(selectedValue) => {
|
|
1027
|
+
const newCle = `${item.key}__exact`
|
|
1028
|
+
const copy = {
|
|
1029
|
+
...filters,
|
|
1030
|
+
search_type: 'filter',
|
|
1031
|
+
}
|
|
1032
|
+
copy[`${newCle}`] = selectedValue
|
|
1033
|
+
setFilters(copy)
|
|
1034
|
+
}}
|
|
1035
|
+
placeholder={DICTIONNARY.Select[language]}
|
|
1036
|
+
loading={null}
|
|
1037
|
+
/>
|
|
1038
|
+
</div>
|
|
1039
|
+
)
|
|
1040
|
+
}
|
|
1041
|
+
</div>
|
|
1042
|
+
))
|
|
1043
|
+
}
|
|
1044
|
+
</div>
|
|
1045
|
+
</div>
|
|
1046
|
+
) : (
|
|
1047
|
+
<div className='bg-white radius-1 flex-center col flex-col gap-3'>
|
|
1048
|
+
<div className="icon-div"><FaFilterCircleXmark className='icon rem-5' /></div>
|
|
1049
|
+
<div className="text-center fw-bold">{DICTIONNARY.NoDataToFilter[language]}</div>
|
|
1050
|
+
</div>
|
|
1051
|
+
)
|
|
1052
|
+
}
|
|
1053
|
+
</div>
|
|
1054
|
+
</div>
|
|
1055
|
+
</>
|
|
1056
|
+
)}
|
|
1057
|
+
{showFR === "fm" && (
|
|
1058
|
+
<>
|
|
1059
|
+
<div className={`param-bar flex-col gap-2 ${showFR === "f" ? "showFiltres" : "hideFiltres"}`}>
|
|
1060
|
+
<div className='card-global-green col flex-col'>
|
|
1061
|
+
<div className={`card-header change-background-color-header-gray`}>
|
|
1062
|
+
<h4 className='title general-title mb-0'>
|
|
1063
|
+
<img className='icon spe-img2' src={activeBouttonDrawerFilter} alt="icon" />
|
|
1064
|
+
{DICTIONNARY.Filtres[language]}
|
|
1065
|
+
</h4>
|
|
1066
|
+
</div>
|
|
1067
|
+
{
|
|
1068
|
+
loading2 ? (
|
|
1069
|
+
<div className='bg-white radius-1 flex-center col'>
|
|
1070
|
+
<div className="text-center">...chargement</div>
|
|
1071
|
+
</div>
|
|
1072
|
+
) : data.length > 0 && filtres.length > 0 ? (
|
|
1073
|
+
<div className='card-body col p-2'>
|
|
1074
|
+
<div className="w-100 justify-end">
|
|
1075
|
+
<NewButton
|
|
1076
|
+
type="custom"
|
|
1077
|
+
icon={<IoMdRefresh className='icon rem-15' />}
|
|
1078
|
+
title={DICTIONNARY.ViderTousLesChamps[language]}
|
|
1079
|
+
onclick={() => {
|
|
1080
|
+
champsRef.current.forEach(item => {
|
|
1081
|
+
if (item) {
|
|
1082
|
+
item.triggerClick()
|
|
1083
|
+
}
|
|
1084
|
+
})
|
|
1085
|
+
champsRef2.current.forEach(item => {
|
|
1086
|
+
if (item) {
|
|
1087
|
+
item.value = ""
|
|
1088
|
+
}
|
|
1089
|
+
})
|
|
1090
|
+
setFilters(filtersMemo)
|
|
1091
|
+
}}
|
|
1092
|
+
/>
|
|
1093
|
+
</div>
|
|
1094
|
+
<div className='w-100'>
|
|
1095
|
+
|
|
1096
|
+
</div>
|
|
1097
|
+
|
|
1098
|
+
</div>
|
|
1099
|
+
) : (
|
|
1100
|
+
<div className='bg-white radius-1 flex-center col flex-col gap-3'>
|
|
1101
|
+
<div className="icon-div"><FaFilterCircleXmark className='icon rem-5' /></div>
|
|
1102
|
+
<div className="text-center fw-bold">{DICTIONNARY.NoDataToFilter[language]}</div>
|
|
1103
|
+
</div>
|
|
1104
|
+
)
|
|
1105
|
+
}
|
|
1106
|
+
</div>
|
|
1107
|
+
</div>
|
|
1108
|
+
</>
|
|
1109
|
+
)}
|
|
1110
|
+
|
|
1111
|
+
{showFR === "r" && (
|
|
1112
|
+
<>
|
|
1113
|
+
<div className={`param-bar flex-col gap-2 ${showFR === "r" ? "showRecherche" : "hideRecherche"}`}>
|
|
1114
|
+
<div className='card-global-green col flex-col'>
|
|
1115
|
+
<div className={`card-header change-background-color-header-gray`}>
|
|
1116
|
+
<h4 className='title general-title mb-0'>
|
|
1117
|
+
<img className='icon spe-img2' src={activeBouttonDrawerSearch} alt="icon" />
|
|
1118
|
+
{DICTIONNARY.Search[language]}
|
|
1119
|
+
</h4>
|
|
1120
|
+
</div>
|
|
1121
|
+
|
|
1122
|
+
<div className='card-body col p-2'>
|
|
1123
|
+
<div className="w-100 justify-end">
|
|
1124
|
+
<NewButton
|
|
1125
|
+
type="custom"
|
|
1126
|
+
icon={<IoMdRefresh className='icon rem-15' />}
|
|
1127
|
+
onclick={() => {
|
|
1128
|
+
setSelectedItems([])
|
|
1129
|
+
setSearch("")
|
|
1130
|
+
const updatedFilters = { center_id: filters.center_id, search_type: 'search' };
|
|
1131
|
+
if (search !== "") {
|
|
1132
|
+
selectedItems.forEach((item) => {
|
|
1133
|
+
|
|
1134
|
+
updatedFilters[`${item}__icontains`] = "";
|
|
1135
|
+
})
|
|
1136
|
+
// for (const key in filters) {
|
|
1137
|
+
// if (filters.hasOwnProperty(key) && key !== 'center_id' && key !== 'page') {
|
|
1138
|
+
// updatedFilters[key] = e.target.value;
|
|
1139
|
+
// }
|
|
1140
|
+
// }
|
|
1141
|
+
|
|
1142
|
+
setFilters(updatedFilters);
|
|
1143
|
+
}
|
|
1144
|
+
searchSelect.current.value = ""
|
|
1145
|
+
}}
|
|
1146
|
+
title={DICTIONNARY.ViderTousLesChamps[language]}
|
|
1147
|
+
/>
|
|
1148
|
+
</div>
|
|
1149
|
+
<div className={`w-100 fdrawer-search`}>
|
|
1150
|
+
<div className='grid-custom-one-column'>
|
|
1151
|
+
<label htmlFor="" className="form-label">{DICTIONNARY.SelectColumns[language]}</label>
|
|
1152
|
+
<select className="form-select" onChange={handleSelectedItem} name='itemSelect' ref={searchSelect}>
|
|
1153
|
+
<option selected="">{DICTIONNARY.Select[language]}</option>
|
|
1154
|
+
{
|
|
1155
|
+
headers.map((item, index) => (
|
|
1156
|
+
<option key={index} value={item.search_name}>{item.name}</option>
|
|
1157
|
+
))
|
|
1158
|
+
}
|
|
1159
|
+
</select>
|
|
1160
|
+
</div>
|
|
1161
|
+
<div className='item-selected-searched'>
|
|
1162
|
+
{
|
|
1163
|
+
selectedItems.length === 0 ? (
|
|
1164
|
+
<></>
|
|
1165
|
+
) : (
|
|
1166
|
+
<>
|
|
1167
|
+
<div className='item-selected'>
|
|
1168
|
+
{
|
|
1169
|
+
selectedItems.map((item, index) => (
|
|
1170
|
+
<>
|
|
1171
|
+
<span title='Cliquer pour supprimer' onClick={() => handleRemoveItem(item)} >{headers.find(hi => hi.key === item)?.name ?? ''}</span>
|
|
1172
|
+
</>
|
|
1173
|
+
))
|
|
1174
|
+
}
|
|
1175
|
+
</div>
|
|
1176
|
+
<div className=''>
|
|
1177
|
+
<label htmlFor="" className="form-label" >Recherche</label>
|
|
1178
|
+
<input className="form-control" type="search" value={search}
|
|
1179
|
+
onChange={(e) => {
|
|
1180
|
+
setSearch(e.target.value)
|
|
1181
|
+
const updatedFilters = { center_id: filters.center_id, search_type: 'search' };
|
|
1182
|
+
selectedItems.forEach((item) => {
|
|
1183
|
+
|
|
1184
|
+
updatedFilters[`${item}__icontains`] = e.target.value;
|
|
1185
|
+
})
|
|
1186
|
+
// for (const key in filters) {
|
|
1187
|
+
// if (filters.hasOwnProperty(key) && key !== 'center_id' && key !== 'page') {
|
|
1188
|
+
// updatedFilters[key] = e.target.value;
|
|
1189
|
+
// }
|
|
1190
|
+
// }
|
|
1191
|
+
|
|
1192
|
+
setFilters(updatedFilters);
|
|
1193
|
+
|
|
1194
|
+
}} />
|
|
1195
|
+
</div>
|
|
1196
|
+
{/* <div className='btn-search'>
|
|
1197
|
+
<img src={bouttonDrawerValidateSearch} className='btn-icon' />
|
|
1198
|
+
</div> */}
|
|
1199
|
+
</>
|
|
1200
|
+
)
|
|
1201
|
+
}
|
|
1202
|
+
</div>
|
|
1203
|
+
</div>
|
|
1204
|
+
</div>
|
|
1205
|
+
</div>
|
|
1206
|
+
</div>
|
|
1207
|
+
</>
|
|
1208
|
+
)}
|
|
1209
|
+
|
|
1210
|
+
{/* {showFR && !["r", "f"].includes(showFR) && (
|
|
1211
|
+
<>
|
|
1212
|
+
<div className={`param-bar flex-col gap-2 ${showFR === "r" ? "showRecherche" : "hideRecherche"}`}>
|
|
1213
|
+
<div className='card-global-green col flex-col'>
|
|
1214
|
+
<div className={`card-header change-background-color-header-gray`}>
|
|
1215
|
+
<h4 className='title general-title mb-0'>
|
|
1216
|
+
<img className='icon spe-img2' src={activeBouttonDrawerSearch} alt="icon" />
|
|
1217
|
+
{DICTIONNARY.Search[language]}
|
|
1218
|
+
</h4>
|
|
1219
|
+
</div>
|
|
1220
|
+
|
|
1221
|
+
<div className='card-body col p-2'>
|
|
1222
|
+
</div>
|
|
1223
|
+
</div>
|
|
1224
|
+
</div>
|
|
1225
|
+
</>
|
|
1226
|
+
)} */}
|
|
1227
|
+
|
|
1228
|
+
{/* ---------------------------------DRAWER BUTTONS----------------------------------- */}
|
|
1229
|
+
<div className={`fdrawer-btns-container ${props.noTitle && "mt-0"}`}>
|
|
1230
|
+
<div className="btnz-container" ref={btnsContainer}>
|
|
1231
|
+
<div className="fdrawer-btn">
|
|
1232
|
+
{showFR ? <RiMenuUnfoldLine /> : <RiMenuFoldLine />}
|
|
1233
|
+
</div>
|
|
1234
|
+
{
|
|
1235
|
+
!noFilter && (
|
|
1236
|
+
<div className={`fdrawer-btn ${showFR === "f" && "active"}`} onClick={() => {
|
|
1237
|
+
|
|
1238
|
+
if (type === 'any') {
|
|
1239
|
+
setShowPeriodModal(true)
|
|
1240
|
+
} else {
|
|
1241
|
+
handleClick("f")
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
}}>
|
|
1245
|
+
<img className='no-hover' src={bouttonDrawerConsult} alt="icon" />
|
|
1246
|
+
<img className='for-hover' src={activebouttonDrawerConsult} alt="icon" />
|
|
1247
|
+
<div className="label-container">
|
|
1248
|
+
{DICTIONNARY.Filtres[language]}
|
|
1249
|
+
</div>
|
|
1250
|
+
</div>
|
|
1251
|
+
)
|
|
1252
|
+
}
|
|
1253
|
+
{
|
|
1254
|
+
!noSearch && (
|
|
1255
|
+
<div className={`fdrawer-btn ${showFR === "r" && "active"} ${type === "any" && "d-none"}`} onClick={() => handleClick("r")}>
|
|
1256
|
+
<img className='no-hover' src={bouttonDrawerSearch} alt="icon" />
|
|
1257
|
+
<img className='for-hover' src={activeBouttonDrawerSearch} alt="icon" />
|
|
1258
|
+
<div className="label-container">
|
|
1259
|
+
{DICTIONNARY.Search[language]}
|
|
1260
|
+
</div>
|
|
1261
|
+
</div>
|
|
1262
|
+
)
|
|
1263
|
+
}
|
|
1264
|
+
{
|
|
1265
|
+
canExport && (
|
|
1266
|
+
<div className={`fdrawer-btn ${showFR === "r" && "active"} ${type === "any" && "d-none"}`} onClick={() => exportDateToExcelFile()}>
|
|
1267
|
+
|
|
1268
|
+
<img className='no-hover' src={bouttonDrawerexcelExport} alt="icon" />
|
|
1269
|
+
<img className='for-hover' src={activebouttonDrawerExcelExport} alt="icon" />
|
|
1270
|
+
<div className="label-container">
|
|
1271
|
+
{DICTIONNARY.ExportExcel[language]}
|
|
1272
|
+
</div>
|
|
1273
|
+
</div>
|
|
1274
|
+
)
|
|
1275
|
+
}
|
|
1276
|
+
{
|
|
1277
|
+
btnsList.length > 0 && btnsList.map(item => (
|
|
1278
|
+
<>
|
|
1279
|
+
<div className={`fdrawer-btn ${item.dropdown && "dropstart"}`} role='button' onClick={item.onclick ?? (() => '')}>
|
|
1280
|
+
{
|
|
1281
|
+
item.type !== "custom" ?
|
|
1282
|
+
(drawerActions[item.type].icon.length > 1 ? (
|
|
1283
|
+
item.dropdown ? (
|
|
1284
|
+
<Link
|
|
1285
|
+
target={item.target ?? "_self"}
|
|
1286
|
+
to={item.to ?? "#"}
|
|
1287
|
+
data-bs-toggle="dropdown"
|
|
1288
|
+
aria-expanded="false"
|
|
1289
|
+
>
|
|
1290
|
+
<img className='no-hover' src={drawerActions[item.type].icon[0]} alt="icon" />
|
|
1291
|
+
<img className='for-hover' src={drawerActions[item.type].icon[1]} alt="icon" />
|
|
1292
|
+
</Link>
|
|
1293
|
+
) : (
|
|
1294
|
+
<Link
|
|
1295
|
+
target={item.target ?? "_self"}
|
|
1296
|
+
to={item.to ?? "#"}
|
|
1297
|
+
>
|
|
1298
|
+
<img className='no-hover' src={drawerActions[item.type].icon[0]} alt="icon" />
|
|
1299
|
+
<img className='for-hover' src={drawerActions[item.type].icon[1]} alt="icon" />
|
|
1300
|
+
</Link>
|
|
1301
|
+
)
|
|
1302
|
+
) : (
|
|
1303
|
+
item.dropdown ? (
|
|
1304
|
+
<Link
|
|
1305
|
+
target={item.target ?? "_self"}
|
|
1306
|
+
to={item.to ?? "#"}
|
|
1307
|
+
data-bs-toggle="dropdown"
|
|
1308
|
+
aria-expanded="false"
|
|
1309
|
+
>
|
|
1310
|
+
{drawerActions[item.type].icon[0]}
|
|
1311
|
+
</Link>
|
|
1312
|
+
) : (
|
|
1313
|
+
<Link
|
|
1314
|
+
target={item.target ?? "_self"}
|
|
1315
|
+
to={item.to ?? "#"}
|
|
1316
|
+
>
|
|
1317
|
+
{drawerActions[item.type].icon[0]}
|
|
1318
|
+
</Link>
|
|
1319
|
+
)
|
|
1320
|
+
)
|
|
1321
|
+
) : (item.icon.length > 1 ? (
|
|
1322
|
+
item.dropdown ? (
|
|
1323
|
+
<Link
|
|
1324
|
+
target={item.target ?? "_self"}
|
|
1325
|
+
to={item.to ?? "#"}
|
|
1326
|
+
data-bs-toggle="dropdown"
|
|
1327
|
+
aria-expanded="false"
|
|
1328
|
+
>
|
|
1329
|
+
{
|
|
1330
|
+
item.icon_type === "img" ? (
|
|
1331
|
+
<>
|
|
1332
|
+
<img className='no-hover' src={item.icon[0]} alt="icon" />
|
|
1333
|
+
<img className='for-hover' src={item.icon[1]} alt="icon" />
|
|
1334
|
+
</>
|
|
1335
|
+
) : (
|
|
1336
|
+
<>
|
|
1337
|
+
{item.icon[0]}
|
|
1338
|
+
{item.icon[1]}
|
|
1339
|
+
</>
|
|
1340
|
+
)
|
|
1341
|
+
}
|
|
1342
|
+
</Link>
|
|
1343
|
+
) : (
|
|
1344
|
+
<Link
|
|
1345
|
+
target={item.target ?? "_self"}
|
|
1346
|
+
to={item.to ?? "#"}
|
|
1347
|
+
>
|
|
1348
|
+
{
|
|
1349
|
+
item.icon_type === "img" ? (
|
|
1350
|
+
<>
|
|
1351
|
+
<img className='no-hover' src={item.icon[0]} alt="icon" />
|
|
1352
|
+
<img className='for-hover' src={item.icon[1]} alt="icon" />
|
|
1353
|
+
</>
|
|
1354
|
+
) : (
|
|
1355
|
+
<>
|
|
1356
|
+
{item.icon[0]}
|
|
1357
|
+
{item.icon[1]}
|
|
1358
|
+
</>
|
|
1359
|
+
)
|
|
1360
|
+
}
|
|
1361
|
+
</Link>
|
|
1362
|
+
)
|
|
1363
|
+
) : (
|
|
1364
|
+
item.dropdown ? (
|
|
1365
|
+
<Link
|
|
1366
|
+
target={item.target ?? "_self"}
|
|
1367
|
+
to={item.to ?? "#"}
|
|
1368
|
+
data-bs-toggle="dropdown"
|
|
1369
|
+
aria-expanded="false"
|
|
1370
|
+
>
|
|
1371
|
+
{item.icon[0]}
|
|
1372
|
+
</Link>
|
|
1373
|
+
) : (
|
|
1374
|
+
<Link
|
|
1375
|
+
target={item.target ?? "_self"}
|
|
1376
|
+
to={item.to ?? "#"}
|
|
1377
|
+
>
|
|
1378
|
+
{item.icon[0]}
|
|
1379
|
+
</Link>
|
|
1380
|
+
)
|
|
1381
|
+
)
|
|
1382
|
+
)
|
|
1383
|
+
}
|
|
1384
|
+
<div className="label-container">
|
|
1385
|
+
{item.label ?? drawerActions[item.type].label}
|
|
1386
|
+
</div>
|
|
1387
|
+
{
|
|
1388
|
+
item.dropdown && (
|
|
1389
|
+
<ul className="dropdown-menu fdrawer-dropdown-menu">
|
|
1390
|
+
{
|
|
1391
|
+
item.dropdown.map(dItem => (
|
|
1392
|
+
<li className="dropdown-item" onClick={dItem.onclick ?? (() => "")}>
|
|
1393
|
+
<Link to={`${dItem.url ?? "#"}`}>
|
|
1394
|
+
{dItem.label}
|
|
1395
|
+
</Link>
|
|
1396
|
+
</li>
|
|
1397
|
+
))
|
|
1398
|
+
}
|
|
1399
|
+
</ul>
|
|
1400
|
+
)
|
|
1401
|
+
}
|
|
1402
|
+
</div>
|
|
1403
|
+
</>
|
|
1404
|
+
))
|
|
1405
|
+
}
|
|
1406
|
+
{
|
|
1407
|
+
props.hasImportExcel &&
|
|
1408
|
+
<>
|
|
1409
|
+
<div className="fdrawer-btn" role='button' onClick={() => setShowImportExcel(true)}>
|
|
1410
|
+
<img className='no-hover' src={bouttonDrawerexcelImport} alt="icon" />
|
|
1411
|
+
<img className='for-hover' src={activebouttonDrawerExcelImport} alt="icon" />
|
|
1412
|
+
<div className="label-container">
|
|
1413
|
+
{DICTIONNARY.ImportExcel[language]}
|
|
1414
|
+
</div>
|
|
1415
|
+
</div>
|
|
1416
|
+
</>
|
|
1417
|
+
}
|
|
1418
|
+
{
|
|
1419
|
+
props.hasExportExcel &&
|
|
1420
|
+
<>
|
|
1421
|
+
<div className="fdrawer-btn" role='button' onClick={() => exportDateToExcelFile()}>
|
|
1422
|
+
<img className='no-hover' src={bouttonDrawerexcelExport} alt="icon" />
|
|
1423
|
+
<img className='for-hover' src={activebouttonDrawerExcelExport} alt="icon" />
|
|
1424
|
+
<div className="label-container">
|
|
1425
|
+
{DICTIONNARY.ExportExcel[language]}
|
|
1426
|
+
</div>
|
|
1427
|
+
</div>
|
|
1428
|
+
</>
|
|
1429
|
+
}
|
|
1430
|
+
{
|
|
1431
|
+
props.hasComHis &&
|
|
1432
|
+
<>
|
|
1433
|
+
<div className="fdrawer-btn" role='button' onClick={() => setShowCommunication(true)}>
|
|
1434
|
+
<img className='no-hover' src={bouttonDrawerMessagerie} alt="icon" />
|
|
1435
|
+
<img className='for-hover' src={activebouttonDrawerMessagerie} alt="icon" />
|
|
1436
|
+
<div className="label-container">
|
|
1437
|
+
{DICTIONNARY.CommunicationHistory[language]}
|
|
1438
|
+
</div>
|
|
1439
|
+
</div>
|
|
1440
|
+
</>
|
|
1441
|
+
}
|
|
1442
|
+
{
|
|
1443
|
+
props.hasAttach &&
|
|
1444
|
+
<>
|
|
1445
|
+
<div className="fdrawer-btn" role='button' onClick={() => setShowAttachments(!showAttachments)}>
|
|
1446
|
+
<img className='no-hover' src={bouttonDrawerAttachement} alt="icon" />
|
|
1447
|
+
<img className='for-hover' src={activebouttonDrawerAttachement} alt="icon" />
|
|
1448
|
+
<div className="label-container">
|
|
1449
|
+
{DICTIONNARY.Attachments[language]}
|
|
1450
|
+
</div>
|
|
1451
|
+
</div>
|
|
1452
|
+
</>
|
|
1453
|
+
}
|
|
1454
|
+
{
|
|
1455
|
+
props.hasExport &&
|
|
1456
|
+
<>
|
|
1457
|
+
<div className="fdrawer-btn" role='button' onClick={() => setShowAttachments(!showAttachments)}>
|
|
1458
|
+
<img className='no-hover' src={bouttonDrawerAttachement} alt="icon" />
|
|
1459
|
+
<img className='for-hover' src={activebouttonDrawerAttachement} alt="icon" />
|
|
1460
|
+
<div className="label-container">
|
|
1461
|
+
{DICTIONNARY.Attachments[language]}
|
|
1462
|
+
</div>
|
|
1463
|
+
</div>
|
|
1464
|
+
</>
|
|
1465
|
+
}
|
|
1466
|
+
{
|
|
1467
|
+
props.save &&
|
|
1468
|
+
<>
|
|
1469
|
+
<div
|
|
1470
|
+
className="fdrawer-btn" role='button'
|
|
1471
|
+
onClick={props.save}
|
|
1472
|
+
>
|
|
1473
|
+
<img className='no-hover' src={bouttonDrawerEnregistrer} alt="icon" />
|
|
1474
|
+
<img className='for-hover' src={activebouttonDrawerEnregistrer} alt="icon" />
|
|
1475
|
+
<div className="label-container">
|
|
1476
|
+
{DICTIONNARY.Save[language]}
|
|
1477
|
+
</div>
|
|
1478
|
+
</div>
|
|
1479
|
+
</>
|
|
1480
|
+
}
|
|
1481
|
+
{
|
|
1482
|
+
props.view &&
|
|
1483
|
+
<>
|
|
1484
|
+
<div
|
|
1485
|
+
className="fdrawer-btn"
|
|
1486
|
+
role='button'
|
|
1487
|
+
data-bs-toggle="dropdown"
|
|
1488
|
+
aria-expanded="false"
|
|
1489
|
+
>
|
|
1490
|
+
<FaEye className='no-hover icon white' alt="icon" />
|
|
1491
|
+
<FaEye className='for-hover icon gray' alt="icon" />
|
|
1492
|
+
<div className="label-container">
|
|
1493
|
+
{DICTIONNARY.ChangerLaVue[language]}
|
|
1494
|
+
</div>
|
|
1495
|
+
</div>
|
|
1496
|
+
<ul className="dropdown-menu fdrawer-dropdown-menu">
|
|
1497
|
+
{
|
|
1498
|
+
props.view_actions && props.view_actions.map(item => (
|
|
1499
|
+
<li className="dropdown-item" onClick={item.onclick ?? (() => "")}>
|
|
1500
|
+
{item.label}
|
|
1501
|
+
</li>
|
|
1502
|
+
))
|
|
1503
|
+
}
|
|
1504
|
+
</ul>
|
|
1505
|
+
</>
|
|
1506
|
+
}
|
|
1507
|
+
</div>
|
|
1508
|
+
<div className="no-floating-btn for-style"></div>
|
|
1509
|
+
<div className="no-floating-btn for-style2"></div>
|
|
1510
|
+
</div>
|
|
1511
|
+
{/* ------------------------------------------------------------------------------------- */}
|
|
1512
|
+
</div>
|
|
1513
|
+
</section>
|
|
1514
|
+
{/* ---------------------------------MODAL COM HIS----------------------------------- */}
|
|
1515
|
+
<FModal
|
|
1516
|
+
type="basic"
|
|
1517
|
+
wHeader={false}
|
|
1518
|
+
show={showCommunication}
|
|
1519
|
+
wBtns={false}
|
|
1520
|
+
modalClassName={"modal-format-attach"}
|
|
1521
|
+
hide={() => setShowCommunication(false)}
|
|
1522
|
+
title={DICTIONNARY.CommunicationHistory[language]}
|
|
1523
|
+
children={
|
|
1524
|
+
<>
|
|
1525
|
+
<CommunicationHistoryComponent lead={props.lead} update_func={props.update_func} />
|
|
1526
|
+
</>
|
|
1527
|
+
}
|
|
1528
|
+
/>
|
|
1529
|
+
{/* ------------------------------------------------------------------------------------- */}
|
|
1530
|
+
{/* ---------------------------------MODAL ATTACHMENT------------------------------------ */}
|
|
1531
|
+
{/* <FModal
|
|
1532
|
+
type="basic"
|
|
1533
|
+
key="FM-att-modal"
|
|
1534
|
+
wBtns={false}
|
|
1535
|
+
show={showAttachments}
|
|
1536
|
+
modalClassName={"modal-format-attach"}
|
|
1537
|
+
hide={() => setShowAttachments(false)}
|
|
1538
|
+
title={DICTIONNARY.Attachments[language]}
|
|
1539
|
+
children={memoizedAttachments}
|
|
1540
|
+
/> */}
|
|
1541
|
+
{/* ------------------------------------------------------------------------------------- */}
|
|
1542
|
+
{/* ---------------------------------MODAL IMPORT EXCEL---------------------------------- */}
|
|
1543
|
+
<ExcelImportModal
|
|
1544
|
+
show={showImportExcel}
|
|
1545
|
+
hide={() => setShowImportExcel(false)}
|
|
1546
|
+
api={props.api_import}
|
|
1547
|
+
onSuccess={() => {
|
|
1548
|
+
setShowImportExcel(false);
|
|
1549
|
+
getDataFilter(); // Recharger les données après import
|
|
1550
|
+
}}
|
|
1551
|
+
/>
|
|
1552
|
+
{/* ------------------------------------------------------------------------------------- */}
|
|
1553
|
+
{/* ---------------------------------MODAL COMMENTAIRE----------------------------------- */}
|
|
1554
|
+
<FModal
|
|
1555
|
+
type="basic"
|
|
1556
|
+
show={showModalComment}
|
|
1557
|
+
hide={() => setShowModalComment(false)}
|
|
1558
|
+
title={DICTIONNARY.Commentaire[language]}
|
|
1559
|
+
modalClassName={"modal-format-com"}
|
|
1560
|
+
secondInfo={secondInfoComment}
|
|
1561
|
+
wBtns={false}
|
|
1562
|
+
children={
|
|
1563
|
+
<>
|
|
1564
|
+
<div className="col radius-1 p-2 bordered">
|
|
1565
|
+
{comment}
|
|
1566
|
+
</div>
|
|
1567
|
+
</>
|
|
1568
|
+
}
|
|
1569
|
+
/>
|
|
1570
|
+
{/* ------------------------------------------------------------------------------------- */}
|
|
1571
|
+
|
|
1572
|
+
|
|
1573
|
+
<ModelTemplapleSimpleV1
|
|
1574
|
+
className={`content`}
|
|
1575
|
+
modalClassName={`crm-modal-custom-drawer`}
|
|
1576
|
+
show={showPeriodModal} hide={() => setShowPeriodModal(false)}
|
|
1577
|
+
children={
|
|
1578
|
+
<>
|
|
1579
|
+
<div className='card-global-green card'>
|
|
1580
|
+
<div className={`card-header change-background-color-header-gray`}>
|
|
1581
|
+
<h4 className='title general-title mb-0'>selectectionner la periode </h4>
|
|
1582
|
+
</div>
|
|
1583
|
+
<div className='content-card'>
|
|
1584
|
+
<CustomFieldset title={`Filtre`} className={`fieldset-drawer-content`} children={
|
|
1585
|
+
<>
|
|
1586
|
+
<div className='grid-custom-one-column content-drawer'>
|
|
1587
|
+
<div className="mb-2">
|
|
1588
|
+
<label htmlFor="" className="form-label">Period</label>
|
|
1589
|
+
<div className="grid-custom-two-column grid-gap-custom">
|
|
1590
|
+
<div className="grid-custom-one-column">
|
|
1591
|
+
<input type="date" value={dateRange.startDate} onChange={changeRange} name="startDate" />
|
|
1592
|
+
</div>
|
|
1593
|
+
<div className="grid-custom-one-column">
|
|
1594
|
+
<input type="date" value={dateRange.endDate} onChange={changeRange} name="endDate" />
|
|
1595
|
+
</div>
|
|
1596
|
+
</div>
|
|
1597
|
+
</div>
|
|
1598
|
+
</div>
|
|
1599
|
+
|
|
1600
|
+
|
|
1601
|
+
</>
|
|
1602
|
+
} />
|
|
1603
|
+
</div>
|
|
1604
|
+
</div>
|
|
1605
|
+
</>
|
|
1606
|
+
}
|
|
1607
|
+
/>
|
|
1608
|
+
|
|
1609
|
+
</>
|
|
1610
|
+
);
|
|
1611
|
+
};
|
|
1612
|
+
|
|
1613
|
+
|
|
1614
|
+
export const FooterSummary: React.FC<FooterSummaryProps> = (props) => {
|
|
1615
|
+
return (
|
|
1616
|
+
<>
|
|
1617
|
+
<div className='card-total two'>
|
|
1618
|
+
<div className="">
|
|
1619
|
+
<table className="fsummary-table">
|
|
1620
|
+
<thead>
|
|
1621
|
+
<tr>
|
|
1622
|
+
<th></th>
|
|
1623
|
+
{
|
|
1624
|
+
props.colonnes.map((item, index) => (
|
|
1625
|
+
<th key={`${index}57435674GFHJKB659764`} className='text-center px-1'>{item}</th>
|
|
1626
|
+
))
|
|
1627
|
+
}
|
|
1628
|
+
</tr>
|
|
1629
|
+
</thead>
|
|
1630
|
+
|
|
1631
|
+
<tbody>
|
|
1632
|
+
{
|
|
1633
|
+
props.rows.map((item, index) => (
|
|
1634
|
+
<tr key={`${index}34843Y6F45FUYG756FJ7UHY65HYGER`} className=''>
|
|
1635
|
+
<td className='pe-1'>{item.label}</td>
|
|
1636
|
+
{
|
|
1637
|
+
item.contents.map((content, index) => (
|
|
1638
|
+
<td key={`${index}34FG2A3QSR4R`} className='text-center'>{content(props.param)}</td>
|
|
1639
|
+
))
|
|
1640
|
+
}
|
|
1641
|
+
</tr>
|
|
1642
|
+
))
|
|
1643
|
+
}
|
|
1644
|
+
</tbody>
|
|
1645
|
+
</table>
|
|
1646
|
+
</div>
|
|
1647
|
+
</div>
|
|
1648
|
+
</>
|
|
1649
|
+
);
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
|
|
1653
|
+
|
|
1654
|
+
export const DropdownActionsMenu: React.FC<DropdownActionsMenuProps> = ({ actions, row, setLineSelected, center }) => {
|
|
1655
|
+
return (
|
|
1656
|
+
<ul className="dropdown-menu dropdown-menu-right">
|
|
1657
|
+
{actions?.map((act) => {
|
|
1658
|
+
const link = act.to ? act.to(row) : "";
|
|
1659
|
+
const hasPermission = !act.permission || center?.user_permissions?.includes(act.permission);
|
|
1660
|
+
const handleClick = () => {
|
|
1661
|
+
if (!hasPermission) return;
|
|
1662
|
+
setLineSelected("");
|
|
1663
|
+
act.onclick?.(row);
|
|
1664
|
+
};
|
|
1665
|
+
|
|
1666
|
+
if (act.condition && !act.condition(row)) return null;
|
|
1667
|
+
|
|
1668
|
+
return (
|
|
1669
|
+
<li key={act.label}>
|
|
1670
|
+
{act.onclick ? (
|
|
1671
|
+
<span
|
|
1672
|
+
className={`dropdown-item ${!hasPermission ? 'wise-disabled text-muted' : ''}`}
|
|
1673
|
+
onClick={handleClick}
|
|
1674
|
+
title={!hasPermission ? "Vous n'avez pas l'autorisation requise pour cette action." : ""}
|
|
1675
|
+
style={{ cursor: hasPermission ? "pointer" : "not-allowed" }}
|
|
1676
|
+
>
|
|
1677
|
+
{act.label}
|
|
1678
|
+
</span>
|
|
1679
|
+
) : (
|
|
1680
|
+
<Link
|
|
1681
|
+
className={`dropdown-item ${!hasPermission ? 'wise-disabled text-muted' : ''}`}
|
|
1682
|
+
to={hasPermission ? link : "#"}
|
|
1683
|
+
title={!hasPermission ? "Vous n'avez pas l'autorisation requise pour cette action." : ""}
|
|
1684
|
+
onClick={(e) => {
|
|
1685
|
+
if (!hasPermission) e.preventDefault();
|
|
1686
|
+
else setLineSelected("");
|
|
1687
|
+
}}
|
|
1688
|
+
style={{ cursor: hasPermission ? "pointer" : "not-allowed" }}
|
|
1689
|
+
>
|
|
1690
|
+
{act.label}
|
|
1691
|
+
</Link>
|
|
1692
|
+
)}
|
|
1693
|
+
</li>
|
|
1694
|
+
);
|
|
1695
|
+
})}
|
|
1696
|
+
</ul>
|
|
1697
|
+
);
|
|
1698
|
+
};
|
|
1699
|
+
|
|
1700
|
+
|
|
1701
|
+
|
|
1702
|
+
export const DynamicTable: React.FC<DynamicTableProps> = (props) => {
|
|
1703
|
+
const [active, setActive] = useState("1");
|
|
1704
|
+
const [rows, setRows] = useState(props.row ?? []);
|
|
1705
|
+
const [rawValues, setRawValues] = useState([])
|
|
1706
|
+
const [newRowValues, setNewRowValues] = useState(props.new_row ?? {})
|
|
1707
|
+
|
|
1708
|
+
|
|
1709
|
+
const handleAddRow = () => {
|
|
1710
|
+
// Générez une nouvelle ligne avec un identifiant unique
|
|
1711
|
+
const newId = Math.random();
|
|
1712
|
+
const newRow = {
|
|
1713
|
+
id: newId,
|
|
1714
|
+
description: '',
|
|
1715
|
+
status: '',
|
|
1716
|
+
};
|
|
1717
|
+
|
|
1718
|
+
setRows([...rows, newRow]);
|
|
1719
|
+
};
|
|
1720
|
+
|
|
1721
|
+
const handleDeleteRow = (inputId) => {
|
|
1722
|
+
// Filtrer les lignes en fonction de l'identifiant unique
|
|
1723
|
+
const updatedRows = rows.filter(row => row.id !== inputId);
|
|
1724
|
+
setRows(updatedRows);
|
|
1725
|
+
};
|
|
1726
|
+
|
|
1727
|
+
const handleDeleteRowValues = (inputId) => {
|
|
1728
|
+
// Filtrer les lignes en fonction de l'identifiant unique
|
|
1729
|
+
const newArr = rawValues.filter(row => row.id !== inputId);
|
|
1730
|
+
setRawValues(newArr);
|
|
1731
|
+
};
|
|
1732
|
+
|
|
1733
|
+
const handleChangeNewRow = (e) => {
|
|
1734
|
+
const copy = newRowValues
|
|
1735
|
+
copy[`${e.currentTarget.name}`] = e.target.value
|
|
1736
|
+
setNewRowValues(copy)
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
const handleResetNewRow = (e) => {
|
|
1740
|
+
const clearRow = {
|
|
1741
|
+
id: Math.random(),
|
|
1742
|
+
description: '',
|
|
1743
|
+
status: '',
|
|
1744
|
+
}
|
|
1745
|
+
setNewRowValues(clearRow)
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
const [selectedItems, setSelectedItems] = useState([]);
|
|
1749
|
+
|
|
1750
|
+
const handleSelectedItem = (event) => {
|
|
1751
|
+
setSelectedItems(prevItems => {
|
|
1752
|
+
if (!prevItems.includes(event)) {
|
|
1753
|
+
return [...prevItems, event];
|
|
1754
|
+
}
|
|
1755
|
+
return prevItems;
|
|
1756
|
+
});
|
|
1757
|
+
};
|
|
1758
|
+
|
|
1759
|
+
return (
|
|
1760
|
+
<>
|
|
1761
|
+
<div className='table-custom custom-list-journal-body-table'>
|
|
1762
|
+
<div className="table-responsive">
|
|
1763
|
+
<table className="table">
|
|
1764
|
+
<thead className='thead_'>
|
|
1765
|
+
<tr>
|
|
1766
|
+
<th className={`text-center ${props.side_of_icon === "gauche" ? "d-block" : "d-none"}`}></th>
|
|
1767
|
+
{props.arr && props.arr.map((item, index) => (
|
|
1768
|
+
<th className='text-center' key={`trg${index}rhyt${item.label}`}>{item.label}</th>
|
|
1769
|
+
))}
|
|
1770
|
+
<th className={`text-center ${props.side_of_icon === "droite" ? "d-block" : "d-none"}`}></th>
|
|
1771
|
+
</tr>
|
|
1772
|
+
</thead>
|
|
1773
|
+
<tbody className='tbody_'>
|
|
1774
|
+
{rows.map((data, index, array) => {
|
|
1775
|
+
const isLastRow = index === array.length - 1;
|
|
1776
|
+
const icon = isLastRow ? (
|
|
1777
|
+
<LuPlusCircle role='button' title="Double click for delete" className="icon green" size={20} onClick={() => {
|
|
1778
|
+
setRawValues(prev => [...prev, newRowValues])
|
|
1779
|
+
handleResetNewRow()
|
|
1780
|
+
handleAddRow()
|
|
1781
|
+
}} />
|
|
1782
|
+
) : (
|
|
1783
|
+
<FaTrashAlt className='icon red delete-icon' onDoubleClick={() => {
|
|
1784
|
+
handleDeleteRowValues(data.id)
|
|
1785
|
+
handleDeleteRow(data.id)
|
|
1786
|
+
}} />
|
|
1787
|
+
);
|
|
1788
|
+
return (
|
|
1789
|
+
<tr key={`${index}Fsrsdcr`}>
|
|
1790
|
+
<td className={`text-center ${props.side_of_icon === "gauche" ? "d-block" : "d-none"} p-2`} >
|
|
1791
|
+
{icon}
|
|
1792
|
+
</td>
|
|
1793
|
+
{props.arr && props.arr.map((item, index) => (
|
|
1794
|
+
<td className='text-center p-1'>
|
|
1795
|
+
{
|
|
1796
|
+
item.type === "list" ? (
|
|
1797
|
+
<CustomSelector
|
|
1798
|
+
optionsInitial={item.list.map(item2 => ({
|
|
1799
|
+
id: item2.id,
|
|
1800
|
+
value: item2.value,
|
|
1801
|
+
label: item2.label
|
|
1802
|
+
}))}
|
|
1803
|
+
onSelect={(selectedValue) => handleSelectedItem(selectedValue)}
|
|
1804
|
+
placeholder={'Select'}
|
|
1805
|
+
loading={null}
|
|
1806
|
+
/>
|
|
1807
|
+
) : (
|
|
1808
|
+
<input className={`w-100 ${item.type === "checkbox" ? "mx-auto" : ""}`} name={item.name} type={item.type} onChange={(e) => handleChangeNewRow(e)} />
|
|
1809
|
+
)
|
|
1810
|
+
}
|
|
1811
|
+
</td>
|
|
1812
|
+
))}
|
|
1813
|
+
<td className={`text-center ${props.side_of_icon === "droite" ? "d-block" : "d-none"} p-2`}>
|
|
1814
|
+
{icon}
|
|
1815
|
+
</td>
|
|
1816
|
+
</tr>
|
|
1817
|
+
)
|
|
1818
|
+
})}
|
|
1819
|
+
</tbody>
|
|
1820
|
+
</table>
|
|
1821
|
+
</div>
|
|
1822
|
+
</div>
|
|
1823
|
+
</>
|
|
1824
|
+
);
|
|
1825
|
+
};
|
|
1826
|
+
|
|
1827
|
+
export const FTable: React.FC<FTableProps> = (props) => {
|
|
1828
|
+
|
|
1829
|
+
|
|
1830
|
+
|
|
1831
|
+
|
|
1832
|
+
// ---------------------------------------------------------------------------
|
|
1833
|
+
// ---------------------------------CUSTOM HOOKS------------------------------
|
|
1834
|
+
// ---------------------------------------------------------------------------
|
|
1835
|
+
|
|
1836
|
+
const navigate = useNavigate();
|
|
1837
|
+
const { center } = useCenter();
|
|
1838
|
+
const { language } = useLanguage();
|
|
1839
|
+
const { setIsLoadingCancelable } = useLoading()
|
|
1840
|
+
|
|
1841
|
+
// ---------------------------------------------------------------------------
|
|
1842
|
+
// ---------------------------------------------------------------------------
|
|
1843
|
+
|
|
1844
|
+
// ---------------------------------------------------------------------------
|
|
1845
|
+
// ---------------------------------REFS--------------------------------------
|
|
1846
|
+
// ---------------------------------------------------------------------------
|
|
1847
|
+
|
|
1848
|
+
const champsRef = useRef([]);
|
|
1849
|
+
const champsRef2 = useRef([]);
|
|
1850
|
+
const searchSelect = useRef();
|
|
1851
|
+
const btnsContainer = useRef();
|
|
1852
|
+
const sweetAlertRef = useRef();
|
|
1853
|
+
const tableRefExportExcel = useRef(null);
|
|
1854
|
+
|
|
1855
|
+
// ---------------------------------------------------------------------------
|
|
1856
|
+
// ---------------------------------------------------------------------------
|
|
1857
|
+
|
|
1858
|
+
|
|
1859
|
+
|
|
1860
|
+
|
|
1861
|
+
|
|
1862
|
+
// ---------------------------------------------------------------------------
|
|
1863
|
+
// ---------------------------------DEFAULT PROPS-----------------------------
|
|
1864
|
+
// ---------------------------------------------------------------------------
|
|
1865
|
+
|
|
1866
|
+
const selected = props.selected ?? []
|
|
1867
|
+
|
|
1868
|
+
const setSelected = props.setSelected ?? ((param) => "")
|
|
1869
|
+
|
|
1870
|
+
const maxText = props.maxText ?? 75
|
|
1871
|
+
|
|
1872
|
+
const type = props.type ?? "table"
|
|
1873
|
+
|
|
1874
|
+
const noFilter = props.noFilter ?? false
|
|
1875
|
+
|
|
1876
|
+
const noSearch = props.noSearch ?? false
|
|
1877
|
+
|
|
1878
|
+
const table_type = props.table_type ?? "basic"
|
|
1879
|
+
|
|
1880
|
+
const rerender = props.toggle ?? "";
|
|
1881
|
+
|
|
1882
|
+
const headers = props.headers ?? [];
|
|
1883
|
+
|
|
1884
|
+
const totalHeaders = props.totalHeaders ?? [];
|
|
1885
|
+
|
|
1886
|
+
const btnsList = props.btnsList ?? [];
|
|
1887
|
+
|
|
1888
|
+
// ---------------------------------------------------------------------------
|
|
1889
|
+
// ---------------------------------------------------------------------------
|
|
1890
|
+
|
|
1891
|
+
|
|
1892
|
+
|
|
1893
|
+
|
|
1894
|
+
|
|
1895
|
+
|
|
1896
|
+
|
|
1897
|
+
// ---------------------------------------------------------------------------
|
|
1898
|
+
// ---------------------------------STATES-----------------------------------
|
|
1899
|
+
// ---------------------------------------------------------------------------
|
|
1900
|
+
|
|
1901
|
+
const [lineSelected, setLineSelected] = useState('')
|
|
1902
|
+
const [showContent, setShowContent] = useState({});
|
|
1903
|
+
const [showModalComment, setShowModalComment] = useState(false);
|
|
1904
|
+
const [secondInfoComment, setSecondInfoComment] = useState("");
|
|
1905
|
+
const [comment, setComment] = useState(false);
|
|
1906
|
+
const [showLeadForm, setShowLeadForm] = useState(false);
|
|
1907
|
+
const [isSorting, setIsSorting] = useState(props.orderByDefault);
|
|
1908
|
+
const [data, setData] = useState([]);
|
|
1909
|
+
const [dataFilters, setDataFilters] = useState([]);
|
|
1910
|
+
const [noFiltres, setNoFiltres] = useState(false);
|
|
1911
|
+
const [showFiltres, setShowFiltres] = useState(false);
|
|
1912
|
+
const [showRecherche, setShowRecherche] = useState(false);
|
|
1913
|
+
const [showFR, setShowFR] = useState("");
|
|
1914
|
+
const [filtres, setFiltres] = useState([]);
|
|
1915
|
+
const [csv, setCsv] = useState("");
|
|
1916
|
+
const [legends, setLegends] = useState([]);
|
|
1917
|
+
const [listFiltres, setListFiltres] = useState([]);
|
|
1918
|
+
const [loading, setLoading] = useState(true);
|
|
1919
|
+
const [loading2, setLoading2] = useState(true);
|
|
1920
|
+
const [queryURL, setQueryURL] = useState('');
|
|
1921
|
+
const [showCommunication, setShowCommunication] = useState(false);
|
|
1922
|
+
const [showAttachments, setShowAttachments] = useState(false);
|
|
1923
|
+
const [showImportExcel, setShowImportExcel] = useState(false);
|
|
1924
|
+
const [attachments, setAttachments] = useState([])
|
|
1925
|
+
const [search, setSearch] = useState('');
|
|
1926
|
+
const [selectedItems, setSelectedItems] = useState([]);
|
|
1927
|
+
const [btnAdd, setBtnAdd] = useState(true);
|
|
1928
|
+
const [reponseDetail, setReponseDetail] = useState({
|
|
1929
|
+
total_pages: null,
|
|
1930
|
+
previous: null,
|
|
1931
|
+
next: null,
|
|
1932
|
+
current_page: null,
|
|
1933
|
+
|
|
1934
|
+
});
|
|
1935
|
+
|
|
1936
|
+
const makeFilters = () => {
|
|
1937
|
+
const newFilters = headers.reduce((acc, item) => {
|
|
1938
|
+
if (item.formule) {
|
|
1939
|
+
acc[`${item.search_name}__icontains`] = ""
|
|
1940
|
+
return acc
|
|
1941
|
+
} else {
|
|
1942
|
+
acc[`${item.key}__icontains`] = ""
|
|
1943
|
+
return acc
|
|
1944
|
+
}
|
|
1945
|
+
})
|
|
1946
|
+
return newFilters
|
|
1947
|
+
}
|
|
1948
|
+
const preFilters = (headers.length) > 0 ? makeFilters() : []
|
|
1949
|
+
|
|
1950
|
+
const [filters, setFilters] = useState({
|
|
1951
|
+
...preFilters,
|
|
1952
|
+
center_id: center?.id ?? null,
|
|
1953
|
+
order_by: props.orderByDefault ?? "id",
|
|
1954
|
+
page: 1
|
|
1955
|
+
})
|
|
1956
|
+
|
|
1957
|
+
const [filtersMemo, setFiltersMemo] = useState({
|
|
1958
|
+
...preFilters,
|
|
1959
|
+
center_id: center?.id ?? null,
|
|
1960
|
+
order_by: props.orderByDefault ?? "id",
|
|
1961
|
+
page: 1
|
|
1962
|
+
})
|
|
1963
|
+
|
|
1964
|
+
// ---------------------------------------------------------------------------
|
|
1965
|
+
// ---------------------------------------------------------------------------
|
|
1966
|
+
|
|
1967
|
+
|
|
1968
|
+
|
|
1969
|
+
|
|
1970
|
+
|
|
1971
|
+
|
|
1972
|
+
const handleClick = (value) => {
|
|
1973
|
+
if (showFR === value) {
|
|
1974
|
+
setShowFR('')
|
|
1975
|
+
} else {
|
|
1976
|
+
setShowFR(value);
|
|
1977
|
+
}
|
|
1978
|
+
};
|
|
1979
|
+
|
|
1980
|
+
const getDataFilter = async () => {
|
|
1981
|
+
if (props.api) {
|
|
1982
|
+
setLoading(true)
|
|
1983
|
+
try {
|
|
1984
|
+
const response = await fetch(queryURL, {
|
|
1985
|
+
method: 'GET',
|
|
1986
|
+
headers: authenticated_header()
|
|
1987
|
+
});
|
|
1988
|
+
|
|
1989
|
+
if (!response.ok) {
|
|
1990
|
+
throw new Error(`HTTP ERROR! STATUS: ${response.status}`);
|
|
1991
|
+
}
|
|
1992
|
+
|
|
1993
|
+
const data = await response.json();
|
|
1994
|
+
setReponseDetail(data)
|
|
1995
|
+
setDataFilters(data.results)
|
|
1996
|
+
setLoading(false)
|
|
1997
|
+
} catch (error) {
|
|
1998
|
+
console.error('ERROR FETCHING DATA', error);
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
2001
|
+
};
|
|
2002
|
+
|
|
2003
|
+
const getData = async () => {
|
|
2004
|
+
if (props.api) {
|
|
2005
|
+
setLoading2(true)
|
|
2006
|
+
try {
|
|
2007
|
+
const response = await fetch(`${addressIpApi}${props.api}?all=true¢er_id=${center?.id ?? null}${props.additional_params ?? ''}`, {
|
|
2008
|
+
method: 'GET',
|
|
2009
|
+
headers: authenticated_header()
|
|
2010
|
+
});
|
|
2011
|
+
|
|
2012
|
+
if (!response.ok) {
|
|
2013
|
+
throw new Error('Error fetching data');
|
|
2014
|
+
}
|
|
2015
|
+
|
|
2016
|
+
const data = await response.json();
|
|
2017
|
+
setData(data.data)
|
|
2018
|
+
const listFilter = []
|
|
2019
|
+
for (let idx = 0; idx < headers.length; idx++) {
|
|
2020
|
+
if (headers[idx].filterable) {
|
|
2021
|
+
listFilter.push(data.data.map(item => ({ id: item.id, name: headers[idx].formule ? headers[idx].formule(item) : item[`${headers[idx].key}`] })))
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
setListFiltres(listFilter)
|
|
2025
|
+
setLoading2(false)
|
|
2026
|
+
|
|
2027
|
+
} catch (error) {
|
|
2028
|
+
console.error('Error fetching data:', error);
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
|
|
2034
|
+
|
|
2035
|
+
|
|
2036
|
+
|
|
2037
|
+
useEffect(() => {
|
|
2038
|
+
const handleClickOutside = (event) => {
|
|
2039
|
+
if (!event.target.classList.contains("selected")) {
|
|
2040
|
+
setLineSelected('');
|
|
2041
|
+
}
|
|
2042
|
+
};
|
|
2043
|
+
|
|
2044
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
2045
|
+
|
|
2046
|
+
return () => {
|
|
2047
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
2048
|
+
};
|
|
2049
|
+
}, []);
|
|
2050
|
+
|
|
2051
|
+
useEffect(() => {
|
|
2052
|
+
const params = new URLSearchParams(filters).toString();
|
|
2053
|
+
setQueryURL(`${addressIpApi}${props.api}?${params}${props.additional_params ?? ''}`);
|
|
2054
|
+
}, [filters]);
|
|
2055
|
+
|
|
2056
|
+
useEffect(() => {
|
|
2057
|
+
getData();
|
|
2058
|
+
}, [center, rerender]);
|
|
2059
|
+
|
|
2060
|
+
useEffect(() => {
|
|
2061
|
+
getDataFilter();
|
|
2062
|
+
}, [center, queryURL, rerender]);
|
|
2063
|
+
|
|
2064
|
+
useEffect(() => {
|
|
2065
|
+
const columns = []
|
|
2066
|
+
headers.forEach(item1 => item1.filterable && columns.push({ label: item1.name, type: item1.type, key: item1.search_name ? item1.search_name : item1.key }))
|
|
2067
|
+
setFiltres(columns)
|
|
2068
|
+
props.btn_add !== undefined && setBtnAdd(props.btn_add)
|
|
2069
|
+
}, [])
|
|
2070
|
+
|
|
2071
|
+
// ---------------------------------------------------------------------------
|
|
2072
|
+
// ---------------------------------------------------------------------------
|
|
2073
|
+
|
|
2074
|
+
return (
|
|
2075
|
+
<>
|
|
2076
|
+
<section
|
|
2077
|
+
id={props.id}
|
|
2078
|
+
className={`ftable-container flex-col`}
|
|
2079
|
+
>
|
|
2080
|
+
<div className={`gap-2 flex-col p-1`}>
|
|
2081
|
+
<div className={`col`}>
|
|
2082
|
+
|
|
2083
|
+
<div className='table-custom custom-list-journal-body-table'>
|
|
2084
|
+
<div className={`table-responsive type-table ${props.inWorkspace && "in-workspace"} ${props.wTotalCard && "w-total-card"} ${props.wMenu && "w-menu"}`}>
|
|
2085
|
+
|
|
2086
|
+
{
|
|
2087
|
+
table_type === "basic" && (
|
|
2088
|
+
<TableBasic
|
|
2089
|
+
actions={props.actions}
|
|
2090
|
+
dataFilters={dataFilters}
|
|
2091
|
+
loading={loading}
|
|
2092
|
+
maxText={maxText}
|
|
2093
|
+
data={data}
|
|
2094
|
+
headers={headers}
|
|
2095
|
+
totalHeaders={totalHeaders}
|
|
2096
|
+
filters={filters}
|
|
2097
|
+
setFilters={setFilters}
|
|
2098
|
+
setComment={setComment}
|
|
2099
|
+
setSecondInfoComment={setSecondInfoComment}
|
|
2100
|
+
setShowModalComment={setShowModalComment}
|
|
2101
|
+
lineSelected={lineSelected}
|
|
2102
|
+
setLineSelected={setLineSelected}
|
|
2103
|
+
isSorting={isSorting}
|
|
2104
|
+
setIsSorting={setIsSorting}
|
|
2105
|
+
/>
|
|
2106
|
+
)
|
|
2107
|
+
}
|
|
2108
|
+
</div>
|
|
2109
|
+
</div>
|
|
2110
|
+
|
|
2111
|
+
</div>
|
|
2112
|
+
|
|
2113
|
+
<div className="w-100 flex-between align-end">
|
|
2114
|
+
{
|
|
2115
|
+
!props.noPagination && dataFilters.length > 0 ? <FilterPagination filters={[filters, setFilters]} reponseDetail={reponseDetail} setQueryURL={setQueryURL} /> : <div className=""></div>
|
|
2116
|
+
}
|
|
2117
|
+
|
|
2118
|
+
{
|
|
2119
|
+
props.summary && <FooterSummary colonnes={props.summary.colonnes} rows={props.summary.rows} param={data} />
|
|
2120
|
+
}
|
|
2121
|
+
</div>
|
|
2122
|
+
</div>
|
|
2123
|
+
</section>
|
|
2124
|
+
{/* ------------------------------------------------------------------------------------- */}
|
|
2125
|
+
{/* ---------------------------------MODAL COMMENTAIRE----------------------------------- */}
|
|
2126
|
+
<FModal
|
|
2127
|
+
type="basic"
|
|
2128
|
+
show={showModalComment}
|
|
2129
|
+
hide={() => setShowModalComment(false)}
|
|
2130
|
+
title={DICTIONNARY.Commentaire[language]}
|
|
2131
|
+
modalClassName={"modal-format-com"}
|
|
2132
|
+
secondInfo={secondInfoComment}
|
|
2133
|
+
wBtns={false}
|
|
2134
|
+
children={
|
|
2135
|
+
<>
|
|
2136
|
+
<div className="col radius-1 p-2 bordered">
|
|
2137
|
+
{comment}
|
|
2138
|
+
</div>
|
|
2139
|
+
</>
|
|
2140
|
+
}
|
|
2141
|
+
/>
|
|
2142
|
+
{/* ------------------------------------------------------------------------------------- */}
|
|
2143
|
+
</>
|
|
2144
|
+
);
|
|
2145
|
+
}
|
|
2146
|
+
|
|
2147
|
+
|
|
2148
|
+
|
|
2149
|
+
export const TableBasic: React.FC<any> = (props) => {
|
|
2150
|
+
|
|
2151
|
+
const dataFilters = props.dataFilters ?? []
|
|
2152
|
+
|
|
2153
|
+
const loading = props.loading ?? true
|
|
2154
|
+
|
|
2155
|
+
const maxText = props.maxText ?? 75
|
|
2156
|
+
|
|
2157
|
+
const data = props.data ?? [];
|
|
2158
|
+
|
|
2159
|
+
const headers = props.headers ?? [];
|
|
2160
|
+
|
|
2161
|
+
const totalHeaders = props.totalHeaders ?? [];
|
|
2162
|
+
|
|
2163
|
+
const filters = props.filters ?? {};
|
|
2164
|
+
|
|
2165
|
+
const setFilters = props.setFilters ?? ((param) => "");
|
|
2166
|
+
|
|
2167
|
+
const setComment = props.setComment ?? ((param) => "");
|
|
2168
|
+
|
|
2169
|
+
const setSecondInfoComment = props.setSecondInfoComment ?? ((param) => "");
|
|
2170
|
+
|
|
2171
|
+
const setShowModalComment = props.setShowModalComment ?? ((param) => "");
|
|
2172
|
+
|
|
2173
|
+
const lineSelected = props.lineSelected ?? "";
|
|
2174
|
+
const setLineSelected = props.setLineSelected ?? ((param) => "");
|
|
2175
|
+
|
|
2176
|
+
const isSorting = props.isSorting;
|
|
2177
|
+
const setIsSorting = props.setIsSorting ?? ((param) => "");
|
|
2178
|
+
|
|
2179
|
+
const { language } = useLanguage()
|
|
2180
|
+
const {center} = useCenter()
|
|
2181
|
+
|
|
2182
|
+
return (
|
|
2183
|
+
<>
|
|
2184
|
+
<table className="table">
|
|
2185
|
+
<thead className="table-dark thead_">
|
|
2186
|
+
<tr>
|
|
2187
|
+
{
|
|
2188
|
+
headers.map((item, index, array) => (
|
|
2189
|
+
<th
|
|
2190
|
+
className={`${(isSorting === item.key || isSorting === `-${item.key}`) && "bg-cararra"} ${!item.sortable && "no-sortable"}`}
|
|
2191
|
+
>
|
|
2192
|
+
{
|
|
2193
|
+
item.sortable ? (
|
|
2194
|
+
<>
|
|
2195
|
+
<div
|
|
2196
|
+
className="align-center gap-1"
|
|
2197
|
+
data-bs-toggle="dropdown"
|
|
2198
|
+
aria-expanded="false"
|
|
2199
|
+
title={item.abbr ?? ""}
|
|
2200
|
+
>
|
|
2201
|
+
{item.name}
|
|
2202
|
+
<FaSort className='icon rem-075 gray' />
|
|
2203
|
+
</div>
|
|
2204
|
+
<ul className="dropdown-menu sort-menu">
|
|
2205
|
+
<li>
|
|
2206
|
+
<span
|
|
2207
|
+
className={`${isSorting === item.key && "sorted"} dropdown-item`}
|
|
2208
|
+
onClick={() => {
|
|
2209
|
+
if (isSorting === item.key) {
|
|
2210
|
+
return ""
|
|
2211
|
+
} else if (isSorting !== item.key) {
|
|
2212
|
+
const copy = {
|
|
2213
|
+
...filters,
|
|
2214
|
+
order_by: item.key,
|
|
2215
|
+
}
|
|
2216
|
+
setIsSorting(item.key)
|
|
2217
|
+
setFilters(copy)
|
|
2218
|
+
}
|
|
2219
|
+
}}
|
|
2220
|
+
>
|
|
2221
|
+
<FaSortAmountDownAlt />
|
|
2222
|
+
Ascending
|
|
2223
|
+
</span>
|
|
2224
|
+
</li>
|
|
2225
|
+
<li>
|
|
2226
|
+
<span
|
|
2227
|
+
className={`${isSorting === `-${item.key}` && "sorted"} dropdown-item`}
|
|
2228
|
+
onClick={() => {
|
|
2229
|
+
if (isSorting !== `-${item.key}`) {
|
|
2230
|
+
const copy = {
|
|
2231
|
+
...filters,
|
|
2232
|
+
order_by: `-${item.key}`,
|
|
2233
|
+
}
|
|
2234
|
+
setIsSorting(`-${item.key}`)
|
|
2235
|
+
setFilters(copy)
|
|
2236
|
+
} else if (isSorting === `-${item.key}`) {
|
|
2237
|
+
return ""
|
|
2238
|
+
}
|
|
2239
|
+
}}
|
|
2240
|
+
>
|
|
2241
|
+
<FaSortAmountDown />
|
|
2242
|
+
Descending
|
|
2243
|
+
</span>
|
|
2244
|
+
</li>
|
|
2245
|
+
</ul>
|
|
2246
|
+
</>
|
|
2247
|
+
) : (
|
|
2248
|
+
item.name
|
|
2249
|
+
)
|
|
2250
|
+
}
|
|
2251
|
+
<div className="resizer"></div>
|
|
2252
|
+
</th>
|
|
2253
|
+
))
|
|
2254
|
+
}
|
|
2255
|
+
{
|
|
2256
|
+
props.actions && props.actions && <th></th>
|
|
2257
|
+
}
|
|
2258
|
+
</tr>
|
|
2259
|
+
</thead>
|
|
2260
|
+
<tbody className='tbody_'>
|
|
2261
|
+
{loading ? (
|
|
2262
|
+
<tr className='no-b no-hover'>
|
|
2263
|
+
<td colSpan={props.actions ? headers.length + 1 : headers.length} className="text-center no-b p-2">...chargement</td>
|
|
2264
|
+
</tr>
|
|
2265
|
+
) : dataFilters.length > 0 ? (
|
|
2266
|
+
dataFilters.map((row) => (
|
|
2267
|
+
<tr key={row.id} className={`${lineSelected === row.id && "selected"}`}>
|
|
2268
|
+
{
|
|
2269
|
+
headers.map((item, index, array) =>
|
|
2270
|
+
item.type === "date" ? (
|
|
2271
|
+
<td key={item.key} className=''>
|
|
2272
|
+
{
|
|
2273
|
+
item.formule ? item.formule(row) !== "-" ? DATETIME.formatDDMMYYYY(item.formule(row)) : "-" : row[`${item.key}`] !== "-" ? DATETIME.formatDDMMYYYY(row[`${item.key}`]) : "-"
|
|
2274
|
+
}
|
|
2275
|
+
</td>
|
|
2276
|
+
) : (
|
|
2277
|
+
item.type === "comment" ? (
|
|
2278
|
+
<td className='' key={item.key}>
|
|
2279
|
+
{
|
|
2280
|
+
item.formule ? (
|
|
2281
|
+
<>
|
|
2282
|
+
{item.formule(row) ? (
|
|
2283
|
+
<img src={table_com_icon2} alt='icon' title='click ' role='button' className='mx-auto icon spe-img' onClick={() => { setComment(item.formule(row)); setSecondInfoComment(item.formuleForComment ? item.formuleForComment(row) : ""); setShowModalComment(true) }} />
|
|
2284
|
+
) : (
|
|
2285
|
+
<img src={table_com_icon} alt='icon' className='mx-auto icon spe-img' />
|
|
2286
|
+
)}
|
|
2287
|
+
</>
|
|
2288
|
+
) :
|
|
2289
|
+
<>
|
|
2290
|
+
{row[`${item.key}`] ? (
|
|
2291
|
+
<img src={table_com_icon2} alt='icon' role='button' className='mx-auto icon spe-img' onClick={() => { setComment(row[`${item.key}`]); setSecondInfoComment(item.formuleForComment ? item.formuleForComment(row) : ""); setShowModalComment(true) }} />
|
|
2292
|
+
) : (
|
|
2293
|
+
<img src={table_com_icon} alt='icon' className='mx-auto icon spe-img' />
|
|
2294
|
+
)}
|
|
2295
|
+
</>}
|
|
2296
|
+
</td>
|
|
2297
|
+
) : (
|
|
2298
|
+
item.type === "choice" ? (
|
|
2299
|
+
<td key={item.key} className='ps-1'>
|
|
2300
|
+
{
|
|
2301
|
+
item.formule ? (
|
|
2302
|
+
<div className="mx-auto" title={item.formule(row)[language]}>
|
|
2303
|
+
{
|
|
2304
|
+
item.formule(row).icon
|
|
2305
|
+
}
|
|
2306
|
+
</div>
|
|
2307
|
+
) : "-"
|
|
2308
|
+
}
|
|
2309
|
+
</td>
|
|
2310
|
+
) : (
|
|
2311
|
+
item.type === "amount" ? (
|
|
2312
|
+
<td key={item.key} className='ps-1'>
|
|
2313
|
+
{
|
|
2314
|
+
item.formule ? item.formule(row) : sep_mil(row[`${item.key}`])
|
|
2315
|
+
}
|
|
2316
|
+
</td>
|
|
2317
|
+
) : (
|
|
2318
|
+
item.type === "description" ? (
|
|
2319
|
+
<td key={item.key} className='ps-1'>
|
|
2320
|
+
{
|
|
2321
|
+
item.formule ? (
|
|
2322
|
+
item.formule(row).length < maxText ? (
|
|
2323
|
+
item.formule(row)
|
|
2324
|
+
) : (
|
|
2325
|
+
<FDropdown
|
|
2326
|
+
trigger={STRING.truncateText(item.formule(row), maxText ?? 75)}
|
|
2327
|
+
content={item.formule(row)}
|
|
2328
|
+
/>
|
|
2329
|
+
)
|
|
2330
|
+
) : (
|
|
2331
|
+
row[`${item.key}`].length < 75 ? (
|
|
2332
|
+
row[`${item.key}`]
|
|
2333
|
+
) : (
|
|
2334
|
+
<FDropdown
|
|
2335
|
+
trigger={STRING.truncateText(row[`${item.key}`], maxText ?? 75)}
|
|
2336
|
+
content={row[`${item.key}`]}
|
|
2337
|
+
/>
|
|
2338
|
+
)
|
|
2339
|
+
)
|
|
2340
|
+
}
|
|
2341
|
+
</td>
|
|
2342
|
+
) : (
|
|
2343
|
+
<td key={item.key} className=''>
|
|
2344
|
+
{
|
|
2345
|
+
item.formule ? item.formule(row) : row[`${item.key}`]
|
|
2346
|
+
}
|
|
2347
|
+
</td>
|
|
2348
|
+
)
|
|
2349
|
+
))))
|
|
2350
|
+
)
|
|
2351
|
+
}
|
|
2352
|
+
{
|
|
2353
|
+
props.actions && props.actions && (
|
|
2354
|
+
<td className='text-center'>
|
|
2355
|
+
<div className="" onClick={() => setLineSelected(row.id)}>
|
|
2356
|
+
<span className="doropdown-vertical-icon"
|
|
2357
|
+
data-bs-toggle="dropdown"
|
|
2358
|
+
aria-expanded="false">
|
|
2359
|
+
<BsThreeDotsVertical />
|
|
2360
|
+
</span>
|
|
2361
|
+
<ul className="dropdown-menu dropdown-menu-right">
|
|
2362
|
+
{props.actions?.map((act) => {
|
|
2363
|
+
const link = act.to ? act.to(row) : "";
|
|
2364
|
+
const hasPermission = !act.permission || center?.user_permissions?.includes(act.permission);
|
|
2365
|
+
const handleClick = () => {
|
|
2366
|
+
if (!hasPermission) return; // Empêche l'action si pas autorisé
|
|
2367
|
+
setLineSelected("");
|
|
2368
|
+
act.onclick?.(row);
|
|
2369
|
+
};
|
|
2370
|
+
|
|
2371
|
+
if (act.condition && !act.condition(row)) return null;
|
|
2372
|
+
|
|
2373
|
+
return (
|
|
2374
|
+
<li key={act.label}>
|
|
2375
|
+
{act.onclick ? (
|
|
2376
|
+
<span
|
|
2377
|
+
className={`dropdown-item ${!hasPermission ? 'wise-disabled text-muted' : ''}`}
|
|
2378
|
+
onClick={handleClick}
|
|
2379
|
+
title={!hasPermission ? "Vous n'avez pas l'autorisation requise pour cette action." : ""}
|
|
2380
|
+
style={{ cursor: hasPermission ? "pointer" : "not-allowed" }}
|
|
2381
|
+
>
|
|
2382
|
+
{act.label}
|
|
2383
|
+
</span>
|
|
2384
|
+
) : (
|
|
2385
|
+
<Link
|
|
2386
|
+
className={`dropdown-item ${!hasPermission ? 'wise-disabled text-muted' : ''}`}
|
|
2387
|
+
to={hasPermission ? link : "#"}
|
|
2388
|
+
title={!hasPermission ? "Vous n'avez pas l'autorisation requise pour cette action." : ""}
|
|
2389
|
+
onClick={(e) => {
|
|
2390
|
+
if (!hasPermission) e.preventDefault();
|
|
2391
|
+
else setLineSelected("");
|
|
2392
|
+
}}
|
|
2393
|
+
style={{ cursor: hasPermission ? "pointer" : "not-allowed" }}
|
|
2394
|
+
>
|
|
2395
|
+
{act.label}
|
|
2396
|
+
</Link>
|
|
2397
|
+
)}
|
|
2398
|
+
</li>
|
|
2399
|
+
);
|
|
2400
|
+
})}
|
|
2401
|
+
</ul>
|
|
2402
|
+
</div>
|
|
2403
|
+
</td>
|
|
2404
|
+
)
|
|
2405
|
+
}
|
|
2406
|
+
</tr>
|
|
2407
|
+
))
|
|
2408
|
+
) : (
|
|
2409
|
+
<tr className='no-b no-hover'>
|
|
2410
|
+
<td
|
|
2411
|
+
colSpan={headers.length}
|
|
2412
|
+
className="no-b no-hover"
|
|
2413
|
+
>
|
|
2414
|
+
<div className="col w-100 d-flex justify-content-center align-items-center">
|
|
2415
|
+
<img className="spe-illus-nodata" src={nodata_illus} alt="illus" />
|
|
2416
|
+
</div>
|
|
2417
|
+
</td>
|
|
2418
|
+
</tr>
|
|
2419
|
+
)}
|
|
2420
|
+
</tbody>
|
|
2421
|
+
{
|
|
2422
|
+
!loading && dataFilters.length > 0 && totalHeaders.length > 0 && (
|
|
2423
|
+
<tfoot className="f-tfoot_">
|
|
2424
|
+
<tr>
|
|
2425
|
+
{
|
|
2426
|
+
totalHeaders.map((item, index) => (
|
|
2427
|
+
<td
|
|
2428
|
+
key={`dsqf${index}mflkdgop`}
|
|
2429
|
+
colSpan={item.colSpan ?? 1}
|
|
2430
|
+
>
|
|
2431
|
+
{item.formule(data) ?? ""}
|
|
2432
|
+
</td>
|
|
2433
|
+
))
|
|
2434
|
+
}
|
|
2435
|
+
{
|
|
2436
|
+
props.actions && (
|
|
2437
|
+
<td className=''>
|
|
2438
|
+
</td>
|
|
2439
|
+
)
|
|
2440
|
+
}
|
|
2441
|
+
</tr>
|
|
2442
|
+
</tfoot>
|
|
2443
|
+
)
|
|
2444
|
+
}
|
|
2445
|
+
</table>
|
|
2446
|
+
</>
|
|
2447
|
+
);
|
|
2448
|
+
}
|