@eintrek/erp-shell 0.1.28 → 0.1.30
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/auth/access-denied.d.ts +4 -1
- package/dist/index.esm.js +18 -5
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +17 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -3,7 +3,10 @@ export interface AccessDeniedProps {
|
|
|
3
3
|
title?: string;
|
|
4
4
|
/** Secondary explanation — pass the page-specific denied reason here. */
|
|
5
5
|
message?: string;
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Where "กลับไปหน้าหลัก" navigates. Defaults to the current organization's
|
|
8
|
+
* home (`/{code}`), falling back to "/" outside an org route.
|
|
9
|
+
*/
|
|
7
10
|
homeHref?: string;
|
|
8
11
|
homeLabel?: string;
|
|
9
12
|
/** When set, shows the "ติดต่อฝ่ายสนับสนุน" button (URL or mailto:). */
|
package/dist/index.esm.js
CHANGED
|
@@ -5,7 +5,7 @@ import { useSession, signOut } from 'next-auth/react';
|
|
|
5
5
|
import { useQueryClient, MutationCache, QueryCache, QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
6
6
|
import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
|
|
7
7
|
import { cn, Button, Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbSeparator, BreadcrumbPage, Avatar, AvatarImage, AvatarFallback, Collapsible, CollapsibleTrigger, CollapsibleContent, Badge, Skeleton, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuItem, DropdownMenuSeparator, Card, CardHeader, CardContent } from '@eintrek/erp-theme';
|
|
8
|
-
import { PanelLeftClose, Menu, ChevronRight, Building2,
|
|
8
|
+
import { PanelLeftClose, Menu, ChevronRight, Building2, Palette, ChevronUp, Sun, Moon, Monitor, Globe, User, LayoutGrid, ExternalLink, Loader2, LogOut, ChevronDown, ChevronsUpDown, Plus, Ban, Home, Headset } from 'lucide-react';
|
|
9
9
|
import { create } from 'zustand';
|
|
10
10
|
import { persist, createJSONStorage } from 'zustand/middleware';
|
|
11
11
|
import { useRouter, usePathname, useParams } from 'next/navigation';
|
|
@@ -768,6 +768,7 @@ function NavUser({ organization, avatarSrc, profileHref, selectOrganizationHref
|
|
|
768
768
|
const [isOpen, setIsOpen] = useState(false);
|
|
769
769
|
const [showThemeMenu, setShowThemeMenu] = useState(false);
|
|
770
770
|
const [showLanguageMenu, setShowLanguageMenu] = useState(false);
|
|
771
|
+
const [showAppsMenu, setShowAppsMenu] = useState(false);
|
|
771
772
|
const buttonRef = useRef(null);
|
|
772
773
|
const [position, setPosition] = useState({ top: 0, left: 0 });
|
|
773
774
|
const user = session?.user
|
|
@@ -860,9 +861,10 @@ function NavUser({ organization, avatarSrc, profileHref, selectOrganizationHref
|
|
|
860
861
|
// sidebar; drop back to the generic icon's empty slot.
|
|
861
862
|
onError: e => {
|
|
862
863
|
e.currentTarget.style.display = "none";
|
|
863
|
-
} })) : (jsx(Building2, { className: "h-5 w-5 text-sidebar-foreground/70 flex-shrink-0" })), jsxs("div", { className: "flex-1 min-w-0", children: [jsx("div", { className: "font-medium text-sm sm:truncate", children: organization.name }), organization.description && (jsx("div", { className: "text-xs text-sidebar-foreground/70 truncate mt-0.5", children: organization.description }))] })] }) })), jsxs("div", { className: "p-2", children: [
|
|
864
|
+
} })) : (jsx(Building2, { className: "h-5 w-5 text-sidebar-foreground/70 flex-shrink-0" })), jsxs("div", { className: "flex-1 min-w-0", children: [jsx("div", { className: "font-medium text-sm sm:truncate", children: organization.name }), organization.description && (jsx("div", { className: "text-xs text-sidebar-foreground/70 truncate mt-0.5", children: organization.description }))] })] }) })), jsxs("div", { className: "p-2", children: [jsxs("div", { className: "relative", children: [jsxs("button", { onClick: () => {
|
|
864
865
|
setShowThemeMenu(!showThemeMenu);
|
|
865
866
|
setShowLanguageMenu(false);
|
|
867
|
+
setShowAppsMenu(false);
|
|
866
868
|
}, 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: [jsx(Palette, { className: "h-4 w-4" }), jsx("span", { className: "flex-1 text-left", children: "\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E18\u0E35\u0E21" }), jsx(ChevronUp, { className: `h-4 w-4 transition-transform ${showThemeMenu ? "rotate-180" : ""}` })] }), showThemeMenu && (jsx("div", { className: "mt-1 ml-4 space-y-1", children: [
|
|
867
869
|
{ key: "light", label: "สว่าง", Icon: Sun },
|
|
868
870
|
{ key: "dark", label: "มืด", Icon: Moon },
|
|
@@ -870,12 +872,17 @@ function NavUser({ organization, avatarSrc, profileHref, selectOrganizationHref
|
|
|
870
872
|
].map(({ key, label, Icon }) => (jsxs("button", { onClick: () => handleThemeChange(key), className: "flex w-full items-center gap-3 px-3 py-2 text-sm text-sidebar-foreground hover:bg-sidebar-accent rounded-md transition-colors", children: [jsx(Icon, { className: "h-4 w-4" }), jsx("span", { className: "flex-1 text-left", children: label }), theme === key && (jsx("div", { className: "h-2 w-2 rounded-full bg-primary" }))] }, key))) }))] }), showLanguageSwitch && (jsxs("div", { className: "relative", children: [jsxs("button", { onClick: () => {
|
|
871
873
|
setShowLanguageMenu(!showLanguageMenu);
|
|
872
874
|
setShowThemeMenu(false);
|
|
875
|
+
setShowAppsMenu(false);
|
|
873
876
|
}, 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: [jsx(Globe, { className: "h-4 w-4" }), jsx("span", { className: "flex-1 text-left", children: "\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E20\u0E32\u0E29\u0E32" }), jsx(ChevronUp, { className: `h-4 w-4 transition-transform ${showLanguageMenu ? "rotate-180" : ""}` })] }), showLanguageMenu && (jsx("div", { className: "mt-1 ml-4 space-y-1", children: [
|
|
874
877
|
{ code: "th", label: "ไทย" },
|
|
875
878
|
{ code: "en", label: "English" },
|
|
876
879
|
{ code: "zh", label: "中文" },
|
|
877
880
|
{ code: "ja", label: "日本語" },
|
|
878
|
-
].map(({ code, label }) => (jsxs("button", { onClick: () => handleLanguageChange(code), className: "flex w-full items-center gap-3 px-3 py-2 text-sm text-sidebar-foreground hover:bg-sidebar-accent rounded-md transition-colors", children: [jsx("span", { className: "flex-1 text-left", children: label }), organization?.language === code && (jsx("div", { className: "h-2 w-2 rounded-full bg-primary" }))] }, code))) }))] })), profileHref && (jsxs("button", { onClick: handleProfile, 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: [jsx(User, { className: "h-4 w-4" }), jsx("span", { className: "flex-1 text-left", children: "\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25\u0E2A\u0E48\u0E27\u0E19\u0E15\u0E31\u0E27" })] })), showSelectOrganization && (jsxs("button", { onClick: handleSelectOrganization, 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: [jsx(Building2, { className: "h-4 w-4" }), jsx("span", { className: "flex-1 text-left", children: "\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E18\u0E38\u0E23\u0E01\u0E34\u0E08" })] })),
|
|
881
|
+
].map(({ code, label }) => (jsxs("button", { onClick: () => handleLanguageChange(code), className: "flex w-full items-center gap-3 px-3 py-2 text-sm text-sidebar-foreground hover:bg-sidebar-accent rounded-md transition-colors", children: [jsx("span", { className: "flex-1 text-left", children: label }), organization?.language === code && (jsx("div", { className: "h-2 w-2 rounded-full bg-primary" }))] }, code))) }))] })), profileHref && (jsxs("button", { onClick: handleProfile, 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: [jsx(User, { className: "h-4 w-4" }), jsx("span", { className: "flex-1 text-left", children: "\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25\u0E2A\u0E48\u0E27\u0E19\u0E15\u0E31\u0E27" })] })), showSelectOrganization && (jsxs("button", { onClick: handleSelectOrganization, 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: [jsx(Building2, { className: "h-4 w-4" }), jsx("span", { className: "flex-1 text-left", children: "\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E18\u0E38\u0E23\u0E01\u0E34\u0E08" })] })), visibleSystemLinks.length > 0 && (jsxs("div", { className: "relative", children: [jsxs("button", { onClick: () => {
|
|
882
|
+
setShowAppsMenu(!showAppsMenu);
|
|
883
|
+
setShowThemeMenu(false);
|
|
884
|
+
setShowLanguageMenu(false);
|
|
885
|
+
}, 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: [jsx(LayoutGrid, { className: "h-4 w-4" }), jsx("span", { className: "flex-1 text-left", children: "\u0E41\u0E2D\u0E1B\u0E1E\u0E25\u0E34\u0E40\u0E04\u0E0A\u0E31\u0E19" }), jsx(ChevronUp, { className: `h-4 w-4 transition-transform ${showAppsMenu ? "rotate-180" : ""}` })] }), showAppsMenu && (jsx("div", { className: "mt-1 ml-4 space-y-1", children: visibleSystemLinks.map(link => (jsxs("button", { type: "button", onClick: () => handleSystemLink(link.href), className: "flex w-full items-center gap-3 px-3 py-2 text-sm text-sidebar-foreground hover:bg-sidebar-accent rounded-md transition-colors", children: [link.icon ?? jsx(ExternalLink, { className: "h-4 w-4" }), jsx("span", { className: "flex-1 text-left", children: link.label })] }, `${link.label}:${link.href}`))) }))] })), jsx("button", { onClick: handleSignOut, disabled: isSigningOut, 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 disabled:opacity-50 disabled:cursor-not-allowed mt-1", children: isSigningOut ? (jsxs(Fragment$1, { children: [jsx(Loader2, { className: "h-4 w-4 animate-spin" }), jsx("span", { className: "flex-1 text-left", children: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E2D\u0E2D\u0E01\u0E08\u0E32\u0E01\u0E23\u0E30\u0E1A\u0E1A..." })] })) : (jsxs(Fragment$1, { children: [jsx(LogOut, { className: "h-4 w-4" }), jsx("span", { className: "flex-1 text-left", children: "\u0E2D\u0E2D\u0E01\u0E08\u0E32\u0E01\u0E23\u0E30\u0E1A\u0E1A" })] })) })] })] })) : null;
|
|
879
886
|
return (jsx("div", { className: "p-2", children: jsxs("div", { className: "relative", children: [jsxs("button", { ref: buttonRef, onClick: () => setIsOpen(!isOpen), className: "flex w-full items-center gap-2 p-2 rounded-md transition-colors", children: [jsxs(Avatar, { className: "h-8 w-8 rounded-lg", children: [user.avatar ? (jsx(AvatarImage, { src: user.avatar, alt: user.name })) : null, jsx(AvatarFallback, { className: "rounded-lg bg-primary text-primary-foreground w-8 h-8", children: getInitials(user.name) })] }), jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [jsx("span", { className: "truncate font-medium", title: user.name, children: user.name }), jsx("span", { className: "truncate text-xs text-sidebar-foreground/70", title: user.email, children: user.email })] }), jsx(ChevronUp, { className: `ml-auto size-4 transition-transform ${isOpen ? "rotate-180" : ""}` })] }), typeof window !== "undefined" &&
|
|
880
887
|
createPortal(dropdownContent, document.body)] }) }));
|
|
881
888
|
}
|
|
@@ -1167,7 +1174,13 @@ function cx(...parts) {
|
|
|
1167
1174
|
* an illustration, a 403 headline, the page-specific reason, and recovery
|
|
1168
1175
|
* actions.
|
|
1169
1176
|
*/
|
|
1170
|
-
function AccessDenied({ title = "ขออภัย, คุณไม่มีสิทธิ์เข้าถึงหน้านี้ (403)", message = "คุณไม่มีสิทธิ์เข้าถึงหน้านี้ ขออภัยในความไม่สะดวก", homeHref
|
|
1177
|
+
function AccessDenied({ title = "ขออภัย, คุณไม่มีสิทธิ์เข้าถึงหน้านี้ (403)", message = "คุณไม่มีสิทธิ์เข้าถึงหน้านี้ ขออภัยในความไม่สะดวก", homeHref, homeLabel = "กลับไปหน้าหลัก", supportHref, supportLabel = "ติดต่อฝ่ายสนับสนุน", fullScreen = true, className, }) {
|
|
1178
|
+
// "/" is not the home page inside an app — it bounces to organization
|
|
1179
|
+
// selection, so the button read "กลับไปหน้าหลัก" and dropped the user into a
|
|
1180
|
+
// picker for the org they were already in. Send them to that org's home.
|
|
1181
|
+
const params = useParams();
|
|
1182
|
+
const code = typeof params?.code === "string" ? params.code : "";
|
|
1183
|
+
const homeTarget = homeHref ?? (code ? `/${code}` : "/");
|
|
1171
1184
|
const go = (href) => {
|
|
1172
1185
|
if (typeof window !== "undefined")
|
|
1173
1186
|
window.location.href = href;
|
|
@@ -1179,7 +1192,7 @@ function AccessDenied({ title = "ขออภัย, คุณไม่มีส
|
|
|
1179
1192
|
]
|
|
1180
1193
|
.filter(Boolean)
|
|
1181
1194
|
.join(" ");
|
|
1182
|
-
return (jsx("div", { className: wrapperClass, children:
|
|
1195
|
+
return (jsx("div", { className: wrapperClass, children: jsx("div", { className: "relative w-full max-w-3xl overflow-hidden rounded-2xl border border-border/60 bg-card/60 p-8 shadow-sm backdrop-blur sm:p-10", children: jsxs("div", { className: "flex flex-col items-center gap-8 text-center sm:flex-row sm:text-left", children: [jsxs("div", { className: "relative shrink-0", children: [jsx("div", { className: "absolute inset-0 rounded-full bg-destructive/20 blur-2xl" }), jsx("div", { className: "relative flex h-28 w-28 items-center justify-center rounded-3xl border border-border/60 bg-gradient-to-br from-muted/40 to-background shadow-inner", children: jsx("div", { className: "flex h-16 w-16 items-center justify-center rounded-full border border-destructive/40 bg-destructive/10", children: jsx(Ban, { className: "h-8 w-8 text-destructive", strokeWidth: 2.5 }) }) })] }), jsxs("div", { className: "min-w-0 flex-1", children: [jsx("h1", { className: "text-xl font-bold text-foreground sm:text-2xl", children: title }), message ? (jsx("p", { className: "mt-3 whitespace-pre-line text-sm leading-relaxed text-muted-foreground sm:text-base", children: message })) : null, jsxs("div", { className: "mt-6 flex flex-col gap-3 sm:flex-row", children: [jsxs(Button, { type: "button", onClick: () => go(homeTarget), className: "w-full sm:w-auto", children: [jsx(Home, { className: "mr-2 h-4 w-4" }), homeLabel] }), supportHref ? (jsxs(Button, { type: "button", variant: "outline", onClick: () => go(supportHref), className: "w-full sm:w-auto", children: [jsx(Headset, { className: "mr-2 h-4 w-4" }), supportLabel] })) : null] })] })] }) }) }));
|
|
1183
1196
|
}
|
|
1184
1197
|
|
|
1185
1198
|
const shellClassName = "flex min-w-0 flex-1 flex-col gap-6 overflow-x-hidden";
|