@eintrek/erp-shell 0.1.15 → 0.1.17
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.esm.js +24 -6
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +24 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -940,9 +940,9 @@ function OrganizationSwitcher({ activeOrganization, isContextLoading = false, or
|
|
|
940
940
|
return (jsx(SidebarMenu, { className: className, children: jsx(SidebarMenuItem, { children: jsxs("div", { className: "flex items-center gap-2 p-2", children: [jsx(Skeleton, { className: "size-8 rounded-lg" }), jsx(Skeleton, { className: "h-4 w-24" })] }) }) }));
|
|
941
941
|
}
|
|
942
942
|
if (organizations.length <= 1) {
|
|
943
|
-
return (jsx(SidebarMenu, { className: className, children: jsx(SidebarMenuItem, { children: jsxs("div", { className: "flex items-center gap-2 p-2", children: [jsx("div", { className: "flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground", children: jsx(Building2, { className: "size-4" }) }), jsx("span", { className: "truncate font-semibold text-sm", children: activeOrganization?.name || "ไม่มีองค์กร" })] }) }) }));
|
|
943
|
+
return (jsx(SidebarMenu, { className: className, children: jsx(SidebarMenuItem, { children: jsxs("div", { className: "flex items-center gap-2 p-2", children: [jsx("div", { className: "flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground", children: jsx(Building2, { className: "size-4" }) }), jsx("span", { className: "truncate font-semibold text-sm min-w-0 flex-1", children: activeOrganization?.name || "ไม่มีองค์กร" })] }) }) }));
|
|
944
944
|
}
|
|
945
|
-
return (jsx(SidebarMenu, { className: className, children: jsx(SidebarMenuItem, { children: jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsxs(SidebarMenuButton, { size: "lg", className: "data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground", children: [jsx("div", { className: "flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground", children: jsx(Building2, { className: "size-4" }) }), jsx("span", { className: "truncate font-semibold text-sm flex-1 text-left", children: activeOrganization?.name || "เลือกองค์กร" }), isPending ? (jsx(Loader2, { className: "ml-auto size-4 animate-spin" })) : (jsx(ChevronsUpDown, { className: "ml-auto size-4" }))] }) }), jsxs(DropdownMenuContent, { className: "w-[--radix-dropdown-menu-trigger-width] min-w-56 rounded-lg", align: "start", side: isMobile ? "bottom" : "right", sideOffset: 4, children: [jsx(DropdownMenuLabel, { className: "text-xs text-muted-foreground", children: "\u0E2D\u0E07\u0E04\u0E4C\u0E01\u0E23" }), organizations.map(org => (jsxs(DropdownMenuItem, { onClick: () => handleOrganizationChange(org), disabled: isPending, className: cn("gap-2 p-2 cursor-pointer", String(activeOrganization?.id) === String(org.id) &&
|
|
945
|
+
return (jsx(SidebarMenu, { className: className, children: jsx(SidebarMenuItem, { children: jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsxs(SidebarMenuButton, { size: "lg", className: "data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground", children: [jsx("div", { className: "flex aspect-square size-8 shrink-0 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground", children: jsx(Building2, { className: "size-4" }) }), jsx("span", { className: "truncate font-semibold text-sm flex-1 min-w-0 text-left", children: activeOrganization?.name || "เลือกองค์กร" }), isPending ? (jsx(Loader2, { className: "ml-auto size-4 animate-spin" })) : (jsx(ChevronsUpDown, { className: "ml-auto size-4" }))] }) }), jsxs(DropdownMenuContent, { className: "w-[--radix-dropdown-menu-trigger-width] min-w-56 rounded-lg", align: "start", side: isMobile ? "bottom" : "right", sideOffset: 4, children: [jsx(DropdownMenuLabel, { className: "text-xs text-muted-foreground", children: "\u0E2D\u0E07\u0E04\u0E4C\u0E01\u0E23" }), organizations.map(org => (jsxs(DropdownMenuItem, { onClick: () => handleOrganizationChange(org), disabled: isPending, className: cn("gap-2 p-2 cursor-pointer", String(activeOrganization?.id) === String(org.id) &&
|
|
946
946
|
"bg-accent"), children: [jsx("div", { className: "flex size-6 items-center justify-center rounded-md border", children: jsx(Building2, { className: "size-3.5 shrink-0" }) }), jsx("span", { className: "truncate", children: org.name })] }, org.id))), jsx(DropdownMenuSeparator, {}), jsxs(DropdownMenuItem, { className: "gap-2 p-2 cursor-pointer", onClick: () => router.push(registerOrganizationHref), children: [jsx("div", { className: "flex size-6 items-center justify-center rounded-md border bg-transparent", children: jsx(Plus, { className: "size-4" }) }), jsx("span", { className: "text-muted-foreground font-medium", children: "\u0E40\u0E1E\u0E34\u0E48\u0E21\u0E2D\u0E07\u0E04\u0E4C\u0E01\u0E23" })] })] })] }) }) }));
|
|
947
947
|
}
|
|
948
948
|
|
|
@@ -980,6 +980,16 @@ function AppLayoutShell({ children, sidebar, loadingComponent, breadcrumb, permi
|
|
|
980
980
|
const params = useParams();
|
|
981
981
|
const code = params?.code;
|
|
982
982
|
const extendedSession = session;
|
|
983
|
+
// Track once-authenticated so a transient accessToken drop during the
|
|
984
|
+
// periodic session refresh (SessionRefreshTrigger every 4 min) doesn't
|
|
985
|
+
// blank the whole page. The initial-load gate below still handles cold
|
|
986
|
+
// start; once we've seen a real token we render children optimistically
|
|
987
|
+
// and let the API layer surface a real 401 if the token actually died.
|
|
988
|
+
const hasSeenAccessTokenRef = useRef(false);
|
|
989
|
+
useEffect(() => {
|
|
990
|
+
if (extendedSession?.accessToken)
|
|
991
|
+
hasSeenAccessTokenRef.current = true;
|
|
992
|
+
}, [extendedSession?.accessToken]);
|
|
983
993
|
// Find the org from the URL `[code]` so we can detect a context mismatch
|
|
984
994
|
// (the user bookmarked a different org than the cookie remembers).
|
|
985
995
|
const orgFromCode = React.useMemo(() => {
|
|
@@ -1022,9 +1032,15 @@ function AppLayoutShell({ children, sidebar, loadingComponent, breadcrumb, permi
|
|
|
1022
1032
|
if (status === "loading" && !session) {
|
|
1023
1033
|
return jsx(Fragment$1, { children: loadingComponent });
|
|
1024
1034
|
}
|
|
1025
|
-
// Session loaded but no accessToken
|
|
1026
|
-
//
|
|
1027
|
-
|
|
1035
|
+
// Session loaded but no accessToken AND we've never seen one → real auth
|
|
1036
|
+
// failure (token refresh gave nothing back on cold start), bounce through
|
|
1037
|
+
// signin. If we HAVE seen one before, the drop is almost certainly the
|
|
1038
|
+
// in-flight periodic refresh (SessionRefreshTrigger). Don't redirect on
|
|
1039
|
+
// that transient — the JWT callback will settle in a moment and API
|
|
1040
|
+
// calls will keep working with the still-valid cookie.
|
|
1041
|
+
if (status === "authenticated" &&
|
|
1042
|
+
!extendedSession?.accessToken &&
|
|
1043
|
+
!hasSeenAccessTokenRef.current) {
|
|
1028
1044
|
if (typeof window !== "undefined") {
|
|
1029
1045
|
const url = new URL(signInUrl, window.location.origin);
|
|
1030
1046
|
url.searchParams.set("error", "NoAccessToken");
|
|
@@ -1033,7 +1049,9 @@ function AppLayoutShell({ children, sidebar, loadingComponent, breadcrumb, permi
|
|
|
1033
1049
|
}
|
|
1034
1050
|
return jsx(Fragment$1, { children: loadingComponent });
|
|
1035
1051
|
}
|
|
1036
|
-
|
|
1052
|
+
// Only blank the page when we've never seen a token — otherwise the
|
|
1053
|
+
// periodic session refresh would visibly flash the loader every 4 min.
|
|
1054
|
+
if (!extendedSession?.accessToken && !hasSeenAccessTokenRef.current) {
|
|
1037
1055
|
return jsx(Fragment$1, { children: loadingComponent });
|
|
1038
1056
|
}
|
|
1039
1057
|
if (!code) {
|