@eintrek/erp-shell 0.1.18 → 0.1.20

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/index.js CHANGED
@@ -738,7 +738,7 @@ function AppBreadcrumb({ labels = {}, homeLabel = "แดชบอร์ด", ro
738
738
  })] }) }));
739
739
  }
740
740
 
741
- function NavUser({ organization, profileHref, selectOrganizationHref = "/select-organization", signInRedirectHref = "/auth/signin", } = {}) {
741
+ function NavUser({ organization, avatarSrc, profileHref, selectOrganizationHref = "/select-organization", signInRedirectHref = "/auth/signin", } = {}) {
742
742
  const { data: session, status } = react.useSession();
743
743
  const router = navigation.useRouter();
744
744
  const { theme, setTheme } = nextThemes.useTheme();
@@ -752,7 +752,10 @@ function NavUser({ organization, profileHref, selectOrganizationHref = "/select-
752
752
  ? {
753
753
  name: session.user.name || "ผู้ใช้",
754
754
  email: session.user.email || "",
755
- avatar: session.user.image || undefined,
755
+ // avatarSrc first: the NextAuth session carries no picture unless the
756
+ // host app deliberately puts one in the JWT, so relying on
757
+ // session.user.image alone left every user on their initials forever.
758
+ avatar: avatarSrc || session.user.image || undefined,
756
759
  }
757
760
  : null;
758
761
  const getInitials = (name) => {
@@ -819,7 +822,14 @@ function NavUser({ organization, profileHref, selectOrganizationHref = "/select-
819
822
  }
820
823
  if (!user)
821
824
  return null;
822
- const dropdownContent = isOpen ? (jsxRuntime.jsxs("div", { "data-dropdown": "nav-user", className: "fixed w-52 sm:w-60 md:w-80 rounded-lg bg-sidebar border border-sidebar-border shadow-xl z-50 overflow-hidden\n -translate-x-[65%] -translate-y-[110%] sm:translate-x-0 sm:-translate-y-full", style: { top: `${position.top}px`, left: `${position.left}px` }, children: [organization && (jsxRuntime.jsx("div", { className: "p-4 border-b border-sidebar-border bg-sidebar-accent/30", children: jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [jsxRuntime.jsx(lucideReact.Building2, { className: "h-5 w-5 text-sidebar-foreground/70 flex-shrink-0" }), jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [jsxRuntime.jsx("div", { className: "font-medium text-sm sm:truncate", children: organization.name }), organization.description && (jsxRuntime.jsx("div", { className: "text-xs text-sidebar-foreground/70 truncate mt-0.5", children: organization.description }))] })] }) })), jsxRuntime.jsxs("div", { className: "p-2", children: [jsxRuntime.jsxs("div", { className: "relative", children: [jsxRuntime.jsxs("button", { onClick: () => {
825
+ const dropdownContent = isOpen ? (jsxRuntime.jsxs("div", { "data-dropdown": "nav-user", className: "fixed w-52 sm:w-60 md:w-80 rounded-lg bg-sidebar border border-sidebar-border shadow-xl z-50 overflow-hidden\n -translate-x-[65%] -translate-y-[110%] sm:translate-x-0 sm:-translate-y-full", style: { top: `${position.top}px`, left: `${position.left}px` }, children: [organization && (jsxRuntime.jsx("div", { className: "p-4 border-b border-sidebar-border bg-sidebar-accent/30", children: jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [organization.logoUrl ? (
826
+ // eslint-disable-next-line @next/next/no-img-element
827
+ jsxRuntime.jsx("img", { src: organization.logoUrl, alt: organization.name ?? "โลโก้บริษัท", className: "h-8 w-8 flex-shrink-0 rounded object-contain bg-white",
828
+ // A dead logo URL must not leave a broken-image glyph in the
829
+ // sidebar; drop back to the generic icon's empty slot.
830
+ onError: e => {
831
+ e.currentTarget.style.display = "none";
832
+ } })) : (jsxRuntime.jsx(lucideReact.Building2, { className: "h-5 w-5 text-sidebar-foreground/70 flex-shrink-0" })), jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [jsxRuntime.jsx("div", { className: "font-medium text-sm sm:truncate", children: organization.name }), organization.description && (jsxRuntime.jsx("div", { className: "text-xs text-sidebar-foreground/70 truncate mt-0.5", children: organization.description }))] })] }) })), jsxRuntime.jsxs("div", { className: "p-2", children: [jsxRuntime.jsxs("div", { className: "relative", children: [jsxRuntime.jsxs("button", { onClick: () => {
823
833
  setShowThemeMenu(!showThemeMenu);
824
834
  setShowLanguageMenu(false);
825
835
  }, className: "flex w-full items-center gap-3 px-3 py-2.5 text-sm text-sidebar-foreground hover:bg-sidebar-accent rounded-md transition-colors", children: [jsxRuntime.jsx(lucideReact.Palette, { className: "h-4 w-4" }), jsxRuntime.jsx("span", { className: "flex-1 text-left", children: "\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E18\u0E35\u0E21" }), jsxRuntime.jsx(lucideReact.ChevronUp, { className: `h-4 w-4 transition-transform ${showThemeMenu ? "rotate-180" : ""}` })] }), showThemeMenu && (jsxRuntime.jsx("div", { className: "mt-1 ml-4 space-y-1", children: [
@@ -1351,8 +1361,19 @@ const getQueryClientConfig = () => ({
1351
1361
  refetchOnWindowFocus: true,
1352
1362
  },
1353
1363
  mutations: {
1354
- retry: 1,
1355
- retryDelay: attemptIndex => Math.min(1000 * 2 ** attemptIndex, 30000),
1364
+ // NEVER auto-retry a mutation. Unlike a query, a mutation is a side
1365
+ // effect on a non-idempotent endpoint (submit, create, approve), and
1366
+ // React Query cannot tell "the network dropped" from "the server
1367
+ // rejected this on business grounds".
1368
+ //
1369
+ // With retry: 1 every failed mutation fired twice. Two visible
1370
+ // consequences: a rejected submit showed up as two failed POSTs in the
1371
+ // network tab, and — far worse — a create whose response was lost in
1372
+ // flight would be re-sent and duplicate the record server-side.
1373
+ //
1374
+ // Retrying is the caller's decision, not a global default: the user
1375
+ // sees the error and presses the button again.
1376
+ retry: 0,
1356
1377
  },
1357
1378
  },
1358
1379
  queryCache: new reactQuery.QueryCache({