@eintrek/erp-shell 0.1.49 → 0.1.51

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
@@ -977,18 +977,35 @@ const PLAN_FEATURES = {
977
977
  MODULE_INVENTORY: "module.inventory",
978
978
  MODULE_PROJECT: "module.project",
979
979
  MODULE_SECRETARIAT: "module.secretariat",
980
+ /** AI pack (paid or trial): AI calls on AntNiti's key while credits remain. */
981
+ AI: "ai",
980
982
  };
981
- /** True when plan features include key (with legacy basic_accounting_hr alias). */
983
+ /** Keys the Accounx add-on carries with it (same alias as org_effective_features). */
984
+ const ACCOUNTING_SUB_KEYS = [
985
+ PLAN_FEATURES.MODULE_SALES,
986
+ PLAN_FEATURES.MODULE_PURCHASING,
987
+ PLAN_FEATURES.MODULE_SECRETARIAT,
988
+ ];
989
+ /**
990
+ * True when plan features include key. Aliases, mirroring the backend:
991
+ * legacy basic_accounting_hr → module.hr + module.accounting (+ its sub-keys);
992
+ * module.accounting → module.sales, module.purchasing, module.secretariat.
993
+ */
982
994
  function hasPlanFeature(features, feature) {
983
995
  if (!features?.length)
984
996
  return false;
985
997
  if (features.includes(feature))
986
998
  return true;
987
999
  if ((feature === PLAN_FEATURES.MODULE_HR ||
988
- feature === PLAN_FEATURES.MODULE_ACCOUNTING) &&
1000
+ feature === PLAN_FEATURES.MODULE_ACCOUNTING ||
1001
+ ACCOUNTING_SUB_KEYS.includes(feature)) &&
989
1002
  features.includes(PLAN_FEATURES.BASIC_ACCOUNTING_HR)) {
990
1003
  return true;
991
1004
  }
1005
+ if (ACCOUNTING_SUB_KEYS.includes(feature) &&
1006
+ features.includes(PLAN_FEATURES.MODULE_ACCOUNTING)) {
1007
+ return true;
1008
+ }
992
1009
  if (feature === PLAN_FEATURES.BASIC_ACCOUNTING_HR &&
993
1010
  features.includes(PLAN_FEATURES.MODULE_HR) &&
994
1011
  features.includes(PLAN_FEATURES.MODULE_ACCOUNTING)) {
@@ -1012,35 +1029,36 @@ const APPS = [
1012
1029
  id: "platform",
1013
1030
  label: "แพลตฟอร์ม",
1014
1031
  icon: jsxRuntime.jsx(lucideReact.Building2, { className: "h-4 w-4 shrink-0" }),
1015
- feature: null,
1032
+ features: null,
1016
1033
  baseUrl: () => normaliseBase(process.env.NEXT_PUBLIC_PLATFORM_URL, "https://platform.antniti.com"),
1017
1034
  },
1018
1035
  {
1019
1036
  id: "accounx",
1020
1037
  label: "Accounx",
1021
1038
  icon: jsxRuntime.jsx(lucideReact.Calculator, { className: "h-4 w-4 shrink-0" }),
1022
- feature: PLAN_FEATURES.MODULE_ACCOUNTING,
1039
+ features: [PLAN_FEATURES.MODULE_ACCOUNTING],
1023
1040
  baseUrl: () => normaliseBase(process.env.NEXT_PUBLIC_ACCOUNTING_URL, "https://accounx.antniti.com"),
1024
1041
  },
1025
1042
  {
1026
1043
  id: "invenx",
1027
1044
  label: "Invenx",
1028
1045
  icon: jsxRuntime.jsx(lucideReact.Warehouse, { className: "h-4 w-4 shrink-0" }),
1029
- feature: PLAN_FEATURES.MODULE_INVENTORY,
1046
+ features: [PLAN_FEATURES.MODULE_INVENTORY],
1030
1047
  baseUrl: () => normaliseBase(process.env.NEXT_PUBLIC_INVENX_URL, "https://invenx.antniti.com"),
1031
1048
  },
1032
1049
  {
1033
1050
  id: "plannex",
1034
1051
  label: "Plannex",
1035
1052
  icon: jsxRuntime.jsx(lucideReact.FolderKanban, { className: "h-4 w-4 shrink-0" }),
1036
- feature: PLAN_FEATURES.MODULE_PROJECT,
1053
+ // Tasks, day-logs and work records are free with HR; projects need the add-on.
1054
+ features: [PLAN_FEATURES.MODULE_HR, PLAN_FEATURES.MODULE_PROJECT],
1037
1055
  baseUrl: () => normaliseBase(process.env.NEXT_PUBLIC_PLANNEX_URL, "https://plannex.antniti.com"),
1038
1056
  },
1039
1057
  {
1040
1058
  id: "peoplx",
1041
1059
  label: "Peoplx",
1042
1060
  icon: jsxRuntime.jsx(lucideReact.Users, { className: "h-4 w-4 shrink-0" }),
1043
- feature: PLAN_FEATURES.MODULE_HR,
1061
+ features: [PLAN_FEATURES.MODULE_HR],
1044
1062
  baseUrl: () => normaliseBase(process.env.NEXT_PUBLIC_HR_URL, "https://peoplx.antniti.com"),
1045
1063
  },
1046
1064
  ];
@@ -1055,8 +1073,8 @@ function buildSystemLinks({ orgCode, activeApp, features, }) {
1055
1073
  if (!orgCode)
1056
1074
  return [];
1057
1075
  return APPS.filter(app => app.id === activeApp ||
1058
- app.feature === null ||
1059
- hasPlanFeature(features, app.feature)).map(app => ({
1076
+ app.features === null ||
1077
+ app.features.some(key => hasPlanFeature(features, key))).map(app => ({
1060
1078
  label: app.label,
1061
1079
  icon: app.icon,
1062
1080
  // Same-app link stays relative so it never leaves the current origin.
@@ -1090,7 +1108,7 @@ function samePage(pathname, url) {
1090
1108
  const strip = (p) => (p.length > 1 ? p.replace(/\/+$/, "") : p);
1091
1109
  return strip(pathname) === strip(url);
1092
1110
  }
1093
- function NavMain({ items, orgCode, closeOnNavigation = false, approvalCounts, chrome = "brand", }) {
1111
+ function NavMain({ items, orgCode, closeOnNavigation = false, approvalCounts, chrome = "brand", highlightActiveModule = false, }) {
1094
1112
  const workspace = chrome === "workspace";
1095
1113
  const params = navigation.useParams();
1096
1114
  const pathname = navigation.usePathname();
@@ -1122,8 +1140,9 @@ function NavMain({ items, orgCode, closeOnNavigation = false, approvalCounts, ch
1122
1140
  isPathActive(pathname, subPage.url)));
1123
1141
  // Parent only active when path matches its URL exactly AND no child
1124
1142
  // is active (so parent+child don't both light up).
1125
- const isItemActive = (workspace ? samePage(pathname, itemUrl) : pathname === itemUrl) &&
1126
- !hasActiveSubItem;
1143
+ const isItemActive = (highlightActiveModule && !item.subModules?.length && !!item.isActive) ||
1144
+ ((workspace ? samePage(pathname, itemUrl) : pathname === itemUrl) &&
1145
+ !hasActiveSubItem);
1127
1146
  return { itemUrl, activeSubItemUrl, hasActiveSubItem, isItemActive };
1128
1147
  });
1129
1148
  // A group opens when its page becomes current and otherwise stays as the
@@ -1282,7 +1301,7 @@ function SidebarHeader({ children, className }) {
1282
1301
  return jsxRuntime.jsx("div", { className: erpTheme.cn("px-2 py-3", className), children: children });
1283
1302
  }
1284
1303
 
1285
- function AppSidebar({ modules, tools, activeModule, orgCode, approvalCounts, closeOnNavigation = false, header, footer, bottom, chrome = "brand", className, }) {
1304
+ function AppSidebar({ modules, tools, activeModule, orgCode, approvalCounts, closeOnNavigation = false, highlightActiveModule = false, header, footer, bottom, chrome = "brand", className, }) {
1286
1305
  const { open } = useSidebar();
1287
1306
  const modulesWithActiveState = React__namespace.useMemo(() => modules.map(m => ({
1288
1307
  ...m,
@@ -1293,7 +1312,7 @@ function AppSidebar({ modules, tools, activeModule, orgCode, approvalCounts, clo
1293
1312
  if (chrome === "workspace") {
1294
1313
  return (jsxRuntime.jsxs("div", { className: erpTheme.cn("flex h-screen w-[244px] shrink-0 flex-col overflow-hidden border-r border-sidebar-border bg-sidebar text-sidebar-foreground",
1295
1314
  // As a drawer (≤1024px) it floats over the page and needs the lift.
1296
- "max-[1024px]:shadow-2xl", className), children: [header ? jsxRuntime.jsx("div", { className: "shrink-0 px-[18px] pt-8 pb-6", children: header }) : null, jsxRuntime.jsxs(SidebarContent, { className: "flex-1 overflow-y-auto px-[18px]", children: [jsxRuntime.jsx(NavMain, { items: modulesWithActiveState, orgCode: orgCode, approvalCounts: approvalCounts, closeOnNavigation: closeOnNavigation, chrome: "workspace" }), jsxRuntime.jsx(NavTools, { tools: tools, closeOnNavigation: closeOnNavigation })] }), bottom ? jsxRuntime.jsx("div", { className: "shrink-0 px-[18px] pt-6", children: bottom }) : null, jsxRuntime.jsx("div", { className: "shrink-0 px-[18px] pb-3", children: footer })] }));
1315
+ "max-[1024px]:shadow-2xl", className), children: [header ? jsxRuntime.jsx("div", { className: "shrink-0 px-[18px] pt-8 pb-6", children: header }) : null, jsxRuntime.jsxs(SidebarContent, { className: "flex-1 overflow-y-auto px-[18px]", children: [jsxRuntime.jsx(NavMain, { items: modulesWithActiveState, orgCode: orgCode, approvalCounts: approvalCounts, closeOnNavigation: closeOnNavigation, chrome: "workspace", highlightActiveModule: highlightActiveModule }), jsxRuntime.jsx(NavTools, { tools: tools, closeOnNavigation: closeOnNavigation })] }), bottom ? jsxRuntime.jsx("div", { className: "shrink-0 px-[18px] pt-6", children: bottom }) : null, jsxRuntime.jsx("div", { className: "shrink-0 px-[18px] pb-3", children: footer })] }));
1297
1316
  }
1298
1317
  return (jsxRuntime.jsxs("div", { className: erpTheme.cn("bg-sidebar shrink-0 flex flex-col overflow-hidden shadow-2xl h-screen w-[var(--sidebar-width-mobile)]", "!w-76 xl:rounded-b-4xl xl:rounded-tl-4xl xl:m-5 xl:h-[calc(100vh-2.5rem)]", className), children: [jsxRuntime.jsx(SidebarHeader, { children: header }), jsxRuntime.jsxs(SidebarContent, { className: "pl-2 pr-2 flex-1 overflow-y-auto", children: [jsxRuntime.jsx(NavMain, { items: modulesWithActiveState, orgCode: orgCode, approvalCounts: approvalCounts, closeOnNavigation: closeOnNavigation }), jsxRuntime.jsx(NavTools, { tools: tools, closeOnNavigation: closeOnNavigation })] }), jsxRuntime.jsx(SidebarFooter, { className: "pl-2 pr-2", children: footer })] }));
1299
1318
  }