@zauru-sdk/components 1.0.112 → 1.0.113
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/CHANGELOG.md +8 -0
- package/dist/HOC/ValidateEmployeeAccess/index.d.ts +5 -0
- package/dist/Layouts/errorLayout/index.d.ts +1 -0
- package/dist/Layouts/index.d.ts +1 -0
- package/dist/cjs/Buttons/Button.js +7 -7
- package/dist/cjs/Form/ReactZodForm/index.js +1 -3
- package/dist/cjs/Form/SelectField/index.js +17 -10
- package/dist/cjs/Form/TextField/index.js +7 -15
- package/dist/cjs/HOC/ValidateEmployeeAccess/index.js +17 -0
- package/dist/cjs/Layouts/errorLayout/index.js +14 -0
- package/dist/cjs/Layouts/index.js +1 -0
- package/dist/cjs/index.js +1 -0
- package/dist/esm/Buttons/Button.js +7 -7
- package/dist/esm/Form/ReactZodForm/index.js +1 -3
- package/dist/esm/Form/SelectField/index.js +18 -11
- package/dist/esm/Form/TextField/index.js +7 -15
- package/dist/esm/HOC/ValidateEmployeeAccess/index.js +13 -0
- package/dist/esm/Layouts/errorLayout/index.js +10 -0
- package/dist/esm/Layouts/index.js +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/index.d.ts +1 -0
- package/package.json +3 -3
- package/src/Buttons/Button.tsx +29 -28
- package/src/Form/ReactZodForm/index.tsx +1 -2
- package/src/Form/SelectField/index.tsx +42 -34
- package/src/Form/TextField/index.tsx +11 -16
- package/src/HOC/ValidateEmployeeAccess/index.tsx +51 -0
- package/src/Layouts/errorLayout/index.tsx +47 -0
- package/src/Layouts/index.ts +1 -0
- package/src/index.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [1.0.113](https://github.com/intuitiva/zauru-typescript-sdk/compare/v1.0.112...v1.0.113) (2024-09-25)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @zauru-sdk/components
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
6
14
|
## [1.0.112](https://github.com/intuitiva/zauru-typescript-sdk/compare/v1.0.111...v1.0.112) (2024-09-19)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @zauru-sdk/components
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const ErrorLayout: () => import("react/jsx-runtime").JSX.Element;
|
package/dist/Layouts/index.d.ts
CHANGED
|
@@ -49,13 +49,13 @@ const Button = (props) => {
|
|
|
49
49
|
.map((error) => error?.message?.toString())
|
|
50
50
|
.join(", ")
|
|
51
51
|
: "";
|
|
52
|
-
const buttonContent = ((0, jsx_runtime_1.jsx)("
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
const buttonContent = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("input", { type: "hidden", name: "action", value: name }), (0, jsx_runtime_1.jsx)("button", { type: type, disabled: loading || disabled || (enableFormErrorsValidation && formHasErrors), onClick: onClickSave, className: `ml-2 ${loading || disabled || (enableFormErrorsValidation && formHasErrors)
|
|
53
|
+
? " bg-opacity-25 "
|
|
54
|
+
: ""} ${loading
|
|
55
|
+
? " cursor-progress"
|
|
56
|
+
: `${disabled || (enableFormErrorsValidation && formHasErrors)
|
|
57
|
+
? ""
|
|
58
|
+
: `hover:${color.bg700}`}`} inline-flex justify-center rounded-md border border-transparent ${color.bg600} py-2 px-4 text-sm font-medium text-white shadow-sm focus:outline-none focus:ring-2 focus:${color.ring500} focus:ring-offset-2 ${className}`, children: loading ? loadingText : inside })] }));
|
|
59
59
|
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(enableFormErrorsValidation && formHasErrors && errorMessage) ||
|
|
60
60
|
(enableFormErrorsDescriptions && errorMessage) ? ((0, jsx_runtime_1.jsx)("div", { className: "flex flex-col items-end mb-2", children: (0, jsx_runtime_1.jsx)("div", { className: "p-2 bg-red-100 border border-red-400 text-red-700 rounded-md shadow-sm", children: (0, jsx_runtime_1.jsx)("p", { className: "text-sm", children: errorMessage }) }) })) : null, buttonContent] }));
|
|
61
61
|
};
|
|
@@ -23,9 +23,7 @@ const ReactZodForm = (props) => {
|
|
|
23
23
|
submit(event?.target, { method });
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
|
-
return ((0, jsx_runtime_1.jsx)(react_hook_form_1.FormProvider, { ...methods, children: (0, jsx_runtime_1.jsx)(react_1.Form, { onSubmit:
|
|
27
|
-
//onSubmit={methods.handleSubmit(handleSubmit)}
|
|
28
|
-
method: method, id: id, children: children }) }));
|
|
26
|
+
return ((0, jsx_runtime_1.jsx)(react_hook_form_1.FormProvider, { ...methods, children: (0, jsx_runtime_1.jsx)(react_1.Form, { onSubmit: methods.handleSubmit(handleSubmit), method: method, id: id, children: children }) }));
|
|
29
27
|
};
|
|
30
28
|
exports.ReactZodForm = ReactZodForm;
|
|
31
29
|
exports.default = exports.ReactZodForm;
|
|
@@ -7,7 +7,7 @@ const react_1 = require("react");
|
|
|
7
7
|
const index_js_1 = require("../../Skeletons/index.js");
|
|
8
8
|
const react_hook_form_1 = require("react-hook-form");
|
|
9
9
|
const SelectField = (props) => {
|
|
10
|
-
const { id, name, title, defaultValue, defaultValueMulti = [], helpText, hint, options, onChange, onChangeMulti, isClearable = false, disabled = false, readOnly = false, isMulti = false, loading = false, className = "", onInputChange, required, } = props;
|
|
10
|
+
const { id, name, title, defaultValue, defaultValueMulti = [], helpText, hint, options, onChange, onChangeMulti, isClearable = false, disabled = false, readOnly = false, isMulti = false, loading = false, className = "", onInputChange, required = false, } = props;
|
|
11
11
|
const [value, setValue] = (0, react_1.useState)(defaultValue || null);
|
|
12
12
|
const [valueMulti, setValueMulti] = (0, react_1.useState)(defaultValueMulti);
|
|
13
13
|
const [inputValue, setInputValue] = (0, react_1.useState)(defaultValue?.label || "");
|
|
@@ -20,8 +20,13 @@ const SelectField = (props) => {
|
|
|
20
20
|
const [isTabPressed, setIsTabPressed] = (0, react_1.useState)(false);
|
|
21
21
|
const [isEnterPressed, setIsEnterPressed] = (0, react_1.useState)(false);
|
|
22
22
|
const [isSearching, setIsSearching] = (0, react_1.useState)(false);
|
|
23
|
-
const {
|
|
23
|
+
const { register: tempRegister, formState: { errors }, setValue: setFormValue, } = (0, react_hook_form_1.useFormContext)() || { formState: {} };
|
|
24
24
|
const error = errors ? errors[props.name ?? "-1"] : undefined;
|
|
25
|
+
const register = tempRegister
|
|
26
|
+
? tempRegister(props.name ?? "-1", {
|
|
27
|
+
required,
|
|
28
|
+
})
|
|
29
|
+
: undefined; // Solo usar register si está disponible
|
|
25
30
|
const color = error ? "red" : "gray";
|
|
26
31
|
const isReadOnly = disabled || readOnly;
|
|
27
32
|
const bgColor = isReadOnly ? "bg-gray-200" : `bg-${color}-50`;
|
|
@@ -40,7 +45,7 @@ const SelectField = (props) => {
|
|
|
40
45
|
if (defaultValue) {
|
|
41
46
|
setValue(defaultValue);
|
|
42
47
|
setInputValue(defaultValue.label);
|
|
43
|
-
setFormValue(name || "", defaultValue);
|
|
48
|
+
setFormValue(name || "", defaultValue.value);
|
|
44
49
|
}
|
|
45
50
|
document.addEventListener("mousedown", handleClickOutside);
|
|
46
51
|
return () => {
|
|
@@ -49,6 +54,9 @@ const SelectField = (props) => {
|
|
|
49
54
|
}, []);
|
|
50
55
|
const handleInputChange = (e) => {
|
|
51
56
|
const newValue = e.target.value;
|
|
57
|
+
if (register) {
|
|
58
|
+
register.onChange(e);
|
|
59
|
+
}
|
|
52
60
|
setInputValue(newValue);
|
|
53
61
|
onInputChange && onInputChange(newValue);
|
|
54
62
|
setIsSearching(true);
|
|
@@ -61,13 +69,13 @@ const SelectField = (props) => {
|
|
|
61
69
|
: [...valueMulti, option];
|
|
62
70
|
setValueMulti(newValue);
|
|
63
71
|
onChangeMulti && onChangeMulti(newValue);
|
|
64
|
-
setFormValue(name || "", newValue);
|
|
72
|
+
setFormValue(name || "", newValue.map((v) => v.value));
|
|
65
73
|
}
|
|
66
74
|
else {
|
|
67
75
|
setValue(option);
|
|
68
76
|
setInputValue(option.label);
|
|
69
77
|
onChange && onChange(option);
|
|
70
|
-
setFormValue(name || "", option);
|
|
78
|
+
setFormValue(name || "", option.value);
|
|
71
79
|
}
|
|
72
80
|
setIsOpen(false);
|
|
73
81
|
};
|
|
@@ -80,7 +88,7 @@ const SelectField = (props) => {
|
|
|
80
88
|
else {
|
|
81
89
|
setValue(null);
|
|
82
90
|
onChange && onChange(null);
|
|
83
|
-
setFormValue(name || "",
|
|
91
|
+
setFormValue(name || "", "");
|
|
84
92
|
}
|
|
85
93
|
setInputValue("");
|
|
86
94
|
};
|
|
@@ -145,10 +153,9 @@ const SelectField = (props) => {
|
|
|
145
153
|
}
|
|
146
154
|
return ((0, jsx_runtime_1.jsxs)("div", { className: `col-span-6 sm:col-span-3 ${className}`, ref: selectRef, children: [title && ((0, jsx_runtime_1.jsxs)("label", { htmlFor: error ? `${name}-error` : `${name}-success`, className: `block text-sm font-medium ${color === "red"
|
|
147
155
|
? "text-red-700 dark:text-red-500"
|
|
148
|
-
: "text-gray-700 dark:text-gray-500"}`, children: [title, required && (0, jsx_runtime_1.jsx)("span", { className: "text-red-500", children: "*" })] })), (0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsx)(
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}, autoComplete: "off" })) }), isClearable && (value || valueMulti.length > 0) && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: handleClear, className: "absolute inset-y-0 right-0 pr-3 flex items-center", children: "\u00D7" })), isOpen && !isReadOnly && ((0, jsx_runtime_1.jsx)("ul", { ref: optionsRef, className: "absolute z-10 mt-1 w-full bg-white shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm", children: filteredOptions.map((option, index) => ((0, jsx_runtime_1.jsx)("li", { className: `cursor-pointer select-none relative py-2 pl-3 pr-9 ${(isMulti
|
|
156
|
+
: "text-gray-700 dark:text-gray-500"}`, children: [title, required && (0, jsx_runtime_1.jsx)("span", { className: "text-red-500", children: "*" })] })), (0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsx)("input", { type: "text", id: id, value: inputValue, onFocus: () => setIsOpen(true), onKeyDown: handleKeyDown, readOnly: isReadOnly, disabled: disabled, className: `block w-full rounded-md ${bgColor} ${borderColor} ${textColor} shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm`, placeholder: isMulti ? "Select options..." : "Select an option...", autoComplete: "off", onChange: handleInputChange, onBlur: handleBlur, required: required }), (0, jsx_runtime_1.jsx)("input", { type: "hidden", ...(register ?? {}), name: name, value: isMulti
|
|
157
|
+
? valueMulti.map((v) => v.value).join(",")
|
|
158
|
+
: value?.value || "" }), isClearable && (value || valueMulti.length > 0) && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: handleClear, className: "absolute inset-y-0 right-0 pr-3 flex items-center", children: "\u00D7" })), isOpen && !isReadOnly && ((0, jsx_runtime_1.jsx)("ul", { ref: optionsRef, className: "absolute z-10 mt-1 w-full bg-white shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm", children: filteredOptions.map((option, index) => ((0, jsx_runtime_1.jsx)("li", { className: `cursor-pointer select-none relative py-2 pl-3 pr-9 ${(isMulti
|
|
152
159
|
? valueMulti.some((v) => v.value === option.value)
|
|
153
160
|
: value?.value === option.value)
|
|
154
161
|
? "text-white bg-indigo-600"
|
|
@@ -9,7 +9,7 @@ const TextField = (props) => {
|
|
|
9
9
|
const { id, name, defaultValue = "", hidden, type = "text", onChange, onKeyDown, disabled = false, readOnly = false, min, integer = false, stopChangeEvents, style, title, helpText, className, hint, required, } = props;
|
|
10
10
|
const [showTooltip, setShowTooltip] = (0, react_1.useState)(false);
|
|
11
11
|
const [value, setValue] = (0, react_1.useState)(defaultValue);
|
|
12
|
-
const { register: tempRegister, formState: { errors }, } = (0, react_hook_form_1.useFormContext)() || { formState: {} }; // Obtener el contexto solo si existe
|
|
12
|
+
const { register: tempRegister, formState: { errors }, setValue: setOnFormValue, } = (0, react_hook_form_1.useFormContext)() || { formState: {} }; // Obtener el contexto solo si existe
|
|
13
13
|
const error = errors ? errors[props.name ?? "-1"] : undefined;
|
|
14
14
|
const register = tempRegister
|
|
15
15
|
? tempRegister(props.name ?? "-1", {
|
|
@@ -23,9 +23,11 @@ const TextField = (props) => {
|
|
|
23
23
|
const textColor = isReadOnly ? "text-gray-500" : `text-${color}-900`;
|
|
24
24
|
const borderColor = isReadOnly ? "border-gray-300" : `border-${color}-500`;
|
|
25
25
|
(0, react_1.useEffect)(() => {
|
|
26
|
+
setOnFormValue(name ?? "-1", defaultValue);
|
|
26
27
|
setValue(defaultValue);
|
|
27
28
|
}, [defaultValue]);
|
|
28
29
|
const handleInputChange = (event) => {
|
|
30
|
+
const newValue = event.target.value;
|
|
29
31
|
if (register) {
|
|
30
32
|
register.onChange(event);
|
|
31
33
|
}
|
|
@@ -33,18 +35,8 @@ const TextField = (props) => {
|
|
|
33
35
|
event.stopPropagation();
|
|
34
36
|
event.preventDefault();
|
|
35
37
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const isInteger = /^[0-9]*$/.test(value);
|
|
39
|
-
if (isInteger || value === "") {
|
|
40
|
-
setValue(value);
|
|
41
|
-
onChange && onChange(value, event);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
setValue(event.target.value);
|
|
46
|
-
onChange && onChange(event.target.value, event);
|
|
47
|
-
}
|
|
38
|
+
setValue(newValue);
|
|
39
|
+
onChange && onChange(newValue, event);
|
|
48
40
|
};
|
|
49
41
|
const handleKeyDown = (event) => {
|
|
50
42
|
if (integer && type === "number") {
|
|
@@ -63,9 +55,9 @@ const TextField = (props) => {
|
|
|
63
55
|
}
|
|
64
56
|
};
|
|
65
57
|
if (hidden) {
|
|
66
|
-
return ((0, jsx_runtime_1.jsx)("input", { type:
|
|
58
|
+
return ((0, jsx_runtime_1.jsx)("input", { type: type, id: id ?? name, value: value, hidden: true, ...(register ?? {}), name: name, onChange: handleInputChange }));
|
|
67
59
|
}
|
|
68
|
-
const inputComponent = ((0, jsx_runtime_1.jsx)("input", { type: type, readOnly:
|
|
60
|
+
const inputComponent = ((0, jsx_runtime_1.jsx)("input", { type: type, readOnly: isReadOnly, disabled: disabled, id: id ?? name, autoComplete: "off", value: value, onWheel: (e) => {
|
|
69
61
|
e.currentTarget.blur();
|
|
70
62
|
}, step: type === "number" ? 0.01 : undefined, onKeyDown: (event) => {
|
|
71
63
|
handleKeyDown(event);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ValidateEmployeeAccess = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const hooks_1 = require("@zauru-sdk/hooks");
|
|
6
|
+
const react_1 = require("@remix-run/react");
|
|
7
|
+
const ValidateEmployeeAccess = ({ children, permissionVariableName, showIfNoPermission = false, }) => {
|
|
8
|
+
const { data: employee } = (0, hooks_1.useGetEmployeeProfile)();
|
|
9
|
+
const variable_string = (0, hooks_1.useGetSessionAttribute)(permissionVariableName, "sessionVariable");
|
|
10
|
+
const variable = variable_string?.split(",");
|
|
11
|
+
const hasPermission = variable?.includes(employee?.id?.toString() || "-1");
|
|
12
|
+
if (showIfNoPermission && !hasPermission) {
|
|
13
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "bg-gray-900 text-white min-h-screen flex flex-col items-center justify-center p-4", children: [(0, jsx_runtime_1.jsx)("img", { src: "/logo.png", alt: "Zauru Logo", className: "mb-8 h-20" }), (0, jsx_runtime_1.jsx)("h1", { className: "text-5xl font-extrabold text-red-500 mb-6", children: "\u00A1Acceso Denegado!" }), (0, jsx_runtime_1.jsx)("div", { className: "w-full max-w-2xl", children: (0, jsx_runtime_1.jsx)("p", { className: "text-2xl text-gray-300 mb-8 text-center", children: "Lo sentimos, no tienes permiso para acceder a esta p\u00E1gina." }) }), (0, jsx_runtime_1.jsx)(react_1.Link, { to: "/", className: "bg-blue-600 text-white py-3 px-8 rounded-full text-lg font-semibold hover:bg-blue-700 transition duration-300 transform hover:scale-105", children: "Regresar al inicio" }), (0, jsx_runtime_1.jsx)("div", { className: "mt-12 text-gray-500", children: (0, jsx_runtime_1.jsx)("p", { children: "Si crees que esto es un error, por favor contacta a soporte." }) })] }));
|
|
14
|
+
}
|
|
15
|
+
return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: hasPermission ? children : null });
|
|
16
|
+
};
|
|
17
|
+
exports.ValidateEmployeeAccess = ValidateEmployeeAccess;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ErrorLayout = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("@remix-run/react");
|
|
6
|
+
const ErrorLayout = () => {
|
|
7
|
+
const error = (0, react_1.useRouteError)();
|
|
8
|
+
return ((0, jsx_runtime_1.jsxs)("html", { lang: "es", className: "bg-gray-900 text-white", children: [(0, jsx_runtime_1.jsxs)("head", { children: [(0, jsx_runtime_1.jsx)("meta", { charSet: "utf-8" }), (0, jsx_runtime_1.jsx)("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), (0, jsx_runtime_1.jsx)("title", { children: "\u00A1Ups! Algo sali\u00F3 mal" }), (0, jsx_runtime_1.jsx)(react_1.Meta, {}), (0, jsx_runtime_1.jsx)(react_1.Links, {})] }), (0, jsx_runtime_1.jsxs)("body", { className: "min-h-screen flex flex-col items-center justify-center p-4", children: [(0, jsx_runtime_1.jsx)("img", { src: "/logo.png", alt: "Zauru Logo", className: "mb-8 h-20" }), (0, jsx_runtime_1.jsx)("h1", { className: "text-5xl font-extrabold text-red-500 mb-6", children: "\u00A1Ups!" }), (0, jsx_runtime_1.jsx)("div", { className: "w-full max-w-2xl", children: (0, jsx_runtime_1.jsx)("p", { className: "text-2xl text-gray-300 mb-8 text-center", children: (0, react_1.isRouteErrorResponse)(error)
|
|
9
|
+
? `Error ${error.status}: ${error.statusText}`
|
|
10
|
+
: error instanceof Error
|
|
11
|
+
? error.message
|
|
12
|
+
: "Ha ocurrido un error inesperado" }) }), (0, jsx_runtime_1.jsx)(react_1.Link, { to: "/", className: "bg-blue-600 text-white py-3 px-8 rounded-full text-lg font-semibold hover:bg-blue-700 transition duration-300 transform hover:scale-105", children: "Regresar al inicio" }), (0, jsx_runtime_1.jsx)("div", { className: "mt-12 text-gray-500", children: (0, jsx_runtime_1.jsx)("p", { children: "Si el problema persiste, por favor contacta a soporte." }) }), (0, jsx_runtime_1.jsx)(react_1.Scripts, {})] })] }));
|
|
13
|
+
};
|
|
14
|
+
exports.ErrorLayout = ErrorLayout;
|
package/dist/cjs/index.js
CHANGED
|
@@ -39,3 +39,4 @@ __exportStar(require("./Tooltip/index.js"), exports);
|
|
|
39
39
|
__exportStar(require("./WithTooltip/index.js"), exports);
|
|
40
40
|
__exportStar(require("./Wizards/index.js"), exports);
|
|
41
41
|
__exportStar(require("./Zendesk/index.js"), exports);
|
|
42
|
+
__exportStar(require("./HOC/ValidateEmployeeAccess/index.js"), exports);
|
|
@@ -46,13 +46,13 @@ export const Button = (props) => {
|
|
|
46
46
|
.map((error) => error?.message?.toString())
|
|
47
47
|
.join(", ")
|
|
48
48
|
: "";
|
|
49
|
-
const buttonContent = (_jsx("
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
const buttonContent = (_jsxs(_Fragment, { children: [_jsx("input", { type: "hidden", name: "action", value: name }), _jsx("button", { type: type, disabled: loading || disabled || (enableFormErrorsValidation && formHasErrors), onClick: onClickSave, className: `ml-2 ${loading || disabled || (enableFormErrorsValidation && formHasErrors)
|
|
50
|
+
? " bg-opacity-25 "
|
|
51
|
+
: ""} ${loading
|
|
52
|
+
? " cursor-progress"
|
|
53
|
+
: `${disabled || (enableFormErrorsValidation && formHasErrors)
|
|
54
|
+
? ""
|
|
55
|
+
: `hover:${color.bg700}`}`} inline-flex justify-center rounded-md border border-transparent ${color.bg600} py-2 px-4 text-sm font-medium text-white shadow-sm focus:outline-none focus:ring-2 focus:${color.ring500} focus:ring-offset-2 ${className}`, children: loading ? loadingText : inside })] }));
|
|
56
56
|
return (_jsxs(_Fragment, { children: [(enableFormErrorsValidation && formHasErrors && errorMessage) ||
|
|
57
57
|
(enableFormErrorsDescriptions && errorMessage) ? (_jsx("div", { className: "flex flex-col items-end mb-2", children: _jsx("div", { className: "p-2 bg-red-100 border border-red-400 text-red-700 rounded-md shadow-sm", children: _jsx("p", { className: "text-sm", children: errorMessage }) }) })) : null, buttonContent] }));
|
|
58
58
|
};
|
|
@@ -20,8 +20,6 @@ export const ReactZodForm = (props) => {
|
|
|
20
20
|
submit(event?.target, { method });
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
|
-
return (_jsx(FormProvider, { ...methods, children: _jsx(Form, { onSubmit:
|
|
24
|
-
//onSubmit={methods.handleSubmit(handleSubmit)}
|
|
25
|
-
method: method, id: id, children: children }) }));
|
|
23
|
+
return (_jsx(FormProvider, { ...methods, children: _jsx(Form, { onSubmit: methods.handleSubmit(handleSubmit), method: method, id: id, children: children }) }));
|
|
26
24
|
};
|
|
27
25
|
export default ReactZodForm;
|
|
@@ -2,9 +2,9 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { IdeaIconSVG } from "@zauru-sdk/icons";
|
|
3
3
|
import { useEffect, useState, useRef } from "react";
|
|
4
4
|
import { LoadingInputSkeleton } from "../../Skeletons/index.js";
|
|
5
|
-
import { useFormContext
|
|
5
|
+
import { useFormContext } from "react-hook-form";
|
|
6
6
|
export const SelectField = (props) => {
|
|
7
|
-
const { id, name, title, defaultValue, defaultValueMulti = [], helpText, hint, options, onChange, onChangeMulti, isClearable = false, disabled = false, readOnly = false, isMulti = false, loading = false, className = "", onInputChange, required, } = props;
|
|
7
|
+
const { id, name, title, defaultValue, defaultValueMulti = [], helpText, hint, options, onChange, onChangeMulti, isClearable = false, disabled = false, readOnly = false, isMulti = false, loading = false, className = "", onInputChange, required = false, } = props;
|
|
8
8
|
const [value, setValue] = useState(defaultValue || null);
|
|
9
9
|
const [valueMulti, setValueMulti] = useState(defaultValueMulti);
|
|
10
10
|
const [inputValue, setInputValue] = useState(defaultValue?.label || "");
|
|
@@ -17,8 +17,13 @@ export const SelectField = (props) => {
|
|
|
17
17
|
const [isTabPressed, setIsTabPressed] = useState(false);
|
|
18
18
|
const [isEnterPressed, setIsEnterPressed] = useState(false);
|
|
19
19
|
const [isSearching, setIsSearching] = useState(false);
|
|
20
|
-
const {
|
|
20
|
+
const { register: tempRegister, formState: { errors }, setValue: setFormValue, } = useFormContext() || { formState: {} };
|
|
21
21
|
const error = errors ? errors[props.name ?? "-1"] : undefined;
|
|
22
|
+
const register = tempRegister
|
|
23
|
+
? tempRegister(props.name ?? "-1", {
|
|
24
|
+
required,
|
|
25
|
+
})
|
|
26
|
+
: undefined; // Solo usar register si está disponible
|
|
22
27
|
const color = error ? "red" : "gray";
|
|
23
28
|
const isReadOnly = disabled || readOnly;
|
|
24
29
|
const bgColor = isReadOnly ? "bg-gray-200" : `bg-${color}-50`;
|
|
@@ -37,7 +42,7 @@ export const SelectField = (props) => {
|
|
|
37
42
|
if (defaultValue) {
|
|
38
43
|
setValue(defaultValue);
|
|
39
44
|
setInputValue(defaultValue.label);
|
|
40
|
-
setFormValue(name || "", defaultValue);
|
|
45
|
+
setFormValue(name || "", defaultValue.value);
|
|
41
46
|
}
|
|
42
47
|
document.addEventListener("mousedown", handleClickOutside);
|
|
43
48
|
return () => {
|
|
@@ -46,6 +51,9 @@ export const SelectField = (props) => {
|
|
|
46
51
|
}, []);
|
|
47
52
|
const handleInputChange = (e) => {
|
|
48
53
|
const newValue = e.target.value;
|
|
54
|
+
if (register) {
|
|
55
|
+
register.onChange(e);
|
|
56
|
+
}
|
|
49
57
|
setInputValue(newValue);
|
|
50
58
|
onInputChange && onInputChange(newValue);
|
|
51
59
|
setIsSearching(true);
|
|
@@ -58,13 +66,13 @@ export const SelectField = (props) => {
|
|
|
58
66
|
: [...valueMulti, option];
|
|
59
67
|
setValueMulti(newValue);
|
|
60
68
|
onChangeMulti && onChangeMulti(newValue);
|
|
61
|
-
setFormValue(name || "", newValue);
|
|
69
|
+
setFormValue(name || "", newValue.map((v) => v.value));
|
|
62
70
|
}
|
|
63
71
|
else {
|
|
64
72
|
setValue(option);
|
|
65
73
|
setInputValue(option.label);
|
|
66
74
|
onChange && onChange(option);
|
|
67
|
-
setFormValue(name || "", option);
|
|
75
|
+
setFormValue(name || "", option.value);
|
|
68
76
|
}
|
|
69
77
|
setIsOpen(false);
|
|
70
78
|
};
|
|
@@ -77,7 +85,7 @@ export const SelectField = (props) => {
|
|
|
77
85
|
else {
|
|
78
86
|
setValue(null);
|
|
79
87
|
onChange && onChange(null);
|
|
80
|
-
setFormValue(name || "",
|
|
88
|
+
setFormValue(name || "", "");
|
|
81
89
|
}
|
|
82
90
|
setInputValue("");
|
|
83
91
|
};
|
|
@@ -142,10 +150,9 @@ export const SelectField = (props) => {
|
|
|
142
150
|
}
|
|
143
151
|
return (_jsxs("div", { className: `col-span-6 sm:col-span-3 ${className}`, ref: selectRef, children: [title && (_jsxs("label", { htmlFor: error ? `${name}-error` : `${name}-success`, className: `block text-sm font-medium ${color === "red"
|
|
144
152
|
? "text-red-700 dark:text-red-500"
|
|
145
|
-
: "text-gray-700 dark:text-gray-500"}`, children: [title, required && _jsx("span", { className: "text-red-500", children: "*" })] })), _jsxs("div", { className: "relative", children: [_jsx(
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}, autoComplete: "off" })) }), isClearable && (value || valueMulti.length > 0) && (_jsx("button", { type: "button", onClick: handleClear, className: "absolute inset-y-0 right-0 pr-3 flex items-center", children: "\u00D7" })), isOpen && !isReadOnly && (_jsx("ul", { ref: optionsRef, className: "absolute z-10 mt-1 w-full bg-white shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm", children: filteredOptions.map((option, index) => (_jsx("li", { className: `cursor-pointer select-none relative py-2 pl-3 pr-9 ${(isMulti
|
|
153
|
+
: "text-gray-700 dark:text-gray-500"}`, children: [title, required && _jsx("span", { className: "text-red-500", children: "*" })] })), _jsxs("div", { className: "relative", children: [_jsx("input", { type: "text", id: id, value: inputValue, onFocus: () => setIsOpen(true), onKeyDown: handleKeyDown, readOnly: isReadOnly, disabled: disabled, className: `block w-full rounded-md ${bgColor} ${borderColor} ${textColor} shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm`, placeholder: isMulti ? "Select options..." : "Select an option...", autoComplete: "off", onChange: handleInputChange, onBlur: handleBlur, required: required }), _jsx("input", { type: "hidden", ...(register ?? {}), name: name, value: isMulti
|
|
154
|
+
? valueMulti.map((v) => v.value).join(",")
|
|
155
|
+
: value?.value || "" }), isClearable && (value || valueMulti.length > 0) && (_jsx("button", { type: "button", onClick: handleClear, className: "absolute inset-y-0 right-0 pr-3 flex items-center", children: "\u00D7" })), isOpen && !isReadOnly && (_jsx("ul", { ref: optionsRef, className: "absolute z-10 mt-1 w-full bg-white shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm", children: filteredOptions.map((option, index) => (_jsx("li", { className: `cursor-pointer select-none relative py-2 pl-3 pr-9 ${(isMulti
|
|
149
156
|
? valueMulti.some((v) => v.value === option.value)
|
|
150
157
|
: value?.value === option.value)
|
|
151
158
|
? "text-white bg-indigo-600"
|
|
@@ -6,7 +6,7 @@ export const TextField = (props) => {
|
|
|
6
6
|
const { id, name, defaultValue = "", hidden, type = "text", onChange, onKeyDown, disabled = false, readOnly = false, min, integer = false, stopChangeEvents, style, title, helpText, className, hint, required, } = props;
|
|
7
7
|
const [showTooltip, setShowTooltip] = useState(false);
|
|
8
8
|
const [value, setValue] = useState(defaultValue);
|
|
9
|
-
const { register: tempRegister, formState: { errors }, } = useFormContext() || { formState: {} }; // Obtener el contexto solo si existe
|
|
9
|
+
const { register: tempRegister, formState: { errors }, setValue: setOnFormValue, } = useFormContext() || { formState: {} }; // Obtener el contexto solo si existe
|
|
10
10
|
const error = errors ? errors[props.name ?? "-1"] : undefined;
|
|
11
11
|
const register = tempRegister
|
|
12
12
|
? tempRegister(props.name ?? "-1", {
|
|
@@ -20,9 +20,11 @@ export const TextField = (props) => {
|
|
|
20
20
|
const textColor = isReadOnly ? "text-gray-500" : `text-${color}-900`;
|
|
21
21
|
const borderColor = isReadOnly ? "border-gray-300" : `border-${color}-500`;
|
|
22
22
|
useEffect(() => {
|
|
23
|
+
setOnFormValue(name ?? "-1", defaultValue);
|
|
23
24
|
setValue(defaultValue);
|
|
24
25
|
}, [defaultValue]);
|
|
25
26
|
const handleInputChange = (event) => {
|
|
27
|
+
const newValue = event.target.value;
|
|
26
28
|
if (register) {
|
|
27
29
|
register.onChange(event);
|
|
28
30
|
}
|
|
@@ -30,18 +32,8 @@ export const TextField = (props) => {
|
|
|
30
32
|
event.stopPropagation();
|
|
31
33
|
event.preventDefault();
|
|
32
34
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const isInteger = /^[0-9]*$/.test(value);
|
|
36
|
-
if (isInteger || value === "") {
|
|
37
|
-
setValue(value);
|
|
38
|
-
onChange && onChange(value, event);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
else {
|
|
42
|
-
setValue(event.target.value);
|
|
43
|
-
onChange && onChange(event.target.value, event);
|
|
44
|
-
}
|
|
35
|
+
setValue(newValue);
|
|
36
|
+
onChange && onChange(newValue, event);
|
|
45
37
|
};
|
|
46
38
|
const handleKeyDown = (event) => {
|
|
47
39
|
if (integer && type === "number") {
|
|
@@ -60,9 +52,9 @@ export const TextField = (props) => {
|
|
|
60
52
|
}
|
|
61
53
|
};
|
|
62
54
|
if (hidden) {
|
|
63
|
-
return (_jsx("input", { type:
|
|
55
|
+
return (_jsx("input", { type: type, id: id ?? name, value: value, hidden: true, ...(register ?? {}), name: name, onChange: handleInputChange }));
|
|
64
56
|
}
|
|
65
|
-
const inputComponent = (_jsx("input", { type: type, readOnly:
|
|
57
|
+
const inputComponent = (_jsx("input", { type: type, readOnly: isReadOnly, disabled: disabled, id: id ?? name, autoComplete: "off", value: value, onWheel: (e) => {
|
|
66
58
|
e.currentTarget.blur();
|
|
67
59
|
}, step: type === "number" ? 0.01 : undefined, onKeyDown: (event) => {
|
|
68
60
|
handleKeyDown(event);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useGetEmployeeProfile, useGetSessionAttribute, } from "@zauru-sdk/hooks";
|
|
3
|
+
import { Link } from "@remix-run/react";
|
|
4
|
+
export const ValidateEmployeeAccess = ({ children, permissionVariableName, showIfNoPermission = false, }) => {
|
|
5
|
+
const { data: employee } = useGetEmployeeProfile();
|
|
6
|
+
const variable_string = useGetSessionAttribute(permissionVariableName, "sessionVariable");
|
|
7
|
+
const variable = variable_string?.split(",");
|
|
8
|
+
const hasPermission = variable?.includes(employee?.id?.toString() || "-1");
|
|
9
|
+
if (showIfNoPermission && !hasPermission) {
|
|
10
|
+
return (_jsxs("div", { className: "bg-gray-900 text-white min-h-screen flex flex-col items-center justify-center p-4", children: [_jsx("img", { src: "/logo.png", alt: "Zauru Logo", className: "mb-8 h-20" }), _jsx("h1", { className: "text-5xl font-extrabold text-red-500 mb-6", children: "\u00A1Acceso Denegado!" }), _jsx("div", { className: "w-full max-w-2xl", children: _jsx("p", { className: "text-2xl text-gray-300 mb-8 text-center", children: "Lo sentimos, no tienes permiso para acceder a esta p\u00E1gina." }) }), _jsx(Link, { to: "/", className: "bg-blue-600 text-white py-3 px-8 rounded-full text-lg font-semibold hover:bg-blue-700 transition duration-300 transform hover:scale-105", children: "Regresar al inicio" }), _jsx("div", { className: "mt-12 text-gray-500", children: _jsx("p", { children: "Si crees que esto es un error, por favor contacta a soporte." }) })] }));
|
|
11
|
+
}
|
|
12
|
+
return _jsx(_Fragment, { children: hasPermission ? children : null });
|
|
13
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { isRouteErrorResponse, Links, Meta, Scripts, useRouteError, Link, } from "@remix-run/react";
|
|
3
|
+
export const ErrorLayout = () => {
|
|
4
|
+
const error = useRouteError();
|
|
5
|
+
return (_jsxs("html", { lang: "es", className: "bg-gray-900 text-white", children: [_jsxs("head", { children: [_jsx("meta", { charSet: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: "\u00A1Ups! Algo sali\u00F3 mal" }), _jsx(Meta, {}), _jsx(Links, {})] }), _jsxs("body", { className: "min-h-screen flex flex-col items-center justify-center p-4", children: [_jsx("img", { src: "/logo.png", alt: "Zauru Logo", className: "mb-8 h-20" }), _jsx("h1", { className: "text-5xl font-extrabold text-red-500 mb-6", children: "\u00A1Ups!" }), _jsx("div", { className: "w-full max-w-2xl", children: _jsx("p", { className: "text-2xl text-gray-300 mb-8 text-center", children: isRouteErrorResponse(error)
|
|
6
|
+
? `Error ${error.status}: ${error.statusText}`
|
|
7
|
+
: error instanceof Error
|
|
8
|
+
? error.message
|
|
9
|
+
: "Ha ocurrido un error inesperado" }) }), _jsx(Link, { to: "/", className: "bg-blue-600 text-white py-3 px-8 rounded-full text-lg font-semibold hover:bg-blue-700 transition duration-300 transform hover:scale-105", children: "Regresar al inicio" }), _jsx("div", { className: "mt-12 text-gray-500", children: _jsx("p", { children: "Si el problema persiste, por favor contacta a soporte." }) }), _jsx(Scripts, {})] })] }));
|
|
10
|
+
};
|
package/dist/esm/index.js
CHANGED
package/dist/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zauru-sdk/components",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.113",
|
|
4
4
|
"description": "Componentes reutilizables en las WebApps de Zauru.",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@zauru-sdk/hooks": "^1.0.112",
|
|
39
39
|
"@zauru-sdk/icons": "^1.0.60",
|
|
40
40
|
"@zauru-sdk/types": "^1.0.109",
|
|
41
|
-
"@zauru-sdk/utils": "^1.0.
|
|
41
|
+
"@zauru-sdk/utils": "^1.0.113",
|
|
42
42
|
"framer-motion": "^11.0.8",
|
|
43
43
|
"jsonwebtoken": "^9.0.2",
|
|
44
44
|
"react": "^18.2.0",
|
|
@@ -50,5 +50,5 @@
|
|
|
50
50
|
"styled-components": "^5.3.5",
|
|
51
51
|
"zod": "^3.23.8"
|
|
52
52
|
},
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "32d6e9f7c23ac5b58be802d23f007f86b4aea904"
|
|
54
54
|
}
|
package/src/Buttons/Button.tsx
CHANGED
|
@@ -83,34 +83,35 @@ export const Button = (props: Props) => {
|
|
|
83
83
|
: "";
|
|
84
84
|
|
|
85
85
|
const buttonContent = (
|
|
86
|
-
|
|
87
|
-
type={
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
86
|
+
<>
|
|
87
|
+
<input type="hidden" name="action" value={name} />
|
|
88
|
+
<button
|
|
89
|
+
type={type}
|
|
90
|
+
disabled={
|
|
91
|
+
loading || disabled || (enableFormErrorsValidation && formHasErrors)
|
|
92
|
+
}
|
|
93
|
+
onClick={onClickSave}
|
|
94
|
+
className={`ml-2 ${
|
|
95
|
+
loading || disabled || (enableFormErrorsValidation && formHasErrors)
|
|
96
|
+
? " bg-opacity-25 "
|
|
97
|
+
: ""
|
|
98
|
+
} ${
|
|
99
|
+
loading
|
|
100
|
+
? " cursor-progress"
|
|
101
|
+
: `${
|
|
102
|
+
disabled || (enableFormErrorsValidation && formHasErrors)
|
|
103
|
+
? ""
|
|
104
|
+
: `hover:${color.bg700}`
|
|
105
|
+
}`
|
|
106
|
+
} inline-flex justify-center rounded-md border border-transparent ${
|
|
107
|
+
color.bg600
|
|
108
|
+
} py-2 px-4 text-sm font-medium text-white shadow-sm focus:outline-none focus:ring-2 focus:${
|
|
109
|
+
color.ring500
|
|
110
|
+
} focus:ring-offset-2 ${className}`}
|
|
111
|
+
>
|
|
112
|
+
{loading ? loadingText : inside}
|
|
113
|
+
</button>
|
|
114
|
+
</>
|
|
114
115
|
);
|
|
115
116
|
|
|
116
117
|
return (
|
|
@@ -46,8 +46,7 @@ export const ReactZodForm = (props: Props) => {
|
|
|
46
46
|
return (
|
|
47
47
|
<FormProvider {...methods}>
|
|
48
48
|
<Form
|
|
49
|
-
onSubmit={
|
|
50
|
-
//onSubmit={methods.handleSubmit(handleSubmit)}
|
|
49
|
+
onSubmit={methods.handleSubmit(handleSubmit)}
|
|
51
50
|
method={method}
|
|
52
51
|
id={id}
|
|
53
52
|
>
|
|
@@ -2,7 +2,7 @@ import { IdeaIconSVG } from "@zauru-sdk/icons";
|
|
|
2
2
|
import { SelectFieldOption } from "@zauru-sdk/types";
|
|
3
3
|
import React, { useEffect, useState, useRef, KeyboardEvent } from "react";
|
|
4
4
|
import { LoadingInputSkeleton } from "../../Skeletons/index.js";
|
|
5
|
-
import { useFormContext
|
|
5
|
+
import { useFormContext } from "react-hook-form";
|
|
6
6
|
|
|
7
7
|
type Props = {
|
|
8
8
|
id?: string;
|
|
@@ -45,7 +45,7 @@ export const SelectField = (props: Props) => {
|
|
|
45
45
|
loading = false,
|
|
46
46
|
className = "",
|
|
47
47
|
onInputChange,
|
|
48
|
-
required,
|
|
48
|
+
required = false,
|
|
49
49
|
} = props;
|
|
50
50
|
|
|
51
51
|
const [value, setValue] = useState<SelectFieldOption | null>(
|
|
@@ -64,11 +64,16 @@ export const SelectField = (props: Props) => {
|
|
|
64
64
|
const [isEnterPressed, setIsEnterPressed] = useState<boolean>(false);
|
|
65
65
|
const [isSearching, setIsSearching] = useState<boolean>(false);
|
|
66
66
|
const {
|
|
67
|
-
|
|
67
|
+
register: tempRegister,
|
|
68
68
|
formState: { errors },
|
|
69
69
|
setValue: setFormValue,
|
|
70
70
|
} = useFormContext() || { formState: {} };
|
|
71
71
|
const error = errors ? errors[props.name ?? "-1"] : undefined;
|
|
72
|
+
const register = tempRegister
|
|
73
|
+
? tempRegister(props.name ?? "-1", {
|
|
74
|
+
required,
|
|
75
|
+
})
|
|
76
|
+
: undefined; // Solo usar register si está disponible
|
|
72
77
|
|
|
73
78
|
const color = error ? "red" : "gray";
|
|
74
79
|
const isReadOnly = disabled || readOnly;
|
|
@@ -93,7 +98,7 @@ export const SelectField = (props: Props) => {
|
|
|
93
98
|
if (defaultValue) {
|
|
94
99
|
setValue(defaultValue);
|
|
95
100
|
setInputValue(defaultValue.label);
|
|
96
|
-
setFormValue(name || "", defaultValue);
|
|
101
|
+
setFormValue(name || "", defaultValue.value);
|
|
97
102
|
}
|
|
98
103
|
|
|
99
104
|
document.addEventListener("mousedown", handleClickOutside);
|
|
@@ -104,6 +109,9 @@ export const SelectField = (props: Props) => {
|
|
|
104
109
|
|
|
105
110
|
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
106
111
|
const newValue = e.target.value;
|
|
112
|
+
if (register) {
|
|
113
|
+
register.onChange(e);
|
|
114
|
+
}
|
|
107
115
|
setInputValue(newValue);
|
|
108
116
|
onInputChange && onInputChange(newValue);
|
|
109
117
|
setIsSearching(true);
|
|
@@ -121,12 +129,15 @@ export const SelectField = (props: Props) => {
|
|
|
121
129
|
: [...valueMulti, option];
|
|
122
130
|
setValueMulti(newValue);
|
|
123
131
|
onChangeMulti && onChangeMulti(newValue);
|
|
124
|
-
setFormValue(
|
|
132
|
+
setFormValue(
|
|
133
|
+
name || "",
|
|
134
|
+
newValue.map((v) => v.value)
|
|
135
|
+
);
|
|
125
136
|
} else {
|
|
126
137
|
setValue(option);
|
|
127
138
|
setInputValue(option.label);
|
|
128
139
|
onChange && onChange(option);
|
|
129
|
-
setFormValue(name || "", option);
|
|
140
|
+
setFormValue(name || "", option.value);
|
|
130
141
|
}
|
|
131
142
|
setIsOpen(false);
|
|
132
143
|
};
|
|
@@ -139,7 +150,7 @@ export const SelectField = (props: Props) => {
|
|
|
139
150
|
} else {
|
|
140
151
|
setValue(null);
|
|
141
152
|
onChange && onChange(null);
|
|
142
|
-
setFormValue(name || "",
|
|
153
|
+
setFormValue(name || "", "");
|
|
143
154
|
}
|
|
144
155
|
setInputValue("");
|
|
145
156
|
};
|
|
@@ -245,33 +256,30 @@ export const SelectField = (props: Props) => {
|
|
|
245
256
|
</label>
|
|
246
257
|
)}
|
|
247
258
|
<div className="relative">
|
|
248
|
-
<
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
autoComplete="off"
|
|
273
|
-
/>
|
|
274
|
-
)}
|
|
259
|
+
<input
|
|
260
|
+
type="text"
|
|
261
|
+
id={id}
|
|
262
|
+
value={inputValue}
|
|
263
|
+
onFocus={() => setIsOpen(true)}
|
|
264
|
+
onKeyDown={handleKeyDown}
|
|
265
|
+
readOnly={isReadOnly}
|
|
266
|
+
disabled={disabled}
|
|
267
|
+
className={`block w-full rounded-md ${bgColor} ${borderColor} ${textColor} shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm`}
|
|
268
|
+
placeholder={isMulti ? "Select options..." : "Select an option..."}
|
|
269
|
+
autoComplete="off"
|
|
270
|
+
onChange={handleInputChange}
|
|
271
|
+
onBlur={handleBlur}
|
|
272
|
+
required={required}
|
|
273
|
+
/>
|
|
274
|
+
<input
|
|
275
|
+
type="hidden"
|
|
276
|
+
{...(register ?? {})}
|
|
277
|
+
name={name}
|
|
278
|
+
value={
|
|
279
|
+
isMulti
|
|
280
|
+
? valueMulti.map((v) => v.value).join(",")
|
|
281
|
+
: value?.value || ""
|
|
282
|
+
}
|
|
275
283
|
/>
|
|
276
284
|
{isClearable && (value || valueMulti.length > 0) && (
|
|
277
285
|
<button
|
|
@@ -53,6 +53,7 @@ export const TextField = (props: Props) => {
|
|
|
53
53
|
const {
|
|
54
54
|
register: tempRegister,
|
|
55
55
|
formState: { errors },
|
|
56
|
+
setValue: setOnFormValue,
|
|
56
57
|
} = useFormContext() || { formState: {} }; // Obtener el contexto solo si existe
|
|
57
58
|
const error = errors ? errors[props.name ?? "-1"] : undefined;
|
|
58
59
|
const register = tempRegister
|
|
@@ -70,10 +71,13 @@ export const TextField = (props: Props) => {
|
|
|
70
71
|
const borderColor = isReadOnly ? "border-gray-300" : `border-${color}-500`;
|
|
71
72
|
|
|
72
73
|
useEffect(() => {
|
|
74
|
+
setOnFormValue(name ?? "-1", defaultValue);
|
|
73
75
|
setValue(defaultValue);
|
|
74
76
|
}, [defaultValue]);
|
|
75
77
|
|
|
76
78
|
const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
79
|
+
const newValue = event.target.value;
|
|
80
|
+
|
|
77
81
|
if (register) {
|
|
78
82
|
register.onChange(event);
|
|
79
83
|
}
|
|
@@ -81,17 +85,9 @@ export const TextField = (props: Props) => {
|
|
|
81
85
|
event.stopPropagation();
|
|
82
86
|
event.preventDefault();
|
|
83
87
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (isInteger || value === "") {
|
|
88
|
-
setValue(value);
|
|
89
|
-
onChange && onChange(value, event);
|
|
90
|
-
}
|
|
91
|
-
} else {
|
|
92
|
-
setValue(event.target.value);
|
|
93
|
-
onChange && onChange(event.target.value, event);
|
|
94
|
-
}
|
|
88
|
+
|
|
89
|
+
setValue(newValue);
|
|
90
|
+
onChange && onChange(newValue, event);
|
|
95
91
|
};
|
|
96
92
|
|
|
97
93
|
const handleKeyDown = (event: React.KeyboardEvent) => {
|
|
@@ -114,11 +110,10 @@ export const TextField = (props: Props) => {
|
|
|
114
110
|
if (hidden) {
|
|
115
111
|
return (
|
|
116
112
|
<input
|
|
117
|
-
type={
|
|
113
|
+
type={type}
|
|
118
114
|
id={id ?? name}
|
|
119
115
|
value={value}
|
|
120
|
-
|
|
121
|
-
hidden={true}
|
|
116
|
+
hidden
|
|
122
117
|
{...(register ?? {})}
|
|
123
118
|
name={name}
|
|
124
119
|
onChange={handleInputChange}
|
|
@@ -129,10 +124,10 @@ export const TextField = (props: Props) => {
|
|
|
129
124
|
const inputComponent = (
|
|
130
125
|
<input
|
|
131
126
|
type={type}
|
|
132
|
-
readOnly={
|
|
127
|
+
readOnly={isReadOnly}
|
|
133
128
|
disabled={disabled}
|
|
134
129
|
id={id ?? name}
|
|
135
|
-
autoComplete="
|
|
130
|
+
autoComplete="off"
|
|
136
131
|
value={value}
|
|
137
132
|
onWheel={(e: React.WheelEvent<HTMLInputElement>) => {
|
|
138
133
|
e.currentTarget.blur();
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useGetEmployeeProfile,
|
|
3
|
+
useGetSessionAttribute,
|
|
4
|
+
} from "@zauru-sdk/hooks";
|
|
5
|
+
import { Link } from "@remix-run/react";
|
|
6
|
+
|
|
7
|
+
export const ValidateEmployeeAccess = ({
|
|
8
|
+
children,
|
|
9
|
+
permissionVariableName,
|
|
10
|
+
showIfNoPermission = false,
|
|
11
|
+
}: {
|
|
12
|
+
children: React.ReactNode;
|
|
13
|
+
permissionVariableName: string;
|
|
14
|
+
showIfNoPermission?: boolean;
|
|
15
|
+
}) => {
|
|
16
|
+
const { data: employee } = useGetEmployeeProfile();
|
|
17
|
+
const variable_string = useGetSessionAttribute(
|
|
18
|
+
permissionVariableName,
|
|
19
|
+
"sessionVariable"
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const variable = variable_string?.split(",");
|
|
23
|
+
const hasPermission = variable?.includes(employee?.id?.toString() || "-1");
|
|
24
|
+
|
|
25
|
+
if (showIfNoPermission && !hasPermission) {
|
|
26
|
+
return (
|
|
27
|
+
<div className="bg-gray-900 text-white min-h-screen flex flex-col items-center justify-center p-4">
|
|
28
|
+
<img src="/logo.png" alt="Zauru Logo" className="mb-8 h-20" />
|
|
29
|
+
<h1 className="text-5xl font-extrabold text-red-500 mb-6">
|
|
30
|
+
¡Acceso Denegado!
|
|
31
|
+
</h1>
|
|
32
|
+
<div className="w-full max-w-2xl">
|
|
33
|
+
<p className="text-2xl text-gray-300 mb-8 text-center">
|
|
34
|
+
Lo sentimos, no tienes permiso para acceder a esta página.
|
|
35
|
+
</p>
|
|
36
|
+
</div>
|
|
37
|
+
<Link
|
|
38
|
+
to="/"
|
|
39
|
+
className="bg-blue-600 text-white py-3 px-8 rounded-full text-lg font-semibold hover:bg-blue-700 transition duration-300 transform hover:scale-105"
|
|
40
|
+
>
|
|
41
|
+
Regresar al inicio
|
|
42
|
+
</Link>
|
|
43
|
+
<div className="mt-12 text-gray-500">
|
|
44
|
+
<p>Si crees que esto es un error, por favor contacta a soporte.</p>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return <>{hasPermission ? children : null}</>;
|
|
51
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isRouteErrorResponse,
|
|
3
|
+
Links,
|
|
4
|
+
Meta,
|
|
5
|
+
Scripts,
|
|
6
|
+
useRouteError,
|
|
7
|
+
Link,
|
|
8
|
+
} from "@remix-run/react";
|
|
9
|
+
|
|
10
|
+
export const ErrorLayout = () => {
|
|
11
|
+
const error = useRouteError();
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<html lang="es" className="bg-gray-900 text-white">
|
|
15
|
+
<head>
|
|
16
|
+
<meta charSet="utf-8" />
|
|
17
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
18
|
+
<title>¡Ups! Algo salió mal</title>
|
|
19
|
+
<Meta />
|
|
20
|
+
<Links />
|
|
21
|
+
</head>
|
|
22
|
+
<body className="min-h-screen flex flex-col items-center justify-center p-4">
|
|
23
|
+
<img src="/logo.png" alt="Zauru Logo" className="mb-8 h-20" />
|
|
24
|
+
<h1 className="text-5xl font-extrabold text-red-500 mb-6">¡Ups!</h1>
|
|
25
|
+
<div className="w-full max-w-2xl">
|
|
26
|
+
<p className="text-2xl text-gray-300 mb-8 text-center">
|
|
27
|
+
{isRouteErrorResponse(error)
|
|
28
|
+
? `Error ${error.status}: ${error.statusText}`
|
|
29
|
+
: error instanceof Error
|
|
30
|
+
? error.message
|
|
31
|
+
: "Ha ocurrido un error inesperado"}
|
|
32
|
+
</p>
|
|
33
|
+
</div>
|
|
34
|
+
<Link
|
|
35
|
+
to="/"
|
|
36
|
+
className="bg-blue-600 text-white py-3 px-8 rounded-full text-lg font-semibold hover:bg-blue-700 transition duration-300 transform hover:scale-105"
|
|
37
|
+
>
|
|
38
|
+
Regresar al inicio
|
|
39
|
+
</Link>
|
|
40
|
+
<div className="mt-12 text-gray-500">
|
|
41
|
+
<p>Si el problema persiste, por favor contacta a soporte.</p>
|
|
42
|
+
</div>
|
|
43
|
+
<Scripts />
|
|
44
|
+
</body>
|
|
45
|
+
</html>
|
|
46
|
+
);
|
|
47
|
+
};
|
package/src/Layouts/index.ts
CHANGED
package/src/index.ts
CHANGED