@infuro/cms-core 1.0.33 → 1.0.34
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/README.md +9 -6
- package/dist/admin.cjs +980 -801
- package/dist/admin.cjs.map +1 -1
- package/dist/admin.d.cts +7 -2
- package/dist/admin.d.ts +7 -2
- package/dist/admin.js +1021 -842
- package/dist/admin.js.map +1 -1
- package/dist/api.cjs +1858 -848
- package/dist/api.cjs.map +1 -1
- package/dist/api.d.cts +1 -1
- package/dist/api.d.ts +1 -1
- package/dist/api.js +1824 -815
- package/dist/api.js.map +1 -1
- package/dist/auth.cjs +94 -11
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +17 -1
- package/dist/auth.d.ts +17 -1
- package/dist/auth.js +89 -11
- package/dist/auth.js.map +1 -1
- package/dist/cli.cjs +39 -0
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +39 -0
- package/dist/cli.js.map +1 -1
- package/dist/{index-rZTnpK7y.d.cts → index-Bf5GO8fu.d.cts} +3 -2
- package/dist/{index-DWd5Gjc4.d.ts → index-DOiJuMQA.d.ts} +3 -2
- package/dist/index.cjs +2078 -841
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +83 -8
- package/dist/index.d.ts +83 -8
- package/dist/index.js +2013 -786
- package/dist/index.js.map +1 -1
- package/dist/migrations/1778660000004-CreateCustomerAndCustomerContacts.ts +99 -0
- package/dist/migrations/1778660000005-AddCustomerIdToVendorCustomers.ts +39 -0
- package/dist/migrations/1778660000006-UpdateVendorCustomersContactNullable.ts +36 -0
- package/dist/migrations/1778660000007-VendorOwnerCustomerContactsPermission.ts +39 -0
- package/dist/migrations/1779300000000-VendorOwnerContactsPermission.ts +39 -0
- package/dist/migrations/1779400000000-AddCustomerContactIdToOrders.ts +33 -0
- package/package.json +4 -3
package/dist/admin.js
CHANGED
|
@@ -99,6 +99,30 @@ var init_permission_entities = __esm({
|
|
|
99
99
|
}
|
|
100
100
|
});
|
|
101
101
|
|
|
102
|
+
// src/auth/role-helpers.ts
|
|
103
|
+
function isSuperAdmin(user) {
|
|
104
|
+
if (!user) return false;
|
|
105
|
+
if (user.groupId === SUPER_ADMIN_GROUP_ID) return true;
|
|
106
|
+
if (user.isRBACAdmin === true) return true;
|
|
107
|
+
return isSuperAdminGroupName(user.groupName);
|
|
108
|
+
}
|
|
109
|
+
function isVendorAdmin(user) {
|
|
110
|
+
if (!user?.email || isSuperAdmin(user)) return false;
|
|
111
|
+
if (user.groupId === VENDOR_ADMIN_GROUP_ID) return true;
|
|
112
|
+
if ((user.vendorIds?.length ?? 0) > 0) return true;
|
|
113
|
+
return isVendorGroupName(user.groupName);
|
|
114
|
+
}
|
|
115
|
+
var SUPER_ADMIN_GROUP_ID, VENDOR_ADMIN_GROUP_ID;
|
|
116
|
+
var init_role_helpers = __esm({
|
|
117
|
+
"src/auth/role-helpers.ts"() {
|
|
118
|
+
"use strict";
|
|
119
|
+
init_permission_entities();
|
|
120
|
+
init_vendor_scope();
|
|
121
|
+
SUPER_ADMIN_GROUP_ID = 1;
|
|
122
|
+
VENDOR_ADMIN_GROUP_ID = 5;
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
102
126
|
// src/auth/vendor-scope.ts
|
|
103
127
|
function isVendorGroupName(name) {
|
|
104
128
|
if (!name?.trim()) return false;
|
|
@@ -107,12 +131,12 @@ function isVendorGroupName(name) {
|
|
|
107
131
|
}
|
|
108
132
|
function isPlatformAdministrator(user) {
|
|
109
133
|
if (!user?.email) return false;
|
|
110
|
-
return
|
|
134
|
+
return isSuperAdmin(user);
|
|
111
135
|
}
|
|
112
136
|
function isVendorPortalUser(user) {
|
|
113
137
|
if (user?.isVendorPortal === true) return true;
|
|
114
138
|
if (!user?.email || isPlatformAdministrator(user)) return false;
|
|
115
|
-
if ((user
|
|
139
|
+
if (isVendorAdmin(user)) return true;
|
|
116
140
|
return isVendorGroupName(user.groupName);
|
|
117
141
|
}
|
|
118
142
|
function isVendorOwner(user) {
|
|
@@ -136,7 +160,7 @@ var VENDOR_SCOPED_STORE_ENTITIES, VENDOR_STORE_RBAC_ENTITIES, VENDOR_OWNER_GROUP
|
|
|
136
160
|
var init_vendor_scope = __esm({
|
|
137
161
|
"src/auth/vendor-scope.ts"() {
|
|
138
162
|
"use strict";
|
|
139
|
-
|
|
163
|
+
init_role_helpers();
|
|
140
164
|
VENDOR_SCOPED_STORE_ENTITIES = /* @__PURE__ */ new Set([
|
|
141
165
|
"products",
|
|
142
166
|
"collections",
|
|
@@ -401,7 +425,7 @@ var init_admin_list_return_url = __esm({
|
|
|
401
425
|
import Link8 from "next/link";
|
|
402
426
|
import { useRouter as useRouter7 } from "next/navigation";
|
|
403
427
|
import { ArrowLeft as ArrowLeft3, X as X14 } from "lucide-react";
|
|
404
|
-
import { Fragment as
|
|
428
|
+
import { Fragment as Fragment10, jsx as jsx49, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
405
429
|
function DetailPageHeader({
|
|
406
430
|
title,
|
|
407
431
|
subtitle,
|
|
@@ -436,7 +460,7 @@ function DetailPageHeader({
|
|
|
436
460
|
] })
|
|
437
461
|
] }),
|
|
438
462
|
/* @__PURE__ */ jsxs39("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
439
|
-
menuItems.length > 0 && /* @__PURE__ */ jsxs39(
|
|
463
|
+
menuItems.length > 0 && /* @__PURE__ */ jsxs39(Fragment10, { children: [
|
|
440
464
|
/* @__PURE__ */ jsx49("div", { className: "flex items-center gap-2 md:hidden", children: menuItems.map((item, i) => {
|
|
441
465
|
const Icon2 = item.icon;
|
|
442
466
|
return /* @__PURE__ */ jsxs39(
|
|
@@ -774,11 +798,11 @@ __export(ContactDetailPage_exports, {
|
|
|
774
798
|
});
|
|
775
799
|
import { useEffect as useEffect46, useState as useState49 } from "react";
|
|
776
800
|
import Link15 from "next/link";
|
|
777
|
-
import { useRouter as
|
|
801
|
+
import { useRouter as useRouter21, useSearchParams as useSearchParams19 } from "next/navigation";
|
|
778
802
|
import { Plus as Plus15, Trash2 as Trash215, X as X22 } from "lucide-react";
|
|
779
803
|
import { toast as toast11 } from "sonner";
|
|
780
804
|
import { Country as Country3, State as State3 } from "country-state-city";
|
|
781
|
-
import { Fragment as
|
|
805
|
+
import { Fragment as Fragment24, jsx as jsx82, jsxs as jsxs69 } from "react/jsx-runtime";
|
|
782
806
|
function formatMoney5(amount, currency = "INR") {
|
|
783
807
|
return new Intl.NumberFormat("en-IN", {
|
|
784
808
|
style: "currency",
|
|
@@ -802,7 +826,7 @@ function RequiredMark() {
|
|
|
802
826
|
] });
|
|
803
827
|
}
|
|
804
828
|
function ContactDetailPage({ contactId }) {
|
|
805
|
-
const router =
|
|
829
|
+
const router = useRouter21();
|
|
806
830
|
const searchParams = useSearchParams19();
|
|
807
831
|
const listReturnUrl = safeAdminListReturnUrl(searchParams.get("from")) ?? "/admin/contacts";
|
|
808
832
|
const [contact, setContact] = useState49(null);
|
|
@@ -943,7 +967,7 @@ function ContactDetailPage({ contactId }) {
|
|
|
943
967
|
/* @__PURE__ */ jsx82(
|
|
944
968
|
DetailPageLayout,
|
|
945
969
|
{
|
|
946
|
-
main: /* @__PURE__ */ jsxs69(
|
|
970
|
+
main: /* @__PURE__ */ jsxs69(Fragment24, { children: [
|
|
947
971
|
/* @__PURE__ */ jsxs69("section", { children: [
|
|
948
972
|
/* @__PURE__ */ jsx82("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Contact details" }),
|
|
949
973
|
/* @__PURE__ */ jsx82("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50", children: /* @__PURE__ */ jsxs69("dl", { className: "min-w-0 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 text-sm", children: [
|
|
@@ -959,7 +983,7 @@ function ContactDetailPage({ contactId }) {
|
|
|
959
983
|
/* @__PURE__ */ jsx82("dt", { className: "text-gray-500", children: "Phone" }),
|
|
960
984
|
/* @__PURE__ */ jsx82("dd", { className: "font-medium text-gray-900 break-words", children: contact.phone ?? "\u2014" })
|
|
961
985
|
] }),
|
|
962
|
-
(contact.type ?? contact.company ?? contact.taxId) && /* @__PURE__ */ jsxs69(
|
|
986
|
+
(contact.type ?? contact.company ?? contact.taxId) && /* @__PURE__ */ jsxs69(Fragment24, { children: [
|
|
963
987
|
contact.type && /* @__PURE__ */ jsxs69("div", { className: "min-w-0", children: [
|
|
964
988
|
/* @__PURE__ */ jsx82("dt", { className: "text-gray-500", children: "Type" }),
|
|
965
989
|
/* @__PURE__ */ jsx82("dd", { className: "font-medium text-gray-900 break-words", children: formatContactType(contact.type) })
|
|
@@ -1030,7 +1054,7 @@ function ContactDetailPage({ contactId }) {
|
|
|
1030
1054
|
] }) })
|
|
1031
1055
|
] })
|
|
1032
1056
|
] }),
|
|
1033
|
-
sidebar: /* @__PURE__ */ jsxs69(
|
|
1057
|
+
sidebar: /* @__PURE__ */ jsxs69(Fragment24, { children: [
|
|
1034
1058
|
/* @__PURE__ */ jsxs69("section", { children: [
|
|
1035
1059
|
/* @__PURE__ */ jsx82("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Summary" }),
|
|
1036
1060
|
/* @__PURE__ */ jsx82("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50", children: /* @__PURE__ */ jsxs69("dl", { className: "min-w-0 grid grid-cols-1 sm:grid-cols-3 gap-3 text-sm", children: [
|
|
@@ -1542,7 +1566,7 @@ var defaultValue = {
|
|
|
1542
1566
|
var AdminConfigContext = createContext(defaultValue);
|
|
1543
1567
|
|
|
1544
1568
|
// src/lib/cms-version.ts
|
|
1545
|
-
var CMS_VERSION = true ? "1.0.
|
|
1569
|
+
var CMS_VERSION = true ? "1.0.34" : "0.0.0";
|
|
1546
1570
|
|
|
1547
1571
|
// src/components/Admin/Sidebar.tsx
|
|
1548
1572
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
@@ -1750,7 +1774,7 @@ function AdminSidebar({ variant = "sidebar" }) {
|
|
|
1750
1774
|
className: `${linkCls} ${isActive("/admin/vendor-onboard") ? linkActive : linkInactive}`,
|
|
1751
1775
|
children: [
|
|
1752
1776
|
/* @__PURE__ */ jsx4(Store, { className: `h-4 w-4 mr-2 ${isActive("/admin/vendor-onboard") ? iconActive : iconInactive}` }),
|
|
1753
|
-
"
|
|
1777
|
+
"Vendors"
|
|
1754
1778
|
]
|
|
1755
1779
|
}
|
|
1756
1780
|
) }),
|
|
@@ -2703,7 +2727,7 @@ function RelationAutocomplete({
|
|
|
2703
2727
|
|
|
2704
2728
|
// src/components/Admin/CreateEditForm.tsx
|
|
2705
2729
|
import { toast } from "sonner";
|
|
2706
|
-
import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2730
|
+
import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2707
2731
|
function todayLocalDateString() {
|
|
2708
2732
|
const d = /* @__PURE__ */ new Date();
|
|
2709
2733
|
const y = d.getFullYear();
|
|
@@ -2745,7 +2769,8 @@ function CreateEditForm({
|
|
|
2745
2769
|
apiEndpoint,
|
|
2746
2770
|
columns,
|
|
2747
2771
|
existingData,
|
|
2748
|
-
duplicateSeed
|
|
2772
|
+
duplicateSeed,
|
|
2773
|
+
resource
|
|
2749
2774
|
}) {
|
|
2750
2775
|
const isMobile = useIsMobile();
|
|
2751
2776
|
const { currency } = useContext3(AdminConfigContext);
|
|
@@ -2753,6 +2778,9 @@ function CreateEditForm({
|
|
|
2753
2778
|
currency: currency || "INR"
|
|
2754
2779
|
});
|
|
2755
2780
|
const [errors, setErrors] = useState6({});
|
|
2781
|
+
const [password, setPassword] = useState6("");
|
|
2782
|
+
const [confirmPassword, setConfirmPassword] = useState6("");
|
|
2783
|
+
const isCustomerCreate = resource === "vendor_customers" && !existingData;
|
|
2756
2784
|
useEffect4(() => {
|
|
2757
2785
|
fetch("/api/settings/store").then((res) => res.json()).then((data) => {
|
|
2758
2786
|
setFormData((prev) => ({
|
|
@@ -2782,14 +2810,10 @@ function CreateEditForm({
|
|
|
2782
2810
|
};
|
|
2783
2811
|
}).filter(Boolean)
|
|
2784
2812
|
);
|
|
2785
|
-
}).catch(
|
|
2786
|
-
(err) => console.error("Failed to load customers", err)
|
|
2787
|
-
);
|
|
2813
|
+
}).catch((err) => console.error("Failed to load customers", err));
|
|
2788
2814
|
}, [columns]);
|
|
2789
2815
|
const handleCustomerSelect = (customerId) => {
|
|
2790
|
-
const customer = customers.find(
|
|
2791
|
-
(c) => String(c.id) === customerId
|
|
2792
|
-
);
|
|
2816
|
+
const customer = customers.find((c) => String(c.id) === customerId);
|
|
2793
2817
|
if (!customer) return;
|
|
2794
2818
|
setFormData((prev) => ({
|
|
2795
2819
|
...prev,
|
|
@@ -2803,23 +2827,14 @@ function CreateEditForm({
|
|
|
2803
2827
|
const [totalLoading, setTotalLoading] = useState6(false);
|
|
2804
2828
|
useEffect4(() => {
|
|
2805
2829
|
return () => {
|
|
2806
|
-
if (debounceRef.current)
|
|
2807
|
-
clearTimeout(debounceRef.current);
|
|
2808
|
-
}
|
|
2830
|
+
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
2809
2831
|
};
|
|
2810
2832
|
}, []);
|
|
2811
2833
|
const recalculateTotal = (itemsSummaryValue) => {
|
|
2812
|
-
if (debounceRef.current)
|
|
2813
|
-
clearTimeout(debounceRef.current);
|
|
2814
|
-
}
|
|
2834
|
+
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
2815
2835
|
const names = itemsSummaryValue.split(",").map((s) => s.trim()).filter(Boolean);
|
|
2816
2836
|
if (names.length === 0) {
|
|
2817
|
-
setFormData((prev) => ({
|
|
2818
|
-
...prev,
|
|
2819
|
-
subtotal: "",
|
|
2820
|
-
tax: "",
|
|
2821
|
-
total: ""
|
|
2822
|
-
}));
|
|
2837
|
+
setFormData((prev) => ({ ...prev, subtotal: "", tax: "", total: "" }));
|
|
2823
2838
|
return;
|
|
2824
2839
|
}
|
|
2825
2840
|
debounceRef.current = setTimeout(async () => {
|
|
@@ -2827,12 +2842,8 @@ function CreateEditForm({
|
|
|
2827
2842
|
try {
|
|
2828
2843
|
const res = await fetch("/api/orders/calculate", {
|
|
2829
2844
|
method: "POST",
|
|
2830
|
-
headers: {
|
|
2831
|
-
|
|
2832
|
-
},
|
|
2833
|
-
body: JSON.stringify({
|
|
2834
|
-
itemsSummary: itemsSummaryValue
|
|
2835
|
-
})
|
|
2845
|
+
headers: { "Content-Type": "application/json" },
|
|
2846
|
+
body: JSON.stringify({ itemsSummary: itemsSummaryValue })
|
|
2836
2847
|
});
|
|
2837
2848
|
if (!res.ok) return;
|
|
2838
2849
|
const data = await res.json();
|
|
@@ -2857,13 +2868,9 @@ function CreateEditForm({
|
|
|
2857
2868
|
const path = col.field || col.key;
|
|
2858
2869
|
if (!path) return;
|
|
2859
2870
|
const v = getNestedValue(ex, path);
|
|
2860
|
-
if (v !== void 0)
|
|
2861
|
-
merged[path] = v === null ? "" : v;
|
|
2862
|
-
}
|
|
2871
|
+
if (v !== void 0) merged[path] = v === null ? "" : v;
|
|
2863
2872
|
});
|
|
2864
|
-
columns.filter(
|
|
2865
|
-
(col) => !col.hideInForm && isDateFormColumn(col.type)
|
|
2866
|
-
).forEach((col) => {
|
|
2873
|
+
columns.filter((col) => !col.hideInForm && isDateFormColumn(col.type)).forEach((col) => {
|
|
2867
2874
|
const path = col.field || col.key;
|
|
2868
2875
|
if (!path) return;
|
|
2869
2876
|
const raw = merged[path];
|
|
@@ -2879,9 +2886,7 @@ function CreateEditForm({
|
|
|
2879
2886
|
).forEach((col) => {
|
|
2880
2887
|
const path = col.field || col.key;
|
|
2881
2888
|
if (!path) return;
|
|
2882
|
-
const allowed = new Set(
|
|
2883
|
-
col.options.map((o) => String(o.value))
|
|
2884
|
-
);
|
|
2889
|
+
const allowed = new Set(col.options.map((o) => String(o.value)));
|
|
2885
2890
|
const raw = merged[path];
|
|
2886
2891
|
if (raw != null && raw !== "" && !allowed.has(String(raw))) {
|
|
2887
2892
|
merged[path] = "";
|
|
@@ -2889,6 +2894,8 @@ function CreateEditForm({
|
|
|
2889
2894
|
});
|
|
2890
2895
|
setFormData(merged);
|
|
2891
2896
|
} else {
|
|
2897
|
+
setPassword("");
|
|
2898
|
+
setConfirmPassword("");
|
|
2892
2899
|
setFormData(
|
|
2893
2900
|
columns.filter((col) => !col.hideInForm).reduce((acc, col) => {
|
|
2894
2901
|
const path = col.field || col.key;
|
|
@@ -2897,29 +2904,18 @@ function CreateEditForm({
|
|
|
2897
2904
|
if (isDateFormColumn(col.type) && (initial === "" || initial == null)) {
|
|
2898
2905
|
initial = todayLocalDateString();
|
|
2899
2906
|
}
|
|
2900
|
-
return {
|
|
2901
|
-
...acc,
|
|
2902
|
-
[path]: initial
|
|
2903
|
-
};
|
|
2907
|
+
return { ...acc, [path]: initial };
|
|
2904
2908
|
}, {})
|
|
2905
2909
|
);
|
|
2906
2910
|
}
|
|
2907
2911
|
}, [existingData, duplicateSeed, columns]);
|
|
2908
2912
|
const handleChange = (e, field) => {
|
|
2909
2913
|
const value = e.target.value;
|
|
2910
|
-
setFormData((prev) => ({
|
|
2911
|
-
|
|
2912
|
-
[field]: value
|
|
2913
|
-
}));
|
|
2914
|
-
if (field === "itemsSummary") {
|
|
2915
|
-
recalculateTotal(value);
|
|
2916
|
-
}
|
|
2914
|
+
setFormData((prev) => ({ ...prev, [field]: value }));
|
|
2915
|
+
if (field === "itemsSummary") recalculateTotal(value);
|
|
2917
2916
|
};
|
|
2918
2917
|
const handleFileUpload = (field, url) => {
|
|
2919
|
-
setFormData({
|
|
2920
|
-
...formData,
|
|
2921
|
-
[field]: url
|
|
2922
|
-
});
|
|
2918
|
+
setFormData({ ...formData, [field]: url });
|
|
2923
2919
|
};
|
|
2924
2920
|
const isValidPhoneFieldValue = (value) => {
|
|
2925
2921
|
const v = String(value ?? "").trim();
|
|
@@ -2943,6 +2939,18 @@ function CreateEditForm({
|
|
|
2943
2939
|
}
|
|
2944
2940
|
}
|
|
2945
2941
|
});
|
|
2942
|
+
if (isCustomerCreate) {
|
|
2943
|
+
if (!password) {
|
|
2944
|
+
newErrors["_password"] = "Password is required";
|
|
2945
|
+
} else if (password.length < 6) {
|
|
2946
|
+
newErrors["_password"] = "Password must be at least 6 characters";
|
|
2947
|
+
}
|
|
2948
|
+
if (!confirmPassword) {
|
|
2949
|
+
newErrors["_confirmPassword"] = "Please confirm your password";
|
|
2950
|
+
} else if (password && confirmPassword !== password) {
|
|
2951
|
+
newErrors["_confirmPassword"] = "Passwords do not match";
|
|
2952
|
+
}
|
|
2953
|
+
}
|
|
2946
2954
|
setErrors(newErrors);
|
|
2947
2955
|
return Object.keys(newErrors).length === 0;
|
|
2948
2956
|
};
|
|
@@ -2960,16 +2968,19 @@ function CreateEditForm({
|
|
|
2960
2968
|
if (!existingData) {
|
|
2961
2969
|
delete payload.id;
|
|
2962
2970
|
}
|
|
2971
|
+
if (isCustomerCreate) {
|
|
2972
|
+
payload._password = password;
|
|
2973
|
+
}
|
|
2963
2974
|
try {
|
|
2964
2975
|
const res = await fetch(url, {
|
|
2965
2976
|
method,
|
|
2966
|
-
headers: {
|
|
2967
|
-
"Content-Type": "application/json"
|
|
2968
|
-
},
|
|
2977
|
+
headers: { "Content-Type": "application/json" },
|
|
2969
2978
|
body: JSON.stringify(payload)
|
|
2970
2979
|
});
|
|
2971
2980
|
if (!res.ok) {
|
|
2972
|
-
|
|
2981
|
+
const errData = await res.json().catch(() => ({}));
|
|
2982
|
+
toast.error(errData.error ?? "Failed to save data");
|
|
2983
|
+
return;
|
|
2973
2984
|
}
|
|
2974
2985
|
const result = await res.json();
|
|
2975
2986
|
if (result.inviteLink) {
|
|
@@ -2983,13 +2994,12 @@ Note: ${result.note}`
|
|
|
2983
2994
|
onClose();
|
|
2984
2995
|
} catch (error) {
|
|
2985
2996
|
console.error("Error saving data:", error);
|
|
2997
|
+
toast.error("An unexpected error occurred. Please try again.");
|
|
2986
2998
|
}
|
|
2987
2999
|
};
|
|
2988
3000
|
const visibleColumns = columns.filter((col) => {
|
|
2989
3001
|
if (col.hideInForm) return false;
|
|
2990
|
-
if (!existingData && col.hideInCreate)
|
|
2991
|
-
return false;
|
|
2992
|
-
}
|
|
3002
|
+
if (!existingData && col.hideInCreate) return false;
|
|
2993
3003
|
return true;
|
|
2994
3004
|
});
|
|
2995
3005
|
const isFieldDisabled = (path) => {
|
|
@@ -3019,228 +3029,193 @@ Note: ${result.note}`
|
|
|
3019
3029
|
}
|
|
3020
3030
|
)
|
|
3021
3031
|
] }),
|
|
3022
|
-
/* @__PURE__ */ jsxs11(
|
|
3023
|
-
"
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
) : null;
|
|
3037
|
-
const rawStr = formData[path] != null && formData[path] !== "" ? String(formData[path]) : "";
|
|
3038
|
-
const selectValue = optionSet ? rawStr !== "" && optionSet.has(rawStr) ? rawStr : col.defaultValue : void 0;
|
|
3039
|
-
return /* @__PURE__ */ jsxs11(React12.Fragment, { children: [
|
|
3040
|
-
/* @__PURE__ */ jsxs11("div", { children: [
|
|
3041
|
-
/* @__PURE__ */ jsxs11(Label3, { className: "block text-sm font-medium mb-1", children: [
|
|
3042
|
-
col.displayName,
|
|
3043
|
-
["subtotal", "tax", "total"].includes(path) && totalLoading && /* @__PURE__ */ jsx17("span", { className: "ml-2 text-xs text-gray-400 font-normal", children: "Calculating\u2026" })
|
|
3044
|
-
] }),
|
|
3045
|
-
col.type === "customerDropdown" ? /* @__PURE__ */ jsxs11(
|
|
3046
|
-
Select,
|
|
3047
|
-
{
|
|
3048
|
-
value: (() => {
|
|
3049
|
-
const match = customers.find(
|
|
3050
|
-
(c) => String(c.id) === String(
|
|
3051
|
-
formData["contactId"]
|
|
3052
|
-
) || c.name === formData["contact.name"]
|
|
3053
|
-
);
|
|
3054
|
-
return match ? String(match.id) : void 0;
|
|
3055
|
-
})(),
|
|
3056
|
-
onValueChange: handleCustomerSelect,
|
|
3057
|
-
children: [
|
|
3058
|
-
/* @__PURE__ */ jsx17(SelectTrigger, { children: /* @__PURE__ */ jsx17(SelectValue, { placeholder: "Select a customer" }) }),
|
|
3059
|
-
/* @__PURE__ */ jsx17(SelectContent, { children: customers.length === 0 ? /* @__PURE__ */ jsx17(
|
|
3060
|
-
SelectItem,
|
|
3061
|
-
{
|
|
3062
|
-
value: "__loading__",
|
|
3063
|
-
disabled: true,
|
|
3064
|
-
children: "Loading\u2026"
|
|
3065
|
-
}
|
|
3066
|
-
) : customers.map((c) => /* @__PURE__ */ jsx17(
|
|
3067
|
-
SelectItem,
|
|
3068
|
-
{
|
|
3069
|
-
value: String(
|
|
3070
|
-
c.id
|
|
3071
|
-
),
|
|
3072
|
-
children: c.name
|
|
3073
|
-
},
|
|
3074
|
-
c.id
|
|
3075
|
-
)) })
|
|
3076
|
-
]
|
|
3077
|
-
}
|
|
3078
|
-
) : col.relationApi ? /* @__PURE__ */ jsx17(
|
|
3079
|
-
RelationAutocomplete,
|
|
3080
|
-
{
|
|
3081
|
-
apiEndpoint: col.relationApi,
|
|
3082
|
-
value: formData[path] ?? "",
|
|
3083
|
-
onChange: (v) => setFormData({
|
|
3084
|
-
...formData,
|
|
3085
|
-
[path]: v
|
|
3086
|
-
}),
|
|
3087
|
-
labelField: col.relationLabelField ?? "name",
|
|
3088
|
-
valueField: col.relationValueField ?? "id",
|
|
3089
|
-
queryParams: col.relationQueryParams,
|
|
3090
|
-
placeholder: `Select ${col.displayName}`
|
|
3091
|
-
}
|
|
3092
|
-
) : col.type === "textarea" ? /* @__PURE__ */ jsx17(
|
|
3093
|
-
Textarea,
|
|
3094
|
-
{
|
|
3095
|
-
rows: typeof col.textareaRows === "number" ? col.textareaRows : 4,
|
|
3096
|
-
className: "min-h-[80px] font-mono text-sm",
|
|
3097
|
-
value: formData[path] ?? "",
|
|
3098
|
-
onChange: (e) => handleChange(e, path),
|
|
3099
|
-
placeholder: col.placeholder,
|
|
3100
|
-
disabled
|
|
3101
|
-
}
|
|
3102
|
-
) : col.type === "select" && Array.isArray(
|
|
3103
|
-
col.options
|
|
3104
|
-
) && col.options.length > 0 ? /* @__PURE__ */ jsxs11(
|
|
3105
|
-
Select,
|
|
3106
|
-
{
|
|
3107
|
-
value: selectValue,
|
|
3108
|
-
onValueChange: (value) => setFormData({
|
|
3109
|
-
...formData,
|
|
3110
|
-
[path]: value
|
|
3111
|
-
}),
|
|
3112
|
-
disabled,
|
|
3113
|
-
children: [
|
|
3114
|
-
/* @__PURE__ */ jsx17(SelectTrigger, { children: /* @__PURE__ */ jsx17(
|
|
3115
|
-
SelectValue,
|
|
3116
|
-
{
|
|
3117
|
-
placeholder: selectValue ? void 0 : "Select an option"
|
|
3118
|
-
}
|
|
3119
|
-
) }),
|
|
3120
|
-
/* @__PURE__ */ jsx17(SelectContent, { children: col.options.map(
|
|
3121
|
-
(option) => /* @__PURE__ */ jsx17(
|
|
3122
|
-
SelectItem,
|
|
3123
|
-
{
|
|
3124
|
-
value: option.value,
|
|
3125
|
-
children: option.label
|
|
3126
|
-
},
|
|
3127
|
-
option.value
|
|
3128
|
-
)
|
|
3129
|
-
) })
|
|
3130
|
-
]
|
|
3131
|
-
}
|
|
3132
|
-
) : col.type === "boolean" ? /* @__PURE__ */ jsx17(
|
|
3133
|
-
Switch,
|
|
3134
|
-
{
|
|
3135
|
-
checked: Boolean(
|
|
3136
|
-
formData[path]
|
|
3137
|
-
),
|
|
3138
|
-
onCheckedChange: (checked) => setFormData({
|
|
3139
|
-
...formData,
|
|
3140
|
-
[path]: checked
|
|
3141
|
-
}),
|
|
3142
|
-
disabled
|
|
3143
|
-
}
|
|
3144
|
-
) : isDateFormColumn(
|
|
3145
|
-
col.type
|
|
3146
|
-
) ? /* @__PURE__ */ jsx17(
|
|
3147
|
-
Input,
|
|
3148
|
-
{
|
|
3149
|
-
type: "date",
|
|
3150
|
-
value: formData[path] ?? "",
|
|
3151
|
-
onChange: (e) => handleChange(e, path),
|
|
3152
|
-
disabled
|
|
3153
|
-
}
|
|
3154
|
-
) : col.type === "password" ? /* @__PURE__ */ jsx17(
|
|
3155
|
-
Input,
|
|
3156
|
-
{
|
|
3157
|
-
type: "password",
|
|
3158
|
-
value: formData[path] || "",
|
|
3159
|
-
onChange: (e) => handleChange(e, path),
|
|
3160
|
-
disabled
|
|
3161
|
-
}
|
|
3162
|
-
) : col.type === "number" ? /* @__PURE__ */ jsx17(
|
|
3163
|
-
Input,
|
|
3164
|
-
{
|
|
3165
|
-
type: "number",
|
|
3166
|
-
placeholder: col.placeholder,
|
|
3167
|
-
value: formData[path] ?? "",
|
|
3168
|
-
onChange: (e) => handleChange(e, path),
|
|
3169
|
-
disabled
|
|
3170
|
-
}
|
|
3171
|
-
) : col.type === "phone" || col.type === "tel" ? /* @__PURE__ */ jsx17(
|
|
3172
|
-
Input,
|
|
3173
|
-
{
|
|
3174
|
-
type: "tel",
|
|
3175
|
-
inputMode: "tel",
|
|
3176
|
-
autoComplete: "tel",
|
|
3177
|
-
placeholder: col.placeholder ?? "e.g. +1 555 123 4567",
|
|
3178
|
-
value: formData[path] ?? "",
|
|
3179
|
-
onChange: (e) => handleChange(e, path),
|
|
3180
|
-
disabled
|
|
3181
|
-
}
|
|
3182
|
-
) : col.type === "file" ? /* @__PURE__ */ jsx17(
|
|
3183
|
-
FileUpload,
|
|
3184
|
-
{
|
|
3185
|
-
onUploadSuccess: (url) => handleFileUpload(
|
|
3186
|
-
path,
|
|
3187
|
-
url
|
|
3188
|
-
)
|
|
3189
|
-
}
|
|
3190
|
-
) : /* @__PURE__ */ jsx17(
|
|
3191
|
-
Input,
|
|
3192
|
-
{
|
|
3193
|
-
type: col.type || "text",
|
|
3194
|
-
placeholder: ["subtotal", "tax", "total"].includes(path) ? "Auto-calculated from items" : col.placeholder,
|
|
3195
|
-
value: formData[path] ?? "",
|
|
3196
|
-
onChange: (e) => handleChange(e, path),
|
|
3197
|
-
disabled
|
|
3198
|
-
}
|
|
3199
|
-
),
|
|
3200
|
-
errors[path] && /* @__PURE__ */ jsx17("p", { className: "text-red-500 text-sm mt-1", children: errors[path] })
|
|
3032
|
+
/* @__PURE__ */ jsxs11("form", { onSubmit: handleSubmit, className: "flex flex-col flex-1 min-h-0", children: [
|
|
3033
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex-1 min-h-0 overflow-y-auto p-6 space-y-4", children: [
|
|
3034
|
+
visibleColumns.map((col) => {
|
|
3035
|
+
const path = col.field || col.key;
|
|
3036
|
+
if (!path) return null;
|
|
3037
|
+
const disabled = isFieldDisabled(path);
|
|
3038
|
+
const optionSet = col.type === "select" && Array.isArray(col.options) ? new Set(col.options.map((o) => String(o.value))) : null;
|
|
3039
|
+
const rawStr = formData[path] != null && formData[path] !== "" ? String(formData[path]) : "";
|
|
3040
|
+
const selectValue = optionSet ? rawStr !== "" && optionSet.has(rawStr) ? rawStr : col.defaultValue : void 0;
|
|
3041
|
+
return /* @__PURE__ */ jsxs11(React12.Fragment, { children: [
|
|
3042
|
+
/* @__PURE__ */ jsxs11("div", { children: [
|
|
3043
|
+
/* @__PURE__ */ jsxs11(Label3, { className: "block text-sm font-medium mb-1", children: [
|
|
3044
|
+
col.displayName,
|
|
3045
|
+
["subtotal", "tax", "total"].includes(path) && totalLoading && /* @__PURE__ */ jsx17("span", { className: "ml-2 text-xs text-gray-400 font-normal", children: "Calculating\u2026" })
|
|
3201
3046
|
] }),
|
|
3202
|
-
col.type === "customerDropdown"
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3047
|
+
col.type === "customerDropdown" ? /* @__PURE__ */ jsxs11(
|
|
3048
|
+
Select,
|
|
3049
|
+
{
|
|
3050
|
+
value: (() => {
|
|
3051
|
+
const match = customers.find(
|
|
3052
|
+
(c) => String(c.id) === String(formData["contactId"]) || c.name === formData["contact.name"]
|
|
3053
|
+
);
|
|
3054
|
+
return match ? String(match.id) : void 0;
|
|
3055
|
+
})(),
|
|
3056
|
+
onValueChange: handleCustomerSelect,
|
|
3057
|
+
children: [
|
|
3058
|
+
/* @__PURE__ */ jsx17(SelectTrigger, { children: /* @__PURE__ */ jsx17(SelectValue, { placeholder: "Select a customer" }) }),
|
|
3059
|
+
/* @__PURE__ */ jsx17(SelectContent, { children: customers.length === 0 ? /* @__PURE__ */ jsx17(SelectItem, { value: "__loading__", disabled: true, children: "Loading\u2026" }) : customers.map((c) => /* @__PURE__ */ jsx17(SelectItem, { value: String(c.id), children: c.name }, c.id)) })
|
|
3060
|
+
]
|
|
3061
|
+
}
|
|
3062
|
+
) : col.relationApi ? /* @__PURE__ */ jsx17(
|
|
3063
|
+
RelationAutocomplete,
|
|
3064
|
+
{
|
|
3065
|
+
apiEndpoint: col.relationApi,
|
|
3066
|
+
value: formData[path] ?? "",
|
|
3067
|
+
onChange: (v) => setFormData({ ...formData, [path]: v }),
|
|
3068
|
+
labelField: col.relationLabelField ?? "name",
|
|
3069
|
+
valueField: col.relationValueField ?? "id",
|
|
3070
|
+
queryParams: col.relationQueryParams,
|
|
3071
|
+
placeholder: `Select ${col.displayName}`
|
|
3072
|
+
}
|
|
3073
|
+
) : col.type === "textarea" ? /* @__PURE__ */ jsx17(
|
|
3074
|
+
Textarea,
|
|
3075
|
+
{
|
|
3076
|
+
rows: typeof col.textareaRows === "number" ? col.textareaRows : 4,
|
|
3077
|
+
className: "min-h-[80px] font-mono text-sm",
|
|
3078
|
+
value: formData[path] ?? "",
|
|
3079
|
+
onChange: (e) => handleChange(e, path),
|
|
3080
|
+
placeholder: col.placeholder,
|
|
3081
|
+
disabled
|
|
3082
|
+
}
|
|
3083
|
+
) : col.type === "select" && Array.isArray(col.options) && col.options.length > 0 ? /* @__PURE__ */ jsxs11(
|
|
3084
|
+
Select,
|
|
3085
|
+
{
|
|
3086
|
+
value: selectValue,
|
|
3087
|
+
onValueChange: (value) => setFormData({ ...formData, [path]: value }),
|
|
3088
|
+
disabled,
|
|
3089
|
+
children: [
|
|
3090
|
+
/* @__PURE__ */ jsx17(SelectTrigger, { children: /* @__PURE__ */ jsx17(
|
|
3091
|
+
SelectValue,
|
|
3092
|
+
{
|
|
3093
|
+
placeholder: selectValue ? void 0 : "Select an option"
|
|
3094
|
+
}
|
|
3095
|
+
) }),
|
|
3096
|
+
/* @__PURE__ */ jsx17(SelectContent, { children: col.options.map((option) => /* @__PURE__ */ jsx17(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
3097
|
+
]
|
|
3098
|
+
}
|
|
3099
|
+
) : col.type === "boolean" ? /* @__PURE__ */ jsx17(
|
|
3100
|
+
Switch,
|
|
3101
|
+
{
|
|
3102
|
+
checked: Boolean(formData[path]),
|
|
3103
|
+
onCheckedChange: (checked) => setFormData({ ...formData, [path]: checked }),
|
|
3104
|
+
disabled
|
|
3105
|
+
}
|
|
3106
|
+
) : isDateFormColumn(col.type) ? /* @__PURE__ */ jsx17(
|
|
3107
|
+
Input,
|
|
3108
|
+
{
|
|
3109
|
+
type: "date",
|
|
3110
|
+
value: formData[path] ?? "",
|
|
3111
|
+
onChange: (e) => handleChange(e, path),
|
|
3112
|
+
disabled
|
|
3113
|
+
}
|
|
3114
|
+
) : col.type === "password" ? /* @__PURE__ */ jsx17(
|
|
3115
|
+
Input,
|
|
3116
|
+
{
|
|
3117
|
+
type: "password",
|
|
3118
|
+
value: formData[path] || "",
|
|
3119
|
+
onChange: (e) => handleChange(e, path),
|
|
3120
|
+
disabled
|
|
3121
|
+
}
|
|
3122
|
+
) : col.type === "number" ? /* @__PURE__ */ jsx17(
|
|
3123
|
+
Input,
|
|
3124
|
+
{
|
|
3125
|
+
type: "number",
|
|
3126
|
+
placeholder: col.placeholder,
|
|
3127
|
+
value: formData[path] ?? "",
|
|
3128
|
+
onChange: (e) => handleChange(e, path),
|
|
3129
|
+
disabled
|
|
3130
|
+
}
|
|
3131
|
+
) : col.type === "phone" || col.type === "tel" ? /* @__PURE__ */ jsx17(
|
|
3132
|
+
Input,
|
|
3133
|
+
{
|
|
3134
|
+
type: "tel",
|
|
3135
|
+
inputMode: "tel",
|
|
3136
|
+
autoComplete: "tel",
|
|
3137
|
+
placeholder: col.placeholder ?? "e.g. +1 555 123 4567",
|
|
3138
|
+
value: formData[path] ?? "",
|
|
3139
|
+
onChange: (e) => handleChange(e, path),
|
|
3140
|
+
disabled
|
|
3141
|
+
}
|
|
3142
|
+
) : col.type === "file" ? /* @__PURE__ */ jsx17(
|
|
3143
|
+
FileUpload,
|
|
3144
|
+
{
|
|
3145
|
+
onUploadSuccess: (url) => handleFileUpload(path, url)
|
|
3146
|
+
}
|
|
3147
|
+
) : /* @__PURE__ */ jsx17(
|
|
3148
|
+
Input,
|
|
3149
|
+
{
|
|
3150
|
+
type: col.type || "text",
|
|
3151
|
+
placeholder: ["subtotal", "tax", "total"].includes(path) ? "Auto-calculated from items" : col.placeholder,
|
|
3152
|
+
value: formData[path] ?? "",
|
|
3153
|
+
onChange: (e) => handleChange(e, path),
|
|
3154
|
+
disabled
|
|
3155
|
+
}
|
|
3156
|
+
),
|
|
3157
|
+
errors[path] && /* @__PURE__ */ jsx17("p", { className: "text-red-500 text-sm mt-1", children: errors[path] })
|
|
3158
|
+
] }),
|
|
3159
|
+
col.type === "customerDropdown" && /* @__PURE__ */ jsxs11("div", { children: [
|
|
3160
|
+
/* @__PURE__ */ jsx17(Label3, { className: "block text-sm font-medium mb-1", children: "Name" }),
|
|
3161
|
+
/* @__PURE__ */ jsx17(
|
|
3162
|
+
Input,
|
|
3163
|
+
{
|
|
3164
|
+
type: "text",
|
|
3165
|
+
placeholder: "Customer name",
|
|
3166
|
+
value: formData["contact.name"] ?? "",
|
|
3167
|
+
onChange: (e) => setFormData((prev) => ({
|
|
3168
|
+
...prev,
|
|
3169
|
+
"contact.name": e.target.value
|
|
3170
|
+
}))
|
|
3171
|
+
}
|
|
3172
|
+
)
|
|
3173
|
+
] })
|
|
3174
|
+
] }, path);
|
|
3175
|
+
}),
|
|
3176
|
+
isCustomerCreate && /* @__PURE__ */ jsxs11(Fragment3, { children: [
|
|
3177
|
+
/* @__PURE__ */ jsxs11("div", { children: [
|
|
3178
|
+
/* @__PURE__ */ jsx17(Label3, { className: "block text-sm font-medium mb-1", children: "Password" }),
|
|
3222
3179
|
/* @__PURE__ */ jsx17(
|
|
3223
|
-
|
|
3180
|
+
Input,
|
|
3224
3181
|
{
|
|
3225
|
-
type: "
|
|
3226
|
-
|
|
3227
|
-
|
|
3182
|
+
type: "password",
|
|
3183
|
+
value: password,
|
|
3184
|
+
onChange: (e) => setPassword(e.target.value),
|
|
3185
|
+
placeholder: "Min. 6 characters"
|
|
3228
3186
|
}
|
|
3229
3187
|
),
|
|
3188
|
+
errors["_password"] && /* @__PURE__ */ jsx17("p", { className: "text-red-500 text-sm mt-1", children: errors["_password"] })
|
|
3189
|
+
] }),
|
|
3190
|
+
/* @__PURE__ */ jsxs11("div", { children: [
|
|
3191
|
+
/* @__PURE__ */ jsx17(Label3, { className: "block text-sm font-medium mb-1", children: "Confirm Password" }),
|
|
3230
3192
|
/* @__PURE__ */ jsx17(
|
|
3231
|
-
|
|
3193
|
+
Input,
|
|
3232
3194
|
{
|
|
3233
|
-
type: "
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
children: "Cancel"
|
|
3195
|
+
type: "password",
|
|
3196
|
+
value: confirmPassword,
|
|
3197
|
+
onChange: (e) => setConfirmPassword(e.target.value),
|
|
3198
|
+
placeholder: "Re-enter password"
|
|
3238
3199
|
}
|
|
3239
|
-
)
|
|
3200
|
+
),
|
|
3201
|
+
errors["_confirmPassword"] && /* @__PURE__ */ jsx17("p", { className: "text-red-500 text-sm mt-1", children: errors["_confirmPassword"] })
|
|
3240
3202
|
] })
|
|
3241
|
-
]
|
|
3242
|
-
}
|
|
3243
|
-
|
|
3203
|
+
] })
|
|
3204
|
+
] }),
|
|
3205
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex gap-2 p-4 border-t border-gray-200 shrink-0 bg-white", children: [
|
|
3206
|
+
/* @__PURE__ */ jsx17(Button, { type: "submit", className: "flex-1", children: "Save" }),
|
|
3207
|
+
/* @__PURE__ */ jsx17(
|
|
3208
|
+
Button,
|
|
3209
|
+
{
|
|
3210
|
+
type: "button",
|
|
3211
|
+
variant: "outline",
|
|
3212
|
+
onClick: onClose,
|
|
3213
|
+
className: "flex-1",
|
|
3214
|
+
children: "Cancel"
|
|
3215
|
+
}
|
|
3216
|
+
)
|
|
3217
|
+
] })
|
|
3218
|
+
] })
|
|
3244
3219
|
]
|
|
3245
3220
|
}
|
|
3246
3221
|
) }) : null;
|
|
@@ -3783,7 +3758,7 @@ init_input();
|
|
|
3783
3758
|
import { useCallback as useCallback2, useEffect as useEffect6, useMemo as useMemo2, useRef as useRef4, useState as useState8 } from "react";
|
|
3784
3759
|
init_utils();
|
|
3785
3760
|
import { Filter, Search, X as X5 } from "lucide-react";
|
|
3786
|
-
import { Fragment as
|
|
3761
|
+
import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
3787
3762
|
var FILTER_BY_NONE = "__filter_by_none__";
|
|
3788
3763
|
var SELECT_VALUE_ALL = "__select_all__";
|
|
3789
3764
|
function isPointerOnRadixOverlayTarget(target, shell) {
|
|
@@ -4067,7 +4042,7 @@ function CrudSearchFilterBar({
|
|
|
4067
4042
|
}
|
|
4068
4043
|
)
|
|
4069
4044
|
] }),
|
|
4070
|
-
activeDef ? /* @__PURE__ */ jsxs15(
|
|
4045
|
+
activeDef ? /* @__PURE__ */ jsxs15(Fragment4, { children: [
|
|
4071
4046
|
activeDef.type === "select" ? /* @__PURE__ */ jsxs15("div", { className: "w-full min-w-0 flex-1 sm:min-w-[200px] sm:max-w-md", children: [
|
|
4072
4047
|
/* @__PURE__ */ jsx22(Label3, { className: "mb-1.5 block text-xs font-medium text-gray-500", children: "Value" }),
|
|
4073
4048
|
activeDef.relationApi && (!relationLabelMaps[activeDef.relationApi] || Object.keys(relationLabelMaps[activeDef.relationApi] ?? {}).length === 0) ? /* @__PURE__ */ jsx22("p", { className: "text-sm text-muted-foreground", children: "Loading options\u2026" }) : /* @__PURE__ */ jsxs15(
|
|
@@ -4423,7 +4398,7 @@ function prepareRecordForDuplicate(resourceName, row) {
|
|
|
4423
4398
|
var CRUD_NO_DUPLICATE_RESOURCES = /* @__PURE__ */ new Set(["form-submissions", "payments"]);
|
|
4424
4399
|
|
|
4425
4400
|
// src/components/Admin/CRUD.tsx
|
|
4426
|
-
import { Fragment as
|
|
4401
|
+
import { Fragment as Fragment5, jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
4427
4402
|
function getNestedValue2(obj, path) {
|
|
4428
4403
|
return path.split(".").reduce((current, key) => {
|
|
4429
4404
|
return current && current[key] !== void 0 ? current[key] : null;
|
|
@@ -5084,7 +5059,7 @@ function AdminCRUD({
|
|
|
5084
5059
|
/* @__PURE__ */ jsx23(Button, { onClick: () => window.location.reload(), children: "Retry" })
|
|
5085
5060
|
] }) });
|
|
5086
5061
|
}
|
|
5087
|
-
return /* @__PURE__ */ jsx23(
|
|
5062
|
+
return /* @__PURE__ */ jsx23(Fragment5, { children: /* @__PURE__ */ jsxs16("div", { className: "rounded-lg bg-white shadow-md min-w-0", children: [
|
|
5088
5063
|
/* @__PURE__ */ jsx23("div", { className: "bg-gray-800 border-b border-gray-700 px-4 py-2.5 rounded-t-lg", children: isMobile ? /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2 min-w-0", children: [
|
|
5089
5064
|
/* @__PURE__ */ jsxs16("div", { className: "min-w-0 flex-1", children: [
|
|
5090
5065
|
/* @__PURE__ */ jsx23("h1", { className: "text-base font-semibold text-white truncate", children: title }),
|
|
@@ -5486,7 +5461,8 @@ function AdminCRUD({
|
|
|
5486
5461
|
apiEndpoint,
|
|
5487
5462
|
columns,
|
|
5488
5463
|
existingData: editingItem,
|
|
5489
|
-
duplicateSeed
|
|
5464
|
+
duplicateSeed,
|
|
5465
|
+
resource: resourceName
|
|
5490
5466
|
}
|
|
5491
5467
|
),
|
|
5492
5468
|
/* @__PURE__ */ jsx23(
|
|
@@ -6561,7 +6537,7 @@ init_input();
|
|
|
6561
6537
|
init_button();
|
|
6562
6538
|
import { useState as useState13, useEffect as useEffect9, useRef as useRef7, useCallback as useCallback6 } from "react";
|
|
6563
6539
|
import { X as X10, Plus as Plus4, Search as Search2 } from "lucide-react";
|
|
6564
|
-
import { Fragment as
|
|
6540
|
+
import { Fragment as Fragment6, jsx as jsx29, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
6565
6541
|
function TagAutocomplete({
|
|
6566
6542
|
selectedTags,
|
|
6567
6543
|
onTagsChange,
|
|
@@ -6704,7 +6680,7 @@ function TagAutocomplete({
|
|
|
6704
6680
|
onClick: handleCreateTag,
|
|
6705
6681
|
disabled: isCreating || selectedTags.includes(inputValue.trim()),
|
|
6706
6682
|
className: "absolute right-1 top-1/2 -translate-y-1/2 h-7 px-2",
|
|
6707
|
-
children: isCreating ? "Creating..." : /* @__PURE__ */ jsxs20(
|
|
6683
|
+
children: isCreating ? "Creating..." : /* @__PURE__ */ jsxs20(Fragment6, { children: [
|
|
6708
6684
|
/* @__PURE__ */ jsx29(Plus4, { className: "h-3 w-3 mr-1" }),
|
|
6709
6685
|
"Create"
|
|
6710
6686
|
] })
|
|
@@ -6834,7 +6810,7 @@ init_input();
|
|
|
6834
6810
|
init_button();
|
|
6835
6811
|
import { useState as useState14, useEffect as useEffect10, useRef as useRef8 } from "react";
|
|
6836
6812
|
import { X as X11, Plus as Plus5, Search as Search3, Check as Check5 } from "lucide-react";
|
|
6837
|
-
import { Fragment as
|
|
6813
|
+
import { Fragment as Fragment7, jsx as jsx31, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
6838
6814
|
function CategoryAutocomplete({
|
|
6839
6815
|
selectedCategory,
|
|
6840
6816
|
onCategoryChange,
|
|
@@ -6972,7 +6948,7 @@ function CategoryAutocomplete({
|
|
|
6972
6948
|
onClick: handleCreateCategory,
|
|
6973
6949
|
disabled: isCreating,
|
|
6974
6950
|
className: "absolute right-1 top-1/2 -translate-y-1/2 h-7 px-2",
|
|
6975
|
-
children: isCreating ? "Creating..." : /* @__PURE__ */ jsxs21(
|
|
6951
|
+
children: isCreating ? "Creating..." : /* @__PURE__ */ jsxs21(Fragment7, { children: [
|
|
6976
6952
|
/* @__PURE__ */ jsx31(Plus5, { className: "h-3 w-3 mr-1" }),
|
|
6977
6953
|
"Create"
|
|
6978
6954
|
] })
|
|
@@ -8493,7 +8469,7 @@ var BLOG_GENERATOR_DEFAULT_VALIDATION_RULES = JSON.stringify(
|
|
|
8493
8469
|
);
|
|
8494
8470
|
|
|
8495
8471
|
// src/components/Admin/BlogGeneratorRssTool.tsx
|
|
8496
|
-
import { Fragment as
|
|
8472
|
+
import { Fragment as Fragment8, jsx as jsx41, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
8497
8473
|
function BlogGeneratorRssTool({
|
|
8498
8474
|
inputIdPrefix = "blog-gen-rss",
|
|
8499
8475
|
variant = "page"
|
|
@@ -8956,11 +8932,11 @@ function BlogGeneratorRssTool({
|
|
|
8956
8932
|
" row \u2014 model",
|
|
8957
8933
|
" ",
|
|
8958
8934
|
/* @__PURE__ */ jsx41("span", { className: "font-mono", children: llmAgentInfo.model ?? "(gateway default)" }),
|
|
8959
|
-
llmAgentInfo.temperature != null && /* @__PURE__ */ jsxs31(
|
|
8935
|
+
llmAgentInfo.temperature != null && /* @__PURE__ */ jsxs31(Fragment8, { children: [
|
|
8960
8936
|
", temperature ",
|
|
8961
8937
|
/* @__PURE__ */ jsx41("span", { className: "font-mono", children: String(llmAgentInfo.temperature) })
|
|
8962
8938
|
] }),
|
|
8963
|
-
llmAgentInfo.maxTokens != null && /* @__PURE__ */ jsxs31(
|
|
8939
|
+
llmAgentInfo.maxTokens != null && /* @__PURE__ */ jsxs31(Fragment8, { children: [
|
|
8964
8940
|
", max_tokens ",
|
|
8965
8941
|
/* @__PURE__ */ jsx41("span", { className: "font-mono", children: String(llmAgentInfo.maxTokens) })
|
|
8966
8942
|
] }),
|
|
@@ -8983,11 +8959,11 @@ function BlogGeneratorRssTool({
|
|
|
8983
8959
|
" \u2014 model",
|
|
8984
8960
|
" ",
|
|
8985
8961
|
/* @__PURE__ */ jsx41("span", { className: "font-mono", children: metadataLlmAgentInfo.model ?? "(gateway default)" }),
|
|
8986
|
-
metadataLlmAgentInfo.temperature != null && /* @__PURE__ */ jsxs31(
|
|
8962
|
+
metadataLlmAgentInfo.temperature != null && /* @__PURE__ */ jsxs31(Fragment8, { children: [
|
|
8987
8963
|
", temperature ",
|
|
8988
8964
|
/* @__PURE__ */ jsx41("span", { className: "font-mono", children: String(metadataLlmAgentInfo.temperature) })
|
|
8989
8965
|
] }),
|
|
8990
|
-
metadataLlmAgentInfo.maxTokens != null && /* @__PURE__ */ jsxs31(
|
|
8966
|
+
metadataLlmAgentInfo.maxTokens != null && /* @__PURE__ */ jsxs31(Fragment8, { children: [
|
|
8991
8967
|
", max_tokens ",
|
|
8992
8968
|
/* @__PURE__ */ jsx41("span", { className: "font-mono", children: String(metadataLlmAgentInfo.maxTokens) })
|
|
8993
8969
|
] }),
|
|
@@ -9395,7 +9371,7 @@ import { useRouter as useRouter6 } from "next/navigation";
|
|
|
9395
9371
|
import { Chart as ChartJS2, ArcElement, Tooltip as Tooltip2, Legend as Legend2 } from "chart.js";
|
|
9396
9372
|
import { Doughnut } from "react-chartjs-2";
|
|
9397
9373
|
import { Users as Users4, Eye, MousePointer, Globe, FileText, ClipboardList as ClipboardList2, UserCheck, TrendingUp, BarChart3, Activity } from "lucide-react";
|
|
9398
|
-
import { Fragment as
|
|
9374
|
+
import { Fragment as Fragment9, jsx as jsx48, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
9399
9375
|
ChartJS2.register(ArcElement, Tooltip2, Legend2);
|
|
9400
9376
|
function DashboardPage() {
|
|
9401
9377
|
const { data: session } = useSession6();
|
|
@@ -9739,7 +9715,7 @@ function DashboardPage() {
|
|
|
9739
9715
|
) })
|
|
9740
9716
|
] })
|
|
9741
9717
|
] }),
|
|
9742
|
-
activeTab === "overview" && analyticsEnabled && !isLoading && analyticsData && /* @__PURE__ */ jsxs38(
|
|
9718
|
+
activeTab === "overview" && analyticsEnabled && !isLoading && analyticsData && /* @__PURE__ */ jsxs38(Fragment9, { children: [
|
|
9743
9719
|
/* @__PURE__ */ jsxs38("div", { className: "mb-4", children: [
|
|
9744
9720
|
/* @__PURE__ */ jsxs38("div", { className: "flex items-center mb-2", children: [
|
|
9745
9721
|
/* @__PURE__ */ jsx48(Globe, { className: "w-4 h-4 text-gray-600 mr-2" }),
|
|
@@ -9825,7 +9801,7 @@ function DashboardPage() {
|
|
|
9825
9801
|
/* @__PURE__ */ jsx48("div", { className: "border-t-2 border-dotted border-gray-200 my-6" }),
|
|
9826
9802
|
/* @__PURE__ */ jsx48("div", { className: "mb-6", children: /* @__PURE__ */ jsx48(GeographicMap, { data: analyticsData.geographicData }) })
|
|
9827
9803
|
] }),
|
|
9828
|
-
activeTab === "crm" && !isLoading && /* @__PURE__ */ jsxs38(
|
|
9804
|
+
activeTab === "crm" && !isLoading && /* @__PURE__ */ jsxs38(Fragment9, { children: [
|
|
9829
9805
|
/* @__PURE__ */ jsxs38("div", { className: "mb-4", children: [
|
|
9830
9806
|
/* @__PURE__ */ jsxs38("div", { className: "flex items-center mb-2", children: [
|
|
9831
9807
|
/* @__PURE__ */ jsx48(Users4, { className: "w-4 h-4 text-gray-600 mr-2" }),
|
|
@@ -9943,7 +9919,7 @@ function DashboardPage() {
|
|
|
9943
9919
|
] })
|
|
9944
9920
|
] })
|
|
9945
9921
|
] }),
|
|
9946
|
-
activeTab === "sales" && !isLoading && storeEnabled && ecommerceData && /* @__PURE__ */ jsxs38(
|
|
9922
|
+
activeTab === "sales" && !isLoading && storeEnabled && ecommerceData && /* @__PURE__ */ jsxs38(Fragment9, { children: [
|
|
9947
9923
|
/* @__PURE__ */ jsx48("div", { className: "border-t-2 border-dotted border-gray-200 my-6" }),
|
|
9948
9924
|
/* @__PURE__ */ jsxs38("div", { className: "mb-4", children: [
|
|
9949
9925
|
/* @__PURE__ */ jsxs38("div", { className: "flex items-center mb-2", children: [
|
|
@@ -10089,7 +10065,7 @@ function DashboardPage() {
|
|
|
10089
10065
|
// src/admin/pages/AdminPageResolver.tsx
|
|
10090
10066
|
import { useState as useState50, useEffect as useEffect47, useContext as useContext9, useMemo as useMemo10, Suspense as Suspense3 } from "react";
|
|
10091
10067
|
import dynamic2 from "next/dynamic";
|
|
10092
|
-
import { useRouter as
|
|
10068
|
+
import { useRouter as useRouter22, useSearchParams as useSearchParams20 } from "next/navigation";
|
|
10093
10069
|
|
|
10094
10070
|
// src/admin/pages/SubmissionDetailPage.tsx
|
|
10095
10071
|
init_admin_list_return_url();
|
|
@@ -10226,7 +10202,7 @@ import Link10 from "next/link";
|
|
|
10226
10202
|
import { useRouter as useRouter8, useSearchParams as useSearchParams5 } from "next/navigation";
|
|
10227
10203
|
import { X as X15, RefreshCw as RefreshCw2, Pencil } from "lucide-react";
|
|
10228
10204
|
import { QRCode } from "react-qr-code";
|
|
10229
|
-
import { Fragment as
|
|
10205
|
+
import { Fragment as Fragment11, jsx as jsx52, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
10230
10206
|
function formatMoney(amount, currency = "INR") {
|
|
10231
10207
|
return new Intl.NumberFormat("en-IN", {
|
|
10232
10208
|
style: "currency",
|
|
@@ -10357,7 +10333,7 @@ function OrderDetailPage({ orderId }) {
|
|
|
10357
10333
|
/* @__PURE__ */ jsx52(
|
|
10358
10334
|
DetailPageLayout,
|
|
10359
10335
|
{
|
|
10360
|
-
main: /* @__PURE__ */ jsxs42(
|
|
10336
|
+
main: /* @__PURE__ */ jsxs42(Fragment11, { children: [
|
|
10361
10337
|
/* @__PURE__ */ jsxs42("section", { children: [
|
|
10362
10338
|
/* @__PURE__ */ jsx52("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Order details" }),
|
|
10363
10339
|
/* @__PURE__ */ jsx52("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50", children: /* @__PURE__ */ jsxs42("dl", { className: "min-w-0 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 text-sm", children: [
|
|
@@ -10389,7 +10365,7 @@ function OrderDetailPage({ orderId }) {
|
|
|
10389
10365
|
/* @__PURE__ */ jsx52("dt", { className: "text-gray-500", children: "Total" }),
|
|
10390
10366
|
/* @__PURE__ */ jsx52("dd", { className: "font-medium text-gray-900", children: formatMoney(Number(order.total), currency) })
|
|
10391
10367
|
] }),
|
|
10392
|
-
(order.orderKind || order.parentOrderId != null) && /* @__PURE__ */ jsxs42(
|
|
10368
|
+
(order.orderKind || order.parentOrderId != null) && /* @__PURE__ */ jsxs42(Fragment11, { children: [
|
|
10393
10369
|
/* @__PURE__ */ jsxs42("div", { className: "min-w-0", children: [
|
|
10394
10370
|
/* @__PURE__ */ jsx52("dt", { className: "text-gray-500", children: "Kind" }),
|
|
10395
10371
|
/* @__PURE__ */ jsx52("dd", { className: "font-medium text-gray-900 capitalize", children: order.orderKind ?? "sale" })
|
|
@@ -10512,7 +10488,7 @@ function OrderDetailPage({ orderId }) {
|
|
|
10512
10488
|
] })
|
|
10513
10489
|
] }) })
|
|
10514
10490
|
] }),
|
|
10515
|
-
sidebar: /* @__PURE__ */ jsxs42(
|
|
10491
|
+
sidebar: /* @__PURE__ */ jsxs42(Fragment11, { children: [
|
|
10516
10492
|
contact && /* @__PURE__ */ jsxs42("section", { children: [
|
|
10517
10493
|
/* @__PURE__ */ jsx52("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Customer" }),
|
|
10518
10494
|
/* @__PURE__ */ jsx52("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50", children: /* @__PURE__ */ jsxs42("dl", { className: "min-w-0 grid grid-cols-1 sm:grid-cols-3 gap-3 text-sm", children: [
|
|
@@ -10641,7 +10617,7 @@ Checkbox.displayName = CheckboxPrimitive.Root.displayName;
|
|
|
10641
10617
|
init_table();
|
|
10642
10618
|
init_DetailPageHeader();
|
|
10643
10619
|
import { toast as toast5 } from "sonner";
|
|
10644
|
-
import { Trash2 as Trash25, ShoppingCart as ShoppingCart4 } from "lucide-react";
|
|
10620
|
+
import { Trash2 as Trash25, ShoppingCart as ShoppingCart4, Users as Users6 } from "lucide-react";
|
|
10645
10621
|
|
|
10646
10622
|
// src/admin/pages/OrderDiscountPanel.tsx
|
|
10647
10623
|
init_input();
|
|
@@ -11053,6 +11029,7 @@ function formatMoney3(amount, currency) {
|
|
|
11053
11029
|
}).format(Number(amount));
|
|
11054
11030
|
}
|
|
11055
11031
|
var MANUAL_CUSTOMER = "__manual__";
|
|
11032
|
+
var MANUAL_CONTACT = "__manual__";
|
|
11056
11033
|
function OrderPlacementPage({ editOrderId }) {
|
|
11057
11034
|
const router = useRouter9();
|
|
11058
11035
|
const searchParams = useSearchParams6();
|
|
@@ -11060,25 +11037,23 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
11060
11037
|
const [customers, setCustomers] = useState28([]);
|
|
11061
11038
|
const [customersLoading, setCustomersLoading] = useState28(true);
|
|
11062
11039
|
const [contactId, setContactId] = useState28(null);
|
|
11040
|
+
const [selectedCustomerId, setSelectedCustomerId] = useState28(null);
|
|
11063
11041
|
const [contactName, setContactName] = useState28("");
|
|
11064
11042
|
const [contactEmail, setContactEmail] = useState28("");
|
|
11065
11043
|
const [contactPhone, setContactPhone] = useState28("");
|
|
11044
|
+
const [placeForSomeoneElse, setPlaceForSomeoneElse] = useState28(false);
|
|
11045
|
+
const [customerContacts, setCustomerContacts] = useState28([]);
|
|
11046
|
+
const [customerContactsLoading, setCustomerContactsLoading] = useState28(false);
|
|
11047
|
+
const [subContactId, setSubContactId] = useState28(null);
|
|
11048
|
+
const [subContactName, setSubContactName] = useState28("");
|
|
11049
|
+
const [subContactEmail, setSubContactEmail] = useState28("");
|
|
11050
|
+
const [subContactPhone, setSubContactPhone] = useState28("");
|
|
11066
11051
|
const [status, setStatus] = useState28("pending");
|
|
11067
11052
|
const [currency, setCurrency] = useState28("INR");
|
|
11068
11053
|
const [loadingOrder, setLoadingOrder] = useState28(Boolean(editOrderId));
|
|
11069
11054
|
const [orderLoadError, setOrderLoadError] = useState28(null);
|
|
11070
|
-
const [couponError, setCouponError] = useState28(null);
|
|
11071
|
-
const [couponLoading, setCouponLoading] = useState28(false);
|
|
11072
11055
|
const [coupons, setCoupons] = useState28([]);
|
|
11073
|
-
const
|
|
11074
|
-
const emptyAddress = {
|
|
11075
|
-
line1: "",
|
|
11076
|
-
line2: "",
|
|
11077
|
-
city: "",
|
|
11078
|
-
state: "",
|
|
11079
|
-
country: "",
|
|
11080
|
-
postalCode: ""
|
|
11081
|
-
};
|
|
11056
|
+
const emptyAddress = { line1: "", line2: "", city: "", state: "", country: "", postalCode: "" };
|
|
11082
11057
|
const [billingAddress, setBillingAddress] = useState28(emptyAddress);
|
|
11083
11058
|
const [shippingAddress, setShippingAddress] = useState28(emptyAddress);
|
|
11084
11059
|
const [sameAsBilling, setSameAsBilling] = useState28(true);
|
|
@@ -11141,9 +11116,7 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
11141
11116
|
setSameAsBilling(true);
|
|
11142
11117
|
}
|
|
11143
11118
|
const loadedCid = typeof cid === "number" && Number.isFinite(cid) ? cid : null;
|
|
11144
|
-
if (loadedCid && !o.billingAddress && !o.shippingAddress)
|
|
11145
|
-
void loadCustomerAddresses(loadedCid);
|
|
11146
|
-
}
|
|
11119
|
+
if (loadedCid && !o.billingAddress && !o.shippingAddress) void loadContactAddresses(loadedCid);
|
|
11147
11120
|
setStatus(String(o.status ?? "pending"));
|
|
11148
11121
|
const cur = String(o.currency ?? "INR").trim().toUpperCase().slice(0, 8);
|
|
11149
11122
|
if (cur) setCurrency(cur);
|
|
@@ -11153,13 +11126,7 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
11153
11126
|
const coll = p?.collection?.name;
|
|
11154
11127
|
const nm = p?.name;
|
|
11155
11128
|
const label = [coll, nm].filter(Boolean).join(" \u2014 ") || nm || `Product #${pid}`;
|
|
11156
|
-
return {
|
|
11157
|
-
key: `line-${it.id}`,
|
|
11158
|
-
productId: pid,
|
|
11159
|
-
label,
|
|
11160
|
-
sku: p?.sku ?? null,
|
|
11161
|
-
quantity: Math.max(1, Math.floor(Number(it.quantity) || 1))
|
|
11162
|
-
};
|
|
11129
|
+
return { key: `line-${it.id}`, productId: pid, label, sku: p?.sku ?? null, quantity: Math.max(1, Math.floor(Number(it.quantity) || 1)) };
|
|
11163
11130
|
});
|
|
11164
11131
|
setLines(draft);
|
|
11165
11132
|
try {
|
|
@@ -11172,18 +11139,7 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
11172
11139
|
if (dr.ok) {
|
|
11173
11140
|
const d = await dr.json();
|
|
11174
11141
|
if (d?.id) {
|
|
11175
|
-
setCoupons([{
|
|
11176
|
-
couponCode: d.couponCode ?? "",
|
|
11177
|
-
discountId: d.id,
|
|
11178
|
-
name: d.name,
|
|
11179
|
-
value: d.value,
|
|
11180
|
-
type: d.discountType,
|
|
11181
|
-
canCombine: !!d.canCombineWithOtherDiscounts,
|
|
11182
|
-
calculatedDiscount: 0,
|
|
11183
|
-
rewardProductIds: [],
|
|
11184
|
-
rewardLines: [],
|
|
11185
|
-
isAutomatic: d.isAutomatic ?? false
|
|
11186
|
-
}]);
|
|
11142
|
+
setCoupons([{ couponCode: d.couponCode ?? "", discountId: d.id, name: d.name, value: d.value, type: d.discountType, canCombine: !!d.canCombineWithOtherDiscounts, calculatedDiscount: 0, rewardProductIds: [], rewardLines: [], isAutomatic: d.isAutomatic ?? false }]);
|
|
11187
11143
|
}
|
|
11188
11144
|
}
|
|
11189
11145
|
}
|
|
@@ -11194,12 +11150,7 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
11194
11150
|
const pid = Number(it.productId);
|
|
11195
11151
|
const p = it.product;
|
|
11196
11152
|
const unit = Number(it.unitPrice ?? 0);
|
|
11197
|
-
productCache.current.set(pid, {
|
|
11198
|
-
id: pid,
|
|
11199
|
-
name: p?.name ?? null,
|
|
11200
|
-
sku: p?.sku ?? null,
|
|
11201
|
-
price: Number.isFinite(unit) ? unit : 0
|
|
11202
|
-
});
|
|
11153
|
+
productCache.current.set(pid, { id: pid, name: p?.name ?? null, sku: p?.sku ?? null, price: Number.isFinite(unit) ? unit : 0 });
|
|
11203
11154
|
}
|
|
11204
11155
|
} catch {
|
|
11205
11156
|
if (!cancelled) setOrderLoadError("Failed to load order");
|
|
@@ -11216,23 +11167,17 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
11216
11167
|
(async () => {
|
|
11217
11168
|
setCustomersLoading(true);
|
|
11218
11169
|
try {
|
|
11219
|
-
const res = await fetch(
|
|
11220
|
-
"/api/vendor_customers?limit=500&sortField=createdAt&sortOrder=asc"
|
|
11221
|
-
);
|
|
11170
|
+
const res = await fetch("/api/vendor_customers?limit=500&sortField=createdAt&sortOrder=asc");
|
|
11222
11171
|
if (!res.ok) {
|
|
11223
11172
|
if (!cancelled) setCustomers([]);
|
|
11224
11173
|
return;
|
|
11225
11174
|
}
|
|
11226
11175
|
const data = await res.json();
|
|
11227
11176
|
const rows = (Array.isArray(data?.data) ? data.data : []).map((row) => {
|
|
11228
|
-
const id = Number(row.
|
|
11177
|
+
const id = Number(row.id);
|
|
11229
11178
|
if (!Number.isFinite(id)) return null;
|
|
11230
|
-
|
|
11231
|
-
|
|
11232
|
-
name: row.name ?? row.contact?.name ?? null,
|
|
11233
|
-
email: row.email ?? row.contact?.email ?? null,
|
|
11234
|
-
phone: row.phone ?? row.contact?.phone ?? null
|
|
11235
|
-
};
|
|
11179
|
+
const rawCustomerId = Number(row.customerId);
|
|
11180
|
+
return { id, customerId: Number.isFinite(rawCustomerId) && rawCustomerId > 0 ? rawCustomerId : null, name: row.name ?? null, email: row.email ?? null, phone: row.phone ?? null };
|
|
11236
11181
|
}).filter((r) => r != null);
|
|
11237
11182
|
if (!cancelled) setCustomers(rows);
|
|
11238
11183
|
} catch {
|
|
@@ -11245,6 +11190,140 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
11245
11190
|
cancelled = true;
|
|
11246
11191
|
};
|
|
11247
11192
|
}, []);
|
|
11193
|
+
async function loadCustomerContacts(customerId) {
|
|
11194
|
+
setCustomerContactsLoading(true);
|
|
11195
|
+
setCustomerContacts([]);
|
|
11196
|
+
setSubContactId(null);
|
|
11197
|
+
setSubContactName("");
|
|
11198
|
+
setSubContactEmail("");
|
|
11199
|
+
setSubContactPhone("");
|
|
11200
|
+
try {
|
|
11201
|
+
const res = await fetch(`/api/customer_contacts?customerId=${customerId}&limit=200&sortField=id&sortOrder=asc`);
|
|
11202
|
+
if (!res.ok) return;
|
|
11203
|
+
const data = await res.json();
|
|
11204
|
+
const rows = (Array.isArray(data?.data) ? data.data : Array.isArray(data) ? data : []).filter((r) => r.contact && Number.isFinite(Number(r.contactId)));
|
|
11205
|
+
setCustomerContacts(rows);
|
|
11206
|
+
} catch {
|
|
11207
|
+
setCustomerContacts([]);
|
|
11208
|
+
} finally {
|
|
11209
|
+
setCustomerContactsLoading(false);
|
|
11210
|
+
}
|
|
11211
|
+
}
|
|
11212
|
+
async function loadContactAddressesByEmail(email) {
|
|
11213
|
+
try {
|
|
11214
|
+
const res = await fetch(`/api/contacts?search=${encodeURIComponent(email)}&limit=5`);
|
|
11215
|
+
if (!res.ok) {
|
|
11216
|
+
setBillingAddress({ ...emptyAddress });
|
|
11217
|
+
setShippingAddress({ ...emptyAddress });
|
|
11218
|
+
return;
|
|
11219
|
+
}
|
|
11220
|
+
const data = await res.json();
|
|
11221
|
+
const match = data.data?.find((c) => c.email?.toLowerCase() === email.toLowerCase());
|
|
11222
|
+
if (!match) {
|
|
11223
|
+
setBillingAddress({ ...emptyAddress });
|
|
11224
|
+
setShippingAddress({ ...emptyAddress });
|
|
11225
|
+
return;
|
|
11226
|
+
}
|
|
11227
|
+
await loadContactAddresses(match.id);
|
|
11228
|
+
} catch {
|
|
11229
|
+
setBillingAddress({ ...emptyAddress });
|
|
11230
|
+
setShippingAddress({ ...emptyAddress });
|
|
11231
|
+
}
|
|
11232
|
+
}
|
|
11233
|
+
async function loadContactAddresses(cid) {
|
|
11234
|
+
try {
|
|
11235
|
+
const res = await fetch(`/api/order_addresses?contactId=${cid}&limit=100&sortField=createdAt&sortOrder=desc`);
|
|
11236
|
+
if (!res.ok) return;
|
|
11237
|
+
const body = await res.json();
|
|
11238
|
+
const rows = Array.isArray(body) ? body : Array.isArray(body?.data) ? body.data : [];
|
|
11239
|
+
const billing = rows.find((a) => a.addressType === "billing_address");
|
|
11240
|
+
const shipping = rows.find((a) => a.addressType === "shipping_address");
|
|
11241
|
+
if (billing) setBillingAddress(mapAddressToForm(billing));
|
|
11242
|
+
else setBillingAddress({ ...emptyAddress });
|
|
11243
|
+
if (sameAsBilling) setShippingAddress(billing ? mapAddressToForm(billing) : { ...emptyAddress });
|
|
11244
|
+
else setShippingAddress(shipping ? mapAddressToForm(shipping) : { ...emptyAddress });
|
|
11245
|
+
} catch {
|
|
11246
|
+
setBillingAddress(emptyAddress);
|
|
11247
|
+
setShippingAddress(emptyAddress);
|
|
11248
|
+
}
|
|
11249
|
+
}
|
|
11250
|
+
function handleCustomerSelect(value) {
|
|
11251
|
+
if (value === MANUAL_CUSTOMER) {
|
|
11252
|
+
setContactId(null);
|
|
11253
|
+
setSelectedCustomerId(null);
|
|
11254
|
+
setCustomerContacts([]);
|
|
11255
|
+
setSubContactId(null);
|
|
11256
|
+
setSubContactName("");
|
|
11257
|
+
setSubContactEmail("");
|
|
11258
|
+
setSubContactPhone("");
|
|
11259
|
+
setBillingAddress({ ...emptyAddress });
|
|
11260
|
+
setShippingAddress({ ...emptyAddress });
|
|
11261
|
+
return;
|
|
11262
|
+
}
|
|
11263
|
+
const id = Number(value);
|
|
11264
|
+
if (!Number.isFinite(id)) return;
|
|
11265
|
+
const customer = customers.find((c) => c.id === id);
|
|
11266
|
+
if (!customer) return;
|
|
11267
|
+
setContactId(id);
|
|
11268
|
+
setSelectedCustomerId(customer.customerId ?? null);
|
|
11269
|
+
setContactName(customer.name ?? "");
|
|
11270
|
+
setContactEmail(customer.email ?? "");
|
|
11271
|
+
setContactPhone(customer.phone ?? "");
|
|
11272
|
+
setSubContactId(null);
|
|
11273
|
+
setSubContactName("");
|
|
11274
|
+
setSubContactEmail("");
|
|
11275
|
+
setSubContactPhone("");
|
|
11276
|
+
setPlaceForSomeoneElse(false);
|
|
11277
|
+
if (customer.customerId != null) loadCustomerContacts(customer.customerId);
|
|
11278
|
+
if (customer.email) {
|
|
11279
|
+
loadContactAddressesByEmail(customer.email);
|
|
11280
|
+
} else {
|
|
11281
|
+
setBillingAddress({ ...emptyAddress });
|
|
11282
|
+
setShippingAddress({ ...emptyAddress });
|
|
11283
|
+
}
|
|
11284
|
+
}
|
|
11285
|
+
function handleSubContactSelect(value) {
|
|
11286
|
+
if (value === MANUAL_CONTACT) {
|
|
11287
|
+
setSubContactId(null);
|
|
11288
|
+
setSubContactName("");
|
|
11289
|
+
setSubContactEmail("");
|
|
11290
|
+
setSubContactPhone("");
|
|
11291
|
+
setBillingAddress({ ...emptyAddress });
|
|
11292
|
+
setShippingAddress({ ...emptyAddress });
|
|
11293
|
+
return;
|
|
11294
|
+
}
|
|
11295
|
+
const cid = Number(value);
|
|
11296
|
+
if (!Number.isFinite(cid)) return;
|
|
11297
|
+
const row = customerContacts.find((r) => r.contactId === cid);
|
|
11298
|
+
if (!row) return;
|
|
11299
|
+
setSubContactId(cid);
|
|
11300
|
+
setSubContactName(row.contact.name ?? "");
|
|
11301
|
+
setSubContactEmail(row.contact.email ?? "");
|
|
11302
|
+
setSubContactPhone(row.contact.phone ?? "");
|
|
11303
|
+
loadContactAddresses(cid);
|
|
11304
|
+
}
|
|
11305
|
+
function handlePlaceForSomeoneElseToggle(checked) {
|
|
11306
|
+
setPlaceForSomeoneElse(checked);
|
|
11307
|
+
if (checked) {
|
|
11308
|
+
setBillingAddress({ ...emptyAddress });
|
|
11309
|
+
setShippingAddress({ ...emptyAddress });
|
|
11310
|
+
setSubContactId(null);
|
|
11311
|
+
setSubContactName("");
|
|
11312
|
+
setSubContactEmail("");
|
|
11313
|
+
setSubContactPhone("");
|
|
11314
|
+
return;
|
|
11315
|
+
}
|
|
11316
|
+
setSubContactId(null);
|
|
11317
|
+
setSubContactName("");
|
|
11318
|
+
setSubContactEmail("");
|
|
11319
|
+
setSubContactPhone("");
|
|
11320
|
+
if (contactEmail) {
|
|
11321
|
+
loadContactAddressesByEmail(contactEmail);
|
|
11322
|
+
} else {
|
|
11323
|
+
setBillingAddress({ ...emptyAddress });
|
|
11324
|
+
setShippingAddress({ ...emptyAddress });
|
|
11325
|
+
}
|
|
11326
|
+
}
|
|
11248
11327
|
const cartProductIds = useMemo6(() => new Set(lines.map((l) => l.productId)), [lines]);
|
|
11249
11328
|
useEffect25(() => {
|
|
11250
11329
|
const q = productQuery.trim();
|
|
@@ -11253,13 +11332,7 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
11253
11332
|
(async () => {
|
|
11254
11333
|
setHitsLoading(true);
|
|
11255
11334
|
try {
|
|
11256
|
-
const params = new URLSearchParams({
|
|
11257
|
-
limit: "50",
|
|
11258
|
-
page: "1",
|
|
11259
|
-
sortField: "name",
|
|
11260
|
-
sortOrder: "asc",
|
|
11261
|
-
status: "available"
|
|
11262
|
-
});
|
|
11335
|
+
const params = new URLSearchParams({ limit: "50", page: "1", sortField: "name", sortOrder: "asc", status: "available" });
|
|
11263
11336
|
if (q.length >= 2) params.set("search", q);
|
|
11264
11337
|
const res = await fetch(`/api/products?${params}`);
|
|
11265
11338
|
if (!res.ok) {
|
|
@@ -11340,53 +11413,34 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
11340
11413
|
const res = await fetch("/api/discounts/validate-coupon", {
|
|
11341
11414
|
method: "POST",
|
|
11342
11415
|
headers: { "Content-Type": "application/json" },
|
|
11343
|
-
body: JSON.stringify({
|
|
11344
|
-
discountId: coupon.discountId,
|
|
11345
|
-
isAutomatic: true,
|
|
11346
|
-
orderLines: nonRewardLines.map((l) => ({ productId: l.productId, quantity: l.quantity })),
|
|
11347
|
-
currency,
|
|
11348
|
-
contactId
|
|
11349
|
-
})
|
|
11416
|
+
body: JSON.stringify({ discountId: coupon.discountId, isAutomatic: true, orderLines: nonRewardLines.map((l) => ({ productId: l.productId, quantity: l.quantity })), currency, contactId })
|
|
11350
11417
|
});
|
|
11351
11418
|
if (cancelled) return;
|
|
11352
11419
|
const data = await res.json();
|
|
11353
11420
|
if (!data.valid) {
|
|
11354
11421
|
const rewardPids = new Set(coupon.rewardLines.map((r) => r.productId));
|
|
11355
11422
|
setCoupons((prev) => prev.filter((c) => c.discountId !== coupon.discountId));
|
|
11356
|
-
setLines(
|
|
11357
|
-
(
|
|
11358
|
-
|
|
11359
|
-
|
|
11360
|
-
|
|
11361
|
-
|
|
11362
|
-
|
|
11363
|
-
}).filter((l) => l !== null)
|
|
11364
|
-
);
|
|
11423
|
+
setLines((prev) => prev.map((l) => {
|
|
11424
|
+
if (!rewardPids.has(l.productId)) return l;
|
|
11425
|
+
const rewardLine = coupon.rewardLines.find((r) => r.productId === l.productId);
|
|
11426
|
+
if (!rewardLine) return l;
|
|
11427
|
+
const newQty = l.quantity - rewardLine.quantity;
|
|
11428
|
+
return newQty > 0 ? { ...l, quantity: newQty } : null;
|
|
11429
|
+
}).filter((l) => l !== null));
|
|
11365
11430
|
rewardPids.forEach((pid) => rewardProductIds.current.delete(pid));
|
|
11366
11431
|
rewardInjectedForDiscount.current.delete(coupon.discountId);
|
|
11367
11432
|
} else {
|
|
11368
11433
|
const newRewardLines = data.discount.rewardLines ?? [];
|
|
11369
|
-
setCoupons((prev) => prev.map(
|
|
11370
|
-
(c) => c.discountId !== coupon.discountId ? c : {
|
|
11371
|
-
...c,
|
|
11372
|
-
calculatedDiscount: data.discount.calculatedDiscount,
|
|
11373
|
-
rewardProductIds: data.discount.rewardProductIds ?? [],
|
|
11374
|
-
rewardLines: newRewardLines
|
|
11375
|
-
}
|
|
11376
|
-
));
|
|
11434
|
+
setCoupons((prev) => prev.map((c) => c.discountId !== coupon.discountId ? c : { ...c, calculatedDiscount: data.discount.calculatedDiscount, rewardProductIds: data.discount.rewardProductIds ?? [], rewardLines: newRewardLines }));
|
|
11377
11435
|
setLines((prev) => {
|
|
11378
11436
|
let next = [...prev];
|
|
11379
11437
|
for (const rewardLine of newRewardLines) {
|
|
11380
11438
|
const idx = next.findIndex((l) => l.productId === rewardLine.productId);
|
|
11381
|
-
if (idx >= 0 && rewardProductIds.current.has(rewardLine.productId)) {
|
|
11382
|
-
next[idx] = { ...next[idx], quantity: rewardLine.quantity };
|
|
11383
|
-
}
|
|
11439
|
+
if (idx >= 0 && rewardProductIds.current.has(rewardLine.productId)) next[idx] = { ...next[idx], quantity: rewardLine.quantity };
|
|
11384
11440
|
}
|
|
11385
11441
|
const newRewardPids = new Set(newRewardLines.map((r) => r.productId));
|
|
11386
11442
|
const oldRewardPids = new Set(coupon.rewardLines.map((r) => r.productId));
|
|
11387
|
-
next = next.filter(
|
|
11388
|
-
(l) => !oldRewardPids.has(l.productId) || newRewardPids.has(l.productId)
|
|
11389
|
-
);
|
|
11443
|
+
next = next.filter((l) => !oldRewardPids.has(l.productId) || newRewardPids.has(l.productId));
|
|
11390
11444
|
return next;
|
|
11391
11445
|
});
|
|
11392
11446
|
}
|
|
@@ -11401,126 +11455,28 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
11401
11455
|
lines.filter((l) => !rewardProductIds.current.has(l.productId)).map((l) => `${l.productId}:${l.quantity}`).join(","),
|
|
11402
11456
|
coupons.filter((c) => c.isAutomatic).map((c) => c.discountId).join(",")
|
|
11403
11457
|
]);
|
|
11404
|
-
async function handleApplyCoupon() {
|
|
11405
|
-
const code = couponInput.trim().toUpperCase();
|
|
11406
|
-
if (!code) return;
|
|
11407
|
-
if (coupons.some((c) => c.couponCode === code)) {
|
|
11408
|
-
setCouponError("Coupon already applied");
|
|
11409
|
-
return;
|
|
11410
|
-
}
|
|
11411
|
-
if (coupons.length > 0 && !coupons[0].canCombine) {
|
|
11412
|
-
setCouponError("Applied coupon cannot be combined with other discounts");
|
|
11413
|
-
return;
|
|
11414
|
-
}
|
|
11415
|
-
setCouponError(null);
|
|
11416
|
-
setCouponLoading(true);
|
|
11417
|
-
try {
|
|
11418
|
-
const orderLines = lines.map((l) => ({ productId: l.productId, quantity: l.quantity }));
|
|
11419
|
-
const res = await fetch("/api/discounts/validate-coupon", {
|
|
11420
|
-
method: "POST",
|
|
11421
|
-
headers: { "Content-Type": "application/json" },
|
|
11422
|
-
body: JSON.stringify({ couponCode: code, orderLines, currency, contactId })
|
|
11423
|
-
});
|
|
11424
|
-
const data = await res.json();
|
|
11425
|
-
if (!res.ok || !data.valid) {
|
|
11426
|
-
setCouponError(data.error ?? "Invalid coupon");
|
|
11427
|
-
return;
|
|
11428
|
-
}
|
|
11429
|
-
const d = data.discount;
|
|
11430
|
-
if (!d.canCombineWithOtherDiscounts && coupons.length > 0) {
|
|
11431
|
-
setCouponError("This coupon cannot be combined with other discounts");
|
|
11432
|
-
return;
|
|
11433
|
-
}
|
|
11434
|
-
setCoupons((prev) => [...prev, {
|
|
11435
|
-
couponCode: code,
|
|
11436
|
-
discountId: d.id,
|
|
11437
|
-
name: d.name,
|
|
11438
|
-
value: d.value,
|
|
11439
|
-
type: d.discountType,
|
|
11440
|
-
canCombine: d.canCombineWithOtherDiscounts,
|
|
11441
|
-
calculatedDiscount: d.calculatedDiscount,
|
|
11442
|
-
rewardProductIds: d.rewardProductIds ?? [],
|
|
11443
|
-
rewardLines: d.rewardLines ?? [],
|
|
11444
|
-
isAutomatic: false
|
|
11445
|
-
}]);
|
|
11446
|
-
setCouponInput("");
|
|
11447
|
-
toast5.success(`Coupon "${code}" applied`);
|
|
11448
|
-
} catch {
|
|
11449
|
-
setCouponError("Failed to validate coupon");
|
|
11450
|
-
} finally {
|
|
11451
|
-
setCouponLoading(false);
|
|
11452
|
-
}
|
|
11453
|
-
}
|
|
11454
11458
|
function handleRemoveCoupon(couponCode) {
|
|
11455
11459
|
const coupon = coupons.find((c) => c.couponCode === couponCode);
|
|
11456
11460
|
if (coupon) {
|
|
11457
|
-
const
|
|
11458
|
-
const rewardKeyForDiscount = new Set(
|
|
11459
|
-
(coupon.rewardLines ?? []).map((r) => `reward-${r.productId}-${coupon.discountId}`)
|
|
11460
|
-
);
|
|
11461
|
+
const rewardKeyForDiscount = new Set((coupon.rewardLines ?? []).map((r) => `reward-${r.productId}-${coupon.discountId}`));
|
|
11461
11462
|
if (rewardKeyForDiscount.size > 0) {
|
|
11462
|
-
setLines(
|
|
11463
|
-
(prev) => prev.filter((l) => !rewardKeyForDiscount.has(l.key))
|
|
11464
|
-
);
|
|
11463
|
+
setLines((prev) => prev.filter((l) => !rewardKeyForDiscount.has(l.key)));
|
|
11465
11464
|
coupon.rewardLines.forEach((r) => {
|
|
11466
|
-
const stillRewardByOther = coupons.some(
|
|
11467
|
-
(c) => c.couponCode !== couponCode && c.rewardLines.some((rl) => rl.productId === r.productId)
|
|
11468
|
-
);
|
|
11465
|
+
const stillRewardByOther = coupons.some((c) => c.couponCode !== couponCode && c.rewardLines.some((rl) => rl.productId === r.productId));
|
|
11469
11466
|
if (!stillRewardByOther) rewardProductIds.current.delete(r.productId);
|
|
11470
11467
|
});
|
|
11471
|
-
}
|
|
11472
|
-
rewardInjectedForDiscount.current.delete(coupon.discountId);
|
|
11473
|
-
}
|
|
11474
|
-
setCoupons((prev) => prev.filter((c) => c.couponCode !== couponCode));
|
|
11475
|
-
setCouponError(null);
|
|
11476
|
-
}
|
|
11477
|
-
function mapAddressToForm(addr) {
|
|
11478
|
-
return {
|
|
11479
|
-
line1: addr.line1 ?? "",
|
|
11480
|
-
line2: addr.line2 ?? "",
|
|
11481
|
-
city: addr.city ?? "",
|
|
11482
|
-
state: addr.state ?? "",
|
|
11483
|
-
country: addr.country ?? "",
|
|
11484
|
-
postalCode: addr.postalCode ?? ""
|
|
11485
|
-
};
|
|
11486
|
-
}
|
|
11487
|
-
function updateAddress(type, field, value) {
|
|
11488
|
-
if (type === "billing") setBillingAddress((prev) => ({ ...prev, [field]: value }));
|
|
11489
|
-
else setShippingAddress((prev) => ({ ...prev, [field]: value }));
|
|
11490
|
-
}
|
|
11491
|
-
function handleCustomerSelect(value) {
|
|
11492
|
-
if (value === MANUAL_CUSTOMER) {
|
|
11493
|
-
setContactId(null);
|
|
11494
|
-
return;
|
|
11495
|
-
}
|
|
11496
|
-
const id = Number(value);
|
|
11497
|
-
if (!Number.isFinite(id)) return;
|
|
11498
|
-
const customer = customers.find((c) => c.id === id);
|
|
11499
|
-
if (!customer) return;
|
|
11500
|
-
setContactId(id);
|
|
11501
|
-
setContactName(customer.name ?? "");
|
|
11502
|
-
setContactEmail(customer.email ?? "");
|
|
11503
|
-
setContactPhone(customer.phone ?? "");
|
|
11504
|
-
loadCustomerAddresses(id);
|
|
11505
|
-
}
|
|
11506
|
-
async function loadCustomerAddresses(customerId) {
|
|
11507
|
-
try {
|
|
11508
|
-
const res = await fetch(`/api/order_addresses?contactId=${customerId}&limit=100&sortField=createdAt&sortOrder=desc`);
|
|
11509
|
-
if (!res.ok) return;
|
|
11510
|
-
const body = await res.json();
|
|
11511
|
-
const rows = Array.isArray(body) ? body : Array.isArray(body?.data) ? body.data : [];
|
|
11512
|
-
const billing = rows.find((a) => a.addressType === "billing_address");
|
|
11513
|
-
const shipping = rows.find((a) => a.addressType === "shipping_address");
|
|
11514
|
-
if (billing) setBillingAddress(mapAddressToForm(billing));
|
|
11515
|
-
else setBillingAddress({ ...emptyAddress });
|
|
11516
|
-
if (sameAsBilling) setShippingAddress(billing ? mapAddressToForm(billing) : { ...emptyAddress });
|
|
11517
|
-
else setShippingAddress(shipping ? mapAddressToForm(shipping) : { ...emptyAddress });
|
|
11518
|
-
} catch {
|
|
11519
|
-
setBillingAddress(emptyAddress);
|
|
11520
|
-
setShippingAddress(emptyAddress);
|
|
11468
|
+
}
|
|
11469
|
+
rewardInjectedForDiscount.current.delete(coupon.discountId);
|
|
11521
11470
|
}
|
|
11471
|
+
setCoupons((prev) => prev.filter((c) => c.couponCode !== couponCode));
|
|
11472
|
+
}
|
|
11473
|
+
function mapAddressToForm(addr) {
|
|
11474
|
+
return { line1: addr.line1 ?? "", line2: addr.line2 ?? "", city: addr.city ?? "", state: addr.state ?? "", country: addr.country ?? "", postalCode: addr.postalCode ?? "" };
|
|
11475
|
+
}
|
|
11476
|
+
function updateAddress(type, field, value) {
|
|
11477
|
+
if (type === "billing") setBillingAddress((prev) => ({ ...prev, [field]: value }));
|
|
11478
|
+
else setShippingAddress((prev) => ({ ...prev, [field]: value }));
|
|
11522
11479
|
}
|
|
11523
|
-
const customerSelectValue = contactId != null ? String(contactId) : MANUAL_CUSTOMER;
|
|
11524
11480
|
function toggleStaged(id) {
|
|
11525
11481
|
setStagedIds((prev) => {
|
|
11526
11482
|
const next = new Set(prev);
|
|
@@ -11557,9 +11513,7 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
11557
11513
|
if (idx >= 0) {
|
|
11558
11514
|
const row = next[idx];
|
|
11559
11515
|
next[idx] = { ...row, quantity: row.quantity + 1 };
|
|
11560
|
-
} else {
|
|
11561
|
-
next.push({ key: String(id), productId: id, label: hit.name ?? `Product #${id}`, sku: hit.sku, quantity: 1 });
|
|
11562
|
-
}
|
|
11516
|
+
} else next.push({ key: String(id), productId: id, label: hit.name ?? `Product #${id}`, sku: hit.sku, quantity: 1 });
|
|
11563
11517
|
}
|
|
11564
11518
|
return next;
|
|
11565
11519
|
});
|
|
@@ -11588,9 +11542,12 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
11588
11542
|
}, [preview]);
|
|
11589
11543
|
async function handleSubmit(e) {
|
|
11590
11544
|
e.preventDefault();
|
|
11591
|
-
const
|
|
11592
|
-
|
|
11593
|
-
|
|
11545
|
+
const effectiveEmail = placeForSomeoneElse ? subContactEmail.trim() : contactEmail.trim();
|
|
11546
|
+
const effectiveName = placeForSomeoneElse ? subContactName.trim() : contactName.trim();
|
|
11547
|
+
const effectivePhone = placeForSomeoneElse ? subContactPhone.trim() : contactPhone.trim();
|
|
11548
|
+
const effectiveContactId = placeForSomeoneElse ? subContactId : contactId;
|
|
11549
|
+
if (effectiveContactId == null && !effectiveEmail) {
|
|
11550
|
+
toast5.error(placeForSomeoneElse ? "Enter the contact's email address" : "Select a customer or enter an email address");
|
|
11594
11551
|
return;
|
|
11595
11552
|
}
|
|
11596
11553
|
if (lines.length === 0) {
|
|
@@ -11604,46 +11561,67 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
11604
11561
|
}
|
|
11605
11562
|
setSubmitting(true);
|
|
11606
11563
|
try {
|
|
11564
|
+
let resolvedContactId = placeForSomeoneElse ? subContactId : null;
|
|
11565
|
+
if (!resolvedContactId && effectiveEmail) {
|
|
11566
|
+
try {
|
|
11567
|
+
const res2 = await fetch(`/api/contacts?search=${encodeURIComponent(effectiveEmail)}&limit=1`);
|
|
11568
|
+
if (res2.ok) {
|
|
11569
|
+
const data = await res2.json();
|
|
11570
|
+
const match = data.data?.find((c) => c.email?.toLowerCase() === effectiveEmail.toLowerCase());
|
|
11571
|
+
if (match) resolvedContactId = match.id;
|
|
11572
|
+
}
|
|
11573
|
+
} catch {
|
|
11574
|
+
}
|
|
11575
|
+
}
|
|
11576
|
+
let orderContactId = resolvedContactId;
|
|
11577
|
+
if (placeForSomeoneElse) {
|
|
11578
|
+
if (contactEmail) {
|
|
11579
|
+
try {
|
|
11580
|
+
const res2 = await fetch(`/api/contacts?search=${encodeURIComponent(contactEmail)}&limit=5`);
|
|
11581
|
+
if (res2.ok) {
|
|
11582
|
+
const data = await res2.json();
|
|
11583
|
+
const match = data.data?.find((c) => c.email?.toLowerCase() === contactEmail.toLowerCase());
|
|
11584
|
+
if (match) orderContactId = match.id;
|
|
11585
|
+
}
|
|
11586
|
+
} catch {
|
|
11587
|
+
}
|
|
11588
|
+
}
|
|
11589
|
+
}
|
|
11607
11590
|
const payload = {
|
|
11608
11591
|
status,
|
|
11609
11592
|
currency,
|
|
11610
|
-
"contact.name":
|
|
11611
|
-
"contact.email":
|
|
11612
|
-
"contact.phone":
|
|
11593
|
+
"contact.name": effectiveName || effectiveEmail.split("@")[0] || "Customer",
|
|
11594
|
+
"contact.email": effectiveEmail || "",
|
|
11595
|
+
"contact.phone": effectivePhone || null,
|
|
11613
11596
|
billingAddress,
|
|
11614
11597
|
shippingAddress: sameAsBilling ? billingAddress : shippingAddress,
|
|
11615
11598
|
orderLines: lines.map((l) => {
|
|
11616
11599
|
const calc = preview?.lines.find((pl) => pl.productId === l.productId);
|
|
11617
|
-
return {
|
|
11618
|
-
productId: l.productId,
|
|
11619
|
-
quantity: l.quantity,
|
|
11620
|
-
unitPrice: calc?.unitPrice ?? productCache.current.get(l.productId)?.price ?? 0
|
|
11621
|
-
};
|
|
11600
|
+
return { productId: l.productId, quantity: l.quantity, unitPrice: calc?.unitPrice ?? productCache.current.get(l.productId)?.price ?? 0 };
|
|
11622
11601
|
})
|
|
11623
11602
|
};
|
|
11624
|
-
if (
|
|
11603
|
+
if (orderContactId != null) payload.contactId = orderContactId;
|
|
11604
|
+
if (!placeForSomeoneElse && contactId != null) payload.customerId = contactId;
|
|
11625
11605
|
if (coupons.length > 0) payload.discountId = coupons[0].discountId;
|
|
11626
11606
|
const url = editOrderId ? `/api/orders/${editOrderId}` : "/api/orders";
|
|
11627
11607
|
const method = editOrderId ? "PUT" : "POST";
|
|
11628
|
-
const res = await fetch(url, {
|
|
11629
|
-
method,
|
|
11630
|
-
headers: { "Content-Type": "application/json" },
|
|
11631
|
-
body: JSON.stringify(payload)
|
|
11632
|
-
});
|
|
11608
|
+
const res = await fetch(url, { method, headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) });
|
|
11633
11609
|
const body = await res.json().catch(() => ({}));
|
|
11634
11610
|
if (!res.ok) {
|
|
11635
11611
|
toast5.error(body.error ?? (editOrderId ? "Failed to update order" : "Failed to create order"));
|
|
11636
11612
|
return;
|
|
11637
11613
|
}
|
|
11638
|
-
if (
|
|
11639
|
-
const
|
|
11614
|
+
if (resolvedContactId == null) {
|
|
11615
|
+
const serverContactId = body.contactId;
|
|
11616
|
+
if (serverContactId != null && Number.isFinite(serverContactId)) {
|
|
11617
|
+
resolvedContactId = serverContactId;
|
|
11618
|
+
}
|
|
11619
|
+
}
|
|
11620
|
+
if (editOrderId && effectiveContactId != null) {
|
|
11621
|
+
const cr = await fetch(`/api/contacts/${effectiveContactId}`, {
|
|
11640
11622
|
method: "PUT",
|
|
11641
11623
|
headers: { "Content-Type": "application/json" },
|
|
11642
|
-
body: JSON.stringify({
|
|
11643
|
-
name: contactName.trim() || email.split("@")[0] || "Customer",
|
|
11644
|
-
email: email || void 0,
|
|
11645
|
-
phone: contactPhone.trim() || null
|
|
11646
|
-
})
|
|
11624
|
+
body: JSON.stringify({ name: effectiveName || effectiveEmail.split("@")[0] || "Customer", email: effectiveEmail || void 0, phone: effectivePhone || null })
|
|
11647
11625
|
});
|
|
11648
11626
|
if (!cr.ok) {
|
|
11649
11627
|
const cb = await cr.json().catch(() => ({}));
|
|
@@ -11655,6 +11633,25 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
11655
11633
|
router.push(withAdminListFromParam(listReturnUrl, `/admin/orders/${editOrderId}/view`));
|
|
11656
11634
|
return;
|
|
11657
11635
|
}
|
|
11636
|
+
if (selectedCustomerId != null && resolvedContactId != null) {
|
|
11637
|
+
try {
|
|
11638
|
+
const linkCheck = await fetch(`/api/customer_contacts?customerId=${selectedCustomerId}&limit=200`);
|
|
11639
|
+
if (linkCheck.ok) {
|
|
11640
|
+
const linkData = await linkCheck.json();
|
|
11641
|
+
const existingRows = Array.isArray(linkData?.data) ? linkData.data : Array.isArray(linkData) ? linkData : [];
|
|
11642
|
+
const alreadyLinked = existingRows.some((r) => Number(r.contactId) === resolvedContactId);
|
|
11643
|
+
if (!alreadyLinked) {
|
|
11644
|
+
await fetch("/api/customer_contacts", {
|
|
11645
|
+
method: "POST",
|
|
11646
|
+
headers: { "Content-Type": "application/json" },
|
|
11647
|
+
body: JSON.stringify({ customerId: selectedCustomerId, contactId: resolvedContactId })
|
|
11648
|
+
});
|
|
11649
|
+
}
|
|
11650
|
+
}
|
|
11651
|
+
} catch {
|
|
11652
|
+
console.warn("[OrderPlacement] Could not link contact to customer");
|
|
11653
|
+
}
|
|
11654
|
+
}
|
|
11658
11655
|
const id = body.id;
|
|
11659
11656
|
toast5.success("Order created");
|
|
11660
11657
|
if (id != null) router.push(withAdminListFromParam(listReturnUrl, `/admin/orders/${id}/view`));
|
|
@@ -11666,6 +11663,8 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
11666
11663
|
}
|
|
11667
11664
|
}
|
|
11668
11665
|
const allVisibleStaged = productHits.length > 0 && productHits.every((p) => stagedIds.has(p.id));
|
|
11666
|
+
const customerSelectValue = contactId != null ? String(contactId) : MANUAL_CUSTOMER;
|
|
11667
|
+
const subContactSelectValue = subContactId != null ? String(subContactId) : MANUAL_CONTACT;
|
|
11669
11668
|
if (editOrderId && loadingOrder) {
|
|
11670
11669
|
return /* @__PURE__ */ jsx55("div", { className: "rounded-lg bg-white shadow-md min-w-0", children: /* @__PURE__ */ jsx55("div", { className: "flex justify-center items-center py-16 text-gray-500 text-sm", children: "Loading order\u2026" }) });
|
|
11671
11670
|
}
|
|
@@ -11710,74 +11709,168 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
11710
11709
|
] }),
|
|
11711
11710
|
/* @__PURE__ */ jsxs44("div", { className: "space-y-2 sm:col-span-2", children: [
|
|
11712
11711
|
/* @__PURE__ */ jsx55(Label3, { htmlFor: "c-email", children: "Email" }),
|
|
11713
|
-
/* @__PURE__ */ jsx55(Input, { id: "c-email", type: "email", value: contactEmail, onChange: (e) => setContactEmail(e.target.value), placeholder: "name@example.com", required: contactId == null })
|
|
11712
|
+
/* @__PURE__ */ jsx55(Input, { id: "c-email", type: "email", value: contactEmail, onChange: (e) => setContactEmail(e.target.value), placeholder: "name@example.com", required: contactId == null && !placeForSomeoneElse })
|
|
11714
11713
|
] }),
|
|
11715
11714
|
/* @__PURE__ */ jsxs44("div", { className: "space-y-2 sm:col-span-2", children: [
|
|
11716
11715
|
/* @__PURE__ */ jsx55(Label3, { htmlFor: "c-phone", children: "Phone" }),
|
|
11717
11716
|
/* @__PURE__ */ jsx55(Input, { id: "c-phone", value: contactPhone, onChange: (e) => setContactPhone(e.target.value), placeholder: "phone number" })
|
|
11717
|
+
] })
|
|
11718
|
+
] }),
|
|
11719
|
+
/* @__PURE__ */ jsxs44("div", { className: "flex items-start gap-3 rounded-lg border border-dashed border-gray-300 bg-gray-50/60 px-4 py-3 mt-1", children: [
|
|
11720
|
+
/* @__PURE__ */ jsx55(
|
|
11721
|
+
Checkbox,
|
|
11722
|
+
{
|
|
11723
|
+
id: "place-for-someone-else",
|
|
11724
|
+
checked: placeForSomeoneElse,
|
|
11725
|
+
onCheckedChange: (checked) => handlePlaceForSomeoneElseToggle(Boolean(checked)),
|
|
11726
|
+
disabled: contactId == null
|
|
11727
|
+
}
|
|
11728
|
+
),
|
|
11729
|
+
/* @__PURE__ */ jsxs44("div", { className: "space-y-0.5", children: [
|
|
11730
|
+
/* @__PURE__ */ jsx55(
|
|
11731
|
+
"label",
|
|
11732
|
+
{
|
|
11733
|
+
htmlFor: "place-for-someone-else",
|
|
11734
|
+
className: `text-sm font-medium leading-none cursor-pointer ${contactId == null ? "text-gray-400" : "text-gray-700"}`,
|
|
11735
|
+
children: "Place this order for someone else"
|
|
11736
|
+
}
|
|
11737
|
+
),
|
|
11738
|
+
/* @__PURE__ */ jsx55("p", { className: "text-xs text-gray-500", children: contactId == null ? "Select a customer above to enable this option." : "Select a linked contact or enter their details below. Addresses will be filled from the selected contact." })
|
|
11739
|
+
] })
|
|
11740
|
+
] }),
|
|
11741
|
+
placeForSomeoneElse && contactId != null && /* @__PURE__ */ jsxs44("div", { className: "rounded-lg border border-blue-200 bg-blue-50/40 p-4 space-y-3", children: [
|
|
11742
|
+
/* @__PURE__ */ jsxs44("div", { className: "flex items-center gap-2", children: [
|
|
11743
|
+
/* @__PURE__ */ jsx55(Users6, { className: "h-4 w-4 text-blue-600" }),
|
|
11744
|
+
/* @__PURE__ */ jsx55("h3", { className: "text-sm font-semibold text-blue-800", children: "Order recipient" })
|
|
11718
11745
|
] }),
|
|
11719
|
-
/* @__PURE__ */
|
|
11720
|
-
/* @__PURE__ */ jsx55(
|
|
11721
|
-
/* @__PURE__ */ jsxs44(
|
|
11722
|
-
|
|
11723
|
-
|
|
11724
|
-
|
|
11725
|
-
|
|
11726
|
-
|
|
11727
|
-
|
|
11728
|
-
|
|
11729
|
-
|
|
11730
|
-
|
|
11731
|
-
|
|
11732
|
-
|
|
11733
|
-
|
|
11734
|
-
|
|
11735
|
-
|
|
11736
|
-
|
|
11737
|
-
|
|
11738
|
-
|
|
11739
|
-
|
|
11740
|
-
|
|
11741
|
-
|
|
11742
|
-
/* @__PURE__ */
|
|
11743
|
-
|
|
11744
|
-
|
|
11745
|
-
|
|
11746
|
+
customerContactsLoading ? /* @__PURE__ */ jsx55("p", { className: "text-xs text-gray-500", children: "Loading contacts\u2026" }) : /* @__PURE__ */ jsxs44("div", { className: "space-y-2", children: [
|
|
11747
|
+
/* @__PURE__ */ jsx55(Label3, { htmlFor: "sc-select", children: "Select contact" }),
|
|
11748
|
+
/* @__PURE__ */ jsxs44(
|
|
11749
|
+
"select",
|
|
11750
|
+
{
|
|
11751
|
+
id: "sc-select",
|
|
11752
|
+
value: subContactSelectValue,
|
|
11753
|
+
onChange: (e) => handleSubContactSelect(e.target.value),
|
|
11754
|
+
className: "w-full h-10 rounded-md border border-gray-300 bg-white px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
11755
|
+
children: [
|
|
11756
|
+
/* @__PURE__ */ jsx55("option", { value: MANUAL_CONTACT, children: "Enter manually (new contact)" }),
|
|
11757
|
+
customerContacts.map((r) => /* @__PURE__ */ jsxs44("option", { value: String(r.contactId), children: [
|
|
11758
|
+
r.contact.name,
|
|
11759
|
+
r.contact.email ? ` \u2014 ${r.contact.email}` : ""
|
|
11760
|
+
] }, r.contactId))
|
|
11761
|
+
]
|
|
11762
|
+
}
|
|
11763
|
+
),
|
|
11764
|
+
customerContacts.length === 0 && /* @__PURE__ */ jsx55("p", { className: "text-xs text-amber-700 bg-amber-50 border border-amber-200 rounded px-3 py-2", children: "No linked contacts found for this customer. Fill in the details below." })
|
|
11765
|
+
] }),
|
|
11766
|
+
/* @__PURE__ */ jsxs44("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3", children: [
|
|
11767
|
+
/* @__PURE__ */ jsxs44("div", { className: "space-y-2 sm:col-span-2", children: [
|
|
11768
|
+
/* @__PURE__ */ jsx55(Label3, { htmlFor: "sc-name", children: "Recipient name" }),
|
|
11769
|
+
/* @__PURE__ */ jsx55(
|
|
11770
|
+
Input,
|
|
11771
|
+
{
|
|
11772
|
+
id: "sc-name",
|
|
11773
|
+
value: subContactName,
|
|
11774
|
+
onChange: (e) => setSubContactName(e.target.value),
|
|
11775
|
+
placeholder: "Full name",
|
|
11776
|
+
readOnly: subContactId != null,
|
|
11777
|
+
className: subContactId != null ? "bg-gray-100 cursor-not-allowed" : ""
|
|
11778
|
+
}
|
|
11779
|
+
)
|
|
11780
|
+
] }),
|
|
11781
|
+
/* @__PURE__ */ jsxs44("div", { className: "space-y-2 sm:col-span-2", children: [
|
|
11782
|
+
/* @__PURE__ */ jsx55(Label3, { htmlFor: "sc-email", children: "Recipient email" }),
|
|
11783
|
+
/* @__PURE__ */ jsx55(
|
|
11784
|
+
Input,
|
|
11785
|
+
{
|
|
11786
|
+
id: "sc-email",
|
|
11787
|
+
type: "email",
|
|
11788
|
+
value: subContactEmail,
|
|
11789
|
+
onChange: (e) => setSubContactEmail(e.target.value),
|
|
11790
|
+
placeholder: "email@example.com",
|
|
11791
|
+
required: placeForSomeoneElse && subContactId == null,
|
|
11792
|
+
readOnly: subContactId != null,
|
|
11793
|
+
className: subContactId != null ? "bg-gray-100 cursor-not-allowed" : ""
|
|
11794
|
+
}
|
|
11795
|
+
)
|
|
11796
|
+
] }),
|
|
11797
|
+
/* @__PURE__ */ jsxs44("div", { className: "space-y-2 sm:col-span-2", children: [
|
|
11798
|
+
/* @__PURE__ */ jsx55(Label3, { htmlFor: "sc-phone", children: "Recipient phone" }),
|
|
11799
|
+
/* @__PURE__ */ jsx55(
|
|
11800
|
+
Input,
|
|
11801
|
+
{
|
|
11802
|
+
id: "sc-phone",
|
|
11803
|
+
value: subContactPhone,
|
|
11804
|
+
onChange: (e) => setSubContactPhone(e.target.value),
|
|
11805
|
+
placeholder: "phone number",
|
|
11806
|
+
readOnly: subContactId != null,
|
|
11807
|
+
className: subContactId != null ? "bg-gray-100 cursor-not-allowed" : ""
|
|
11808
|
+
}
|
|
11809
|
+
)
|
|
11810
|
+
] })
|
|
11811
|
+
] })
|
|
11812
|
+
] }),
|
|
11813
|
+
/* @__PURE__ */ jsxs44("div", { className: "space-y-4 border rounded-lg p-4", children: [
|
|
11814
|
+
/* @__PURE__ */ jsx55("h3", { className: "text-sm font-semibold", children: "Billing Address" }),
|
|
11815
|
+
/* @__PURE__ */ jsxs44("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: [
|
|
11816
|
+
/* @__PURE__ */ jsxs44("div", { className: "space-y-2 md:col-span-2", children: [
|
|
11817
|
+
/* @__PURE__ */ jsx55(Label3, { children: "Address Line 1" }),
|
|
11818
|
+
/* @__PURE__ */ jsx55(Input, { value: billingAddress.line1, onChange: (e) => updateAddress("billing", "line1", e.target.value), placeholder: "Street Address" })
|
|
11819
|
+
] }),
|
|
11820
|
+
/* @__PURE__ */ jsxs44("div", { className: "space-y-2 md:col-span-2", children: [
|
|
11821
|
+
/* @__PURE__ */ jsx55(Label3, { children: "Address Line 2" }),
|
|
11822
|
+
/* @__PURE__ */ jsx55(Input, { value: billingAddress.line2, onChange: (e) => updateAddress("billing", "line2", e.target.value), placeholder: "Apartment, Suite, Floor, etc." })
|
|
11823
|
+
] }),
|
|
11824
|
+
/* @__PURE__ */ jsxs44("div", { className: "space-y-2", children: [
|
|
11825
|
+
/* @__PURE__ */ jsx55(Label3, { children: "City" }),
|
|
11826
|
+
/* @__PURE__ */ jsx55(Input, { value: billingAddress.city, onChange: (e) => updateAddress("billing", "city", e.target.value), placeholder: "City" })
|
|
11827
|
+
] }),
|
|
11828
|
+
/* @__PURE__ */ jsxs44("div", { className: "space-y-2", children: [
|
|
11829
|
+
/* @__PURE__ */ jsx55(Label3, { children: "State" }),
|
|
11830
|
+
/* @__PURE__ */ jsx55(Input, { value: billingAddress.state, onChange: (e) => updateAddress("billing", "state", e.target.value), placeholder: "State" })
|
|
11831
|
+
] }),
|
|
11832
|
+
/* @__PURE__ */ jsxs44("div", { className: "space-y-2", children: [
|
|
11833
|
+
/* @__PURE__ */ jsx55(Label3, { children: "Country" }),
|
|
11834
|
+
/* @__PURE__ */ jsx55(Input, { value: billingAddress.country, onChange: (e) => updateAddress("billing", "country", e.target.value), placeholder: "Country" })
|
|
11835
|
+
] }),
|
|
11836
|
+
/* @__PURE__ */ jsxs44("div", { className: "space-y-2", children: [
|
|
11837
|
+
/* @__PURE__ */ jsx55(Label3, { children: "Postal Code" }),
|
|
11838
|
+
/* @__PURE__ */ jsx55(Input, { value: billingAddress.postalCode, onChange: (e) => updateAddress("billing", "postalCode", e.target.value), placeholder: "Postal Code" })
|
|
11839
|
+
] })
|
|
11840
|
+
] })
|
|
11841
|
+
] }),
|
|
11842
|
+
/* @__PURE__ */ jsxs44("div", { className: "space-y-4 border rounded-lg p-4", children: [
|
|
11843
|
+
/* @__PURE__ */ jsxs44("div", { className: "flex items-center justify-between", children: [
|
|
11844
|
+
/* @__PURE__ */ jsx55("h3", { className: "text-sm font-semibold", children: "Shipping Address" }),
|
|
11845
|
+
/* @__PURE__ */ jsxs44("div", { className: "flex items-center gap-2", children: [
|
|
11846
|
+
/* @__PURE__ */ jsx55(Checkbox, { checked: sameAsBilling, onCheckedChange: (checked) => setSameAsBilling(Boolean(checked)) }),
|
|
11847
|
+
/* @__PURE__ */ jsx55("span", { className: "text-sm text-gray-600", children: "Same as Billing" })
|
|
11746
11848
|
] })
|
|
11747
11849
|
] }),
|
|
11748
|
-
/* @__PURE__ */ jsxs44("div", { className: "
|
|
11749
|
-
/* @__PURE__ */ jsxs44("div", { className: "
|
|
11750
|
-
/* @__PURE__ */ jsx55(
|
|
11751
|
-
/* @__PURE__ */
|
|
11752
|
-
/* @__PURE__ */ jsx55(Checkbox, { checked: sameAsBilling, onCheckedChange: (checked) => setSameAsBilling(Boolean(checked)) }),
|
|
11753
|
-
/* @__PURE__ */ jsx55("span", { className: "text-sm text-gray-600", children: "Same as Billing" })
|
|
11754
|
-
] })
|
|
11850
|
+
!sameAsBilling && /* @__PURE__ */ jsxs44("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: [
|
|
11851
|
+
/* @__PURE__ */ jsxs44("div", { className: "space-y-2 md:col-span-2", children: [
|
|
11852
|
+
/* @__PURE__ */ jsx55(Label3, { children: "Address Line 1" }),
|
|
11853
|
+
/* @__PURE__ */ jsx55(Input, { value: shippingAddress.line1, onChange: (e) => updateAddress("shipping", "line1", e.target.value), placeholder: "Street Address" })
|
|
11755
11854
|
] }),
|
|
11756
|
-
|
|
11757
|
-
/* @__PURE__ */
|
|
11758
|
-
|
|
11759
|
-
|
|
11760
|
-
|
|
11761
|
-
/* @__PURE__ */
|
|
11762
|
-
|
|
11763
|
-
|
|
11764
|
-
|
|
11765
|
-
/* @__PURE__ */
|
|
11766
|
-
|
|
11767
|
-
|
|
11768
|
-
|
|
11769
|
-
/* @__PURE__ */
|
|
11770
|
-
|
|
11771
|
-
|
|
11772
|
-
|
|
11773
|
-
/* @__PURE__ */
|
|
11774
|
-
|
|
11775
|
-
/* @__PURE__ */ jsx55(Input, { value: shippingAddress.country, onChange: (e) => updateAddress("shipping", "country", e.target.value), placeholder: "Country" })
|
|
11776
|
-
] }),
|
|
11777
|
-
/* @__PURE__ */ jsxs44("div", { className: "space-y-2 md:col-span-2", children: [
|
|
11778
|
-
/* @__PURE__ */ jsx55(Label3, { children: "Postal Code" }),
|
|
11779
|
-
/* @__PURE__ */ jsx55(Input, { value: shippingAddress.postalCode, onChange: (e) => updateAddress("shipping", "postalCode", e.target.value), placeholder: "Postal Code" })
|
|
11780
|
-
] })
|
|
11855
|
+
/* @__PURE__ */ jsxs44("div", { className: "space-y-2 md:col-span-2", children: [
|
|
11856
|
+
/* @__PURE__ */ jsx55(Label3, { children: "Address Line 2" }),
|
|
11857
|
+
/* @__PURE__ */ jsx55(Input, { value: shippingAddress.line2, onChange: (e) => updateAddress("shipping", "line2", e.target.value), placeholder: "Apartment, Suite, Floor, etc." })
|
|
11858
|
+
] }),
|
|
11859
|
+
/* @__PURE__ */ jsxs44("div", { className: "space-y-2 md:col-span-2", children: [
|
|
11860
|
+
/* @__PURE__ */ jsx55(Label3, { children: "City" }),
|
|
11861
|
+
/* @__PURE__ */ jsx55(Input, { value: shippingAddress.city, onChange: (e) => updateAddress("shipping", "city", e.target.value), placeholder: "City" })
|
|
11862
|
+
] }),
|
|
11863
|
+
/* @__PURE__ */ jsxs44("div", { className: "space-y-2 md:col-span-2", children: [
|
|
11864
|
+
/* @__PURE__ */ jsx55(Label3, { children: "State" }),
|
|
11865
|
+
/* @__PURE__ */ jsx55(Input, { value: shippingAddress.state, onChange: (e) => updateAddress("shipping", "state", e.target.value), placeholder: "State" })
|
|
11866
|
+
] }),
|
|
11867
|
+
/* @__PURE__ */ jsxs44("div", { className: "space-y-2 md:col-span-2", children: [
|
|
11868
|
+
/* @__PURE__ */ jsx55(Label3, { children: "Country" }),
|
|
11869
|
+
/* @__PURE__ */ jsx55(Input, { value: shippingAddress.country, onChange: (e) => updateAddress("shipping", "country", e.target.value), placeholder: "Country" })
|
|
11870
|
+
] }),
|
|
11871
|
+
/* @__PURE__ */ jsxs44("div", { className: "space-y-2 md:col-span-2", children: [
|
|
11872
|
+
/* @__PURE__ */ jsx55(Label3, { children: "Postal Code" }),
|
|
11873
|
+
/* @__PURE__ */ jsx55(Input, { value: shippingAddress.postalCode, onChange: (e) => updateAddress("shipping", "postalCode", e.target.value), placeholder: "Postal Code" })
|
|
11781
11874
|
] })
|
|
11782
11875
|
] })
|
|
11783
11876
|
] })
|
|
@@ -11875,51 +11968,21 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
11875
11968
|
const active = selectedKey === line.key;
|
|
11876
11969
|
const calc = calcByProductId.get(line.productId);
|
|
11877
11970
|
const isReward = line.key.startsWith("reward-");
|
|
11878
|
-
return /* @__PURE__ */ jsxs44(
|
|
11879
|
-
|
|
11880
|
-
|
|
11881
|
-
|
|
11882
|
-
|
|
11883
|
-
|
|
11884
|
-
|
|
11885
|
-
|
|
11886
|
-
|
|
11887
|
-
|
|
11888
|
-
|
|
11889
|
-
|
|
11890
|
-
|
|
11891
|
-
|
|
11892
|
-
|
|
11893
|
-
min: 1,
|
|
11894
|
-
className: "h-8 w-14 ml-auto text-right",
|
|
11895
|
-
value: line.quantity,
|
|
11896
|
-
onChange: (e) => updateQty(line.key, Number(e.target.value)),
|
|
11897
|
-
onClick: (e) => e.stopPropagation(),
|
|
11898
|
-
readOnly: isReward,
|
|
11899
|
-
disabled: isReward
|
|
11900
|
-
}
|
|
11901
|
-
) }),
|
|
11902
|
-
/* @__PURE__ */ jsx55(TableCell, { className: "align-top text-right text-sm hidden sm:table-cell whitespace-nowrap", children: calc ? formatMoney3(calc.unitPrice, currency) : previewLoading ? "\u2026" : "\u2014" }),
|
|
11903
|
-
/* @__PURE__ */ jsx55(TableCell, { className: "align-top text-right text-sm hidden md:table-cell whitespace-nowrap", children: calc ? formatMoney3(calc.tax, currency) : previewLoading ? "\u2026" : "\u2014" }),
|
|
11904
|
-
/* @__PURE__ */ jsx55(TableCell, { className: "align-top text-right font-medium text-sm whitespace-nowrap", children: calc ? formatMoney3(calc.total, currency) : previewLoading ? "\u2026" : "\u2014" }),
|
|
11905
|
-
/* @__PURE__ */ jsx55(TableCell, { className: "align-top", children: !isReward && /* @__PURE__ */ jsx55(
|
|
11906
|
-
Button,
|
|
11907
|
-
{
|
|
11908
|
-
type: "button",
|
|
11909
|
-
variant: "ghost",
|
|
11910
|
-
size: "icon",
|
|
11911
|
-
className: "h-8 w-8 text-red-600",
|
|
11912
|
-
onClick: (e) => {
|
|
11913
|
-
e.stopPropagation();
|
|
11914
|
-
removeLine(line.key);
|
|
11915
|
-
},
|
|
11916
|
-
children: /* @__PURE__ */ jsx55(Trash25, { className: "h-4 w-4" })
|
|
11917
|
-
}
|
|
11918
|
-
) })
|
|
11919
|
-
]
|
|
11920
|
-
},
|
|
11921
|
-
line.key
|
|
11922
|
-
);
|
|
11971
|
+
return /* @__PURE__ */ jsxs44(TableRow, { className: active ? "bg-blue-50/80 cursor-pointer" : "cursor-pointer", onClick: () => setSelectedKey(line.key), children: [
|
|
11972
|
+
/* @__PURE__ */ jsxs44(TableCell, { className: "align-top min-w-0", children: [
|
|
11973
|
+
/* @__PURE__ */ jsx55("p", { className: "font-medium text-gray-900 break-words", children: line.label }),
|
|
11974
|
+
/* @__PURE__ */ jsx55("p", { className: "text-xs text-gray-500 font-mono", children: line.sku ?? "\u2014" }),
|
|
11975
|
+
isReward && /* @__PURE__ */ jsx55("span", { className: "text-[10px] text-purple-600 font-medium", children: "\u{1F381} Reward" })
|
|
11976
|
+
] }),
|
|
11977
|
+
/* @__PURE__ */ jsx55(TableCell, { className: "align-top text-right", children: /* @__PURE__ */ jsx55(Input, { type: "number", min: 1, className: "h-8 w-14 ml-auto text-right", value: line.quantity, onChange: (e) => updateQty(line.key, Number(e.target.value)), onClick: (e) => e.stopPropagation(), readOnly: isReward, disabled: isReward }) }),
|
|
11978
|
+
/* @__PURE__ */ jsx55(TableCell, { className: "align-top text-right text-sm hidden sm:table-cell whitespace-nowrap", children: calc ? formatMoney3(calc.unitPrice, currency) : previewLoading ? "\u2026" : "\u2014" }),
|
|
11979
|
+
/* @__PURE__ */ jsx55(TableCell, { className: "align-top text-right text-sm hidden md:table-cell whitespace-nowrap", children: calc ? formatMoney3(calc.tax, currency) : previewLoading ? "\u2026" : "\u2014" }),
|
|
11980
|
+
/* @__PURE__ */ jsx55(TableCell, { className: "align-top text-right font-medium text-sm whitespace-nowrap", children: calc ? formatMoney3(calc.total, currency) : previewLoading ? "\u2026" : "\u2014" }),
|
|
11981
|
+
/* @__PURE__ */ jsx55(TableCell, { className: "align-top", children: !isReward && /* @__PURE__ */ jsx55(Button, { type: "button", variant: "ghost", size: "icon", className: "h-8 w-8 text-red-600", onClick: (e) => {
|
|
11982
|
+
e.stopPropagation();
|
|
11983
|
+
removeLine(line.key);
|
|
11984
|
+
}, children: /* @__PURE__ */ jsx55(Trash25, { className: "h-4 w-4" }) }) })
|
|
11985
|
+
] }, line.key);
|
|
11923
11986
|
}) })
|
|
11924
11987
|
] }) }),
|
|
11925
11988
|
/* @__PURE__ */ jsxs44("div", { className: "flex flex-wrap items-center gap-4 justify-between border border-gray-200 rounded-lg p-4 bg-gray-50/70 text-sm", children: [
|
|
@@ -11986,21 +12049,13 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
11986
12049
|
if (!hit) return;
|
|
11987
12050
|
const productHit = hit;
|
|
11988
12051
|
setLines((prev) => {
|
|
11989
|
-
const existingRewardIdx = prev.findIndex(
|
|
11990
|
-
(l) => l.productId === pid && rewardProductIds.current.has(pid)
|
|
11991
|
-
);
|
|
12052
|
+
const existingRewardIdx = prev.findIndex((l) => l.productId === pid && rewardProductIds.current.has(pid));
|
|
11992
12053
|
if (existingRewardIdx >= 0) {
|
|
11993
12054
|
const next = [...prev];
|
|
11994
12055
|
next[existingRewardIdx] = { ...next[existingRewardIdx], quantity: qty };
|
|
11995
12056
|
return next;
|
|
11996
12057
|
}
|
|
11997
|
-
return [...prev, {
|
|
11998
|
-
key: `reward-${pid}-${coupon.discountId}`,
|
|
11999
|
-
productId: pid,
|
|
12000
|
-
label: productHit.name ?? `Product #${pid}`,
|
|
12001
|
-
sku: productHit.sku,
|
|
12002
|
-
quantity: qty
|
|
12003
|
-
}];
|
|
12058
|
+
return [...prev, { key: `reward-${pid}-${coupon.discountId}`, productId: pid, label: productHit.name ?? `Product #${pid}`, sku: productHit.sku, quantity: qty }];
|
|
12004
12059
|
});
|
|
12005
12060
|
});
|
|
12006
12061
|
}
|
|
@@ -12174,7 +12229,7 @@ import { useEffect as useEffect27, useState as useState30 } from "react";
|
|
|
12174
12229
|
import Link12 from "next/link";
|
|
12175
12230
|
import { useRouter as useRouter10, useSearchParams as useSearchParams8 } from "next/navigation";
|
|
12176
12231
|
import { X as X17 } from "lucide-react";
|
|
12177
|
-
import { Fragment as
|
|
12232
|
+
import { Fragment as Fragment12, jsx as jsx57, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
12178
12233
|
function formatMoney4(amount, currency = "INR") {
|
|
12179
12234
|
return new Intl.NumberFormat("en-IN", {
|
|
12180
12235
|
style: "currency",
|
|
@@ -12238,7 +12293,7 @@ function PaymentDetailPage({ paymentId }) {
|
|
|
12238
12293
|
/* @__PURE__ */ jsx57(
|
|
12239
12294
|
DetailPageLayout,
|
|
12240
12295
|
{
|
|
12241
|
-
main: /* @__PURE__ */ jsxs46(
|
|
12296
|
+
main: /* @__PURE__ */ jsxs46(Fragment12, { children: [
|
|
12242
12297
|
/* @__PURE__ */ jsxs46("section", { children: [
|
|
12243
12298
|
/* @__PURE__ */ jsx57("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Payment details" }),
|
|
12244
12299
|
/* @__PURE__ */ jsx57("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50", children: /* @__PURE__ */ jsxs46("dl", { className: "min-w-0 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 text-sm", children: [
|
|
@@ -12301,7 +12356,7 @@ function PaymentDetailPage({ paymentId }) {
|
|
|
12301
12356
|
] })
|
|
12302
12357
|
] })
|
|
12303
12358
|
] }),
|
|
12304
|
-
sidebar: /* @__PURE__ */ jsx57(
|
|
12359
|
+
sidebar: /* @__PURE__ */ jsx57(Fragment12, { children: customer && /* @__PURE__ */ jsxs46("section", { children: [
|
|
12305
12360
|
/* @__PURE__ */ jsx57("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Customer" }),
|
|
12306
12361
|
/* @__PURE__ */ jsx57("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50", children: /* @__PURE__ */ jsxs46("dl", { className: "min-w-0 grid grid-cols-1 sm:grid-cols-3 gap-3 text-sm", children: [
|
|
12307
12362
|
/* @__PURE__ */ jsxs46("div", { className: "min-w-0", children: [
|
|
@@ -12337,7 +12392,7 @@ import { useState as useState31, useEffect as useEffect28, useContext as useCont
|
|
|
12337
12392
|
import { useSearchParams as useSearchParams9 } from "next/navigation";
|
|
12338
12393
|
import { toast as toast6 } from "sonner";
|
|
12339
12394
|
import { Save as Save3, RotateCcw, ArrowLeftRight, Plus as Plus8, Trash2 as Trash26, X as X18 } from "lucide-react";
|
|
12340
|
-
import { Fragment as
|
|
12395
|
+
import { Fragment as Fragment13, jsx as jsx58, jsxs as jsxs47 } from "react/jsx-runtime";
|
|
12341
12396
|
var DEFAULT_CURRENCY = "INR";
|
|
12342
12397
|
var DEFAULTS = {
|
|
12343
12398
|
primaryColor: "#313996",
|
|
@@ -12668,7 +12723,7 @@ function SettingsPage() {
|
|
|
12668
12723
|
/* @__PURE__ */ jsx58("span", { className: "text-[11px] text-gray-400", children: "Smaller spacing in admin" })
|
|
12669
12724
|
] }) })
|
|
12670
12725
|
] }),
|
|
12671
|
-
tab === "navbar" && /* @__PURE__ */ jsx58("div", { className: "space-y-6", children: themeSettingsLoading ? /* @__PURE__ */ jsx58("div", { className: "flex items-center gap-2 text-gray-500", children: "Loading..." }) : /* @__PURE__ */ jsxs47(
|
|
12726
|
+
tab === "navbar" && /* @__PURE__ */ jsx58("div", { className: "space-y-6", children: themeSettingsLoading ? /* @__PURE__ */ jsx58("div", { className: "flex items-center gap-2 text-gray-500", children: "Loading..." }) : /* @__PURE__ */ jsxs47(Fragment13, { children: [
|
|
12672
12727
|
/* @__PURE__ */ jsxs47("div", { children: [
|
|
12673
12728
|
/* @__PURE__ */ jsx58("h2", { className: "text-lg font-semibold text-gray-900 mb-2", children: "Navbar & pages" }),
|
|
12674
12729
|
/* @__PURE__ */ jsx58("p", { className: "text-sm text-gray-500 mb-4", children: "Set logo and menu items." }),
|
|
@@ -12676,7 +12731,7 @@ function SettingsPage() {
|
|
|
12676
12731
|
] }),
|
|
12677
12732
|
/* @__PURE__ */ jsx58(Button, { onClick: handleSaveNavbar, disabled: saving, children: saving ? "Saving..." : "Save navbar" })
|
|
12678
12733
|
] }) }),
|
|
12679
|
-
tab === "store" && /* @__PURE__ */ jsx58("div", { className: "space-y-6", children: storeSettingsLoading ? /* @__PURE__ */ jsx58("div", { className: "flex items-center gap-2 text-gray-500", children: "Loading..." }) : /* @__PURE__ */ jsxs47(
|
|
12734
|
+
tab === "store" && /* @__PURE__ */ jsx58("div", { className: "space-y-6", children: storeSettingsLoading ? /* @__PURE__ */ jsx58("div", { className: "flex items-center gap-2 text-gray-500", children: "Loading..." }) : /* @__PURE__ */ jsxs47(Fragment13, { children: [
|
|
12680
12735
|
/* @__PURE__ */ jsxs47("div", { children: [
|
|
12681
12736
|
/* @__PURE__ */ jsx58("h2", { className: "text-lg font-semibold text-gray-900 mb-2", children: "Store / E-commerce" }),
|
|
12682
12737
|
/* @__PURE__ */ jsx58("p", { className: "text-sm text-gray-500 mb-4", children: "Enable e-commerce functionality to manage products, orders, payments, and more." }),
|
|
@@ -13236,7 +13291,7 @@ import {
|
|
|
13236
13291
|
Check as Check9
|
|
13237
13292
|
} from "lucide-react";
|
|
13238
13293
|
import { toast as toast8 } from "sonner";
|
|
13239
|
-
import { Fragment as
|
|
13294
|
+
import { Fragment as Fragment14, jsx as jsx60, jsxs as jsxs49 } from "react/jsx-runtime";
|
|
13240
13295
|
function getTypeCategory(mime, kind, filename) {
|
|
13241
13296
|
if (kind === "folder" || mime === "inode/directory") return "folder";
|
|
13242
13297
|
if (isZipMedia(mime, filename ?? "")) return "zip";
|
|
@@ -13450,7 +13505,7 @@ function VideoGridThumb({ src, label }) {
|
|
|
13450
13505
|
if (broken) {
|
|
13451
13506
|
return /* @__PURE__ */ jsx60("div", { ref: wrapRef, className: "absolute inset-0 flex items-center justify-center bg-gray-200", children: /* @__PURE__ */ jsx60(Film, { className: "h-12 w-12 text-slate-600", "aria-hidden": true }) });
|
|
13452
13507
|
}
|
|
13453
|
-
return /* @__PURE__ */ jsx60("div", { ref: wrapRef, className: "absolute inset-0 bg-neutral-900", children: !visible ? /* @__PURE__ */ jsx60("div", { className: "flex h-full w-full items-center justify-center bg-neutral-800", children: /* @__PURE__ */ jsx60(Film, { className: "h-12 w-12 text-slate-400", "aria-hidden": true }) }) : /* @__PURE__ */ jsxs49(
|
|
13508
|
+
return /* @__PURE__ */ jsx60("div", { ref: wrapRef, className: "absolute inset-0 bg-neutral-900", children: !visible ? /* @__PURE__ */ jsx60("div", { className: "flex h-full w-full items-center justify-center bg-neutral-800", children: /* @__PURE__ */ jsx60(Film, { className: "h-12 w-12 text-slate-400", "aria-hidden": true }) }) : /* @__PURE__ */ jsxs49(Fragment14, { children: [
|
|
13454
13509
|
/* @__PURE__ */ jsx60(
|
|
13455
13510
|
"video",
|
|
13456
13511
|
{
|
|
@@ -14323,7 +14378,7 @@ function MediaLibraryPage() {
|
|
|
14323
14378
|
editModal && /* @__PURE__ */ jsx60("div", { className: "space-y-4 py-2", children: editModal.kind === "folder" ? /* @__PURE__ */ jsxs49("div", { children: [
|
|
14324
14379
|
/* @__PURE__ */ jsx60("label", { className: "text-sm font-medium", children: "Name" }),
|
|
14325
14380
|
/* @__PURE__ */ jsx60(Input, { value: editFilename, onChange: (e) => setEditFilename(e.target.value), className: "mt-1" })
|
|
14326
|
-
] }) : /* @__PURE__ */ jsxs49(
|
|
14381
|
+
] }) : /* @__PURE__ */ jsxs49(Fragment14, { children: [
|
|
14327
14382
|
/* @__PURE__ */ jsxs49("div", { children: [
|
|
14328
14383
|
/* @__PURE__ */ jsx60("label", { className: "text-sm font-medium", children: "Alt text" }),
|
|
14329
14384
|
/* @__PURE__ */ jsx60(
|
|
@@ -14362,7 +14417,7 @@ function MediaLibraryPage() {
|
|
|
14362
14417
|
previewItem.size ? ` \xB7 ${formatMediaBytes(previewItem.size)}` : ""
|
|
14363
14418
|
] })
|
|
14364
14419
|
] }),
|
|
14365
|
-
previewItem && previewAbsUrl && /* @__PURE__ */ jsxs49(
|
|
14420
|
+
previewItem && previewAbsUrl && /* @__PURE__ */ jsxs49(Fragment14, { children: [
|
|
14366
14421
|
/* @__PURE__ */ jsx60("div", { className: "min-h-0 flex-1 overflow-auto rounded-md border bg-muted/15 p-2", children: /* @__PURE__ */ jsx60(MediaPreviewBody, { item: previewItem, absoluteUrl: previewAbsUrl }) }),
|
|
14367
14422
|
/* @__PURE__ */ jsxs49("div", { className: "flex shrink-0 flex-col-reverse gap-2 border-t pt-3 sm:flex-row sm:flex-wrap sm:items-center sm:justify-between", children: [
|
|
14368
14423
|
/* @__PURE__ */ jsxs49("div", { className: "flex flex-wrap gap-2", children: [
|
|
@@ -14474,7 +14529,7 @@ function getCatalog(theme) {
|
|
|
14474
14529
|
// src/admin/pages/PageBuilderPage.tsx
|
|
14475
14530
|
import * as LucideIcons from "lucide-react";
|
|
14476
14531
|
import React20 from "react";
|
|
14477
|
-
import { Fragment as
|
|
14532
|
+
import { Fragment as Fragment15, jsx as jsx61, jsxs as jsxs50 } from "react/jsx-runtime";
|
|
14478
14533
|
function createSelectable(Comp) {
|
|
14479
14534
|
function SelectableWrapper(props) {
|
|
14480
14535
|
const { id, connectors, displayName, isHovered } = useNode((node) => ({
|
|
@@ -14888,7 +14943,7 @@ function RightSidebar({ theme, resolver, activeTab, setActiveTab, seoProps }) {
|
|
|
14888
14943
|
tab
|
|
14889
14944
|
)) }),
|
|
14890
14945
|
/* @__PURE__ */ jsxs50("div", { className: "flex-1 overflow-y-auto flex flex-col min-h-0", children: [
|
|
14891
|
-
activeTab === "designer" && /* @__PURE__ */ jsxs50(
|
|
14946
|
+
activeTab === "designer" && /* @__PURE__ */ jsxs50(Fragment15, { children: [
|
|
14892
14947
|
/* @__PURE__ */ jsx61(
|
|
14893
14948
|
CollapsibleSection,
|
|
14894
14949
|
{
|
|
@@ -15733,7 +15788,7 @@ function JobScheduleTypeTabs({
|
|
|
15733
15788
|
}
|
|
15734
15789
|
|
|
15735
15790
|
// src/admin/JobSchedulesTool.tsx
|
|
15736
|
-
import { Fragment as
|
|
15791
|
+
import { Fragment as Fragment16, jsx as jsx65, jsxs as jsxs54 } from "react/jsx-runtime";
|
|
15737
15792
|
var WEEKDAY_LABELS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
15738
15793
|
var EMPTY_DRAFT = {
|
|
15739
15794
|
name: "",
|
|
@@ -16098,7 +16153,7 @@ function JobSchedulesTool({
|
|
|
16098
16153
|
),
|
|
16099
16154
|
/* @__PURE__ */ jsx65("p", { className: "text-[11px] text-gray-500", children: "Standard 5-field cron (minute hour dom month dow)." })
|
|
16100
16155
|
] }) : null,
|
|
16101
|
-
activeJobType === "blog_generate" ? /* @__PURE__ */ jsxs54(
|
|
16156
|
+
activeJobType === "blog_generate" ? /* @__PURE__ */ jsxs54(Fragment16, { children: [
|
|
16102
16157
|
/* @__PURE__ */ jsxs54("div", { className: "space-y-1", children: [
|
|
16103
16158
|
/* @__PURE__ */ jsx65(Label3, { className: "text-sm", children: "Author (blog drafts)" }),
|
|
16104
16159
|
/* @__PURE__ */ jsx65(
|
|
@@ -16342,7 +16397,7 @@ var BLOG_LLM_AGENT_SLUGS = [
|
|
|
16342
16397
|
];
|
|
16343
16398
|
|
|
16344
16399
|
// src/admin/pages/PluginsPage.tsx
|
|
16345
|
-
import { Fragment as
|
|
16400
|
+
import { Fragment as Fragment17, jsx as jsx66, jsxs as jsxs55 } from "react/jsx-runtime";
|
|
16346
16401
|
function normalizeLinkedInOrganizations(payload) {
|
|
16347
16402
|
if (!payload || typeof payload !== "object") return [];
|
|
16348
16403
|
const orgs = payload.organizations;
|
|
@@ -18134,7 +18189,7 @@ function PluginSettingsPanel({
|
|
|
18134
18189
|
}
|
|
18135
18190
|
}
|
|
18136
18191
|
})(),
|
|
18137
|
-
children: linkedinFetchLoading ? /* @__PURE__ */ jsxs55(
|
|
18192
|
+
children: linkedinFetchLoading ? /* @__PURE__ */ jsxs55(Fragment17, { children: [
|
|
18138
18193
|
/* @__PURE__ */ jsx66(Loader25, { className: "h-3.5 w-3.5 animate-spin" }),
|
|
18139
18194
|
"Fetching\u2026"
|
|
18140
18195
|
] }) : "Fetch pages"
|
|
@@ -18287,7 +18342,7 @@ function PluginSettingsPanel({
|
|
|
18287
18342
|
await persistMetaFacebookPageId(fr.selectedPageId);
|
|
18288
18343
|
}
|
|
18289
18344
|
})(),
|
|
18290
|
-
children: fbFetchLoading ? /* @__PURE__ */ jsxs55(
|
|
18345
|
+
children: fbFetchLoading ? /* @__PURE__ */ jsxs55(Fragment17, { children: [
|
|
18291
18346
|
/* @__PURE__ */ jsx66(Loader25, { className: "h-3.5 w-3.5 animate-spin" }),
|
|
18292
18347
|
"Fetching\u2026"
|
|
18293
18348
|
] }) : "Fetch managed pages"
|
|
@@ -18348,7 +18403,7 @@ function PluginSettingsPanel({
|
|
|
18348
18403
|
),
|
|
18349
18404
|
/* @__PURE__ */ jsx66("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: "Only paste code from sources you trust." })
|
|
18350
18405
|
] }),
|
|
18351
|
-
chatMode === "llm" && /* @__PURE__ */ jsxs55(
|
|
18406
|
+
chatMode === "llm" && /* @__PURE__ */ jsxs55(Fragment17, { children: [
|
|
18352
18407
|
/* @__PURE__ */ jsxs55("div", { className: "inline-flex rounded-lg border border-gray-200 bg-gray-50 p-0.5 dark:border-gray-600 dark:bg-gray-800/80", children: [
|
|
18353
18408
|
/* @__PURE__ */ jsxs55(
|
|
18354
18409
|
"button",
|
|
@@ -18375,7 +18430,7 @@ function PluginSettingsPanel({
|
|
|
18375
18430
|
}
|
|
18376
18431
|
)
|
|
18377
18432
|
] }),
|
|
18378
|
-
llmConfigTab === "chat" ? /* @__PURE__ */ jsxs55(
|
|
18433
|
+
llmConfigTab === "chat" ? /* @__PURE__ */ jsxs55(Fragment17, { children: [
|
|
18379
18434
|
/* @__PURE__ */ jsxs55("div", { className: "rounded-lg border border-gray-200 dark:border-gray-600 bg-white dark:bg-gray-900/40 p-3 space-y-3", children: [
|
|
18380
18435
|
/* @__PURE__ */ jsx66("p", { className: "text-sm font-medium text-gray-900 dark:text-white", children: "Widget on your site" }),
|
|
18381
18436
|
/* @__PURE__ */ jsx66("p", { className: "text-[11px] text-gray-500 dark:text-gray-400", children: "Title, icon, and colors visitors see on the chat bubble." }),
|
|
@@ -18479,7 +18534,7 @@ function PluginSettingsPanel({
|
|
|
18479
18534
|
agentLoading ? /* @__PURE__ */ jsxs55("div", { className: "flex items-center gap-2 text-sm text-gray-500", children: [
|
|
18480
18535
|
/* @__PURE__ */ jsx66(Loader25, { className: "h-4 w-4 animate-spin" }),
|
|
18481
18536
|
"Loading\u2026"
|
|
18482
|
-
] }) : /* @__PURE__ */ jsxs55(
|
|
18537
|
+
] }) : /* @__PURE__ */ jsxs55(Fragment17, { children: [
|
|
18483
18538
|
agentProvisionError ? /* @__PURE__ */ jsx66("p", { className: "rounded border border-amber-200 bg-amber-50 p-2 text-xs text-amber-900 dark:border-amber-800 dark:bg-amber-950/40 dark:text-amber-100", children: agentProvisionError }) : null,
|
|
18484
18539
|
/* @__PURE__ */ jsxs55("div", { className: "space-y-1", children: [
|
|
18485
18540
|
/* @__PURE__ */ jsx66(Label3, { htmlFor: "agent-system", className: "text-sm", children: "System instruction" }),
|
|
@@ -18562,7 +18617,7 @@ function PluginSettingsPanel({
|
|
|
18562
18617
|
children: agentSaving ? /* @__PURE__ */ jsxs55("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
18563
18618
|
/* @__PURE__ */ jsx66(Loader25, { className: "h-3.5 w-3.5 animate-spin" }),
|
|
18564
18619
|
"Creating\u2026"
|
|
18565
|
-
] }) : /* @__PURE__ */ jsxs55(
|
|
18620
|
+
] }) : /* @__PURE__ */ jsxs55(Fragment17, { children: [
|
|
18566
18621
|
/* @__PURE__ */ jsx66(Bot, { className: "h-3.5 w-3.5" }),
|
|
18567
18622
|
"Create assistant"
|
|
18568
18623
|
] })
|
|
@@ -18680,7 +18735,7 @@ function PluginSettingsPanel({
|
|
|
18680
18735
|
!emailPluginAvailable ? /* @__PURE__ */ jsx66("p", { className: "rounded border border-amber-200 bg-amber-50/80 p-2 text-[11px] text-amber-700 dark:border-amber-800 dark:bg-amber-950/40 dark:text-amber-300", children: "Enable the Email plugin (SMTP) to send lead alert emails." }) : notifyEmailLoading ? /* @__PURE__ */ jsxs55("div", { className: "flex items-center gap-2 text-sm text-gray-500", children: [
|
|
18681
18736
|
/* @__PURE__ */ jsx66(Loader25, { className: "h-4 w-4 animate-spin" }),
|
|
18682
18737
|
"Loading\u2026"
|
|
18683
|
-
] }) : /* @__PURE__ */ jsxs55(
|
|
18738
|
+
] }) : /* @__PURE__ */ jsxs55(Fragment17, { children: [
|
|
18684
18739
|
notifyEmailProvisionError ? /* @__PURE__ */ jsx66("p", { className: "rounded border border-amber-200 bg-amber-50 p-2 text-xs text-amber-900 dark:border-amber-800 dark:bg-amber-950/40 dark:text-amber-100", children: notifyEmailProvisionError }) : null,
|
|
18685
18740
|
/* @__PURE__ */ jsxs55("div", { className: "space-y-1", children: [
|
|
18686
18741
|
/* @__PURE__ */ jsx66(Label3, { htmlFor: "notify-email-system", className: "text-sm", children: "Routing instructions" }),
|
|
@@ -18946,17 +19001,17 @@ function PluginsPage() {
|
|
|
18946
19001
|
/* @__PURE__ */ jsx66("div", { className: "min-w-0 flex-1", children: !selectedName ? /* @__PURE__ */ jsxs55("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [
|
|
18947
19002
|
/* @__PURE__ */ jsx66(Puzzle2, { className: "h-10 w-10 text-gray-300 dark:text-gray-600" }),
|
|
18948
19003
|
/* @__PURE__ */ jsx66("p", { className: "mt-3 text-sm text-gray-500 dark:text-gray-400", children: "Select a plugin to view or edit its configuration." })
|
|
18949
|
-
] }) : /* @__PURE__ */ jsx66("div", { className: "rounded-lg border border-gray-200 bg-gray-50/50 p-5 dark:border-gray-700 dark:bg-gray-800/50", children: selectedDescriptor?.name === "blog_generator" ? /* @__PURE__ */ jsxs55(
|
|
19004
|
+
] }) : /* @__PURE__ */ jsx66("div", { className: "rounded-lg border border-gray-200 bg-gray-50/50 p-5 dark:border-gray-700 dark:bg-gray-800/50", children: selectedDescriptor?.name === "blog_generator" ? /* @__PURE__ */ jsxs55(Fragment17, { children: [
|
|
18950
19005
|
/* @__PURE__ */ jsxs55("h2", { className: "text-sm font-medium text-gray-700 dark:text-gray-300 mb-1", children: [
|
|
18951
19006
|
selectedDescriptor.label || selectedDescriptor.name,
|
|
18952
19007
|
" \u2014 RSS preview"
|
|
18953
19008
|
] }),
|
|
18954
19009
|
/* @__PURE__ */ jsx66("p", { className: "text-xs text-gray-500 dark:text-gray-400 mb-4", children: "Paste a feed URL and click the button to load the newest entry here (read-only; does not create a blog)." }),
|
|
18955
19010
|
/* @__PURE__ */ jsx66(BlogGeneratorRssTool, { variant: "embedded", inputIdPrefix: "admin-plugins-blog-gen" })
|
|
18956
|
-
] }) : selectedDescriptor?.name === "pg_boss" ? /* @__PURE__ */ jsxs55(
|
|
19011
|
+
] }) : selectedDescriptor?.name === "pg_boss" ? /* @__PURE__ */ jsxs55(Fragment17, { children: [
|
|
18957
19012
|
/* @__PURE__ */ jsx66("h2", { className: "text-sm font-medium text-gray-700 dark:text-gray-300 mb-1", children: selectedDescriptor.label || selectedDescriptor.name }),
|
|
18958
19013
|
/* @__PURE__ */ jsx66(JobSchedulesTool, { variant: "embedded", inputIdPrefix: "admin-plugins-pg-boss" })
|
|
18959
|
-
] }) : selectedDescriptor?.settingsGroup ? /* @__PURE__ */ jsxs55(
|
|
19014
|
+
] }) : selectedDescriptor?.settingsGroup ? /* @__PURE__ */ jsxs55(Fragment17, { children: [
|
|
18960
19015
|
/* @__PURE__ */ jsxs55("h2", { className: "text-sm font-medium text-gray-700 dark:text-gray-300 mb-4", children: [
|
|
18961
19016
|
selectedDescriptor.label || selectedDescriptor.name,
|
|
18962
19017
|
" \u2014 Configuration"
|
|
@@ -19073,7 +19128,7 @@ async function fetchSeo(seoId) {
|
|
|
19073
19128
|
// src/admin/pages/BrandEditPage.tsx
|
|
19074
19129
|
init_DetailPageLayout();
|
|
19075
19130
|
init_DetailPageHeader();
|
|
19076
|
-
import { Fragment as
|
|
19131
|
+
import { Fragment as Fragment18, jsx as jsx68, jsxs as jsxs57 } from "react/jsx-runtime";
|
|
19077
19132
|
var isCreate = (id) => id === "create";
|
|
19078
19133
|
function BrandEditPage({ brandId }) {
|
|
19079
19134
|
const router = useRouter14();
|
|
@@ -19206,7 +19261,7 @@ function BrandEditPage({ brandId }) {
|
|
|
19206
19261
|
/* @__PURE__ */ jsx68(
|
|
19207
19262
|
DetailPageLayout,
|
|
19208
19263
|
{
|
|
19209
|
-
main: /* @__PURE__ */ jsxs57(
|
|
19264
|
+
main: /* @__PURE__ */ jsxs57(Fragment18, { children: [
|
|
19210
19265
|
/* @__PURE__ */ jsxs57("section", { children: [
|
|
19211
19266
|
/* @__PURE__ */ jsx68("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Basic info" }),
|
|
19212
19267
|
/* @__PURE__ */ jsxs57("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50 space-y-4", children: [
|
|
@@ -19279,7 +19334,7 @@ function BrandEditPage({ brandId }) {
|
|
|
19279
19334
|
/* @__PURE__ */ jsx68("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50", children: /* @__PURE__ */ jsx68(SeoSection, { values: seo, onChange: (field, value) => setSeo((s) => ({ ...s, [field]: value })) }) })
|
|
19280
19335
|
] })
|
|
19281
19336
|
] }),
|
|
19282
|
-
sidebar: /* @__PURE__ */ jsx68(
|
|
19337
|
+
sidebar: /* @__PURE__ */ jsx68(Fragment18, { children: /* @__PURE__ */ jsxs57("section", { children: [
|
|
19283
19338
|
/* @__PURE__ */ jsx68("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Status" }),
|
|
19284
19339
|
/* @__PURE__ */ jsx68("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50", children: /* @__PURE__ */ jsxs57("label", { className: "flex items-center gap-2 cursor-pointer", children: [
|
|
19285
19340
|
/* @__PURE__ */ jsx68(
|
|
@@ -19449,7 +19504,7 @@ function AttributeFacetNameInput({
|
|
|
19449
19504
|
}
|
|
19450
19505
|
|
|
19451
19506
|
// src/admin/pages/ProductEditPage.tsx
|
|
19452
|
-
import { Fragment as
|
|
19507
|
+
import { Fragment as Fragment19, jsx as jsx70, jsxs as jsxs59 } from "react/jsx-runtime";
|
|
19453
19508
|
var isCreate2 = (id) => id === "create";
|
|
19454
19509
|
var sectionCls = "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50";
|
|
19455
19510
|
var labelCls = "block text-xs font-medium text-gray-600 mb-1";
|
|
@@ -19983,7 +20038,7 @@ function ProductEditPage({ productId }) {
|
|
|
19983
20038
|
/* @__PURE__ */ jsx70(
|
|
19984
20039
|
DetailPageLayout,
|
|
19985
20040
|
{
|
|
19986
|
-
main: /* @__PURE__ */ jsxs59(
|
|
20041
|
+
main: /* @__PURE__ */ jsxs59(Fragment19, { children: [
|
|
19987
20042
|
/* @__PURE__ */ jsxs59("section", { children: [
|
|
19988
20043
|
/* @__PURE__ */ jsx70("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Product details" }),
|
|
19989
20044
|
/* @__PURE__ */ jsxs59("div", { className: `${sectionCls} space-y-4`, children: [
|
|
@@ -20336,7 +20391,7 @@ import { useRouter as useRouter16, useSearchParams as useSearchParams16 } from "
|
|
|
20336
20391
|
import { AlertCircle as AlertCircle8, Plus as Plus12, Trash2 as Trash211, ChevronDown as ChevronDown6, ChevronUp as ChevronUp2, Save as Save9, Power as Power2 } from "lucide-react";
|
|
20337
20392
|
init_DetailPageLayout();
|
|
20338
20393
|
init_DetailPageHeader();
|
|
20339
|
-
import { Fragment as
|
|
20394
|
+
import { Fragment as Fragment20, jsx as jsx71, jsxs as jsxs60 } from "react/jsx-runtime";
|
|
20340
20395
|
var isCreate3 = (id) => id === "create";
|
|
20341
20396
|
var emptySlide = () => ({ url: "", type: "image", caption: "" });
|
|
20342
20397
|
var emptyVariant = () => ({ name: "", price: "", extraSpecs: [] });
|
|
@@ -20581,7 +20636,7 @@ function CollectionEditPage({ collectionId }) {
|
|
|
20581
20636
|
/* @__PURE__ */ jsx71(
|
|
20582
20637
|
DetailPageLayout,
|
|
20583
20638
|
{
|
|
20584
|
-
main: /* @__PURE__ */ jsxs60(
|
|
20639
|
+
main: /* @__PURE__ */ jsxs60(Fragment20, { children: [
|
|
20585
20640
|
/* @__PURE__ */ jsxs60("section", { children: [
|
|
20586
20641
|
/* @__PURE__ */ jsx71("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Basic info" }),
|
|
20587
20642
|
/* @__PURE__ */ jsxs60("div", { className: `${sectionCls2} space-y-4`, children: [
|
|
@@ -20701,7 +20756,7 @@ function CollectionEditPage({ collectionId }) {
|
|
|
20701
20756
|
] })
|
|
20702
20757
|
] })
|
|
20703
20758
|
] }),
|
|
20704
|
-
sidebar: /* @__PURE__ */ jsxs60(
|
|
20759
|
+
sidebar: /* @__PURE__ */ jsxs60(Fragment20, { children: [
|
|
20705
20760
|
/* @__PURE__ */ jsxs60("section", { children: [
|
|
20706
20761
|
/* @__PURE__ */ jsx71("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Status" }),
|
|
20707
20762
|
/* @__PURE__ */ jsx71("div", { className: sectionCls2, children: /* @__PURE__ */ jsxs60("label", { className: "flex items-center gap-2 cursor-pointer", children: [
|
|
@@ -21067,10 +21122,14 @@ function SchedulesPage() {
|
|
|
21067
21122
|
|
|
21068
21123
|
// src/admin/pages/VendorOnboardPage.tsx
|
|
21069
21124
|
init_vendor_scope();
|
|
21070
|
-
init_button();
|
|
21071
|
-
init_input();
|
|
21072
21125
|
import { useState as useState43 } from "react";
|
|
21126
|
+
import { useRouter as useRouter18 } from "next/navigation";
|
|
21073
21127
|
import { useSession as useSession9 } from "next-auth/react";
|
|
21128
|
+
import { AlertCircle as AlertCircle9, Save as Save11 } from "lucide-react";
|
|
21129
|
+
init_DetailPageHeader();
|
|
21130
|
+
init_DetailPageLayout();
|
|
21131
|
+
init_button();
|
|
21132
|
+
init_input();
|
|
21074
21133
|
|
|
21075
21134
|
// src/components/ui/radio-group.tsx
|
|
21076
21135
|
init_utils();
|
|
@@ -21106,11 +21165,40 @@ var RadioGroupItem = React22.forwardRef(({ className, ...props }, ref) => {
|
|
|
21106
21165
|
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
|
|
21107
21166
|
|
|
21108
21167
|
// src/admin/pages/VendorOnboardPage.tsx
|
|
21109
|
-
import { Fragment as
|
|
21110
|
-
|
|
21111
|
-
|
|
21112
|
-
|
|
21113
|
-
|
|
21168
|
+
import { Fragment as Fragment21, jsx as jsx76, jsxs as jsxs63 } from "react/jsx-runtime";
|
|
21169
|
+
var VENDOR_LIST_COLUMNS = [
|
|
21170
|
+
{ field: "name", displayName: "Name" },
|
|
21171
|
+
{ field: "slug", displayName: "Slug" },
|
|
21172
|
+
{ field: "email", displayName: "Email" },
|
|
21173
|
+
{ field: "phone", displayName: "Phone" },
|
|
21174
|
+
{ field: "active", displayName: "Active", type: "boolean" },
|
|
21175
|
+
{
|
|
21176
|
+
field: "inviteStatus",
|
|
21177
|
+
displayName: "Invite",
|
|
21178
|
+
type: "select",
|
|
21179
|
+
options: [
|
|
21180
|
+
{ value: "none", label: "None" },
|
|
21181
|
+
{ value: "pending", label: "Pending" },
|
|
21182
|
+
{ value: "expired", label: "Expired" },
|
|
21183
|
+
{ value: "accepted", label: "Accepted" }
|
|
21184
|
+
]
|
|
21185
|
+
},
|
|
21186
|
+
{ field: "createdAt", displayName: "Created", type: "date" }
|
|
21187
|
+
];
|
|
21188
|
+
function AccessDenied({ groupName }) {
|
|
21189
|
+
return /* @__PURE__ */ jsx76("div", { className: "rounded-lg bg-white p-6 shadow-md max-w-lg", children: /* @__PURE__ */ jsxs63("p", { className: "text-sm text-red-600", children: [
|
|
21190
|
+
"Only users in the ",
|
|
21191
|
+
/* @__PURE__ */ jsx76("strong", { children: "Administrator" }),
|
|
21192
|
+
" group can manage vendors.",
|
|
21193
|
+
groupName ? /* @__PURE__ */ jsxs63(Fragment21, { children: [
|
|
21194
|
+
" ",
|
|
21195
|
+
"Your group is ",
|
|
21196
|
+
/* @__PURE__ */ jsx76("strong", { children: groupName }),
|
|
21197
|
+
". Assign Administrator under System \u2192 Users, then sign out and sign in again."
|
|
21198
|
+
] }) : /* @__PURE__ */ jsx76(Fragment21, { children: " Assign the Administrator group under System \u2192 Users, then sign out and sign in again." })
|
|
21199
|
+
] }) });
|
|
21200
|
+
}
|
|
21201
|
+
function VendorOnboardForm({ onSuccess }) {
|
|
21114
21202
|
const [vendorName, setVendorName] = useState43("");
|
|
21115
21203
|
const [vendorSlug, setVendorSlug] = useState43("");
|
|
21116
21204
|
const [vendorEmail, setVendorEmail] = useState43("");
|
|
@@ -21118,44 +21206,31 @@ function VendorOnboardPage() {
|
|
|
21118
21206
|
const [ownerName, setOwnerName] = useState43("");
|
|
21119
21207
|
const [ownerEmail, setOwnerEmail] = useState43("");
|
|
21120
21208
|
const [activationMode, setActivationMode] = useState43("invite");
|
|
21121
|
-
const [
|
|
21209
|
+
const [sendOwnerEmail, setSendOwnerEmail] = useState43(true);
|
|
21122
21210
|
const [ownerPassword, setOwnerPassword] = useState43("");
|
|
21123
21211
|
const [ownerPasswordConfirm, setOwnerPasswordConfirm] = useState43("");
|
|
21124
21212
|
const [loading, setLoading] = useState43(false);
|
|
21125
21213
|
const [message, setMessage] = useState43(null);
|
|
21126
21214
|
const [inviteLink, setInviteLink] = useState43(null);
|
|
21127
|
-
const [
|
|
21128
|
-
|
|
21129
|
-
return /* @__PURE__ */ jsx76("div", { className: "p-6 max-w-lg", children: /* @__PURE__ */ jsxs63("p", { className: "text-sm text-red-600", children: [
|
|
21130
|
-
"Only users in the ",
|
|
21131
|
-
/* @__PURE__ */ jsx76("strong", { children: "Administrator" }),
|
|
21132
|
-
" group can onboard vendors.",
|
|
21133
|
-
sessionUser?.groupName ? /* @__PURE__ */ jsxs63(Fragment20, { children: [
|
|
21134
|
-
" Your group is ",
|
|
21135
|
-
/* @__PURE__ */ jsx76("strong", { children: sessionUser.groupName }),
|
|
21136
|
-
". Assign Administrator under System \u2192 Users, then sign out and sign in again."
|
|
21137
|
-
] }) : /* @__PURE__ */ jsx76(Fragment20, { children: " Assign the Administrator group under System \u2192 Users, then sign out and sign in again." })
|
|
21138
|
-
] }) });
|
|
21139
|
-
}
|
|
21140
|
-
const handleSubmit = async (e) => {
|
|
21141
|
-
e.preventDefault();
|
|
21215
|
+
const [errors, setErrors] = useState43([]);
|
|
21216
|
+
const handleSubmit = async () => {
|
|
21142
21217
|
setLoading(true);
|
|
21143
21218
|
setMessage(null);
|
|
21144
|
-
|
|
21219
|
+
setErrors([]);
|
|
21145
21220
|
setInviteLink(null);
|
|
21146
21221
|
if (activationMode === "password") {
|
|
21147
21222
|
if (!ownerPassword) {
|
|
21148
|
-
|
|
21223
|
+
setErrors(["Enter a password for the owner account"]);
|
|
21149
21224
|
setLoading(false);
|
|
21150
21225
|
return;
|
|
21151
21226
|
}
|
|
21152
21227
|
if (ownerPassword !== ownerPasswordConfirm) {
|
|
21153
|
-
|
|
21228
|
+
setErrors(["Passwords do not match"]);
|
|
21154
21229
|
setLoading(false);
|
|
21155
21230
|
return;
|
|
21156
21231
|
}
|
|
21157
21232
|
if (ownerPassword.length < 6) {
|
|
21158
|
-
|
|
21233
|
+
setErrors(["Password must be at least 6 characters"]);
|
|
21159
21234
|
setLoading(false);
|
|
21160
21235
|
return;
|
|
21161
21236
|
}
|
|
@@ -21166,7 +21241,7 @@ function VendorOnboardPage() {
|
|
|
21166
21241
|
headers: { "Content-Type": "application/json" },
|
|
21167
21242
|
body: JSON.stringify({
|
|
21168
21243
|
activation: activationMode,
|
|
21169
|
-
|
|
21244
|
+
sendOwnerEmail,
|
|
21170
21245
|
vendor: {
|
|
21171
21246
|
name: vendorName,
|
|
21172
21247
|
slug: vendorSlug || void 0,
|
|
@@ -21183,140 +21258,241 @@ function VendorOnboardPage() {
|
|
|
21183
21258
|
});
|
|
21184
21259
|
const data = await res.json();
|
|
21185
21260
|
if (!res.ok) {
|
|
21186
|
-
|
|
21261
|
+
setErrors([data.error || "Onboarding failed"]);
|
|
21187
21262
|
return;
|
|
21188
21263
|
}
|
|
21189
21264
|
setMessage(data.message || "Vendor created");
|
|
21190
21265
|
setInviteLink(data.inviteLink ?? null);
|
|
21191
|
-
|
|
21192
|
-
|
|
21193
|
-
|
|
21194
|
-
setVendorPhone("");
|
|
21195
|
-
setOwnerName("");
|
|
21196
|
-
setOwnerEmail("");
|
|
21197
|
-
setOwnerPassword("");
|
|
21198
|
-
setOwnerPasswordConfirm("");
|
|
21266
|
+
if (!data.inviteLink) {
|
|
21267
|
+
onSuccess();
|
|
21268
|
+
}
|
|
21199
21269
|
} catch {
|
|
21200
|
-
|
|
21270
|
+
setErrors(["Request failed"]);
|
|
21201
21271
|
} finally {
|
|
21202
21272
|
setLoading(false);
|
|
21203
21273
|
}
|
|
21204
21274
|
};
|
|
21205
|
-
const submitLabel = activationMode === "password" ? "Create vendor & set password" :
|
|
21206
|
-
|
|
21207
|
-
|
|
21208
|
-
/* @__PURE__ */ jsx76(
|
|
21209
|
-
|
|
21210
|
-
|
|
21211
|
-
|
|
21212
|
-
|
|
21213
|
-
|
|
21214
|
-
|
|
21215
|
-
|
|
21216
|
-
|
|
21217
|
-
|
|
21218
|
-
|
|
21219
|
-
|
|
21220
|
-
/* @__PURE__ */
|
|
21221
|
-
|
|
21222
|
-
|
|
21223
|
-
|
|
21224
|
-
|
|
21225
|
-
|
|
21226
|
-
|
|
21227
|
-
|
|
21228
|
-
|
|
21229
|
-
|
|
21230
|
-
/* @__PURE__ */ jsx76("h2", { className: "text-sm font-medium text-gray-900 dark:text-white", children: "Owner account" }),
|
|
21231
|
-
/* @__PURE__ */ jsxs63("div", { children: [
|
|
21232
|
-
/* @__PURE__ */ jsx76(Label3, { htmlFor: "ownerName", children: "Name" }),
|
|
21233
|
-
/* @__PURE__ */ jsx76(Input, { id: "ownerName", required: true, value: ownerName, onChange: (e) => setOwnerName(e.target.value), className: "mt-1" })
|
|
21234
|
-
] }),
|
|
21235
|
-
/* @__PURE__ */ jsxs63("div", { children: [
|
|
21236
|
-
/* @__PURE__ */ jsx76(Label3, { htmlFor: "ownerEmail", children: "Email" }),
|
|
21237
|
-
/* @__PURE__ */ jsx76(Input, { id: "ownerEmail", type: "email", required: true, value: ownerEmail, onChange: (e) => setOwnerEmail(e.target.value), className: "mt-1" })
|
|
21238
|
-
] })
|
|
21275
|
+
const submitLabel = activationMode === "password" ? sendOwnerEmail ? "Create vendor & send welcome email" : "Create vendor & set password" : sendOwnerEmail ? "Create vendor & send invite" : "Create vendor & copy invite link";
|
|
21276
|
+
const fieldClass = "w-full rounded-md border border-gray-300 px-3 py-2 text-sm";
|
|
21277
|
+
return /* @__PURE__ */ jsxs63("div", { className: "rounded-lg bg-white shadow-md", children: [
|
|
21278
|
+
/* @__PURE__ */ jsx76(
|
|
21279
|
+
DetailPageHeader,
|
|
21280
|
+
{
|
|
21281
|
+
title: "Create vendor",
|
|
21282
|
+
subtitle: "Creates a vendor store and a Vendor Owner account",
|
|
21283
|
+
closeHref: "/admin/vendor-onboard",
|
|
21284
|
+
menuItems: [{ label: loading ? "Creating\u2026" : submitLabel, icon: Save11, onClick: handleSubmit }]
|
|
21285
|
+
}
|
|
21286
|
+
),
|
|
21287
|
+
errors.length > 0 && /* @__PURE__ */ jsx76("div", { className: "bg-red-50 border-l-4 border-red-400 p-4 mx-6 mt-4", children: /* @__PURE__ */ jsxs63("div", { className: "flex", children: [
|
|
21288
|
+
/* @__PURE__ */ jsx76(AlertCircle9, { className: "h-5 w-5 text-red-400 flex-shrink-0" }),
|
|
21289
|
+
/* @__PURE__ */ jsxs63("div", { className: "ml-3", children: [
|
|
21290
|
+
/* @__PURE__ */ jsx76("h3", { className: "text-sm font-medium text-red-800", children: "Please fix the following errors:" }),
|
|
21291
|
+
/* @__PURE__ */ jsx76("ul", { className: "mt-2 text-sm text-red-700 list-disc pl-5 space-y-1", children: errors.map((e, i) => /* @__PURE__ */ jsx76("li", { children: e }, i)) })
|
|
21292
|
+
] })
|
|
21293
|
+
] }) }),
|
|
21294
|
+
message && /* @__PURE__ */ jsxs63("div", { className: "mx-6 mt-4 rounded-lg border border-green-200 bg-green-50 p-4 text-sm text-green-800", children: [
|
|
21295
|
+
/* @__PURE__ */ jsx76("p", { children: message }),
|
|
21296
|
+
inviteLink && /* @__PURE__ */ jsxs63("p", { className: "mt-2 text-xs break-all", children: [
|
|
21297
|
+
"Invite link:",
|
|
21298
|
+
" ",
|
|
21299
|
+
/* @__PURE__ */ jsx76("a", { href: inviteLink, className: "text-blue-600 underline", children: inviteLink })
|
|
21239
21300
|
] }),
|
|
21240
|
-
/* @__PURE__ */
|
|
21241
|
-
|
|
21242
|
-
|
|
21243
|
-
|
|
21244
|
-
|
|
21245
|
-
|
|
21246
|
-
|
|
21247
|
-
className: "
|
|
21248
|
-
children: [
|
|
21249
|
-
/* @__PURE__ */ jsxs63("div", {
|
|
21250
|
-
/* @__PURE__ */ jsx76(
|
|
21251
|
-
/* @__PURE__ */
|
|
21252
|
-
|
|
21253
|
-
|
|
21254
|
-
|
|
21301
|
+
/* @__PURE__ */ jsx76(Button, { type: "button", variant: "outline", size: "sm", className: "mt-3", onClick: onSuccess, children: "Back to vendors" })
|
|
21302
|
+
] }),
|
|
21303
|
+
!message && /* @__PURE__ */ jsx76(
|
|
21304
|
+
DetailPageLayout,
|
|
21305
|
+
{
|
|
21306
|
+
main: /* @__PURE__ */ jsxs63(Fragment21, { children: [
|
|
21307
|
+
/* @__PURE__ */ jsxs63("section", { children: [
|
|
21308
|
+
/* @__PURE__ */ jsx76("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Store" }),
|
|
21309
|
+
/* @__PURE__ */ jsxs63("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50 space-y-4", children: [
|
|
21310
|
+
/* @__PURE__ */ jsxs63("div", { children: [
|
|
21311
|
+
/* @__PURE__ */ jsx76(Label3, { htmlFor: "vendorName", className: "text-xs font-medium text-gray-600", children: "Store name *" }),
|
|
21312
|
+
/* @__PURE__ */ jsx76(
|
|
21313
|
+
Input,
|
|
21314
|
+
{
|
|
21315
|
+
id: "vendorName",
|
|
21316
|
+
required: true,
|
|
21317
|
+
value: vendorName,
|
|
21318
|
+
onChange: (e) => setVendorName(e.target.value),
|
|
21319
|
+
className: `mt-1 ${fieldClass}`
|
|
21320
|
+
}
|
|
21321
|
+
)
|
|
21255
21322
|
] }),
|
|
21256
|
-
/* @__PURE__ */ jsxs63("div", {
|
|
21257
|
-
/* @__PURE__ */ jsx76(
|
|
21258
|
-
/* @__PURE__ */
|
|
21259
|
-
|
|
21260
|
-
|
|
21261
|
-
|
|
21323
|
+
/* @__PURE__ */ jsxs63("div", { children: [
|
|
21324
|
+
/* @__PURE__ */ jsx76(Label3, { htmlFor: "vendorSlug", className: "text-xs font-medium text-gray-600", children: "Slug (optional)" }),
|
|
21325
|
+
/* @__PURE__ */ jsx76(
|
|
21326
|
+
Input,
|
|
21327
|
+
{
|
|
21328
|
+
id: "vendorSlug",
|
|
21329
|
+
value: vendorSlug,
|
|
21330
|
+
onChange: (e) => setVendorSlug(e.target.value),
|
|
21331
|
+
placeholder: "auto from name",
|
|
21332
|
+
className: `mt-1 ${fieldClass}`
|
|
21333
|
+
}
|
|
21334
|
+
)
|
|
21335
|
+
] }),
|
|
21336
|
+
/* @__PURE__ */ jsxs63("div", { children: [
|
|
21337
|
+
/* @__PURE__ */ jsx76(Label3, { htmlFor: "vendorEmail", className: "text-xs font-medium text-gray-600", children: "Store email" }),
|
|
21338
|
+
/* @__PURE__ */ jsx76(
|
|
21339
|
+
Input,
|
|
21340
|
+
{
|
|
21341
|
+
id: "vendorEmail",
|
|
21342
|
+
type: "email",
|
|
21343
|
+
value: vendorEmail,
|
|
21344
|
+
onChange: (e) => setVendorEmail(e.target.value),
|
|
21345
|
+
className: `mt-1 ${fieldClass}`
|
|
21346
|
+
}
|
|
21347
|
+
)
|
|
21348
|
+
] }),
|
|
21349
|
+
/* @__PURE__ */ jsxs63("div", { children: [
|
|
21350
|
+
/* @__PURE__ */ jsx76(Label3, { htmlFor: "vendorPhone", className: "text-xs font-medium text-gray-600", children: "Phone" }),
|
|
21351
|
+
/* @__PURE__ */ jsx76(
|
|
21352
|
+
Input,
|
|
21353
|
+
{
|
|
21354
|
+
id: "vendorPhone",
|
|
21355
|
+
value: vendorPhone,
|
|
21356
|
+
onChange: (e) => setVendorPhone(e.target.value),
|
|
21357
|
+
className: `mt-1 ${fieldClass}`
|
|
21358
|
+
}
|
|
21359
|
+
)
|
|
21262
21360
|
] })
|
|
21263
|
-
]
|
|
21264
|
-
}
|
|
21265
|
-
),
|
|
21266
|
-
activationMode === "invite" && /* @__PURE__ */ jsxs63("div", { className: "flex items-center gap-2 pt-1", children: [
|
|
21267
|
-
/* @__PURE__ */ jsx76(
|
|
21268
|
-
Checkbox,
|
|
21269
|
-
{
|
|
21270
|
-
id: "sendInviteEmail",
|
|
21271
|
-
checked: sendInviteEmail,
|
|
21272
|
-
onCheckedChange: (checked) => setSendInviteEmail(checked === true)
|
|
21273
|
-
}
|
|
21274
|
-
),
|
|
21275
|
-
/* @__PURE__ */ jsx76(Label3, { htmlFor: "sendInviteEmail", className: "font-normal cursor-pointer text-sm", children: "Send invite email to owner" })
|
|
21276
|
-
] }),
|
|
21277
|
-
activationMode === "password" && /* @__PURE__ */ jsxs63("div", { className: "space-y-3 pt-1", children: [
|
|
21278
|
-
/* @__PURE__ */ jsxs63("div", { children: [
|
|
21279
|
-
/* @__PURE__ */ jsx76(Label3, { htmlFor: "ownerPassword", children: "Password" }),
|
|
21280
|
-
/* @__PURE__ */ jsx76(
|
|
21281
|
-
Input,
|
|
21282
|
-
{
|
|
21283
|
-
id: "ownerPassword",
|
|
21284
|
-
type: "password",
|
|
21285
|
-
required: true,
|
|
21286
|
-
autoComplete: "new-password",
|
|
21287
|
-
value: ownerPassword,
|
|
21288
|
-
onChange: (e) => setOwnerPassword(e.target.value),
|
|
21289
|
-
className: "mt-1"
|
|
21290
|
-
}
|
|
21291
|
-
)
|
|
21361
|
+
] })
|
|
21292
21362
|
] }),
|
|
21293
|
-
/* @__PURE__ */ jsxs63("
|
|
21294
|
-
/* @__PURE__ */ jsx76(
|
|
21295
|
-
/* @__PURE__ */
|
|
21296
|
-
|
|
21363
|
+
/* @__PURE__ */ jsxs63("section", { children: [
|
|
21364
|
+
/* @__PURE__ */ jsx76("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Owner account" }),
|
|
21365
|
+
/* @__PURE__ */ jsxs63("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50 space-y-4", children: [
|
|
21366
|
+
/* @__PURE__ */ jsxs63("div", { children: [
|
|
21367
|
+
/* @__PURE__ */ jsx76(Label3, { htmlFor: "ownerName", className: "text-xs font-medium text-gray-600", children: "Name *" }),
|
|
21368
|
+
/* @__PURE__ */ jsx76(
|
|
21369
|
+
Input,
|
|
21370
|
+
{
|
|
21371
|
+
id: "ownerName",
|
|
21372
|
+
required: true,
|
|
21373
|
+
value: ownerName,
|
|
21374
|
+
onChange: (e) => setOwnerName(e.target.value),
|
|
21375
|
+
className: `mt-1 ${fieldClass}`
|
|
21376
|
+
}
|
|
21377
|
+
)
|
|
21378
|
+
] }),
|
|
21379
|
+
/* @__PURE__ */ jsxs63("div", { children: [
|
|
21380
|
+
/* @__PURE__ */ jsx76(Label3, { htmlFor: "ownerEmail", className: "text-xs font-medium text-gray-600", children: "Email *" }),
|
|
21381
|
+
/* @__PURE__ */ jsx76(
|
|
21382
|
+
Input,
|
|
21383
|
+
{
|
|
21384
|
+
id: "ownerEmail",
|
|
21385
|
+
type: "email",
|
|
21386
|
+
required: true,
|
|
21387
|
+
value: ownerEmail,
|
|
21388
|
+
onChange: (e) => setOwnerEmail(e.target.value),
|
|
21389
|
+
className: `mt-1 ${fieldClass}`
|
|
21390
|
+
}
|
|
21391
|
+
)
|
|
21392
|
+
] })
|
|
21393
|
+
] })
|
|
21394
|
+
] })
|
|
21395
|
+
] }),
|
|
21396
|
+
sidebar: /* @__PURE__ */ jsxs63("section", { children: [
|
|
21397
|
+
/* @__PURE__ */ jsx76("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Owner access" }),
|
|
21398
|
+
/* @__PURE__ */ jsxs63("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50 space-y-4", children: [
|
|
21399
|
+
/* @__PURE__ */ jsxs63(
|
|
21400
|
+
RadioGroup2,
|
|
21297
21401
|
{
|
|
21298
|
-
|
|
21299
|
-
|
|
21300
|
-
|
|
21301
|
-
|
|
21302
|
-
|
|
21303
|
-
|
|
21304
|
-
|
|
21402
|
+
value: activationMode,
|
|
21403
|
+
onValueChange: (v) => setActivationMode(v),
|
|
21404
|
+
className: "gap-3",
|
|
21405
|
+
children: [
|
|
21406
|
+
/* @__PURE__ */ jsxs63("div", { className: "flex items-start gap-2", children: [
|
|
21407
|
+
/* @__PURE__ */ jsx76(RadioGroupItem, { value: "invite", id: "activation-invite", className: "mt-0.5" }),
|
|
21408
|
+
/* @__PURE__ */ jsxs63("div", { children: [
|
|
21409
|
+
/* @__PURE__ */ jsx76(Label3, { htmlFor: "activation-invite", className: "font-normal cursor-pointer text-sm", children: "Send invite link" }),
|
|
21410
|
+
/* @__PURE__ */ jsx76("p", { className: "text-xs text-gray-500 mt-0.5", children: "Owner sets their own password via email or the link below." })
|
|
21411
|
+
] })
|
|
21412
|
+
] }),
|
|
21413
|
+
/* @__PURE__ */ jsxs63("div", { className: "flex items-start gap-2", children: [
|
|
21414
|
+
/* @__PURE__ */ jsx76(RadioGroupItem, { value: "password", id: "activation-password", className: "mt-0.5" }),
|
|
21415
|
+
/* @__PURE__ */ jsxs63("div", { children: [
|
|
21416
|
+
/* @__PURE__ */ jsx76(Label3, { htmlFor: "activation-password", className: "font-normal cursor-pointer text-sm", children: "Set password now" }),
|
|
21417
|
+
/* @__PURE__ */ jsx76("p", { className: "text-xs text-gray-500 mt-0.5", children: "Account is active immediately; share the password with the owner securely." })
|
|
21418
|
+
] })
|
|
21419
|
+
] })
|
|
21420
|
+
]
|
|
21305
21421
|
}
|
|
21306
|
-
)
|
|
21422
|
+
),
|
|
21423
|
+
/* @__PURE__ */ jsxs63("div", { className: "flex items-center gap-2 pt-1", children: [
|
|
21424
|
+
/* @__PURE__ */ jsx76(
|
|
21425
|
+
Checkbox,
|
|
21426
|
+
{
|
|
21427
|
+
id: "sendOwnerEmail",
|
|
21428
|
+
checked: sendOwnerEmail,
|
|
21429
|
+
onCheckedChange: (checked) => setSendOwnerEmail(checked === true)
|
|
21430
|
+
}
|
|
21431
|
+
),
|
|
21432
|
+
/* @__PURE__ */ jsx76(Label3, { htmlFor: "sendOwnerEmail", className: "font-normal cursor-pointer text-sm", children: activationMode === "invite" ? "Send invite email to owner" : "Send welcome email to owner" })
|
|
21433
|
+
] }),
|
|
21434
|
+
activationMode === "password" && /* @__PURE__ */ jsxs63("div", { className: "space-y-3 pt-1", children: [
|
|
21435
|
+
/* @__PURE__ */ jsxs63("div", { children: [
|
|
21436
|
+
/* @__PURE__ */ jsx76(Label3, { htmlFor: "ownerPassword", className: "text-xs font-medium text-gray-600", children: "Password *" }),
|
|
21437
|
+
/* @__PURE__ */ jsx76(
|
|
21438
|
+
Input,
|
|
21439
|
+
{
|
|
21440
|
+
id: "ownerPassword",
|
|
21441
|
+
type: "password",
|
|
21442
|
+
required: true,
|
|
21443
|
+
autoComplete: "new-password",
|
|
21444
|
+
value: ownerPassword,
|
|
21445
|
+
onChange: (e) => setOwnerPassword(e.target.value),
|
|
21446
|
+
className: `mt-1 ${fieldClass}`
|
|
21447
|
+
}
|
|
21448
|
+
)
|
|
21449
|
+
] }),
|
|
21450
|
+
/* @__PURE__ */ jsxs63("div", { children: [
|
|
21451
|
+
/* @__PURE__ */ jsx76(Label3, { htmlFor: "ownerPasswordConfirm", className: "text-xs font-medium text-gray-600", children: "Confirm password *" }),
|
|
21452
|
+
/* @__PURE__ */ jsx76(
|
|
21453
|
+
Input,
|
|
21454
|
+
{
|
|
21455
|
+
id: "ownerPasswordConfirm",
|
|
21456
|
+
type: "password",
|
|
21457
|
+
required: true,
|
|
21458
|
+
autoComplete: "new-password",
|
|
21459
|
+
value: ownerPasswordConfirm,
|
|
21460
|
+
onChange: (e) => setOwnerPasswordConfirm(e.target.value),
|
|
21461
|
+
className: `mt-1 ${fieldClass}`
|
|
21462
|
+
}
|
|
21463
|
+
)
|
|
21464
|
+
] })
|
|
21465
|
+
] }),
|
|
21466
|
+
/* @__PURE__ */ jsx76(Button, { type: "button", disabled: loading, onClick: handleSubmit, className: "w-full", children: loading ? "Creating\u2026" : submitLabel })
|
|
21307
21467
|
] })
|
|
21308
21468
|
] })
|
|
21309
|
-
|
|
21310
|
-
|
|
21311
|
-
message && /* @__PURE__ */ jsx76("p", { className: "text-sm text-green-700", children: message }),
|
|
21312
|
-
inviteLink && /* @__PURE__ */ jsxs63("p", { className: "text-xs text-gray-600 break-all", children: [
|
|
21313
|
-
"Invite link: ",
|
|
21314
|
-
/* @__PURE__ */ jsx76("a", { href: inviteLink, className: "text-blue-600 underline", children: inviteLink })
|
|
21315
|
-
] }),
|
|
21316
|
-
/* @__PURE__ */ jsx76(Button, { type: "submit", disabled: loading, children: loading ? "Creating\u2026" : submitLabel })
|
|
21317
|
-
] })
|
|
21469
|
+
}
|
|
21470
|
+
)
|
|
21318
21471
|
] });
|
|
21319
21472
|
}
|
|
21473
|
+
function VendorOnboardPage({ showCreateForm }) {
|
|
21474
|
+
const router = useRouter18();
|
|
21475
|
+
const { data: session } = useSession9();
|
|
21476
|
+
const sessionUser = session?.user;
|
|
21477
|
+
const isAdmin = canOnboardVendors(session?.user);
|
|
21478
|
+
if (!isAdmin) {
|
|
21479
|
+
return /* @__PURE__ */ jsx76(AccessDenied, { groupName: sessionUser?.groupName });
|
|
21480
|
+
}
|
|
21481
|
+
if (showCreateForm) {
|
|
21482
|
+
return /* @__PURE__ */ jsx76(VendorOnboardForm, { onSuccess: () => router.push("/admin/vendor-onboard") });
|
|
21483
|
+
}
|
|
21484
|
+
return /* @__PURE__ */ jsx76(
|
|
21485
|
+
AdminCRUD,
|
|
21486
|
+
{
|
|
21487
|
+
title: "Vendors",
|
|
21488
|
+
apiEndpoint: "/api/vendors",
|
|
21489
|
+
columns: [...VENDOR_LIST_COLUMNS],
|
|
21490
|
+
addEditPageUrl: "/admin/vendor-onboard",
|
|
21491
|
+
defaultSortField: "createdAt",
|
|
21492
|
+
defaultSortOrder: "desc"
|
|
21493
|
+
}
|
|
21494
|
+
);
|
|
21495
|
+
}
|
|
21320
21496
|
|
|
21321
21497
|
// src/admin/pages/VendorTeamPage.tsx
|
|
21322
21498
|
init_button();
|
|
@@ -21834,9 +22010,9 @@ init_DetailPageLayout();
|
|
|
21834
22010
|
init_DetailPageHeader();
|
|
21835
22011
|
import { useEffect as useEffect42, useState as useState45 } from "react";
|
|
21836
22012
|
import Link14 from "next/link";
|
|
21837
|
-
import { useRouter as
|
|
22013
|
+
import { useRouter as useRouter19, useSearchParams as useSearchParams17 } from "next/navigation";
|
|
21838
22014
|
import { X as X21, Pencil as Pencil3, ChevronDown as ChevronDown7, ChevronRight as ChevronRight6, Zap as Zap2 } from "lucide-react";
|
|
21839
|
-
import { Fragment as
|
|
22015
|
+
import { Fragment as Fragment22, jsx as jsx78, jsxs as jsxs65 } from "react/jsx-runtime";
|
|
21840
22016
|
function statusBadge2(status) {
|
|
21841
22017
|
const map = {
|
|
21842
22018
|
ACTIVE: "bg-green-100 text-green-800",
|
|
@@ -21913,7 +22089,7 @@ function RuleTreeNode({ node, depth = 0 }) {
|
|
|
21913
22089
|
const borderColor = depth % 2 === 0 ? "border-blue-200" : "border-purple-200";
|
|
21914
22090
|
const bgColor = depth % 2 === 0 ? "bg-blue-50/30" : "bg-purple-50/30";
|
|
21915
22091
|
return /* @__PURE__ */ jsxs65("div", { className: `border rounded-lg p-3 ${borderColor} ${bgColor}`, children: [
|
|
21916
|
-
/* @__PURE__ */ jsx78("div", { className: "flex items-center gap-2 text-sm flex-wrap", children: isGroup ? /* @__PURE__ */ jsxs65(
|
|
22092
|
+
/* @__PURE__ */ jsx78("div", { className: "flex items-center gap-2 text-sm flex-wrap", children: isGroup ? /* @__PURE__ */ jsxs65(Fragment22, { children: [
|
|
21917
22093
|
/* @__PURE__ */ jsx78(
|
|
21918
22094
|
"button",
|
|
21919
22095
|
{
|
|
@@ -21925,7 +22101,7 @@ function RuleTreeNode({ node, depth = 0 }) {
|
|
|
21925
22101
|
),
|
|
21926
22102
|
/* @__PURE__ */ jsx78("span", { className: "font-semibold text-xs uppercase text-gray-500", children: "Group" }),
|
|
21927
22103
|
/* @__PURE__ */ jsx78("span", { className: "rounded bg-white border border-gray-200 px-2 py-0.5 text-xs font-mono font-semibold text-gray-700", children: (node.conditionOperator ?? "and").toUpperCase() })
|
|
21928
|
-
] }) : /* @__PURE__ */ jsxs65(
|
|
22104
|
+
] }) : /* @__PURE__ */ jsxs65(Fragment22, { children: [
|
|
21929
22105
|
node.type && /* @__PURE__ */ jsx78("span", { className: "rounded bg-white border border-gray-200 px-2 py-0.5 text-xs text-gray-700", children: RULE_TYPE_LABEL[node.type] ?? node.type }),
|
|
21930
22106
|
node.subType && /* @__PURE__ */ jsx78("span", { className: "text-gray-400 text-xs", children: node.subType }),
|
|
21931
22107
|
node.comparisonOperator && /* @__PURE__ */ jsx78("span", { className: "font-mono text-xs font-semibold text-gray-700", children: node.comparisonOperator }),
|
|
@@ -21935,7 +22111,7 @@ function RuleTreeNode({ node, depth = 0 }) {
|
|
|
21935
22111
|
] });
|
|
21936
22112
|
}
|
|
21937
22113
|
function DiscountDetailPage({ discountId }) {
|
|
21938
|
-
const router =
|
|
22114
|
+
const router = useRouter19();
|
|
21939
22115
|
const searchParams = useSearchParams17();
|
|
21940
22116
|
const listReturnUrl = safeAdminListReturnUrl(searchParams.get("from")) ?? "/admin/discounts";
|
|
21941
22117
|
const [discount, setDiscount] = useState45(null);
|
|
@@ -22020,7 +22196,7 @@ function DiscountDetailPage({ discountId }) {
|
|
|
22020
22196
|
/* @__PURE__ */ jsx78(
|
|
22021
22197
|
DetailPageLayout,
|
|
22022
22198
|
{
|
|
22023
|
-
main: /* @__PURE__ */ jsxs65(
|
|
22199
|
+
main: /* @__PURE__ */ jsxs65(Fragment22, { children: [
|
|
22024
22200
|
/* @__PURE__ */ jsxs65("section", { children: [
|
|
22025
22201
|
/* @__PURE__ */ jsx78("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Discount details" }),
|
|
22026
22202
|
/* @__PURE__ */ jsxs65("div", { className: "border border-gray-200 rounded-lg p-4 bg-gray-50/50", children: [
|
|
@@ -22095,7 +22271,7 @@ function DiscountDetailPage({ discountId }) {
|
|
|
22095
22271
|
/* @__PURE__ */ jsx78("div", { className: "border border-gray-200 rounded-lg p-4 bg-gray-50/50 space-y-2", children: ruleTree.length === 0 ? /* @__PURE__ */ jsx78("p", { className: "text-sm text-gray-400", children: "No conditions \u2014 applies to all orders." }) : ruleTree.map((node) => /* @__PURE__ */ jsx78(RuleTreeNode, { node }, node.id)) })
|
|
22096
22272
|
] })
|
|
22097
22273
|
] }),
|
|
22098
|
-
sidebar: /* @__PURE__ */ jsxs65(
|
|
22274
|
+
sidebar: /* @__PURE__ */ jsxs65(Fragment22, { children: [
|
|
22099
22275
|
/* @__PURE__ */ jsxs65("section", { children: [
|
|
22100
22276
|
/* @__PURE__ */ jsx78("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Usage" }),
|
|
22101
22277
|
/* @__PURE__ */ jsxs65("div", { className: "border border-gray-200 rounded-lg p-4 bg-gray-50/50 space-y-3 text-sm", children: [
|
|
@@ -22167,8 +22343,8 @@ init_admin_list_return_url();
|
|
|
22167
22343
|
init_DetailPageLayout();
|
|
22168
22344
|
init_DetailPageHeader();
|
|
22169
22345
|
import { useState as useState47, useEffect as useEffect44 } from "react";
|
|
22170
|
-
import { useRouter as
|
|
22171
|
-
import { AlertCircle as
|
|
22346
|
+
import { useRouter as useRouter20, useSearchParams as useSearchParams18 } from "next/navigation";
|
|
22347
|
+
import { AlertCircle as AlertCircle10, Save as Save12, Zap as Zap3 } from "lucide-react";
|
|
22172
22348
|
|
|
22173
22349
|
// src/admin/pages/DiscountsConditionsBuilder.tsx
|
|
22174
22350
|
init_button();
|
|
@@ -22958,7 +23134,7 @@ function DiscountConditionsBuilder({
|
|
|
22958
23134
|
}
|
|
22959
23135
|
|
|
22960
23136
|
// src/admin/pages/DiscountEditPage.tsx
|
|
22961
|
-
import { Fragment as
|
|
23137
|
+
import { Fragment as Fragment23, jsx as jsx80, jsxs as jsxs67 } from "react/jsx-runtime";
|
|
22962
23138
|
function uid2() {
|
|
22963
23139
|
return Math.random().toString(36).slice(2, 10);
|
|
22964
23140
|
}
|
|
@@ -23026,7 +23202,7 @@ function useConvertedValue2(value, fromCurrency, toCurrency, discountType) {
|
|
|
23026
23202
|
var inputCls4 = "w-full rounded-md border border-gray-300 px-3 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-gray-400";
|
|
23027
23203
|
var isCreate4 = (id) => id === "create";
|
|
23028
23204
|
function DiscountEditPage({ discountId }) {
|
|
23029
|
-
const router =
|
|
23205
|
+
const router = useRouter20();
|
|
23030
23206
|
const searchParams = useSearchParams18();
|
|
23031
23207
|
const listReturnUrl = safeAdminListReturnUrl(searchParams.get("from")) ?? "/admin/discounts";
|
|
23032
23208
|
const create = isCreate4(discountId);
|
|
@@ -23188,12 +23364,12 @@ function DiscountEditPage({ discountId }) {
|
|
|
23188
23364
|
subtitle: create ? "Create a new discount coupon" : `Editing: ${couponCode || discountId}`,
|
|
23189
23365
|
closeHref: listReturnUrl,
|
|
23190
23366
|
menuItems: [
|
|
23191
|
-
{ label: saving ? "Saving..." : "Save", icon:
|
|
23367
|
+
{ label: saving ? "Saving..." : "Save", icon: Save12, onClick: handleSave }
|
|
23192
23368
|
]
|
|
23193
23369
|
}
|
|
23194
23370
|
),
|
|
23195
23371
|
errors.length > 0 && /* @__PURE__ */ jsx80("div", { className: "bg-red-50 border-l-4 border-red-400 p-4 mx-6 mt-4", children: /* @__PURE__ */ jsxs67("div", { className: "flex", children: [
|
|
23196
|
-
/* @__PURE__ */ jsx80(
|
|
23372
|
+
/* @__PURE__ */ jsx80(AlertCircle10, { className: "h-5 w-5 text-red-400 flex-shrink-0" }),
|
|
23197
23373
|
/* @__PURE__ */ jsxs67("div", { className: "ml-3", children: [
|
|
23198
23374
|
/* @__PURE__ */ jsx80("h3", { className: "text-sm font-medium text-red-800", children: "Please fix the following errors:" }),
|
|
23199
23375
|
/* @__PURE__ */ jsx80("ul", { className: "mt-2 text-sm text-red-700 list-disc pl-5 space-y-1", children: errors.map((e, i) => /* @__PURE__ */ jsx80("li", { children: e }, i)) })
|
|
@@ -23202,7 +23378,7 @@ function DiscountEditPage({ discountId }) {
|
|
|
23202
23378
|
/* @__PURE__ */ jsx80(
|
|
23203
23379
|
DetailPageLayout,
|
|
23204
23380
|
{
|
|
23205
|
-
main: /* @__PURE__ */ jsxs67(
|
|
23381
|
+
main: /* @__PURE__ */ jsxs67(Fragment23, { children: [
|
|
23206
23382
|
/* @__PURE__ */ jsxs67("section", { children: [
|
|
23207
23383
|
/* @__PURE__ */ jsx80("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Basic info" }),
|
|
23208
23384
|
/* @__PURE__ */ jsxs67("div", { className: "border border-gray-200 rounded-lg p-4 bg-gray-50/50 space-y-4", children: [
|
|
@@ -23430,7 +23606,7 @@ function DiscountEditPage({ discountId }) {
|
|
|
23430
23606
|
) })
|
|
23431
23607
|
] })
|
|
23432
23608
|
] }),
|
|
23433
|
-
sidebar: /* @__PURE__ */ jsxs67(
|
|
23609
|
+
sidebar: /* @__PURE__ */ jsxs67(Fragment23, { children: [
|
|
23434
23610
|
/* @__PURE__ */ jsxs67("section", { children: [
|
|
23435
23611
|
/* @__PURE__ */ jsx80("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Status" }),
|
|
23436
23612
|
/* @__PURE__ */ jsxs67("div", { className: "border border-gray-200 rounded-lg p-4 bg-gray-50/50 space-y-3", children: [
|
|
@@ -23467,7 +23643,7 @@ function DiscountEditPage({ discountId }) {
|
|
|
23467
23643
|
value && !isNaN(Number(value)) && /* @__PURE__ */ jsxs67("section", { children: [
|
|
23468
23644
|
/* @__PURE__ */ jsx80("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Preview" }),
|
|
23469
23645
|
/* @__PURE__ */ jsxs67("div", { className: "border border-gray-200 rounded-lg p-4 bg-gray-50/50 space-y-1 text-sm", children: [
|
|
23470
|
-
!isAutomatic && /* @__PURE__ */ jsxs67(
|
|
23646
|
+
!isAutomatic && /* @__PURE__ */ jsxs67(Fragment23, { children: [
|
|
23471
23647
|
/* @__PURE__ */ jsx80("p", { className: "text-gray-500", children: "Code" }),
|
|
23472
23648
|
/* @__PURE__ */ jsx80("p", { className: "font-mono font-semibold text-gray-900", children: couponCode || "\u2014" })
|
|
23473
23649
|
] }),
|
|
@@ -23508,7 +23684,6 @@ var PAGE_MAP = {
|
|
|
23508
23684
|
roles: RolesPage,
|
|
23509
23685
|
"blog-generator": BlogGeneratorPage,
|
|
23510
23686
|
schedules: SchedulesPage,
|
|
23511
|
-
"vendor-onboard": VendorOnboardPage,
|
|
23512
23687
|
"vendor-team": VendorTeamPage
|
|
23513
23688
|
};
|
|
23514
23689
|
var CRUD_CONFIGS = {
|
|
@@ -23664,7 +23839,7 @@ function BlogEditorWrapper({
|
|
|
23664
23839
|
);
|
|
23665
23840
|
}
|
|
23666
23841
|
function AdminPageResolver({ slug }) {
|
|
23667
|
-
const router =
|
|
23842
|
+
const router = useRouter22();
|
|
23668
23843
|
const searchParams = useSearchParams20();
|
|
23669
23844
|
const { customCrudConfigs, storeEnabled } = useContext9(AdminConfigContext);
|
|
23670
23845
|
const key = slug?.[0] || "dashboard";
|
|
@@ -23708,6 +23883,10 @@ function AdminPageResolver({ slug }) {
|
|
|
23708
23883
|
/* @__PURE__ */ jsx83("span", { className: "ml-2", children: "Opening Plugins\u2026" })
|
|
23709
23884
|
] });
|
|
23710
23885
|
}
|
|
23886
|
+
if (key === "vendor-onboard") {
|
|
23887
|
+
const sub = slug?.[1];
|
|
23888
|
+
return /* @__PURE__ */ jsx83(VendorOnboardPage, { showCreateForm: sub === "create" });
|
|
23889
|
+
}
|
|
23711
23890
|
const Page = PAGE_MAP[key];
|
|
23712
23891
|
if (Page) {
|
|
23713
23892
|
return /* @__PURE__ */ jsx83(Page, {});
|
|
@@ -23798,7 +23977,7 @@ function AdminPageResolver({ slug }) {
|
|
|
23798
23977
|
// src/admin/pages/LayoutSettingsPage.tsx
|
|
23799
23978
|
init_button();
|
|
23800
23979
|
import { useState as useState51, useEffect as useEffect48, useContext as useContext10 } from "react";
|
|
23801
|
-
import { Save as
|
|
23980
|
+
import { Save as Save13 } from "lucide-react";
|
|
23802
23981
|
import { jsx as jsx84, jsxs as jsxs71 } from "react/jsx-runtime";
|
|
23803
23982
|
function LayoutSettingsPage() {
|
|
23804
23983
|
const { theme } = useContext10(AdminConfigContext);
|
|
@@ -23870,7 +24049,7 @@ function LayoutSettingsPage() {
|
|
|
23870
24049
|
disabled: saving,
|
|
23871
24050
|
className: "bg-white text-gray-800 hover:bg-gray-100 border-0 text-xs",
|
|
23872
24051
|
children: [
|
|
23873
|
-
/* @__PURE__ */ jsx84(
|
|
24052
|
+
/* @__PURE__ */ jsx84(Save13, { className: "h-4 w-4 mr-2" }),
|
|
23874
24053
|
saving ? "Saving..." : "Save"
|
|
23875
24054
|
]
|
|
23876
24055
|
}
|