@infuro/cms-core 1.0.39 → 1.0.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/admin.js CHANGED
@@ -10,7 +10,7 @@ import { Slot } from '@radix-ui/react-slot';
10
10
  import { cva } from 'class-variance-authority';
11
11
  import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
12
12
  import * as LucideIcons from 'lucide-react';
13
- import { ChevronDown, User, Settings, LogOut, LayoutDashboard, Store, FolderTree, Layers, Building2, CalendarDays, ShoppingBag, Package, Receipt, BadgePercent, ShoppingCart, CreditCard, Users, Inbox, File, LinkIcon, ClipboardList, MessageSquare, Image as Image$1, FileText, Shield, Puzzle, X, Plus, MoreVertical, Upload, Download, Edit, Copy, RefreshCw, Trash2, Save, Check, Search, AlertCircle, MapPin, BarChart3, TrendingUp, UserCheck, Activity, Globe, Eye, MousePointer, ArrowLeftRight, RotateCcw, KeyRound, Loader2, CalendarClock, Rss, ArrowLeft, Pencil, FolderPlus, LayoutGrid, List, Move, Archive, Edit2, ExternalLink, Power, Star, ChevronUp, Zap, Filter, CheckCircle2, ImageIcon, GripVertical, ChevronRight, ArrowRight, ArrowUpRight, IndianRupee, XCircle, Clock, Play, MessageCircle, Mail, Bot, FileUp, Tag, Box, SlidersHorizontal, Calculator, Link2 as Link2$1, Unlink, Gift, MoreHorizontal, Bell, QrCode, Car, Circle, Settings2, DollarSign, Hash, ChevronLeft, Share2, Smartphone, HardDrive, Folder, Film } from 'lucide-react';
13
+ import { ChevronDown, User, Settings, LogOut, LayoutDashboard, Store, FolderTree, Layers, Building2, CalendarDays, ShoppingBag, Package, Receipt, BadgePercent, ShoppingCart, CreditCard, Users, Inbox, File, LinkIcon, ClipboardList, MessageSquare, Image as Image$1, FileText, Shield, Puzzle, X, Plus, MoreVertical, Upload, Download, Edit, Copy, RefreshCw, Trash2, Save, Check, Search, AlertCircle, MapPin, BarChart3, TrendingUp, UserCheck, Activity, Globe, Eye, MousePointer, ArrowLeftRight, RotateCcw, KeyRound, Loader2, CalendarClock, Rss, ArrowLeft, Pencil, FolderPlus, LayoutGrid, List, Move, Archive, Edit2, ExternalLink, Power, Star, ChevronUp, Mail, Zap, Filter, CheckCircle2, ImageIcon, GripVertical, ChevronRight, ArrowRight, ArrowUpRight, IndianRupee, XCircle, Clock, Play, MessageCircle, Bot, FileUp, Tag, Box, SlidersHorizontal, Calculator, Link2 as Link2$1, Unlink, Gift, MoreHorizontal, Bell, QrCode, Car, Circle, Settings2, DollarSign, Hash, ChevronLeft, Share2, Smartphone, HardDrive, Folder, Film } from 'lucide-react';
14
14
  import Image from 'next/image';
15
15
  import Link2 from 'next/link';
16
16
  import { usePathname, useSearchParams, useRouter } from 'next/navigation';
@@ -457,7 +457,7 @@ var init_admin_config_context = __esm({
457
457
  var CMS_VERSION;
458
458
  var init_cms_version = __esm({
459
459
  "src/lib/cms-version.ts"() {
460
- CMS_VERSION = "1.0.39" ;
460
+ CMS_VERSION = "1.0.41" ;
461
461
  }
462
462
  });
463
463
  function useCatalogCategories(enabled = true) {
@@ -9110,11 +9110,40 @@ function InvitePageContent() {
9110
9110
  confirmPassword: ""
9111
9111
  });
9112
9112
  const [loading, setLoading] = useState(false);
9113
+ const [checking, setChecking] = useState(Boolean(token));
9114
+ const [inviteValid, setInviteValid] = useState(false);
9113
9115
  const [message, setMessage] = useState("");
9114
9116
  useEffect(() => {
9115
9117
  if (!token) {
9116
9118
  setMessage("Invalid invite link. Token is missing.");
9119
+ setChecking(false);
9120
+ return;
9117
9121
  }
9122
+ let cancelled = false;
9123
+ void (async () => {
9124
+ try {
9125
+ const res = await fetch(`/api/users/invite?token=${encodeURIComponent(token)}`);
9126
+ const result = await res.json();
9127
+ if (cancelled) return;
9128
+ if (res.ok && result.valid === true) {
9129
+ setInviteValid(true);
9130
+ setMessage("");
9131
+ } else {
9132
+ setInviteValid(false);
9133
+ setMessage(result.error || "This invitation is no longer valid.");
9134
+ }
9135
+ } catch {
9136
+ if (!cancelled) {
9137
+ setInviteValid(false);
9138
+ setMessage("Could not verify this invite link. Please try again.");
9139
+ }
9140
+ } finally {
9141
+ if (!cancelled) setChecking(false);
9142
+ }
9143
+ })();
9144
+ return () => {
9145
+ cancelled = true;
9146
+ };
9118
9147
  }, [
9119
9148
  token
9120
9149
  ]);
@@ -9157,12 +9186,21 @@ function InvitePageContent() {
9157
9186
  setLoading(false);
9158
9187
  }
9159
9188
  }, "handleSubmit");
9160
- if (!token) {
9189
+ if (!token || checking) {
9161
9190
  return /* @__PURE__ */ React26__default.createElement(AuthPageLayout, null, /* @__PURE__ */ React26__default.createElement("div", {
9162
9191
  className: "w-full space-y-4 p-5 sm:p-6 bg-white rounded-lg shadow-md text-center"
9163
9192
  }, /* @__PURE__ */ React26__default.createElement("h2", {
9164
9193
  className: "text-xl font-bold text-gray-900"
9165
- }, "Invalid invite"), /* @__PURE__ */ React26__default.createElement("p", {
9194
+ }, checking ? "Checking invite\u2026" : "Invalid invite"), !checking && /* @__PURE__ */ React26__default.createElement("p", {
9195
+ className: "text-sm text-gray-600"
9196
+ }, message)));
9197
+ }
9198
+ if (!inviteValid) {
9199
+ return /* @__PURE__ */ React26__default.createElement(AuthPageLayout, null, /* @__PURE__ */ React26__default.createElement("div", {
9200
+ className: "w-full space-y-4 p-5 sm:p-6 bg-white rounded-lg shadow-md text-center"
9201
+ }, /* @__PURE__ */ React26__default.createElement("h2", {
9202
+ className: "text-xl font-bold text-gray-900"
9203
+ }, "Invite unavailable"), /* @__PURE__ */ React26__default.createElement("p", {
9166
9204
  className: "text-sm text-gray-600"
9167
9205
  }, message)));
9168
9206
  }
@@ -12670,7 +12708,7 @@ function SettingsPage() {
12670
12708
  onCheckedChange: setMultiVendorEnabled
12671
12709
  }), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(Label3, {
12672
12710
  className: "text-sm font-medium text-gray-700"
12673
- }, "Multi Vendor Support"), /* @__PURE__ */ React.createElement("p", {
12711
+ }, "Multi Vendor"), /* @__PURE__ */ React.createElement("p", {
12674
12712
  className: "text-xs text-gray-500"
12675
12713
  }, "Enable vendor portals, vendor logins, and vendor-scoped store data. Disabling this blocks vendor-only accounts from signing in."))), storeEnabled && /* @__PURE__ */ React.createElement("div", {
12676
12714
  className: "mt-4 flex items-center gap-3 p-4 bg-gray-50 rounded-lg border border-gray-200"
@@ -31495,10 +31533,10 @@ function VendorEditPage({ vendorId }) {
31495
31533
  const [ownerPhone, setOwnerPhone] = useState("");
31496
31534
  const [ownerDesignation, setOwnerDesignation] = useState("");
31497
31535
  const [termsAccepted, setTermsAccepted] = useState(false);
31498
- const [activationMode, setActivationMode] = useState("invite");
31499
- const [sendOwnerEmail, setSendOwnerEmail] = useState(true);
31500
- const [ownerPassword, setOwnerPassword] = useState("");
31501
- const [ownerPasswordConfirm, setOwnerPasswordConfirm] = useState("");
31536
+ const [reinviting, setReinviting] = useState(false);
31537
+ const [inviteDialog, setInviteDialog] = useState(null);
31538
+ const [sendingInviteEmail, setSendingInviteEmail] = useState(false);
31539
+ const [linkCopied, setLinkCopied] = useState(false);
31502
31540
  const vendorPayload = /* @__PURE__ */ __name(() => ({
31503
31541
  name: name.trim(),
31504
31542
  legalName: legalName.trim() || null,
@@ -31578,11 +31616,115 @@ function VendorEditPage({ vendorId }) {
31578
31616
  vendorId,
31579
31617
  create
31580
31618
  ]);
31619
+ const canReinviteOwner = !create && (inviteStatus === "pending" || inviteStatus === "expired");
31620
+ const handleReinviteOwner = /* @__PURE__ */ __name(async () => {
31621
+ setReinviting(true);
31622
+ setErrors([]);
31623
+ try {
31624
+ const res = await fetch(`/api/admin/vendors/${vendorId}/resend-invite`, {
31625
+ method: "POST",
31626
+ headers: {
31627
+ "Content-Type": "application/json"
31628
+ },
31629
+ body: JSON.stringify({
31630
+ sendEmail: true
31631
+ })
31632
+ });
31633
+ const data = await res.json();
31634
+ if (!res.ok) {
31635
+ setErrors([
31636
+ data.error || data.message || "Failed to resend invite"
31637
+ ]);
31638
+ return;
31639
+ }
31640
+ const refreshRes = await fetch(`/api/vendors/${vendorId}`);
31641
+ if (refreshRes.ok) {
31642
+ const refreshed = await refreshRes.json();
31643
+ setInviteStatus(refreshed.inviteStatus ?? "pending");
31644
+ setMetadata(refreshed.metadata && typeof refreshed.metadata === "object" ? refreshed.metadata : null);
31645
+ } else {
31646
+ setInviteStatus("pending");
31647
+ }
31648
+ const inviteLink = typeof data.inviteLink === "string" ? data.inviteLink.trim() : "";
31649
+ if (inviteLink) {
31650
+ try {
31651
+ await navigator.clipboard.writeText(inviteLink);
31652
+ toast.success(data.message || "Invite resent. New link copied \u2014 previous invite links no longer work.");
31653
+ } catch {
31654
+ toast.success(data.message || "Invite resent.");
31655
+ toast.message("New invite link (previous links are invalid)", {
31656
+ description: inviteLink
31657
+ });
31658
+ }
31659
+ } else {
31660
+ toast.success(data.message || "Invite resent.");
31661
+ }
31662
+ } catch {
31663
+ setErrors([
31664
+ "Failed to resend invite"
31665
+ ]);
31666
+ } finally {
31667
+ setReinviting(false);
31668
+ }
31669
+ }, "handleReinviteOwner");
31581
31670
  if (!canOnboardVendors(session?.user)) {
31582
31671
  return /* @__PURE__ */ React26__default.createElement(VendorAccessDenied, {
31583
31672
  groupName: sessionUser?.groupName
31584
31673
  });
31585
31674
  }
31675
+ const copyInviteLink = /* @__PURE__ */ __name(async () => {
31676
+ const inviteLink = inviteDialog?.inviteLink;
31677
+ if (!inviteLink) {
31678
+ toast.error("Invite link is not available");
31679
+ return;
31680
+ }
31681
+ try {
31682
+ await navigator.clipboard.writeText(inviteLink);
31683
+ setLinkCopied(true);
31684
+ toast.success("Invite link copied");
31685
+ window.setTimeout(() => setLinkCopied(false), 2e3);
31686
+ } catch {
31687
+ toast.error("Could not copy invite link");
31688
+ }
31689
+ }, "copyInviteLink");
31690
+ const sendInviteEmail = /* @__PURE__ */ __name(async () => {
31691
+ if (!inviteDialog) return;
31692
+ setSendingInviteEmail(true);
31693
+ try {
31694
+ const res = await fetch(`/api/admin/vendors/${inviteDialog.vendorId}/resend-invite`, {
31695
+ method: "POST",
31696
+ headers: {
31697
+ "Content-Type": "application/json"
31698
+ },
31699
+ body: JSON.stringify({
31700
+ sendEmail: true,
31701
+ rotate: false
31702
+ })
31703
+ });
31704
+ const data = await res.json();
31705
+ if (!res.ok) {
31706
+ toast.error(data.error || data.message || "Failed to send invite email");
31707
+ return;
31708
+ }
31709
+ const nextLink = typeof data.inviteLink === "string" ? data.inviteLink.trim() : "";
31710
+ if (nextLink) {
31711
+ setInviteDialog((prev) => prev ? {
31712
+ ...prev,
31713
+ inviteLink: nextLink
31714
+ } : prev);
31715
+ }
31716
+ toast.success(data.emailSent ? "Invite email sent" : data.message || "Invite email queued");
31717
+ } catch {
31718
+ toast.error("Failed to send invite email");
31719
+ } finally {
31720
+ setSendingInviteEmail(false);
31721
+ }
31722
+ }, "sendInviteEmail");
31723
+ const closeInviteDialog = /* @__PURE__ */ __name(() => {
31724
+ setInviteDialog(null);
31725
+ setLinkCopied(false);
31726
+ router.push(listReturnUrl);
31727
+ }, "closeInviteDialog");
31586
31728
  const handleCreate = /* @__PURE__ */ __name(async () => {
31587
31729
  setSaving(true);
31588
31730
  setErrors([]);
@@ -31608,29 +31750,6 @@ function VendorEditPage({ vendorId }) {
31608
31750
  setSaving(false);
31609
31751
  return;
31610
31752
  }
31611
- if (activationMode === "password") {
31612
- if (!ownerPassword) {
31613
- setErrors([
31614
- "Enter a password for the owner account"
31615
- ]);
31616
- setSaving(false);
31617
- return;
31618
- }
31619
- if (ownerPassword !== ownerPasswordConfirm) {
31620
- setErrors([
31621
- "Passwords do not match"
31622
- ]);
31623
- setSaving(false);
31624
- return;
31625
- }
31626
- if (ownerPassword.length < 6) {
31627
- setErrors([
31628
- "Password must be at least 6 characters"
31629
- ]);
31630
- setSaving(false);
31631
- return;
31632
- }
31633
- }
31634
31753
  try {
31635
31754
  const res = await fetch("/api/admin/vendors/onboard", {
31636
31755
  method: "POST",
@@ -31638,18 +31757,15 @@ function VendorEditPage({ vendorId }) {
31638
31757
  "Content-Type": "application/json"
31639
31758
  },
31640
31759
  body: JSON.stringify({
31641
- activation: activationMode,
31642
- sendOwnerEmail,
31760
+ activation: "invite",
31761
+ sendOwnerEmail: false,
31643
31762
  termsAccepted: true,
31644
31763
  vendor: vendorPayload(),
31645
31764
  user: {
31646
31765
  name: ownerName.trim(),
31647
31766
  email: ownerEmail.trim(),
31648
31767
  phone: ownerPhone.trim() || void 0,
31649
- designation: ownerDesignation.trim() || void 0,
31650
- ...activationMode === "password" ? {
31651
- password: ownerPassword
31652
- } : {}
31768
+ designation: ownerDesignation.trim() || void 0
31653
31769
  }
31654
31770
  })
31655
31771
  });
@@ -31660,22 +31776,19 @@ function VendorEditPage({ vendorId }) {
31660
31776
  ]);
31661
31777
  return;
31662
31778
  }
31663
- const message = data.message || "Vendor created";
31664
- const inviteLink = typeof data.inviteLink === "string" ? data.inviteLink.trim() : "";
31665
- if (inviteLink) {
31666
- try {
31667
- await navigator.clipboard.writeText(inviteLink);
31668
- toast.success(`${message} Invite link copied to clipboard.`);
31669
- } catch {
31670
- toast.success(message);
31671
- toast.message("Invite link", {
31672
- description: inviteLink
31673
- });
31674
- }
31675
- } else {
31676
- toast.success(message);
31779
+ const vendorIdNum = Number(data.vendor?.id);
31780
+ const inviteLink = typeof data.inviteLink === "string" && data.inviteLink.trim() ? data.inviteLink.trim() : "";
31781
+ if (!Number.isFinite(vendorIdNum) || vendorIdNum <= 0 || !inviteLink) {
31782
+ toast.success(data.message || "Vendor created");
31783
+ router.push(listReturnUrl);
31784
+ return;
31677
31785
  }
31678
- router.push(listReturnUrl);
31786
+ toast.success(data.message || "Vendor created");
31787
+ setLinkCopied(false);
31788
+ setInviteDialog({
31789
+ vendorId: vendorIdNum,
31790
+ inviteLink
31791
+ });
31679
31792
  } catch {
31680
31793
  setErrors([
31681
31794
  "Request failed"
@@ -31746,7 +31859,6 @@ function VendorEditPage({ vendorId }) {
31746
31859
  setSaving(false);
31747
31860
  }
31748
31861
  }, "handleSave");
31749
- const createSubmitLabel = activationMode === "password" ? sendOwnerEmail ? "Create vendor & send welcome email" : "Create vendor & set password" : sendOwnerEmail ? "Create vendor & send invite" : "Create vendor & copy invite link";
31750
31862
  if (loading) {
31751
31863
  return /* @__PURE__ */ React26__default.createElement("div", {
31752
31864
  className: "flex items-center justify-center py-12"
@@ -31758,11 +31870,11 @@ function VendorEditPage({ vendorId }) {
31758
31870
  className: "rounded-lg bg-white shadow-md min-h-[420px]"
31759
31871
  }, /* @__PURE__ */ React26__default.createElement(DetailPageHeader, {
31760
31872
  title: create ? "Add vendor" : "Edit vendor",
31761
- subtitle: create ? "Register a vendor store and create the owner account" : "Update store and registration details",
31873
+ subtitle: create ? "Register a vendor store and create the owner invite" : "Update store and registration details",
31762
31874
  closeHref: listReturnUrl,
31763
31875
  menuItems: create ? [
31764
31876
  {
31765
- label: saving ? "Creating\u2026" : createSubmitLabel,
31877
+ label: saving ? "Creating\u2026" : "Create vendor",
31766
31878
  icon: Save,
31767
31879
  onClick: handleCreate
31768
31880
  }
@@ -32009,7 +32121,20 @@ function VendorEditPage({ vendorId }) {
32009
32121
  readOnly: true,
32010
32122
  value: inviteStatus,
32011
32123
  className: `mt-1 ${fieldClass} bg-gray-100`
32012
- })), /* @__PURE__ */ React26__default.createElement("div", null, /* @__PURE__ */ React26__default.createElement(FieldLabel, null, "Active"), /* @__PURE__ */ React26__default.createElement(Input, {
32124
+ })), canReinviteOwner && /* @__PURE__ */ React26__default.createElement("div", {
32125
+ className: "pt-1"
32126
+ }, /* @__PURE__ */ React26__default.createElement(Button, {
32127
+ type: "button",
32128
+ variant: "outline",
32129
+ size: "sm",
32130
+ className: "w-full",
32131
+ disabled: reinviting || saving,
32132
+ onClick: /* @__PURE__ */ __name(() => void handleReinviteOwner(), "onClick")
32133
+ }, /* @__PURE__ */ React26__default.createElement(Mail, {
32134
+ className: "h-4 w-4 mr-2"
32135
+ }), reinviting ? "Sending invite\u2026" : "Re-invite owner"), /* @__PURE__ */ React26__default.createElement("p", {
32136
+ className: "mt-2 text-xs text-gray-500"
32137
+ }, "Sends a new invite email and invalidates any previous invite link immediately.")), /* @__PURE__ */ React26__default.createElement("div", null, /* @__PURE__ */ React26__default.createElement(FieldLabel, null, "Active"), /* @__PURE__ */ React26__default.createElement(Input, {
32013
32138
  readOnly: true,
32014
32139
  value: active ? "Yes" : "No",
32015
32140
  className: `mt-1 ${fieldClass} bg-gray-100`
@@ -32017,64 +32142,42 @@ function VendorEditPage({ vendorId }) {
32017
32142
  className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2"
32018
32143
  }, "Owner access"), /* @__PURE__ */ React26__default.createElement("div", {
32019
32144
  className: sectionCls6
32020
- }, /* @__PURE__ */ React26__default.createElement(RadioGroup2, {
32021
- value: activationMode,
32022
- onValueChange: /* @__PURE__ */ __name((v) => setActivationMode(v), "onValueChange"),
32023
- className: "gap-3"
32024
- }, /* @__PURE__ */ React26__default.createElement("div", {
32025
- className: "flex items-start gap-2"
32026
- }, /* @__PURE__ */ React26__default.createElement(RadioGroupItem, {
32027
- value: "invite",
32028
- id: "activation-invite",
32029
- className: "mt-0.5"
32030
- }), /* @__PURE__ */ React26__default.createElement(Label3, {
32031
- htmlFor: "activation-invite",
32032
- className: "font-normal cursor-pointer text-sm"
32033
- }, "Send invite link")), /* @__PURE__ */ React26__default.createElement("div", {
32034
- className: "flex items-start gap-2"
32035
- }, /* @__PURE__ */ React26__default.createElement(RadioGroupItem, {
32036
- value: "password",
32037
- id: "activation-password",
32038
- className: "mt-0.5"
32039
- }), /* @__PURE__ */ React26__default.createElement(Label3, {
32040
- htmlFor: "activation-password",
32041
- className: "font-normal cursor-pointer text-sm"
32042
- }, "Set password now"))), /* @__PURE__ */ React26__default.createElement("div", {
32043
- className: "flex items-center gap-2 pt-1"
32044
- }, /* @__PURE__ */ React26__default.createElement(Checkbox, {
32045
- id: "sendOwnerEmail",
32046
- checked: sendOwnerEmail,
32047
- onCheckedChange: /* @__PURE__ */ __name((checked) => setSendOwnerEmail(checked === true), "onCheckedChange")
32048
- }), /* @__PURE__ */ React26__default.createElement(Label3, {
32049
- htmlFor: "sendOwnerEmail",
32050
- className: "font-normal cursor-pointer text-sm"
32051
- }, activationMode === "invite" ? "Send invite email" : "Send welcome email")), activationMode === "password" && /* @__PURE__ */ React26__default.createElement("div", {
32052
- className: "space-y-3 pt-1"
32053
- }, /* @__PURE__ */ React26__default.createElement("div", null, /* @__PURE__ */ React26__default.createElement(FieldLabel, {
32054
- htmlFor: "ownerPassword",
32055
- required: true
32056
- }, "Password"), /* @__PURE__ */ React26__default.createElement(Input, {
32057
- id: "ownerPassword",
32058
- type: "password",
32059
- value: ownerPassword,
32060
- onChange: /* @__PURE__ */ __name((e) => setOwnerPassword(e.target.value), "onChange"),
32061
- className: `mt-1 ${fieldClass}`
32062
- })), /* @__PURE__ */ React26__default.createElement("div", null, /* @__PURE__ */ React26__default.createElement(FieldLabel, {
32063
- htmlFor: "ownerPasswordConfirm",
32064
- required: true
32065
- }, "Confirm password"), /* @__PURE__ */ React26__default.createElement(Input, {
32066
- id: "ownerPasswordConfirm",
32067
- type: "password",
32068
- value: ownerPasswordConfirm,
32069
- onChange: /* @__PURE__ */ __name((e) => setOwnerPasswordConfirm(e.target.value), "onChange"),
32070
- className: `mt-1 ${fieldClass}`
32071
- }))), /* @__PURE__ */ React26__default.createElement(Button, {
32145
+ }, /* @__PURE__ */ React26__default.createElement("p", {
32146
+ className: "text-sm text-gray-600"
32147
+ }, "Creates the vendor and an invite for the owner. After create, you can send the invite email or copy the invite link."), /* @__PURE__ */ React26__default.createElement(Button, {
32072
32148
  type: "button",
32073
32149
  disabled: saving,
32074
32150
  onClick: handleCreate,
32075
32151
  className: "w-full"
32076
- }, saving ? "Creating\u2026" : createSubmitLabel))) : void 0)
32077
- }));
32152
+ }, saving ? "Creating\u2026" : "Create vendor"))) : void 0)
32153
+ }), /* @__PURE__ */ React26__default.createElement(Dialog, {
32154
+ open: inviteDialog != null,
32155
+ onOpenChange: /* @__PURE__ */ __name((open) => {
32156
+ if (!open) closeInviteDialog();
32157
+ }, "onOpenChange")
32158
+ }, /* @__PURE__ */ React26__default.createElement(DialogContent, {
32159
+ className: "max-w-md"
32160
+ }, /* @__PURE__ */ React26__default.createElement(DialogHeader, null, /* @__PURE__ */ React26__default.createElement(DialogTitle, null, "Vendor created"), /* @__PURE__ */ React26__default.createElement(DialogDescription, null, "Send an invite email to the owner, or copy the invite link to share another way. The link is not shown here.")), /* @__PURE__ */ React26__default.createElement("div", {
32161
+ className: "flex flex-col gap-2 py-2"
32162
+ }, /* @__PURE__ */ React26__default.createElement(Button, {
32163
+ type: "button",
32164
+ disabled: sendingInviteEmail,
32165
+ onClick: /* @__PURE__ */ __name(() => void sendInviteEmail(), "onClick")
32166
+ }, /* @__PURE__ */ React26__default.createElement(Mail, {
32167
+ className: "h-4 w-4 mr-2"
32168
+ }), sendingInviteEmail ? "Sending\u2026" : "Send email"), /* @__PURE__ */ React26__default.createElement(Button, {
32169
+ type: "button",
32170
+ variant: "outline",
32171
+ onClick: /* @__PURE__ */ __name(() => void copyInviteLink(), "onClick")
32172
+ }, linkCopied ? /* @__PURE__ */ React26__default.createElement(Check, {
32173
+ className: "h-4 w-4 mr-2"
32174
+ }) : /* @__PURE__ */ React26__default.createElement(Copy, {
32175
+ className: "h-4 w-4 mr-2"
32176
+ }), linkCopied ? "Copied" : "Copy invite link")), /* @__PURE__ */ React26__default.createElement(DialogFooter, null, /* @__PURE__ */ React26__default.createElement(Button, {
32177
+ type: "button",
32178
+ variant: "secondary",
32179
+ onClick: closeInviteDialog
32180
+ }, "Done")))));
32078
32181
  }
32079
32182
  var isCreate6, fieldClass, selectClass, sectionCls6;
32080
32183
  var init_VendorEditPage = __esm({
@@ -32090,7 +32193,7 @@ var init_VendorEditPage = __esm({
32090
32193
  init_label();
32091
32194
  init_textarea();
32092
32195
  init_checkbox();
32093
- init_radio_group();
32196
+ init_dialog();
32094
32197
  init_vendor_profile();
32095
32198
  init_vendor_list_config();
32096
32199
  init_vendor_access_denied();
package/dist/api.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkERJK5QXN_cjs = require('./chunk-ERJK5QXN.cjs');
3
+ var chunkQU554KAZ_cjs = require('./chunk-QU554KAZ.cjs');
4
4
  require('./chunk-22FFHLTO.cjs');
5
5
  require('./chunk-UCKN4BBY.cjs');
6
6
  require('./chunk-7NMT3GBR.cjs');
@@ -20,127 +20,127 @@ require('./chunk-USNT2KNT.cjs');
20
20
 
21
21
  Object.defineProperty(exports, "createAnalyticsHandlers", {
22
22
  enumerable: true,
23
- get: function () { return chunkERJK5QXN_cjs.createAnalyticsHandlers; }
23
+ get: function () { return chunkQU554KAZ_cjs.createAnalyticsHandlers; }
24
24
  });
25
25
  Object.defineProperty(exports, "createBlogBySlugHandler", {
26
26
  enumerable: true,
27
- get: function () { return chunkERJK5QXN_cjs.createBlogBySlugHandler; }
27
+ get: function () { return chunkQU554KAZ_cjs.createBlogBySlugHandler; }
28
28
  });
29
29
  Object.defineProperty(exports, "createChangePasswordHandler", {
30
30
  enumerable: true,
31
- get: function () { return chunkERJK5QXN_cjs.createChangePasswordHandler; }
31
+ get: function () { return chunkQU554KAZ_cjs.createChangePasswordHandler; }
32
32
  });
33
33
  Object.defineProperty(exports, "createCmsApiHandler", {
34
34
  enumerable: true,
35
- get: function () { return chunkERJK5QXN_cjs.createCmsApiHandler; }
35
+ get: function () { return chunkQU554KAZ_cjs.createCmsApiHandler; }
36
36
  });
37
37
  Object.defineProperty(exports, "createCrudByIdHandler", {
38
38
  enumerable: true,
39
- get: function () { return chunkERJK5QXN_cjs.createCrudByIdHandler; }
39
+ get: function () { return chunkQU554KAZ_cjs.createCrudByIdHandler; }
40
40
  });
41
41
  Object.defineProperty(exports, "createCrudHandler", {
42
42
  enumerable: true,
43
- get: function () { return chunkERJK5QXN_cjs.createCrudHandler; }
43
+ get: function () { return chunkQU554KAZ_cjs.createCrudHandler; }
44
44
  });
45
45
  Object.defineProperty(exports, "createDashboardStatsHandler", {
46
46
  enumerable: true,
47
- get: function () { return chunkERJK5QXN_cjs.createDashboardStatsHandler; }
47
+ get: function () { return chunkQU554KAZ_cjs.createDashboardStatsHandler; }
48
48
  });
49
49
  Object.defineProperty(exports, "createEcommerceAnalyticsHandler", {
50
50
  enumerable: true,
51
- get: function () { return chunkERJK5QXN_cjs.createEcommerceAnalyticsHandler; }
51
+ get: function () { return chunkQU554KAZ_cjs.createEcommerceAnalyticsHandler; }
52
52
  });
53
53
  Object.defineProperty(exports, "createForgotPasswordHandler", {
54
54
  enumerable: true,
55
- get: function () { return chunkERJK5QXN_cjs.createForgotPasswordHandler; }
55
+ get: function () { return chunkQU554KAZ_cjs.createForgotPasswordHandler; }
56
56
  });
57
57
  Object.defineProperty(exports, "createFormBySlugHandler", {
58
58
  enumerable: true,
59
- get: function () { return chunkERJK5QXN_cjs.createFormBySlugHandler; }
59
+ get: function () { return chunkQU554KAZ_cjs.createFormBySlugHandler; }
60
60
  });
61
61
  Object.defineProperty(exports, "createInviteAcceptHandler", {
62
62
  enumerable: true,
63
- get: function () { return chunkERJK5QXN_cjs.createInviteAcceptHandler; }
63
+ get: function () { return chunkQU554KAZ_cjs.createInviteAcceptHandler; }
64
64
  });
65
65
  Object.defineProperty(exports, "createJobScheduleHandlers", {
66
66
  enumerable: true,
67
- get: function () { return chunkERJK5QXN_cjs.createJobScheduleHandlers; }
67
+ get: function () { return chunkQU554KAZ_cjs.createJobScheduleHandlers; }
68
68
  });
69
69
  Object.defineProperty(exports, "createLlmAgentKnowledgeHandlers", {
70
70
  enumerable: true,
71
- get: function () { return chunkERJK5QXN_cjs.createLlmAgentKnowledgeHandlers; }
71
+ get: function () { return chunkQU554KAZ_cjs.createLlmAgentKnowledgeHandlers; }
72
72
  });
73
73
  Object.defineProperty(exports, "createMediaZipExtractHandler", {
74
74
  enumerable: true,
75
- get: function () { return chunkERJK5QXN_cjs.createMediaZipExtractHandler; }
75
+ get: function () { return chunkQU554KAZ_cjs.createMediaZipExtractHandler; }
76
76
  });
77
77
  Object.defineProperty(exports, "createSetPasswordHandler", {
78
78
  enumerable: true,
79
- get: function () { return chunkERJK5QXN_cjs.createSetPasswordHandler; }
79
+ get: function () { return chunkQU554KAZ_cjs.createSetPasswordHandler; }
80
80
  });
81
81
  Object.defineProperty(exports, "createSettingsApiHandlers", {
82
82
  enumerable: true,
83
- get: function () { return chunkERJK5QXN_cjs.createSettingsApiHandlers; }
83
+ get: function () { return chunkQU554KAZ_cjs.createSettingsApiHandlers; }
84
84
  });
85
85
  Object.defineProperty(exports, "createStorefrontApiHandler", {
86
86
  enumerable: true,
87
- get: function () { return chunkERJK5QXN_cjs.createStorefrontApiHandler; }
87
+ get: function () { return chunkQU554KAZ_cjs.createStorefrontApiHandler; }
88
88
  });
89
89
  Object.defineProperty(exports, "createUploadHandler", {
90
90
  enumerable: true,
91
- get: function () { return chunkERJK5QXN_cjs.createUploadHandler; }
91
+ get: function () { return chunkQU554KAZ_cjs.createUploadHandler; }
92
92
  });
93
93
  Object.defineProperty(exports, "createUserAuthApiRouter", {
94
94
  enumerable: true,
95
- get: function () { return chunkERJK5QXN_cjs.createUserAuthApiRouter; }
95
+ get: function () { return chunkQU554KAZ_cjs.createUserAuthApiRouter; }
96
96
  });
97
97
  Object.defineProperty(exports, "createUserAvatarHandler", {
98
98
  enumerable: true,
99
- get: function () { return chunkERJK5QXN_cjs.createUserAvatarHandler; }
99
+ get: function () { return chunkQU554KAZ_cjs.createUserAvatarHandler; }
100
100
  });
101
101
  Object.defineProperty(exports, "createUserProfileHandler", {
102
102
  enumerable: true,
103
- get: function () { return chunkERJK5QXN_cjs.createUserProfileHandler; }
103
+ get: function () { return chunkQU554KAZ_cjs.createUserProfileHandler; }
104
104
  });
105
105
  Object.defineProperty(exports, "createUsersApiHandlers", {
106
106
  enumerable: true,
107
- get: function () { return chunkERJK5QXN_cjs.createUsersApiHandlers; }
107
+ get: function () { return chunkQU554KAZ_cjs.createUsersApiHandlers; }
108
108
  });
109
109
  Object.defineProperty(exports, "createVendorDashboardHandler", {
110
110
  enumerable: true,
111
- get: function () { return chunkERJK5QXN_cjs.createVendorDashboardHandler; }
111
+ get: function () { return chunkQU554KAZ_cjs.createVendorDashboardHandler; }
112
112
  });
113
113
  Object.defineProperty(exports, "createVendorOnboardHandlers", {
114
114
  enumerable: true,
115
- get: function () { return chunkERJK5QXN_cjs.createVendorOnboardHandlers; }
115
+ get: function () { return chunkQU554KAZ_cjs.createVendorOnboardHandlers; }
116
116
  });
117
117
  Object.defineProperty(exports, "getPublicSettingsGroup", {
118
118
  enumerable: true,
119
- get: function () { return chunkERJK5QXN_cjs.getPublicSettingsGroup; }
119
+ get: function () { return chunkQU554KAZ_cjs.getPublicSettingsGroup; }
120
120
  });
121
121
  Object.defineProperty(exports, "mergeGuardrailsIntoSystemPrompt", {
122
122
  enumerable: true,
123
- get: function () { return chunkERJK5QXN_cjs.mergeGuardrailsIntoSystemPrompt; }
123
+ get: function () { return chunkQU554KAZ_cjs.mergeGuardrailsIntoSystemPrompt; }
124
124
  });
125
125
  Object.defineProperty(exports, "parseLlmAgentValidationRules", {
126
126
  enumerable: true,
127
- get: function () { return chunkERJK5QXN_cjs.parseLlmAgentValidationRules; }
127
+ get: function () { return chunkQU554KAZ_cjs.parseLlmAgentValidationRules; }
128
128
  });
129
129
  Object.defineProperty(exports, "simpleDecrypt", {
130
130
  enumerable: true,
131
- get: function () { return chunkERJK5QXN_cjs.simpleDecrypt; }
131
+ get: function () { return chunkQU554KAZ_cjs.simpleDecrypt; }
132
132
  });
133
133
  Object.defineProperty(exports, "simpleEncrypt", {
134
134
  enumerable: true,
135
- get: function () { return chunkERJK5QXN_cjs.simpleEncrypt; }
135
+ get: function () { return chunkQU554KAZ_cjs.simpleEncrypt; }
136
136
  });
137
137
  Object.defineProperty(exports, "validateUserMessageAgainstAgentRules", {
138
138
  enumerable: true,
139
- get: function () { return chunkERJK5QXN_cjs.validateUserMessageAgainstAgentRules; }
139
+ get: function () { return chunkQU554KAZ_cjs.validateUserMessageAgainstAgentRules; }
140
140
  });
141
141
  Object.defineProperty(exports, "validateUserMessageAgainstStructuredRules", {
142
142
  enumerable: true,
143
- get: function () { return chunkERJK5QXN_cjs.validateUserMessageAgainstStructuredRules; }
143
+ get: function () { return chunkQU554KAZ_cjs.validateUserMessageAgainstStructuredRules; }
144
144
  });
145
145
  Object.defineProperty(exports, "createCmsAuthBundle", {
146
146
  enumerable: true,
package/dist/api.d.cts CHANGED
@@ -137,7 +137,7 @@ interface InviteAcceptConfig extends AuthHandlersConfig {
137
137
  entityMap: EntityMap;
138
138
  beforeActivate?: (email: string, userId: number) => Promise<void>;
139
139
  }
140
- /** Decode invite token (base64 email) and set password + unblock user */
140
+ /** Accept invite: vendor rotating token (preferred) or legacy base64 email token */
141
141
  declare function createInviteAcceptHandler(config: InviteAcceptConfig): (request: Request) => Promise<Response>;
142
142
  interface ChangePasswordConfig extends AuthHandlersConfig {
143
143
  dataSource: DataSource;
@@ -165,6 +165,7 @@ interface UserAuthApiConfig extends ForgotPasswordConfig, Omit<SetPasswordConfig
165
165
  * Path is the segment after the mount (e.g. "forgot-password"). Returns 404 for unknown paths.
166
166
  */
167
167
  declare function createUserAuthApiRouter(config: UserAuthApiConfig): {
168
+ GET(req: Request, pathname: string): Promise<Response>;
168
169
  POST(req: Request, pathname: string): Promise<Response>;
169
170
  };
170
171
 
@@ -564,6 +565,8 @@ interface VendorOnboardHandlersConfig {
564
565
  declare function createVendorOnboardHandlers(config: VendorOnboardHandlersConfig): {
565
566
  /** POST /api/admin/vendors/onboard — create vendor + owner user + vendor_users + invite */
566
567
  onboard(req: Request): Promise<Response>;
568
+ /** POST /api/admin/vendors/:id/resend-invite — rotate owner invite token and resend email */
569
+ resendInvite(req: Request, vendorIdStr: string): Promise<Response>;
567
570
  /** POST /api/admin/vendor/switch — set active vendor in session (JWT update via client) */
568
571
  switchVendor(req: Request): Promise<Response>;
569
572
  /** GET /api/admin/vendor/team */