@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.
- package/dist/admin.cjs +97 -24
- package/dist/admin.js +97 -24
- package/dist/api.cjs +38 -38
- package/dist/api.js +5 -5
- package/dist/auth.cjs +51 -51
- package/dist/auth.js +3 -3
- package/dist/{chunk-6DBDJ4VD.js → chunk-2ISSXYBZ.js} +2 -2
- package/dist/{chunk-NIRYYJIJ.cjs → chunk-5MZFQRDW.cjs} +73 -55
- package/dist/{chunk-MVHDC3XF.js → chunk-5NOZSG6J.js} +22 -11
- package/dist/{chunk-YHEITFHR.cjs → chunk-BVLN75LP.cjs} +540 -143
- package/dist/{chunk-YEAXE4U2.js → chunk-FLUF2GZH.js} +5 -11
- package/dist/{chunk-SANKKGB3.js → chunk-GLLCLRCQ.js} +464 -67
- package/dist/{chunk-ACBN6UWZ.js → chunk-NV5IRHI3.js} +26 -8
- package/dist/{chunk-J7FMZK66.cjs → chunk-O4AFPDQ4.cjs} +22 -11
- package/dist/{chunk-4U6DATGZ.cjs → chunk-OV5TRZET.cjs} +7 -7
- package/dist/{chunk-BXAKL2TF.cjs → chunk-PA6YDMFZ.cjs} +5 -11
- package/dist/{chunk-RDEVZMO5.js → chunk-RCE5SJBA.js} +2 -2
- package/dist/{chunk-KM2I6AFP.cjs → chunk-SS3K7OIM.cjs} +9 -9
- package/dist/{chunk-V6EYAC7X.cjs → chunk-WMMZZRDJ.cjs} +15 -15
- package/dist/{chunk-NR44CK5E.js → chunk-ZY64VJMS.js} +1 -1
- package/dist/{emit-order-notification-trigger-UCKJHDQK.js → emit-order-notification-trigger-EJJZ6XTS.js} +2 -2
- package/dist/{emit-order-notification-trigger-DR74TQXN.cjs → emit-order-notification-trigger-ZD5YN3JM.cjs} +4 -4
- package/dist/index.cjs +284 -280
- package/dist/index.d.cts +14 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +10 -10
- package/dist/migrations/1783300000000-CreateOrderAssigneesTable.ts +43 -0
- package/dist/{order-assignees-handlers-NPKD64P6.cjs → order-assignees-handlers-KF7RMTV5.cjs} +77 -8
- package/dist/{order-assignees-handlers-LKMAGLG6.js → order-assignees-handlers-L3RVKUBS.js} +77 -8
- package/dist/{order-completion-otp-handlers-RW5RSXH3.cjs → order-completion-otp-handlers-DZAXK4GQ.cjs} +70 -16
- package/dist/{order-completion-otp-handlers-CH22ZRAI.js → order-completion-otp-handlers-HFGCPC4O.js} +69 -15
- package/dist/{order-notification-dispatcher-3TXUAJ7L.js → order-notification-dispatcher-ECPFI7CD.js} +2 -2
- package/dist/{order-notification-dispatcher-Y7NZAALH.cjs → order-notification-dispatcher-LL7ETKLU.cjs} +7 -7
- package/dist/{rbac-debug-db-5R6XFPSV.js → rbac-debug-db-DFZWZ6GV.js} +1 -1
- package/dist/{rbac-debug-db-JKK2MCWF.cjs → rbac-debug-db-KWV7D5PQ.cjs} +2 -2
- 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.
|
|
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/
|
|
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/
|
|
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/
|
|
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
|
-
|
|
24702
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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" : "
|
|
24791
|
+
sonner.toast.success(selectedAssigneeId || selectedVendorId ? "Order assigned successfully" : "Assignment removed");
|
|
24773
24792
|
} catch {
|
|
24774
|
-
sonner.toast.error("Failed to update
|
|
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
|
-
}, "
|
|
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
|
|
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-
|
|
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:
|
|
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
|
-
}, "
|
|
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-
|
|
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(() =>
|
|
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-
|
|
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
|
|
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.
|
|
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/
|
|
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/
|
|
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/
|
|
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
|
-
|
|
24668
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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" : "
|
|
24757
|
+
toast.success(selectedAssigneeId || selectedVendorId ? "Order assigned successfully" : "Assignment removed");
|
|
24739
24758
|
} catch {
|
|
24740
|
-
toast.error("Failed to update
|
|
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
|
-
}, "
|
|
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
|
|
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-
|
|
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:
|
|
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
|
-
}, "
|
|
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-
|
|
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(() =>
|
|
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-
|
|
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
|
|
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"
|