@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/index.js CHANGED
@@ -787,6 +787,7 @@ function NavUser({ organization, avatarSrc, profileHref, selectOrganizationHref
787
787
  const [isOpen, setIsOpen] = React.useState(false);
788
788
  const [showThemeMenu, setShowThemeMenu] = React.useState(false);
789
789
  const [showLanguageMenu, setShowLanguageMenu] = React.useState(false);
790
+ const [showAppsMenu, setShowAppsMenu] = React.useState(false);
790
791
  const buttonRef = React.useRef(null);
791
792
  const [position, setPosition] = React.useState({ top: 0, left: 0 });
792
793
  const user = session?.user
@@ -879,9 +880,10 @@ function NavUser({ organization, avatarSrc, profileHref, selectOrganizationHref
879
880
  // sidebar; drop back to the generic icon's empty slot.
880
881
  onError: e => {
881
882
  e.currentTarget.style.display = "none";
882
- } })) : (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: [visibleSystemLinks.length > 0 ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [visibleSystemLinks.map(link => (jsxRuntime.jsxs("button", { type: "button", onClick: () => handleSystemLink(link.href), 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: [link.icon ?? jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-4 w-4" }), jsxRuntime.jsx("span", { className: "flex-1 text-left", children: link.label })] }, `${link.label}:${link.href}`))), jsxRuntime.jsx("div", { className: "my-1 border-t border-sidebar-border" })] })) : null, jsxRuntime.jsxs("div", { className: "relative", children: [jsxRuntime.jsxs("button", { onClick: () => {
883
+ } })) : (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: () => {
883
884
  setShowThemeMenu(!showThemeMenu);
884
885
  setShowLanguageMenu(false);
886
+ setShowAppsMenu(false);
885
887
  }, 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: [
886
888
  { key: "light", label: "สว่าง", Icon: lucideReact.Sun },
887
889
  { key: "dark", label: "มืด", Icon: lucideReact.Moon },
@@ -889,12 +891,17 @@ function NavUser({ organization, avatarSrc, profileHref, selectOrganizationHref
889
891
  ].map(({ key, label, Icon }) => (jsxRuntime.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: [jsxRuntime.jsx(Icon, { className: "h-4 w-4" }), jsxRuntime.jsx("span", { className: "flex-1 text-left", children: label }), theme === key && (jsxRuntime.jsx("div", { className: "h-2 w-2 rounded-full bg-primary" }))] }, key))) }))] }), showLanguageSwitch && (jsxRuntime.jsxs("div", { className: "relative", children: [jsxRuntime.jsxs("button", { onClick: () => {
890
892
  setShowLanguageMenu(!showLanguageMenu);
891
893
  setShowThemeMenu(false);
894
+ setShowAppsMenu(false);
892
895
  }, 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.Globe, { className: "h-4 w-4" }), jsxRuntime.jsx("span", { className: "flex-1 text-left", children: "\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E20\u0E32\u0E29\u0E32" }), jsxRuntime.jsx(lucideReact.ChevronUp, { className: `h-4 w-4 transition-transform ${showLanguageMenu ? "rotate-180" : ""}` })] }), showLanguageMenu && (jsxRuntime.jsx("div", { className: "mt-1 ml-4 space-y-1", children: [
893
896
  { code: "th", label: "ไทย" },
894
897
  { code: "en", label: "English" },
895
898
  { code: "zh", label: "中文" },
896
899
  { code: "ja", label: "日本語" },
897
- ].map(({ code, label }) => (jsxRuntime.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: [jsxRuntime.jsx("span", { className: "flex-1 text-left", children: label }), organization?.language === code && (jsxRuntime.jsx("div", { className: "h-2 w-2 rounded-full bg-primary" }))] }, code))) }))] })), profileHref && (jsxRuntime.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: [jsxRuntime.jsx(lucideReact.User, { className: "h-4 w-4" }), jsxRuntime.jsx("span", { className: "flex-1 text-left", children: "\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25\u0E2A\u0E48\u0E27\u0E19\u0E15\u0E31\u0E27" })] })), showSelectOrganization && (jsxRuntime.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: [jsxRuntime.jsx(lucideReact.Building2, { className: "h-4 w-4" }), jsxRuntime.jsx("span", { className: "flex-1 text-left", children: "\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E18\u0E38\u0E23\u0E01\u0E34\u0E08" })] })), jsxRuntime.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 ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin" }), jsxRuntime.jsx("span", { className: "flex-1 text-left", children: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E2D\u0E2D\u0E01\u0E08\u0E32\u0E01\u0E23\u0E30\u0E1A\u0E1A..." })] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(lucideReact.LogOut, { className: "h-4 w-4" }), jsxRuntime.jsx("span", { className: "flex-1 text-left", children: "\u0E2D\u0E2D\u0E01\u0E08\u0E32\u0E01\u0E23\u0E30\u0E1A\u0E1A" })] })) })] })] })) : null;
900
+ ].map(({ code, label }) => (jsxRuntime.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: [jsxRuntime.jsx("span", { className: "flex-1 text-left", children: label }), organization?.language === code && (jsxRuntime.jsx("div", { className: "h-2 w-2 rounded-full bg-primary" }))] }, code))) }))] })), profileHref && (jsxRuntime.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: [jsxRuntime.jsx(lucideReact.User, { className: "h-4 w-4" }), jsxRuntime.jsx("span", { className: "flex-1 text-left", children: "\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25\u0E2A\u0E48\u0E27\u0E19\u0E15\u0E31\u0E27" })] })), showSelectOrganization && (jsxRuntime.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: [jsxRuntime.jsx(lucideReact.Building2, { className: "h-4 w-4" }), jsxRuntime.jsx("span", { className: "flex-1 text-left", children: "\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E18\u0E38\u0E23\u0E01\u0E34\u0E08" })] })), visibleSystemLinks.length > 0 && (jsxRuntime.jsxs("div", { className: "relative", children: [jsxRuntime.jsxs("button", { onClick: () => {
901
+ setShowAppsMenu(!showAppsMenu);
902
+ setShowThemeMenu(false);
903
+ setShowLanguageMenu(false);
904
+ }, 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.LayoutGrid, { className: "h-4 w-4" }), jsxRuntime.jsx("span", { className: "flex-1 text-left", children: "\u0E41\u0E2D\u0E1B\u0E1E\u0E25\u0E34\u0E40\u0E04\u0E0A\u0E31\u0E19" }), jsxRuntime.jsx(lucideReact.ChevronUp, { className: `h-4 w-4 transition-transform ${showAppsMenu ? "rotate-180" : ""}` })] }), showAppsMenu && (jsxRuntime.jsx("div", { className: "mt-1 ml-4 space-y-1", children: visibleSystemLinks.map(link => (jsxRuntime.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 ?? jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-4 w-4" }), jsxRuntime.jsx("span", { className: "flex-1 text-left", children: link.label })] }, `${link.label}:${link.href}`))) }))] })), jsxRuntime.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 ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin" }), jsxRuntime.jsx("span", { className: "flex-1 text-left", children: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E2D\u0E2D\u0E01\u0E08\u0E32\u0E01\u0E23\u0E30\u0E1A\u0E1A..." })] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(lucideReact.LogOut, { className: "h-4 w-4" }), jsxRuntime.jsx("span", { className: "flex-1 text-left", children: "\u0E2D\u0E2D\u0E01\u0E08\u0E32\u0E01\u0E23\u0E30\u0E1A\u0E1A" })] })) })] })] })) : null;
898
905
  return (jsxRuntime.jsx("div", { className: "p-2", children: jsxRuntime.jsxs("div", { className: "relative", children: [jsxRuntime.jsxs("button", { ref: buttonRef, onClick: () => setIsOpen(!isOpen), className: "flex w-full items-center gap-2 p-2 rounded-md transition-colors", children: [jsxRuntime.jsxs(erpTheme.Avatar, { className: "h-8 w-8 rounded-lg", children: [user.avatar ? (jsxRuntime.jsx(erpTheme.AvatarImage, { src: user.avatar, alt: user.name })) : null, jsxRuntime.jsx(erpTheme.AvatarFallback, { className: "rounded-lg bg-primary text-primary-foreground w-8 h-8", children: getInitials(user.name) })] }), jsxRuntime.jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [jsxRuntime.jsx("span", { className: "truncate font-medium", title: user.name, children: user.name }), jsxRuntime.jsx("span", { className: "truncate text-xs text-sidebar-foreground/70", title: user.email, children: user.email })] }), jsxRuntime.jsx(lucideReact.ChevronUp, { className: `ml-auto size-4 transition-transform ${isOpen ? "rotate-180" : ""}` })] }), typeof window !== "undefined" &&
899
906
  reactDom.createPortal(dropdownContent, document.body)] }) }));
900
907
  }
@@ -1186,7 +1193,13 @@ function cx(...parts) {
1186
1193
  * an illustration, a 403 headline, the page-specific reason, and recovery
1187
1194
  * actions.
1188
1195
  */
1189
- function AccessDenied({ title = "ขออภัย, คุณไม่มีสิทธิ์เข้าถึงหน้านี้ (403)", message = "คุณไม่มีสิทธิ์เข้าถึงหน้านี้ ขออภัยในความไม่สะดวก", homeHref = "/", homeLabel = "กลับไปหน้าหลัก", supportHref, supportLabel = "ติดต่อฝ่ายสนับสนุน", fullScreen = true, className, }) {
1196
+ function AccessDenied({ title = "ขออภัย, คุณไม่มีสิทธิ์เข้าถึงหน้านี้ (403)", message = "คุณไม่มีสิทธิ์เข้าถึงหน้านี้ ขออภัยในความไม่สะดวก", homeHref, homeLabel = "กลับไปหน้าหลัก", supportHref, supportLabel = "ติดต่อฝ่ายสนับสนุน", fullScreen = true, className, }) {
1197
+ // "/" is not the home page inside an app — it bounces to organization
1198
+ // selection, so the button read "กลับไปหน้าหลัก" and dropped the user into a
1199
+ // picker for the org they were already in. Send them to that org's home.
1200
+ const params = navigation.useParams();
1201
+ const code = typeof params?.code === "string" ? params.code : "";
1202
+ const homeTarget = homeHref ?? (code ? `/${code}` : "/");
1190
1203
  const go = (href) => {
1191
1204
  if (typeof window !== "undefined")
1192
1205
  window.location.href = href;
@@ -1198,7 +1211,7 @@ function AccessDenied({ title = "ขออภัย, คุณไม่มีส
1198
1211
  ]
1199
1212
  .filter(Boolean)
1200
1213
  .join(" ");
1201
- return (jsxRuntime.jsx("div", { className: wrapperClass, children: jsxRuntime.jsxs("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: [jsxRuntime.jsx(lucideReact.Sparkles, { className: "pointer-events-none absolute right-6 top-6 h-5 w-5 text-primary/40" }), jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-8 text-center sm:flex-row sm:text-left", children: [jsxRuntime.jsxs("div", { className: "relative shrink-0", children: [jsxRuntime.jsx("div", { className: "absolute inset-0 rounded-full bg-destructive/20 blur-2xl" }), jsxRuntime.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: jsxRuntime.jsx("div", { className: "flex h-16 w-16 items-center justify-center rounded-full border border-destructive/40 bg-destructive/10", children: jsxRuntime.jsx(lucideReact.Ban, { className: "h-8 w-8 text-destructive", strokeWidth: 2.5 }) }) })] }), jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [jsxRuntime.jsx("h1", { className: "text-xl font-bold text-foreground sm:text-2xl", children: title }), message ? (jsxRuntime.jsx("p", { className: "mt-3 whitespace-pre-line text-sm leading-relaxed text-muted-foreground sm:text-base", children: message })) : null, jsxRuntime.jsxs("div", { className: "mt-6 flex flex-col gap-3 sm:flex-row", children: [jsxRuntime.jsxs(erpTheme.Button, { type: "button", onClick: () => go(homeHref), className: "w-full sm:w-auto", children: [jsxRuntime.jsx(lucideReact.Home, { className: "mr-2 h-4 w-4" }), homeLabel] }), supportHref ? (jsxRuntime.jsxs(erpTheme.Button, { type: "button", variant: "outline", onClick: () => go(supportHref), className: "w-full sm:w-auto", children: [jsxRuntime.jsx(lucideReact.Headset, { className: "mr-2 h-4 w-4" }), supportLabel] })) : null] })] })] })] }) }));
1214
+ return (jsxRuntime.jsx("div", { className: wrapperClass, children: jsxRuntime.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: jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-8 text-center sm:flex-row sm:text-left", children: [jsxRuntime.jsxs("div", { className: "relative shrink-0", children: [jsxRuntime.jsx("div", { className: "absolute inset-0 rounded-full bg-destructive/20 blur-2xl" }), jsxRuntime.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: jsxRuntime.jsx("div", { className: "flex h-16 w-16 items-center justify-center rounded-full border border-destructive/40 bg-destructive/10", children: jsxRuntime.jsx(lucideReact.Ban, { className: "h-8 w-8 text-destructive", strokeWidth: 2.5 }) }) })] }), jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [jsxRuntime.jsx("h1", { className: "text-xl font-bold text-foreground sm:text-2xl", children: title }), message ? (jsxRuntime.jsx("p", { className: "mt-3 whitespace-pre-line text-sm leading-relaxed text-muted-foreground sm:text-base", children: message })) : null, jsxRuntime.jsxs("div", { className: "mt-6 flex flex-col gap-3 sm:flex-row", children: [jsxRuntime.jsxs(erpTheme.Button, { type: "button", onClick: () => go(homeTarget), className: "w-full sm:w-auto", children: [jsxRuntime.jsx(lucideReact.Home, { className: "mr-2 h-4 w-4" }), homeLabel] }), supportHref ? (jsxRuntime.jsxs(erpTheme.Button, { type: "button", variant: "outline", onClick: () => go(supportHref), className: "w-full sm:w-auto", children: [jsxRuntime.jsx(lucideReact.Headset, { className: "mr-2 h-4 w-4" }), supportLabel] })) : null] })] })] }) }) }));
1202
1215
  }
1203
1216
 
1204
1217
  const shellClassName = "flex min-w-0 flex-1 flex-col gap-6 overflow-x-hidden";