@infuro/cms-core 1.0.35 → 1.0.36

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.
Files changed (65) hide show
  1. package/dist/admin.cjs +861 -626
  2. package/dist/admin.d.cts +6 -0
  3. package/dist/admin.d.ts +6 -0
  4. package/dist/admin.js +863 -628
  5. package/dist/api.cjs +40 -39
  6. package/dist/api.js +8 -7
  7. package/dist/auth.cjs +51 -51
  8. package/dist/auth.d.cts +3 -3
  9. package/dist/auth.d.ts +3 -3
  10. package/dist/auth.js +3 -3
  11. package/dist/{chunk-BGJAV67S.cjs → chunk-2AEVFOQP.cjs} +7923 -7197
  12. package/dist/chunk-COBORIJH.cjs +2373 -0
  13. package/dist/{chunk-EQPITOP6.js → chunk-FG6I64HP.js} +70 -9
  14. package/dist/chunk-HCIRL37O.js +21 -0
  15. package/dist/chunk-HT5DI3XW.cjs +82 -0
  16. package/dist/{chunk-2XE4X74C.js → chunk-JS2W7XZ4.js} +7510 -6800
  17. package/dist/{chunk-EF2JBPDM.js → chunk-KFFB6EMZ.js} +9 -0
  18. package/dist/{chunk-3KPNTQBV.cjs → chunk-KPKFNLQQ.cjs} +50 -22
  19. package/dist/{chunk-6KPQWRFW.js → chunk-LI2IXVAY.js} +1 -1
  20. package/dist/{chunk-N44BJZ4C.cjs → chunk-SPQFNIYJ.cjs} +9 -0
  21. package/dist/chunk-UCKN4BBY.cjs +24 -0
  22. package/dist/{chunk-4TRPKBKO.js → chunk-UF3BYUXY.js} +50 -23
  23. package/dist/chunk-VMY2S32H.js +2342 -0
  24. package/dist/{chunk-TIAEXJLI.cjs → chunk-WO2DW4AU.cjs} +7 -7
  25. package/dist/chunk-X47PBV4I.js +79 -0
  26. package/dist/{chunk-CNTSLED2.cjs → chunk-X6H5VBQ2.cjs} +75 -14
  27. package/dist/cli.cjs +4 -2
  28. package/dist/cli.js +4 -2
  29. package/dist/emit-order-notification-trigger-D2N3KFHL.cjs +16 -0
  30. package/dist/emit-order-notification-trigger-IVLWKKJL.js +3 -0
  31. package/dist/{event-order-defaults-DUGDVGJI.cjs → event-order-defaults-EMWBIGL3.cjs} +9 -9
  32. package/dist/{event-order-defaults-6E543227.js → event-order-defaults-SDRNAZHC.js} +1 -1
  33. package/dist/index.cjs +805 -1059
  34. package/dist/index.d.cts +827 -728
  35. package/dist/index.d.ts +827 -728
  36. package/dist/index.js +385 -724
  37. package/dist/migrations/1781220000000-AddWhatsappTriggerBindings.ts +23 -0
  38. package/dist/migrations/1781230000000-AddOrderNotificationTriggers.ts +46 -0
  39. package/dist/migrations/1781240000000-DropEventOrderNotificationColumns.ts +29 -0
  40. package/dist/migrations/1781250000000-RemoveOrderRefundedTrigger.ts +36 -0
  41. package/dist/{rbac-debug-db-D7ME7QUY.cjs → rbac-debug-db-HWP65A4O.cjs} +2 -2
  42. package/dist/{rbac-debug-db-MTCTVNNM.js → rbac-debug-db-QJH3AD34.js} +1 -1
  43. package/dist/whatsapp-trigger-dispatcher-ONHXI7UY.cjs +19 -0
  44. package/dist/whatsapp-trigger-dispatcher-PWFI4FKP.js +6 -0
  45. package/package.json +1 -1
  46. package/dist/chunk-46GKADYE.cjs +0 -84
  47. package/dist/chunk-7YIBMQDR.cjs +0 -86
  48. package/dist/chunk-J7XHLOLO.js +0 -830
  49. package/dist/chunk-JBRR5UYL.js +0 -87
  50. package/dist/chunk-JHF4YYRC.cjs +0 -188
  51. package/dist/chunk-PAMVINEX.cjs +0 -577
  52. package/dist/chunk-QM733NUK.js +0 -186
  53. package/dist/chunk-R73BKDRO.cjs +0 -90
  54. package/dist/chunk-TFUOHI37.cjs +0 -839
  55. package/dist/chunk-XDSNZUW7.js +0 -564
  56. package/dist/chunk-ZQ4X6OAU.js +0 -82
  57. package/dist/chunk-ZSVCP6N3.js +0 -83
  58. package/dist/email-FKR4FXFI.js +0 -5
  59. package/dist/email-KVKVPNCL.cjs +0 -58
  60. package/dist/event-order-notifications-5GSAOYVS.cjs +0 -27
  61. package/dist/event-order-notifications-IIIF23D5.js +0 -10
  62. package/dist/layout-36UFTHC5.cjs +0 -11
  63. package/dist/layout-AOBN26XG.js +0 -2
  64. package/dist/whatsapp-queue-3DXA4MXU.js +0 -2
  65. package/dist/whatsapp-queue-KG65MXD5.cjs +0 -15
package/dist/admin.cjs CHANGED
@@ -491,7 +491,7 @@ var init_admin_config_context = __esm({
491
491
  var CMS_VERSION;
492
492
  var init_cms_version = __esm({
493
493
  "src/lib/cms-version.ts"() {
494
- CMS_VERSION = "1.0.35" ;
494
+ CMS_VERSION = "1.0.36" ;
495
495
  }
496
496
  });
497
497
  function useCatalogCategories(enabled = true) {
@@ -601,25 +601,20 @@ function AdminSidebar({ variant = "sidebar" }) {
601
601
  const sessionUser = session?.user;
602
602
  const showVendorOnboard = canOnboardVendors(sessionUser);
603
603
  const vendorPortal = isVendorPortalUser(sessionUser);
604
- const { customNavItems, customNavSections = [], storeEnabled } = React26.useContext(exports.AdminConfigContext);
604
+ const { customNavItems, customNavSections = [], storeEnabled, multiVendorEnabled, eventsEnabled } = React26.useContext(exports.AdminConfigContext);
605
605
  const showStoreNav = storeEnabled || vendorPortal;
606
606
  const showPlatformNav = !vendorPortal;
607
607
  const isDrawer = variant === "drawer";
608
608
  const { categories: catalogCategories } = useCatalogCategories(showStoreNav);
609
- const activeCategoryId = searchParams.get("categoryId")?.trim() ?? "";
609
+ searchParams.get("categoryId")?.trim() ?? "";
610
610
  const hasCustomEventsNav = customNavItems.some((item) => item.href === "/admin/events" || item.href.startsWith("/admin/events/")) || customNavSections.some((section) => section.items.some((item) => item.href === "/admin/events" || item.href.startsWith("/admin/events/")));
611
- const vendorCatalogCategories = catalogCategories.filter((category) => category.slug !== "events");
611
+ catalogCategories.filter((category) => category.slug !== "events");
612
612
  const isActive = /* @__PURE__ */ __name((path) => {
613
613
  if (path === "/admin/dashboard") {
614
614
  return pathname === path || vendorPortal && pathname === "/admin/analytics";
615
615
  }
616
616
  return pathname.startsWith(path);
617
617
  }, "isActive");
618
- const isVendorCategoryActive = /* @__PURE__ */ __name((categoryId) => {
619
- if (!pathname.startsWith("/admin/products")) return false;
620
- if (!activeCategoryId) return false;
621
- return activeCategoryId === String(categoryId);
622
- }, "isVendorCategoryActive");
623
618
  const linkActive = "bg-gray-200 text-gray-900";
624
619
  const linkInactive = "text-gray-600 hover:bg-gray-100 hover:text-gray-900";
625
620
  const iconActive = "text-gray-700";
@@ -706,30 +701,13 @@ function AdminSidebar({ variant = "sidebar" }) {
706
701
  }, /* @__PURE__ */ React.createElement(Icon2, {
707
702
  className: `h-4 w-4 mr-2 ${isActive(item.href) ? iconActive : iconInactive}`
708
703
  }), item.label));
709
- })))), vendorCatalogCategories.length > 0 && /* @__PURE__ */ React.createElement("div", {
710
- className: sectionCls8
711
- }, /* @__PURE__ */ React.createElement("h3", {
712
- className: headingCls
713
- }, "Categories"), /* @__PURE__ */ React.createElement("ul", {
714
- className: "space-y-0.5"
715
- }, vendorCatalogCategories.map((category) => {
716
- const href = vendorCategoryWorkspaceUrl(category.id);
717
- const active = isVendorCategoryActive(category.id);
718
- return /* @__PURE__ */ React.createElement("li", {
719
- key: category.id
720
- }, /* @__PURE__ */ React.createElement(Link2__default.default, {
721
- href,
722
- className: `${linkCls} ${active ? linkActive : linkInactive}`
723
- }, /* @__PURE__ */ React.createElement(LucideIcons.FolderTree, {
724
- className: `h-4 w-4 mr-2 ${active ? iconActive : iconInactive}`
725
- }), category.name));
726
- }))), showStoreNav && /* @__PURE__ */ React.createElement("div", {
704
+ })))), showStoreNav && /* @__PURE__ */ React.createElement("div", {
727
705
  className: sectionCls8
728
706
  }, /* @__PURE__ */ React.createElement("h3", {
729
707
  className: headingCls
730
708
  }, "Store"), /* @__PURE__ */ React.createElement("ul", {
731
709
  className: "space-y-0.5"
732
- }, showVendorOnboard && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
710
+ }, showVendorOnboard && multiVendorEnabled !== false && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
733
711
  href: "/admin/vendors",
734
712
  className: `${linkCls} ${isActive("/admin/vendors") ? linkActive : linkInactive}`
735
713
  }, /* @__PURE__ */ React.createElement(LucideIcons.Store, {
@@ -749,12 +727,12 @@ function AdminSidebar({ variant = "sidebar" }) {
749
727
  className: `${linkCls} ${isActive("/admin/brands") ? linkActive : linkInactive}`
750
728
  }, /* @__PURE__ */ React.createElement(LucideIcons.Building2, {
751
729
  className: `h-4 w-4 mr-2 ${isActive("/admin/brands") ? iconActive : iconInactive}`
752
- }), "Brands")), !hasCustomEventsNav ? /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
730
+ }), "Brands")), !hasCustomEventsNav && eventsEnabled !== false ? /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
753
731
  href: "/admin/events",
754
732
  className: `${linkCls} ${isActive("/admin/events") ? linkActive : linkInactive}`
755
733
  }, /* @__PURE__ */ React.createElement(LucideIcons.CalendarDays, {
756
734
  className: `h-4 w-4 mr-2 ${isActive("/admin/events") ? iconActive : iconInactive}`
757
- }), "Events")) : null, !vendorPortal && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
735
+ }), "Events")) : null, /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
758
736
  href: "/admin/products",
759
737
  className: `${linkCls} ${isActive("/admin/products") ? linkActive : linkInactive}`
760
738
  }, /* @__PURE__ */ React.createElement(LucideIcons.ShoppingBag, {
@@ -1182,7 +1160,7 @@ var init_builtin_plugin_descriptors = __esm({
1182
1160
  },
1183
1161
  {
1184
1162
  name: "event_notifications",
1185
- label: "Event notifications",
1163
+ label: "Notifications",
1186
1164
  version: "1.0.0",
1187
1165
  description: "Order confirmation templates with QR code and order details for events.",
1188
1166
  enabled: true,
@@ -1197,9 +1175,7 @@ var init_builtin_plugin_descriptors = __esm({
1197
1175
  function isAuthDebugClientEnabled() {
1198
1176
  if (typeof window === "undefined") return false;
1199
1177
  const v = process.env.NEXT_PUBLIC_CMS_AUTH_DEBUG?.trim().toLowerCase();
1200
- if (v === "1" || v === "true" || v === "yes") return true;
1201
- if (v === "0" || v === "false" || v === "no") return false;
1202
- return process.env.NODE_ENV === "development";
1178
+ return v === "1" || v === "true" || v === "yes";
1203
1179
  }
1204
1180
  function logAuthClient(message, data) {
1205
1181
  if (!isAuthDebugClientEnabled()) return;
@@ -1243,13 +1219,16 @@ function useAdminViewSettings() {
1243
1219
  }
1244
1220
  function AdminLayoutInner({ children }) {
1245
1221
  const { data: session, status } = react.useSession();
1222
+ const { multiVendorEnabled } = React26.useContext(exports.AdminConfigContext);
1246
1223
  const router = navigation.useRouter();
1247
1224
  const pathname = navigation.usePathname();
1248
1225
  const [loadingTimeout, setLoadingTimeout] = React26.useState(false);
1249
1226
  const [moreSheetOpen, setMoreSheetOpen] = React26.useState(false);
1250
1227
  const isMobile = useIsMobile();
1228
+ const vendorBlockRedirectRef = React26.useRef(false);
1251
1229
  useAdminViewSettings();
1252
1230
  const isPublicPath = PUBLIC_ADMIN_PATHS.includes(pathname);
1231
+ const isVendorOnlySession = session?.user?.isVendorPortal === true && session?.user?.isRBACAdmin !== true;
1253
1232
  React26.useEffect(() => {
1254
1233
  if (isMobile) setMoreSheetOpen(false);
1255
1234
  }, [
@@ -1276,6 +1255,7 @@ function AdminLayoutInner({ children }) {
1276
1255
  return () => clearTimeout(timeout);
1277
1256
  }
1278
1257
  if (status === "unauthenticated") {
1258
+ if (vendorBlockRedirectRef.current) return;
1279
1259
  logAuthClient("AdminLayout redirect \u2192 /admin/signin (unauthenticated)", {
1280
1260
  pathname
1281
1261
  });
@@ -1289,6 +1269,29 @@ function AdminLayoutInner({ children }) {
1289
1269
  pathname,
1290
1270
  isPublicPath
1291
1271
  ]);
1272
+ React26.useEffect(() => {
1273
+ if (isPublicPath) return;
1274
+ if (status !== "authenticated" || !session) return;
1275
+ if (!multiVendorEnabled && isVendorOnlySession) {
1276
+ vendorBlockRedirectRef.current = true;
1277
+ logAuthClient("AdminLayout: vendor session blocked (multi-vendor disabled)", {
1278
+ pathname
1279
+ });
1280
+ react.signOut({
1281
+ redirect: false
1282
+ }).then(() => {
1283
+ router.replace("/admin/signin?error=CredentialsSignin");
1284
+ });
1285
+ }
1286
+ }, [
1287
+ status,
1288
+ session,
1289
+ multiVendorEnabled,
1290
+ isVendorOnlySession,
1291
+ router,
1292
+ pathname,
1293
+ isPublicPath
1294
+ ]);
1292
1295
  if (isPublicPath) {
1293
1296
  return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(AdminStyle, null), children);
1294
1297
  }
@@ -1313,6 +1316,9 @@ function AdminLayoutInner({ children }) {
1313
1316
  if (!session) {
1314
1317
  return null;
1315
1318
  }
1319
+ if (!multiVendorEnabled && isVendorOnlySession) {
1320
+ return null;
1321
+ }
1316
1322
  const isOrderProductEmbed = pathname?.includes("/admin/orders/product-frame") === true;
1317
1323
  if (isOrderProductEmbed) {
1318
1324
  return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(AdminStyle, null), /* @__PURE__ */ React.createElement("div", {
@@ -1384,9 +1390,48 @@ function useStoreEnabled() {
1384
1390
  currency
1385
1391
  };
1386
1392
  }
1393
+ function parseBooleanSetting(value) {
1394
+ if (typeof value === "boolean") return value;
1395
+ if (typeof value === "number") return value !== 0;
1396
+ if (typeof value === "string") {
1397
+ const normalized = value.trim().toLowerCase();
1398
+ if (normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "on") return true;
1399
+ if (normalized === "false" || normalized === "0" || normalized === "no" || normalized === "off") return false;
1400
+ }
1401
+ if (value && typeof value === "object") {
1402
+ const record = value;
1403
+ const nested = parseBooleanSetting(record.value ?? record.enabled ?? record.isEnabled ?? record.active ?? record.state);
1404
+ if (nested != null) return nested;
1405
+ }
1406
+ return null;
1407
+ }
1408
+ function useMultiVendorEnabled() {
1409
+ const [multiVendorEnabled, setMultiVendorEnabled] = React26.useState(true);
1410
+ React26.useEffect(() => {
1411
+ fetch("/api/settings/multi_vendor").then((r) => r.ok ? r.json() : {}).then((data) => {
1412
+ const parsed = parseBooleanSetting(data?.enabled ?? data?.value ?? data?.isEnabled ?? data?.active ?? data?.state);
1413
+ setMultiVendorEnabled(parsed ?? true);
1414
+ }).catch(() => {
1415
+ });
1416
+ }, []);
1417
+ return multiVendorEnabled;
1418
+ }
1419
+ function useEventsEnabled() {
1420
+ const [eventsEnabled, setEventsEnabled] = React26.useState(true);
1421
+ React26.useEffect(() => {
1422
+ fetch("/api/settings/events").then((r) => r.ok ? r.json() : {}).then((data) => {
1423
+ const parsed = parseBooleanSetting(data?.enabled ?? data?.value ?? data?.isEnabled ?? data?.active ?? data?.state);
1424
+ setEventsEnabled(parsed ?? true);
1425
+ }).catch(() => {
1426
+ });
1427
+ }, []);
1428
+ return eventsEnabled;
1429
+ }
1387
1430
  function AdminLayout({ children, customNavItems = [], customNavSections = [], customCrudConfigs = {}, categoryRelatedProductLabels = {}, renderOrderDetailFooter, theme, themeRegistry, pluginDescriptors = [] }) {
1388
1431
  const resolvedTheme = useResolvedTheme(theme, themeRegistry);
1389
1432
  const { storeEnabled, currency } = useStoreEnabled();
1433
+ const multiVendorEnabled = useMultiVendorEnabled();
1434
+ const eventsEnabled = useEventsEnabled();
1390
1435
  const mergedPluginDescriptors = React26.useMemo(() => {
1391
1436
  const seen = new Set(pluginDescriptors.map((p) => p.name));
1392
1437
  const extra = BUILTIN_PLUGIN_DESCRIPTORS.filter((p) => !seen.has(p.name));
@@ -1407,7 +1452,9 @@ function AdminLayout({ children, customNavItems = [], customNavSections = [], cu
1407
1452
  themeRegistry,
1408
1453
  pluginDescriptors: mergedPluginDescriptors,
1409
1454
  storeEnabled,
1410
- currency
1455
+ currency,
1456
+ multiVendorEnabled,
1457
+ eventsEnabled
1411
1458
  }), [
1412
1459
  customNavItems,
1413
1460
  customNavSections,
@@ -1418,7 +1465,9 @@ function AdminLayout({ children, customNavItems = [], customNavSections = [], cu
1418
1465
  themeRegistry,
1419
1466
  mergedPluginDescriptors,
1420
1467
  storeEnabled,
1421
- currency
1468
+ currency,
1469
+ multiVendorEnabled,
1470
+ eventsEnabled
1422
1471
  ]);
1423
1472
  return /* @__PURE__ */ React.createElement(exports.AdminConfigContext.Provider, {
1424
1473
  value: configValue
@@ -1453,6 +1502,9 @@ var init_AdminLayout = __esm({
1453
1502
  __name(AdminLayoutInner, "AdminLayoutInner");
1454
1503
  __name(useResolvedTheme, "useResolvedTheme");
1455
1504
  __name(useStoreEnabled, "useStoreEnabled");
1505
+ __name(parseBooleanSetting, "parseBooleanSetting");
1506
+ __name(useMultiVendorEnabled, "useMultiVendorEnabled");
1507
+ __name(useEventsEnabled, "useEventsEnabled");
1456
1508
  __name(AdminLayout, "AdminLayout");
1457
1509
  }
1458
1510
  });
@@ -8730,6 +8782,14 @@ var init_SignInPage = __esm({
8730
8782
  const [error, setError] = React26.useState("");
8731
8783
  const [loading, setLoading] = React26.useState(false);
8732
8784
  const { status } = react.useSession();
8785
+ const searchParams = navigation.useSearchParams();
8786
+ React26.useEffect(() => {
8787
+ if (searchParams.get("error")) {
8788
+ setError("Invalid email or password");
8789
+ }
8790
+ }, [
8791
+ searchParams
8792
+ ]);
8733
8793
  React26.useEffect(() => {
8734
8794
  logAuthClient("SignInPage session status", {
8735
8795
  status
@@ -11078,8 +11138,17 @@ var init_store_crud_configs = __esm({
11078
11138
  },
11079
11139
  {
11080
11140
  param: "eventId",
11081
- label: "Event ID",
11082
- type: "text"
11141
+ label: "Event",
11142
+ type: "select",
11143
+ options: [
11144
+ {
11145
+ value: "",
11146
+ label: "All"
11147
+ }
11148
+ ],
11149
+ relationApi: "/api/events",
11150
+ relationLabelField: "name",
11151
+ relationValueField: "id"
11083
11152
  }
11084
11153
  ],
11085
11154
  columns: [
@@ -12162,6 +12231,8 @@ function SettingsPage() {
12162
12231
  });
12163
12232
  const [themeSettingsLoading, setThemeSettingsLoading] = React26.useState(true);
12164
12233
  const [storeEnabled, setStoreEnabled] = React26.useState(false);
12234
+ const [multiVendorEnabled, setMultiVendorEnabled] = React26.useState(true);
12235
+ const [eventsEnabled, setEventsEnabled] = React26.useState(true);
12165
12236
  const [storeSettingsLoading, setStoreSettingsLoading] = React26.useState(true);
12166
12237
  const [currency, setCurrency] = React26.useState(DEFAULT_CURRENCY);
12167
12238
  const [currencies, setCurrencies] = React26.useState([]);
@@ -12219,6 +12290,14 @@ function SettingsPage() {
12219
12290
  setStoreEnabled(data.enabled === "true");
12220
12291
  setCurrency(data.currency || DEFAULT_CURRENCY);
12221
12292
  }).finally(() => setStoreSettingsLoading(false));
12293
+ fetch("/api/settings/multi_vendor").then((r) => r.ok ? r.json() : {}).then((data) => {
12294
+ setMultiVendorEnabled(data.enabled !== "false");
12295
+ }).catch(() => {
12296
+ });
12297
+ fetch("/api/settings/events").then((r) => r.ok ? r.json() : {}).then((data) => {
12298
+ setEventsEnabled(data.enabled !== "false");
12299
+ }).catch(() => {
12300
+ });
12222
12301
  fetch("/api/currencies/exchange-rates").then((r) => r.ok ? r.json() : []).then((data) => {
12223
12302
  if (data.length > 0) {
12224
12303
  setExchangeRates(data.map((entry) => ({
@@ -12335,6 +12414,30 @@ function SettingsPage() {
12335
12414
  }
12336
12415
  })
12337
12416
  });
12417
+ await fetch("/api/settings/multi_vendor", {
12418
+ method: "PUT",
12419
+ headers: {
12420
+ "Content-Type": "application/json"
12421
+ },
12422
+ body: JSON.stringify({
12423
+ enabled: {
12424
+ value: multiVendorEnabled ? "true" : "false",
12425
+ type: "public"
12426
+ }
12427
+ })
12428
+ });
12429
+ await fetch("/api/settings/events", {
12430
+ method: "PUT",
12431
+ headers: {
12432
+ "Content-Type": "application/json"
12433
+ },
12434
+ body: JSON.stringify({
12435
+ enabled: {
12436
+ value: eventsEnabled ? "true" : "false",
12437
+ type: "public"
12438
+ }
12439
+ })
12440
+ });
12338
12441
  sonner.toast.success("Store settings saved");
12339
12442
  window.location.reload();
12340
12443
  } catch {
@@ -12594,7 +12697,25 @@ function SettingsPage() {
12594
12697
  className: "text-sm font-medium text-gray-700"
12595
12698
  }, "Enable Store"), /* @__PURE__ */ React.createElement("p", {
12596
12699
  className: "text-xs text-gray-500"
12597
- }, "Shows Store section in sidebar with Products, Orders, Payments, etc.")))), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", {
12700
+ }, "Shows Store section in sidebar with Products, Orders, Payments, etc.")))), storeEnabled && /* @__PURE__ */ React.createElement("div", {
12701
+ className: "mt-4 flex items-center gap-3 p-4 bg-gray-50 rounded-lg border border-gray-200"
12702
+ }, /* @__PURE__ */ React.createElement(Switch, {
12703
+ checked: multiVendorEnabled,
12704
+ onCheckedChange: setMultiVendorEnabled
12705
+ }), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(Label3, {
12706
+ className: "text-sm font-medium text-gray-700"
12707
+ }, "Multi Vendor Support"), /* @__PURE__ */ React.createElement("p", {
12708
+ className: "text-xs text-gray-500"
12709
+ }, "Enable vendor portals, vendor logins, and vendor-scoped store data. Disabling this blocks vendor-only accounts from signing in."))), storeEnabled && /* @__PURE__ */ React.createElement("div", {
12710
+ className: "mt-4 flex items-center gap-3 p-4 bg-gray-50 rounded-lg border border-gray-200"
12711
+ }, /* @__PURE__ */ React.createElement(Switch, {
12712
+ checked: eventsEnabled,
12713
+ onCheckedChange: setEventsEnabled
12714
+ }), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(Label3, {
12715
+ className: "text-sm font-medium text-gray-700"
12716
+ }, "Events"), /* @__PURE__ */ React.createElement("p", {
12717
+ className: "text-xs text-gray-500"
12718
+ }, "Enable event management. Disabling this hides the Events tab and blocks all event-related APIs."))), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", {
12598
12719
  className: "flex items-center justify-between mb-1"
12599
12720
  }, /* @__PURE__ */ React.createElement("label", {
12600
12721
  className: "block text-sm font-semibold text-gray-700"
@@ -14381,6 +14502,417 @@ var init_EventOrderGlobalTemplates = __esm({
14381
14502
  __name(saveEventOrderTemplateRows, "saveEventOrderTemplateRows");
14382
14503
  }
14383
14504
  });
14505
+ function varCount(t) {
14506
+ const explicit = t.providerMeta?.variableCount;
14507
+ if (typeof explicit === "number") return explicit;
14508
+ const matches = t.body.match(/\{\{\d+\}\}/g);
14509
+ return matches ? new Set(matches).size : 0;
14510
+ }
14511
+ function bodyExample(t) {
14512
+ const body = t.providerMeta?.components?.find((c) => c.type === "BODY");
14513
+ return body?.example?.body_text?.[0] ?? [];
14514
+ }
14515
+ function guessFromContext(context) {
14516
+ const c = context.toLowerCase();
14517
+ for (const { pattern, var: v } of CONTEXT_HINTS) {
14518
+ if (pattern.test(c)) return v;
14519
+ }
14520
+ return "";
14521
+ }
14522
+ function guessFromExampleShape(example) {
14523
+ const v = example.trim();
14524
+ if (!v) return "";
14525
+ if (/^\+?\d{10,15}$/.test(v)) return "customerPhone";
14526
+ if (/^[A-Z]{3}$/.test(v)) return "currency";
14527
+ if (/^[A-Za-z]{1,4}-?\d{2,}$/.test(v) || /^#?\d{3,}$/.test(v)) return "orderNumber";
14528
+ if (/^\d+(\.\d{1,2})?$/.test(v)) return "total";
14529
+ if (/^[A-Za-z]+(\s[A-Za-z]+)?$/.test(v) && v.length <= 30) return "customerName";
14530
+ return "";
14531
+ }
14532
+ function guessKnownVar(context, example, used) {
14533
+ const candidates = [
14534
+ guessFromContext(context),
14535
+ guessFromExampleShape(example)
14536
+ ].filter((v) => Boolean(v));
14537
+ for (const c of candidates) {
14538
+ if (!used.has(c)) return c;
14539
+ }
14540
+ return "";
14541
+ }
14542
+ function contextBeforePlaceholder(bodyText, n) {
14543
+ const marker = `{{${n}}}`;
14544
+ const idx = bodyText.indexOf(marker);
14545
+ if (idx === -1) return "";
14546
+ return bodyText.slice(Math.max(0, idx - 25), idx);
14547
+ }
14548
+ async function jsonFetch(url, init) {
14549
+ const res = await fetch(url, {
14550
+ credentials: "include",
14551
+ ...init
14552
+ });
14553
+ const data = await res.json().catch(() => ({}));
14554
+ if (!res.ok) {
14555
+ throw new Error(data?.error || `Request failed (${res.status})`);
14556
+ }
14557
+ return data;
14558
+ }
14559
+ function WhatsAppTriggerBindings() {
14560
+ const [triggers, setTriggers] = React26.useState([]);
14561
+ const [bindings, setBindings] = React26.useState([]);
14562
+ const [templates, setTemplates] = React26.useState([]);
14563
+ const [loading, setLoading] = React26.useState(true);
14564
+ const [syncing, setSyncing] = React26.useState(false);
14565
+ const [editingTemplateId, setEditingTemplateId] = React26.useState(null);
14566
+ const templatesById = React26.useMemo(() => {
14567
+ const m = /* @__PURE__ */ new Map();
14568
+ for (const t of templates) m.set(t.id, t);
14569
+ return m;
14570
+ }, [
14571
+ templates
14572
+ ]);
14573
+ const load = React26.useCallback(async () => {
14574
+ setLoading(true);
14575
+ try {
14576
+ const [triggersRes, bindingsRes, templatesRes] = await Promise.all([
14577
+ jsonFetch("/api/order_notification_triggers?limit=100&sortField=sortOrder&sortOrder=asc"),
14578
+ jsonFetch("/api/whatsapp_trigger_bindings?limit=100"),
14579
+ jsonFetch("/api/message-templates/whatsapp")
14580
+ ]);
14581
+ setTriggers((triggersRes.data ?? []).filter((t) => t.enabled));
14582
+ setBindings(bindingsRes.data ?? []);
14583
+ setTemplates(templatesRes.items ?? []);
14584
+ } catch (e) {
14585
+ sonner.toast.error(e instanceof Error ? e.message : "Failed to load WhatsApp trigger bindings");
14586
+ } finally {
14587
+ setLoading(false);
14588
+ }
14589
+ }, []);
14590
+ React26.useEffect(() => {
14591
+ void load();
14592
+ }, [
14593
+ load
14594
+ ]);
14595
+ const handleSync = /* @__PURE__ */ __name(async () => {
14596
+ setSyncing(true);
14597
+ try {
14598
+ await jsonFetch("/api/message-templates/whatsapp/sync", {
14599
+ method: "POST"
14600
+ });
14601
+ await load();
14602
+ sonner.toast.success("Synced templates from Meta");
14603
+ } catch (e) {
14604
+ sonner.toast.error(e instanceof Error ? e.message : "Sync failed");
14605
+ } finally {
14606
+ setSyncing(false);
14607
+ }
14608
+ }, "handleSync");
14609
+ const handleRebind = /* @__PURE__ */ __name(async (triggerKey, messageTemplateId) => {
14610
+ const existing = bindings.find((b) => b.triggerKey === triggerKey);
14611
+ try {
14612
+ if (existing) {
14613
+ const updated = await jsonFetch(`/api/whatsapp_trigger_bindings/${existing.id}`, {
14614
+ method: "PUT",
14615
+ headers: {
14616
+ "Content-Type": "application/json"
14617
+ },
14618
+ body: JSON.stringify({
14619
+ messageTemplateId
14620
+ })
14621
+ });
14622
+ setBindings((prev) => prev.map((b) => b.id === updated.id ? updated : b));
14623
+ } else {
14624
+ const created = await jsonFetch("/api/whatsapp_trigger_bindings", {
14625
+ method: "POST",
14626
+ headers: {
14627
+ "Content-Type": "application/json"
14628
+ },
14629
+ body: JSON.stringify({
14630
+ triggerKey,
14631
+ messageTemplateId,
14632
+ enabled: true
14633
+ })
14634
+ });
14635
+ setBindings((prev) => [
14636
+ ...prev,
14637
+ created
14638
+ ]);
14639
+ }
14640
+ sonner.toast.success(`"${triggerKey}" bound to "${templatesById.get(messageTemplateId)?.name ?? messageTemplateId}"`);
14641
+ } catch (e) {
14642
+ sonner.toast.error(e instanceof Error ? e.message : "Failed to update binding");
14643
+ }
14644
+ }, "handleRebind");
14645
+ const handleSaveParamOrder = /* @__PURE__ */ __name(async (templateId, paramOrder) => {
14646
+ try {
14647
+ const res = await jsonFetch(`/api/message-templates/whatsapp/${templateId}`, {
14648
+ method: "PATCH",
14649
+ headers: {
14650
+ "Content-Type": "application/json"
14651
+ },
14652
+ body: JSON.stringify({
14653
+ paramOrder
14654
+ })
14655
+ });
14656
+ setTemplates((prev) => prev.map((t) => t.id === res.item.id ? res.item : t));
14657
+ sonner.toast.success("Param order saved");
14658
+ setEditingTemplateId(null);
14659
+ } catch (e) {
14660
+ sonner.toast.error(e instanceof Error ? e.message : "Failed to save param order");
14661
+ }
14662
+ }, "handleSaveParamOrder");
14663
+ if (loading) {
14664
+ return /* @__PURE__ */ React.createElement("div", {
14665
+ className: "flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400"
14666
+ }, /* @__PURE__ */ React.createElement(LucideIcons.Loader2, {
14667
+ className: "h-4 w-4 animate-spin"
14668
+ }), "Loading trigger bindings\u2026");
14669
+ }
14670
+ return /* @__PURE__ */ React.createElement("div", {
14671
+ className: "space-y-3 rounded-md border border-gray-200 dark:border-gray-600 p-3"
14672
+ }, /* @__PURE__ */ React.createElement("div", {
14673
+ className: "flex items-start justify-between gap-2"
14674
+ }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("p", {
14675
+ className: "text-sm font-medium text-gray-900 dark:text-white"
14676
+ }, "Order trigger templates"), /* @__PURE__ */ React.createElement("p", {
14677
+ className: "text-xs text-gray-500 dark:text-gray-400 mt-1"
14678
+ }, "When an order is placed or cancelled, the matching template is sent on WhatsApp. Sync templates from Meta, then pick one for each trigger below.")), /* @__PURE__ */ React.createElement(Button, {
14679
+ type: "button",
14680
+ variant: "outline",
14681
+ size: "sm",
14682
+ className: "gap-1.5 h-8 shrink-0",
14683
+ disabled: syncing,
14684
+ onClick: /* @__PURE__ */ __name(() => void handleSync(), "onClick")
14685
+ }, syncing ? /* @__PURE__ */ React.createElement(LucideIcons.Loader2, {
14686
+ className: "h-3.5 w-3.5 animate-spin"
14687
+ }) : /* @__PURE__ */ React.createElement(LucideIcons.RefreshCw, {
14688
+ className: "h-3.5 w-3.5"
14689
+ }), "Sync from Meta")), /* @__PURE__ */ React.createElement("div", {
14690
+ className: "space-y-3"
14691
+ }, triggers.length === 0 ? /* @__PURE__ */ React.createElement("p", {
14692
+ className: "text-xs text-amber-600 dark:text-amber-400"
14693
+ }, "No order triggers found. Run database migrations to seed default triggers.") : null, triggers.map(({ triggerKey, label, description }) => {
14694
+ const binding = bindings.find((b) => b.triggerKey === triggerKey) ?? null;
14695
+ const template = binding?.messageTemplateId != null ? templatesById.get(binding.messageTemplateId) : void 0;
14696
+ const paramOrder = template?.providerMeta?.paramOrder ?? [];
14697
+ const missingParamOrder = template && varCount(template) > 0 && paramOrder.length === 0;
14698
+ return /* @__PURE__ */ React.createElement("div", {
14699
+ key: triggerKey,
14700
+ className: "space-y-2 border-t border-gray-100 pt-3 first:border-t-0 first:pt-0 dark:border-gray-700"
14701
+ }, /* @__PURE__ */ React.createElement("div", {
14702
+ className: "flex items-center gap-2"
14703
+ }, /* @__PURE__ */ React.createElement(LucideIcons.MessageCircle, {
14704
+ className: "h-3.5 w-3.5 text-gray-400 shrink-0"
14705
+ }), /* @__PURE__ */ React.createElement("span", {
14706
+ className: "text-sm font-medium text-gray-900 dark:text-gray-100"
14707
+ }, label), /* @__PURE__ */ React.createElement("span", {
14708
+ className: "text-[11px] font-mono text-gray-400"
14709
+ }, triggerKey)), description ? /* @__PURE__ */ React.createElement("p", {
14710
+ className: "text-[11px] text-gray-500 dark:text-gray-400"
14711
+ }, description) : null, /* @__PURE__ */ React.createElement("div", {
14712
+ className: "flex flex-wrap items-center gap-2"
14713
+ }, /* @__PURE__ */ React.createElement(Select, {
14714
+ value: binding?.messageTemplateId != null ? String(binding.messageTemplateId) : void 0,
14715
+ onValueChange: /* @__PURE__ */ __name((v) => void handleRebind(triggerKey, Number(v)), "onValueChange")
14716
+ }, /* @__PURE__ */ React.createElement(SelectTrigger, {
14717
+ className: "h-8 text-sm w-64"
14718
+ }, /* @__PURE__ */ React.createElement(SelectValue, {
14719
+ placeholder: "Select a template\u2026"
14720
+ })), /* @__PURE__ */ React.createElement(SelectContent, null, templates.map((t) => /* @__PURE__ */ React.createElement(SelectItem, {
14721
+ key: t.id,
14722
+ value: String(t.id)
14723
+ }, t.name, t.providerMeta?.status ? ` (${t.providerMeta.status})` : "")))), template ? /* @__PURE__ */ React.createElement(Button, {
14724
+ type: "button",
14725
+ variant: "ghost",
14726
+ size: "sm",
14727
+ className: "h-8 gap-1 text-xs",
14728
+ onClick: /* @__PURE__ */ __name(() => setEditingTemplateId(template.id), "onClick")
14729
+ }, /* @__PURE__ */ React.createElement(LucideIcons.Settings2, {
14730
+ className: "h-3.5 w-3.5"
14731
+ }), paramOrder.length > 0 ? `Params: ${paramOrder.join(" \u2192 ")}` : "Set param order") : null), missingParamOrder ? /* @__PURE__ */ React.createElement("p", {
14732
+ className: "text-xs text-amber-600 dark:text-amber-400"
14733
+ }, "\u26A0 No param order set \u2014 variables may send in the wrong slots.") : null, template?.providerMeta?.language ? /* @__PURE__ */ React.createElement("p", {
14734
+ className: "text-[11px] text-gray-400"
14735
+ }, "Language: ", template.providerMeta.language) : null);
14736
+ })), editingTemplateId !== null && templatesById.get(editingTemplateId) && /* @__PURE__ */ React.createElement(ParamOrderEditor, {
14737
+ template: templatesById.get(editingTemplateId),
14738
+ onCancel: /* @__PURE__ */ __name(() => setEditingTemplateId(null), "onCancel"),
14739
+ onSave: /* @__PURE__ */ __name((order) => void handleSaveParamOrder(editingTemplateId, order), "onSave")
14740
+ }));
14741
+ }
14742
+ function ParamOrderEditor({ template, onCancel, onSave }) {
14743
+ const count = Math.max(varCount(template), template.providerMeta?.paramOrder?.length ?? 0);
14744
+ const example = bodyExample(template);
14745
+ const existing = template.providerMeta?.paramOrder ?? [];
14746
+ const bodyText = template.providerMeta?.components?.find((c) => c.type === "BODY")?.text ?? template.body;
14747
+ const initialGuesses = React26.useMemo(() => {
14748
+ const base = Array.from({
14749
+ length: count
14750
+ }, (_, i) => existing[i] ?? "");
14751
+ const used = new Set(base.filter(Boolean));
14752
+ const auto = /* @__PURE__ */ new Set();
14753
+ const withGuesses = base.map((v, i) => {
14754
+ if (v) return v;
14755
+ const context = contextBeforePlaceholder(bodyText, i + 1);
14756
+ const guess = guessKnownVar(context, example[i] ?? "", used);
14757
+ if (guess) {
14758
+ used.add(guess);
14759
+ auto.add(i);
14760
+ return guess;
14761
+ }
14762
+ return v;
14763
+ });
14764
+ return {
14765
+ values: withGuesses,
14766
+ autoFilled: auto
14767
+ };
14768
+ }, []);
14769
+ const [values, setValues] = React26.useState(initialGuesses.values);
14770
+ const [autoFilled, setAutoFilled] = React26.useState(initialGuesses.autoFilled);
14771
+ const [customIndex, setCustomIndex] = React26.useState(null);
14772
+ function setValue(i, v) {
14773
+ setValues((prev) => {
14774
+ const next = [
14775
+ ...prev
14776
+ ];
14777
+ next[i] = v;
14778
+ return next;
14779
+ });
14780
+ setAutoFilled((prev) => {
14781
+ if (!prev.has(i)) return prev;
14782
+ const next = new Set(prev);
14783
+ next.delete(i);
14784
+ return next;
14785
+ });
14786
+ }
14787
+ __name(setValue, "setValue");
14788
+ const allFilled = values.length > 0 && values.every((v) => v.trim() !== "");
14789
+ return /* @__PURE__ */ React.createElement("div", {
14790
+ className: "fixed inset-0 bg-black/30 flex items-center justify-center z-50 p-4"
14791
+ }, /* @__PURE__ */ React.createElement("div", {
14792
+ className: "bg-white dark:bg-gray-900 rounded-lg shadow-xl w-full max-w-lg p-5 space-y-4 border border-gray-200 dark:border-gray-700"
14793
+ }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("h2", {
14794
+ className: "font-semibold text-gray-900 dark:text-gray-100"
14795
+ }, template.name), /* @__PURE__ */ React.createElement("p", {
14796
+ className: "text-xs text-gray-500 dark:text-gray-400 mt-1 font-mono break-words"
14797
+ }, bodyText)), count === 0 ? /* @__PURE__ */ React.createElement("p", {
14798
+ className: "text-sm text-gray-500 dark:text-gray-400"
14799
+ }, "This template has no positional variables \u2014 nothing to configure.") : /* @__PURE__ */ React.createElement("div", {
14800
+ className: "space-y-2"
14801
+ }, autoFilled.size > 0 ? /* @__PURE__ */ React.createElement("p", {
14802
+ className: "text-xs text-gray-500 dark:text-gray-400"
14803
+ }, "We pre-filled variables we're fairly confident about, based on this template's wording and Meta's example values. Review and adjust anything that looks wrong before saving.") : null, Array.from({
14804
+ length: count
14805
+ }).map((_, i) => /* @__PURE__ */ React.createElement("div", {
14806
+ key: i,
14807
+ className: "flex items-center gap-2"
14808
+ }, /* @__PURE__ */ React.createElement("span", {
14809
+ className: "text-xs font-mono text-gray-400 w-10"
14810
+ }, `{{${i + 1}}}`), customIndex === i ? /* @__PURE__ */ React.createElement("input", {
14811
+ autoFocus: true,
14812
+ value: values[i],
14813
+ onChange: /* @__PURE__ */ __name((e) => setValue(i, e.target.value), "onChange"),
14814
+ onBlur: /* @__PURE__ */ __name(() => setCustomIndex(null), "onBlur"),
14815
+ placeholder: "custom variable name",
14816
+ className: "flex-1 h-8 border border-gray-300 dark:border-gray-600 rounded-md px-2 text-sm font-mono bg-transparent"
14817
+ }) : /* @__PURE__ */ React.createElement(Select, {
14818
+ value: KNOWN_VARS.includes(values[i]) ? values[i] : values[i] ? "__custom__" : void 0,
14819
+ onValueChange: /* @__PURE__ */ __name((v) => {
14820
+ if (v === "__custom__") {
14821
+ setValue(i, "");
14822
+ setCustomIndex(i);
14823
+ } else {
14824
+ setValue(i, v);
14825
+ }
14826
+ }, "onValueChange")
14827
+ }, /* @__PURE__ */ React.createElement(SelectTrigger, {
14828
+ className: "flex-1 h-8 text-sm"
14829
+ }, /* @__PURE__ */ React.createElement(SelectValue, {
14830
+ placeholder: "Select variable\u2026"
14831
+ })), /* @__PURE__ */ React.createElement(SelectContent, null, KNOWN_VARS.map((v) => /* @__PURE__ */ React.createElement(SelectItem, {
14832
+ key: v,
14833
+ value: v
14834
+ }, v)), /* @__PURE__ */ React.createElement(SelectItem, {
14835
+ value: "__custom__"
14836
+ }, "Custom\u2026"))), autoFilled.has(i) ? /* @__PURE__ */ React.createElement("span", {
14837
+ className: "text-[10px] font-medium text-emerald-600 dark:text-emerald-400 shrink-0"
14838
+ }, "auto") : null, example[i] ? /* @__PURE__ */ React.createElement("span", {
14839
+ className: "text-xs text-gray-400 w-24 truncate shrink-0",
14840
+ title: example[i]
14841
+ }, "e.g. ", example[i]) : null))), /* @__PURE__ */ React.createElement("div", {
14842
+ className: "flex justify-end gap-2 pt-2"
14843
+ }, /* @__PURE__ */ React.createElement(Button, {
14844
+ type: "button",
14845
+ variant: "outline",
14846
+ size: "sm",
14847
+ onClick: onCancel
14848
+ }, "Cancel"), /* @__PURE__ */ React.createElement(Button, {
14849
+ type: "button",
14850
+ size: "sm",
14851
+ disabled: count > 0 && !allFilled,
14852
+ onClick: /* @__PURE__ */ __name(() => onSave(values), "onClick")
14853
+ }, "Save"))));
14854
+ }
14855
+ var KNOWN_VARS, CONTEXT_HINTS;
14856
+ var init_whatsappTriggerBindingsPage = __esm({
14857
+ "src/admin/pages/whatsappTriggerBindingsPage.tsx"() {
14858
+ "use client";
14859
+ init_button();
14860
+ init_select();
14861
+ __name(varCount, "varCount");
14862
+ __name(bodyExample, "bodyExample");
14863
+ KNOWN_VARS = [
14864
+ "orderId",
14865
+ "orderNumber",
14866
+ "customerName",
14867
+ "customerPhone",
14868
+ "total",
14869
+ "currency",
14870
+ "vendorId",
14871
+ "refundAmount"
14872
+ ];
14873
+ CONTEXT_HINTS = [
14874
+ {
14875
+ pattern: /refund/,
14876
+ var: "refundAmount"
14877
+ },
14878
+ {
14879
+ pattern: /(order\s*(no\.?|number|#|id))/,
14880
+ var: "orderNumber"
14881
+ },
14882
+ {
14883
+ pattern: /\border\b/,
14884
+ var: "orderNumber"
14885
+ },
14886
+ {
14887
+ pattern: /(phone|mobile|contact\s*number)/,
14888
+ var: "customerPhone"
14889
+ },
14890
+ {
14891
+ pattern: /(vendor|seller|store)/,
14892
+ var: "vendorId"
14893
+ },
14894
+ {
14895
+ pattern: /currency/,
14896
+ var: "currency"
14897
+ },
14898
+ {
14899
+ pattern: /(total|amount|price|pay(?:ment)?)/,
14900
+ var: "total"
14901
+ },
14902
+ {
14903
+ pattern: /(hi|hello|dear|name|customer)/,
14904
+ var: "customerName"
14905
+ }
14906
+ ];
14907
+ __name(guessFromContext, "guessFromContext");
14908
+ __name(guessFromExampleShape, "guessFromExampleShape");
14909
+ __name(guessKnownVar, "guessKnownVar");
14910
+ __name(contextBeforePlaceholder, "contextBeforePlaceholder");
14911
+ __name(jsonFetch, "jsonFetch");
14912
+ __name(WhatsAppTriggerBindings, "WhatsAppTriggerBindings");
14913
+ __name(ParamOrderEditor, "ParamOrderEditor");
14914
+ }
14915
+ });
14384
14916
  function EventNotificationsPluginSettings({ settingsGroup, enabled, onEnabledChange, onSaveSettings, saving }) {
14385
14917
  const [tab, setTab] = React26.useState("email");
14386
14918
  const [templateItems, setTemplateItems] = React26.useState([]);
@@ -14424,19 +14956,20 @@ function EventNotificationsPluginSettings({ settingsGroup, enabled, onEnabledCha
14424
14956
  className: "space-y-2 text-sm text-gray-700 dark:text-gray-300"
14425
14957
  }, /* @__PURE__ */ React.createElement("p", {
14426
14958
  className: "font-medium text-gray-900 dark:text-white"
14427
- }, "How event notifications work"), /* @__PURE__ */ React.createElement("ol", {
14959
+ }, "Order notifications"), /* @__PURE__ */ React.createElement("ol", {
14428
14960
  className: "list-decimal pl-4 space-y-1 text-xs leading-relaxed"
14429
- }, /* @__PURE__ */ React.createElement("li", null, "Configure ", /* @__PURE__ */ React.createElement("strong", null, "global templates"), " here (email + WhatsApp)."), /* @__PURE__ */ React.createElement("li", null, "Enable notifications per event under", " ", /* @__PURE__ */ React.createElement(Link2__default.default, {
14430
- href: "/admin/events",
14431
- className: "text-blue-600 hover:underline"
14432
- }, "Events \u2192 Edit \u2192 Event settings"), "."), /* @__PURE__ */ React.createElement("li", null, "When an order is placed, customers receive order details and a QR code to track / check in.")), /* @__PURE__ */ React.createElement("p", {
14961
+ }, /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement("strong", null, "Email"), " tab: configure the order confirmation email template."), /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement("strong", null, "WhatsApp"), " tab: sync Meta templates, then link each trigger from the database list to a template."), /* @__PURE__ */ React.createElement("li", null, "Triggers are stored in ", /* @__PURE__ */ React.createElement("code", {
14962
+ className: "text-[11px]"
14963
+ }, "order_notification_triggers"), " (migration seeds defaults). Bindings live in", " ", /* @__PURE__ */ React.createElement("code", {
14964
+ className: "text-[11px]"
14965
+ }, "whatsapp_trigger_bindings"), ".")), /* @__PURE__ */ React.createElement("p", {
14433
14966
  className: "text-xs text-gray-500 dark:text-gray-400"
14434
14967
  }, "Requires ", /* @__PURE__ */ React.createElement("strong", null, "Email"), " plugin (SMTP) for email and ", /* @__PURE__ */ React.createElement("strong", null, "WhatsApp"), " plugin (Meta credentials) for WhatsApp delivery.")))), /* @__PURE__ */ React.createElement("div", {
14435
14968
  className: "flex items-center justify-between gap-2"
14436
14969
  }, /* @__PURE__ */ React.createElement(Label3, {
14437
14970
  htmlFor: `${settingsGroup}-enabled`,
14438
14971
  className: "text-sm"
14439
- }, "Event notifications enabled"), /* @__PURE__ */ React.createElement(Switch, {
14972
+ }, "Order notifications enabled"), /* @__PURE__ */ React.createElement(Switch, {
14440
14973
  id: `${settingsGroup}-enabled`,
14441
14974
  checked: enabled,
14442
14975
  onCheckedChange: onEnabledChange
@@ -14456,7 +14989,7 @@ function EventNotificationsPluginSettings({ settingsGroup, enabled, onEnabledCha
14456
14989
  className: `inline-flex items-center gap-2 px-4 py-2.5 text-sm font-medium border-b-2 ${tab === "whatsapp" ? "border-gray-800 text-gray-800 dark:border-gray-200 dark:text-gray-100" : "border-transparent text-gray-500 hover:text-gray-700"}`
14457
14990
  }, /* @__PURE__ */ React.createElement(LucideIcons.MessageCircle, {
14458
14991
  className: "h-4 w-4"
14459
- }), "WhatsApp template"))), loadingTemplates ? /* @__PURE__ */ React.createElement("p", {
14992
+ }), "WhatsApp template"))), tab === "whatsapp" ? /* @__PURE__ */ React.createElement(WhatsAppTriggerBindings, null) : loadingTemplates ? /* @__PURE__ */ React.createElement("p", {
14460
14993
  className: "text-sm text-gray-500"
14461
14994
  }, "Loading templates\u2026") : /* @__PURE__ */ React.createElement(EventOrderGlobalTemplates, {
14462
14995
  items: templateItems,
@@ -14479,6 +15012,7 @@ var init_EventNotificationsPluginSettings = __esm({
14479
15012
  init_label();
14480
15013
  init_switch();
14481
15014
  init_EventOrderGlobalTemplates();
15015
+ init_whatsappTriggerBindingsPage();
14482
15016
  __name(EventNotificationsPluginSettings, "EventNotificationsPluginSettings");
14483
15017
  }
14484
15018
  });
@@ -14858,6 +15392,7 @@ function PluginSettingsPanel({ descriptor, onSaved }) {
14858
15392
  const isWhatsapp = settingsGroup === "whatsapp";
14859
15393
  const isEventNotifications = settingsGroup === "event_notifications";
14860
15394
  const isSocialMedia = settingsGroup === "social_media";
15395
+ const isMultiVendor = settingsGroup === "multi_vendor";
14861
15396
  const [enabled, setEnabled] = React26.useState(true);
14862
15397
  const [botName, setBotName] = React26.useState("");
14863
15398
  const [icon, setIcon] = React26.useState("");
@@ -14938,6 +15473,7 @@ function PluginSettingsPanel({ descriptor, onSaved }) {
14938
15473
  const [smsTplItems, setSmsTplItems] = React26.useState([]);
14939
15474
  const [whatsappAccessToken, setWhatsappAccessToken] = React26.useState("");
14940
15475
  const [whatsappPhoneNumberId, setWhatsappPhoneNumberId] = React26.useState("");
15476
+ const [whatsappWabaId, setWhatsappWabaId] = React26.useState("");
14941
15477
  const [whatsappHasSavedToken, setWhatsappHasSavedToken] = React26.useState(false);
14942
15478
  const [loading, setLoading] = React26.useState(true);
14943
15479
  const [saving, setSaving] = React26.useState(false);
@@ -15204,6 +15740,7 @@ function PluginSettingsPanel({ descriptor, onSaved }) {
15204
15740
  setWhatsappAccessToken(savedToken);
15205
15741
  setWhatsappHasSavedToken(Boolean(savedToken));
15206
15742
  setWhatsappPhoneNumberId(String(data.phoneNumberId ?? data.WHATSAPP_PHONE_NUMBER_ID ?? "").trim());
15743
+ setWhatsappWabaId(String(data.wabaId ?? data.WHATSAPP_WABA_ID ?? "").trim());
15207
15744
  }
15208
15745
  if (isSocialMedia) {
15209
15746
  const savedLiToken = String(data.linkedin_access_token ?? "").trim();
@@ -15241,7 +15778,8 @@ function PluginSettingsPanel({ descriptor, onSaved }) {
15241
15778
  isSms,
15242
15779
  isWhatsapp,
15243
15780
  isEventNotifications,
15244
- isSocialMedia
15781
+ isSocialMedia,
15782
+ isMultiVendor
15245
15783
  ]);
15246
15784
  React26.useEffect(() => {
15247
15785
  if (!isSocialMedia || loading || linkedInOrgsPrefetchedRef.current) return;
@@ -15656,6 +16194,10 @@ function PluginSettingsPanel({ descriptor, onSaved }) {
15656
16194
  phoneNumberId: {
15657
16195
  value: whatsappPhoneNumberId.trim(),
15658
16196
  type: "public"
16197
+ },
16198
+ wabaId: {
16199
+ value: whatsappWabaId.trim(),
16200
+ type: "public"
15659
16201
  }
15660
16202
  };
15661
16203
  if (whatsappAccessToken.trim()) {
@@ -15667,6 +16209,14 @@ function PluginSettingsPanel({ descriptor, onSaved }) {
15667
16209
  }
15668
16210
  return payload2;
15669
16211
  }
16212
+ if (isMultiVendor) {
16213
+ return {
16214
+ enabled: {
16215
+ value: enabled ? "true" : "false",
16216
+ type: "public"
16217
+ }
16218
+ };
16219
+ }
15670
16220
  if (isEventNotifications) {
15671
16221
  return {
15672
16222
  enabled: {
@@ -16255,6 +16805,27 @@ function PluginSettingsPanel({ descriptor, onSaved }) {
16255
16805
  className: "h-3.5 w-3.5"
16256
16806
  }), "Save"));
16257
16807
  }
16808
+ if (isMultiVendor) {
16809
+ return /* @__PURE__ */ React.createElement("div", {
16810
+ className: "space-y-4"
16811
+ }, /* @__PURE__ */ React.createElement("div", {
16812
+ className: "flex items-center justify-between gap-2"
16813
+ }, /* @__PURE__ */ React.createElement(Label3, {
16814
+ htmlFor: `${settingsGroup}-enabled`,
16815
+ className: "text-sm"
16816
+ }, "Enabled"), /* @__PURE__ */ React.createElement(Switch, {
16817
+ id: `${settingsGroup}-enabled`,
16818
+ checked: enabled,
16819
+ onCheckedChange: setEnabled
16820
+ })), /* @__PURE__ */ React.createElement(Button, {
16821
+ size: "sm",
16822
+ onClick: handleSave,
16823
+ disabled: saving,
16824
+ className: "gap-1"
16825
+ }, /* @__PURE__ */ React.createElement(LucideIcons.Save, {
16826
+ className: "h-3.5 w-3.5"
16827
+ }), "Save"));
16828
+ }
16258
16829
  if (isEventNotifications) {
16259
16830
  return /* @__PURE__ */ React.createElement(EventNotificationsPluginSettings, {
16260
16831
  settingsGroup,
@@ -16483,6 +17054,19 @@ function PluginSettingsPanel({ descriptor, onSaved }) {
16483
17054
  className: "h-9 text-sm"
16484
17055
  })), /* @__PURE__ */ React.createElement("div", {
16485
17056
  className: "space-y-1"
17057
+ }, /* @__PURE__ */ React.createElement(Label3, {
17058
+ htmlFor: `${settingsGroup}-wabaId`,
17059
+ className: "text-sm"
17060
+ }, "WhatsApp Business Account (WABA) ID"), /* @__PURE__ */ React.createElement(Input, {
17061
+ id: `${settingsGroup}-wabaId`,
17062
+ value: whatsappWabaId,
17063
+ onChange: /* @__PURE__ */ __name((e) => setWhatsappWabaId(e.target.value), "onChange"),
17064
+ placeholder: "From Meta Business Manager \u2192 WhatsApp Accounts",
17065
+ className: "h-9 text-sm"
17066
+ }), /* @__PURE__ */ React.createElement("p", {
17067
+ className: "text-xs text-gray-500 dark:text-gray-400"
17068
+ }, "Used to list/sync approved templates for this account \u2014 distinct from the phone number ID above.")), /* @__PURE__ */ React.createElement("div", {
17069
+ className: "space-y-1"
16486
17070
  }, /* @__PURE__ */ React.createElement(Label3, {
16487
17071
  htmlFor: `${settingsGroup}-accessToken`,
16488
17072
  className: "text-sm"
@@ -16493,9 +17077,7 @@ function PluginSettingsPanel({ descriptor, onSaved }) {
16493
17077
  onChange: /* @__PURE__ */ __name((e) => setWhatsappAccessToken(e.target.value), "onChange"),
16494
17078
  placeholder: "Permanent or system user token",
16495
17079
  className: "h-9 text-sm"
16496
- })), /* @__PURE__ */ React.createElement("p", {
16497
- className: "text-xs text-gray-500 dark:text-gray-400"
16498
- }, "Message templates for events are configured under Plugins \u2192 Event notifications."), /* @__PURE__ */ React.createElement(Button, {
17080
+ })), /* @__PURE__ */ React.createElement(Button, {
16499
17081
  size: "sm",
16500
17082
  onClick: handleSave,
16501
17083
  disabled: saving
@@ -24173,7 +24755,7 @@ function LayoutPanelContent() {
24173
24755
  flexFill: props.flexFill ?? false
24174
24756
  };
24175
24757
  const fieldCls = "flex items-center gap-2 min-h-[28px]";
24176
- const labelCls9 = "text-[11px] text-gray-500 font-medium w-14 shrink-0";
24758
+ const labelCls8 = "text-[11px] text-gray-500 font-medium w-14 shrink-0";
24177
24759
  const inputCls9 = "h-7 text-xs flex-1 min-w-0 rounded border border-input bg-background px-2";
24178
24760
  const selectCls = "h-7 w-full text-xs rounded border border-input bg-background px-2";
24179
24761
  return /* @__PURE__ */ React26__namespace.default.createElement("div", {
@@ -24187,7 +24769,7 @@ function LayoutPanelContent() {
24187
24769
  }, /* @__PURE__ */ React26__namespace.default.createElement("div", {
24188
24770
  className: fieldCls
24189
24771
  }, /* @__PURE__ */ React26__namespace.default.createElement(Label3, {
24190
- className: labelCls9
24772
+ className: labelCls8
24191
24773
  }, "W"), /* @__PURE__ */ React26__namespace.default.createElement(Input, {
24192
24774
  value: layoutProps.width,
24193
24775
  onChange: /* @__PURE__ */ __name((e) => setLayoutProp("width", e.target.value), "onChange"),
@@ -24196,7 +24778,7 @@ function LayoutPanelContent() {
24196
24778
  })), /* @__PURE__ */ React26__namespace.default.createElement("div", {
24197
24779
  className: fieldCls
24198
24780
  }, /* @__PURE__ */ React26__namespace.default.createElement(Label3, {
24199
- className: labelCls9
24781
+ className: labelCls8
24200
24782
  }, "H"), /* @__PURE__ */ React26__namespace.default.createElement(Input, {
24201
24783
  value: layoutProps.height,
24202
24784
  onChange: /* @__PURE__ */ __name((e) => setLayoutProp("height", e.target.value), "onChange"),
@@ -24211,7 +24793,7 @@ function LayoutPanelContent() {
24211
24793
  }, /* @__PURE__ */ React26__namespace.default.createElement("div", {
24212
24794
  className: fieldCls
24213
24795
  }, /* @__PURE__ */ React26__namespace.default.createElement(Label3, {
24214
- className: labelCls9
24796
+ className: labelCls8
24215
24797
  }, "Margin"), /* @__PURE__ */ React26__namespace.default.createElement(Input, {
24216
24798
  value: layoutProps.margin,
24217
24799
  onChange: /* @__PURE__ */ __name((e) => setLayoutProp("margin", e.target.value), "onChange"),
@@ -24220,7 +24802,7 @@ function LayoutPanelContent() {
24220
24802
  })), /* @__PURE__ */ React26__namespace.default.createElement("div", {
24221
24803
  className: fieldCls
24222
24804
  }, /* @__PURE__ */ React26__namespace.default.createElement(Label3, {
24223
- className: labelCls9
24805
+ className: labelCls8
24224
24806
  }, "Padding"), /* @__PURE__ */ React26__namespace.default.createElement(Input, {
24225
24807
  value: layoutProps.padding,
24226
24808
  onChange: /* @__PURE__ */ __name((e) => setLayoutProp("padding", e.target.value), "onChange"),
@@ -24235,7 +24817,7 @@ function LayoutPanelContent() {
24235
24817
  }, /* @__PURE__ */ React26__namespace.default.createElement("div", {
24236
24818
  className: fieldCls
24237
24819
  }, /* @__PURE__ */ React26__namespace.default.createElement(Label3, {
24238
- className: labelCls9
24820
+ className: labelCls8
24239
24821
  }, "Radius"), /* @__PURE__ */ React26__namespace.default.createElement(Input, {
24240
24822
  value: layoutProps.borderRadius,
24241
24823
  onChange: /* @__PURE__ */ __name((e) => setLayoutProp("borderRadius", e.target.value), "onChange"),
@@ -24244,7 +24826,7 @@ function LayoutPanelContent() {
24244
24826
  })), /* @__PURE__ */ React26__namespace.default.createElement("div", {
24245
24827
  className: fieldCls
24246
24828
  }, /* @__PURE__ */ React26__namespace.default.createElement(Label3, {
24247
- className: labelCls9
24829
+ className: labelCls8
24248
24830
  }, "Shadow"), /* @__PURE__ */ React26__namespace.default.createElement(Input, {
24249
24831
  value: layoutProps.boxShadow,
24250
24832
  onChange: /* @__PURE__ */ __name((e) => setLayoutProp("boxShadow", e.target.value), "onChange"),
@@ -24259,7 +24841,7 @@ function LayoutPanelContent() {
24259
24841
  }, /* @__PURE__ */ React26__namespace.default.createElement("div", {
24260
24842
  className: fieldCls
24261
24843
  }, /* @__PURE__ */ React26__namespace.default.createElement(Label3, {
24262
- className: labelCls9
24844
+ className: labelCls8
24263
24845
  }, "Direction"), /* @__PURE__ */ React26__namespace.default.createElement("select", {
24264
24846
  value: layoutProps.flexDirection,
24265
24847
  onChange: /* @__PURE__ */ __name((e) => setLayoutProp("flexDirection", e.target.value), "onChange"),
@@ -24275,7 +24857,7 @@ function LayoutPanelContent() {
24275
24857
  }, "Column reverse"))), /* @__PURE__ */ React26__namespace.default.createElement("div", {
24276
24858
  className: fieldCls
24277
24859
  }, /* @__PURE__ */ React26__namespace.default.createElement(Label3, {
24278
- className: labelCls9
24860
+ className: labelCls8
24279
24861
  }, "Align"), /* @__PURE__ */ React26__namespace.default.createElement("select", {
24280
24862
  value: layoutProps.alignItems,
24281
24863
  onChange: /* @__PURE__ */ __name((e) => setLayoutProp("alignItems", e.target.value), "onChange"),
@@ -24291,7 +24873,7 @@ function LayoutPanelContent() {
24291
24873
  }, "Stretch"))), /* @__PURE__ */ React26__namespace.default.createElement("div", {
24292
24874
  className: fieldCls
24293
24875
  }, /* @__PURE__ */ React26__namespace.default.createElement(Label3, {
24294
- className: labelCls9
24876
+ className: labelCls8
24295
24877
  }, "Justify"), /* @__PURE__ */ React26__namespace.default.createElement("select", {
24296
24878
  value: layoutProps.justifyContent,
24297
24879
  onChange: /* @__PURE__ */ __name((e) => setLayoutProp("justifyContent", e.target.value), "onChange"),
@@ -28860,428 +29442,6 @@ var init_EventProductsSection = __esm({
28860
29442
  __name(EventProductsSection, "EventProductsSection");
28861
29443
  }
28862
29444
  });
28863
- function VariableChip({ name, onCopy }) {
28864
- return /* @__PURE__ */ React.createElement("button", {
28865
- type: "button",
28866
- onClick: onCopy,
28867
- className: "inline-flex items-center rounded-md border border-gray-200 bg-white px-2 py-0.5 font-mono text-[11px] text-gray-700 hover:border-gray-300 hover:bg-gray-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700",
28868
- title: "Click to copy"
28869
- }, `{{${name}}}`);
28870
- }
28871
- function ChannelToggle({ label, icon: Icon2, checked, onChange }) {
28872
- return /* @__PURE__ */ React.createElement("button", {
28873
- type: "button",
28874
- role: "checkbox",
28875
- "aria-checked": checked,
28876
- onClick: onChange,
28877
- className: `inline-flex items-center gap-2 rounded-lg border px-3 py-2 text-sm font-medium transition-colors ${checked ? "border-gray-800 bg-gray-900 text-white dark:border-gray-300 dark:bg-gray-100 dark:text-gray-900" : "border-gray-200 bg-white text-gray-700 hover:border-gray-300 hover:bg-gray-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700"}`
28878
- }, /* @__PURE__ */ React.createElement(Icon2, {
28879
- className: "h-4 w-4 shrink-0"
28880
- }), label);
28881
- }
28882
- function EventNotificationSettings({ eventId }) {
28883
- const [loading, setLoading] = React26.useState(true);
28884
- const [saving, setSaving] = React26.useState(false);
28885
- const [settings, setSettings] = React26.useState(null);
28886
- const [testEmail, setTestEmail] = React26.useState("");
28887
- const [testPhone, setTestPhone] = React26.useState("");
28888
- const [testing, setTesting] = React26.useState(null);
28889
- const [varsOpen, setVarsOpen] = React26.useState(false);
28890
- const load = React26.useCallback(async () => {
28891
- setLoading(true);
28892
- try {
28893
- const res = await fetch(`/api/events/${eventId}/notifications`);
28894
- if (!res.ok) throw new Error("Failed to load");
28895
- const data = await res.json();
28896
- setSettings(data);
28897
- } catch {
28898
- sonner.toast.error("Could not load notification settings");
28899
- } finally {
28900
- setLoading(false);
28901
- }
28902
- }, [
28903
- eventId
28904
- ]);
28905
- React26.useEffect(() => {
28906
- void load();
28907
- }, [
28908
- load
28909
- ]);
28910
- const toggleChannel = /* @__PURE__ */ __name((ch) => {
28911
- if (!settings) return;
28912
- const has = settings.channels.includes(ch);
28913
- setSettings({
28914
- ...settings,
28915
- channels: has ? settings.channels.filter((c) => c !== ch) : [
28916
- ...settings.channels,
28917
- ch
28918
- ]
28919
- });
28920
- }, "toggleChannel");
28921
- const updateTemplate = /* @__PURE__ */ __name((ch, patch) => {
28922
- if (!settings) return;
28923
- setSettings({
28924
- ...settings,
28925
- templates: {
28926
- ...settings.templates,
28927
- [ch]: {
28928
- ...settings.templates[ch],
28929
- ...patch
28930
- }
28931
- }
28932
- });
28933
- }, "updateTemplate");
28934
- const resetTemplate = /* @__PURE__ */ __name((ch) => {
28935
- if (!settings) return;
28936
- const def = settings.globalDefaults.find((d) => d.channel === ch);
28937
- if (!def) return;
28938
- setSettings({
28939
- ...settings,
28940
- templates: {
28941
- ...settings.templates,
28942
- [ch]: {
28943
- subject: def.subject ?? "",
28944
- body: def.body,
28945
- externalTemplateRef: def.externalTemplateRef ?? ""
28946
- }
28947
- }
28948
- });
28949
- sonner.toast.success(`${ch === "email" ? "Email" : "WhatsApp"} template reset to default`);
28950
- }, "resetTemplate");
28951
- const copyVariable = /* @__PURE__ */ __name(async (name) => {
28952
- try {
28953
- await navigator.clipboard.writeText(`{{${name}}}`);
28954
- sonner.toast.success(`Copied {{${name}}}`);
28955
- } catch {
28956
- sonner.toast.error("Could not copy");
28957
- }
28958
- }, "copyVariable");
28959
- const handleSave = /* @__PURE__ */ __name(async () => {
28960
- if (!settings) return;
28961
- setSaving(true);
28962
- try {
28963
- const res = await fetch(`/api/events/${eventId}/notifications`, {
28964
- method: "PUT",
28965
- headers: {
28966
- "Content-Type": "application/json"
28967
- },
28968
- body: JSON.stringify({
28969
- enabled: settings.enabled,
28970
- channels: settings.channels,
28971
- templates: settings.templates
28972
- })
28973
- });
28974
- if (!res.ok) throw new Error();
28975
- sonner.toast.success("Notification settings saved");
28976
- await load();
28977
- } catch {
28978
- sonner.toast.error("Failed to save notification settings");
28979
- } finally {
28980
- setSaving(false);
28981
- }
28982
- }, "handleSave");
28983
- const sendTest = /* @__PURE__ */ __name(async (channel) => {
28984
- setTesting(channel);
28985
- try {
28986
- const res = await fetch(`/api/events/${eventId}/notifications/test`, {
28987
- method: "POST",
28988
- headers: {
28989
- "Content-Type": "application/json"
28990
- },
28991
- body: JSON.stringify({
28992
- channel,
28993
- email: testEmail.trim() || void 0,
28994
- phone: testPhone.trim() || void 0
28995
- })
28996
- });
28997
- const data = await res.json().catch(() => ({}));
28998
- if (!res.ok) {
28999
- sonner.toast.error(data.error ?? "Test failed");
29000
- return;
29001
- }
29002
- sonner.toast.success(data.message ?? "Test notification queued");
29003
- } catch {
29004
- sonner.toast.error("Test failed");
29005
- } finally {
29006
- setTesting(null);
29007
- }
29008
- }, "sendTest");
29009
- if (loading) {
29010
- return /* @__PURE__ */ React.createElement("div", {
29011
- className: `${panelCls} flex items-center gap-2 text-sm text-gray-500`
29012
- }, /* @__PURE__ */ React.createElement(LucideIcons.Loader2, {
29013
- className: "h-4 w-4 animate-spin"
29014
- }), "Loading notification settings\u2026");
29015
- }
29016
- if (!settings) return null;
29017
- const emailTpl = settings.templates.email ?? {};
29018
- const waTpl = settings.templates.whatsapp ?? {};
29019
- const emailDefault = settings.globalDefaults.find((d) => d.channel === "email");
29020
- const waDefault = settings.globalDefaults.find((d) => d.channel === "whatsapp");
29021
- return /* @__PURE__ */ React.createElement("div", {
29022
- className: "space-y-5"
29023
- }, /* @__PURE__ */ React.createElement("div", {
29024
- className: panelCls
29025
- }, /* @__PURE__ */ React.createElement("div", {
29026
- className: "flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between"
29027
- }, /* @__PURE__ */ React.createElement("div", {
29028
- className: "space-y-1 min-w-0"
29029
- }, /* @__PURE__ */ React.createElement("label", {
29030
- className: "flex items-start gap-3 cursor-pointer group"
29031
- }, /* @__PURE__ */ React.createElement("input", {
29032
- type: "checkbox",
29033
- checked: settings.enabled,
29034
- onChange: /* @__PURE__ */ __name((e) => setSettings({
29035
- ...settings,
29036
- enabled: e.target.checked
29037
- }), "onChange"),
29038
- className: "mt-0.5 h-4 w-4 rounded border-gray-300"
29039
- }), /* @__PURE__ */ React.createElement("span", null, /* @__PURE__ */ React.createElement("span", {
29040
- className: "block text-sm font-medium text-gray-900 dark:text-gray-100"
29041
- }, "Send notifications when an order is placed"), /* @__PURE__ */ React.createElement("span", {
29042
- className: hintCls
29043
- }, "Uses global templates from Plugins \u2192 Event notifications. Requires Email and/or WhatsApp plugins for delivery."))))), settings.enabled ? /* @__PURE__ */ React.createElement("div", {
29044
- className: "mt-5 pt-5 border-t border-gray-100 dark:border-gray-700"
29045
- }, /* @__PURE__ */ React.createElement("p", {
29046
- className: labelCls5
29047
- }, "Channels"), /* @__PURE__ */ React.createElement("div", {
29048
- className: "flex flex-wrap gap-2"
29049
- }, /* @__PURE__ */ React.createElement(ChannelToggle, {
29050
- label: "Email",
29051
- icon: LucideIcons.Mail,
29052
- checked: settings.channels.includes("email"),
29053
- onChange: /* @__PURE__ */ __name(() => toggleChannel("email"), "onChange")
29054
- }), /* @__PURE__ */ React.createElement(ChannelToggle, {
29055
- label: "WhatsApp",
29056
- icon: LucideIcons.MessageCircle,
29057
- checked: settings.channels.includes("whatsapp"),
29058
- onChange: /* @__PURE__ */ __name(() => toggleChannel("whatsapp"), "onChange")
29059
- })), settings.channels.length === 0 ? /* @__PURE__ */ React.createElement("p", {
29060
- className: "mt-2 text-xs text-amber-700 dark:text-amber-400"
29061
- }, "Select at least one channel to send notifications.") : null) : null), settings.enabled && settings.channels.length > 0 ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", {
29062
- className: panelCls
29063
- }, /* @__PURE__ */ React.createElement("button", {
29064
- type: "button",
29065
- onClick: /* @__PURE__ */ __name(() => setVarsOpen((o) => !o), "onClick"),
29066
- className: "flex w-full items-center justify-between gap-2 text-left"
29067
- }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("p", {
29068
- className: "text-sm font-medium text-gray-900 dark:text-gray-100"
29069
- }, "Template variables"), /* @__PURE__ */ React.createElement("p", {
29070
- className: hintCls
29071
- }, "Click a variable to copy it into your template.")), varsOpen ? /* @__PURE__ */ React.createElement(LucideIcons.ChevronUp, {
29072
- className: "h-4 w-4 shrink-0 text-gray-400"
29073
- }) : /* @__PURE__ */ React.createElement(LucideIcons.ChevronDown, {
29074
- className: "h-4 w-4 shrink-0 text-gray-400"
29075
- })), varsOpen ? /* @__PURE__ */ React.createElement("div", {
29076
- className: "mt-3 flex flex-wrap gap-1.5"
29077
- }, settings.templateVariables.map((v) => /* @__PURE__ */ React.createElement(VariableChip, {
29078
- key: v,
29079
- name: v,
29080
- onCopy: /* @__PURE__ */ __name(() => copyVariable(v), "onCopy")
29081
- }))) : null), settings.channels.includes("email") ? /* @__PURE__ */ React.createElement("div", {
29082
- className: panelCls
29083
- }, /* @__PURE__ */ React.createElement("div", {
29084
- className: "flex flex-wrap items-center justify-between gap-3 mb-4"
29085
- }, /* @__PURE__ */ React.createElement("div", {
29086
- className: "flex items-center gap-2"
29087
- }, /* @__PURE__ */ React.createElement(LucideIcons.Mail, {
29088
- className: "h-4 w-4 text-gray-500"
29089
- }), /* @__PURE__ */ React.createElement("h3", {
29090
- className: "text-sm font-semibold text-gray-900 dark:text-gray-100"
29091
- }, "Email template")), /* @__PURE__ */ React.createElement(Button, {
29092
- type: "button",
29093
- variant: "outline",
29094
- size: "sm",
29095
- onClick: /* @__PURE__ */ __name(() => resetTemplate("email"), "onClick"),
29096
- className: "gap-1.5 h-8"
29097
- }, /* @__PURE__ */ React.createElement(LucideIcons.RotateCcw, {
29098
- className: "h-3.5 w-3.5"
29099
- }), "Reset to default")), /* @__PURE__ */ React.createElement("div", {
29100
- className: subPanelCls
29101
- }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(Label3, {
29102
- className: labelCls5
29103
- }, "Subject"), /* @__PURE__ */ React.createElement(Input, {
29104
- value: emailTpl.subject ?? "",
29105
- onChange: /* @__PURE__ */ __name((e) => updateTemplate("email", {
29106
- subject: e.target.value
29107
- }), "onChange"),
29108
- className: "h-9 text-sm",
29109
- placeholder: emailDefault?.subject ?? "Order confirmation for {{eventName}}"
29110
- })), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(Label3, {
29111
- className: labelCls5
29112
- }, "Body"), /* @__PURE__ */ React.createElement("p", {
29113
- className: `${hintCls} mb-2`
29114
- }, "HTML is supported. Use variables from the list above."), /* @__PURE__ */ React.createElement(Textarea, {
29115
- value: emailTpl.body ?? "",
29116
- onChange: /* @__PURE__ */ __name((e) => updateTemplate("email", {
29117
- body: e.target.value
29118
- }), "onChange"),
29119
- rows: 8,
29120
- className: "text-sm font-mono min-h-[180px] resize-y",
29121
- placeholder: emailDefault?.body ?? ""
29122
- })))) : null, settings.channels.includes("whatsapp") ? /* @__PURE__ */ React.createElement("div", {
29123
- className: panelCls
29124
- }, /* @__PURE__ */ React.createElement("div", {
29125
- className: "flex flex-wrap items-center justify-between gap-3 mb-4"
29126
- }, /* @__PURE__ */ React.createElement("div", {
29127
- className: "flex items-center gap-2"
29128
- }, /* @__PURE__ */ React.createElement(LucideIcons.MessageCircle, {
29129
- className: "h-4 w-4 text-gray-500"
29130
- }), /* @__PURE__ */ React.createElement("h3", {
29131
- className: "text-sm font-semibold text-gray-900 dark:text-gray-100"
29132
- }, "WhatsApp template")), /* @__PURE__ */ React.createElement(Button, {
29133
- type: "button",
29134
- variant: "outline",
29135
- size: "sm",
29136
- onClick: /* @__PURE__ */ __name(() => resetTemplate("whatsapp"), "onClick"),
29137
- className: "gap-1.5 h-8"
29138
- }, /* @__PURE__ */ React.createElement(LucideIcons.RotateCcw, {
29139
- className: "h-3.5 w-3.5"
29140
- }), "Reset to default")), /* @__PURE__ */ React.createElement("div", {
29141
- className: subPanelCls
29142
- }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(Label3, {
29143
- className: labelCls5
29144
- }, "Meta approved template name"), /* @__PURE__ */ React.createElement(Input, {
29145
- value: waTpl.externalTemplateRef ?? "",
29146
- onChange: /* @__PURE__ */ __name((e) => updateTemplate("whatsapp", {
29147
- externalTemplateRef: e.target.value
29148
- }), "onChange"),
29149
- placeholder: waDefault?.externalTemplateRef ?? "event_order_placed",
29150
- className: "h-9 text-sm"
29151
- }), /* @__PURE__ */ React.createElement("p", {
29152
- className: `${hintCls} mt-1.5`
29153
- }, "Must match a template approved in your Meta Business account.")), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(Label3, {
29154
- className: labelCls5
29155
- }, "Body (reference)"), /* @__PURE__ */ React.createElement("p", {
29156
- className: `${hintCls} mb-2`
29157
- }, "Used as fallback documentation; WhatsApp sends via the Meta template above."), /* @__PURE__ */ React.createElement(Textarea, {
29158
- value: waTpl.body ?? "",
29159
- onChange: /* @__PURE__ */ __name((e) => updateTemplate("whatsapp", {
29160
- body: e.target.value
29161
- }), "onChange"),
29162
- rows: 4,
29163
- className: "text-sm min-h-[100px] resize-y",
29164
- placeholder: waDefault?.body ?? ""
29165
- })))) : null, /* @__PURE__ */ React.createElement("div", {
29166
- className: panelCls
29167
- }, /* @__PURE__ */ React.createElement("p", {
29168
- className: "text-sm font-semibold text-gray-900 dark:text-gray-100 mb-1"
29169
- }, "Send test"), /* @__PURE__ */ React.createElement("p", {
29170
- className: `${hintCls} mb-4`
29171
- }, "Queue a test notification with sample order data. Uses the templates above (save first if you changed them)."), /* @__PURE__ */ React.createElement("div", {
29172
- className: "grid gap-4 sm:grid-cols-2"
29173
- }, /* @__PURE__ */ React.createElement("div", {
29174
- className: subPanelCls
29175
- }, /* @__PURE__ */ React.createElement("div", {
29176
- className: "flex items-center gap-2 mb-3"
29177
- }, /* @__PURE__ */ React.createElement(LucideIcons.Mail, {
29178
- className: "h-4 w-4 text-gray-500"
29179
- }), /* @__PURE__ */ React.createElement("span", {
29180
- className: "text-sm font-medium text-gray-900 dark:text-gray-100"
29181
- }, "Test email")), /* @__PURE__ */ React.createElement(Label3, {
29182
- className: labelCls5
29183
- }, "Recipient"), /* @__PURE__ */ React.createElement(Input, {
29184
- value: testEmail,
29185
- onChange: /* @__PURE__ */ __name((e) => setTestEmail(e.target.value), "onChange"),
29186
- type: "email",
29187
- className: "h-9 text-sm mb-3",
29188
- placeholder: "you@example.com"
29189
- }), /* @__PURE__ */ React.createElement(Button, {
29190
- type: "button",
29191
- variant: "outline",
29192
- size: "sm",
29193
- disabled: testing !== null || !settings.channels.includes("email"),
29194
- onClick: /* @__PURE__ */ __name(() => sendTest("email"), "onClick"),
29195
- className: "gap-1.5 w-full sm:w-auto"
29196
- }, testing === "email" ? /* @__PURE__ */ React.createElement(LucideIcons.Loader2, {
29197
- className: "h-3.5 w-3.5 animate-spin"
29198
- }) : /* @__PURE__ */ React.createElement(LucideIcons.Send, {
29199
- className: "h-3.5 w-3.5"
29200
- }), "Send test email")), /* @__PURE__ */ React.createElement("div", {
29201
- className: subPanelCls
29202
- }, /* @__PURE__ */ React.createElement("div", {
29203
- className: "flex items-center gap-2 mb-3"
29204
- }, /* @__PURE__ */ React.createElement(LucideIcons.MessageCircle, {
29205
- className: "h-4 w-4 text-gray-500"
29206
- }), /* @__PURE__ */ React.createElement("span", {
29207
- className: "text-sm font-medium text-gray-900 dark:text-gray-100"
29208
- }, "Test WhatsApp")), /* @__PURE__ */ React.createElement(Label3, {
29209
- className: labelCls5
29210
- }, "Phone number"), /* @__PURE__ */ React.createElement(Input, {
29211
- value: testPhone,
29212
- onChange: /* @__PURE__ */ __name((e) => setTestPhone(e.target.value), "onChange"),
29213
- className: "h-9 text-sm mb-3",
29214
- placeholder: "+91 98765 43210"
29215
- }), /* @__PURE__ */ React.createElement(Button, {
29216
- type: "button",
29217
- variant: "outline",
29218
- size: "sm",
29219
- disabled: testing !== null || !settings.channels.includes("whatsapp"),
29220
- onClick: /* @__PURE__ */ __name(() => sendTest("whatsapp"), "onClick"),
29221
- className: "gap-1.5 w-full sm:w-auto"
29222
- }, testing === "whatsapp" ? /* @__PURE__ */ React.createElement(LucideIcons.Loader2, {
29223
- className: "h-3.5 w-3.5 animate-spin"
29224
- }) : /* @__PURE__ */ React.createElement(LucideIcons.Send, {
29225
- className: "h-3.5 w-3.5"
29226
- }), "Send test WhatsApp"))))) : null, /* @__PURE__ */ React.createElement("div", {
29227
- className: "flex justify-end pt-1"
29228
- }, /* @__PURE__ */ React.createElement(Button, {
29229
- type: "button",
29230
- onClick: handleSave,
29231
- disabled: saving,
29232
- className: "min-w-[160px]"
29233
- }, saving ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(LucideIcons.Loader2, {
29234
- className: "h-4 w-4 animate-spin mr-2"
29235
- }), "Saving\u2026") : "Save settings")));
29236
- }
29237
- function EventNotificationSummary({ eventId }) {
29238
- const [summary, setSummary] = React26.useState(null);
29239
- React26.useEffect(() => {
29240
- let cancelled = false;
29241
- fetch(`/api/events/${eventId}/notifications`).then((r) => r.ok ? r.json() : null).then((data) => {
29242
- if (!cancelled && data) {
29243
- setSummary({
29244
- enabled: Boolean(data.enabled),
29245
- channels: data.channels ?? []
29246
- });
29247
- }
29248
- }).catch(() => void 0);
29249
- return () => {
29250
- cancelled = true;
29251
- };
29252
- }, [
29253
- eventId
29254
- ]);
29255
- if (!summary?.enabled) {
29256
- return /* @__PURE__ */ React.createElement("p", {
29257
- className: "text-sm text-gray-500"
29258
- }, "Order notifications: disabled");
29259
- }
29260
- const ch = summary.channels.length ? summary.channels.join(", ") : "none";
29261
- return /* @__PURE__ */ React.createElement("p", {
29262
- className: "text-sm text-gray-700 dark:text-gray-300"
29263
- }, "Order notifications: ", /* @__PURE__ */ React.createElement("span", {
29264
- className: "font-medium text-green-700 dark:text-green-400"
29265
- }, "enabled"), " (", ch, ")");
29266
- }
29267
- var panelCls, subPanelCls, labelCls5, hintCls;
29268
- var init_EventNotificationSettings = __esm({
29269
- "src/admin/components/EventNotificationSettings.tsx"() {
29270
- "use client";
29271
- init_button();
29272
- init_input();
29273
- init_label();
29274
- init_textarea();
29275
- panelCls = "rounded-lg border border-gray-200 bg-white p-4 sm:p-5 dark:border-gray-600 dark:bg-gray-900/30";
29276
- subPanelCls = "rounded-md border border-gray-100 bg-gray-50/80 p-4 space-y-4 dark:border-gray-700 dark:bg-gray-800/40";
29277
- labelCls5 = "block text-xs font-medium text-gray-600 dark:text-gray-400 mb-1.5";
29278
- hintCls = "text-xs text-gray-500 dark:text-gray-400 leading-relaxed";
29279
- __name(VariableChip, "VariableChip");
29280
- __name(ChannelToggle, "ChannelToggle");
29281
- __name(EventNotificationSettings, "EventNotificationSettings");
29282
- __name(EventNotificationSummary, "EventNotificationSummary");
29283
- }
29284
- });
29285
29445
 
29286
29446
  // src/lib/social-media-links.ts
29287
29447
  function isValidHttpUrl(value) {
@@ -29382,7 +29542,7 @@ function SocialMediaLinksForm({ fields, values, onChange }) {
29382
29542
  return /* @__PURE__ */ React.createElement("div", {
29383
29543
  key: field.key
29384
29544
  }, /* @__PURE__ */ React.createElement("label", {
29385
- className: labelCls6
29545
+ className: labelCls5
29386
29546
  }, field.label), /* @__PURE__ */ React.createElement("div", {
29387
29547
  className: "relative"
29388
29548
  }, Icon2 ? /* @__PURE__ */ React.createElement(Icon2, {
@@ -29541,14 +29701,14 @@ function MultiCurrencyPriceFields({ defaultCurrency, currencies, defaultPrice, a
29541
29701
  }));
29542
29702
  }))) : null);
29543
29703
  }
29544
- var inputCls5, labelCls6, ICONS;
29704
+ var inputCls5, labelCls5, ICONS;
29545
29705
  var init_EventManagementFields = __esm({
29546
29706
  "src/components/Admin/EventManagementFields.tsx"() {
29547
29707
  "use client";
29548
29708
  init_social_brand_icons();
29549
29709
  init_social_media_links();
29550
29710
  inputCls5 = "w-full rounded-md border border-gray-300 px-2 py-1.5 text-sm pl-9";
29551
- labelCls6 = "block text-xs font-medium text-gray-600 mb-1";
29711
+ labelCls5 = "block text-xs font-medium text-gray-600 mb-1";
29552
29712
  ICONS = {
29553
29713
  facebook: FacebookBrandIcon,
29554
29714
  instagram: InstagramBrandIcon,
@@ -29924,7 +30084,7 @@ __export(EventEditPage_exports, {
29924
30084
  });
29925
30085
  function RequiredLabel({ children }) {
29926
30086
  return /* @__PURE__ */ React.createElement("label", {
29927
- className: labelCls7
30087
+ className: labelCls6
29928
30088
  }, children, " ", /* @__PURE__ */ React.createElement("span", {
29929
30089
  className: "text-red-600"
29930
30090
  }, "*"));
@@ -30369,21 +30529,21 @@ function EventEditPage({ eventId }) {
30369
30529
  }, /* @__PURE__ */ React.createElement("div", {
30370
30530
  className: "sm:col-span-2"
30371
30531
  }, /* @__PURE__ */ React.createElement("label", {
30372
- className: labelCls7
30532
+ className: labelCls6
30373
30533
  }, "Name"), /* @__PURE__ */ React.createElement("input", {
30374
30534
  type: "text",
30375
30535
  value: name,
30376
30536
  onChange: /* @__PURE__ */ __name((e) => setName(e.target.value), "onChange"),
30377
30537
  className: inputCls6
30378
30538
  })), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("label", {
30379
- className: labelCls7
30539
+ className: labelCls6
30380
30540
  }, "Slug"), /* @__PURE__ */ React.createElement("input", {
30381
30541
  type: "text",
30382
30542
  value: slug,
30383
30543
  onChange: /* @__PURE__ */ __name((e) => setSlug(e.target.value), "onChange"),
30384
30544
  className: inputCls6
30385
30545
  })), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("label", {
30386
- className: labelCls7
30546
+ className: labelCls6
30387
30547
  }, "Sort order"), /* @__PURE__ */ React.createElement("input", {
30388
30548
  type: "number",
30389
30549
  value: sortOrder,
@@ -30392,7 +30552,7 @@ function EventEditPage({ eventId }) {
30392
30552
  })), /* @__PURE__ */ React.createElement("div", {
30393
30553
  className: "sm:col-span-2"
30394
30554
  }, /* @__PURE__ */ React.createElement("label", {
30395
- className: labelCls7
30555
+ className: labelCls6
30396
30556
  }, "Description"), /* @__PURE__ */ React.createElement("div", {
30397
30557
  className: "rounded-md border border-gray-300 bg-white overflow-hidden"
30398
30558
  }, /* @__PURE__ */ React.createElement(JoditRichText, {
@@ -30403,7 +30563,7 @@ function EventEditPage({ eventId }) {
30403
30563
  }))), /* @__PURE__ */ React.createElement("div", {
30404
30564
  className: "sm:col-span-2"
30405
30565
  }, /* @__PURE__ */ React.createElement("label", {
30406
- className: labelCls7
30566
+ className: labelCls6
30407
30567
  }, "Entity types"), /* @__PURE__ */ React.createElement("div", {
30408
30568
  className: "flex flex-wrap gap-2"
30409
30569
  }, ENTITY_TYPE_OPTIONS.map((type) => /* @__PURE__ */ React.createElement("label", {
@@ -30419,7 +30579,7 @@ function EventEditPage({ eventId }) {
30419
30579
  }, type)))), /* @__PURE__ */ React.createElement("div", {
30420
30580
  className: "mt-3 space-y-2"
30421
30581
  }, /* @__PURE__ */ React.createElement("label", {
30422
- className: labelCls7
30582
+ className: labelCls6
30423
30583
  }, "Custom entity type"), /* @__PURE__ */ React.createElement("div", {
30424
30584
  className: "flex flex-wrap gap-2"
30425
30585
  }, /* @__PURE__ */ React.createElement("input", {
@@ -30459,7 +30619,7 @@ function EventEditPage({ eventId }) {
30459
30619
  onChange: setBannerImageUrl,
30460
30620
  previewVariant: "banner",
30461
30621
  inputClassName: inputCls6,
30462
- labelClassName: labelCls7
30622
+ labelClassName: labelCls6
30463
30623
  })), /* @__PURE__ */ React.createElement("div", {
30464
30624
  className: "sm:col-span-2"
30465
30625
  }, /* @__PURE__ */ React.createElement(ImageOrUrlField, {
@@ -30468,9 +30628,9 @@ function EventEditPage({ eventId }) {
30468
30628
  onChange: setLogoUrl,
30469
30629
  previewVariant: "logo",
30470
30630
  inputClassName: inputCls6,
30471
- labelClassName: labelCls7
30631
+ labelClassName: labelCls6
30472
30632
  })), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("label", {
30473
- className: labelCls7
30633
+ className: labelCls6
30474
30634
  }, "Pricing type"), /* @__PURE__ */ React.createElement("select", {
30475
30635
  value: pricingType,
30476
30636
  onChange: /* @__PURE__ */ __name((e) => setPricingType(e.target.value), "onChange"),
@@ -30482,7 +30642,7 @@ function EventEditPage({ eventId }) {
30482
30642
  }, "Free"), /* @__PURE__ */ React.createElement("option", {
30483
30643
  value: "paid"
30484
30644
  }, "Paid"))), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("label", {
30485
- className: labelCls7
30645
+ className: labelCls6
30486
30646
  }, "Mode"), /* @__PURE__ */ React.createElement("select", {
30487
30647
  value: entityMode,
30488
30648
  onChange: /* @__PURE__ */ __name((e) => setEntityMode(e.target.value), "onChange"),
@@ -30502,7 +30662,7 @@ function EventEditPage({ eventId }) {
30502
30662
  }, /* @__PURE__ */ React.createElement("div", {
30503
30663
  className: "sm:col-span-2"
30504
30664
  }, /* @__PURE__ */ React.createElement("label", {
30505
- className: labelCls7
30665
+ className: labelCls6
30506
30666
  }, "Venue"), /* @__PURE__ */ React.createElement("input", {
30507
30667
  type: "text",
30508
30668
  value: venue,
@@ -30511,7 +30671,7 @@ function EventEditPage({ eventId }) {
30511
30671
  })), /* @__PURE__ */ React.createElement("div", {
30512
30672
  className: "sm:col-span-2"
30513
30673
  }, /* @__PURE__ */ React.createElement("label", {
30514
- className: labelCls7
30674
+ className: labelCls6
30515
30675
  }, "Additional venue details"), /* @__PURE__ */ React.createElement("textarea", {
30516
30676
  value: additionalVenueDetails,
30517
30677
  onChange: /* @__PURE__ */ __name((e) => setAdditionalVenueDetails(e.target.value.slice(0, ADDITIONAL_VENUE_MAX_CHARS)), "onChange"),
@@ -30522,14 +30682,14 @@ function EventEditPage({ eventId }) {
30522
30682
  }), /* @__PURE__ */ React.createElement("p", {
30523
30683
  className: "mt-1 text-xs text-gray-500 text-right"
30524
30684
  }, additionalVenueDetails.length, " / ", ADDITIONAL_VENUE_MAX_CHARS, " characters")), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("label", {
30525
- className: labelCls7
30685
+ className: labelCls6
30526
30686
  }, "City"), /* @__PURE__ */ React.createElement("input", {
30527
30687
  type: "text",
30528
30688
  value: city,
30529
30689
  onChange: /* @__PURE__ */ __name((e) => setCity(e.target.value), "onChange"),
30530
30690
  className: inputCls6
30531
30691
  })), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("label", {
30532
- className: labelCls7
30692
+ className: labelCls6
30533
30693
  }, "Country"), /* @__PURE__ */ React.createElement("input", {
30534
30694
  type: "text",
30535
30695
  value: country,
@@ -30560,14 +30720,14 @@ function EventEditPage({ eventId }) {
30560
30720
  className: inputCls6,
30561
30721
  required: true
30562
30722
  })), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("label", {
30563
- className: labelCls7
30723
+ className: labelCls6
30564
30724
  }, "Registration opens"), /* @__PURE__ */ React.createElement("input", {
30565
30725
  type: "datetime-local",
30566
30726
  value: registrationOpensAt,
30567
30727
  onChange: /* @__PURE__ */ __name((e) => setRegistrationOpensAt(e.target.value), "onChange"),
30568
30728
  className: inputCls6
30569
30729
  })), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("label", {
30570
- className: labelCls7
30730
+ className: labelCls6
30571
30731
  }, "Registration closes"), /* @__PURE__ */ React.createElement("input", {
30572
30732
  type: "datetime-local",
30573
30733
  value: registrationClosesAt,
@@ -30588,20 +30748,20 @@ function EventEditPage({ eventId }) {
30588
30748
  onDefaultChange: setDefaultCurrency,
30589
30749
  onSupportedChange: setSupportedCurrencies,
30590
30750
  inputCls: inputCls6,
30591
- labelCls: labelCls7
30751
+ labelCls: labelCls6
30592
30752
  }) : /* @__PURE__ */ React.createElement("p", {
30593
30753
  className: "text-sm text-gray-500"
30594
30754
  }, "No active currencies configured. Add currencies in Store settings first."), /* @__PURE__ */ React.createElement("div", {
30595
30755
  className: "grid gap-3 sm:grid-cols-2"
30596
30756
  }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("label", {
30597
- className: labelCls7
30757
+ className: labelCls6
30598
30758
  }, "Official website URL"), /* @__PURE__ */ React.createElement("input", {
30599
30759
  type: "url",
30600
30760
  value: officialWebsiteUrl,
30601
30761
  onChange: /* @__PURE__ */ __name((e) => setOfficialWebsiteUrl(e.target.value), "onChange"),
30602
30762
  className: inputCls6
30603
30763
  })), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("label", {
30604
- className: labelCls7
30764
+ className: labelCls6
30605
30765
  }, "Support contact"), /* @__PURE__ */ React.createElement("input", {
30606
30766
  type: "text",
30607
30767
  value: supportContact,
@@ -30610,7 +30770,7 @@ function EventEditPage({ eventId }) {
30610
30770
  })), /* @__PURE__ */ React.createElement("div", {
30611
30771
  className: "sm:col-span-2"
30612
30772
  }, /* @__PURE__ */ React.createElement("label", {
30613
- className: labelCls7
30773
+ className: labelCls6
30614
30774
  }, "Contact form"), /* @__PURE__ */ React.createElement("select", {
30615
30775
  value: contactFormId ?? "",
30616
30776
  onChange: /* @__PURE__ */ __name((e) => setContactFormId(e.target.value ? Number(e.target.value) : null), "onChange"),
@@ -30625,7 +30785,7 @@ function EventEditPage({ eventId }) {
30625
30785
  }, "Attendee registration form used during checkout for this event.")), /* @__PURE__ */ React.createElement("div", {
30626
30786
  className: "sm:col-span-2 grid gap-4 sm:grid-cols-2 sm:items-end"
30627
30787
  }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("label", {
30628
- className: labelCls7
30788
+ className: labelCls6
30629
30789
  }, "Max group purchase quantity"), /* @__PURE__ */ React.createElement("input", {
30630
30790
  type: "number",
30631
30791
  value: maxGroupPurchaseQuantity,
@@ -30661,13 +30821,7 @@ function EventEditPage({ eventId }) {
30661
30821
  ...prev,
30662
30822
  [key]: value
30663
30823
  })), "onChange")
30664
- })), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("h2", {
30665
- className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-3"
30666
- }, "Order notifications"), eventRecordId ? /* @__PURE__ */ React.createElement(EventNotificationSettings, {
30667
- eventId: eventRecordId
30668
- }) : /* @__PURE__ */ React.createElement("p", {
30669
- className: "text-sm text-gray-500"
30670
- }, "Save the event first to configure order notification channels and templates."))))
30824
+ }))))
30671
30825
  }), showEventProducts ? /* @__PURE__ */ React.createElement("div", {
30672
30826
  className: "border-t border-gray-200 px-4 py-4 sm:px-6"
30673
30827
  }, /* @__PURE__ */ React.createElement(EventProductsSection, {
@@ -30675,7 +30829,7 @@ function EventEditPage({ eventId }) {
30675
30829
  returnUrl: eventEditUrl
30676
30830
  })) : null);
30677
30831
  }
30678
- var ADDITIONAL_VENUE_MAX_CHARS, DEFAULT_EVENT_TIMEZONE, DEFAULT_EVENT_CURRENCY, EVENT_SOCIAL_KEYS, isCreate4, sectionCls5, labelCls7, inputCls6, ENTITY_TYPE_OPTIONS;
30832
+ var ADDITIONAL_VENUE_MAX_CHARS, DEFAULT_EVENT_TIMEZONE, DEFAULT_EVENT_CURRENCY, EVENT_SOCIAL_KEYS, isCreate4, sectionCls5, labelCls6, inputCls6, ENTITY_TYPE_OPTIONS;
30679
30833
  var init_EventEditPage = __esm({
30680
30834
  "src/admin/pages/EventEditPage.tsx"() {
30681
30835
  "use client";
@@ -30685,7 +30839,6 @@ var init_EventEditPage = __esm({
30685
30839
  init_ImageOrUrlField();
30686
30840
  init_JoditRichText();
30687
30841
  init_EventProductsSection();
30688
- init_EventNotificationSettings();
30689
30842
  init_EventManagementFields();
30690
30843
  init_event_named_lists();
30691
30844
  init_social_media_links();
@@ -30698,7 +30851,7 @@ var init_EventEditPage = __esm({
30698
30851
  EVENT_SOCIAL_KEYS = EVENT_SOCIAL_FIELDS.map((f) => f.key);
30699
30852
  isCreate4 = /* @__PURE__ */ __name((id) => id === "create", "isCreate");
30700
30853
  sectionCls5 = "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50";
30701
- labelCls7 = "block text-xs font-medium text-gray-600 mb-1";
30854
+ labelCls6 = "block text-xs font-medium text-gray-600 mb-1";
30702
30855
  inputCls6 = "w-full rounded-md border border-gray-300 px-2 py-1.5 text-sm";
30703
30856
  __name(RequiredLabel, "RequiredLabel");
30704
30857
  ENTITY_TYPE_OPTIONS = [
@@ -32093,35 +32246,48 @@ var VendorCategoryWorkspacePage_exports = {};
32093
32246
  __export(VendorCategoryWorkspacePage_exports, {
32094
32247
  default: () => VendorCategoryWorkspacePage
32095
32248
  });
32096
- function buildAdminProductColumns(base) {
32249
+ function buildAdminProductColumns(base, multiVendorEnabled, eventsEnabled) {
32250
+ const extraColumns = [
32251
+ ...multiVendorEnabled ? [
32252
+ VENDOR_EXTRA_COLUMN
32253
+ ] : [],
32254
+ ...eventsEnabled ? [
32255
+ EVENT_EXTRA_COLUMN
32256
+ ] : []
32257
+ ];
32097
32258
  const cols = base.filter((c) => c.field && !CATEGORY_PRODUCT_HIDDEN_FIELDS.has(c.field));
32098
32259
  const nameIdx = cols.findIndex((c) => c.field === "name");
32099
32260
  if (nameIdx < 0) return [
32100
- ...CATEGORY_PRODUCT_EXTRA_COLUMNS,
32261
+ ...extraColumns,
32101
32262
  ...cols
32102
32263
  ];
32103
32264
  return [
32104
32265
  ...cols.slice(0, nameIdx + 1),
32105
- ...CATEGORY_PRODUCT_EXTRA_COLUMNS,
32266
+ ...extraColumns,
32106
32267
  ...cols.slice(nameIdx + 1)
32107
32268
  ];
32108
32269
  }
32109
- function buildAdminAllProductColumns(base) {
32270
+ function buildAllProductColumns(base, multiVendorEnabled, eventsEnabled) {
32271
+ const extraColumns = [
32272
+ ...multiVendorEnabled ? [
32273
+ VENDOR_EXTRA_COLUMN
32274
+ ] : [],
32275
+ ...eventsEnabled ? [
32276
+ EVENT_EXTRA_COLUMN
32277
+ ] : []
32278
+ ];
32110
32279
  const cols = base.filter((c) => Boolean(c.field));
32111
32280
  const nameIdx = cols.findIndex((c) => c.field === "name");
32112
32281
  if (nameIdx < 0) return [
32113
- ...CATEGORY_PRODUCT_EXTRA_COLUMNS,
32282
+ ...extraColumns,
32114
32283
  ...cols
32115
32284
  ];
32116
32285
  return [
32117
32286
  ...cols.slice(0, nameIdx + 1),
32118
- ...CATEGORY_PRODUCT_EXTRA_COLUMNS,
32287
+ ...extraColumns,
32119
32288
  ...cols.slice(nameIdx + 1)
32120
32289
  ];
32121
32290
  }
32122
- function buildVendorProductColumns(base) {
32123
- return base.filter((c) => c.field !== "categoryId" && c.field !== "vendorId");
32124
- }
32125
32291
  function withCollectionRelationApi(columns, categoryId, vendorPortal) {
32126
32292
  const relationApi = collectionsRelationApi({
32127
32293
  vendorPortal,
@@ -32133,47 +32299,34 @@ function withCollectionRelationApi(columns, categoryId, vendorPortal) {
32133
32299
  } : col);
32134
32300
  }
32135
32301
  function VendorCategoryWorkspacePage() {
32136
- const router = navigation.useRouter();
32137
32302
  const searchParams = navigation.useSearchParams();
32138
32303
  const { data: session } = react.useSession();
32139
32304
  const vendorPortal = isVendorPortalUser(session?.user);
32305
+ const { multiVendorEnabled, eventsEnabled } = React26.useContext(exports.AdminConfigContext);
32140
32306
  const { categories, loading, error } = useCatalogCategories();
32141
32307
  const categoryIdParam = searchParams.get("categoryId")?.trim() ?? "";
32142
32308
  const activeCategoryId = React26.useMemo(() => {
32143
32309
  if (categoryIdParam && categories.some((c) => String(c.id) === categoryIdParam)) {
32144
32310
  return categoryIdParam;
32145
32311
  }
32146
- if (vendorPortal) {
32147
- const first = categories[0];
32148
- return first ? String(first.id) : "";
32149
- }
32150
32312
  return "";
32151
32313
  }, [
32152
32314
  categoryIdParam,
32153
- categories,
32154
- vendorPortal
32155
- ]);
32156
- React26.useEffect(() => {
32157
- if (!vendorPortal) return;
32158
- if (!activeCategoryId || activeCategoryId === categoryIdParam) return;
32159
- router.replace(vendorCategoryWorkspaceUrl(activeCategoryId));
32160
- }, [
32161
- activeCategoryId,
32162
- categoryIdParam,
32163
- router,
32164
- vendorPortal
32315
+ categories
32165
32316
  ]);
32166
32317
  const activeCategory = categories.find((c) => String(c.id) === activeCategoryId);
32167
- const showAllProducts = !vendorPortal && !activeCategoryId;
32168
- const workspaceFrom = activeCategoryId ? vendorCategoryWorkspaceUrl(activeCategoryId) : "/admin/products";
32318
+ const showAllProducts = !activeCategoryId;
32319
+ const workspaceFrom = activeCategoryId ? `/admin/products?categoryId=${activeCategoryId}` : "/admin/products";
32169
32320
  const itemLabel = activeCategory ? categorySingularName(activeCategory.name) : "Product";
32170
32321
  const productColumns2 = React26.useMemo(() => {
32171
- const base = vendorPortal ? buildVendorProductColumns(exports.STORE_CRUD_CONFIGS.products.columns) : showAllProducts ? buildAdminAllProductColumns(exports.STORE_CRUD_CONFIGS.products.columns) : buildAdminProductColumns(exports.STORE_CRUD_CONFIGS.products.columns);
32322
+ const base = showAllProducts ? buildAllProductColumns(exports.STORE_CRUD_CONFIGS.products.columns, multiVendorEnabled !== false, eventsEnabled !== false) : buildAdminProductColumns(exports.STORE_CRUD_CONFIGS.products.columns, multiVendorEnabled !== false, eventsEnabled !== false);
32172
32323
  return withCollectionRelationApi(base, activeCategoryId, vendorPortal);
32173
32324
  }, [
32174
32325
  vendorPortal,
32175
32326
  activeCategoryId,
32176
- showAllProducts
32327
+ showAllProducts,
32328
+ multiVendorEnabled,
32329
+ eventsEnabled
32177
32330
  ]);
32178
32331
  const productFilterColumns2 = React26.useMemo(() => productColumns2, [
32179
32332
  productColumns2
@@ -32190,20 +32343,8 @@ function VendorCategoryWorkspacePage() {
32190
32343
  className: "text-red-600 text-sm"
32191
32344
  }, error));
32192
32345
  }
32193
- if (categories.length === 0) {
32194
- return /* @__PURE__ */ React26__namespace.default.createElement("div", {
32195
- className: "rounded-lg bg-white p-6 shadow-md"
32196
- }, /* @__PURE__ */ React26__namespace.default.createElement("h1", {
32197
- className: "text-lg font-semibold text-gray-900"
32198
- }, "Store"), /* @__PURE__ */ React26__namespace.default.createElement("p", {
32199
- className: "mt-2 text-sm text-gray-600"
32200
- }, "No catalog categories are available yet. Ask your platform administrator to add store categories."));
32201
- }
32202
- if (!showAllProducts && (!activeCategoryId || !activeCategory)) {
32203
- return null;
32204
- }
32205
- const listTitle = showAllProducts ? "Products" : activeCategory.name;
32206
- const listKey = showAllProducts ? "products-all-admin" : `products-${activeCategoryId}-${vendorPortal ? "vendor" : "admin"}`;
32346
+ const listTitle = showAllProducts ? "Products" : activeCategory?.name ?? "Products";
32347
+ const listKey = showAllProducts ? "products-all" : `products-${activeCategoryId}`;
32207
32348
  return /* @__PURE__ */ React26__namespace.default.createElement("div", {
32208
32349
  className: "rounded-lg bg-white shadow-md min-h-[420px]"
32209
32350
  }, /* @__PURE__ */ React26__namespace.default.createElement("div", {
@@ -32227,12 +32368,10 @@ function VendorCategoryWorkspacePage() {
32227
32368
  ...activeCategoryId ? {
32228
32369
  categoryId: activeCategoryId
32229
32370
  } : {},
32230
- ...!vendorPortal ? {
32231
- includeEventNames: "1"
32232
- } : {}
32371
+ includeEventNames: "1"
32233
32372
  },
32234
32373
  emptyState: {
32235
- title: showAllProducts ? "No products found" : `No ${activeCategory.name.toLowerCase()} found`,
32374
+ title: showAllProducts ? "No products found" : `No ${(activeCategory?.name ?? "product").toLowerCase()} found`,
32236
32375
  description: showAllProducts ? "Add a product to get started." : `Add a ${itemLabel.toLowerCase()} and select a collection for it.`,
32237
32376
  action: /* @__PURE__ */ React26__namespace.default.createElement(Link2__default.default, {
32238
32377
  href: activeCategoryId ? vendorProductCreateUrl(activeCategoryId, {
@@ -32243,34 +32382,32 @@ function VendorCategoryWorkspacePage() {
32243
32382
  }
32244
32383
  }))));
32245
32384
  }
32246
- var CATEGORY_PRODUCT_HIDDEN_FIELDS, CATEGORY_PRODUCT_EXTRA_COLUMNS;
32385
+ var CATEGORY_PRODUCT_HIDDEN_FIELDS, VENDOR_EXTRA_COLUMN, EVENT_EXTRA_COLUMN;
32247
32386
  var init_VendorCategoryWorkspacePage = __esm({
32248
32387
  "src/admin/pages/VendorCategoryWorkspacePage.tsx"() {
32249
32388
  "use client";
32250
32389
  init_vendor_scope();
32251
32390
  init_CRUD();
32252
32391
  init_store_crud_configs();
32392
+ init_admin_config_context();
32253
32393
  init_use_catalog_categories();
32254
32394
  init_category_item_label();
32255
32395
  CATEGORY_PRODUCT_HIDDEN_FIELDS = /* @__PURE__ */ new Set([
32256
32396
  "categoryId"
32257
32397
  ]);
32258
- CATEGORY_PRODUCT_EXTRA_COLUMNS = [
32259
- {
32260
- field: "vendorId",
32261
- displayName: "Vendor",
32262
- relationApi: "/api/vendors",
32263
- relationLabelField: "name",
32264
- relationValueField: "id"
32265
- },
32266
- {
32267
- field: "eventName",
32268
- displayName: "Event"
32269
- }
32270
- ];
32398
+ VENDOR_EXTRA_COLUMN = {
32399
+ field: "vendorId",
32400
+ displayName: "Vendor",
32401
+ relationApi: "/api/vendors",
32402
+ relationLabelField: "name",
32403
+ relationValueField: "id"
32404
+ };
32405
+ EVENT_EXTRA_COLUMN = {
32406
+ field: "eventName",
32407
+ displayName: "Event"
32408
+ };
32271
32409
  __name(buildAdminProductColumns, "buildAdminProductColumns");
32272
- __name(buildAdminAllProductColumns, "buildAdminAllProductColumns");
32273
- __name(buildVendorProductColumns, "buildVendorProductColumns");
32410
+ __name(buildAllProductColumns, "buildAllProductColumns");
32274
32411
  __name(withCollectionRelationApi, "withCollectionRelationApi");
32275
32412
  __name(VendorCategoryWorkspacePage, "VendorCategoryWorkspacePage");
32276
32413
  }
@@ -32285,7 +32422,52 @@ function CollectionsWorkspacePage() {
32285
32422
  const { data: session } = react.useSession();
32286
32423
  const vendorPortal = isVendorPortalUser(session?.user);
32287
32424
  const isCatalog = !vendorPortal;
32288
- const collectionColumns = React26.useMemo(() => exports.STORE_CRUD_CONFIGS.collections.columns.filter((c) => c.field !== "vendorId"), []);
32425
+ const { multiVendorEnabled } = React26.useContext(exports.AdminConfigContext);
32426
+ const [vendorOptions, setVendorOptions] = React26.useState([]);
32427
+ React26.useEffect(() => {
32428
+ if (vendorPortal || multiVendorEnabled === false) return;
32429
+ fetch("/api/vendors?limit=500").then((r) => r.ok ? r.json() : null).then((data) => {
32430
+ if (!data?.data?.length) return;
32431
+ setVendorOptions(data.data.map((v) => ({
32432
+ value: String(v.id),
32433
+ label: v.name
32434
+ })));
32435
+ }).catch(() => {
32436
+ });
32437
+ }, [
32438
+ vendorPortal,
32439
+ multiVendorEnabled
32440
+ ]);
32441
+ const showVendorColumn = multiVendorEnabled !== false && !vendorPortal;
32442
+ const collectionColumns = React26.useMemo(() => {
32443
+ const base = exports.STORE_CRUD_CONFIGS.collections.columns.filter((c) => c.field !== "vendorId");
32444
+ return showVendorColumn ? [
32445
+ VENDOR_COLUMN,
32446
+ ...base
32447
+ ] : base;
32448
+ }, [
32449
+ showVendorColumn
32450
+ ]);
32451
+ const collectionFilters = React26.useMemo(() => {
32452
+ if (!showVendorColumn || vendorOptions.length <= 1) return void 0;
32453
+ return [
32454
+ {
32455
+ param: "vendorId",
32456
+ label: "Vendor",
32457
+ type: "select",
32458
+ options: [
32459
+ {
32460
+ value: "",
32461
+ label: "All vendors"
32462
+ },
32463
+ ...vendorOptions
32464
+ ]
32465
+ }
32466
+ ];
32467
+ }, [
32468
+ showVendorColumn,
32469
+ vendorOptions
32470
+ ]);
32289
32471
  const listParams = React26.useMemo(() => isCatalog ? {
32290
32472
  isCatalog: "true"
32291
32473
  } : void 0, [
@@ -32301,20 +32483,32 @@ function CollectionsWorkspacePage() {
32301
32483
  title: "Collections",
32302
32484
  apiEndpoint: "/api/collections",
32303
32485
  columns: collectionColumns,
32304
- filterColumns: exports.STORE_CRUD_CONFIGS.collections.columns,
32486
+ filterColumns: collectionColumns,
32305
32487
  addEditPageUrl: "/admin/collections",
32306
32488
  createQueryParams,
32307
32489
  defaultSortField: "sortOrder",
32308
32490
  defaultSortOrder: "asc",
32309
- extraListParams: listParams
32491
+ extraListParams: listParams,
32492
+ filters: collectionFilters
32310
32493
  });
32311
32494
  }
32495
+ var VENDOR_COLUMN;
32312
32496
  var init_CollectionsWorkspacePage = __esm({
32313
32497
  "src/admin/pages/CollectionsWorkspacePage.tsx"() {
32314
32498
  "use client";
32315
32499
  init_vendor_scope();
32316
32500
  init_CRUD();
32317
32501
  init_store_crud_configs();
32502
+ init_admin_config_context();
32503
+ VENDOR_COLUMN = {
32504
+ field: "vendorId",
32505
+ displayName: "Vendor",
32506
+ hideInCreate: true,
32507
+ hideInEdit: true,
32508
+ relationApi: "/api/vendors",
32509
+ relationLabelField: "name",
32510
+ relationValueField: "id"
32511
+ };
32318
32512
  __name(CollectionsWorkspacePage, "CollectionsWorkspacePage");
32319
32513
  }
32320
32514
  });
@@ -36226,7 +36420,7 @@ function AdminPageResolver({ slug }) {
36226
36420
  const searchParams = navigation.useSearchParams();
36227
36421
  const { data: session } = react.useSession();
36228
36422
  const vendorPortal = isVendorPortalUser(session?.user);
36229
- const { customCrudConfigs, storeEnabled } = React26.useContext(exports.AdminConfigContext);
36423
+ const { customCrudConfigs, storeEnabled, multiVendorEnabled, eventsEnabled } = React26.useContext(exports.AdminConfigContext);
36230
36424
  const key = slug?.[0] || "dashboard";
36231
36425
  const [vendorOptions, setVendorOptions] = React26.useState([]);
36232
36426
  React26.useEffect(() => {
@@ -36252,17 +36446,21 @@ function AdminPageResolver({ slug }) {
36252
36446
  if (!config) return void 0;
36253
36447
  let columns = config.columns;
36254
36448
  let filters = config.filters ?? [];
36255
- if (vendorPortal) {
36449
+ if (vendorPortal || multiVendorEnabled === false) {
36256
36450
  columns = columns.filter((column) => column.field !== "vendorId");
36257
36451
  filters = filters.filter((filter) => filter.param !== "vendorId");
36258
36452
  }
36259
- if (!vendorPortal && STORE_VENDOR_RESOURCES.has(key) && key !== "product_categories" && key !== "event_products" && !columns.some((c) => c.field === "vendorId")) {
36453
+ if (eventsEnabled === false) {
36454
+ columns = columns.filter((column) => column.field !== "eventId" && column.field !== "eventName");
36455
+ filters = filters.filter((filter) => filter.param !== "eventId");
36456
+ }
36457
+ if (multiVendorEnabled !== false && !vendorPortal && STORE_VENDOR_RESOURCES.has(key) && key !== "event_products" && !columns.some((c) => c.field === "vendorId")) {
36260
36458
  columns = [
36261
- VENDOR_COLUMN,
36459
+ VENDOR_COLUMN2,
36262
36460
  ...columns
36263
36461
  ];
36264
36462
  }
36265
- if (!vendorPortal && STORE_VENDOR_RESOURCES.has(key) && key !== "product_categories" && key !== "event_products" && vendorOptions.length > 1 && !filters.some((f) => f.param === "vendorId")) {
36463
+ if (multiVendorEnabled !== false && !vendorPortal && STORE_VENDOR_RESOURCES.has(key) && key !== "event_products" && vendorOptions.length > 1 && !filters.some((f) => f.param === "vendorId")) {
36266
36464
  filters = [
36267
36465
  {
36268
36466
  param: "vendorId",
@@ -36291,7 +36489,9 @@ function AdminPageResolver({ slug }) {
36291
36489
  key,
36292
36490
  customCrudConfigs,
36293
36491
  vendorOptions,
36294
- vendorPortal
36492
+ vendorPortal,
36493
+ multiVendorEnabled,
36494
+ eventsEnabled
36295
36495
  ]);
36296
36496
  const isContactsWithStore = key === "contacts" && storeEnabled;
36297
36497
  const extraListParams = React26.useMemo(() => isContactsWithStore ? {
@@ -36319,6 +36519,20 @@ function AdminPageResolver({ slug }) {
36319
36519
  crud,
36320
36520
  isContactsWithStore
36321
36521
  ]);
36522
+ const isVendorRelated = React26.useMemo(() => {
36523
+ return key === "vendors" || key === "vendor-team" || key === "vendor-roles" || key === "vendor-profile" || key === "store" || key === "analytics" || key === "vendor_users" || key === "vendor_role_permissions";
36524
+ }, [
36525
+ key
36526
+ ]);
36527
+ React26.useEffect(() => {
36528
+ if (multiVendorEnabled === false && isVendorRelated) {
36529
+ router.replace("/admin/access-denied");
36530
+ }
36531
+ }, [
36532
+ multiVendorEnabled,
36533
+ isVendorRelated,
36534
+ router
36535
+ ]);
36322
36536
  React26.useEffect(() => {
36323
36537
  if (key === "layout-settings") {
36324
36538
  router.replace("/admin/settings?tab=navbar");
@@ -36336,6 +36550,34 @@ function AdminPageResolver({ slug }) {
36336
36550
  router,
36337
36551
  vendorPortal
36338
36552
  ]);
36553
+ const isEventsRelated = key === "events";
36554
+ React26.useEffect(() => {
36555
+ if (eventsEnabled === false && isEventsRelated) {
36556
+ router.replace("/admin/access-denied");
36557
+ }
36558
+ }, [
36559
+ eventsEnabled,
36560
+ isEventsRelated,
36561
+ router
36562
+ ]);
36563
+ if (multiVendorEnabled === false && isVendorRelated) {
36564
+ return /* @__PURE__ */ React26__namespace.default.createElement("div", {
36565
+ className: "flex justify-center py-8"
36566
+ }, /* @__PURE__ */ React26__namespace.default.createElement("div", {
36567
+ className: "animate-spin rounded-full h-6 w-6 border-2 border-gray-300 border-t-gray-600"
36568
+ }), /* @__PURE__ */ React26__namespace.default.createElement("span", {
36569
+ className: "ml-2"
36570
+ }, "Redirecting\u2026"));
36571
+ }
36572
+ if (eventsEnabled === false && isEventsRelated) {
36573
+ return /* @__PURE__ */ React26__namespace.default.createElement("div", {
36574
+ className: "flex justify-center py-8"
36575
+ }, /* @__PURE__ */ React26__namespace.default.createElement("div", {
36576
+ className: "animate-spin rounded-full h-6 w-6 border-2 border-gray-300 border-t-gray-600"
36577
+ }), /* @__PURE__ */ React26__namespace.default.createElement("span", {
36578
+ className: "ml-2"
36579
+ }, "Redirecting\u2026"));
36580
+ }
36339
36581
  if (key === "layout-settings") {
36340
36582
  return /* @__PURE__ */ React26__namespace.default.createElement("div", {
36341
36583
  className: "flex justify-center py-8"
@@ -36632,7 +36874,7 @@ function AdminPageResolver({ slug }) {
36632
36874
  className: "text-gray-500"
36633
36875
  }, "Page not found"));
36634
36876
  }
36635
- var VendorAnalyticsPage2, DashboardPage2, SignInPage, ForgotPasswordPage2, ResetPasswordPage2, InvitePage2, SettingsPage2, AdminProfilePage2, PluginsPage2, RolesPage2, BlogGeneratorPage2, SchedulesPage2, VendorTeamPage2, VendorRolesPage2, VendorPortalProfilePage2, SubmissionDetailPage2, OrderDetailPage2, OrderPlacementPage2, OrderProductFramePage2, PaymentDetailPage2, MediaLibraryPage2, PageBuilderPage2, BrandEditPage2, ProductEditPage2, CollectionEditPage2, EventEditPage2, ComboEditPage2, VendorEditPage2, VendorsListPage2, VendorStorePage2, VendorCategoryWorkspacePage2, CollectionsWorkspacePage2, DiscountDetailPage2, DiscountEditPage2, ContactDetailPage2, BlogEditorPage, FormBuilder2, PolicyPage2, PAGE_MAP, CRUD_CONFIGS, VENDOR_COLUMN, STORE_VENDOR_RESOURCES;
36877
+ var VendorAnalyticsPage2, DashboardPage2, SignInPage, ForgotPasswordPage2, ResetPasswordPage2, InvitePage2, SettingsPage2, AdminProfilePage2, PluginsPage2, RolesPage2, BlogGeneratorPage2, SchedulesPage2, VendorTeamPage2, VendorRolesPage2, VendorPortalProfilePage2, SubmissionDetailPage2, OrderDetailPage2, OrderPlacementPage2, OrderProductFramePage2, PaymentDetailPage2, MediaLibraryPage2, PageBuilderPage2, BrandEditPage2, ProductEditPage2, CollectionEditPage2, EventEditPage2, ComboEditPage2, VendorEditPage2, VendorsListPage2, VendorStorePage2, VendorCategoryWorkspacePage2, CollectionsWorkspacePage2, DiscountDetailPage2, DiscountEditPage2, ContactDetailPage2, BlogEditorPage, FormBuilder2, PolicyPage2, PAGE_MAP, CRUD_CONFIGS, VENDOR_COLUMN2, STORE_VENDOR_RESOURCES;
36636
36878
  var init_AdminPageResolver = __esm({
36637
36879
  "src/admin/pages/AdminPageResolver.tsx"() {
36638
36880
  "use client";
@@ -36965,7 +37207,7 @@ var init_AdminPageResolver = __esm({
36965
37207
  }
36966
37208
  };
36967
37209
  __name(BlogEditorWrapper, "BlogEditorWrapper");
36968
- VENDOR_COLUMN = {
37210
+ VENDOR_COLUMN2 = {
36969
37211
  field: "vendorId",
36970
37212
  displayName: "Vendor",
36971
37213
  hideInCreate: true,
@@ -37211,21 +37453,21 @@ function EventDetailPage({ eventId }) {
37211
37453
  }, /* @__PURE__ */ React.createElement("dl", {
37212
37454
  className: "grid gap-4 sm:grid-cols-2"
37213
37455
  }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("dt", {
37214
- className: labelCls8
37456
+ className: labelCls7
37215
37457
  }, "Name"), /* @__PURE__ */ React.createElement("dd", {
37216
37458
  className: valueCls
37217
37459
  }, displayValue(event.name))), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("dt", {
37218
- className: labelCls8
37460
+ className: labelCls7
37219
37461
  }, "Slug"), /* @__PURE__ */ React.createElement("dd", {
37220
37462
  className: valueCls
37221
37463
  }, displayValue(event.slug))), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("dt", {
37222
- className: labelCls8
37464
+ className: labelCls7
37223
37465
  }, "Sort order"), /* @__PURE__ */ React.createElement("dd", {
37224
37466
  className: valueCls
37225
37467
  }, event.sortOrder)), /* @__PURE__ */ React.createElement("div", {
37226
37468
  className: "sm:col-span-2"
37227
37469
  }, /* @__PURE__ */ React.createElement("dt", {
37228
- className: labelCls8
37470
+ className: labelCls7
37229
37471
  }, "Description"), /* @__PURE__ */ React.createElement("dd", {
37230
37472
  className: `${valueCls} prose prose-sm max-w-none`,
37231
37473
  dangerouslySetInnerHTML: {
@@ -37234,11 +37476,11 @@ function EventDetailPage({ eventId }) {
37234
37476
  })), /* @__PURE__ */ React.createElement("div", {
37235
37477
  className: "sm:col-span-2"
37236
37478
  }, /* @__PURE__ */ React.createElement("dt", {
37237
- className: labelCls8
37479
+ className: labelCls7
37238
37480
  }, "Entity types"), /* @__PURE__ */ React.createElement("dd", {
37239
37481
  className: valueCls
37240
37482
  }, event.entityTypes?.length ? event.entityTypes.map(formatEventEntityTypeLabel).join(", ") : "\u2014")), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("dt", {
37241
- className: labelCls8
37483
+ className: labelCls7
37242
37484
  }, "Banner image"), /* @__PURE__ */ React.createElement("dd", {
37243
37485
  className: valueCls
37244
37486
  }, event.bannerImageUrl ? /* @__PURE__ */ React.createElement("a", {
@@ -37247,7 +37489,7 @@ function EventDetailPage({ eventId }) {
37247
37489
  rel: "noreferrer",
37248
37490
  className: "text-blue-600 hover:underline break-all"
37249
37491
  }, event.bannerImageUrl) : "\u2014")), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("dt", {
37250
- className: labelCls8
37492
+ className: labelCls7
37251
37493
  }, "Logo"), /* @__PURE__ */ React.createElement("dd", {
37252
37494
  className: valueCls
37253
37495
  }, event.logoUrl ? /* @__PURE__ */ React.createElement("a", {
@@ -37256,11 +37498,11 @@ function EventDetailPage({ eventId }) {
37256
37498
  rel: "noreferrer",
37257
37499
  className: "text-blue-600 hover:underline break-all"
37258
37500
  }, event.logoUrl) : "\u2014")), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("dt", {
37259
- className: labelCls8
37501
+ className: labelCls7
37260
37502
  }, "Pricing type"), /* @__PURE__ */ React.createElement("dd", {
37261
37503
  className: valueCls
37262
37504
  }, event.pricingType ? event.pricingType.charAt(0).toUpperCase() + event.pricingType.slice(1) : "\u2014")), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("dt", {
37263
- className: labelCls8
37505
+ className: labelCls7
37264
37506
  }, "Mode"), /* @__PURE__ */ React.createElement("dd", {
37265
37507
  className: valueCls
37266
37508
  }, formatMode(event.entityMode))))) : activeTab === "venue" ? /* @__PURE__ */ React.createElement("section", {
@@ -37270,21 +37512,21 @@ function EventDetailPage({ eventId }) {
37270
37512
  }, /* @__PURE__ */ React.createElement("div", {
37271
37513
  className: "sm:col-span-2"
37272
37514
  }, /* @__PURE__ */ React.createElement("dt", {
37273
- className: labelCls8
37515
+ className: labelCls7
37274
37516
  }, "Venue"), /* @__PURE__ */ React.createElement("dd", {
37275
37517
  className: valueCls
37276
37518
  }, displayValue(event.venue))), event.additionalVenueDetails ? /* @__PURE__ */ React.createElement("div", {
37277
37519
  className: "sm:col-span-2"
37278
37520
  }, /* @__PURE__ */ React.createElement("dt", {
37279
- className: labelCls8
37521
+ className: labelCls7
37280
37522
  }, "Additional venue details"), /* @__PURE__ */ React.createElement("dd", {
37281
37523
  className: `${valueCls} whitespace-pre-wrap`
37282
37524
  }, event.additionalVenueDetails)) : null, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("dt", {
37283
- className: labelCls8
37525
+ className: labelCls7
37284
37526
  }, "City"), /* @__PURE__ */ React.createElement("dd", {
37285
37527
  className: valueCls
37286
37528
  }, displayValue(event.city ?? event.cityCountry?.split(",")[0]?.trim()))), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("dt", {
37287
- className: labelCls8
37529
+ className: labelCls7
37288
37530
  }, "Country"), /* @__PURE__ */ React.createElement("dd", {
37289
37531
  className: valueCls
37290
37532
  }, displayValue(event.country ?? (event.cityCountry?.includes(",") ? event.cityCountry.split(",").slice(1).join(",").trim() : null)))))) : activeTab === "datetime" ? /* @__PURE__ */ React.createElement("section", {
@@ -37292,29 +37534,29 @@ function EventDetailPage({ eventId }) {
37292
37534
  }, /* @__PURE__ */ React.createElement("dl", {
37293
37535
  className: "grid gap-4 sm:grid-cols-2"
37294
37536
  }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("dt", {
37295
- className: labelCls8
37537
+ className: labelCls7
37296
37538
  }, "Timezone"), /* @__PURE__ */ React.createElement("dd", {
37297
37539
  className: valueCls
37298
37540
  }, displayValue(event.timezone))), /* @__PURE__ */ React.createElement("div", null), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("dt", {
37299
- className: labelCls8
37541
+ className: labelCls7
37300
37542
  }, "Event start"), /* @__PURE__ */ React.createElement("dd", {
37301
37543
  className: valueCls
37302
37544
  }, event.startDate ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", null, startFormatted.dateLine), startFormatted.timeLine ? /* @__PURE__ */ React.createElement("div", {
37303
37545
  className: "text-gray-600"
37304
37546
  }, startFormatted.timeLine) : null) : "\u2014")), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("dt", {
37305
- className: labelCls8
37547
+ className: labelCls7
37306
37548
  }, "Event end"), /* @__PURE__ */ React.createElement("dd", {
37307
37549
  className: valueCls
37308
37550
  }, event.endDate ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", null, endFormatted.dateLine), endFormatted.timeLine ? /* @__PURE__ */ React.createElement("div", {
37309
37551
  className: "text-gray-600"
37310
37552
  }, endFormatted.timeLine) : null) : "\u2014")), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("dt", {
37311
- className: labelCls8
37553
+ className: labelCls7
37312
37554
  }, "Registration opens"), /* @__PURE__ */ React.createElement("dd", {
37313
37555
  className: valueCls
37314
37556
  }, event.registrationOpensAt ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", null, regOpensFormatted.dateLine), regOpensFormatted.timeLine ? /* @__PURE__ */ React.createElement("div", {
37315
37557
  className: "text-gray-600"
37316
37558
  }, regOpensFormatted.timeLine) : null) : "\u2014")), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("dt", {
37317
- className: labelCls8
37559
+ className: labelCls7
37318
37560
  }, "Registration closes"), /* @__PURE__ */ React.createElement("dd", {
37319
37561
  className: valueCls
37320
37562
  }, event.registrationClosesAt ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", null, regClosesFormatted.dateLine), regClosesFormatted.timeLine ? /* @__PURE__ */ React.createElement("div", {
@@ -37328,15 +37570,15 @@ function EventDetailPage({ eventId }) {
37328
37570
  }, "Checkout & website"), /* @__PURE__ */ React.createElement("dl", {
37329
37571
  className: "grid gap-4 sm:grid-cols-2"
37330
37572
  }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("dt", {
37331
- className: labelCls8
37573
+ className: labelCls7
37332
37574
  }, "Default currency"), /* @__PURE__ */ React.createElement("dd", {
37333
37575
  className: valueCls
37334
37576
  }, displayValue(event.defaultCurrency))), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("dt", {
37335
- className: labelCls8
37577
+ className: labelCls7
37336
37578
  }, "Supported currencies"), /* @__PURE__ */ React.createElement("dd", {
37337
37579
  className: valueCls
37338
37580
  }, event.supportedCurrencies?.length ? event.supportedCurrencies.join(", ") : "\u2014")), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("dt", {
37339
- className: labelCls8
37581
+ className: labelCls7
37340
37582
  }, "Website"), /* @__PURE__ */ React.createElement("dd", {
37341
37583
  className: valueCls
37342
37584
  }, event.officialWebsiteUrl ? /* @__PURE__ */ React.createElement("a", {
@@ -37345,13 +37587,13 @@ function EventDetailPage({ eventId }) {
37345
37587
  rel: "noreferrer",
37346
37588
  className: "text-blue-600 hover:underline break-all"
37347
37589
  }, event.officialWebsiteUrl) : "\u2014")), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("dt", {
37348
- className: labelCls8
37590
+ className: labelCls7
37349
37591
  }, "Support contact"), /* @__PURE__ */ React.createElement("dd", {
37350
37592
  className: valueCls
37351
37593
  }, displayValue(event.supportContact))), /* @__PURE__ */ React.createElement("div", {
37352
37594
  className: "sm:col-span-2"
37353
37595
  }, /* @__PURE__ */ React.createElement("dt", {
37354
- className: labelCls8
37596
+ className: labelCls7
37355
37597
  }, "Contact form"), /* @__PURE__ */ React.createElement("dd", {
37356
37598
  className: valueCls
37357
37599
  }, event.contactFormId != null ? /* @__PURE__ */ React.createElement(Link2__default.default, {
@@ -37360,7 +37602,7 @@ function EventDetailPage({ eventId }) {
37360
37602
  }, contactFormLabel ?? `Form #${event.contactFormId}`) : "\u2014")), /* @__PURE__ */ React.createElement("div", {
37361
37603
  className: "sm:col-span-2 grid gap-4 sm:grid-cols-2 sm:items-end"
37362
37604
  }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("dt", {
37363
- className: labelCls8
37605
+ className: labelCls7
37364
37606
  }, "Max group quantity"), /* @__PURE__ */ React.createElement("dd", {
37365
37607
  className: valueCls
37366
37608
  }, event.maxGroupPurchaseQuantity != null ? event.maxGroupPurchaseQuantity : "\u2014")), /* @__PURE__ */ React.createElement("div", {
@@ -37369,13 +37611,7 @@ function EventDetailPage({ eventId }) {
37369
37611
  className: valueCls
37370
37612
  }, event.allowGroupOrders ? "Group orders allowed" : "Group orders disabled"), /* @__PURE__ */ React.createElement("dd", {
37371
37613
  className: valueCls
37372
- }, event.sendIndividualTicketPDFToAttendees ? "Individual ticket PDFs sent to attendees" : "Individual ticket PDFs not sent"))), /* @__PURE__ */ React.createElement("div", {
37373
- className: "sm:col-span-2"
37374
- }, /* @__PURE__ */ React.createElement("dd", {
37375
- className: valueCls
37376
- }, /* @__PURE__ */ React.createElement(EventNotificationSummary, {
37377
- eventId: String(event.id)
37378
- }))))), event.socialMediaLinks && Object.keys(event.socialMediaLinks).length > 0 ? /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("h2", {
37614
+ }, event.sendIndividualTicketPDFToAttendees ? "Individual ticket PDFs sent to attendees" : "Individual ticket PDFs not sent"))))), event.socialMediaLinks && Object.keys(event.socialMediaLinks).length > 0 ? /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("h2", {
37379
37615
  className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-3"
37380
37616
  }, "Social media"), /* @__PURE__ */ React.createElement(SocialMediaLinksDisplay, {
37381
37617
  links: event.socialMediaLinks,
@@ -37387,7 +37623,7 @@ function EventDetailPage({ eventId }) {
37387
37623
  }))
37388
37624
  }));
37389
37625
  }
37390
- var sectionCls7, labelCls8, valueCls;
37626
+ var sectionCls7, labelCls7, valueCls;
37391
37627
  var init_EventDetailPage = __esm({
37392
37628
  "src/admin/pages/EventDetailPage.tsx"() {
37393
37629
  "use client";
@@ -37399,9 +37635,8 @@ var init_EventDetailPage = __esm({
37399
37635
  init_DetailPageLayout();
37400
37636
  init_DetailPageHeader();
37401
37637
  init_EventProductsSection();
37402
- init_EventNotificationSettings();
37403
37638
  sectionCls7 = "border border-gray-200 rounded-lg p-4 bg-gray-50/50";
37404
- labelCls8 = "text-xs font-medium text-gray-500";
37639
+ labelCls7 = "text-xs font-medium text-gray-500";
37405
37640
  valueCls = "text-sm text-gray-900 mt-0.5";
37406
37641
  __name(displayValue, "displayValue");
37407
37642
  __name(formatMode, "formatMode");