flysoft-react-ui 0.5.2 → 1.0.0
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/dist/App.d.ts.map +1 -1
- package/dist/App.js +5 -6
- package/dist/components/form-controls/AutocompleteInput.d.ts.map +1 -1
- package/dist/components/form-controls/AutocompleteInput.js +177 -131
- package/dist/components/form-controls/Button.d.ts +3 -0
- package/dist/components/form-controls/Button.d.ts.map +1 -1
- package/dist/components/form-controls/Button.js +160 -19
- package/dist/components/form-controls/Checkbox.d.ts.map +1 -1
- package/dist/components/form-controls/Checkbox.js +3 -1
- package/dist/components/form-controls/DateInput.d.ts +5 -1
- package/dist/components/form-controls/DateInput.d.ts.map +1 -1
- package/dist/components/form-controls/DateInput.js +94 -27
- package/dist/components/form-controls/Input.d.ts.map +1 -1
- package/dist/components/form-controls/Input.js +2 -1
- package/dist/components/form-controls/LinkButton.d.ts +15 -0
- package/dist/components/form-controls/LinkButton.d.ts.map +1 -0
- package/dist/components/form-controls/LinkButton.js +248 -0
- package/dist/components/form-controls/SearchSelectInput-OLD.d.ts.map +1 -1
- package/dist/components/form-controls/SearchSelectInput-OLD.js +5 -4
- package/dist/components/form-controls/SearchSelectInput.d.ts.map +1 -1
- package/dist/components/form-controls/SearchSelectInput.js +3 -2
- package/dist/components/form-controls/index.d.ts +2 -0
- package/dist/components/form-controls/index.d.ts.map +1 -1
- package/dist/components/form-controls/index.js +1 -0
- package/dist/components/layout/Accordion.d.ts +13 -0
- package/dist/components/layout/Accordion.d.ts.map +1 -0
- package/dist/components/layout/Accordion.js +67 -0
- package/dist/components/layout/AppLayout.d.ts.map +1 -1
- package/dist/components/layout/AppLayout.js +7 -7
- package/dist/components/layout/Card.d.ts +8 -3
- package/dist/components/layout/Card.d.ts.map +1 -1
- package/dist/components/layout/Card.js +21 -22
- package/dist/components/layout/DataTable.js +1 -1
- package/dist/components/layout/DropdownMenu.d.ts.map +1 -0
- package/dist/components/{utils → layout}/DropdownMenu.js +12 -6
- package/dist/components/layout/DropdownPanel.d.ts +7 -0
- package/dist/components/layout/DropdownPanel.d.ts.map +1 -0
- package/dist/components/layout/DropdownPanel.js +137 -0
- package/dist/components/{utils → layout}/Filter.d.ts +5 -0
- package/dist/components/layout/Filter.d.ts.map +1 -0
- package/dist/components/{utils → layout}/Filter.js +18 -9
- package/dist/components/layout/Menu.d.ts +31 -0
- package/dist/components/layout/Menu.d.ts.map +1 -0
- package/dist/components/layout/Menu.js +21 -0
- package/dist/components/layout/index.d.ts +10 -0
- package/dist/components/layout/index.d.ts.map +1 -1
- package/dist/components/layout/index.js +5 -0
- package/dist/components/utils/Badge.d.ts.map +1 -1
- package/dist/components/utils/Badge.js +3 -2
- package/dist/components/utils/Dialog.d.ts +2 -2
- package/dist/components/utils/Dialog.d.ts.map +1 -1
- package/dist/components/utils/Dialog.js +4 -3
- package/dist/components/utils/FiltersDialog.d.ts +1 -1
- package/dist/components/utils/FiltersDialog.d.ts.map +1 -1
- package/dist/components/utils/FiltersDialog.js +2 -2
- package/dist/components/utils/Loader.js +1 -1
- package/dist/components/utils/RoadMap.d.ts.map +1 -1
- package/dist/components/utils/RoadMap.js +2 -1
- package/dist/components/utils/Snackbar.d.ts.map +1 -1
- package/dist/components/utils/Snackbar.js +2 -1
- package/dist/components/utils/iconUtils.d.ts +16 -0
- package/dist/components/utils/iconUtils.d.ts.map +1 -0
- package/dist/components/utils/iconUtils.js +40 -0
- package/dist/components/utils/index.d.ts +0 -2
- package/dist/components/utils/index.d.ts.map +1 -1
- package/dist/components/utils/index.js +0 -1
- package/dist/contexts/CrudContext.d.ts +62 -0
- package/dist/contexts/CrudContext.d.ts.map +1 -0
- package/dist/contexts/CrudContext.js +333 -0
- package/dist/contexts/index.d.ts +2 -2
- package/dist/contexts/index.d.ts.map +1 -1
- package/dist/contexts/index.js +2 -2
- package/dist/docs/AccordionDocs.d.ts +4 -0
- package/dist/docs/AccordionDocs.d.ts.map +1 -0
- package/dist/docs/AccordionDocs.js +21 -0
- package/dist/docs/AuthDocs.tsx/AuthDocsContent.js +3 -5
- package/dist/docs/AutocompleteInputDocs.js +1 -1
- package/dist/docs/ButtonDocs.d.ts.map +1 -1
- package/dist/docs/ButtonDocs.js +1 -1
- package/dist/docs/CardDocs.d.ts.map +1 -1
- package/dist/docs/CardDocs.js +17 -8
- package/dist/docs/DataTableDocs.js +3 -3
- package/dist/docs/DialogDocs.d.ts.map +1 -1
- package/dist/docs/DialogDocs.js +1 -1
- package/dist/docs/DocAdmin.js +1 -1
- package/dist/docs/DocsMenu.d.ts.map +1 -1
- package/dist/docs/DocsMenu.js +3 -3
- package/dist/docs/DocsRouter.d.ts.map +1 -1
- package/dist/docs/DocsRouter.js +5 -1
- package/dist/docs/DropdownMenuDocs.js +1 -1
- package/dist/docs/DropdownPanelDocs.d.ts +4 -0
- package/dist/docs/DropdownPanelDocs.d.ts.map +1 -0
- package/dist/docs/DropdownPanelDocs.js +7 -0
- package/dist/docs/FilterDocs.d.ts.map +1 -1
- package/dist/docs/FilterDocs.js +19 -1
- package/dist/docs/LinkButtonDocs.d.ts +4 -0
- package/dist/docs/LinkButtonDocs.d.ts.map +1 -0
- package/dist/docs/LinkButtonDocs.js +7 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.d.ts +0 -9
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.d.ts.map +1 -1
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocs.js +32 -16
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.d.ts +2 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.d.ts.map +1 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaPersonas.js +34 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.d.ts +2 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.d.ts.map +1 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresaSingle.js +66 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresas.d.ts +2 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresas.d.ts.map +1 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresas.js +7 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.d.ts +10 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.d.ts.map +1 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentEmpresasPersonasEditDialog.js +39 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.d.ts.map +1 -1
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsContentPersonas.js +33 -27
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsEditDialog.d.ts +9 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsEditDialog.d.ts.map +1 -0
- package/dist/docs/ListCrudDocs.tsx/ListCrudDocsEditDialog.js +30 -0
- package/dist/docs/MenuDocs.d.ts +4 -0
- package/dist/docs/MenuDocs.d.ts.map +1 -0
- package/dist/docs/MenuDocs.js +26 -0
- package/dist/docs/SearchSelectInputDocs.js +1 -1
- package/dist/docs/docMockServices/empresaService.d.ts +5 -5
- package/dist/docs/docMockServices/empresaService.d.ts.map +1 -1
- package/dist/docs/docMockServices/empresaService.js +20 -11
- package/dist/docs/docMockServices/interfaces.d.ts +12 -0
- package/dist/docs/docMockServices/interfaces.d.ts.map +1 -1
- package/dist/docs/docMockServices/personaEmpresaService.d.ts +6 -6
- package/dist/docs/docMockServices/personaEmpresaService.d.ts.map +1 -1
- package/dist/docs/docMockServices/personaEmpresaService.js +52 -14
- package/dist/docs/docMockServices/personaService.d.ts +2 -2
- package/dist/docs/docMockServices/personaService.d.ts.map +1 -1
- package/dist/docs/docMockServices/personaService.js +17 -7
- package/dist/index.css +1 -1
- package/dist/index.d.ts +12 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/templates/forms/ContactForm.js +2 -2
- package/dist/templates/forms/LoginForm.js +1 -1
- package/dist/templates/forms/RegistrationForm.js +1 -1
- package/dist/templates/layouts/SidebarLayout.d.ts.map +1 -1
- package/dist/templates/layouts/SidebarLayout.js +3 -2
- package/dist/templates/patterns/FormPattern.d.ts.map +1 -1
- package/dist/templates/patterns/FormPattern.js +4 -3
- package/package.json +4 -3
- package/dist/components/utils/DropdownMenu.d.ts.map +0 -1
- package/dist/components/utils/Filter.d.ts.map +0 -1
- package/dist/contexts/ListCrudContext.d.ts +0 -29
- package/dist/contexts/ListCrudContext.d.ts.map +0 -1
- package/dist/contexts/ListCrudContext.js +0 -209
- /package/dist/components/{utils → layout}/DropdownMenu.d.ts +0 -0
|
@@ -44,9 +44,9 @@ export const ContactForm = ({ onSubmit, loading = false, success = false, error,
|
|
|
44
44
|
}
|
|
45
45
|
};
|
|
46
46
|
if (success) {
|
|
47
|
-
return (_jsx(Card, { title: "Mensaje Enviado", subtitle: "Gracias por contactarnos", className: className, children: _jsxs("div", { className: "text-center py-8", children: [_jsx("div", { className: "w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4", children: _jsx("i", { className: "
|
|
47
|
+
return (_jsx(Card, { title: "Mensaje Enviado", subtitle: "Gracias por contactarnos", className: className, children: _jsxs("div", { className: "text-center py-8", children: [_jsx("div", { className: "w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4", children: _jsx("i", { className: "fal fa-check text-green-600 text-2xl" }) }), _jsx("h3", { className: "text-lg font-semibold text-gray-900 mb-2", children: "\u00A1Mensaje enviado con \u00E9xito!" }), _jsx("p", { className: "text-gray-600 mb-4", children: "Hemos recibido tu mensaje y te responderemos pronto." }), _jsx(Button, { variant: "outline", onClick: () => window.location.reload(), icon: "fa-refresh", children: "Enviar otro mensaje" })] }) }));
|
|
48
48
|
}
|
|
49
|
-
return (_jsx(Card, { title: "Cont\u00E1ctanos", subtitle: "Env\u00EDanos un mensaje y te responderemos pronto", className: className, children: _jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [error && (_jsx("div", { className: "p-3 bg-red-50 border border-red-200 rounded-lg", children: _jsxs("p", { className: "text-sm text-red-600", children: [_jsx("i", { className: "
|
|
49
|
+
return (_jsx(Card, { title: "Cont\u00E1ctanos", subtitle: "Env\u00EDanos un mensaje y te responderemos pronto", className: className, children: _jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [error && (_jsx("div", { className: "p-3 bg-red-50 border border-red-200 rounded-lg", children: _jsxs("p", { className: "text-sm text-red-600", children: [_jsx("i", { className: "fal fa-exclamation-triangle mr-2" }), error] }) })), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [_jsx(Input, { label: "Nombre Completo", placeholder: "Tu nombre completo", icon: "fa-user", value: formData.name, onChange: handleChange("name"), error: errors.name, disabled: loading }), _jsx(Input, { label: "Email", type: "email", placeholder: "tu@email.com", icon: "fa-envelope", value: formData.email, onChange: handleChange("email"), error: errors.email, disabled: loading })] }), _jsx(Input, { label: "Asunto", placeholder: "\u00BFEn qu\u00E9 podemos ayudarte?", icon: "fa-tag", value: formData.subject, onChange: handleChange("subject"), error: errors.subject, disabled: loading }), _jsxs("div", { className: "w-full", children: [_jsx("label", { className: "block text-sm font-medium text-[var(--color-text-primary)] mb-1 font-[var(--font-default)]", children: "Mensaje" }), _jsxs("div", { className: "relative", children: [_jsx("i", { className: "fal fa-comment text-[var(--color-text-muted)] absolute top-3 left-3 w-5 h-5" }), _jsx("textarea", { placeholder: "Escribe tu mensaje aqu\u00ED...", className: `
|
|
50
50
|
w-full border rounded-lg transition-colors focus:outline-none focus:ring-2
|
|
51
51
|
disabled:opacity-50 disabled:cursor-not-allowed
|
|
52
52
|
font-[var(--font-default)] text-[var(--color-text-primary)]
|
|
@@ -32,5 +32,5 @@ export const LoginForm = ({ onSubmit, loading = false, error, className = "", })
|
|
|
32
32
|
setErrors((prev) => ({ ...prev, [field]: undefined }));
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
|
-
return (_jsxs(Card, { title: "Iniciar Sesi\u00F3n", subtitle: "Ingresa tus credenciales para acceder", className: className, children: [_jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [error && (_jsx("div", { className: "p-3 bg-red-50 border border-red-200 rounded-lg", children: _jsxs("p", { className: "text-sm text-red-600", children: [_jsx("i", { className: "
|
|
35
|
+
return (_jsxs(Card, { title: "Iniciar Sesi\u00F3n", subtitle: "Ingresa tus credenciales para acceder", className: className, children: [_jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [error && (_jsx("div", { className: "p-3 bg-red-50 border border-red-200 rounded-lg", children: _jsxs("p", { className: "text-sm text-red-600", children: [_jsx("i", { className: "fal fa-exclamation-triangle mr-2" }), error] }) })), _jsx(Input, { label: "Email", type: "email", placeholder: "tu@email.com", icon: "fa-envelope", value: formData.email, onChange: handleChange("email"), error: errors.email, disabled: loading }), _jsx(Input, { label: "Contrase\u00F1a", type: "password", placeholder: "Tu contrase\u00F1a", icon: "fa-lock", value: formData.password, onChange: handleChange("password"), error: errors.password, disabled: loading }), _jsx(Button, { type: "submit", variant: "primary", size: "lg", icon: "fa-sign-in-alt", loading: loading, className: "w-full", children: "Iniciar Sesi\u00F3n" })] }), _jsx("div", { className: "mt-4 text-center", children: _jsxs("p", { className: "text-sm text-gray-600", children: ["\u00BFNo tienes cuenta?", " ", _jsx("a", { href: "#", className: "text-blue-600 hover:text-blue-800 font-medium", children: "Reg\u00EDstrate aqu\u00ED" })] }) })] }));
|
|
36
36
|
};
|
|
@@ -50,5 +50,5 @@ export const RegistrationForm = ({ onSubmit, loading = false, error, className =
|
|
|
50
50
|
setErrors((prev) => ({ ...prev, [field]: undefined }));
|
|
51
51
|
}
|
|
52
52
|
};
|
|
53
|
-
return (_jsxs(Card, { title: "Crear Cuenta", subtitle: "Completa los datos para registrarte", className: className, children: [_jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [error && (_jsx("div", { className: "p-3 bg-red-50 border border-red-200 rounded-lg", children: _jsxs("p", { className: "text-sm text-red-600", children: [_jsx("i", { className: "
|
|
53
|
+
return (_jsxs(Card, { title: "Crear Cuenta", subtitle: "Completa los datos para registrarte", className: className, children: [_jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [error && (_jsx("div", { className: "p-3 bg-red-50 border border-red-200 rounded-lg", children: _jsxs("p", { className: "text-sm text-red-600", children: [_jsx("i", { className: "fal fa-exclamation-triangle mr-2" }), error] }) })), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [_jsx(Input, { label: "Nombre", placeholder: "Tu nombre", icon: "fa-user", value: formData.firstName, onChange: handleChange("firstName"), error: errors.firstName, disabled: loading }), _jsx(Input, { label: "Apellido", placeholder: "Tu apellido", icon: "fa-user", value: formData.lastName, onChange: handleChange("lastName"), error: errors.lastName, disabled: loading })] }), _jsx(Input, { label: "Email", type: "email", placeholder: "tu@email.com", icon: "fa-envelope", value: formData.email, onChange: handleChange("email"), error: errors.email, disabled: loading }), _jsx(Input, { label: "Contrase\u00F1a", type: "password", placeholder: "M\u00EDnimo 6 caracteres", icon: "fa-lock", value: formData.password, onChange: handleChange("password"), error: errors.password, disabled: loading }), _jsx(Input, { label: "Confirmar Contrase\u00F1a", type: "password", placeholder: "Repite tu contrase\u00F1a", icon: "fa-lock", value: formData.confirmPassword, onChange: handleChange("confirmPassword"), error: errors.confirmPassword, disabled: loading }), _jsx(Button, { type: "submit", variant: "primary", size: "lg", icon: "fa-user-plus", loading: loading, className: "w-full", children: "Crear Cuenta" })] }), _jsx("div", { className: "mt-4 text-center", children: _jsxs("p", { className: "text-sm text-gray-600", children: ["\u00BFYa tienes cuenta?", " ", _jsx("a", { href: "#", className: "text-blue-600 hover:text-blue-800 font-medium", children: "Inicia sesi\u00F3n aqu\u00ED" })] }) })] }));
|
|
54
54
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SidebarLayout.d.ts","sourceRoot":"","sources":["../../../src/templates/layouts/SidebarLayout.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"SidebarLayout.d.ts","sourceRoot":"","sources":["../../../src/templates/layouts/SidebarLayout.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAIxC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAwItD,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import React, { useState } from "react";
|
|
3
3
|
import { Button, Badge } from "../../index";
|
|
4
|
+
import { normalizeIconClass } from "../../components/utils/iconUtils";
|
|
4
5
|
export const SidebarLayout = ({ title, menuItems, user, children, className = "", onLogout, }) => {
|
|
5
6
|
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
6
7
|
const [activeItem, setActiveItem] = useState(menuItems[0]?.href || "");
|
|
@@ -15,7 +16,7 @@ export const SidebarLayout = ({ title, menuItems, user, children, className = ""
|
|
|
15
16
|
fixed inset-y-0 left-0 z-50 w-64 bg-white shadow-lg transform transition-transform duration-300 ease-in-out
|
|
16
17
|
${sidebarOpen ? "translate-x-0" : "-translate-x-full"}
|
|
17
18
|
lg:translate-x-0 lg:static lg:inset-0
|
|
18
|
-
`, children: [_jsxs("div", { className: "flex items-center justify-between h-16 px-6 border-b", children: [_jsx("h1", { className: "text-xl font-bold text-gray-900", children: title }), _jsx("button", { onClick: toggleSidebar, className: "lg:hidden p-2 rounded-md text-gray-400 hover:text-gray-600", children: _jsx("i", { className: "
|
|
19
|
+
`, children: [_jsxs("div", { className: "flex items-center justify-between h-16 px-6 border-b", children: [_jsx("h1", { className: "text-xl font-bold text-gray-900", children: title }), _jsx("button", { onClick: toggleSidebar, className: "lg:hidden p-2 rounded-md text-gray-400 hover:text-gray-600", children: _jsx("i", { className: "fal fa-times" }) })] }), _jsx("nav", { className: "mt-6 px-3", children: _jsx("div", { className: "space-y-1", children: menuItems.map((item) => (_jsxs("a", { href: item.href, onClick: (e) => {
|
|
19
20
|
e.preventDefault();
|
|
20
21
|
handleMenuClick(item.href);
|
|
21
22
|
}, className: `
|
|
@@ -23,5 +24,5 @@ export const SidebarLayout = ({ title, menuItems, user, children, className = ""
|
|
|
23
24
|
${activeItem === item.href
|
|
24
25
|
? "bg-blue-100 text-blue-700"
|
|
25
26
|
: "text-gray-600 hover:bg-gray-50 hover:text-gray-900"}
|
|
26
|
-
`, children: [_jsx("i", { className:
|
|
27
|
+
`, children: [_jsx("i", { className: `${normalizeIconClass(item.icon)} mr-3 flex-shrink-0` }), _jsx("span", { className: "flex-1", children: item.label }), item.badge && (_jsx(Badge, { variant: "primary", size: "sm", className: "ml-2", children: item.badge }))] }, item.href))) }) }), _jsx("div", { className: "absolute bottom-0 left-0 right-0 p-4 border-t", children: _jsxs("div", { className: "flex items-center", children: [_jsx("div", { className: "flex-shrink-0", children: _jsx("div", { className: "w-8 h-8 bg-gray-300 rounded-full flex items-center justify-center", children: _jsx("i", { className: `${normalizeIconClass(user.avatar || "fa-user")} text-gray-600` }) }) }), _jsxs("div", { className: "ml-3 flex-1", children: [_jsx("p", { className: "text-sm font-medium text-gray-900", children: user.name }), user.email && (_jsx("p", { className: "text-xs text-gray-500", children: user.email }))] }), onLogout && (_jsx("button", { onClick: onLogout, className: "ml-2 p-1 text-gray-400 hover:text-gray-600", title: "Cerrar sesi\u00F3n", children: _jsx("i", { className: "fal fa-sign-out-alt" }) }))] }) })] }), _jsxs("div", { className: "lg:pl-64", children: [_jsx("div", { className: "sticky top-0 z-10 bg-white shadow-sm border-b", children: _jsxs("div", { className: "flex items-center justify-between h-16 px-4 sm:px-6 lg:px-8", children: [_jsx("button", { onClick: toggleSidebar, className: "lg:hidden p-2 rounded-md text-gray-400 hover:text-gray-600", children: _jsx("i", { className: "fal fa-bars" }) }), _jsxs("div", { className: "flex items-center space-x-4", children: [_jsx(Button, { variant: "ghost", size: "sm", icon: "fa-bell", children: "Notificaciones" }), _jsx(Button, { variant: "ghost", size: "sm", icon: "fa-cog", children: "Configuraci\u00F3n" })] })] }) }), _jsx("main", { className: "p-4 sm:p-6 lg:p-8", children: children })] })] }));
|
|
27
28
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormPattern.d.ts","sourceRoot":"","sources":["../../../src/templates/patterns/FormPattern.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"FormPattern.d.ts","sourceRoot":"","sources":["../../../src/templates/patterns/FormPattern.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAIxC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACnD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;CAClB;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAkLlD,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import React, { useState } from "react";
|
|
3
3
|
import { Button, Input, Card } from "../../index";
|
|
4
|
+
import { normalizeIconClass } from "../../components/utils/iconUtils";
|
|
4
5
|
export const FormPattern = ({ title, subtitle, fields, onSubmit, submitText = "Enviar", submitIcon = "fa-paper-plane", loading = false, error, success = false, className = "", gridCols = 1, }) => {
|
|
5
6
|
const [formData, setFormData] = useState(fields.reduce((acc, field) => ({ ...acc, [field.name]: "" }), {}));
|
|
6
7
|
const [errors, setErrors] = useState({});
|
|
@@ -47,7 +48,7 @@ export const FormPattern = ({ title, subtitle, fields, onSubmit, submitText = "E
|
|
|
47
48
|
disabled: loading,
|
|
48
49
|
};
|
|
49
50
|
if (field.multiline) {
|
|
50
|
-
return (_jsxs("div", { className: "w-full", children: [_jsxs("label", { className: "block text-sm font-medium text-[var(--color-text-primary)] mb-1 font-[var(--font-default)]", children: [field.label, field.required && _jsx("span", { className: "text-red-500 ml-1", children: "*" })] }), _jsxs("div", { className: "relative", children: [field.icon && (_jsx("i", { className:
|
|
51
|
+
return (_jsxs("div", { className: "w-full", children: [_jsxs("label", { className: "block text-sm font-medium text-[var(--color-text-primary)] mb-1 font-[var(--font-default)]", children: [field.label, field.required && _jsx("span", { className: "text-red-500 ml-1", children: "*" })] }), _jsxs("div", { className: "relative", children: [field.icon && (_jsx("i", { className: `${normalizeIconClass(field.icon)} text-[var(--color-text-muted)] absolute top-3 left-3 w-5 h-5` })), _jsx("textarea", { placeholder: field.placeholder, className: `
|
|
51
52
|
w-full border rounded-lg transition-colors focus:outline-none focus:ring-2
|
|
52
53
|
disabled:opacity-50 disabled:cursor-not-allowed
|
|
53
54
|
font-[var(--font-default)] text-[var(--color-text-primary)]
|
|
@@ -61,7 +62,7 @@ export const FormPattern = ({ title, subtitle, fields, onSubmit, submitText = "E
|
|
|
61
62
|
return (_jsx(Input, { type: field.type || "text", ...commonProps }, field.name));
|
|
62
63
|
};
|
|
63
64
|
if (success) {
|
|
64
|
-
return (_jsx(Card, { title: "\u00A1\u00C9xito!", subtitle: "La operaci\u00F3n se complet\u00F3 correctamente", className: className, children: _jsxs("div", { className: "text-center py-8", children: [_jsx("div", { className: "w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4", children: _jsx("i", { className: "
|
|
65
|
+
return (_jsx(Card, { title: "\u00A1\u00C9xito!", subtitle: "La operaci\u00F3n se complet\u00F3 correctamente", className: className, children: _jsxs("div", { className: "text-center py-8", children: [_jsx("div", { className: "w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4", children: _jsx("i", { className: "fal fa-check text-green-600 text-2xl" }) }), _jsx("h3", { className: "text-lg font-semibold text-gray-900 mb-2", children: "\u00A1Operaci\u00F3n exitosa!" }), _jsx("p", { className: "text-gray-600 mb-4", children: "Los datos se han procesado correctamente." }), _jsx(Button, { variant: "outline", onClick: () => window.location.reload(), icon: "fa-refresh", children: "Continuar" })] }) }));
|
|
65
66
|
}
|
|
66
|
-
return (_jsx(Card, { title: title, subtitle: subtitle, className: className, children: _jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [error && (_jsx("div", { className: "p-3 bg-red-50 border border-red-200 rounded-lg", children: _jsxs("p", { className: "text-sm text-red-600", children: [_jsx("i", { className: "
|
|
67
|
+
return (_jsx(Card, { title: title, subtitle: subtitle, className: className, children: _jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [error && (_jsx("div", { className: "p-3 bg-red-50 border border-red-200 rounded-lg", children: _jsxs("p", { className: "text-sm text-red-600", children: [_jsx("i", { className: "fal fa-exclamation-triangle mr-2" }), error] }) })), _jsx("div", { className: `grid grid-cols-1 ${gridCols === 2 ? "md:grid-cols-2" : ""} gap-4`, children: fields.map(renderField) }), _jsx(Button, { type: "submit", variant: "primary", size: "lg", icon: submitIcon, loading: loading, className: "w-full", children: submitText })] }) }));
|
|
67
68
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flysoft-react-ui",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "1.0.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "A modern React UI component library with Tailwind CSS, TypeScript, and FontAwesome 5. Includes forms, layouts, themes, and templates for rapid development.",
|
|
7
7
|
"keywords": [
|
|
@@ -63,13 +63,14 @@
|
|
|
63
63
|
"docs:validate": "npm run validate-docs"
|
|
64
64
|
},
|
|
65
65
|
"peerDependencies": {
|
|
66
|
+
"dayjs": "^1.11.0",
|
|
66
67
|
"react": "^18.0.0 || ^19.0.0",
|
|
67
|
-
"react-dom": "^18.0.0 || ^19.0.0"
|
|
68
|
-
"dayjs": "^1.11.0"
|
|
68
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
69
69
|
},
|
|
70
70
|
"dependencies": {
|
|
71
71
|
"@tailwindcss/vite": "^4.1.12",
|
|
72
72
|
"axios": "^1.13.2",
|
|
73
|
+
"tailwind-merge": "^3.4.0",
|
|
73
74
|
"tailwindcss": "^4.1.12"
|
|
74
75
|
},
|
|
75
76
|
"devDependencies": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DropdownMenu.d.ts","sourceRoot":"","sources":["../../../src/components/utils/DropdownMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AAGf,MAAM,WAAW,iBAAiB,CAAC,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE;IACtD,OAAO,EAAE,CAAC,EAAE,CAAC;IACb,gBAAgB,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IACpC,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IACrC;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC5C;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,eAAO,MAAM,YAAY,GAAI,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,EAAG,iGAOlD,iBAAiB,CAAC,CAAC,CAAC,4CAiNtB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Filter.d.ts","sourceRoot":"","sources":["../../../src/components/utils/Filter.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAQ3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAE7E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAGvE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAGD,UAAU,eAAe;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC/C;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAGD,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACxD,UAAU,EAAE,QAAQ,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB,CAAC,CAAC,GAAG,kBAAkB,EAAE,CAAC,GAAG,MAAM,CACzE,SAAQ,eAAe;IACvB,UAAU,EAAE,cAAc,CAAC;IAC3B,OAAO,EAAE,CAAC,EAAE,CAAC;IACb,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IACrC,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC;IAChC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC5C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACxD,UAAU,EAAE,QAAQ,CAAC;CACtB;AAED,MAAM,WAAW,uBAAuB,CAAC,CAAC,GAAG,kBAAkB,EAAE,CAAC,GAAG,MAAM,CACzE,SAAQ,eAAe;IACvB,UAAU,EAAE,cAAc,CAAC;IAC3B,iBAAiB,EAAE,CACjB,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,uBAAuB,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC9D,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IACrC,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC;IAChC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAGD,MAAM,MAAM,WAAW,GACnB,eAAe,GACf,iBAAiB,GACjB,eAAe,GACf,uBAAuB,GACvB,iBAAiB,GACjB,uBAAuB,CAAC;AAE5B,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAu8BxC,CAAC"}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { type ReactNode } from "react";
|
|
2
|
-
import { type PaginationInterface } from "../components/form-controls/Pagination";
|
|
3
|
-
export interface ListCrudContextType<T> {
|
|
4
|
-
list: Array<T> | undefined;
|
|
5
|
-
page: number;
|
|
6
|
-
pages: number;
|
|
7
|
-
total: number;
|
|
8
|
-
limit: number;
|
|
9
|
-
isLoading: boolean;
|
|
10
|
-
pagination: ReactNode;
|
|
11
|
-
params: Record<string, any>;
|
|
12
|
-
refetch: (params?: Record<string, any>) => Promise<void>;
|
|
13
|
-
createItem: (item: T) => Promise<T | undefined>;
|
|
14
|
-
deleteItem: (item: T) => Promise<void>;
|
|
15
|
-
}
|
|
16
|
-
export declare const ListCrudContext: import("react").Context<ListCrudContextType<any> | undefined>;
|
|
17
|
-
interface ListCrudProviderProps<T> {
|
|
18
|
-
children: ReactNode;
|
|
19
|
-
getPromise: (params?: Record<string, any>) => Promise<Array<T> | PaginationInterface<T> | undefined>;
|
|
20
|
-
postPromise?: (item: T) => Promise<T | undefined>;
|
|
21
|
-
deletePromise?: (item: T) => Promise<void>;
|
|
22
|
-
urlParams?: Array<string>;
|
|
23
|
-
limit?: number;
|
|
24
|
-
pageParam?: string;
|
|
25
|
-
}
|
|
26
|
-
export declare function ListCrudProvider<T>({ children, getPromise, postPromise, deletePromise, limit, pageParam, urlParams, }: ListCrudProviderProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
27
|
-
export declare function useListCrud<T>(): ListCrudContextType<T>;
|
|
28
|
-
export {};
|
|
29
|
-
//# sourceMappingURL=ListCrudContext.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ListCrudContext.d.ts","sourceRoot":"","sources":["../../src/contexts/ListCrudContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,wCAAwC,CAAC;AAGhD,MAAM,WAAW,mBAAmB,CAAC,CAAC;IACpC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,SAAS,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAChD,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAQD,eAAO,MAAM,eAAe,+DAA+B,CAAC;AAE5D,UAAU,qBAAqB,CAAC,CAAC;IAC/B,QAAQ,EAAE,SAAS,CAAC;IACpB,UAAU,EAAE,CACV,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KACzB,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC5D,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAClD,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,SAAS,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,EAClC,QAAQ,EACR,UAAU,EACV,WAAW,EACX,aAAa,EACb,KAAU,EACV,SAAoB,EACpB,SAAc,GACf,EAAE,qBAAqB,CAAC,CAAC,CAAC,2CAwP1B;AAID,wBAAgB,WAAW,CAAC,CAAC,KAAK,mBAAmB,CAAC,CAAC,CAAC,CAMvD"}
|
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { createContext, useContext, useEffect, useMemo, useRef, useState, useCallback, } from "react";
|
|
3
|
-
import { useSearchParams } from "react-router-dom";
|
|
4
|
-
import { Pagination, } from "../components/form-controls/Pagination";
|
|
5
|
-
import { useAsyncRequest } from "../hooks/useAsyncRequest";
|
|
6
|
-
const createListCrudContext = () => {
|
|
7
|
-
return createContext(undefined);
|
|
8
|
-
};
|
|
9
|
-
// Crear el contexto con un tipo genérico por defecto
|
|
10
|
-
// Los usuarios pueden crear su propio contexto con su tipo específico
|
|
11
|
-
export const ListCrudContext = createListCrudContext();
|
|
12
|
-
export function ListCrudProvider({ children, getPromise, postPromise, deletePromise, limit = 15, pageParam = "pagina", urlParams = [], }) {
|
|
13
|
-
const [list, setList] = useState(undefined);
|
|
14
|
-
const [page, setPage] = useState(1);
|
|
15
|
-
const [pages, setPages] = useState(1);
|
|
16
|
-
const [total, setTotal] = useState(0);
|
|
17
|
-
const getPromiseRef = useRef(getPromise);
|
|
18
|
-
const [searchParams, setSearchParams] = useSearchParams();
|
|
19
|
-
const lastFetchParamsRef = useRef("");
|
|
20
|
-
// Hooks para manejar las peticiones asíncronas
|
|
21
|
-
// fetchDataAsync sin mensaje para cargas automáticas
|
|
22
|
-
const fetchDataAsync = useAsyncRequest();
|
|
23
|
-
// fetchDataAsyncManual con mensaje para refetch manual
|
|
24
|
-
const fetchDataAsyncManual = useAsyncRequest({
|
|
25
|
-
successMessage: "Datos cargados correctamente",
|
|
26
|
-
});
|
|
27
|
-
const createItemAsync = useAsyncRequest();
|
|
28
|
-
const deleteItemAsync = useAsyncRequest();
|
|
29
|
-
// El isLoading del contexto combina ambos hooks de fetchData
|
|
30
|
-
const isLoading = fetchDataAsync.isLoading || fetchDataAsyncManual.isLoading;
|
|
31
|
-
// Actualizar la referencia cuando cambie getPromise
|
|
32
|
-
useEffect(() => {
|
|
33
|
-
getPromiseRef.current = getPromise;
|
|
34
|
-
}, [getPromise]);
|
|
35
|
-
// Función para obtener los parámetros de la URL
|
|
36
|
-
const getUrlParams = useCallback(() => {
|
|
37
|
-
const params = { limit };
|
|
38
|
-
// Agregar pageParam si existe en la URL
|
|
39
|
-
const pageValue = searchParams.get(pageParam);
|
|
40
|
-
if (pageValue) {
|
|
41
|
-
const parsedPage = parseInt(pageValue, 10);
|
|
42
|
-
if (!isNaN(parsedPage)) {
|
|
43
|
-
params[pageParam] = parsedPage;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
// Agregar urlParams si existen en la URL
|
|
47
|
-
urlParams.forEach((paramName) => {
|
|
48
|
-
const paramValue = searchParams.get(paramName);
|
|
49
|
-
if (paramValue !== null) {
|
|
50
|
-
params[paramName] = paramValue;
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
return params;
|
|
54
|
-
}, [searchParams, pageParam, urlParams, limit]);
|
|
55
|
-
// Función para obtener los datos
|
|
56
|
-
const fetchData = useCallback(async (params, showSuccessMessage = false) => {
|
|
57
|
-
const asyncRequest = showSuccessMessage
|
|
58
|
-
? fetchDataAsyncManual
|
|
59
|
-
: fetchDataAsync;
|
|
60
|
-
// Obtener los parámetros que se van a usar
|
|
61
|
-
const requestParams = params || getUrlParams();
|
|
62
|
-
// Crear una clave única para estos parámetros
|
|
63
|
-
const paramsKey = JSON.stringify({
|
|
64
|
-
...requestParams,
|
|
65
|
-
showSuccessMessage,
|
|
66
|
-
});
|
|
67
|
-
// Evitar ejecuciones duplicadas con los mismos parámetros
|
|
68
|
-
if (!showSuccessMessage && lastFetchParamsRef.current === paramsKey) {
|
|
69
|
-
console.log("Skipping duplicate fetchData call");
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
lastFetchParamsRef.current = paramsKey;
|
|
73
|
-
console.log("fetchData called", {
|
|
74
|
-
showSuccessMessage,
|
|
75
|
-
isLoading: asyncRequest.isLoading,
|
|
76
|
-
params: requestParams,
|
|
77
|
-
});
|
|
78
|
-
const result = await asyncRequest.execute(async () => {
|
|
79
|
-
console.log("Executing promise with params:", requestParams);
|
|
80
|
-
const promiseResult = await getPromiseRef.current(requestParams);
|
|
81
|
-
console.log("Promise result:", promiseResult);
|
|
82
|
-
return promiseResult;
|
|
83
|
-
});
|
|
84
|
-
console.log("fetchData result:", result);
|
|
85
|
-
// Solo procesar el resultado si no es undefined (undefined significa error)
|
|
86
|
-
if (result !== undefined) {
|
|
87
|
-
if (result && typeof result === "object" && "list" in result) {
|
|
88
|
-
// Es un PaginationInterface
|
|
89
|
-
const { list, page, pages, total } = result;
|
|
90
|
-
setList(list);
|
|
91
|
-
setPage(page);
|
|
92
|
-
setPages(pages);
|
|
93
|
-
setTotal(total);
|
|
94
|
-
}
|
|
95
|
-
else if (Array.isArray(result)) {
|
|
96
|
-
// Es un array simple
|
|
97
|
-
setList(result);
|
|
98
|
-
setPage(1);
|
|
99
|
-
setTotal(result.length);
|
|
100
|
-
setPages(Math.ceil(result.length / limit));
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
// Resultado null
|
|
104
|
-
setList(undefined);
|
|
105
|
-
setPage(1);
|
|
106
|
-
setPages(1);
|
|
107
|
-
setTotal(0);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
console.log("Result is undefined, not processing");
|
|
112
|
-
}
|
|
113
|
-
}, [getUrlParams, limit, fetchDataAsync, fetchDataAsyncManual]);
|
|
114
|
-
// Ref para almacenar los valores anteriores de urlParams
|
|
115
|
-
const prevUrlParamsValuesRef = useRef({});
|
|
116
|
-
// Memoizar los valores actuales de los urlParams
|
|
117
|
-
const urlParamsValues = useMemo(() => {
|
|
118
|
-
const values = {};
|
|
119
|
-
urlParams.forEach((paramName) => {
|
|
120
|
-
values[paramName] = searchParams.get(paramName);
|
|
121
|
-
});
|
|
122
|
-
return values;
|
|
123
|
-
}, [searchParams, urlParams]);
|
|
124
|
-
// Memoizar los parámetros de URL para evitar re-renders innecesarios
|
|
125
|
-
const urlParamsKey = useMemo(() => urlParams.join(","), [urlParams]);
|
|
126
|
-
// Memoizar los parámetros actuales para exponerlos
|
|
127
|
-
const currentParams = useMemo(() => getUrlParams(),
|
|
128
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
129
|
-
[searchParams, pageParam, urlParamsKey, limit, urlParams]);
|
|
130
|
-
// Función para recargar los datos
|
|
131
|
-
const refetch = useCallback(async (params) => {
|
|
132
|
-
await fetchData(params, true); // Mostrar mensaje de éxito en refetch manual
|
|
133
|
-
}, [fetchData]);
|
|
134
|
-
// Función para crear un item
|
|
135
|
-
const createItem = useCallback(async (item) => {
|
|
136
|
-
if (!postPromise) {
|
|
137
|
-
throw new Error("postPromise is not defined. Please provide postPromise to ListCrudProvider.");
|
|
138
|
-
}
|
|
139
|
-
return await createItemAsync.execute(async () => {
|
|
140
|
-
return await postPromise(item);
|
|
141
|
-
});
|
|
142
|
-
}, [postPromise, createItemAsync]);
|
|
143
|
-
// Función para eliminar un item
|
|
144
|
-
const deleteItem = useCallback(async (item) => {
|
|
145
|
-
if (!deletePromise) {
|
|
146
|
-
throw new Error("deletePromise is not defined. Please provide deletePromise to ListCrudProvider.");
|
|
147
|
-
}
|
|
148
|
-
await deleteItemAsync.execute(async () => {
|
|
149
|
-
await deletePromise(item);
|
|
150
|
-
});
|
|
151
|
-
}, [deletePromise, deleteItemAsync]);
|
|
152
|
-
// useEffect para resetear pageParam a 1 cuando cambien los urlParams
|
|
153
|
-
useEffect(() => {
|
|
154
|
-
// Verificar si hay algún urlParam definido
|
|
155
|
-
if (urlParams.length === 0) {
|
|
156
|
-
prevUrlParamsValuesRef.current = {};
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
// Comparar valores actuales con los anteriores
|
|
160
|
-
const prevValues = prevUrlParamsValuesRef.current;
|
|
161
|
-
const hasChanged = urlParams.some((paramName) => prevValues[paramName] !== urlParamsValues[paramName]);
|
|
162
|
-
// Si los urlParams cambiaron, resetear pageParam a 1
|
|
163
|
-
if (hasChanged) {
|
|
164
|
-
const currentPage = searchParams.get(pageParam);
|
|
165
|
-
if (currentPage && currentPage !== "1") {
|
|
166
|
-
const newSearchParams = new URLSearchParams(searchParams);
|
|
167
|
-
newSearchParams.set(pageParam, "1");
|
|
168
|
-
setSearchParams(newSearchParams, { replace: true });
|
|
169
|
-
// No hacer fetchData aquí, se hará cuando cambien los searchParams
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
// Actualizar los valores anteriores
|
|
174
|
-
prevUrlParamsValuesRef.current = { ...urlParamsValues };
|
|
175
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
176
|
-
}, [JSON.stringify(urlParamsValues), pageParam, urlParamsKey]);
|
|
177
|
-
// useEffect consolidado para escuchar cambios que requieren recargar datos
|
|
178
|
-
useEffect(() => {
|
|
179
|
-
// Usar un pequeño delay para agrupar múltiples cambios rápidos en el mismo tick
|
|
180
|
-
const timeoutId = setTimeout(() => {
|
|
181
|
-
fetchData();
|
|
182
|
-
}, 0);
|
|
183
|
-
return () => clearTimeout(timeoutId);
|
|
184
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
185
|
-
}, [getPromise, searchParams, pageParam, urlParamsKey]);
|
|
186
|
-
const value = {
|
|
187
|
-
list,
|
|
188
|
-
page,
|
|
189
|
-
pages,
|
|
190
|
-
total,
|
|
191
|
-
limit,
|
|
192
|
-
isLoading,
|
|
193
|
-
params: currentParams,
|
|
194
|
-
refetch,
|
|
195
|
-
createItem,
|
|
196
|
-
deleteItem,
|
|
197
|
-
pagination: (_jsx(Pagination, { page: page, pages: pages, total: total, fieldName: pageParam, isLoading: isLoading })),
|
|
198
|
-
};
|
|
199
|
-
return (_jsx(ListCrudContext.Provider, { value: value, children: children }));
|
|
200
|
-
}
|
|
201
|
-
// Hook to use ListCrud context
|
|
202
|
-
// eslint-disable-next-line react-refresh/only-export-components
|
|
203
|
-
export function useListCrud() {
|
|
204
|
-
const context = useContext(ListCrudContext);
|
|
205
|
-
if (context === undefined) {
|
|
206
|
-
throw new Error("useListCrud must be used within a ListCrudProvider");
|
|
207
|
-
}
|
|
208
|
-
return context;
|
|
209
|
-
}
|
|
File without changes
|