@eintrek/erp-shell 0.1.12 → 0.1.14

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
@@ -351,9 +351,15 @@ function useOrganizationIdState(initialOrganizationId, actions) {
351
351
  }
352
352
 
353
353
  /**
354
- * Invalidate ALL React Query queries when `organizationId` changes
355
- * (skips the initial mount). Use inside the ERP provider so org-scoped
356
- * data is refetched cleanly when the user switches org.
354
+ * Invalidate ALL React Query queries when `organizationId` changes between
355
+ * two real orgs (e.g. the user switches org in the picker). Skips the
356
+ * initial mount and the first-resolve transition (undefined/null/"" x)
357
+ * — that's the URL `[code]` segment finally syncing into the ERP context,
358
+ * not a real switch, and invalidating there triggers a cascade of refetches
359
+ * on top of the queries that already just fired.
360
+ *
361
+ * Use inside the ERP provider so org-scoped data is wiped cleanly when the
362
+ * user really does switch between two orgs.
357
363
  */
358
364
  function useInvalidateQueriesOnOrgChange(organizationId) {
359
365
  const queryClient = reactQuery.useQueryClient();
@@ -367,7 +373,15 @@ function useInvalidateQueriesOnOrgChange(organizationId) {
367
373
  }
368
374
  if (previousRef.current === organizationId)
369
375
  return;
376
+ const wasEmpty = previousRef.current === undefined ||
377
+ previousRef.current === null ||
378
+ previousRef.current === "";
370
379
  previousRef.current = organizationId;
380
+ // First-resolve: nothing to invalidate yet (queries either haven't run
381
+ // or are running with the right key already). Real org switches (a → b)
382
+ // still hit the invalidate path below.
383
+ if (wasEmpty)
384
+ return;
371
385
  queryClient.invalidateQueries();
372
386
  }, [organizationId, queryClient]);
373
387
  }
@@ -473,7 +487,7 @@ function SidebarTrigger({ className }) {
473
487
  * Provides a beautiful gradient background that can be customized.
474
488
  */
475
489
  function HeaderBackground({ className }) {
476
- return (jsxRuntime.jsx("div", { className: erpTheme.cn("absolute top-0 left-0 w-full h-[144px] rounded-br-xl", "bg-gradient-to-r from-[#E4535E] to-[#831015]", className) }));
490
+ return (jsxRuntime.jsx("div", { className: erpTheme.cn("absolute inset-0 rounded-br-xl", "bg-gradient-to-r from-[#E4535E] to-[#831015]", className) }));
477
491
  }
478
492
 
479
493
  const useSidebarToggle = zustand.create(middleware.persist((set, get) => ({
@@ -716,11 +730,11 @@ function AppBreadcrumb({ labels = {}, homeLabel = "แดชบอร์ด", ro
716
730
  if (segments.length === 0) {
717
731
  return jsxRuntime.jsx("h1", { className: "text-xl font-semibold", children: homeLabel });
718
732
  }
719
- return (jsxRuntime.jsx(erpTheme.Breadcrumb, { children: jsxRuntime.jsxs(erpTheme.BreadcrumbList, { children: [jsxRuntime.jsx(erpTheme.BreadcrumbItem, { className: "hidden md:block", children: jsxRuntime.jsx(erpTheme.BreadcrumbLink, { asChild: true, children: jsxRuntime.jsx(Link, { href: "/", className: "font-thai text-12[px] xl:text-base font-normal text-white/80 hover:text-white transition-colors", children: rootLabel }) }) }), segments.map((segment, index) => {
733
+ return (jsxRuntime.jsx(erpTheme.Breadcrumb, { children: jsxRuntime.jsxs(erpTheme.BreadcrumbList, { children: [jsxRuntime.jsx(erpTheme.BreadcrumbItem, { className: "hidden md:block", children: jsxRuntime.jsx(erpTheme.BreadcrumbLink, { asChild: true, children: jsxRuntime.jsx(Link, { href: "/", className: "font-thai text-[14px] font-normal text-white/80 hover:text-white transition-colors", children: rootLabel }) }) }), segments.map((segment, index) => {
720
734
  const href = "/" + segments.slice(0, index + 1).join("/");
721
735
  const isLast = index === segments.length - 1;
722
736
  const label = labels[segment] || segment;
723
- return (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx(erpTheme.BreadcrumbSeparator, { className: "hidden md:block text-white/80", children: jsxRuntime.jsx(lucideReact.ChevronRight, { strokeWidth: 2, className: "h-4 w-4" }) }), jsxRuntime.jsx(erpTheme.BreadcrumbItem, { children: isLast ? (jsxRuntime.jsx(erpTheme.BreadcrumbPage, { className: "font-thai text-[12px] md:text-[10px] lg:text-base font-bold text-white leading-none", children: decodeURIComponent(label) })) : (jsxRuntime.jsx(erpTheme.BreadcrumbLink, { asChild: true, children: jsxRuntime.jsx(Link, { href: href, className: "font-thai text-[11px] md:text-[11px] lg:text-base font-normal text-white/80 hover:text-white transition-colors leading-none", children: decodeURIComponent(label) }) })) })] }, `${segment}-${index}`));
737
+ return (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx(erpTheme.BreadcrumbSeparator, { className: "hidden md:block text-white/80", children: jsxRuntime.jsx(lucideReact.ChevronRight, { strokeWidth: 2, className: "h-4 w-4" }) }), jsxRuntime.jsx(erpTheme.BreadcrumbItem, { children: isLast ? (jsxRuntime.jsx(erpTheme.BreadcrumbPage, { className: "font-thai text-[14px] font-bold text-white/95 leading-none", children: decodeURIComponent(label) })) : (jsxRuntime.jsx(erpTheme.BreadcrumbLink, { asChild: true, children: jsxRuntime.jsx(Link, { href: href, className: "font-thai text-[14px] font-normal text-white/80 hover:text-white transition-colors leading-none", children: decodeURIComponent(label) }) })) })] }, `${segment}-${index}`));
724
738
  })] }) }));
725
739
  }
726
740
 
@@ -1050,7 +1064,7 @@ function AppLayoutShell({ children, sidebar, loadingComponent, breadcrumb, permi
1050
1064
  const contentMargin = open && !isSidebarModalLayout ? "ml-[21.5rem]" : "";
1051
1065
  const needsLeftGutter = !(open && !isSidebarModalLayout);
1052
1066
  const wrap = permissionProvider ?? ((c) => c);
1053
- return (jsxRuntime.jsxs("div", { className: "flex min-h-screen w-full bg-background", children: [open && (jsxRuntime.jsx("div", { className: "fixed left-0 top-0 z-50 h-screen", children: sidebar })), open && isSidebarModalLayout && (jsxRuntime.jsx("button", { type: "button", "aria-label": "\u0E1B\u0E34\u0E14\u0E40\u0E21\u0E19\u0E39", className: "fixed inset-0 z-40 bg-black/50", onClick: () => setOpen(false) })), jsxRuntime.jsx("div", { className: cx("relative flex min-w-0 flex-1 flex-col transition-all", contentMargin), children: jsxRuntime.jsxs("main", { className: "flex flex-1 flex-col min-h-screen gap-6", children: [jsxRuntime.jsxs("div", { className: "sticky top-0 z-30 shrink-0 w-full", children: [jsxRuntime.jsx(HeaderBackground, {}), jsxRuntime.jsxs("header", { className: "relative shrink-0 gap-2 py-4 h-auto min-h-[100px] sm:h-[144px] w-full z-10", children: [jsxRuntime.jsxs("div", { className: "flex w-full items-center gap-2 px-3 sm:px-4 lg:px-6", children: [jsxRuntime.jsx(SidebarTrigger, { className: "shrink-0 text-white hover:bg-white/10" }), jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: breadcrumb })] }), jsxRuntime.jsx("div", { id: "header-title" })] })] }), jsxRuntime.jsx(React.Suspense, { fallback: jsxRuntime.jsx("div", { className: "relative z-10 min-h-[calc(100vh-8rem)]", children: jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: jsxRuntime.jsxs("div", { className: "space-y-4 text-center", children: [jsxRuntime.jsx("div", { className: "mx-auto h-8 w-8 animate-spin rounded-full border-b-2 border-primary" }), jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E42\u0E2B\u0E25\u0E14..." })] }) }) }), children: jsxRuntime.jsx("div", { className: cx("relative z-10 pr-6 pb-12", needsLeftGutter && "pl-6"), children: wrap(children) }, `org-${organizationId ?? "no-org"}`) })] }) })] }));
1067
+ return (jsxRuntime.jsxs("div", { className: "flex min-h-screen w-full bg-background", children: [open && (jsxRuntime.jsx("div", { className: "fixed left-0 top-0 z-50 h-screen", children: sidebar })), open && isSidebarModalLayout && (jsxRuntime.jsx("button", { type: "button", "aria-label": "\u0E1B\u0E34\u0E14\u0E40\u0E21\u0E19\u0E39", className: "fixed inset-0 z-40 bg-black/50", onClick: () => setOpen(false) })), jsxRuntime.jsx("div", { className: cx("relative flex min-w-0 flex-1 flex-col transition-all", contentMargin), children: jsxRuntime.jsxs("main", { className: "flex flex-1 flex-col min-h-screen gap-4", children: [jsxRuntime.jsxs("div", { className: "sticky top-0 z-30 shrink-0 w-full", children: [jsxRuntime.jsx(HeaderBackground, {}), jsxRuntime.jsxs("header", { className: "relative shrink-0 gap-2 py-4 h-auto min-h-[123.5px] w-full z-10", children: [jsxRuntime.jsxs("div", { className: "flex w-full items-center gap-2 px-3 sm:px-4 lg:px-6", children: [jsxRuntime.jsx(SidebarTrigger, { className: "shrink-0 text-white hover:bg-white/10" }), jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: breadcrumb })] }), jsxRuntime.jsx("div", { id: "header-title" })] })] }), jsxRuntime.jsx(React.Suspense, { fallback: jsxRuntime.jsx("div", { className: "relative z-10 min-h-[calc(100vh-8rem)]", children: jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: jsxRuntime.jsxs("div", { className: "space-y-4 text-center", children: [jsxRuntime.jsx("div", { className: "mx-auto h-8 w-8 animate-spin rounded-full border-b-2 border-primary" }), jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E42\u0E2B\u0E25\u0E14..." })] }) }) }), children: jsxRuntime.jsx("div", { className: cx("relative z-10 pr-6 pb-12", needsLeftGutter && "pl-6"), children: wrap(children) }, `org-${organizationId ?? "no-org"}`) })] }) })] }));
1054
1068
  }
1055
1069
  /** Local tiny classnames helper — avoids pulling clsx/tailwind-merge into
1056
1070
  * the shell just for the layout file. Falsy values are skipped. */