@visns-studio/visns-components 4.10.48 → 5.0.1-8.1

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 (61) hide show
  1. package/package.json +29 -29
  2. package/src/components/cms/Field.jsx +39 -63
  3. package/src/components/crm/AsyncSelect.jsx +121 -15
  4. package/src/components/crm/Breadcrumb.jsx +2 -18
  5. package/src/components/crm/DataGrid.jsx +51 -424
  6. package/src/components/crm/Field.jsx +185 -358
  7. package/src/components/crm/Form.jsx +104 -92
  8. package/src/components/crm/MultiSelect.jsx +66 -45
  9. package/src/components/crm/Navigation.jsx +9 -92
  10. package/src/components/crm/QuickAction.jsx +1 -0
  11. package/src/components/crm/auth/Login.jsx +9 -1
  12. package/src/components/crm/auth/Profile.jsx +4 -2
  13. package/src/components/crm/auth/styles/Login.module.scss +52 -82
  14. package/src/components/crm/auth/styles/Profile.module.scss +150 -44
  15. package/src/components/crm/auth/styles/Reset.module.scss +55 -37
  16. package/src/components/crm/auth/styles/Verify.module.scss +55 -76
  17. package/src/components/crm/generic/GenericAuth.jsx +12 -5
  18. package/src/components/crm/generic/GenericDashboard.jsx +30 -340
  19. package/src/components/crm/generic/GenericDetail.jsx +534 -86
  20. package/src/components/crm/generic/GenericDynamic.jsx +76 -94
  21. package/src/components/crm/generic/GenericEditableTable.jsx +407 -0
  22. package/src/components/crm/generic/GenericFormBuilder.jsx +19 -79
  23. package/src/components/crm/generic/GenericIndex.jsx +1 -2
  24. package/src/components/crm/generic/styles/AuditLog.module.scss +4 -37
  25. package/src/components/crm/generic/styles/AuditLogs.module.scss +0 -51
  26. package/src/components/crm/generic/styles/GenericDetail.module.scss +263 -244
  27. package/src/components/crm/generic/styles/GenericDynamic.module.scss +100 -198
  28. package/src/components/crm/generic/styles/GenericEditableTable.module.scss +178 -0
  29. package/src/components/crm/generic/styles/GenericFormBuilder.module.scss +63 -101
  30. package/src/components/crm/generic/styles/GenericIndex.module.scss +46 -66
  31. package/src/components/crm/generic/styles/GenericMain.module.scss +7 -7
  32. package/src/components/crm/generic/styles/GenericSort.module.scss +0 -36
  33. package/src/components/crm/generic/styles/NotificationList.module.scss +1 -32
  34. package/src/components/crm/styles/Autocomplete.module.scss +12 -20
  35. package/src/components/crm/styles/DataGrid.module.scss +28 -86
  36. package/src/components/crm/styles/Field.module.scss +72 -252
  37. package/src/components/crm/styles/Form.module.scss +141 -450
  38. package/src/components/crm/styles/Navigation.module.scss +356 -507
  39. package/src/components/crm/styles/Notification.module.scss +1 -0
  40. package/src/components/crm/styles/QrCode.module.scss +4 -18
  41. package/src/components/crm/styles/SwitchAccount.module.scss +0 -1
  42. package/src/components/crm/styles/TableFilter.module.scss +2 -1
  43. package/src/components/styles/global.css +164 -34
  44. package/src/index.js +0 -8
  45. package/src/components/crm/generic/styles/GenericDashboard.module.scss +0 -325
  46. package/src/components/crm/sketch/SketchField.jsx +0 -395
  47. package/src/components/crm/sketch/arrow.jsx +0 -108
  48. package/src/components/crm/sketch/circle.jsx +0 -75
  49. package/src/components/crm/sketch/default-tool.jsx +0 -16
  50. package/src/components/crm/sketch/fabrictool.jsx +0 -22
  51. package/src/components/crm/sketch/history.jsx +0 -144
  52. package/src/components/crm/sketch/json/config.json +0 -14
  53. package/src/components/crm/sketch/line.jsx +0 -64
  54. package/src/components/crm/sketch/pan.jsx +0 -48
  55. package/src/components/crm/sketch/pencil.jsx +0 -36
  56. package/src/components/crm/sketch/rectangle-label-object.jsx +0 -69
  57. package/src/components/crm/sketch/rectangle-label.jsx +0 -93
  58. package/src/components/crm/sketch/rectangle.jsx +0 -76
  59. package/src/components/crm/sketch/select.jsx +0 -16
  60. package/src/components/crm/sketch/tools.jsx +0 -11
  61. package/src/components/crm/sketch/utils.jsx +0 -67
@@ -1,11 +1,17 @@
1
1
  .formItem {
2
2
  width: 50%;
3
- padding: 0.5em;
4
3
  position: relative;
5
4
  box-sizing: border-box;
6
5
 
6
+ h1 {
7
+ text-align: center;
8
+ font-size: 1.25rem;
9
+ }
10
+
7
11
  .fi__label {
8
12
  position: relative;
13
+ display: flex;
14
+ align-items: center;
9
15
  }
10
16
 
11
17
  .fi__span {
@@ -13,9 +19,9 @@
13
19
  transition: all 200ms;
14
20
  opacity: 0.8;
15
21
  left: 0;
16
- padding: 19px 20px;
17
22
  transform-origin: top left;
18
23
  cursor: text;
24
+ padding: 0 1rem;
19
25
  }
20
26
 
21
27
  .fi__div {
@@ -23,14 +29,14 @@
23
29
  opacity: 0.8;
24
30
  left: 0;
25
31
  padding: 19px 13px;
26
- border-radius: var(--br);
27
- border: 1px solid rgba(var(--paragraph-color-rgb), 0.15);
32
+ border-radius: var(--radius);
33
+ border: 1px solid rgba(var(--paragraph-rgb), 0.15);
28
34
  box-shadow: none;
29
35
  }
30
36
 
31
37
  .fi__toggle {
32
38
  width: max-content;
33
- padding: 0px 10px 0px 0;
39
+ padding: 0 10px 0 0;
34
40
  box-sizing: border-box;
35
41
  display: inline;
36
42
  }
@@ -43,8 +49,10 @@
43
49
  }
44
50
  }
45
51
 
46
- .fwItem {
47
- flex-basis: 100%;
52
+ .fwItem,
53
+ .fwBuilderItem {
54
+ grid-column: 1 / -1;
55
+ width: 100%;
48
56
  }
49
57
 
50
58
  .lastItem {
@@ -72,16 +80,33 @@
72
80
  flex-wrap: wrap;
73
81
  }
74
82
 
83
+ .loginlogo {
84
+ display: block;
85
+ width: 100%;
86
+ max-width: 200px;
87
+ height: auto;
88
+ margin: 0 auto;
89
+ padding-bottom: 1rem;
90
+ }
91
+
92
+ .logincontainer {
93
+ width: 100%;
94
+ min-height: 100vh;
95
+ display: grid;
96
+ place-items: center;
97
+ padding: 1rem;
98
+ }
99
+
75
100
  .login {
76
101
  width: 35rem;
77
- height: auto;
78
102
  padding: 1rem;
79
103
  margin: 0;
80
- display: flex;
81
- flex-wrap: wrap;
104
+ display: grid;
105
+ grid-template-columns: 1fr;
106
+ gap: 0.5rem;
82
107
 
83
108
  > .formItem {
84
- padding: 0.25em 0;
109
+ padding: 0;
85
110
 
86
111
  small {
87
112
  position: absolute;
@@ -94,12 +119,11 @@
94
119
  }
95
120
 
96
121
  > .loginitem {
97
- width: 100%;
122
+ grid-column: 1 / -1;
98
123
  padding: 0.25em 0;
99
124
 
100
125
  label {
101
126
  width: 100%;
102
- padding-bottom: 0.25rem;
103
127
  }
104
128
 
105
129
  button {
@@ -108,27 +132,28 @@
108
132
  }
109
133
  }
110
134
 
111
- .forgotten {
112
- span {
113
- display: block;
114
- text-align: center;
115
- color: var(--paragraph-color);
116
- padding: 1rem 0;
135
+ .forgotten span {
136
+ display: block;
137
+ text-align: center;
138
+ color: var(--paragraph-color);
139
+ padding: 1rem 0;
117
140
 
118
- a {
119
- color: var(--highlight-color);
120
- text-decoration: none;
121
- }
141
+ a {
142
+ color: var(--secondary-color);
143
+ text-decoration: none;
122
144
  }
123
145
  }
124
146
 
125
147
  .lcontainer {
126
- --sidebar-width: 35%;
127
148
  min-height: 100vh;
149
+ display: flex;
150
+ align-items: center;
151
+ justify-content: center;
128
152
  }
129
153
 
130
154
  .lwrap {
131
- display: flex;
155
+ display: grid;
156
+ grid-template-columns: var(--sidebar-width) 1fr;
132
157
  }
133
158
 
134
159
  .aside {
@@ -139,53 +164,6 @@
139
164
  width: var(--sidebar-width);
140
165
  }
141
166
 
142
- .fwItem {
143
- flex-basis: 100%;
144
- }
145
-
146
- .lastItem .btn {
147
- width: 100%;
148
- }
149
-
150
- .login .formItem {
151
- padding: 0.25em 0;
152
- }
153
-
154
- .login .formItem small {
155
- position: absolute;
156
- width: 18px;
157
- height: 18px;
158
- right: 18px;
159
- top: 18px;
160
- opacity: 0.15;
161
- }
162
-
163
- .login .loginitem {
164
- width: 100%;
165
- padding: 0.25em 0;
166
- }
167
-
168
- .login .loginitem label {
169
- width: 100%;
170
- padding-bottom: 0.25rem;
171
- }
172
-
173
- .login .loginitem button {
174
- width: 100%;
175
- }
176
-
177
- .forgotten span {
178
- display: block;
179
- text-align: center;
180
- color: var(--paragraph-color);
181
- padding: 1rem 0;
182
- }
183
-
184
- .forgotten span a {
185
- color: var(--highlight-color);
186
- text-decoration: none;
187
- }
188
-
189
167
  .btn {
190
168
  width: max-content;
191
169
  display: inline-block;
@@ -207,9 +185,10 @@
207
185
  input:not(:placeholder-shown) + .fi__span,
208
186
  textarea:not(:placeholder-shown) + .fi__span,
209
187
  select:not(:placeholder-shown) + .fi__span {
210
- transform: translateY(-40%) translateX(10px) scale(0.75);
188
+ transform: translateY(-110%) translateX(10px) scale(0.75);
211
189
  opacity: 1;
212
- padding: 0 4px;
213
- background: var(--tertiary-color);
190
+ padding: 0;
191
+ background: var(--bg-color);
214
192
  font-weight: 300;
215
- }
193
+ transition: all 0.5s cubic-bezier(0.5, 0.5, 0, 1);
194
+ }
@@ -7,7 +7,7 @@ import {
7
7
  Navigate,
8
8
  Outlet,
9
9
  } from 'react-router-dom';
10
- import { ToastContainer } from 'react-toastify';
10
+ import { Flip, ToastContainer } from 'react-toastify';
11
11
  import { Tooltip } from 'react-tooltip';
12
12
  import 'react-tooltip/dist/react-tooltip.css';
13
13
  import 'react-toastify/dist/ReactToastify.css';
@@ -56,7 +56,6 @@ const GenericAuth = ({
56
56
  setUserProfile(data);
57
57
  setIsAuthenticated(true);
58
58
  }
59
-
60
59
  setIsLoading(false);
61
60
 
62
61
  if (location.pathname.split('/')[1] === 'login') {
@@ -138,9 +137,17 @@ const GenericAuth = ({
138
137
  </Route>
139
138
  </Routes>
140
139
  <ToastContainer
141
- theme="light"
142
- position="bottom-center"
143
- style={{ width: '600px' }}
140
+ position="bottom-right"
141
+ autoClose={7000}
142
+ hideProgressBar={false}
143
+ newestOnTop
144
+ closeOnClick
145
+ rtl={false}
146
+ pauseOnFocusLoss
147
+ draggable={false}
148
+ pauseOnHover
149
+ theme="dark"
150
+ transition={Flip}
144
151
  />
145
152
  <Tooltip id="system-tooltip" />
146
153
  </>
@@ -1,352 +1,42 @@
1
- import React, { useEffect, useState } from 'react';
2
- import { ResponsiveBar } from '@nivo/bar';
3
- import Select from 'react-select';
4
- import styles from './styles/GenericDashboard.module.scss';
1
+ import React, { useState, useEffect } from 'react';
2
+ import { toast } from 'react-toastify';
3
+ import CustomFetch from '../../crm/Fetch';
5
4
 
6
- import CustomFetch from '../Fetch';
7
-
8
- function GenericDashboard({ setting, userProfile }) {
5
+ const GenericDashboard = ({ userProfile }) => {
9
6
  const [data, setData] = useState([]);
10
- const [dropdown, setDropdown] = useState({ filters: [] });
11
- const [selectedFilters, setSelectedFilters] = useState({});
12
- const [filterValues, setFilterValues] = useState({});
13
- const [errorMessage, setErrorMessage] = useState('');
14
-
15
- const customStyles = {
16
- control: (base) => ({
17
- ...base,
18
- height: '51px',
19
- minHeight: '51px',
20
- padding: '0',
21
- borderColor: '#ced4da',
22
- borderRadius: '5px',
23
- boxShadow: 'none',
24
- '&:hover': {
25
- borderColor: '#80bdff',
26
- },
27
- }),
28
- valueContainer: (base) => ({
29
- ...base,
30
- height: '51px',
31
- padding: '0 8px',
32
- display: 'flex',
33
- alignItems: 'center',
34
- }),
35
- };
36
-
37
- const fetchDropdownData = async () => {
38
- try {
39
- const response = await CustomFetch(
40
- setting.api.dropdownUrl,
41
- 'POST',
42
- {}
43
- );
44
- setDropdown((prevState) => ({
45
- ...prevState,
46
- filters: response?.data?.data || [],
47
- }));
48
- } catch (error) {
49
- console.error('Error fetching dropdown data:', error);
50
- }
51
- };
52
-
53
- const fetchData = async () => {
54
- try {
55
- const filters = Object.keys(filterValues).reduce((acc, key) => {
56
- if (filterValues[key]) {
57
- acc[key] = filterValues[key];
58
- }
59
- return acc;
60
- }, {});
61
-
62
- const response = await CustomFetch(
63
- setting.api.fetchDataUrl,
64
- 'POST',
65
- filters
66
- );
67
- setData(response?.data?.data || []);
68
- } catch (error) {
69
- console.error('Error fetching data:', error);
70
- }
71
- };
72
-
73
- const handleFilterChange = (filterId, value) => {
74
- setFilterValues((prevValues) => ({
75
- ...prevValues,
76
- [filterId]: value,
77
- }));
78
- };
79
-
80
- useEffect(() => {
81
- fetchDropdownData();
82
- }, []);
83
-
84
- useEffect(() => {
85
- fetchData();
86
- }, [filterValues]);
87
7
 
88
8
  return (
89
- <div className={styles.grid}>
90
- <div className={styles.filterContainer}>
91
- <div className={styles.filterHeader}>
92
- <h3>{setting.filters?.title || 'Filters'}</h3>
93
- </div>
94
- <div className={styles.filterFields}>
95
- {setting.filters?.filters?.map((filter, index) => {
96
- switch (filter.type) {
97
- case 'dateRange':
98
- return (
99
- <div
100
- key={index}
101
- className={styles.filterField}
102
- >
103
- <label htmlFor={filter.startDateId}>
104
- {filter.startDateLabel ||
105
- 'Start Date'}
106
- </label>
107
- <input
108
- id={filter.startDateId}
109
- type="date"
110
- value={
111
- filterValues[
112
- filter.startDateId
113
- ] || ''
114
- }
115
- onChange={(e) =>
116
- handleFilterChange(
117
- filter.startDateId,
118
- e.target.value
119
- )
120
- }
121
- />
122
- <label htmlFor={filter.endDateId}>
123
- {filter.endDateLabel || 'End Date'}
124
- </label>
125
- <input
126
- id={filter.endDateId}
127
- type="date"
128
- value={
129
- filterValues[
130
- filter.endDateId
131
- ] || ''
132
- }
133
- onChange={(e) =>
134
- handleFilterChange(
135
- filter.endDateId,
136
- e.target.value
137
- )
138
- }
139
- />
140
- </div>
141
- );
142
- case 'dropdown':
143
- return (
144
- <div
145
- key={index}
146
- className={styles.filterField}
147
- >
148
- <label htmlFor={filter.id}>
149
- {filter.label || 'Select Option'}
150
- </label>
151
- <Select
152
- id={filter.id}
153
- isMulti={filter.isMulti}
154
- options={dropdown.filters.map(
155
- (option) => ({
156
- value: option.id,
157
- label: option.label,
158
- })
159
- )}
160
- styles={customStyles}
161
- value={selectedFilters[filter.id]}
162
- onChange={(value) =>
163
- handleFilterChange(
164
- filter.id,
165
- value
166
- )
167
- }
168
- />
169
- </div>
170
- );
171
- default:
172
- return null;
173
- }
174
- })}
175
- <div className={styles.filterActions}>
176
- <button onClick={fetchData} className="btn btn-primary">
177
- {setting.filters?.applyButtonLabel ||
178
- 'Apply Filters'}
179
- </button>
180
- <button
181
- onClick={() => {
182
- setFilterValues({});
183
- setErrorMessage('');
184
- }}
185
- className="btn btn-secondary"
186
- >
187
- {setting.filters?.clearButtonLabel ||
188
- 'Clear Filters'}
189
- </button>
9
+ <div className="grid">
10
+ <div className="grid__row">
11
+ <div className="grid__three dashtopwidge">
12
+ <div className="dashtopwidge__left">
13
+ <h2>
14
+ Current
15
+ <span>
16
+ <strong>Enquiries</strong>
17
+ </span>
18
+ </h2>
19
+ </div>
20
+ <div className="dashtopwidge__right">
21
+ <span>0</span>
190
22
  </div>
191
23
  </div>
192
- {errorMessage && (
193
- <div className={styles.errorMessage}>
194
- <p>{errorMessage}</p>
24
+ <div className="grid__three dashtopwidge">
25
+ <div className="dashtopwidge__left">
26
+ <h2>
27
+ Current{' '}
28
+ <span>
29
+ <strong>Enquiries</strong>
30
+ </span>
31
+ </h2>
195
32
  </div>
196
- )}
33
+ <div className="dashtopwidge__right">
34
+ <span>0</span>
35
+ </div>
36
+ </div>
197
37
  </div>
198
-
199
- {setting.widgets?.map((widget, index) => {
200
- switch (widget.type) {
201
- case 'chart':
202
- return (
203
- <div key={index} className={styles.grid__row}>
204
- <div className={styles.grid__dashfull}>
205
- <div className={styles.widgetTitle}>
206
- <h2>
207
- {widget.title || 'Chart Widget'}
208
- </h2>
209
- </div>
210
- <div style={{ height: 600 }}>
211
- {data.length > 0 ? (
212
- <ResponsiveBar
213
- data={data}
214
- keys={widget.keys || []}
215
- indexBy={
216
- widget.indexBy ||
217
- 'supervisor'
218
- }
219
- margin={
220
- widget.margin || {
221
- top: 20,
222
- right: 200,
223
- bottom: 110,
224
- left: 80,
225
- }
226
- }
227
- padding={0.2}
228
- valueScale={{ type: 'linear' }}
229
- indexScale={{
230
- type: 'band',
231
- round: true,
232
- }}
233
- colors={{
234
- scheme:
235
- widget.colorScheme ||
236
- 'set3',
237
- }}
238
- borderColor={{
239
- from: 'color',
240
- modifiers: [
241
- ['darker', 1.6],
242
- ],
243
- }}
244
- axisBottom={
245
- widget.axisBottom || {
246
- tickSize: 5,
247
- tickPadding: 5,
248
- tickRotation: 45,
249
- }
250
- }
251
- axisLeft={
252
- widget.axisLeft || {
253
- tickSize: 5,
254
- tickPadding: 5,
255
- }
256
- }
257
- legends={widget.legends || []}
258
- />
259
- ) : (
260
- <div>Loading chart...</div>
261
- )}
262
- </div>
263
- </div>
264
- </div>
265
- );
266
- case 'table':
267
- return (
268
- <div key={index} className={styles.grid__row}>
269
- <div className={styles.grid__dashfull}>
270
- <div className={styles.widgetTitle}>
271
- <h2>
272
- {widget.title || 'Table Widget'}
273
- </h2>
274
- </div>
275
- <div className={styles.tableContainer}>
276
- {data.length > 0 ? (
277
- <table>
278
- <thead>
279
- <tr>
280
- <th>
281
- {widget.tableHeader ||
282
- 'Data'}
283
- </th>
284
- {data.map(
285
- (row, index) => (
286
- <th key={index}>
287
- {
288
- row.supervisor
289
- }
290
- </th>
291
- )
292
- )}
293
- </tr>
294
- </thead>
295
- <tbody>
296
- {widget.keys?.map(
297
- (key, index) => {
298
- let total = 0;
299
- return (
300
- <tr key={index}>
301
- <td>
302
- {key}
303
- </td>
304
- {data.map(
305
- (
306
- row
307
- ) => {
308
- const count =
309
- row[
310
- key
311
- ] ||
312
- 0;
313
- total +=
314
- count;
315
- return (
316
- <td
317
- key={
318
- row.supervisor
319
- }
320
- >
321
- {
322
- count
323
- }
324
- </td>
325
- );
326
- }
327
- )}
328
- <td>
329
- {total}
330
- </td>
331
- </tr>
332
- );
333
- }
334
- )}
335
- </tbody>
336
- </table>
337
- ) : (
338
- <div>No data available</div>
339
- )}
340
- </div>
341
- </div>
342
- </div>
343
- );
344
- default:
345
- return null;
346
- }
347
- })}
348
38
  </div>
349
39
  );
350
- }
40
+ };
351
41
 
352
42
  export default GenericDashboard;