@infuro/cms-core 1.0.65 → 1.0.67

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 (36) hide show
  1. package/dist/admin.cjs +97 -24
  2. package/dist/admin.js +97 -24
  3. package/dist/api.cjs +38 -38
  4. package/dist/api.js +5 -5
  5. package/dist/auth.cjs +51 -51
  6. package/dist/auth.js +3 -3
  7. package/dist/{chunk-6DBDJ4VD.js → chunk-2ISSXYBZ.js} +2 -2
  8. package/dist/{chunk-NIRYYJIJ.cjs → chunk-5MZFQRDW.cjs} +73 -55
  9. package/dist/{chunk-MVHDC3XF.js → chunk-5NOZSG6J.js} +22 -11
  10. package/dist/{chunk-YHEITFHR.cjs → chunk-BVLN75LP.cjs} +540 -143
  11. package/dist/{chunk-YEAXE4U2.js → chunk-FLUF2GZH.js} +5 -11
  12. package/dist/{chunk-SANKKGB3.js → chunk-GLLCLRCQ.js} +464 -67
  13. package/dist/{chunk-ACBN6UWZ.js → chunk-NV5IRHI3.js} +26 -8
  14. package/dist/{chunk-J7FMZK66.cjs → chunk-O4AFPDQ4.cjs} +22 -11
  15. package/dist/{chunk-4U6DATGZ.cjs → chunk-OV5TRZET.cjs} +7 -7
  16. package/dist/{chunk-BXAKL2TF.cjs → chunk-PA6YDMFZ.cjs} +5 -11
  17. package/dist/{chunk-RDEVZMO5.js → chunk-RCE5SJBA.js} +2 -2
  18. package/dist/{chunk-KM2I6AFP.cjs → chunk-SS3K7OIM.cjs} +9 -9
  19. package/dist/{chunk-V6EYAC7X.cjs → chunk-WMMZZRDJ.cjs} +15 -15
  20. package/dist/{chunk-NR44CK5E.js → chunk-ZY64VJMS.js} +1 -1
  21. package/dist/{emit-order-notification-trigger-UCKJHDQK.js → emit-order-notification-trigger-EJJZ6XTS.js} +2 -2
  22. package/dist/{emit-order-notification-trigger-DR74TQXN.cjs → emit-order-notification-trigger-ZD5YN3JM.cjs} +4 -4
  23. package/dist/index.cjs +284 -280
  24. package/dist/index.d.cts +14 -1
  25. package/dist/index.d.ts +14 -1
  26. package/dist/index.js +10 -10
  27. package/dist/migrations/1783300000000-CreateOrderAssigneesTable.ts +43 -0
  28. package/dist/{order-assignees-handlers-NPKD64P6.cjs → order-assignees-handlers-KF7RMTV5.cjs} +77 -8
  29. package/dist/{order-assignees-handlers-LKMAGLG6.js → order-assignees-handlers-L3RVKUBS.js} +77 -8
  30. package/dist/{order-completion-otp-handlers-RW5RSXH3.cjs → order-completion-otp-handlers-DZAXK4GQ.cjs} +70 -16
  31. package/dist/{order-completion-otp-handlers-CH22ZRAI.js → order-completion-otp-handlers-HFGCPC4O.js} +69 -15
  32. package/dist/{order-notification-dispatcher-3TXUAJ7L.js → order-notification-dispatcher-ECPFI7CD.js} +2 -2
  33. package/dist/{order-notification-dispatcher-Y7NZAALH.cjs → order-notification-dispatcher-LL7ETKLU.cjs} +7 -7
  34. package/dist/{rbac-debug-db-5R6XFPSV.js → rbac-debug-db-DFZWZ6GV.js} +1 -1
  35. package/dist/{rbac-debug-db-JKK2MCWF.cjs → rbac-debug-db-KWV7D5PQ.cjs} +2 -2
  36. package/package.json +1 -1
package/dist/admin.cjs CHANGED
@@ -895,7 +895,7 @@ var init_admin_config_context = __esm({
895
895
  var CMS_VERSION;
896
896
  var init_cms_version = __esm({
897
897
  "src/lib/cms-version.ts"() {
898
- CMS_VERSION = "1.0.65" ;
898
+ CMS_VERSION = "1.0.67" ;
899
899
  }
900
900
  });
901
901
  function useCatalogCategories(enabled = true) {
@@ -17509,7 +17509,7 @@ function PushTriggerBindings({ audience = "customer" }) {
17509
17509
  (async () => {
17510
17510
  try {
17511
17511
  setLoadingTpl(true);
17512
- const res = await fetch("/api/message-templates/email", {
17512
+ const res = await fetch("/api/message-templates/mobile", {
17513
17513
  cache: "no-store"
17514
17514
  });
17515
17515
  if (!res.ok) throw new Error("Failed to load message templates");
@@ -17613,7 +17613,7 @@ function PushTriggerBindings({ audience = "customer" }) {
17613
17613
  try {
17614
17614
  let tplId = activeBindingTplId;
17615
17615
  if (tplId) {
17616
- const res = await jsonFetch(`/api/message-templates/email/${tplId}`, {
17616
+ const res = await jsonFetch(`/api/message-templates/mobile/${tplId}`, {
17617
17617
  method: "PATCH",
17618
17618
  headers: {
17619
17619
  "Content-Type": "application/json"
@@ -17628,7 +17628,7 @@ function PushTriggerBindings({ audience = "customer" }) {
17628
17628
  setTemplates((prev) => prev.map((t) => t.id === res.item.id ? res.item : t));
17629
17629
  }
17630
17630
  } else {
17631
- const res = await jsonFetch("/api/message-templates/email", {
17631
+ const res = await jsonFetch("/api/message-templates/mobile", {
17632
17632
  method: "POST",
17633
17633
  headers: {
17634
17634
  "Content-Type": "application/json"
@@ -24598,7 +24598,10 @@ function OrderDetailPage({ orderId }) {
24598
24598
  const [cancelModal, setCancelModal] = React27.useState(null);
24599
24599
  const [assignModalOpen, setAssignModalOpen] = React27.useState(false);
24600
24600
  const [assigneesList, setAssigneesList] = React27.useState([]);
24601
+ const [vendorsList, setVendorsList] = React27.useState([]);
24602
+ const [isPlatformAdmin, setIsPlatformAdmin] = React27.useState(false);
24601
24603
  const [loadingAssignees, setLoadingAssignees] = React27.useState(false);
24604
+ const [selectedVendorId, setSelectedVendorId] = React27.useState(null);
24602
24605
  const [selectedAssigneeId, setSelectedAssigneeId] = React27.useState(null);
24603
24606
  const [savingAssignee, setSavingAssignee] = React27.useState(false);
24604
24607
  const [completeModalOpen, setCompleteModalOpen] = React27.useState(false);
@@ -24698,8 +24701,9 @@ function OrderDetailPage({ orderId }) {
24698
24701
  async function handleStartProcessing() {
24699
24702
  if (!order || startingProcessing) return;
24700
24703
  const currentAssigneeId = order.assignedUserId ?? order.assignedUser?.id ?? null;
24701
- if (!currentAssigneeId) {
24702
- sonner.toast.info("Please assign a teammate before starting order processing.");
24704
+ const currentVendorId = order.vendorId ?? order.vendor?.id ?? null;
24705
+ if (!currentAssigneeId && !currentVendorId) {
24706
+ sonner.toast.info("Please assign a vendor or teammate before starting order processing.");
24703
24707
  handleOpenAssignModal();
24704
24708
  return;
24705
24709
  }
@@ -24712,7 +24716,9 @@ function OrderDetailPage({ orderId }) {
24712
24716
  },
24713
24717
  body: JSON.stringify({
24714
24718
  status: "processing",
24715
- assignedUserId: currentAssigneeId
24719
+ ...currentAssigneeId ? {
24720
+ assignedUserId: currentAssigneeId
24721
+ } : {}
24716
24722
  })
24717
24723
  });
24718
24724
  const data = await res.json().catch(() => ({}));
@@ -24734,14 +24740,19 @@ function OrderDetailPage({ orderId }) {
24734
24740
  setAssignModalOpen(true);
24735
24741
  setLoadingAssignees(true);
24736
24742
  setSelectedAssigneeId(order?.assignedUserId ?? null);
24743
+ setSelectedVendorId(order?.vendorId ?? null);
24737
24744
  try {
24738
24745
  const res = await fetch(`/api/orders/${orderId}/eligible-assignees`);
24739
24746
  if (res.ok) {
24740
24747
  const data = await res.json();
24741
24748
  setAssigneesList(data.assignees ?? []);
24749
+ setVendorsList(data.vendors ?? []);
24750
+ setIsPlatformAdmin(Boolean(data.isPlatformAdmin));
24751
+ if (data.currentVendorId != null) setSelectedVendorId(data.currentVendorId);
24752
+ if (data.currentAssignedUserId != null) setSelectedAssigneeId(data.currentAssignedUserId);
24742
24753
  }
24743
24754
  } catch {
24744
- sonner.toast.error("Failed to load eligible team members");
24755
+ sonner.toast.error("Failed to load eligible assignees");
24745
24756
  } finally {
24746
24757
  setLoadingAssignees(false);
24747
24758
  }
@@ -24754,6 +24765,14 @@ function OrderDetailPage({ orderId }) {
24754
24765
  const bodyPayload = {
24755
24766
  assignedUserId: selectedAssigneeId
24756
24767
  };
24768
+ if (isPlatformAdmin) {
24769
+ const chosenAssignee = assigneesList.find((a) => a.id === selectedAssigneeId);
24770
+ if (chosenAssignee && chosenAssignee.vendorId === null) {
24771
+ bodyPayload.vendorId = 1;
24772
+ } else {
24773
+ bodyPayload.vendorId = chosenAssignee?.vendorId ?? (selectedVendorId || 1);
24774
+ }
24775
+ }
24757
24776
  const res = await fetch(`/api/orders/${orderId}`, {
24758
24777
  method: "PUT",
24759
24778
  headers: {
@@ -24763,15 +24782,15 @@ function OrderDetailPage({ orderId }) {
24763
24782
  });
24764
24783
  if (!res.ok) {
24765
24784
  const err = await res.json().catch(() => ({}));
24766
- sonner.toast.error(err.error ?? "Failed to update assignee");
24785
+ sonner.toast.error(err.error ?? "Failed to update assignment");
24767
24786
  return;
24768
24787
  }
24769
24788
  const updated = await fetch(`/api/orders/${orderId}`);
24770
24789
  if (updated.ok) setOrder(await updated.json());
24771
24790
  setAssignModalOpen(false);
24772
- sonner.toast.success(selectedAssigneeId ? "Order assigned successfully" : "Assignee removed");
24791
+ sonner.toast.success(selectedAssigneeId || selectedVendorId ? "Order assigned successfully" : "Assignment removed");
24773
24792
  } catch {
24774
- sonner.toast.error("Failed to update assignee");
24793
+ sonner.toast.error("Failed to update assignment");
24775
24794
  } finally {
24776
24795
  setSavingAssignee(false);
24777
24796
  }
@@ -25156,7 +25175,19 @@ function OrderDetailPage({ orderId }) {
25156
25175
  className: "min-w-0"
25157
25176
  }, /* @__PURE__ */ React.createElement("dt", {
25158
25177
  className: "text-gray-500"
25159
- }, "Assigned To"), /* @__PURE__ */ React.createElement("dd", {
25178
+ }, "Vendor"), /* @__PURE__ */ React.createElement("dd", {
25179
+ className: "font-medium text-gray-900 flex flex-wrap items-center gap-1.5 mt-0.5"
25180
+ }, order.vendor ? /* @__PURE__ */ React.createElement("span", {
25181
+ className: "inline-flex items-center gap-1 text-xs bg-purple-50 text-purple-800 font-medium px-2 py-0.5 rounded-full border border-purple-200"
25182
+ }, order.vendor.name || `Vendor #${order.vendor.id}`) : order.vendorId ? /* @__PURE__ */ React.createElement("span", {
25183
+ className: "inline-flex items-center gap-1 text-xs bg-purple-50 text-purple-800 font-medium px-2 py-0.5 rounded-full border border-purple-200"
25184
+ }, `Vendor #${order.vendorId}`) : /* @__PURE__ */ React.createElement("span", {
25185
+ className: "text-gray-400 text-xs italic"
25186
+ }, "Platform Default"))), /* @__PURE__ */ React.createElement("div", {
25187
+ className: "min-w-0"
25188
+ }, /* @__PURE__ */ React.createElement("dt", {
25189
+ className: "text-gray-500"
25190
+ }, "Assigned Teammate"), /* @__PURE__ */ React.createElement("dd", {
25160
25191
  className: "font-medium text-gray-900 flex flex-wrap items-center gap-1.5 mt-0.5"
25161
25192
  }, order.assignedUser ? /* @__PURE__ */ React.createElement("span", {
25162
25193
  className: "inline-flex items-center gap-1 text-xs bg-blue-50 text-blue-800 font-medium px-2 py-0.5 rounded-full border border-blue-200"
@@ -25425,7 +25456,7 @@ function OrderDetailPage({ orderId }) {
25425
25456
  className: "text-base font-semibold text-gray-900 flex items-center gap-2"
25426
25457
  }, /* @__PURE__ */ React.createElement(LucideIcons.UserCheck, {
25427
25458
  className: "h-5 w-5 text-blue-600"
25428
- }), "Assign Order to Teammate"), /* @__PURE__ */ React.createElement("button", {
25459
+ }), isPlatformAdmin ? "Assign Order (Vendor & Team)" : "Assign Order to Teammate"), /* @__PURE__ */ React.createElement("button", {
25429
25460
  type: "button",
25430
25461
  onClick: /* @__PURE__ */ __name(() => setAssignModalOpen(false), "onClick"),
25431
25462
  className: "text-gray-400 hover:text-gray-600"
@@ -25433,14 +25464,42 @@ function OrderDetailPage({ orderId }) {
25433
25464
  className: "h-5 w-5"
25434
25465
  }))), /* @__PURE__ */ React.createElement("p", {
25435
25466
  className: "text-xs text-gray-500"
25436
- }, "Select a team member to handle this order. When assigned, order status automatically moves to Processing."), loadingAssignees ? /* @__PURE__ */ React.createElement("div", {
25467
+ }, isPlatformAdmin ? "Assign this order to a Vendor or directly to any Vendor's Team Member." : "Select a member of your team to handle this service, or keep it unassigned to your general store."), loadingAssignees ? /* @__PURE__ */ React.createElement("div", {
25437
25468
  className: "flex justify-center py-8"
25438
25469
  }, /* @__PURE__ */ React.createElement(LucideIcons.Loader2, {
25439
25470
  className: "h-6 w-6 animate-spin text-blue-600"
25440
25471
  })) : /* @__PURE__ */ React.createElement("div", {
25441
- className: "space-y-2 max-h-64 overflow-y-auto pr-1"
25472
+ className: "space-y-4"
25473
+ }, isPlatformAdmin && vendorsList.length > 0 && /* @__PURE__ */ React.createElement("div", {
25474
+ className: "space-y-1.5"
25475
+ }, /* @__PURE__ */ React.createElement("label", {
25476
+ className: "block text-xs font-semibold text-gray-700"
25477
+ }, "Assigned Vendor"), /* @__PURE__ */ React.createElement("select", {
25478
+ value: selectedVendorId ?? "",
25479
+ onChange: /* @__PURE__ */ __name((e) => {
25480
+ const val = e.target.value ? Number(e.target.value) : null;
25481
+ setSelectedVendorId(val);
25482
+ if (val && selectedAssigneeId) {
25483
+ const assignee = assigneesList.find((a) => a.id === selectedAssigneeId);
25484
+ if (assignee && assignee.vendorId !== val) {
25485
+ setSelectedAssigneeId(null);
25486
+ }
25487
+ }
25488
+ }, "onChange"),
25489
+ className: "w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
25490
+ }, /* @__PURE__ */ React.createElement("option", {
25491
+ value: ""
25492
+ }, "All Vendors / Any Vendor"), vendorsList.map((v) => /* @__PURE__ */ React.createElement("option", {
25493
+ key: v.id,
25494
+ value: v.id
25495
+ }, v.name)))), /* @__PURE__ */ React.createElement("div", {
25496
+ className: "space-y-1.5"
25442
25497
  }, /* @__PURE__ */ React.createElement("label", {
25443
- className: `flex items-center justify-between p-3 rounded-lg border cursor-pointer transition ${selectedAssigneeId === null ? "border-blue-600 bg-blue-50/50" : "border-gray-200 hover:bg-gray-50"}`
25498
+ className: "block text-xs font-semibold text-gray-700"
25499
+ }, isPlatformAdmin ? "Assigned Team Member" : "Select Team Member"), /* @__PURE__ */ React.createElement("div", {
25500
+ className: "space-y-2 max-h-56 overflow-y-auto pr-1"
25501
+ }, /* @__PURE__ */ React.createElement("label", {
25502
+ className: `flex items-center justify-between p-2.5 rounded-lg border cursor-pointer transition ${selectedAssigneeId === null ? "border-blue-600 bg-blue-50/50" : "border-gray-200 hover:bg-gray-50"}`
25444
25503
  }, /* @__PURE__ */ React.createElement("div", {
25445
25504
  className: "flex items-center gap-3"
25446
25505
  }, /* @__PURE__ */ React.createElement("input", {
@@ -25451,26 +25510,40 @@ function OrderDetailPage({ orderId }) {
25451
25510
  className: "text-blue-600"
25452
25511
  }), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("p", {
25453
25512
  className: "text-sm font-medium text-gray-800"
25454
- }, "Unassigned"), /* @__PURE__ */ React.createElement("p", {
25513
+ }, "Unassigned to specific person"), /* @__PURE__ */ React.createElement("p", {
25455
25514
  className: "text-xs text-gray-400"
25456
- }, "No specific team member")))), assigneesList.map((a) => /* @__PURE__ */ React.createElement("label", {
25515
+ }, selectedVendorId ? "Vendor general queue" : "General queue")))), assigneesList.filter((a) => {
25516
+ if (!isPlatformAdmin) return true;
25517
+ if (selectedVendorId && selectedVendorId !== 1) {
25518
+ return a.vendorId === selectedVendorId;
25519
+ }
25520
+ if (selectedVendorId === 1) {
25521
+ return a.vendorId === 1 || a.vendorId === null;
25522
+ }
25523
+ return true;
25524
+ }).map((a) => /* @__PURE__ */ React.createElement("label", {
25457
25525
  key: a.id,
25458
- className: `flex items-center justify-between p-3 rounded-lg border cursor-pointer transition ${selectedAssigneeId === a.id ? "border-blue-600 bg-blue-50/50" : "border-gray-200 hover:bg-gray-50"}`
25526
+ className: `flex items-center justify-between p-2.5 rounded-lg border cursor-pointer transition ${selectedAssigneeId === a.id ? "border-blue-600 bg-blue-50/50" : "border-gray-200 hover:bg-gray-50"}`
25459
25527
  }, /* @__PURE__ */ React.createElement("div", {
25460
25528
  className: "flex items-center gap-3"
25461
25529
  }, /* @__PURE__ */ React.createElement("input", {
25462
25530
  type: "radio",
25463
25531
  name: "assignee",
25464
25532
  checked: selectedAssigneeId === a.id,
25465
- onChange: /* @__PURE__ */ __name(() => setSelectedAssigneeId(a.id), "onChange"),
25533
+ onChange: /* @__PURE__ */ __name(() => {
25534
+ setSelectedAssigneeId(a.id);
25535
+ if (isPlatformAdmin) {
25536
+ setSelectedVendorId(a.vendorId || 1);
25537
+ }
25538
+ }, "onChange"),
25466
25539
  className: "text-blue-600"
25467
25540
  }), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("p", {
25468
25541
  className: "text-sm font-medium text-gray-900"
25469
25542
  }, a.name), /* @__PURE__ */ React.createElement("p", {
25470
25543
  className: "text-xs text-gray-500"
25471
- }, a.email))), /* @__PURE__ */ React.createElement("span", {
25472
- className: "text-[11px] font-medium text-gray-500 bg-gray-100 px-2 py-0.5 rounded"
25473
- }, a.role)))), /* @__PURE__ */ React.createElement("div", {
25544
+ }, a.email, isPlatformAdmin && a.vendorName ? ` \u2022 ${a.vendorName}` : ""))), /* @__PURE__ */ React.createElement("span", {
25545
+ className: "text-[11px] font-medium text-gray-600 bg-gray-100 px-2 py-0.5 rounded"
25546
+ }, a.role)))))), /* @__PURE__ */ React.createElement("div", {
25474
25547
  className: "flex justify-end gap-2 pt-2 border-t border-gray-100"
25475
25548
  }, /* @__PURE__ */ React.createElement(Button, {
25476
25549
  variant: "outline",
@@ -25480,7 +25553,7 @@ function OrderDetailPage({ orderId }) {
25480
25553
  onClick: handleSaveAssignee,
25481
25554
  disabled: savingAssignee,
25482
25555
  className: "bg-blue-600 hover:bg-blue-700 text-white"
25483
- }, savingAssignee ? "Saving..." : "Save Assignee")))), completeModalOpen && /* @__PURE__ */ React.createElement("div", {
25556
+ }, savingAssignee ? "Saving..." : "Save Assignment")))), completeModalOpen && /* @__PURE__ */ React.createElement("div", {
25484
25557
  className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm p-4 animate-in fade-in duration-150"
25485
25558
  }, /* @__PURE__ */ React.createElement("div", {
25486
25559
  className: "bg-white rounded-xl shadow-2xl w-full max-w-md p-6 space-y-4 border border-gray-100"
package/dist/admin.js CHANGED
@@ -861,7 +861,7 @@ var init_admin_config_context = __esm({
861
861
  var CMS_VERSION;
862
862
  var init_cms_version = __esm({
863
863
  "src/lib/cms-version.ts"() {
864
- CMS_VERSION = "1.0.65" ;
864
+ CMS_VERSION = "1.0.67" ;
865
865
  }
866
866
  });
867
867
  function useCatalogCategories(enabled = true) {
@@ -17475,7 +17475,7 @@ function PushTriggerBindings({ audience = "customer" }) {
17475
17475
  (async () => {
17476
17476
  try {
17477
17477
  setLoadingTpl(true);
17478
- const res = await fetch("/api/message-templates/email", {
17478
+ const res = await fetch("/api/message-templates/mobile", {
17479
17479
  cache: "no-store"
17480
17480
  });
17481
17481
  if (!res.ok) throw new Error("Failed to load message templates");
@@ -17579,7 +17579,7 @@ function PushTriggerBindings({ audience = "customer" }) {
17579
17579
  try {
17580
17580
  let tplId = activeBindingTplId;
17581
17581
  if (tplId) {
17582
- const res = await jsonFetch(`/api/message-templates/email/${tplId}`, {
17582
+ const res = await jsonFetch(`/api/message-templates/mobile/${tplId}`, {
17583
17583
  method: "PATCH",
17584
17584
  headers: {
17585
17585
  "Content-Type": "application/json"
@@ -17594,7 +17594,7 @@ function PushTriggerBindings({ audience = "customer" }) {
17594
17594
  setTemplates((prev) => prev.map((t) => t.id === res.item.id ? res.item : t));
17595
17595
  }
17596
17596
  } else {
17597
- const res = await jsonFetch("/api/message-templates/email", {
17597
+ const res = await jsonFetch("/api/message-templates/mobile", {
17598
17598
  method: "POST",
17599
17599
  headers: {
17600
17600
  "Content-Type": "application/json"
@@ -24564,7 +24564,10 @@ function OrderDetailPage({ orderId }) {
24564
24564
  const [cancelModal, setCancelModal] = useState(null);
24565
24565
  const [assignModalOpen, setAssignModalOpen] = useState(false);
24566
24566
  const [assigneesList, setAssigneesList] = useState([]);
24567
+ const [vendorsList, setVendorsList] = useState([]);
24568
+ const [isPlatformAdmin, setIsPlatformAdmin] = useState(false);
24567
24569
  const [loadingAssignees, setLoadingAssignees] = useState(false);
24570
+ const [selectedVendorId, setSelectedVendorId] = useState(null);
24568
24571
  const [selectedAssigneeId, setSelectedAssigneeId] = useState(null);
24569
24572
  const [savingAssignee, setSavingAssignee] = useState(false);
24570
24573
  const [completeModalOpen, setCompleteModalOpen] = useState(false);
@@ -24664,8 +24667,9 @@ function OrderDetailPage({ orderId }) {
24664
24667
  async function handleStartProcessing() {
24665
24668
  if (!order || startingProcessing) return;
24666
24669
  const currentAssigneeId = order.assignedUserId ?? order.assignedUser?.id ?? null;
24667
- if (!currentAssigneeId) {
24668
- toast.info("Please assign a teammate before starting order processing.");
24670
+ const currentVendorId = order.vendorId ?? order.vendor?.id ?? null;
24671
+ if (!currentAssigneeId && !currentVendorId) {
24672
+ toast.info("Please assign a vendor or teammate before starting order processing.");
24669
24673
  handleOpenAssignModal();
24670
24674
  return;
24671
24675
  }
@@ -24678,7 +24682,9 @@ function OrderDetailPage({ orderId }) {
24678
24682
  },
24679
24683
  body: JSON.stringify({
24680
24684
  status: "processing",
24681
- assignedUserId: currentAssigneeId
24685
+ ...currentAssigneeId ? {
24686
+ assignedUserId: currentAssigneeId
24687
+ } : {}
24682
24688
  })
24683
24689
  });
24684
24690
  const data = await res.json().catch(() => ({}));
@@ -24700,14 +24706,19 @@ function OrderDetailPage({ orderId }) {
24700
24706
  setAssignModalOpen(true);
24701
24707
  setLoadingAssignees(true);
24702
24708
  setSelectedAssigneeId(order?.assignedUserId ?? null);
24709
+ setSelectedVendorId(order?.vendorId ?? null);
24703
24710
  try {
24704
24711
  const res = await fetch(`/api/orders/${orderId}/eligible-assignees`);
24705
24712
  if (res.ok) {
24706
24713
  const data = await res.json();
24707
24714
  setAssigneesList(data.assignees ?? []);
24715
+ setVendorsList(data.vendors ?? []);
24716
+ setIsPlatformAdmin(Boolean(data.isPlatformAdmin));
24717
+ if (data.currentVendorId != null) setSelectedVendorId(data.currentVendorId);
24718
+ if (data.currentAssignedUserId != null) setSelectedAssigneeId(data.currentAssignedUserId);
24708
24719
  }
24709
24720
  } catch {
24710
- toast.error("Failed to load eligible team members");
24721
+ toast.error("Failed to load eligible assignees");
24711
24722
  } finally {
24712
24723
  setLoadingAssignees(false);
24713
24724
  }
@@ -24720,6 +24731,14 @@ function OrderDetailPage({ orderId }) {
24720
24731
  const bodyPayload = {
24721
24732
  assignedUserId: selectedAssigneeId
24722
24733
  };
24734
+ if (isPlatformAdmin) {
24735
+ const chosenAssignee = assigneesList.find((a) => a.id === selectedAssigneeId);
24736
+ if (chosenAssignee && chosenAssignee.vendorId === null) {
24737
+ bodyPayload.vendorId = 1;
24738
+ } else {
24739
+ bodyPayload.vendorId = chosenAssignee?.vendorId ?? (selectedVendorId || 1);
24740
+ }
24741
+ }
24723
24742
  const res = await fetch(`/api/orders/${orderId}`, {
24724
24743
  method: "PUT",
24725
24744
  headers: {
@@ -24729,15 +24748,15 @@ function OrderDetailPage({ orderId }) {
24729
24748
  });
24730
24749
  if (!res.ok) {
24731
24750
  const err = await res.json().catch(() => ({}));
24732
- toast.error(err.error ?? "Failed to update assignee");
24751
+ toast.error(err.error ?? "Failed to update assignment");
24733
24752
  return;
24734
24753
  }
24735
24754
  const updated = await fetch(`/api/orders/${orderId}`);
24736
24755
  if (updated.ok) setOrder(await updated.json());
24737
24756
  setAssignModalOpen(false);
24738
- toast.success(selectedAssigneeId ? "Order assigned successfully" : "Assignee removed");
24757
+ toast.success(selectedAssigneeId || selectedVendorId ? "Order assigned successfully" : "Assignment removed");
24739
24758
  } catch {
24740
- toast.error("Failed to update assignee");
24759
+ toast.error("Failed to update assignment");
24741
24760
  } finally {
24742
24761
  setSavingAssignee(false);
24743
24762
  }
@@ -25122,7 +25141,19 @@ function OrderDetailPage({ orderId }) {
25122
25141
  className: "min-w-0"
25123
25142
  }, /* @__PURE__ */ React.createElement("dt", {
25124
25143
  className: "text-gray-500"
25125
- }, "Assigned To"), /* @__PURE__ */ React.createElement("dd", {
25144
+ }, "Vendor"), /* @__PURE__ */ React.createElement("dd", {
25145
+ className: "font-medium text-gray-900 flex flex-wrap items-center gap-1.5 mt-0.5"
25146
+ }, order.vendor ? /* @__PURE__ */ React.createElement("span", {
25147
+ className: "inline-flex items-center gap-1 text-xs bg-purple-50 text-purple-800 font-medium px-2 py-0.5 rounded-full border border-purple-200"
25148
+ }, order.vendor.name || `Vendor #${order.vendor.id}`) : order.vendorId ? /* @__PURE__ */ React.createElement("span", {
25149
+ className: "inline-flex items-center gap-1 text-xs bg-purple-50 text-purple-800 font-medium px-2 py-0.5 rounded-full border border-purple-200"
25150
+ }, `Vendor #${order.vendorId}`) : /* @__PURE__ */ React.createElement("span", {
25151
+ className: "text-gray-400 text-xs italic"
25152
+ }, "Platform Default"))), /* @__PURE__ */ React.createElement("div", {
25153
+ className: "min-w-0"
25154
+ }, /* @__PURE__ */ React.createElement("dt", {
25155
+ className: "text-gray-500"
25156
+ }, "Assigned Teammate"), /* @__PURE__ */ React.createElement("dd", {
25126
25157
  className: "font-medium text-gray-900 flex flex-wrap items-center gap-1.5 mt-0.5"
25127
25158
  }, order.assignedUser ? /* @__PURE__ */ React.createElement("span", {
25128
25159
  className: "inline-flex items-center gap-1 text-xs bg-blue-50 text-blue-800 font-medium px-2 py-0.5 rounded-full border border-blue-200"
@@ -25391,7 +25422,7 @@ function OrderDetailPage({ orderId }) {
25391
25422
  className: "text-base font-semibold text-gray-900 flex items-center gap-2"
25392
25423
  }, /* @__PURE__ */ React.createElement(UserCheck, {
25393
25424
  className: "h-5 w-5 text-blue-600"
25394
- }), "Assign Order to Teammate"), /* @__PURE__ */ React.createElement("button", {
25425
+ }), isPlatformAdmin ? "Assign Order (Vendor & Team)" : "Assign Order to Teammate"), /* @__PURE__ */ React.createElement("button", {
25395
25426
  type: "button",
25396
25427
  onClick: /* @__PURE__ */ __name(() => setAssignModalOpen(false), "onClick"),
25397
25428
  className: "text-gray-400 hover:text-gray-600"
@@ -25399,14 +25430,42 @@ function OrderDetailPage({ orderId }) {
25399
25430
  className: "h-5 w-5"
25400
25431
  }))), /* @__PURE__ */ React.createElement("p", {
25401
25432
  className: "text-xs text-gray-500"
25402
- }, "Select a team member to handle this order. When assigned, order status automatically moves to Processing."), loadingAssignees ? /* @__PURE__ */ React.createElement("div", {
25433
+ }, isPlatformAdmin ? "Assign this order to a Vendor or directly to any Vendor's Team Member." : "Select a member of your team to handle this service, or keep it unassigned to your general store."), loadingAssignees ? /* @__PURE__ */ React.createElement("div", {
25403
25434
  className: "flex justify-center py-8"
25404
25435
  }, /* @__PURE__ */ React.createElement(Loader2, {
25405
25436
  className: "h-6 w-6 animate-spin text-blue-600"
25406
25437
  })) : /* @__PURE__ */ React.createElement("div", {
25407
- className: "space-y-2 max-h-64 overflow-y-auto pr-1"
25438
+ className: "space-y-4"
25439
+ }, isPlatformAdmin && vendorsList.length > 0 && /* @__PURE__ */ React.createElement("div", {
25440
+ className: "space-y-1.5"
25441
+ }, /* @__PURE__ */ React.createElement("label", {
25442
+ className: "block text-xs font-semibold text-gray-700"
25443
+ }, "Assigned Vendor"), /* @__PURE__ */ React.createElement("select", {
25444
+ value: selectedVendorId ?? "",
25445
+ onChange: /* @__PURE__ */ __name((e) => {
25446
+ const val = e.target.value ? Number(e.target.value) : null;
25447
+ setSelectedVendorId(val);
25448
+ if (val && selectedAssigneeId) {
25449
+ const assignee = assigneesList.find((a) => a.id === selectedAssigneeId);
25450
+ if (assignee && assignee.vendorId !== val) {
25451
+ setSelectedAssigneeId(null);
25452
+ }
25453
+ }
25454
+ }, "onChange"),
25455
+ className: "w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
25456
+ }, /* @__PURE__ */ React.createElement("option", {
25457
+ value: ""
25458
+ }, "All Vendors / Any Vendor"), vendorsList.map((v) => /* @__PURE__ */ React.createElement("option", {
25459
+ key: v.id,
25460
+ value: v.id
25461
+ }, v.name)))), /* @__PURE__ */ React.createElement("div", {
25462
+ className: "space-y-1.5"
25408
25463
  }, /* @__PURE__ */ React.createElement("label", {
25409
- className: `flex items-center justify-between p-3 rounded-lg border cursor-pointer transition ${selectedAssigneeId === null ? "border-blue-600 bg-blue-50/50" : "border-gray-200 hover:bg-gray-50"}`
25464
+ className: "block text-xs font-semibold text-gray-700"
25465
+ }, isPlatformAdmin ? "Assigned Team Member" : "Select Team Member"), /* @__PURE__ */ React.createElement("div", {
25466
+ className: "space-y-2 max-h-56 overflow-y-auto pr-1"
25467
+ }, /* @__PURE__ */ React.createElement("label", {
25468
+ className: `flex items-center justify-between p-2.5 rounded-lg border cursor-pointer transition ${selectedAssigneeId === null ? "border-blue-600 bg-blue-50/50" : "border-gray-200 hover:bg-gray-50"}`
25410
25469
  }, /* @__PURE__ */ React.createElement("div", {
25411
25470
  className: "flex items-center gap-3"
25412
25471
  }, /* @__PURE__ */ React.createElement("input", {
@@ -25417,26 +25476,40 @@ function OrderDetailPage({ orderId }) {
25417
25476
  className: "text-blue-600"
25418
25477
  }), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("p", {
25419
25478
  className: "text-sm font-medium text-gray-800"
25420
- }, "Unassigned"), /* @__PURE__ */ React.createElement("p", {
25479
+ }, "Unassigned to specific person"), /* @__PURE__ */ React.createElement("p", {
25421
25480
  className: "text-xs text-gray-400"
25422
- }, "No specific team member")))), assigneesList.map((a) => /* @__PURE__ */ React.createElement("label", {
25481
+ }, selectedVendorId ? "Vendor general queue" : "General queue")))), assigneesList.filter((a) => {
25482
+ if (!isPlatformAdmin) return true;
25483
+ if (selectedVendorId && selectedVendorId !== 1) {
25484
+ return a.vendorId === selectedVendorId;
25485
+ }
25486
+ if (selectedVendorId === 1) {
25487
+ return a.vendorId === 1 || a.vendorId === null;
25488
+ }
25489
+ return true;
25490
+ }).map((a) => /* @__PURE__ */ React.createElement("label", {
25423
25491
  key: a.id,
25424
- className: `flex items-center justify-between p-3 rounded-lg border cursor-pointer transition ${selectedAssigneeId === a.id ? "border-blue-600 bg-blue-50/50" : "border-gray-200 hover:bg-gray-50"}`
25492
+ className: `flex items-center justify-between p-2.5 rounded-lg border cursor-pointer transition ${selectedAssigneeId === a.id ? "border-blue-600 bg-blue-50/50" : "border-gray-200 hover:bg-gray-50"}`
25425
25493
  }, /* @__PURE__ */ React.createElement("div", {
25426
25494
  className: "flex items-center gap-3"
25427
25495
  }, /* @__PURE__ */ React.createElement("input", {
25428
25496
  type: "radio",
25429
25497
  name: "assignee",
25430
25498
  checked: selectedAssigneeId === a.id,
25431
- onChange: /* @__PURE__ */ __name(() => setSelectedAssigneeId(a.id), "onChange"),
25499
+ onChange: /* @__PURE__ */ __name(() => {
25500
+ setSelectedAssigneeId(a.id);
25501
+ if (isPlatformAdmin) {
25502
+ setSelectedVendorId(a.vendorId || 1);
25503
+ }
25504
+ }, "onChange"),
25432
25505
  className: "text-blue-600"
25433
25506
  }), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("p", {
25434
25507
  className: "text-sm font-medium text-gray-900"
25435
25508
  }, a.name), /* @__PURE__ */ React.createElement("p", {
25436
25509
  className: "text-xs text-gray-500"
25437
- }, a.email))), /* @__PURE__ */ React.createElement("span", {
25438
- className: "text-[11px] font-medium text-gray-500 bg-gray-100 px-2 py-0.5 rounded"
25439
- }, a.role)))), /* @__PURE__ */ React.createElement("div", {
25510
+ }, a.email, isPlatformAdmin && a.vendorName ? ` \u2022 ${a.vendorName}` : ""))), /* @__PURE__ */ React.createElement("span", {
25511
+ className: "text-[11px] font-medium text-gray-600 bg-gray-100 px-2 py-0.5 rounded"
25512
+ }, a.role)))))), /* @__PURE__ */ React.createElement("div", {
25440
25513
  className: "flex justify-end gap-2 pt-2 border-t border-gray-100"
25441
25514
  }, /* @__PURE__ */ React.createElement(Button, {
25442
25515
  variant: "outline",
@@ -25446,7 +25519,7 @@ function OrderDetailPage({ orderId }) {
25446
25519
  onClick: handleSaveAssignee,
25447
25520
  disabled: savingAssignee,
25448
25521
  className: "bg-blue-600 hover:bg-blue-700 text-white"
25449
- }, savingAssignee ? "Saving..." : "Save Assignee")))), completeModalOpen && /* @__PURE__ */ React.createElement("div", {
25522
+ }, savingAssignee ? "Saving..." : "Save Assignment")))), completeModalOpen && /* @__PURE__ */ React.createElement("div", {
25450
25523
  className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm p-4 animate-in fade-in duration-150"
25451
25524
  }, /* @__PURE__ */ React.createElement("div", {
25452
25525
  className: "bg-white rounded-xl shadow-2xl w-full max-w-md p-6 space-y-4 border border-gray-100"