@visns-studio/visns-components 4.7.0 → 4.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/dist/104e5636d8ddb791614c.woff2 +0 -0
  2. package/dist/11fe6a83d647de5daf95.woff +0 -0
  3. package/dist/141e2a8c7836495afe2a.woff +0 -0
  4. package/dist/2ba5877f7079830b5383.woff +0 -0
  5. package/dist/2d6836f45b2037be41f3.woff +0 -0
  6. package/dist/399.0a0f3e0d21be1057d599.css +8 -0
  7. package/dist/399.b8f57fa3f8c0c10119e4.js +1 -0
  8. package/dist/47d566c3b1293dfd9d77.woff +0 -0
  9. package/dist/6282a13cbba671a71913.woff2 +0 -0
  10. package/dist/78266f551031aa9db127.woff +0 -0
  11. package/dist/7b7da89f1e3fdcbfe36c.woff2 +0 -0
  12. package/dist/7e78e8338af7efeda712.woff2 +0 -0
  13. package/dist/7fa387951673abf164b1.woff2 +0 -0
  14. package/dist/819d59862c2d0640aad8.woff +0 -0
  15. package/dist/b615e1a6c838ea059a56.woff +0 -0
  16. package/dist/b9b1aa739c660c4ce67c.woff2 +0 -0
  17. package/dist/c5f3640b11df9414facb.woff +0 -0
  18. package/dist/da26d162ff5af71d6590.woff2 +0 -0
  19. package/dist/dd5b2912dbf896310865.woff2 +0 -0
  20. package/dist/f282b331272463c1aa6c.woff2 +0 -0
  21. package/dist/index.css +2902 -0
  22. package/dist/index.js +2 -0
  23. package/dist/index.js.LICENSE.txt +150 -0
  24. package/dist/main.83b033670d64419bb497.css +1 -0
  25. package/dist/main.b1723d17cd2d3513ab62.js +1 -0
  26. package/dist/report.html +39 -0
  27. package/dist/runtime.33c276593b23f8035b8d.js +1 -0
  28. package/package.json +26 -6
  29. package/.idea/codeStyles/Project.xml +0 -50
  30. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  31. package/.idea/deployment.xml +0 -4
  32. package/.idea/modules.xml +0 -8
  33. package/.idea/php.xml +0 -19
  34. package/.idea/vcs.xml +0 -6
  35. package/.idea/visns-components.iml +0 -8
  36. package/.prettierrc.json +0 -7
  37. package/.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs +0 -541
  38. package/.yarn/releases/yarn-3.6.1.cjs +0 -874
  39. package/.yarnrc.yml +0 -7
  40. package/components/cms/DataGrid.jsx +0 -1461
  41. package/components/cms/DropZone.jsx +0 -349
  42. package/components/cms/Field.jsx +0 -802
  43. package/components/cms/Form.jsx +0 -476
  44. package/components/cms/generic/CmsDetail.jsx +0 -36
  45. package/components/cms/generic/CmsIndex.jsx +0 -73
  46. package/components/cms/generic/CmsSort.jsx +0 -125
  47. package/components/cms/sorting/Item.jsx +0 -115
  48. package/components/cms/sorting/List.jsx +0 -30
  49. package/components/crm/AsyncSelect.jsx +0 -125
  50. package/components/crm/Autocomplete.jsx +0 -174
  51. package/components/crm/Breadcrumb.jsx +0 -52
  52. package/components/crm/Call.jsx +0 -220
  53. package/components/crm/DataGrid.jsx +0 -2701
  54. package/components/crm/Download.jsx +0 -101
  55. package/components/crm/Fetch.jsx +0 -119
  56. package/components/crm/Field.jsx +0 -1557
  57. package/components/crm/Form.jsx +0 -1409
  58. package/components/crm/Loader.jsx +0 -29
  59. package/components/crm/MultiSelect.jsx +0 -78
  60. package/components/crm/Navigation.jsx +0 -619
  61. package/components/crm/Notification.jsx +0 -197
  62. package/components/crm/QrCode.jsx +0 -83
  63. package/components/crm/Select.jsx +0 -58
  64. package/components/crm/SelectList.jsx +0 -21
  65. package/components/crm/TableFilter.jsx +0 -198
  66. package/components/crm/auth/Login.jsx +0 -223
  67. package/components/crm/auth/Profile.jsx +0 -280
  68. package/components/crm/auth/Reset.jsx +0 -111
  69. package/components/crm/auth/Verify.jsx +0 -174
  70. package/components/crm/auth/styles/Login.module.css +0 -243
  71. package/components/crm/auth/styles/Profile.module.css +0 -222
  72. package/components/crm/auth/styles/Reset.module.css +0 -216
  73. package/components/crm/auth/styles/Verify.module.css +0 -216
  74. package/components/crm/generic/AuditLog.jsx +0 -108
  75. package/components/crm/generic/AuditLogs.jsx +0 -115
  76. package/components/crm/generic/GenericAuth.jsx +0 -166
  77. package/components/crm/generic/GenericDashboard.jsx +0 -42
  78. package/components/crm/generic/GenericDetail.jsx +0 -1499
  79. package/components/crm/generic/GenericDynamic.jsx +0 -915
  80. package/components/crm/generic/GenericFormBuilder.jsx +0 -1765
  81. package/components/crm/generic/GenericIndex.jsx +0 -376
  82. package/components/crm/generic/GenericMain.jsx +0 -129
  83. package/components/crm/generic/GenericSort.jsx +0 -188
  84. package/components/crm/generic/NotificationList.jsx +0 -64
  85. package/components/crm/generic/styles/AuditLog.module.css +0 -147
  86. package/components/crm/generic/styles/AuditLogs.module.css +0 -92
  87. package/components/crm/generic/styles/GenericDetail.module.css +0 -634
  88. package/components/crm/generic/styles/GenericDynamic.module.css +0 -932
  89. package/components/crm/generic/styles/GenericFormBuilder.module.css +0 -944
  90. package/components/crm/generic/styles/GenericIndex.module.css +0 -247
  91. package/components/crm/generic/styles/GenericMain.module.css +0 -91
  92. package/components/crm/generic/styles/GenericSort.module.css +0 -123
  93. package/components/crm/generic/styles/NotificationList.module.css +0 -67
  94. package/components/crm/sorting/Item.jsx +0 -117
  95. package/components/crm/sorting/List.jsx +0 -32
  96. package/components/crm/sorting/styles/Item.module.css +0 -68
  97. package/components/crm/sorting/styles/List.module.css +0 -68
  98. package/components/crm/styles/AsyncSelect.module.css +0 -8
  99. package/components/crm/styles/Autocomplete.module.css +0 -44
  100. package/components/crm/styles/DataGrid.module.css +0 -210
  101. package/components/crm/styles/Field.module.css +0 -311
  102. package/components/crm/styles/Form.module.css +0 -499
  103. package/components/crm/styles/Loader.module.css +0 -94
  104. package/components/crm/styles/MultiSelect.module.css +0 -8
  105. package/components/crm/styles/Navigation.module.css +0 -978
  106. package/components/crm/styles/Notification.module.css +0 -147
  107. package/components/crm/styles/QrCode.module.css +0 -87
  108. package/components/crm/styles/TableFilter.module.css +0 -52
  109. package/components/styles/global.css +0 -73
  110. package/index.js +0 -86
@@ -1,376 +0,0 @@
1
- import '../../styles/global.css';
2
-
3
- import React, { useCallback, useEffect, useRef, useState } from 'react';
4
- import { Outlet } from 'react-router-dom';
5
- import { toast } from 'react-toastify';
6
- import { saveAs } from 'file-saver';
7
- import _ from 'lodash';
8
-
9
- import CustomFetch from '../Fetch';
10
- import Download from '../Download';
11
- import Field from '../Field';
12
- import Table from '../DataGrid';
13
- import TableFilter from '../TableFilter';
14
-
15
- import styles from './styles/GenericIndex.module.css';
16
-
17
- function useWindowHeight() {
18
- const [windowHeight, setWindowHeight] = useState(window.innerHeight);
19
-
20
- useEffect(() => {
21
- const handleResize = () => setWindowHeight(window.innerHeight);
22
- window.addEventListener('resize', handleResize);
23
- return () => window.removeEventListener('resize', handleResize);
24
- }, []);
25
-
26
- return windowHeight;
27
- }
28
-
29
- function useConfig(setting, tabs, filters, setRowsSelected, tableSetting) {
30
- const [config, setConfig] = useState({});
31
- const [subnav, setSubnav] = useState(filters || []);
32
-
33
- useEffect(() => {
34
- setConfig({
35
- ajaxSetting: setting.ajaxSetting,
36
- form: setting.form,
37
- columns: setting.columns,
38
- setRowsSelected,
39
- settings: setting.settings,
40
- tableSetting,
41
- type: setting.type ? setting.type : 'table',
42
- });
43
- setSubnav(filters);
44
- }, [setting, filters, setRowsSelected, tableSetting]);
45
-
46
- useEffect(() => {
47
- if (tabs?.length > 0 && subnav) {
48
- const activeTab = subnav.find((s) => s.show);
49
- const activeTabConfig = tabs.find((t) => t.id === activeTab?.id);
50
-
51
- if (activeTabConfig) {
52
- setConfig((currentConfig) => ({
53
- ...currentConfig,
54
- id: activeTabConfig.id,
55
- ajaxSetting: activeTabConfig.ajaxSetting,
56
- form: activeTabConfig.form,
57
- columns: activeTabConfig.columns,
58
- settings: activeTabConfig.settings,
59
- type: activeTabConfig.type ? activeTabConfig.type : 'table',
60
- }));
61
- }
62
- }
63
- }, [subnav, tabs]);
64
-
65
- return { config, setConfig, subnav, setSubnav };
66
- }
67
-
68
- const ReportForm = ({ config, userProfile }) => {
69
- const [formData, setFormData] = useState({});
70
-
71
- const handleChange = (e) => {
72
- const {
73
- value,
74
- dataset: { name },
75
- } = e.target;
76
-
77
- setFormData((prevData) => ({ ...prevData, [name]: value }));
78
- };
79
-
80
- const handleChangeDate = (date, id) => {
81
- setFormData((prevData) => ({ ...prevData, [id]: date }));
82
- };
83
-
84
- const handleChangeSelect = (inputValue, action, id) => {
85
- setFormData((prevData) => ({ ...prevData, [id]: inputValue }));
86
- };
87
-
88
- const handleExport = async (e) => {
89
- try {
90
- if (e) {
91
- e.preventDefault();
92
- }
93
-
94
- const missingFields = config.form.filters
95
- .filter(
96
- (item) => item.required === true && formData[item.id] === ''
97
- )
98
- .map((item) => item.label);
99
-
100
- if (missingFields.length > 0) {
101
- const fieldNames = missingFields.join(', ');
102
- const errorMessage = `Please fill in a value for the following field(s): ${fieldNames}.`;
103
- toast.error(errorMessage);
104
- } else {
105
- const res = await Download(
106
- config.form.url,
107
- config.form.method,
108
- formData
109
- );
110
-
111
- if (res.data.error) {
112
- toast.error(res.data.error);
113
- } else {
114
- // Assuming the response contains a Blob or similar data
115
- if (res.data && res.data instanceof Blob) {
116
- const fileName = `${config.form.filename}`;
117
- saveAs(res.data, fileName);
118
- } else {
119
- // Handle the case where the response is not a Blob
120
- toast.error('Invalid file format received.');
121
- }
122
- }
123
- }
124
- } catch (err) {
125
- console.error(err);
126
- }
127
- };
128
-
129
- useEffect(() => {
130
- const tmpForm = config.form?.filters.reduce((acc, item) => {
131
- acc[item.id] = '';
132
- return acc;
133
- }, {});
134
- setFormData(tmpForm);
135
- }, [config.form?.filters]);
136
-
137
- return (
138
- <div className="formcontainer">
139
- <form className="modalForm">
140
- {config.form?.filters.map((item, key) => (
141
- <Field
142
- api={userProfile.settings.api}
143
- autocompleteCallback={() => {}}
144
- childDropdownCallback={() => {}}
145
- fetchData={() => {}}
146
- formData={formData}
147
- inputClass={''}
148
- inputValue={formData[item.id]}
149
- key={`filter-fields-${key}`}
150
- mapbox={{}}
151
- onChange={handleChange}
152
- onChangeCheckbox={() => {}}
153
- onChangeDate={handleChangeDate}
154
- onChangeNumberFormat={() => {}}
155
- onChangeRicheditor={() => {}}
156
- onChangeSelect={handleChangeSelect}
157
- onChangeToggle={() => {}}
158
- settings={item}
159
- setFormData={setFormData}
160
- style={userProfile.settings.style}
161
- uploadProgress={0}
162
- userProfile={userProfile}
163
- />
164
- ))}
165
- <div className="formItem fwItem lastItem">
166
- <button className="btn modalsave" onClick={handleExport}>
167
- Export
168
- </button>
169
- </div>
170
- </form>
171
- </div>
172
- );
173
- };
174
-
175
- function GenericIndex({ layout = 'full', setting, userProfile }) {
176
- const gridRef = useRef(null);
177
- const [rowsSelected, setRowsSelected] = useState({});
178
- const [total, setTotal] = useState(0);
179
- const windowHeight = useWindowHeight();
180
- const { config, setConfig, subnav, setSubnav } = useConfig(
181
- setting,
182
- setting.tabs,
183
- setting.filters,
184
- setRowsSelected,
185
- setting.tableSetting
186
- );
187
-
188
- const handleCheckboxUpdate = useCallback(async () => {
189
- try {
190
- const { data, method, message, url } = setting?.functions
191
- ?.checkboxUpdate
192
- ? setting.functions.checkboxUpdate
193
- : config.form.functions.checkboxUpdate;
194
- if (!Object.keys(rowsSelected).length) {
195
- toast.warning(message.warning);
196
- return;
197
- }
198
- const res = await CustomFetch(url, method, {
199
- ...data,
200
- rows: rowsSelected,
201
- });
202
- if (res.data.error === '') {
203
- toast.success(message.success);
204
- gridRef.current.reload();
205
- } else {
206
- toast.error(message.error);
207
- }
208
- } catch (error) {
209
- console.error(error);
210
- }
211
- }, [rowsSelected, setting?.functions?.checkboxUpdate]);
212
-
213
- const renderTable = useCallback(() => {
214
- const isConfigValid = (config) => {
215
- return (
216
- config.ajaxSetting &&
217
- config.form &&
218
- config.columns &&
219
- config.settings
220
- );
221
- };
222
-
223
- const renderTableComponent = () => (
224
- <Table
225
- {...config}
226
- ref={gridRef}
227
- gridHeight={windowHeight * 0.65}
228
- setConfig={setConfig}
229
- setTotal={setTotal}
230
- style={userProfile?.settings?.style || {}}
231
- userProfile={userProfile}
232
- />
233
- );
234
-
235
- if (subnav) {
236
- // Find the active subnav item with show: true
237
- const activeSubnav = subnav.find((item) => item.show === true);
238
-
239
- // Check if the config.id matches the active subnav id
240
- if (
241
- activeSubnav &&
242
- activeSubnav.id === config.id &&
243
- isConfigValid(config)
244
- ) {
245
- return renderTableComponent();
246
- }
247
-
248
- // Check for active alternative subnav
249
- const activeAltSubNav = subnav.find(
250
- (item) =>
251
- item.class === 'subactive' || item.class === 'activetab'
252
- );
253
-
254
- const activeTabExist =
255
- config.ajaxSetting?.where?.some(
256
- (w) =>
257
- w.id === activeAltSubNav?.id &&
258
- parseInt(w.value) === parseInt(activeAltSubNav?.value)
259
- ) || false;
260
-
261
- if (isConfigValid(config) && activeTabExist) {
262
- return renderTableComponent();
263
- }
264
- } else if (isConfigValid(config)) {
265
- return renderTableComponent();
266
- }
267
-
268
- return null;
269
- }, [config, subnav, windowHeight, userProfile, setConfig, setTotal]);
270
-
271
- const renderContentBasedOnType = useCallback(() => {
272
- switch (config.type) {
273
- case 'table':
274
- return renderTable();
275
- case 'report':
276
- return <ReportForm config={config} userProfile={userProfile} />;
277
- default:
278
- return renderTable(); // Fallback to table if no type is specified or recognized
279
- }
280
- }, [config, renderTable]);
281
-
282
- const renderContent = useCallback(() => {
283
- if (subnav?.length > 0) {
284
- return (
285
- <div className={styles.grid__subrow}>
286
- {layout === 'simple' ? (
287
- <div className={styles.grid__full}>
288
- <div className={styles.tabcontent}>
289
- <div className={styles.tabcontent__menu}>
290
- <TableFilter
291
- filters={subnav}
292
- setFilters={setSubnav}
293
- setSettings={setConfig}
294
- type={layout}
295
- />
296
- </div>
297
- <div className={styles.tabcontent__main}>
298
- {renderContentBasedOnType()}
299
- </div>
300
- </div>
301
- </div>
302
- ) : (
303
- <>
304
- <div className={styles.grid__subnav}>
305
- <TableFilter
306
- filters={subnav}
307
- setFilters={setSubnav}
308
- setSettings={setConfig}
309
- type={layout}
310
- />
311
- </div>
312
- <div className={styles.grid__subcontent}>
313
- {renderContentBasedOnType()}
314
- </div>
315
- </>
316
- )}
317
- </div>
318
- );
319
- } else {
320
- return (
321
- <div className={styles.grid__full}>
322
- {renderContentBasedOnType()}
323
- </div>
324
- );
325
- }
326
- }, [layout, subnav, setSubnav, setConfig, renderTable]);
327
-
328
- return (
329
- <>
330
- <div className={styles.grid}>
331
- <div className={styles.grid__row}>
332
- <div
333
- className={`${styles.grid__full} ${
334
- layout === 'full'
335
- ? styles.crmtitle
336
- : styles.crmtitleSimple
337
- }`}
338
- >
339
- <h1>{setting.page?.title}</h1>
340
- <div className={styles.titleInfo}>
341
- <span>
342
- [<strong>{total}</strong> Total{' '}
343
- {setting.page?.title}]
344
- </span>
345
- </div>
346
- </div>
347
- </div>
348
- </div>
349
-
350
- <div className={styles.grid}>{renderContent()}</div>
351
- <Outlet />
352
- {setting.functions?.checkboxUpdate && (
353
- <div className={styles.polActions}>
354
- <button
355
- className={styles.btn}
356
- onClick={handleCheckboxUpdate}
357
- >
358
- {setting.functions.checkboxUpdate.label || 'Update'}
359
- </button>
360
- </div>
361
- )}
362
- {config?.form?.functions?.checkboxUpdate && (
363
- <div className={styles.polActions}>
364
- <button
365
- className={styles.btn}
366
- onClick={handleCheckboxUpdate}
367
- >
368
- {config.form.functions.checkboxUpdate.label || 'Update'}
369
- </button>
370
- </div>
371
- )}
372
- </>
373
- );
374
- }
375
-
376
- export default GenericIndex;
@@ -1,129 +0,0 @@
1
- import '../../styles/global.css';
2
-
3
- import React, { useState } from 'react';
4
- import { Routes, Route, Navigate } from 'react-router-dom';
5
-
6
- import Call from '../Call';
7
- import Loader from '../Loader';
8
- import Navigation from '../Navigation';
9
-
10
- import styles from './styles/GenericMain.module.css';
11
-
12
- const GenericMain = ({
13
- layout = 'full',
14
- logo,
15
- navigation,
16
- routeConfig,
17
- setSystemAuth,
18
- setUserProfile,
19
- themeType,
20
- userProfile,
21
- }) => {
22
- const [incomingCallData, setIncomingCallData] = useState({});
23
-
24
- // Function to extract route parameters
25
- const extractRouteParams = (path) => {
26
- const params = path.match(/:\w+/g) || [];
27
- return params.map((param) => param.substring(1));
28
- };
29
-
30
- // Recursive function to render routes
31
- const renderRoutes = (routes) => {
32
- return routes.map((route, index) => {
33
- let elementProps = {
34
- userProfile: userProfile,
35
- setUserProfile: setUserProfile,
36
- };
37
-
38
- const routeParams = extractRouteParams(route.path);
39
- const extraParams = routeParams.filter(
40
- (param) => param !== 'dataId'
41
- );
42
-
43
- if (routeParams.includes('dataId')) {
44
- elementProps.urlParam = 'dataId';
45
- }
46
-
47
- if (extraParams.length > 0) {
48
- elementProps.extraUrlParam = extraParams;
49
- }
50
-
51
- let element = route.element
52
- ? React.cloneElement(route.element, elementProps)
53
- : null;
54
-
55
- if (route.children && route.children.length > 0) {
56
- // If the route has children, render them recursively
57
- return (
58
- <Route key={index} path={route.path}>
59
- {renderRoutes(route.children)}
60
- </Route>
61
- );
62
- } else {
63
- return (
64
- <Route key={index} path={route.path} element={element} />
65
- );
66
- }
67
- });
68
- };
69
-
70
- return layout === 'full' ? (
71
- <div>
72
- <header
73
- className={
74
- themeType === 'alternate'
75
- ? styles.headerAlternate
76
- : styles.header
77
- }
78
- >
79
- <Navigation
80
- layout={layout}
81
- logo={logo}
82
- navConfig={navigation}
83
- setSystemAuth={setSystemAuth}
84
- themeType={themeType}
85
- userProfile={userProfile}
86
- />
87
- </header>
88
- <main className={styles.content}>
89
- <div className={styles['content-main']} id="app">
90
- <div className={styles.padding}>
91
- <Routes>
92
- {renderRoutes(routeConfig)}
93
- {/* Add a wildcard route for handling unknown paths */}
94
- <Route
95
- path="*"
96
- element={<Navigate to="/" replace />}
97
- />
98
- </Routes>
99
- </div>
100
- <Call incomingCallData={incomingCallData} />
101
- <Loader />
102
- </div>
103
- </main>
104
- </div>
105
- ) : (
106
- <Navigation
107
- layout={layout}
108
- logo={logo}
109
- navConfig={navigation}
110
- setSystemAuth={setSystemAuth}
111
- themeType={themeType}
112
- userProfile={userProfile}
113
- >
114
- <div className={styles['content-main']} id="app">
115
- <div className={styles.paddingSimple}>
116
- <Routes>
117
- {renderRoutes(routeConfig)}
118
- {/* Add a wildcard route for handling unknown paths */}
119
- <Route path="*" element={<Navigate to="/" replace />} />
120
- </Routes>
121
- </div>
122
- <Call incomingCallData={incomingCallData} />
123
- <Loader />
124
- </div>
125
- </Navigation>
126
- );
127
- };
128
-
129
- export default GenericMain;
@@ -1,188 +0,0 @@
1
- import React, { useState, useEffect } from 'react';
2
- import { useLocation, useParams } from 'react-router-dom';
3
- import { arrayMoveImmutable } from 'array-move';
4
- import { toast } from 'react-toastify';
5
- import CustomFetch from '../../crm/Fetch';
6
- import SortableList from '../sorting/List';
7
- import Breadcrumb from '../Breadcrumb';
8
- import styles from './styles/GenericSort.module.css';
9
-
10
- // Utility function to convert camelCase to space-separated words with uppercase first letters
11
- function camelCaseToUcFirst(str) {
12
- return str
13
- .replace(/([A-Z])/g, ' $1') // Add a space before each uppercase letter
14
- .replace(/^./, function (str) {
15
- return str.toUpperCase();
16
- }) // Capitalize the first letter
17
- .trim(); // Remove leading and trailing whitespace
18
- }
19
-
20
- const ChildSort = ({ item, url }) => {
21
- const [data, setData] = useState(item.child);
22
-
23
- const onSortEnd = ({ oldIndex, newIndex }) => {
24
- setData((prevItem) => arrayMoveImmutable(prevItem, oldIndex, newIndex));
25
- };
26
-
27
- useEffect(() => {
28
- if (data.length > 0) {
29
- CustomFetch(
30
- `${url}/sort_update`,
31
- 'POST',
32
- {
33
- list: data,
34
- },
35
- function (result) {
36
- if (result.error === '') {
37
- toast.success('Sort updated successfully');
38
- } else {
39
- toast.error(String(result.error));
40
- }
41
- }
42
- );
43
- }
44
- }, [data]);
45
-
46
- return (
47
- <>
48
- <h1>{item.label}</h1>
49
- <SortableList
50
- items={data}
51
- onSortEnd={onSortEnd}
52
- axis="xy"
53
- helperClass="dragitem"
54
- transitionDuration={250}
55
- useDragHandle
56
- />
57
- </>
58
- );
59
- };
60
-
61
- const GenericSort = ({ category = false, layout = 'full' }) => {
62
- const location = useLocation();
63
- const routeParams = useParams();
64
- const {
65
- form,
66
- page = {}, // Provide a default empty object for page
67
- paramValue,
68
- } = location.state || {}; // Safely access location.state
69
-
70
- const [sortData, setSortData] = useState([]);
71
- const url = form?.url;
72
- const data = page?.data || {}; // Safely access data from page, default to an empty object
73
-
74
- const onSortEnd = ({ oldIndex, newIndex }) => {
75
- setSortData((prevItem) =>
76
- arrayMoveImmutable(prevItem, oldIndex, newIndex)
77
- );
78
- };
79
-
80
- const sortList = async () => {
81
- try {
82
- let fetchUrl = url;
83
- let payload = {};
84
-
85
- if (form?.json) {
86
- fetchUrl = fetchUrl + '/jsonSortList';
87
- payload.id = paramValue;
88
- } else {
89
- fetchUrl = fetchUrl + '/sort_list';
90
- }
91
-
92
- const res = await CustomFetch(fetchUrl, 'POST', payload);
93
- setSortData(res.data);
94
- } catch (err) {
95
- console.log(err);
96
- }
97
- };
98
-
99
- const sortUpdate = async () => {
100
- try {
101
- let fetchUrl = url;
102
- let payload = {
103
- list: sortData,
104
- };
105
-
106
- if (form?.json) {
107
- fetchUrl = fetchUrl + '/jsonSortUpdate';
108
- payload.id = paramValue;
109
- } else {
110
- fetchUrl = fetchUrl + '/sort_update';
111
- }
112
-
113
- if (category === false) {
114
- if (sortData.length > 0) {
115
- const res = await CustomFetch(fetchUrl, 'POST', payload);
116
-
117
- if (res.data.error !== '') {
118
- toast.error(String(res.data.error));
119
- }
120
- }
121
- }
122
- } catch (err) {
123
- console.log(err);
124
- }
125
- };
126
-
127
- useEffect(() => {
128
- sortUpdate();
129
- }, [sortData]);
130
-
131
- useEffect(() => {
132
- sortList();
133
- }, []);
134
-
135
- return (
136
- <>
137
- <div className={styles.grid}>
138
- <div className={styles.grid__row}>
139
- <div
140
- className={`${styles.grid__full} ${
141
- layout === 'full'
142
- ? styles.crmtitle
143
- : styles.crmtitleSimple
144
- }`}
145
- >
146
- <Breadcrumb
147
- data={{
148
- label: camelCaseToUcFirst(routeParams.dataId),
149
- }} // Use utility function here
150
- page={{
151
- parentTitle: 'Settings',
152
- parentUrl: '/settings',
153
- titleKey: 'label',
154
- }}
155
- />
156
- </div>
157
- </div>
158
- </div>
159
- <div className={styles.grid}>
160
- <div className={styles.grid__row}>
161
- <div className={styles.grid__full}>
162
- {category === false ? (
163
- <SortableList
164
- items={sortData}
165
- onSortEnd={onSortEnd}
166
- axis="xy"
167
- helperClass={styles.dragitem}
168
- transitionDuration={250}
169
- useDragHandle
170
- />
171
- ) : (
172
- sortData.length > 0 &&
173
- sortData.map((item) => (
174
- <ChildSort
175
- key={`category-${item.id}`}
176
- item={item}
177
- url={url}
178
- />
179
- ))
180
- )}
181
- </div>
182
- </div>
183
- </div>
184
- </>
185
- );
186
- };
187
-
188
- export default GenericSort;