@zauru-sdk/components 1.0.12 → 1.0.14

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 (104) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/Alerts/index.d.ts +0 -1
  3. package/dist/Alerts/index.js +0 -1
  4. package/dist/Chat/ChatLayout.d.ts +2 -2
  5. package/dist/Chat/ChatLayout.js +4 -3
  6. package/dist/Chat/ChatMessageHistory.js +1 -1
  7. package/dist/ConnectionState/ConnectionState.d.ts +2 -0
  8. package/dist/ConnectionState/ConnectionState.js +22 -0
  9. package/dist/ConnectionState/index.d.ts +1 -0
  10. package/dist/ConnectionState/index.js +1 -0
  11. package/dist/DynamicTable/BasicPrintDynamicTable.d.ts +10 -0
  12. package/dist/DynamicTable/BasicPrintDynamicTable.js +27 -0
  13. package/dist/DynamicTable/DynamicPrintTable.d.ts +23 -0
  14. package/dist/DynamicTable/DynamicPrintTable.js +132 -0
  15. package/dist/DynamicTable/GenericDynamicTable.d.ts +21 -0
  16. package/dist/DynamicTable/GenericDynamicTable.js +195 -0
  17. package/dist/DynamicTable/index.d.ts +24 -0
  18. package/dist/DynamicTable/index.js +193 -0
  19. package/dist/Footer/Footer.js +2 -2
  20. package/dist/Form/Checkbox/index.d.ts +17 -0
  21. package/dist/Form/Checkbox/index.js +34 -0
  22. package/dist/Form/Checklist/index.d.ts +14 -0
  23. package/dist/Form/Checklist/index.js +10 -0
  24. package/dist/Form/DatePicker/index.d.ts +18 -0
  25. package/dist/Form/DatePicker/index.js +31 -0
  26. package/dist/Form/DynamicBaculoForm/index.d.ts +18 -0
  27. package/dist/Form/DynamicBaculoForm/index.js +138 -0
  28. package/dist/Form/FieldContainer/DoubleFieldContainer.d.ts +8 -0
  29. package/dist/Form/FieldContainer/DoubleFieldContainer.js +14 -0
  30. package/dist/Form/FieldContainer/QuadrupleFieldContainer.d.ts +7 -0
  31. package/dist/Form/FieldContainer/QuadrupleFieldContainer.js +14 -0
  32. package/dist/Form/FieldContainer/TripleFieldContainer.d.ts +7 -0
  33. package/dist/Form/FieldContainer/TripleFieldContainer.js +14 -0
  34. package/dist/Form/FieldContainer/index.d.ts +3 -0
  35. package/dist/Form/FieldContainer/index.js +3 -0
  36. package/dist/Form/FileUpload/index.d.ts +21 -0
  37. package/dist/Form/FileUpload/index.js +54 -0
  38. package/dist/Form/FormButtons/index.d.ts +16 -0
  39. package/dist/Form/FormButtons/index.js +5 -0
  40. package/dist/Form/FormLayout/index.d.ts +11 -0
  41. package/dist/Form/FormLayout/index.js +7 -0
  42. package/dist/Form/SelectField/index.d.ts +27 -0
  43. package/dist/Form/SelectField/index.js +74 -0
  44. package/dist/Form/TextArea/index.d.ts +23 -0
  45. package/dist/Form/TextArea/index.js +36 -0
  46. package/dist/Form/TextField/index.d.ts +25 -0
  47. package/dist/Form/TextField/index.js +70 -0
  48. package/dist/Form/TimePicker/index.d.ts +16 -0
  49. package/dist/Form/TimePicker/index.js +31 -0
  50. package/dist/Form/YesNo/index.d.ts +12 -0
  51. package/dist/Form/YesNo/index.js +19 -0
  52. package/dist/Form/index.d.ts +13 -0
  53. package/dist/Form/index.js +13 -0
  54. package/dist/NavBar/NavBar.js +2 -2
  55. package/dist/Table/ZauruTable.js +1 -1
  56. package/dist/Zendesk/Chat.d.ts +2 -2
  57. package/dist/Zendesk/Chat.js +2 -1
  58. package/dist/Zendesk/zendesk.config.d.ts +1 -1
  59. package/dist/index.d.ts +4 -0
  60. package/dist/index.js +4 -2
  61. package/package.json +9 -8
  62. package/src/Alerts/index.ts +0 -1
  63. package/src/Chat/ChatLayout.tsx +133 -0
  64. package/src/Chat/ChatMessageHistory.tsx +142 -0
  65. package/src/Chat/index.ts +2 -0
  66. package/src/ConnectionState/ConnectionState.tsx +29 -0
  67. package/src/ConnectionState/index.tsx +1 -0
  68. package/src/DynamicTable/BasicPrintDynamicTable.tsx +73 -0
  69. package/src/DynamicTable/DynamicPrintTable.tsx +290 -0
  70. package/src/DynamicTable/GenericDynamicTable.tsx +455 -0
  71. package/src/DynamicTable/index.tsx +407 -0
  72. package/src/Footer/Footer.tsx +3 -3
  73. package/src/Form/Checkbox/index.tsx +96 -0
  74. package/src/Form/Checklist/index.tsx +35 -0
  75. package/src/Form/DatePicker/index.tsx +132 -0
  76. package/src/Form/DynamicBaculoForm/index.tsx +359 -0
  77. package/src/Form/FieldContainer/DoubleFieldContainer.tsx +35 -0
  78. package/src/Form/FieldContainer/QuadrupleFieldContainer.tsx +36 -0
  79. package/src/Form/FieldContainer/TripleFieldContainer.tsx +35 -0
  80. package/src/Form/FieldContainer/index.ts +3 -0
  81. package/src/Form/FileUpload/index.tsx +184 -0
  82. package/src/Form/FormButtons/index.tsx +78 -0
  83. package/src/Form/FormLayout/index.tsx +37 -0
  84. package/src/Form/SelectField/index.tsx +237 -0
  85. package/src/Form/TextArea/index.tsx +125 -0
  86. package/src/Form/TextField/index.tsx +194 -0
  87. package/src/Form/TimePicker/index.tsx +127 -0
  88. package/src/Form/YesNo/index.tsx +79 -0
  89. package/src/Form/index.ts +13 -0
  90. package/src/NavBar/NavBar.tsx +2 -2
  91. package/src/Table/ZauruTable.tsx +1 -1
  92. package/src/Zendesk/Chat.tsx +85 -0
  93. package/src/Zendesk/index.ts +2 -0
  94. package/src/Zendesk/zendesk.config.ts +40 -0
  95. package/src/index.ts +4 -2
  96. package/dist/Alerts/Alert.d.ts +0 -9
  97. package/dist/Alerts/Alert.js +0 -97
  98. package/dist/Icons/Icons.d.ts +0 -47
  99. package/dist/Icons/Icons.js +0 -110
  100. package/dist/Icons/StylesConstants.d.ts +0 -26
  101. package/dist/Icons/StylesConstants.js +0 -34
  102. package/src/Alerts/Alert.tsx +0 -149
  103. package/src/Icons/Icons.tsx +0 -782
  104. package/src/Icons/StylesConstants.tsx +0 -66
@@ -0,0 +1,455 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import { SelectFieldWithoutValidation } from "../Form/SelectField";
3
+ import { TextFieldWithoutValidation } from "../Form/TextField";
4
+ import { CheckboxWithoutValidation } from "../Form/Checkbox";
5
+ import { createModal } from "../Modal";
6
+ import { Button } from "../Buttons/Button";
7
+ import {
8
+ GenericDynamicTableColumn,
9
+ RowDataType,
10
+ SelectFieldOption,
11
+ } from "@zauru-sdk/types";
12
+ import { useAppSelector } from "@zauru-sdk/redux";
13
+ import { generateClientUUID } from "@zauru-sdk/common";
14
+ import { LoadingInputSkeleton, WithTooltip } from "src";
15
+ import { TrashSvg } from "@zauru-sdk/icons";
16
+
17
+ type Props = {
18
+ name?: string;
19
+ className?: string;
20
+ columns: GenericDynamicTableColumn[];
21
+ onChange?: (tableState?: any[]) => void;
22
+ defaultValue?: RowDataType[];
23
+ footerRow?: RowDataType;
24
+ thCSSProperties?: React.CSSProperties;
25
+ thElementsClassName?: string;
26
+ editable?: boolean;
27
+ searcheables?: SelectFieldOption[];
28
+ loading?: boolean;
29
+ paginated?: boolean;
30
+ defaultItemsPerPage?: number;
31
+ itemsPerPageOptions?: number[];
32
+ withoutBg?: boolean;
33
+ };
34
+
35
+ const GenericDynamicTableErrorComponent = ({
36
+ name,
37
+ formName,
38
+ }: {
39
+ name: string;
40
+ formName?: string;
41
+ }) => {
42
+ const { formValidations } = useAppSelector((state) => state.formValidation);
43
+ const error = formValidations[formName ?? "-1"]?.[name ?? "-1"];
44
+
45
+ return error ? (
46
+ <p className={`mt-2 text-sm text-red-600 dark:text-red-500`}>
47
+ <span className="font-medium">Oops!</span> {error}
48
+ </p>
49
+ ) : (
50
+ <></>
51
+ );
52
+ };
53
+
54
+ export const GenericDynamicTable = (props: Props) => {
55
+ const {
56
+ columns,
57
+ onChange,
58
+ className,
59
+ footerRow,
60
+ defaultValue = [],
61
+ thCSSProperties,
62
+ thElementsClassName = "",
63
+ editable = true,
64
+ searcheables = [],
65
+ loading = false,
66
+ paginated = true,
67
+ defaultItemsPerPage = 10,
68
+ itemsPerPageOptions = [10, 50, 100],
69
+ name,
70
+ withoutBg = false,
71
+ } = props;
72
+
73
+ const [tableData, setTableData] = useState<RowDataType[]>(defaultValue);
74
+ const [deletedData, setDeletedData] = useState<RowDataType[]>([]);
75
+ const [search, setSearch] = useState("");
76
+ const [filteredTableData, setFilteredTableData] =
77
+ useState<RowDataType[]>(tableData);
78
+ const [currentPage, setCurrentPage] = useState(1);
79
+ const [itemsPerPage, setItemsPerPage] = useState(defaultItemsPerPage);
80
+
81
+ useEffect(() => {
82
+ if (defaultValue.length) {
83
+ setTableData(defaultValue);
84
+ }
85
+ }, []);
86
+
87
+ useEffect(() => {
88
+ setFilteredTableData(tableData);
89
+ }, [tableData]);
90
+
91
+ useEffect(() => {
92
+ changeFilteredData();
93
+ }, [tableData, search]);
94
+
95
+ const totalPages = () => {
96
+ return Math.ceil(filteredTableData.length / itemsPerPage);
97
+ };
98
+
99
+ const addRow = () => {
100
+ const defs: { [key: string]: any } = {};
101
+ columns.forEach((x) => {
102
+ defs[`${x.name}`] =
103
+ x.type == "label" || x.type == "textField"
104
+ ? ""
105
+ : x.type == "selectField"
106
+ ? 0
107
+ : x.type == "checkbox"
108
+ ? false
109
+ : 0;
110
+ });
111
+ setTableData((prevData) => [
112
+ ...prevData,
113
+ { id: generateClientUUID(), ...defs },
114
+ ]);
115
+ };
116
+
117
+ const removeRow = (rowId: string) => {
118
+ const newDeletedData = [...deletedData];
119
+ const deletedItem = tableData?.find((x) => x.id === rowId);
120
+ if (deletedItem && !isNaN(deletedItem.id)) {
121
+ newDeletedData.push(deletedItem);
122
+ }
123
+ setDeletedData(newDeletedData);
124
+ setTableData((prevData) => prevData?.filter((x) => x.id !== rowId));
125
+ };
126
+
127
+ const handleChange = (name: string, value: any, rowId: string) => {
128
+ // Encontrar el índice de la fila que está cambiando
129
+ const rowIndex = tableData.findIndex((x) => x.id === rowId);
130
+
131
+ // Crear una copia del objeto en esa fila
132
+ const updatedRow = { ...tableData[rowIndex], [name]: value };
133
+
134
+ // Copiar todo el array
135
+ const updatedData = [...tableData];
136
+
137
+ // Reemplazar el objeto en la fila que cambió
138
+ updatedData[rowIndex] = updatedRow;
139
+
140
+ // Actualizar el estado con el nuevo array
141
+ setTableData(updatedData);
142
+ onChange && onChange(updatedData);
143
+ };
144
+
145
+ const renderHeader = () => (
146
+ <tr style={{ ...thCSSProperties }}>
147
+ {columns.map((column, index) => {
148
+ const ancho =
149
+ column.width ?? (editable ? 94 : 100) / (columns.length ?? 1);
150
+ return (
151
+ <th
152
+ key={index}
153
+ className={`text-left align-middle p-2 ${thElementsClassName}`}
154
+ style={{ width: `${ancho}%` }}
155
+ >
156
+ {column.label}
157
+ </th>
158
+ );
159
+ })}
160
+ {editable && <th style={{ width: "4%" }}></th>}
161
+ </tr>
162
+ );
163
+
164
+ const renderRow = (rowData: RowDataType, index: number) => {
165
+ return (
166
+ <tr
167
+ key={rowData.id}
168
+ className={index % 2 === 0 ? `${withoutBg ? "" : "bg-gray-200"}` : ""}
169
+ >
170
+ {columns.map((column) => {
171
+ if (loading) {
172
+ return (
173
+ <td
174
+ key={`${rowData.id}-${column.name}`}
175
+ className="align-middle p-1"
176
+ >
177
+ <LoadingInputSkeleton />
178
+ </td>
179
+ );
180
+ }
181
+ const tempVal = rowData[column.name as any];
182
+
183
+ const defaultVal =
184
+ column.type === "selectField"
185
+ ? column.options?.find((x) => x.value === tempVal)
186
+ : tempVal;
187
+
188
+ if (column.type === "label") {
189
+ return (
190
+ <td
191
+ key={`${rowData.id}-${column.name}`}
192
+ className="align-middle p-1"
193
+ >
194
+ <div>{defaultVal}</div>
195
+ </td>
196
+ );
197
+ }
198
+
199
+ const FieldComponent =
200
+ column.type === "textField"
201
+ ? TextFieldWithoutValidation
202
+ : column.type === "checkbox"
203
+ ? CheckboxWithoutValidation
204
+ : SelectFieldWithoutValidation;
205
+
206
+ const setTableValue = (columnName: string, newValue: any) => {
207
+ setTableData((prevState) => {
208
+ // Encontrar el índice de la fila que está cambiando
209
+ const rowIndex = prevState.findIndex((x) => x.id === rowData.id);
210
+ // Crear una copia del objeto en esa fila
211
+ const updatedRow = {
212
+ ...prevState[rowIndex],
213
+ [columnName]: newValue,
214
+ };
215
+ // Copiar todo el array
216
+ const updatedData = [...prevState];
217
+
218
+ // Reemplazar el objeto en la fila que cambió
219
+ updatedData[rowIndex] = updatedRow;
220
+ return updatedData;
221
+ });
222
+ };
223
+
224
+ return (
225
+ <td
226
+ key={`${rowData.id}-${column.name}`}
227
+ className="align-middle p-1"
228
+ >
229
+ {column.loadingOptions ? (
230
+ <LoadingInputSkeleton />
231
+ ) : (
232
+ <FieldComponent
233
+ key={`${rowData.id}-${column.name}`}
234
+ //name={column.name}
235
+ type={column.textFieldType}
236
+ integer={!!column.integer}
237
+ disabled={column.disabled}
238
+ isClearable
239
+ onChange={(value: any) => {
240
+ const sendValue = value?.value ?? value;
241
+ handleChange(column.name, sendValue, rowData.id);
242
+ column.onChange &&
243
+ column.onChange(rowData, sendValue, setTableValue);
244
+ }}
245
+ defaultValue={defaultVal}
246
+ options={column.options ?? []}
247
+ />
248
+ )}
249
+ </td>
250
+ );
251
+ })}
252
+ {editable && (
253
+ <td className="align-middle w-16">
254
+ <WithTooltip text="Eliminar">
255
+ <button
256
+ className="bg-red-500 hover:bg-red-600 font-bold py-1 px-2 rounded ml-2"
257
+ onClick={(
258
+ event: React.MouseEvent<HTMLButtonElement, MouseEvent>
259
+ ) => {
260
+ event.preventDefault();
261
+ event.stopPropagation();
262
+ createModal({
263
+ title: "¿Está seguro que quiere eliminar este registro?",
264
+ description:
265
+ "Una vez eliminada la información no podrá ser recuperada.",
266
+ }).then((response) => {
267
+ if (response === "OK") {
268
+ removeRow(rowData.id);
269
+ }
270
+ });
271
+ }}
272
+ type="button"
273
+ >
274
+ <TrashSvg />
275
+ </button>
276
+ </WithTooltip>
277
+ </td>
278
+ )}
279
+ </tr>
280
+ );
281
+ };
282
+
283
+ const renderRows = () => {
284
+ let mapeable = filteredTableData.slice(
285
+ (currentPage - 1) * itemsPerPage,
286
+ currentPage * itemsPerPage
287
+ );
288
+
289
+ if (loading) {
290
+ mapeable = [
291
+ { id: 1 },
292
+ { id: 2 },
293
+ { id: 3 },
294
+ { id: 4 },
295
+ { id: 5 },
296
+ { id: 6 },
297
+ { id: 7 },
298
+ { id: 8 },
299
+ { id: 9 },
300
+ { id: 10 },
301
+ ] as RowDataType[];
302
+ }
303
+
304
+ return mapeable.map((rowData, index) => renderRow(rowData, index));
305
+ };
306
+
307
+ const handleChangeSearch = (newSearch: string) => {
308
+ setSearch(newSearch);
309
+ };
310
+
311
+ const changeFilteredData = () => {
312
+ if (search) {
313
+ const filteredData = tableData.filter((rowData) => {
314
+ for (const searchable of searcheables) {
315
+ const column = columns.find((col) => col.name === searchable.value);
316
+ if (column) {
317
+ const tempVal = rowData[column.name as any];
318
+ const defaultVal =
319
+ column.type === "selectField"
320
+ ? column.options?.find((x) => x.value === tempVal)?.label
321
+ : tempVal;
322
+ if (
323
+ defaultVal
324
+ ?.toString()
325
+ .toLowerCase()
326
+ .includes(search.toLowerCase())
327
+ ) {
328
+ return true;
329
+ }
330
+ }
331
+ }
332
+ return false;
333
+ });
334
+ setFilteredTableData(filteredData);
335
+ } else {
336
+ setFilteredTableData(tableData);
337
+ }
338
+ };
339
+
340
+ return (
341
+ <>
342
+ {name && (
343
+ <>
344
+ <GenericDynamicTableErrorComponent name={name} />
345
+ <input
346
+ name={name}
347
+ type="hidden"
348
+ value={JSON.stringify(tableData)}
349
+ hidden
350
+ />
351
+ <input
352
+ name={`deleted_${name}`}
353
+ type="hidden"
354
+ value={JSON.stringify(deletedData)}
355
+ hidden
356
+ />
357
+ </>
358
+ )}
359
+ <div className={`${className}`}>
360
+ {searcheables.length > 0 && (
361
+ <div>
362
+ <TextFieldWithoutValidation
363
+ className="mb-2"
364
+ name="search"
365
+ title={`Buscar por: ${searcheables
366
+ .map((x) => x.label)
367
+ .join(", ")}`}
368
+ onChange={handleChangeSearch}
369
+ disabled={loading}
370
+ />
371
+ </div>
372
+ )}
373
+ <table className="w-full">
374
+ <thead>{renderHeader()}</thead>
375
+ <tbody>{renderRows()}</tbody>
376
+ {footerRow && !editable ? (
377
+ <tfoot className="border-t-2 border-black">
378
+ <tr>
379
+ {Object.keys(footerRow ?? {})?.map((x, indx) => {
380
+ return (
381
+ <td className="align-middle" key={indx}>
382
+ {(footerRow as any)[x]}
383
+ </td>
384
+ );
385
+ })}
386
+ </tr>
387
+ </tfoot>
388
+ ) : editable ? (
389
+ <tfoot>
390
+ <tr>
391
+ <td className="align-middle">
392
+ <button
393
+ className="bg-blue-500 hover:bg-blue-600 font-bold py-2 px-4 rounded"
394
+ onClick={(
395
+ event: React.MouseEvent<HTMLButtonElement, MouseEvent>
396
+ ) => {
397
+ event.preventDefault();
398
+ event.stopPropagation();
399
+ addRow();
400
+ }}
401
+ type="button"
402
+ >
403
+ +
404
+ </button>
405
+ </td>
406
+ </tr>
407
+ </tfoot>
408
+ ) : (
409
+ <></>
410
+ )}
411
+ </table>
412
+ {paginated && totalPages() > 1 && (
413
+ <div className="flex justify-between items-center mt-4">
414
+ <div className="flex items-center">
415
+ <Button
416
+ type="button"
417
+ disabled={currentPage === 1}
418
+ onClickSave={() =>
419
+ setCurrentPage((old) => Math.max(old - 1, 1))
420
+ }
421
+ >
422
+ Anterior
423
+ </Button>
424
+ <span className="mx-2">{`Página ${currentPage} de ${totalPages()}`}</span>
425
+ <Button
426
+ type="button"
427
+ disabled={currentPage === totalPages()}
428
+ onClickSave={() =>
429
+ setCurrentPage((old) => Math.min(old + 1, totalPages()))
430
+ }
431
+ >
432
+ Siguiente
433
+ </Button>
434
+ </div>
435
+ <div>
436
+ <select
437
+ value={itemsPerPage}
438
+ onChange={(e) => {
439
+ setItemsPerPage(Number(e.target.value));
440
+ setCurrentPage(1); // resetear la página al cambiar los elementos por página
441
+ }}
442
+ >
443
+ {itemsPerPageOptions.map((option) => (
444
+ <option key={option} value={option}>
445
+ {option} elementos por página
446
+ </option>
447
+ ))}
448
+ </select>
449
+ </div>
450
+ </div>
451
+ )}
452
+ </div>
453
+ </>
454
+ );
455
+ };