@zauru-sdk/components 1.0.98 → 1.0.100

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 (95) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/Form/Checkbox/index.d.ts +1 -3
  3. package/dist/Form/DatePicker/index.d.ts +1 -3
  4. package/dist/Form/FileUpload/index.d.ts +1 -2
  5. package/dist/Form/ReactZodForm/index.d.ts +12 -0
  6. package/dist/Form/SelectField/index.d.ts +6 -9
  7. package/dist/Form/TextArea/index.d.ts +1 -3
  8. package/dist/Form/TextField/index.d.ts +1 -3
  9. package/dist/Form/TimePicker/index.d.ts +1 -2
  10. package/dist/Form/YesNo/index.d.ts +1 -0
  11. package/dist/Form/index.d.ts +1 -2
  12. package/dist/Layouts/homeLayout/index.d.ts +3 -1
  13. package/dist/Modal/Modal.d.ts +1 -1
  14. package/dist/Zendesk/zendesk.config.d.ts +1 -1
  15. package/dist/cjs/Alerts/StaticAlert.js +0 -6
  16. package/dist/cjs/Buttons/Button.js +13 -2
  17. package/dist/cjs/DynamicTable/DynamicPrintTable.js +2 -2
  18. package/dist/cjs/DynamicTable/DynamicTable.js +3 -3
  19. package/dist/cjs/DynamicTable/GenericDynamicTable.js +4 -5
  20. package/dist/cjs/Footer/Footer.js +1 -1
  21. package/dist/cjs/Form/Checkbox/index.js +14 -14
  22. package/dist/cjs/Form/Checklist/index.js +1 -1
  23. package/dist/cjs/Form/DatePicker/index.js +14 -13
  24. package/dist/cjs/Form/DynamicBaculoForm/index.js +1 -1
  25. package/dist/cjs/Form/FileUpload/index.js +25 -13
  26. package/dist/cjs/Form/ReactZodForm/index.js +31 -0
  27. package/dist/cjs/Form/SelectField/index.js +118 -73
  28. package/dist/cjs/Form/TextArea/index.js +15 -15
  29. package/dist/cjs/Form/TextField/index.js +20 -16
  30. package/dist/cjs/Form/TimePicker/index.js +17 -15
  31. package/dist/cjs/Form/YesNo/index.js +12 -6
  32. package/dist/cjs/Form/index.js +1 -2
  33. package/dist/cjs/Layouts/homeLayout/index.js +45 -8
  34. package/dist/cjs/Modal/Modal.js +1 -2
  35. package/dist/cjs/NavBar/NavBar.js +12 -17
  36. package/dist/cjs/Table/ZauruTable.js +11 -4
  37. package/dist/cjs/WithTooltip/WithTooltip.js +1 -1
  38. package/dist/cjs/Zendesk/zendesk.config.js +7 -9
  39. package/dist/esm/Alerts/StaticAlert.js +0 -6
  40. package/dist/esm/Buttons/Button.js +13 -2
  41. package/dist/esm/DynamicTable/DynamicPrintTable.js +4 -4
  42. package/dist/esm/DynamicTable/DynamicTable.js +6 -6
  43. package/dist/esm/DynamicTable/GenericDynamicTable.js +7 -8
  44. package/dist/esm/Footer/Footer.js +1 -1
  45. package/dist/esm/Form/Checkbox/index.js +13 -12
  46. package/dist/esm/Form/Checklist/index.js +2 -2
  47. package/dist/esm/Form/DatePicker/index.js +13 -11
  48. package/dist/esm/Form/DynamicBaculoForm/index.js +2 -2
  49. package/dist/esm/Form/FileUpload/index.js +24 -11
  50. package/dist/esm/Form/ReactZodForm/index.js +27 -0
  51. package/dist/esm/Form/SelectField/index.js +118 -49
  52. package/dist/esm/Form/TextArea/index.js +14 -13
  53. package/dist/esm/Form/TextField/index.js +19 -14
  54. package/dist/esm/Form/TimePicker/index.js +16 -13
  55. package/dist/esm/Form/YesNo/index.js +12 -6
  56. package/dist/esm/Form/index.js +1 -2
  57. package/dist/esm/Layouts/homeLayout/index.js +46 -9
  58. package/dist/esm/Modal/Modal.js +1 -2
  59. package/dist/esm/NavBar/NavBar.js +12 -17
  60. package/dist/esm/Table/ZauruTable.js +11 -4
  61. package/dist/esm/WithTooltip/WithTooltip.js +2 -2
  62. package/dist/esm/Zendesk/zendesk.config.js +7 -6
  63. package/package.json +9 -6
  64. package/src/Alerts/StaticAlert.tsx +0 -10
  65. package/src/Buttons/Button.tsx +24 -4
  66. package/src/DynamicTable/DynamicPrintTable.tsx +5 -6
  67. package/src/DynamicTable/DynamicTable.tsx +7 -7
  68. package/src/DynamicTable/GenericDynamicTable.tsx +7 -8
  69. package/src/Footer/Footer.tsx +1 -1
  70. package/src/Form/Checkbox/index.tsx +21 -18
  71. package/src/Form/Checklist/index.tsx +2 -2
  72. package/src/Form/DatePicker/index.tsx +22 -19
  73. package/src/Form/DynamicBaculoForm/index.tsx +2 -2
  74. package/src/Form/FileUpload/index.tsx +29 -14
  75. package/src/Form/ReactZodForm/index.tsx +60 -0
  76. package/src/Form/SelectField/index.tsx +246 -130
  77. package/src/Form/TextArea/index.tsx +22 -19
  78. package/src/Form/TextField/index.tsx +25 -18
  79. package/src/Form/TimePicker/index.tsx +25 -18
  80. package/src/Form/YesNo/index.tsx +20 -7
  81. package/src/Form/index.ts +1 -2
  82. package/src/Layouts/homeLayout/index.tsx +114 -21
  83. package/src/Modal/Modal.tsx +2 -5
  84. package/src/NavBar/NavBar.tsx +35 -46
  85. package/src/Table/ZauruTable.tsx +11 -4
  86. package/src/WithTooltip/WithTooltip.tsx +8 -7
  87. package/src/Zendesk/zendesk.config.ts +8 -6
  88. package/dist/Form/FormLayout/index.d.ts +0 -11
  89. package/dist/Form/RadioButtonGroup/index.d.ts +0 -20
  90. package/dist/cjs/Form/FormLayout/index.js +0 -11
  91. package/dist/cjs/Form/RadioButtonGroup/index.js +0 -26
  92. package/dist/esm/Form/FormLayout/index.js +0 -7
  93. package/dist/esm/Form/RadioButtonGroup/index.js +0 -21
  94. package/src/Form/FormLayout/index.tsx +0 -37
  95. package/src/Form/RadioButtonGroup/index.tsx +0 -108
@@ -1,4 +1,4 @@
1
- import jwt from "jsonwebtoken";
1
+ //import jwt from "jsonwebtoken";
2
2
  export function zendeskJwt(current_user, configuration) {
3
3
  // get the INFO
4
4
  const jwtSecret = configuration.zendeskJWTSecret;
@@ -16,9 +16,10 @@ export function zendeskJwt(current_user, configuration) {
16
16
  scope: "user",
17
17
  exp: expiresIn,
18
18
  };
19
- const jwtHeader = { kid: jwtKey, typ: "JWT", alg: "HS256" };
20
- return jwt.sign(payload, jwtSecret, {
21
- algorithm: "HS256",
22
- header: jwtHeader,
23
- });
19
+ // const jwtHeader: jwt.JwtHeader = { kid: jwtKey, typ: "JWT", alg: "HS256" };
20
+ // return jwt.sign(payload, jwtSecret, {
21
+ // algorithm: "HS256",
22
+ // header: jwtHeader,
23
+ // });
24
+ return {};
24
25
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zauru-sdk/components",
3
- "version": "1.0.98",
3
+ "version": "1.0.100",
4
4
  "description": "Componentes reutilizables en las WebApps de Zauru.",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -31,21 +31,24 @@
31
31
  "typescript": "^5.1.6"
32
32
  },
33
33
  "dependencies": {
34
+ "@hookform/resolvers": "^3.9.0",
34
35
  "@reduxjs/toolkit": "^2.2.1",
35
36
  "@remix-run/react": "^2.8.1",
36
- "@zauru-sdk/common": "^1.0.98",
37
- "@zauru-sdk/hooks": "^1.0.98",
37
+ "@zauru-sdk/common": "^1.0.99",
38
+ "@zauru-sdk/hooks": "^1.0.99",
38
39
  "@zauru-sdk/icons": "^1.0.60",
39
40
  "@zauru-sdk/types": "^1.0.98",
40
- "@zauru-sdk/utils": "^1.0.98",
41
+ "@zauru-sdk/utils": "^1.0.99",
41
42
  "framer-motion": "^11.0.8",
42
43
  "jsonwebtoken": "^9.0.2",
43
44
  "react": "^18.2.0",
44
45
  "react-data-table-component": "^7.6.2",
45
46
  "react-dom": "^18.2.0",
47
+ "react-hook-form": "^7.53.0",
46
48
  "react-is": "^18.2.0",
47
49
  "react-select": "^5.8.0",
48
- "styled-components": "^5.3.5"
50
+ "styled-components": "^5.3.5",
51
+ "zod": "^3.23.8"
49
52
  },
50
- "gitHead": "e3b92fe4d2aea4be988540f6b233f0a27eb72a40"
53
+ "gitHead": "c1abff96d35de414e81db8d1cff843e430d06ff7"
51
54
  }
@@ -33,16 +33,6 @@ const getConfig = (type: string) => {
33
33
  <path d="M8.445 12.6675A.9.9 0 0 0 7.1424 13.91l2.5726 2.7448c.3679.3856.9884.3689 1.335-.036l5.591-7.0366a.9.9 0 0 0-1.3674-1.1705l-4.6548 5.9132a.4.4 0 0 1-.607.0252l-1.567-1.6826zM1.9995 12c0-5.5 4.5-10 10-10s10 4.5 10 10-4.5 10-10 10-10-4.5-10-10z"></path>
34
34
  ),
35
35
  };
36
- case "warning":
37
- return {
38
- containerClassName:
39
- "text-yellow-900 bg-yellow-100 border border-yellow-200 rounded-md",
40
- buttonClassName:
41
- "rounded-md focus:outline-none focus:ring-2 focus:ring-yellow-500",
42
- path: (
43
- <path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2M12 18a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm0-9a1 1 0 0 1 1 1v4a1 1 0 0 1-2 0v-4a1 1 0 0 1 1-1z" />
44
- ),
45
- };
46
36
  default:
47
37
  return {
48
38
  containerClassName:
@@ -1,4 +1,6 @@
1
1
  import type { ColorInterface } from "../NavBar/NavBar.types.js";
2
+ import { useFormContext } from "react-hook-form";
3
+ import { WithTooltip } from "../index.js";
2
4
 
3
5
  type Props = {
4
6
  type?: "reset" | "button" | "submit" | undefined;
@@ -28,6 +30,10 @@ export const Button = (props: Props) => {
28
30
  disabled = false,
29
31
  } = props;
30
32
 
33
+ const formContext = useFormContext();
34
+ const formHasErrors = formContext ? !formContext.formState.isValid : false;
35
+ const formErrors = formContext ? formContext.formState.errors : {};
36
+
31
37
  const COLORS = {
32
38
  green: {
33
39
  bg900: "bg-green-900",
@@ -67,17 +73,25 @@ export const Button = (props: Props) => {
67
73
 
68
74
  const inside = children ?? title;
69
75
 
70
- return (
76
+ const errorMessage = formHasErrors
77
+ ? Object.values(formErrors)
78
+ .map((error) => error?.message?.toString())
79
+ .join(", ")
80
+ : "";
81
+
82
+ const buttonContent = (
71
83
  <button
72
84
  type={type}
73
85
  name="action"
74
- disabled={loading || disabled}
86
+ disabled={loading || disabled || formHasErrors}
75
87
  value={name}
76
88
  onClick={onClickSave}
77
- className={`ml-2 ${loading || disabled ? " bg-opacity-25 " : ""} ${
89
+ className={`ml-2 ${
90
+ loading || disabled || formHasErrors ? " bg-opacity-25 " : ""
91
+ } ${
78
92
  loading
79
93
  ? " cursor-progress"
80
- : `${disabled ? "" : `hover:${color.bg700}`}`
94
+ : `${disabled || formHasErrors ? "" : `hover:${color.bg700}`}`
81
95
  } inline-flex justify-center rounded-md border border-transparent ${
82
96
  color.bg600
83
97
  } py-2 px-4 text-sm font-medium text-white shadow-sm focus:outline-none focus:ring-2 focus:${
@@ -87,4 +101,10 @@ export const Button = (props: Props) => {
87
101
  {loading ? loadingText : inside}
88
102
  </button>
89
103
  );
104
+
105
+ return formHasErrors ? (
106
+ <WithTooltip text={errorMessage}>{buttonContent}</WithTooltip>
107
+ ) : (
108
+ buttonContent
109
+ );
90
110
  };
@@ -1,7 +1,6 @@
1
1
  import React, { useEffect, useCallback, useState, type ReactNode } from "react";
2
- import { TextFieldWithoutValidation } from "../Form/TextField/index.js";
3
- import { SelectFieldWithoutValidation } from "../Form/SelectField/index.js";
4
- import type { SingleValue } from "react-select";
2
+ import { TextField } from "../Form/TextField/index.js";
3
+ import { SelectField } from "../Form/SelectField/index.js";
5
4
  import { useAppSelector } from "@zauru-sdk/redux";
6
5
  import { SelectFieldOption } from "@zauru-sdk/types";
7
6
 
@@ -43,11 +42,11 @@ export const DynamicPrintTable = ({ forwardedRef, ...props }: Props) => {
43
42
  rowIndex: number,
44
43
  defaultValue?: SelectFieldOption
45
44
  ) => (
46
- <SelectFieldWithoutValidation
45
+ <SelectField
47
46
  key={rowIndex}
48
47
  name="item_select"
49
48
  isClearable
50
- onChange={(value: SingleValue<SelectFieldOption>) => {
49
+ onChange={(value: SelectFieldOption | null) => {
51
50
  const selectedItem = items?.find((x) => x.value === value?.value);
52
51
  updateRow(rowIndex, selectedItem);
53
52
  }}
@@ -57,7 +56,7 @@ export const DynamicPrintTable = ({ forwardedRef, ...props }: Props) => {
57
56
  );
58
57
 
59
58
  const createItemQuantity = (rowIndex: number, defaultValue?: number) => (
60
- <TextFieldWithoutValidation
59
+ <TextField
61
60
  key={rowIndex}
62
61
  name="item_quantity"
63
62
  type="number"
@@ -1,7 +1,7 @@
1
1
  import React, { useEffect, useState } from "react";
2
- import { TextAreaWithoutValidation } from "../Form/TextArea/index.js";
3
- import { TextFieldWithoutValidation } from "../Form/TextField/index.js";
4
- import { CheckboxWithoutValidation } from "../Form/Checkbox/index.js";
2
+ import { TextArea } from "../Form/TextArea/index.js";
3
+ import { TextField } from "../Form/TextField/index.js";
4
+ import { CheckBox } from "../Form/Checkbox/index.js";
5
5
 
6
6
  type Props = {
7
7
  cellInputs?: boolean;
@@ -251,7 +251,7 @@ export const DynamicTable = (
251
251
  style={{ ...cellBordered, ...pastelGrayBackground }}
252
252
  >
253
253
  <div className="inline-flex">
254
- <TextFieldWithoutValidation
254
+ <TextField
255
255
  style={{ maxWidth: "45%", minWidth: "45%" }}
256
256
  name={`column${col.id}`}
257
257
  defaultValue={tableData[`column${col.id}`] || 1}
@@ -298,7 +298,7 @@ export const DynamicTable = (
298
298
  }}
299
299
  >
300
300
  <div className="inline-flex">
301
- <TextFieldWithoutValidation
301
+ <TextField
302
302
  style={{ maxWidth: "45%", minWidth: "45%" }}
303
303
  name={`row${rowId}`}
304
304
  defaultValue={tableData[`row${rowId}`] || 1}
@@ -329,13 +329,13 @@ export const DynamicTable = (
329
329
  style={{ ...cellBordered, ...cellCenteredContent }}
330
330
  >
331
331
  {cellInputs ? (
332
- <TextAreaWithoutValidation
332
+ <TextArea
333
333
  name={cellId}
334
334
  defaultValue={tableData[cellId] || ""}
335
335
  onChange={(value) => handleInputChange(cellId, value)}
336
336
  />
337
337
  ) : (
338
- <CheckboxWithoutValidation
338
+ <CheckBox
339
339
  name={cellId}
340
340
  defaultValue={cellValidation}
341
341
  onChange={(value) => {
@@ -1,7 +1,7 @@
1
1
  import React, { useEffect, useState } from "react";
2
- import { SelectFieldWithoutValidation } from "../Form/SelectField/index.js";
3
- import { TextFieldWithoutValidation } from "../Form/TextField/index.js";
4
- import { CheckboxWithoutValidation } from "../Form/Checkbox/index.js";
2
+ import { SelectField } from "../Form/SelectField/index.js";
3
+ import { TextField } from "../Form/TextField/index.js";
4
+ import { CheckBox } from "../Form/Checkbox/index.js";
5
5
  import { createModal } from "../Modal/index.js";
6
6
  import { Button } from "../Buttons/index.js";
7
7
  import {
@@ -122,7 +122,6 @@ export const GenericDynamicTable = (props: Props) => {
122
122
  newDeletedData.push(deletedItem);
123
123
  }
124
124
  setDeletedData(newDeletedData);
125
- onChange && onChange(tableData?.filter((x) => x.id !== rowId));
126
125
  setTableData((prevData) => prevData?.filter((x) => x.id !== rowId));
127
126
  };
128
127
 
@@ -200,10 +199,10 @@ export const GenericDynamicTable = (props: Props) => {
200
199
 
201
200
  const FieldComponent =
202
201
  column.type === "textField"
203
- ? TextFieldWithoutValidation
202
+ ? TextField
204
203
  : column.type === "checkbox"
205
- ? CheckboxWithoutValidation
206
- : SelectFieldWithoutValidation;
204
+ ? CheckBox
205
+ : SelectField;
207
206
 
208
207
  const setTableValue = (columnName: string, newValue: any) => {
209
208
  setTableData((prevState) => {
@@ -361,7 +360,7 @@ export const GenericDynamicTable = (props: Props) => {
361
360
  <div className={`${className}`}>
362
361
  {searcheables.length > 0 && (
363
362
  <div>
364
- <TextFieldWithoutValidation
363
+ <TextField
365
364
  className="mb-2"
366
365
  name="search"
367
366
  title={`Buscar por: ${searcheables
@@ -37,7 +37,7 @@ export const Footer = ({
37
37
  <div className="px-4 mx-auto flex flex-wrap items-center justify-center">
38
38
  <p className="text-white text-[1.2rem]">
39
39
  {`Creado en `} <a href={href}>Zauru</a>{" "}
40
- {`con ❤️ ${new Date().getFullYear()} v.3.2`}
40
+ {`con ❤️ ${new Date().getFullYear()} v.2.0.0`}
41
41
  </p>
42
42
  {showConnection && (
43
43
  <div className="ml-5">
@@ -1,10 +1,9 @@
1
- import { useAppSelector } from "@zauru-sdk/redux";
2
1
  import React, { useEffect, useState } from "react";
2
+ import { useFormContext } from "react-hook-form";
3
3
 
4
4
  type Props = {
5
5
  id?: string;
6
6
  name?: string;
7
- formName?: string;
8
7
  label?: string;
9
8
  defaultValue?: boolean;
10
9
  onChange?: (
@@ -12,19 +11,19 @@ type Props = {
12
11
  event: React.ChangeEvent<HTMLInputElement>
13
12
  ) => { stopUIChange: boolean } | void;
14
13
  disabled?: boolean;
15
- error?: string | undefined;
16
14
  borderColor?: string;
15
+ required?: boolean;
17
16
  };
18
17
 
19
- export const CheckboxWithoutValidation = (props: Props) => {
18
+ export const CheckBox = (props: Props) => {
20
19
  const {
21
20
  id,
22
21
  name,
23
22
  defaultValue = false,
24
23
  onChange,
25
24
  disabled = false,
26
- error,
27
25
  label,
26
+ required = false,
28
27
  } = props;
29
28
 
30
29
  const [checked, setChecked] = useState(defaultValue);
@@ -35,6 +34,9 @@ export const CheckboxWithoutValidation = (props: Props) => {
35
34
 
36
35
  const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
37
36
  const isChecked = event.target.checked;
37
+ if (register) {
38
+ register.onChange(event);
39
+ }
38
40
  if (onChange) {
39
41
  const result = onChange(isChecked, event);
40
42
  if (result?.stopUIChange) {
@@ -44,6 +46,15 @@ export const CheckboxWithoutValidation = (props: Props) => {
44
46
  setChecked(isChecked);
45
47
  };
46
48
 
49
+ const {
50
+ register: tempRegister,
51
+ formState: { errors },
52
+ } = useFormContext() || { formState: {} }; // Obtener el contexto solo si existe
53
+ const error = errors ? errors[props.name ?? "-1"] : undefined;
54
+ const register = tempRegister
55
+ ? tempRegister(props.name ?? "-1", { required })
56
+ : undefined; // Solo usar register si está disponible
57
+
47
58
  const color = error ? "red" : "gray";
48
59
  const borderColor = disabled ? "border-gray-300" : `border-${color}-500`;
49
60
 
@@ -51,11 +62,12 @@ export const CheckboxWithoutValidation = (props: Props) => {
51
62
  <input
52
63
  type="checkbox"
53
64
  id={id ?? name}
54
- name={name}
55
65
  checked={checked}
56
- onChange={handleInputChange}
57
66
  className={`form-checkbox h-4 w-4 text-indigo-600 ${borderColor} focus:border-indigo-500 focus:ring-indigo-500`}
58
67
  disabled={disabled}
68
+ {...(register ?? {})}
69
+ name={name}
70
+ onChange={handleInputChange}
59
71
  />
60
72
  );
61
73
 
@@ -73,24 +85,15 @@ export const CheckboxWithoutValidation = (props: Props) => {
73
85
  className={`ml-2 block text-sm font-medium text-${color}-700 dark:text-${color}-500`}
74
86
  >
75
87
  {label}
88
+ {required && <span className="text-red-500">*</span>}
76
89
  </label>
77
90
  )}
78
91
  </div>
79
92
  {error && (
80
93
  <p className={`mt-2 text-sm text-${color}-600 dark:text-${color}-500`}>
81
- <span className="font-medium">Oops!</span> {error}
94
+ <span className="font-medium">Oops!</span> {error.message?.toString()}
82
95
  </p>
83
96
  )}
84
97
  </div>
85
98
  );
86
99
  };
87
-
88
- //<reference> https://tailwindui.com/components/application-ui/forms/form-layouts
89
- export const CheckBox = (props: Props) => {
90
- const { formValidations } = useAppSelector((state) => state.formValidation);
91
- const error = formValidations[props.formName ?? "-1"]?.[props.name ?? "-1"];
92
-
93
- props = { ...props, error };
94
-
95
- return <CheckboxWithoutValidation {...props} />;
96
- };
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { CheckboxWithoutValidation } from "../Checkbox/index.js";
2
+ import { CheckBox } from "../Checkbox/index.js";
3
3
 
4
4
  export type ChecklistItem = {
5
5
  id: string;
@@ -24,7 +24,7 @@ export const Checklist: React.FC<ChecklistProps> = ({ items, onChange }) => {
24
24
  return (
25
25
  <div>
26
26
  {items.map((item) => (
27
- <CheckboxWithoutValidation
27
+ <CheckBox
28
28
  key={item.id}
29
29
  {...item}
30
30
  onChange={(value) => handleCheckboxChange(item.name, value)}
@@ -1,11 +1,10 @@
1
1
  import React, { useEffect, useState } from "react";
2
2
  import { CalendarIconSVG, CloseSvgIcon, IdeaIconSVG } from "@zauru-sdk/icons";
3
- import { useAppSelector } from "@zauru-sdk/redux";
3
+ import { useFormContext } from "react-hook-form";
4
4
 
5
5
  type Props = {
6
6
  id?: string;
7
7
  name: string;
8
- formName?: string;
9
8
  title?: string;
10
9
  hint?: string;
11
10
  helpText?: string;
@@ -13,12 +12,12 @@ type Props = {
13
12
  onChange?: (value: string) => void;
14
13
  isClearable?: boolean;
15
14
  tabIndex?: number;
16
- error?: string;
17
15
  disabled?: boolean;
18
16
  className?: string;
17
+ required?: boolean;
19
18
  };
20
19
 
21
- export const FormDatePickerWithoutValidation = (props: Props) => {
20
+ export const FormDatePicker = (props: Props) => {
22
21
  const {
23
22
  id,
24
23
  name,
@@ -28,14 +27,22 @@ export const FormDatePickerWithoutValidation = (props: Props) => {
28
27
  helpText,
29
28
  onChange,
30
29
  tabIndex,
31
- error,
32
30
  disabled = false,
33
31
  className = "",
34
32
  isClearable = false,
33
+ required = false,
35
34
  } = props;
36
35
 
37
36
  const [value, setValue] = useState<string | null>(defaultValue);
38
37
  const [showTooltip, setShowTooltip] = useState<boolean>(false);
38
+ const {
39
+ register: tempRegister,
40
+ formState: { errors },
41
+ } = useFormContext() || { formState: {} }; // Obtener el contexto solo si existe
42
+ const error = errors ? errors[props.name ?? "-1"] : undefined;
43
+ const register = tempRegister
44
+ ? tempRegister(props.name ?? "-1", { required })
45
+ : undefined; // Solo usar register si está disponible
39
46
 
40
47
  const color = error ? "red" : "gray";
41
48
 
@@ -61,6 +68,7 @@ export const FormDatePickerWithoutValidation = (props: Props) => {
61
68
  className={`block text-sm font-medium ${textColor} ${className}`}
62
69
  >
63
70
  {title}
71
+ {required && <span className="text-red-500">*</span>}
64
72
  </label>
65
73
  )}
66
74
  <div className="flex relative items-center">
@@ -69,16 +77,20 @@ export const FormDatePickerWithoutValidation = (props: Props) => {
69
77
  </div>
70
78
  <input
71
79
  id={id}
72
- name={name}
73
80
  tabIndex={tabIndex}
74
81
  type="date"
82
+ value={value ?? ""}
83
+ pattern="\d{4}-\d{2}-\d{2}"
84
+ className={`${bgColor} ${borderColor} ${textColor} text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full pl-10 p-2.5`}
85
+ {...(register ?? {})}
86
+ name={name}
75
87
  onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
76
88
  setValue(e.target.value);
77
89
  onChange && onChange(e.target.value);
90
+ if (register) {
91
+ register.onChange(e);
92
+ }
78
93
  }}
79
- value={value ?? ""}
80
- pattern="\d{4}-\d{2}-\d{2}"
81
- className={`${bgColor} ${borderColor} ${textColor} text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full pl-10 p-2.5`}
82
94
  ></input>
83
95
  {value && isClearable && (
84
96
  <button
@@ -108,7 +120,7 @@ export const FormDatePickerWithoutValidation = (props: Props) => {
108
120
  </div>
109
121
  {error && (
110
122
  <p className={`mt-2 text-sm text-${color}-600 dark:text-${color}-500`}>
111
- <span className="font-medium">Oops!</span> {error}
123
+ <span className="font-medium">Oops!</span> {error.message?.toString()}
112
124
  </p>
113
125
  )}
114
126
  {!error && hint && (
@@ -121,12 +133,3 @@ export const FormDatePickerWithoutValidation = (props: Props) => {
121
133
  </>
122
134
  );
123
135
  };
124
-
125
- export const FormDatePicker = (props: Props) => {
126
- const { formValidations } = useAppSelector((state) => state.formValidation);
127
- const error = formValidations[props.formName ?? "-1"]?.[props.name ?? "-1"];
128
-
129
- props = { ...props, error };
130
-
131
- return <FormDatePickerWithoutValidation {...props} />;
132
- };
@@ -1,4 +1,4 @@
1
- import { TextField, TextFieldWithoutValidation } from "../TextField/index.js";
1
+ import { TextField } from "../TextField/index.js";
2
2
  import { TripleFieldContainer } from "../FieldContainer/index.js";
3
3
  import { DoubleFieldContainer } from "../FieldContainer/index.js";
4
4
  import { YesNo } from "../YesNo/index.js";
@@ -74,7 +74,7 @@ export function DynamicBaculoForm(props: Props) {
74
74
  }
75
75
  case "zauru_data":
76
76
  return (
77
- <TextFieldWithoutValidation
77
+ <TextField
78
78
  key={field.id}
79
79
  title={`${field.required ? "*" : ""}${field.name}`}
80
80
  hint={field.hint}
@@ -1,6 +1,6 @@
1
1
  import { DownloadIconSVG, IdeaIconSVG } from "@zauru-sdk/icons";
2
- import { useAppSelector } from "@zauru-sdk/redux";
3
2
  import React, { useState } from "react";
3
+ import { useFormContext } from "react-hook-form";
4
4
 
5
5
  type Props = {
6
6
  id?: string;
@@ -12,15 +12,15 @@ type Props = {
12
12
  onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
13
13
  disabled?: boolean;
14
14
  readOnly?: boolean;
15
- error?: string | undefined;
16
15
  fileTypes?: string[];
17
16
  showAvailableTypes?: boolean;
18
17
  className?: string;
19
18
  defaultValue?: string | File;
20
19
  download?: boolean;
20
+ required?: boolean;
21
21
  };
22
22
 
23
- export const FileUploadFieldWithoutValidation = (props: Props) => {
23
+ export const FileUploadField = (props: Props) => {
24
24
  const {
25
25
  id,
26
26
  name,
@@ -30,14 +30,23 @@ export const FileUploadFieldWithoutValidation = (props: Props) => {
30
30
  onChange,
31
31
  disabled = false,
32
32
  readOnly = false,
33
- error,
34
33
  fileTypes = [],
35
34
  showAvailableTypes = false,
36
35
  className,
37
36
  defaultValue = undefined,
38
37
  download = false,
38
+ required = false,
39
39
  } = props;
40
40
 
41
+ const {
42
+ register: tempRegister,
43
+ formState: { errors },
44
+ } = useFormContext() || { formState: {} }; // Obtener el contexto solo si existe
45
+ const error = errors ? errors[props.name ?? "-1"] : undefined;
46
+ const register = tempRegister
47
+ ? tempRegister(props.name ?? "-1", { required })
48
+ : undefined; // Solo usar register si está disponible
49
+
41
50
  const [showTooltip, setShowTooltip] = useState<boolean>(false);
42
51
 
43
52
  if (typeof defaultValue == "string") {
@@ -76,17 +85,32 @@ export const FileUploadFieldWithoutValidation = (props: Props) => {
76
85
  className={`block mb-1 text-sm font-medium text-gray-700`}
77
86
  >
78
87
  {title}
88
+ {required && <span className="text-red-500">*</span>}
79
89
  </label>
80
90
  )}{" "}
81
91
  <div
82
92
  role="button"
83
93
  tabIndex={0}
84
94
  onClick={() => {
95
+ if (register) {
96
+ register.onChange({
97
+ target: {
98
+ value: defaultValue,
99
+ },
100
+ });
101
+ }
85
102
  window.open(defaultValue, "_blank");
86
103
  }}
87
104
  onKeyDown={(event) => {
88
105
  // Permite que el evento se active con la tecla Enter
89
106
  if (event.key === "Enter") {
107
+ if (register) {
108
+ register.onChange({
109
+ target: {
110
+ value: defaultValue,
111
+ },
112
+ });
113
+ }
90
114
  window.open(defaultValue, "_blank");
91
115
  }
92
116
  }}
@@ -164,7 +188,7 @@ export const FileUploadFieldWithoutValidation = (props: Props) => {
164
188
  </div>
165
189
  {error && (
166
190
  <p className={`mt-2 text-sm text-${color}-600`}>
167
- <span className="font-medium">Oops!</span> {error}
191
+ <span className="font-medium">Oops!</span> {error.message?.toString()}
168
192
  </p>
169
193
  )}
170
194
  {!error && hintMessage && (
@@ -173,12 +197,3 @@ export const FileUploadFieldWithoutValidation = (props: Props) => {
173
197
  </div>
174
198
  );
175
199
  };
176
-
177
- export const FileUploadField = (props: Props) => {
178
- const { formValidations } = useAppSelector((state) => state.formValidation);
179
- const error = formValidations[props.formName ?? "-1"]?.[props.name ?? "-1"];
180
-
181
- props = { ...props, error };
182
-
183
- return <FileUploadFieldWithoutValidation {...props} />;
184
- };
@@ -0,0 +1,60 @@
1
+ import { zodResolver } from "@hookform/resolvers/zod";
2
+ import { Form, useSubmit } from "@remix-run/react";
3
+ import {
4
+ FieldValues,
5
+ FormProvider,
6
+ SubmitHandler,
7
+ useForm,
8
+ } from "react-hook-form";
9
+ import { z, ZodSchema } from "zod";
10
+ import React from "react";
11
+
12
+ type Props = {
13
+ children: React.ReactNode;
14
+ schema?: ZodSchema;
15
+ onSubmit?: SubmitHandler<FieldValues>;
16
+ id?: string;
17
+ method?: "post" | "put" | "delete" | "patch";
18
+ };
19
+
20
+ const emptySchema = z.any();
21
+
22
+ export const ReactZodForm = (props: Props) => {
23
+ const {
24
+ children,
25
+ method = "post",
26
+ schema = emptySchema,
27
+ onSubmit,
28
+ id,
29
+ } = props;
30
+
31
+ const submit = useSubmit();
32
+ const methods = useForm({
33
+ resolver: zodResolver(schema),
34
+ mode: "onSubmit",
35
+ });
36
+
37
+ const handleSubmit: SubmitHandler<FieldValues> = (data, event) => {
38
+ if (onSubmit) {
39
+ onSubmit(data, event);
40
+ } else {
41
+ // If no onSubmit is provided, use Remix's submit function
42
+ submit(event?.target as HTMLFormElement, { method });
43
+ }
44
+ };
45
+
46
+ return (
47
+ <FormProvider {...methods}>
48
+ <Form
49
+ onSubmit={onSubmit ? methods.handleSubmit(onSubmit) : undefined}
50
+ //onSubmit={methods.handleSubmit(handleSubmit)}
51
+ method={method}
52
+ id={id}
53
+ >
54
+ {children}
55
+ </Form>
56
+ </FormProvider>
57
+ );
58
+ };
59
+
60
+ export default ReactZodForm;