@zauru-sdk/components 2.0.96 → 2.0.97

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 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
+ ## [2.0.97](https://github.com/intuitiva/zauru-typescript-sdk/compare/v2.0.96...v2.0.97) (2025-01-07)
7
+
8
+ **Note:** Version bump only for package @zauru-sdk/components
9
+
10
+
11
+
12
+
13
+
6
14
  ## [2.0.96](https://github.com/intuitiva/zauru-typescript-sdk/compare/v2.0.95...v2.0.96) (2025-01-03)
7
15
 
8
16
  **Note:** Version bump only for package @zauru-sdk/components
@@ -1,4 +1,5 @@
1
- export declare const ErrorLayout: ({ from, error: parentError, }: {
1
+ export declare const ErrorLayout: ({ from, isRootLevel, error: parentError, }: {
2
2
  from?: string;
3
+ isRootLevel?: boolean;
3
4
  error?: Error;
4
- }) => import("react/jsx-runtime").JSX.Element;
5
+ }) => import("react/jsx-runtime").JSX.Element | null;
@@ -1,15 +1,17 @@
1
- export type NavBarItemsSchema = {
1
+ export type NavBarItem = {
2
2
  name: string;
3
3
  link: string;
4
4
  loggedIn: boolean;
5
5
  icon?: any;
6
- color?: "green";
7
- childrens?: Exclude<NavBarItemsSchema, "loggedIn">[];
6
+ selectedColor?: "green";
7
+ color?: ColorInterface;
8
+ childrens?: Exclude<NavBarItem, "loggedIn">[];
9
+ reduxNotificationBadge?: (state: any) => string | number;
8
10
  };
9
11
  export type NavBarProps = {
10
12
  title: string;
11
13
  loggedIn: boolean;
12
- items: Array<NavBarItemsSchema>;
14
+ items: Array<NavBarItem>;
13
15
  selectedColor: "pink" | "purple" | "slate" | "green" | "yellow" | "red" | "sky";
14
16
  LinkComponent?: any;
15
17
  version?: string;
@@ -26,14 +28,6 @@ export type ColorInterface = {
26
28
  ring600: string;
27
29
  ring500: string;
28
30
  };
29
- export type NavItemProps = {
30
- name: string;
31
- link: string;
32
- icon?: any;
33
- color: ColorInterface;
34
- specialColor?: ColorInterface;
35
- childrens?: Exclude<NavItemProps, "index" | "color">[];
36
- };
37
31
  export type EntityNameType = {
38
32
  entityName: string;
39
33
  };
@@ -1,20 +1,24 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { isRouteErrorResponse, Links, Meta, Scripts, useRouteError, Link, } from "@remix-run/react";
3
3
  import { useState } from "react";
4
- export const ErrorLayout = ({ from, error: parentError, }) => {
4
+ export const ErrorLayout = ({ from, isRootLevel = true, error: parentError, }) => {
5
5
  try {
6
6
  const error = useRouteError();
7
7
  const [showDetails, setShowDetails] = useState(!!parentError);
8
- 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!" }), _jsxs("div", { className: "w-full max-w-2xl flex flex-col items-center", children: [_jsx("p", { className: "text-2xl text-gray-300 mb-8 text-center", children: isRouteErrorResponse(error)
9
- ? `Error ${error.status}: ${error.statusText}`
10
- : error instanceof Error
11
- ? error.message
12
- : "Ha ocurrido un error inesperado" }), from && (_jsxs("p", { className: "text-lg text-gray-400 mb-4 text-center", children: ["Error lanzado desde: ", from] })), parentError && (_jsxs("div", { className: "mb-4 text-center", children: [_jsx("button", { onClick: () => setShowDetails(!showDetails), className: "text-blue-400 hover:text-blue-300 transition duration-300", children: showDetails ? "Ocultar detalles" : "Ver más detalles" }), showDetails && (_jsx("p", { className: "mt-2 text-gray-400 text-sm", children: parentError instanceof Error
13
- ? parentError.message
14
- : String(parentError) }))] }))] }), _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 text-center", children: _jsx("p", { children: "Si el problema persiste, por favor contacta a soporte." }) }), _jsx(Scripts, {})] })] }));
8
+ const baseError = (_jsxs("div", { 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!" }), _jsxs("div", { className: "w-full max-w-2xl flex flex-col items-center", children: [_jsx("p", { className: "text-2xl text-gray-300 mb-8 text-center", children: isRouteErrorResponse(error)
9
+ ? `Error ${error.status}: ${error.statusText}`
10
+ : error instanceof Error
11
+ ? error.message
12
+ : "Ha ocurrido un error inesperado" }), from && (_jsxs("p", { className: "text-lg text-gray-400 mb-4 text-center", children: ["Error lanzado desde: ", from] })), parentError && (_jsxs("div", { className: "mb-4 text-center", children: [_jsx("button", { onClick: () => setShowDetails(!showDetails), className: "text-blue-400 hover:text-blue-300 transition duration-300", children: showDetails ? "Ocultar detalles" : "Ver más detalles" }), showDetails && (_jsx("p", { className: "mt-2 text-gray-400 text-sm", children: parentError instanceof Error
13
+ ? parentError.message
14
+ : String(parentError) }))] }))] }), _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 text-center", children: _jsx("p", { children: "Si el problema persiste, por favor contacta a soporte." }) })] }));
15
+ if (!isRootLevel) {
16
+ return baseError;
17
+ }
18
+ 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: [baseError, _jsx(Scripts, {})] })] }));
15
19
  }
16
20
  catch (error) {
17
- console.error(error);
18
- return (_jsxs("html", { lang: "es", className: "bg-gray-900 text-white", children: [_jsx("head", { children: _jsx("title", { children: "\u00A1Ups! Algo sali\u00F3 mal" }) }), _jsxs("body", { children: ["Error al renderizar el layout de error ", error] })] }));
21
+ console.error("Error en el layout de error:", error);
22
+ return null;
19
23
  }
20
24
  };
@@ -3,11 +3,23 @@ import React, { useState, useEffect } from "react";
3
3
  import { DropDownArrowSvgIcon, LogoutDropDownSvgIcon, MenuAlt4Svg, OpcionButtonSvgIcon, } from "@zauru-sdk/icons";
4
4
  import { COLORS } from "./NavBar.utils.js";
5
5
  import { Link, useNavigate } from "@remix-run/react";
6
+ import { useAppSelector } from "@zauru-sdk/redux";
6
7
  const OptionsDropDownButton = ({ color, options, name }) => {
7
8
  const [showOptionsMenu, setShowOptionsMenu] = useState(true);
8
9
  return (_jsx("div", { className: "nav-item ml-auto", children: _jsx("div", { className: "flex justify-center", children: _jsxs("div", { className: "relative inline-block", children: [_jsxs("button", { onClick: () => setShowOptionsMenu(!showOptionsMenu), className: `relative flex items-center p-2 text-xs text-white ${color.bg700} active:${color.bg900} border border-transparent rounded-full uppercase focus:ring-opacity-40 focus:outline-none`, children: [name ?? _jsx(OpcionButtonSvgIcon, {}), _jsx(DropDownArrowSvgIcon, {})] }), _jsx("div", { className: "absolute right-0 z-20 w-56 py-2 mt-2 overflow-hidden bg-white rounded-md shadow-xl dark:bg-gray-800", hidden: showOptionsMenu, onMouseLeave: () => setShowOptionsMenu(true), children: options.map((option, index) => (_jsx(React.Fragment, { children: option }, index))) })] }) }) }));
9
10
  };
10
- const NavItem = ({ name, link, icon, color, specialColor, childrens = [], }) => (_jsx("li", { className: "nav-item", children: childrens.length > 0 ? (_jsx(OptionsDropDownButton, { name: name, color: color, specialColor: specialColor, options: childrens.map((x, index) => (_jsx(Link, { to: x.link, className: `block px-4 py-3 text-sm text-gray-600 capitalize transition-colors duration-200 transform dark:text-gray-300 hover:bg-red-100 dark:hover:bg-gray-700 dark:hover:text-white`, children: x.name }, index))) })) : (_jsx("div", { className: `${specialColor ? specialColor.bg700 : color.bg700} container text-white w-full sm:w-auto h-10 text-sm py-1 uppercase shadow hover:shadow-lg outline-none rounded-full focus:outline-none my-auto sm:my-0 sm:mr-1 mb-1 ease-linear transition-all duration-150`, children: _jsx(Link, { className: "px-3 flex items-center text-xs leading-snug text-white uppercase hover:opacity-75", to: link, prefetch: "none", children: _jsxs("div", { className: "mx-auto pt-2", children: [icon, _jsx("span", { children: name })] }) }) })) }));
11
+ const NavItem = ({ name, link, icon, selectedColor, childrens = [], reduxNotificationBadge, }) => {
12
+ const specialColor = selectedColor
13
+ ? COLORS[selectedColor]
14
+ : COLORS["slate"];
15
+ // Selecciona solo la parte del estado relevante
16
+ const relevantState = useAppSelector((state) => reduxNotificationBadge ? reduxNotificationBadge(state) : undefined);
17
+ const [notificationBadge, setNotificationBadge] = useState();
18
+ useEffect(() => {
19
+ setNotificationBadge(relevantState);
20
+ }, [relevantState]);
21
+ return (_jsx("li", { className: "nav-item relative", children: childrens.length > 0 ? (_jsx(OptionsDropDownButton, { name: name, color: specialColor, options: childrens.map((x, index) => (_jsx(Link, { to: x.link, className: `block px-4 py-3 text-sm text-gray-600 capitalize transition-colors duration-200 transform dark:text-gray-300 hover:bg-red-100 dark:hover:bg-gray-700 dark:hover:text-white`, children: x.name }, index))) })) : (_jsx("div", { className: `${specialColor.bg700} container text-white w-full sm:w-auto h-10 text-sm py-1 uppercase shadow hover:shadow-lg outline-none rounded-full focus:outline-none my-auto sm:my-0 sm:mr-1 mb-1 ease-linear transition-all duration-150`, children: _jsxs(Link, { className: "px-3 flex items-center text-xs leading-snug text-white uppercase hover:opacity-75 relative", to: link, children: [_jsxs("div", { className: "mx-auto pt-2", children: [icon, _jsx("span", { children: name })] }), notificationBadge !== undefined && (_jsx("span", { className: "absolute -top-2 -right-2 bg-red-500 text-white text-xs font-bold rounded-full flex items-center justify-center w-5 h-5", children: notificationBadge }))] }) })) }));
22
+ };
11
23
  export const NavBar = ({ title, loggedIn, items, selectedColor, version, }) => {
12
24
  const color = COLORS[selectedColor];
13
25
  const [NavBarOpen, setNavBarOpen] = useState(false);
@@ -22,15 +34,12 @@ export const NavBar = ({ title, loggedIn, items, selectedColor, version, }) => {
22
34
  navigate(0);
23
35
  };
24
36
  const renderNavItems = (items) => (_jsx("div", { className: "flex flex-col lg:flex-row w-full", children: items.map((item, index) => {
25
- const specialColor = item.color
26
- ? COLORS[item.color]
27
- : undefined;
28
- return (_jsx(NavItem, { name: item.name, link: item.link, icon: item.icon, specialColor: specialColor, color: color, childrens: item.childrens?.map((x) => {
37
+ return (_jsx(NavItem, { name: item.name, link: item.link, icon: item.icon, selectedColor: item.selectedColor, color: color, loggedIn: item.loggedIn, reduxNotificationBadge: item.reduxNotificationBadge, childrens: item.childrens?.map((x) => {
29
38
  return { ...x };
30
39
  }) }, index));
31
40
  }) }));
32
41
  const options = (_jsxs(_Fragment, { children: [_jsx("ul", { className: "w-full lg:flex lg:items-center", children: renderNavItems(items.filter((item) => item.loggedIn === loggedIn)) }), _jsx("ul", { className: "sm:flex sm:flex-col lg:flex-row ml-auto", children: loggedIn && (_jsx(OptionsDropDownButton, { color: color, options: [
33
- _jsx(Link, { className: `block px-4 py-3 text-sm text-gray-600 capitalize transition-colors duration-200 transform dark:text-gray-300 hover:bg-red-100 dark:hover:bg-gray-700 dark:hover:text-white`, to: "/logout", prefetch: "none", children: _jsxs("div", { className: "mx-auto pt-2", children: [_jsx(LogoutDropDownSvgIcon, {}), _jsx("span", { children: "Cerrar sesi\u00F3n" })] }) }),
42
+ _jsx(Link, { className: `block px-4 py-3 text-sm text-gray-600 capitalize transition-colors duration-200 transform dark:text-gray-300 hover:bg-red-100 dark:hover:bg-gray-700 dark:hover:text-white`, to: "/logout", children: _jsxs("div", { className: "mx-auto pt-2", children: [_jsx(LogoutDropDownSvgIcon, {}), _jsx("span", { children: "Cerrar sesi\u00F3n" })] }) }),
34
43
  ] })) })] }));
35
- return (_jsx("nav", { className: `py-3 ${color.bg600}`, children: _jsxs("div", { className: "flex items-center justify-between ml-5 mr-5", children: [_jsxs("div", { className: "flex justify-between items-center w-full lg:w-auto", children: [_jsx(Link, { className: "text-sm font-bold leading-relaxed inline-block mr-4 py-2 whitespace-nowrap uppercase text-white", to: "/home", prefetch: "none", children: _jsxs(_Fragment, { children: [_jsx("div", { className: "inline-block mr-2 mb-2 align-middle", children: _jsx("img", { className: "w-auto h-7", src: "/logo.png", alt: "logo-zauru" }) }), title] }) }), version !== currentVersion && (_jsx("button", { className: `ml-2 px-2 py-1 text-xs text-white ${color.bg700} rounded-full hover:${color.bg900} transition-colors duration-200`, onClick: refreshPage, children: "\uD83D\uDD04 Actualizar versi\u00F3n" })), _jsx("button", { className: `rounded lg:hidden focus:outline-none focus:ring focus:${color.ring600} focus:ring-opacity-50`, "aria-label": "Toggle mobile menu", type: "button", onClick: () => setNavBarOpen(!NavBarOpen), children: _jsx(MenuAlt4Svg, { open: NavBarOpen }) })] }), _jsx("div", { className: `lg:hidden fixed top-0 left-0 z-50 w-64 h-full ${color.bg700} dark:bg-gray-900 shadow-lg transform ${NavBarOpen ? "translate-x-0" : "-translate-x-full"} transition-transform duration-300 ease-in-out overflow-y-auto`, children: _jsx("div", { className: "p-4", children: options }) }), _jsx("div", { className: "hidden lg:flex lg:items-center w-full lg:w-auto", children: options })] }) }));
44
+ return (_jsx("nav", { className: `py-3 ${color.bg600}`, children: _jsxs("div", { className: "flex items-center justify-between ml-5 mr-5", children: [_jsxs("div", { className: "flex justify-between items-center w-full lg:w-auto", children: [_jsx(Link, { className: "text-sm font-bold leading-relaxed inline-block mr-4 py-2 whitespace-nowrap uppercase text-white", to: "/home", children: _jsxs(_Fragment, { children: [_jsx("div", { className: "inline-block mr-2 mb-2 align-middle", children: _jsx("img", { className: "w-auto h-7", src: "/logo.png", alt: "logo-zauru" }) }), title] }) }), version !== currentVersion && (_jsx("button", { className: `ml-2 px-2 py-1 text-xs text-white ${color.bg700} rounded-full hover:${color.bg900} transition-colors duration-200`, onClick: refreshPage, children: "\uD83D\uDD04 Actualizar versi\u00F3n" })), _jsx("button", { className: `rounded lg:hidden focus:outline-none focus:ring focus:${color.ring600} focus:ring-opacity-50`, "aria-label": "Toggle mobile menu", type: "button", onClick: () => setNavBarOpen(!NavBarOpen), children: _jsx(MenuAlt4Svg, { open: NavBarOpen }) })] }), _jsx("div", { className: `lg:hidden fixed top-0 left-0 z-50 w-64 h-full ${color.bg700} dark:bg-gray-900 shadow-lg transform ${NavBarOpen ? "translate-x-0" : "-translate-x-full"} transition-transform duration-300 ease-in-out overflow-y-auto`, children: _jsx("div", { className: "p-4", children: options }) }), _jsx("div", { className: "hidden lg:flex lg:items-center w-full lg:w-auto", children: options })] }) }));
36
45
  };
@@ -27,7 +27,6 @@ const customStyles = {
27
27
  highlightOnHoverStyle: {
28
28
  backgroundColor: "rgb(230, 244, 244)",
29
29
  borderBottomColor: "#FFFFFF",
30
- borderRadius: "25px",
31
30
  outline: "1px solid #FFFFFF",
32
31
  },
33
32
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zauru-sdk/components",
3
- "version": "2.0.96",
3
+ "version": "2.0.97",
4
4
  "description": "Componentes reutilizables en las WebApps de Zauru.",
5
5
  "main": "./dist/esm/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -34,8 +34,8 @@
34
34
  "@reduxjs/toolkit": "^2.2.1",
35
35
  "@remix-run/react": "^2.8.1",
36
36
  "@zauru-sdk/common": "^2.0.94",
37
- "@zauru-sdk/hooks": "^2.0.94",
38
- "@zauru-sdk/icons": "^2.0.87",
37
+ "@zauru-sdk/hooks": "^2.0.97",
38
+ "@zauru-sdk/icons": "^2.0.97",
39
39
  "@zauru-sdk/types": "^2.0.92",
40
40
  "@zauru-sdk/utils": "^2.0.96",
41
41
  "framer-motion": "^11.7.0",
@@ -49,5 +49,5 @@
49
49
  "styled-components": "^5.3.5",
50
50
  "zod": "^3.23.8"
51
51
  },
52
- "gitHead": "b46314dae63e6d018c4913cc8fc7ecb0c6c51d91"
52
+ "gitHead": "3f46d9c99fafe5f245791a7ade3c8ab5f5e8da87"
53
53
  }
@@ -10,80 +10,85 @@ import { useState } from "react";
10
10
 
11
11
  export const ErrorLayout = ({
12
12
  from,
13
+ isRootLevel = true,
13
14
  error: parentError,
14
15
  }: {
15
16
  from?: string;
17
+ isRootLevel?: boolean;
16
18
  error?: Error;
17
19
  }) => {
18
20
  try {
19
21
  const error = useRouteError();
20
22
  const [showDetails, setShowDetails] = useState(!!parentError);
21
23
 
24
+ const baseError = (
25
+ <div className="min-h-screen flex flex-col items-center justify-center p-4">
26
+ <img src="/logo.png" alt="Zauru Logo" className="mb-8 h-20" />
27
+ <h1 className="text-5xl font-extrabold text-red-500 mb-6">¡Ups!</h1>
28
+ <div className="w-full max-w-2xl flex flex-col items-center">
29
+ <p className="text-2xl text-gray-300 mb-8 text-center">
30
+ {isRouteErrorResponse(error)
31
+ ? `Error ${error.status}: ${error.statusText}`
32
+ : error instanceof Error
33
+ ? error.message
34
+ : "Ha ocurrido un error inesperado"}
35
+ </p>
36
+ {from && (
37
+ <p className="text-lg text-gray-400 mb-4 text-center">
38
+ Error lanzado desde: {from}
39
+ </p>
40
+ )}
41
+ {parentError && (
42
+ <div className="mb-4 text-center">
43
+ <button
44
+ onClick={() => setShowDetails(!showDetails)}
45
+ className="text-blue-400 hover:text-blue-300 transition duration-300"
46
+ >
47
+ {showDetails ? "Ocultar detalles" : "Ver más detalles"}
48
+ </button>
49
+ {showDetails && (
50
+ <p className="mt-2 text-gray-400 text-sm">
51
+ {parentError instanceof Error
52
+ ? parentError.message
53
+ : String(parentError)}
54
+ </p>
55
+ )}
56
+ </div>
57
+ )}
58
+ </div>
59
+ <Link
60
+ to="/"
61
+ 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"
62
+ >
63
+ Regresar al inicio
64
+ </Link>
65
+ <div className="mt-12 text-gray-500 text-center">
66
+ <p>Si el problema persiste, por favor contacta a soporte.</p>
67
+ </div>
68
+ </div>
69
+ );
70
+
71
+ if (!isRootLevel) {
72
+ return baseError;
73
+ }
74
+
22
75
  return (
23
76
  <html lang="es" className="bg-gray-900 text-white">
24
77
  <head>
25
78
  <meta charSet="utf-8" />
26
79
  <meta name="viewport" content="width=device-width, initial-scale=1" />
27
- <title>¡Ups! Algo salió mal</title>
80
+ <title>¡Ups! Algo salió mal *</title>
28
81
  <Meta />
29
82
  <Links />
30
83
  </head>
31
84
  <body className="min-h-screen flex flex-col items-center justify-center p-4">
32
- <img src="/logo.png" alt="Zauru Logo" className="mb-8 h-20" />
33
- <h1 className="text-5xl font-extrabold text-red-500 mb-6">¡Ups!</h1>
34
- <div className="w-full max-w-2xl flex flex-col items-center">
35
- <p className="text-2xl text-gray-300 mb-8 text-center">
36
- {isRouteErrorResponse(error)
37
- ? `Error ${error.status}: ${error.statusText}`
38
- : error instanceof Error
39
- ? error.message
40
- : "Ha ocurrido un error inesperado"}
41
- </p>
42
- {from && (
43
- <p className="text-lg text-gray-400 mb-4 text-center">
44
- Error lanzado desde: {from}
45
- </p>
46
- )}
47
- {parentError && (
48
- <div className="mb-4 text-center">
49
- <button
50
- onClick={() => setShowDetails(!showDetails)}
51
- className="text-blue-400 hover:text-blue-300 transition duration-300"
52
- >
53
- {showDetails ? "Ocultar detalles" : "Ver más detalles"}
54
- </button>
55
- {showDetails && (
56
- <p className="mt-2 text-gray-400 text-sm">
57
- {parentError instanceof Error
58
- ? parentError.message
59
- : String(parentError)}
60
- </p>
61
- )}
62
- </div>
63
- )}
64
- </div>
65
- <Link
66
- to="/"
67
- 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"
68
- >
69
- Regresar al inicio
70
- </Link>
71
- <div className="mt-12 text-gray-500 text-center">
72
- <p>Si el problema persiste, por favor contacta a soporte.</p>
73
- </div>
85
+ {baseError}
74
86
  <Scripts />
75
87
  </body>
76
88
  </html>
77
89
  );
78
- } catch (error: any) {
79
- console.error(error);
80
- return (
81
- <html lang="es" className="bg-gray-900 text-white">
82
- <head>
83
- <title>¡Ups! Algo salió mal</title>
84
- </head>
85
- <body>Error al renderizar el layout de error {error}</body>
86
- </html>
87
- );
90
+ } catch (error) {
91
+ console.error("Error en el layout de error:", error);
92
+ return null;
88
93
  }
89
94
  };
@@ -9,11 +9,11 @@ import { COLORS } from "./NavBar.utils.js";
9
9
  import type {
10
10
  ColorInterface,
11
11
  EntityProps,
12
- NavBarItemsSchema,
12
+ NavBarItem,
13
13
  NavBarProps,
14
- NavItemProps,
15
14
  } from "./NavBar.types.js";
16
15
  import { Link, useNavigate } from "@remix-run/react";
16
+ import { useAppSelector } from "@zauru-sdk/redux";
17
17
 
18
18
  const OptionsDropDownButton = ({ color, options, name }: EntityProps) => {
19
19
  const [showOptionsMenu, setShowOptionsMenu] = useState(true);
@@ -48,46 +48,67 @@ const NavItem = ({
48
48
  name,
49
49
  link,
50
50
  icon,
51
- color,
52
- specialColor,
51
+ selectedColor,
53
52
  childrens = [],
54
- }: NavItemProps) => (
55
- <li className="nav-item">
56
- {childrens.length > 0 ? (
57
- <OptionsDropDownButton
58
- name={name}
59
- color={color}
60
- specialColor={specialColor}
61
- options={childrens.map((x, index) => (
53
+ reduxNotificationBadge,
54
+ }: NavBarItem) => {
55
+ const specialColor: ColorInterface = selectedColor
56
+ ? COLORS[selectedColor]
57
+ : COLORS["slate"];
58
+
59
+ // Selecciona solo la parte del estado relevante
60
+ const relevantState = useAppSelector((state) =>
61
+ reduxNotificationBadge ? reduxNotificationBadge(state) : undefined
62
+ );
63
+
64
+ const [notificationBadge, setNotificationBadge] = useState<
65
+ undefined | string | number
66
+ >();
67
+
68
+ useEffect(() => {
69
+ setNotificationBadge(relevantState);
70
+ }, [relevantState]);
71
+
72
+ return (
73
+ <li className="nav-item relative">
74
+ {childrens.length > 0 ? (
75
+ <OptionsDropDownButton
76
+ name={name}
77
+ color={specialColor}
78
+ options={childrens.map((x, index) => (
79
+ <Link
80
+ key={index}
81
+ to={x.link}
82
+ className={`block px-4 py-3 text-sm text-gray-600 capitalize transition-colors duration-200 transform dark:text-gray-300 hover:bg-red-100 dark:hover:bg-gray-700 dark:hover:text-white`}
83
+ >
84
+ {x.name}
85
+ </Link>
86
+ ))}
87
+ />
88
+ ) : (
89
+ <div
90
+ className={`${specialColor.bg700} container text-white w-full sm:w-auto h-10 text-sm py-1 uppercase shadow hover:shadow-lg outline-none rounded-full focus:outline-none my-auto sm:my-0 sm:mr-1 mb-1 ease-linear transition-all duration-150`}
91
+ >
62
92
  <Link
63
- key={index}
64
- to={x.link}
65
- className={`block px-4 py-3 text-sm text-gray-600 capitalize transition-colors duration-200 transform dark:text-gray-300 hover:bg-red-100 dark:hover:bg-gray-700 dark:hover:text-white`}
93
+ className="px-3 flex items-center text-xs leading-snug text-white uppercase hover:opacity-75 relative"
94
+ to={link}
66
95
  >
67
- {x.name}
96
+ <div className="mx-auto pt-2">
97
+ {icon}
98
+ <span>{name}</span>
99
+ </div>
100
+ {/* Badge de notificaciones */}
101
+ {notificationBadge !== undefined && (
102
+ <span className="absolute -top-2 -right-2 bg-red-500 text-white text-xs font-bold rounded-full flex items-center justify-center w-5 h-5">
103
+ {notificationBadge}
104
+ </span>
105
+ )}
68
106
  </Link>
69
- ))}
70
- />
71
- ) : (
72
- <div
73
- className={`${
74
- specialColor ? specialColor.bg700 : color.bg700
75
- } container text-white w-full sm:w-auto h-10 text-sm py-1 uppercase shadow hover:shadow-lg outline-none rounded-full focus:outline-none my-auto sm:my-0 sm:mr-1 mb-1 ease-linear transition-all duration-150`}
76
- >
77
- <Link
78
- className="px-3 flex items-center text-xs leading-snug text-white uppercase hover:opacity-75"
79
- to={link}
80
- prefetch="none"
81
- >
82
- <div className="mx-auto pt-2">
83
- {icon}
84
- <span>{name}</span>
85
- </div>
86
- </Link>
87
- </div>
88
- )}
89
- </li>
90
- );
107
+ </div>
108
+ )}
109
+ </li>
110
+ );
111
+ };
91
112
 
92
113
  export const NavBar = ({
93
114
  title,
@@ -111,20 +132,19 @@ export const NavBar = ({
111
132
  navigate(0);
112
133
  };
113
134
 
114
- const renderNavItems = (items: NavBarItemsSchema[]) => (
135
+ const renderNavItems = (items: NavBarItem[]) => (
115
136
  <div className="flex flex-col lg:flex-row w-full">
116
137
  {items.map((item, index) => {
117
- const specialColor: ColorInterface | undefined = item.color
118
- ? COLORS[item.color]
119
- : undefined;
120
138
  return (
121
139
  <NavItem
122
140
  key={index}
123
141
  name={item.name}
124
142
  link={item.link}
125
143
  icon={item.icon}
126
- specialColor={specialColor}
144
+ selectedColor={item.selectedColor}
127
145
  color={color}
146
+ loggedIn={item.loggedIn}
147
+ reduxNotificationBadge={item.reduxNotificationBadge}
128
148
  childrens={item.childrens?.map((x) => {
129
149
  return { ...x } as any;
130
150
  })}
@@ -147,7 +167,6 @@ export const NavBar = ({
147
167
  <Link
148
168
  className={`block px-4 py-3 text-sm text-gray-600 capitalize transition-colors duration-200 transform dark:text-gray-300 hover:bg-red-100 dark:hover:bg-gray-700 dark:hover:text-white`}
149
169
  to="/logout"
150
- prefetch="none"
151
170
  >
152
171
  <div className="mx-auto pt-2">
153
172
  {<LogoutDropDownSvgIcon />}
@@ -168,7 +187,6 @@ export const NavBar = ({
168
187
  <Link
169
188
  className="text-sm font-bold leading-relaxed inline-block mr-4 py-2 whitespace-nowrap uppercase text-white"
170
189
  to={"/home"}
171
- prefetch="none"
172
190
  children={
173
191
  <>
174
192
  <div className="inline-block mr-2 mb-2 align-middle">
@@ -1,16 +1,18 @@
1
- export type NavBarItemsSchema = {
1
+ export type NavBarItem = {
2
2
  name: string;
3
3
  link: string;
4
4
  loggedIn: boolean;
5
5
  icon?: any;
6
- color?: "green";
7
- childrens?: Exclude<NavBarItemsSchema, "loggedIn">[];
6
+ selectedColor?: "green";
7
+ color?: ColorInterface;
8
+ childrens?: Exclude<NavBarItem, "loggedIn">[];
9
+ reduxNotificationBadge?: (state: any) => string | number;
8
10
  };
9
11
 
10
12
  export type NavBarProps = {
11
13
  title: string;
12
14
  loggedIn: boolean;
13
- items: Array<NavBarItemsSchema>;
15
+ items: Array<NavBarItem>;
14
16
  selectedColor:
15
17
  | "pink"
16
18
  | "purple"
@@ -37,15 +39,6 @@ export type ColorInterface = {
37
39
  ring500: string;
38
40
  };
39
41
 
40
- export type NavItemProps = {
41
- name: string;
42
- link: string;
43
- icon?: any;
44
- color: ColorInterface;
45
- specialColor?: ColorInterface;
46
- childrens?: Exclude<NavItemProps, "index" | "color">[];
47
- };
48
-
49
42
  export type EntityNameType = {
50
43
  entityName: string;
51
44
  };
@@ -1,5 +1,3 @@
1
1
  export * from "./NavBar.js";
2
-
3
2
  export * from "./NavBar.types.js";
4
-
5
3
  export * from "./NavBar.utils.js";
@@ -32,7 +32,6 @@ const customStyles: TableStyles = {
32
32
  highlightOnHoverStyle: {
33
33
  backgroundColor: "rgb(230, 244, 244)",
34
34
  borderBottomColor: "#FFFFFF",
35
- borderRadius: "25px",
36
35
  outline: "1px solid #FFFFFF",
37
36
  },
38
37
  },