@infuro/cms-core 1.0.42 → 1.0.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin.cjs +73 -26
- package/dist/admin.d.cts +3 -1
- package/dist/admin.d.ts +3 -1
- package/dist/admin.js +73 -26
- package/dist/api.cjs +32 -32
- package/dist/api.js +1 -1
- package/dist/{chunk-GINYYPXK.cjs → chunk-P2IWWBJV.cjs} +286 -53
- package/dist/{chunk-W2NL365N.js → chunk-SQGBHYJF.js} +286 -53
- package/dist/index.cjs +201 -201
- package/dist/index.js +2 -2
- package/package.json +1 -1
package/dist/admin.cjs
CHANGED
|
@@ -492,7 +492,7 @@ var init_admin_config_context = __esm({
|
|
|
492
492
|
var CMS_VERSION;
|
|
493
493
|
var init_cms_version = __esm({
|
|
494
494
|
"src/lib/cms-version.ts"() {
|
|
495
|
-
CMS_VERSION = "1.0.
|
|
495
|
+
CMS_VERSION = "1.0.44" ;
|
|
496
496
|
}
|
|
497
497
|
});
|
|
498
498
|
function useCatalogCategories(enabled = true) {
|
|
@@ -6708,9 +6708,10 @@ var init_CategoryAutocomplete = __esm({
|
|
|
6708
6708
|
__name(CategoryAutocomplete, "CategoryAutocomplete");
|
|
6709
6709
|
}
|
|
6710
6710
|
});
|
|
6711
|
-
function UserAutocomplete({ selectedUserId, onUserChange, placeholder = "Select author...", className = "" }) {
|
|
6711
|
+
function UserAutocomplete({ selectedUserId, onUserChange, placeholder = "Select author...", className = "", groupName = ADMIN_GROUP_NAME }) {
|
|
6712
6712
|
const [inputValue, setInputValue] = React26.useState("");
|
|
6713
6713
|
const [suggestions, setSuggestions] = React26.useState([]);
|
|
6714
|
+
const [selectedUser, setSelectedUser] = React26.useState(null);
|
|
6714
6715
|
const [isLoading, setIsLoading] = React26.useState(false);
|
|
6715
6716
|
const [showSuggestions, setShowSuggestions] = React26.useState(false);
|
|
6716
6717
|
const inputRef = React26.useRef(null);
|
|
@@ -6719,14 +6720,18 @@ function UserAutocomplete({ selectedUserId, onUserChange, placeholder = "Select
|
|
|
6719
6720
|
setIsLoading(true);
|
|
6720
6721
|
try {
|
|
6721
6722
|
const params = new URLSearchParams();
|
|
6722
|
-
if (query.trim())
|
|
6723
|
-
params.append("search", query);
|
|
6724
|
-
}
|
|
6723
|
+
if (query.trim()) params.append("search", query);
|
|
6725
6724
|
params.append("limit", "50");
|
|
6725
|
+
const group = groupName.trim() || ADMIN_GROUP_NAME;
|
|
6726
|
+
params.append("groupName", group);
|
|
6726
6727
|
const response = await fetch(`/api/users?${params}`);
|
|
6727
6728
|
if (response.ok) {
|
|
6728
6729
|
const data = await response.json();
|
|
6729
|
-
|
|
6730
|
+
const rows = Array.isArray(data.data) ? data.data : [];
|
|
6731
|
+
setSuggestions(rows.filter((u) => {
|
|
6732
|
+
const g = u.group?.name;
|
|
6733
|
+
return g == null || g === group;
|
|
6734
|
+
}));
|
|
6730
6735
|
}
|
|
6731
6736
|
} catch (error) {
|
|
6732
6737
|
console.error("Error fetching users:", error);
|
|
@@ -6740,28 +6745,57 @@ function UserAutocomplete({ selectedUserId, onUserChange, placeholder = "Select
|
|
|
6740
6745
|
}, 300);
|
|
6741
6746
|
return () => clearTimeout(timeoutId);
|
|
6742
6747
|
}, [
|
|
6743
|
-
inputValue
|
|
6748
|
+
inputValue,
|
|
6749
|
+
groupName
|
|
6750
|
+
]);
|
|
6751
|
+
React26.useEffect(() => {
|
|
6752
|
+
if (selectedUserId == null) {
|
|
6753
|
+
setSelectedUser(null);
|
|
6754
|
+
return;
|
|
6755
|
+
}
|
|
6756
|
+
if (selectedUser?.id === selectedUserId) return;
|
|
6757
|
+
let cancelled = false;
|
|
6758
|
+
(async () => {
|
|
6759
|
+
try {
|
|
6760
|
+
const res = await fetch(`/api/users/${selectedUserId}`);
|
|
6761
|
+
if (!res.ok || cancelled) return;
|
|
6762
|
+
const data = await res.json();
|
|
6763
|
+
if (!cancelled && data?.id != null) {
|
|
6764
|
+
setSelectedUser({
|
|
6765
|
+
id: Number(data.id),
|
|
6766
|
+
name: String(data.name ?? ""),
|
|
6767
|
+
email: String(data.email ?? "")
|
|
6768
|
+
});
|
|
6769
|
+
}
|
|
6770
|
+
} catch {
|
|
6771
|
+
}
|
|
6772
|
+
})();
|
|
6773
|
+
return () => {
|
|
6774
|
+
cancelled = true;
|
|
6775
|
+
};
|
|
6776
|
+
}, [
|
|
6777
|
+
selectedUserId,
|
|
6778
|
+
selectedUser?.id
|
|
6744
6779
|
]);
|
|
6745
6780
|
const handleInputChange = /* @__PURE__ */ __name((e) => {
|
|
6746
|
-
|
|
6747
|
-
setInputValue(value);
|
|
6781
|
+
setInputValue(e.target.value);
|
|
6748
6782
|
setShowSuggestions(true);
|
|
6749
6783
|
}, "handleInputChange");
|
|
6750
6784
|
const handleSuggestionSelect = /* @__PURE__ */ __name((user) => {
|
|
6751
6785
|
onUserChange(user.id);
|
|
6786
|
+
setSelectedUser(user);
|
|
6752
6787
|
setInputValue("");
|
|
6753
6788
|
setShowSuggestions(false);
|
|
6754
6789
|
setSuggestions([]);
|
|
6755
6790
|
}, "handleSuggestionSelect");
|
|
6756
6791
|
const handleRemoveUser = /* @__PURE__ */ __name(() => {
|
|
6757
6792
|
onUserChange(null);
|
|
6793
|
+
setSelectedUser(null);
|
|
6758
6794
|
}, "handleRemoveUser");
|
|
6759
6795
|
const handleKeyPress = /* @__PURE__ */ __name((e) => {
|
|
6760
6796
|
if (e.key === "Enter") {
|
|
6761
6797
|
e.preventDefault();
|
|
6762
|
-
if (suggestions.length > 0)
|
|
6763
|
-
handleSuggestionSelect(suggestions[0]);
|
|
6764
|
-
}
|
|
6798
|
+
if (suggestions.length > 0) handleSuggestionSelect(suggestions[0]);
|
|
6765
6799
|
} else if (e.key === "Escape") {
|
|
6766
6800
|
setShowSuggestions(false);
|
|
6767
6801
|
inputRef.current?.blur();
|
|
@@ -6776,14 +6810,13 @@ function UserAutocomplete({ selectedUserId, onUserChange, placeholder = "Select
|
|
|
6776
6810
|
document.addEventListener("mousedown", handleClickOutside);
|
|
6777
6811
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
6778
6812
|
}, []);
|
|
6779
|
-
const selectedUser = suggestions.find((user) => user.id === selectedUserId);
|
|
6780
6813
|
return /* @__PURE__ */ React.createElement("div", {
|
|
6781
6814
|
className: `relative ${className}`
|
|
6782
6815
|
}, selectedUser && /* @__PURE__ */ React.createElement("div", {
|
|
6783
6816
|
className: "mb-2"
|
|
6784
6817
|
}, /* @__PURE__ */ React.createElement(Badge, {
|
|
6785
6818
|
className: "flex items-center gap-1"
|
|
6786
|
-
}, selectedUser.name
|
|
6819
|
+
}, selectedUser.name || selectedUser.email || `User #${selectedUser.id}`, /* @__PURE__ */ React.createElement(LucideIcons.X, {
|
|
6787
6820
|
size: 12,
|
|
6788
6821
|
className: "cursor-pointer hover:text-red-500",
|
|
6789
6822
|
onClick: handleRemoveUser
|
|
@@ -6827,6 +6860,7 @@ var init_UserAutocomplete = __esm({
|
|
|
6827
6860
|
"use client";
|
|
6828
6861
|
init_input();
|
|
6829
6862
|
init_badge();
|
|
6863
|
+
init_permission_entities();
|
|
6830
6864
|
__name(UserAutocomplete, "UserAutocomplete");
|
|
6831
6865
|
}
|
|
6832
6866
|
});
|
|
@@ -7257,7 +7291,8 @@ function BlogEditor({ existingBlog, duplicateSource }) {
|
|
|
7257
7291
|
selectedUserId: authorId,
|
|
7258
7292
|
onUserChange: setAuthorId,
|
|
7259
7293
|
placeholder: "Select author...",
|
|
7260
|
-
className: "w-full"
|
|
7294
|
+
className: "w-full",
|
|
7295
|
+
groupName: "Administrator"
|
|
7261
7296
|
})), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(ImageUpload, {
|
|
7262
7297
|
value: coverImage,
|
|
7263
7298
|
onChange: setCoverImage,
|
|
@@ -13991,7 +14026,11 @@ function ScheduleAuthorSelect({ value, onChange, disabled }) {
|
|
|
13991
14026
|
(async () => {
|
|
13992
14027
|
setLoading(true);
|
|
13993
14028
|
try {
|
|
13994
|
-
const
|
|
14029
|
+
const params = new URLSearchParams({
|
|
14030
|
+
limit: "100",
|
|
14031
|
+
groupName: ADMIN_GROUP_NAME
|
|
14032
|
+
});
|
|
14033
|
+
const res = await fetch(`/api/users?${params}`);
|
|
13995
14034
|
if (!res.ok || cancelled) return;
|
|
13996
14035
|
const data = await res.json();
|
|
13997
14036
|
const rows = Array.isArray(data.data) ? data.data : [];
|
|
@@ -14024,7 +14063,7 @@ function ScheduleAuthorSelect({ value, onChange, disabled }) {
|
|
|
14024
14063
|
}, /* @__PURE__ */ React.createElement(SelectTrigger, {
|
|
14025
14064
|
className: "w-full"
|
|
14026
14065
|
}, /* @__PURE__ */ React.createElement(SelectValue, {
|
|
14027
|
-
placeholder: users.length === 0 ? "No
|
|
14066
|
+
placeholder: users.length === 0 ? "No administrators found" : "Select author"
|
|
14028
14067
|
})), /* @__PURE__ */ React.createElement(SelectContent, {
|
|
14029
14068
|
className: "max-h-72"
|
|
14030
14069
|
}, users.map((u) => /* @__PURE__ */ React.createElement(SelectItem, {
|
|
@@ -14036,6 +14075,7 @@ var init_ScheduleAuthorSelect = __esm({
|
|
|
14036
14075
|
"src/admin/ScheduleAuthorSelect.tsx"() {
|
|
14037
14076
|
"use client";
|
|
14038
14077
|
init_select();
|
|
14078
|
+
init_permission_entities();
|
|
14039
14079
|
__name(userLabel, "userLabel");
|
|
14040
14080
|
__name(ScheduleAuthorSelect, "ScheduleAuthorSelect");
|
|
14041
14081
|
}
|
|
@@ -27043,7 +27083,7 @@ function variantsFromForm(rows, defaultCurrency) {
|
|
|
27043
27083
|
};
|
|
27044
27084
|
}).filter((row) => row != null);
|
|
27045
27085
|
}
|
|
27046
|
-
function ProductVariantsSection({ hasVariants, onHasVariantsChange, variantOptionRows, onVariantOptionRowsChange, variantRows, onVariantRowsChange, defaultCurrency, currencySymbol: currencySymbol3 }) {
|
|
27086
|
+
function ProductVariantsSection({ hasVariants, onHasVariantsChange, variantOptionRows, onVariantOptionRowsChange, variantRows, onVariantRowsChange, defaultCurrency, currencySymbol: currencySymbol3, lockVariantStatus = false }) {
|
|
27047
27087
|
const parsedOptions = variantOptionsFromForm(variantOptionRows);
|
|
27048
27088
|
const baseCurrency = defaultCurrency.trim().toUpperCase() || "INR";
|
|
27049
27089
|
const setOptionName = /* @__PURE__ */ __name((index, value) => {
|
|
@@ -27278,9 +27318,11 @@ function ProductVariantsSection({ hasVariants, onHasVariantsChange, variantOptio
|
|
|
27278
27318
|
})), /* @__PURE__ */ React.createElement("td", {
|
|
27279
27319
|
className: "px-3 py-2 align-top"
|
|
27280
27320
|
}, /* @__PURE__ */ React.createElement("select", {
|
|
27281
|
-
value: row.status,
|
|
27321
|
+
value: lockVariantStatus ? "draft" : row.status,
|
|
27282
27322
|
onChange: /* @__PURE__ */ __name((e) => setVariantField(i, "status", e.target.value), "onChange"),
|
|
27283
|
-
className: inputCls2
|
|
27323
|
+
className: inputCls2,
|
|
27324
|
+
disabled: lockVariantStatus,
|
|
27325
|
+
title: lockVariantStatus ? "Variant status stays draft until the product is approved" : void 0
|
|
27284
27326
|
}, /* @__PURE__ */ React.createElement("option", {
|
|
27285
27327
|
value: "draft"
|
|
27286
27328
|
}, "Draft"), /* @__PURE__ */ React.createElement("option", {
|
|
@@ -27289,7 +27331,9 @@ function ProductVariantsSection({ hasVariants, onHasVariantsChange, variantOptio
|
|
|
27289
27331
|
value: "reserved"
|
|
27290
27332
|
}, "Reserved"), /* @__PURE__ */ React.createElement("option", {
|
|
27291
27333
|
value: "sold"
|
|
27292
|
-
}, "Sold"))
|
|
27334
|
+
}, "Sold")), lockVariantStatus ? /* @__PURE__ */ React.createElement("p", {
|
|
27335
|
+
className: "mt-1 text-[11px] text-gray-500"
|
|
27336
|
+
}, "Locked until product approval") : null), /* @__PURE__ */ React.createElement("td", {
|
|
27293
27337
|
className: "px-3 py-2 align-top min-w-[240px]"
|
|
27294
27338
|
}, (() => {
|
|
27295
27339
|
const lines = row.imageUrlsText === "" ? [
|
|
@@ -27464,13 +27508,14 @@ function apiVariantsToDrafts(rows, _defaultCurrency) {
|
|
|
27464
27508
|
};
|
|
27465
27509
|
});
|
|
27466
27510
|
}
|
|
27467
|
-
async function syncProductVariants(productId, drafts) {
|
|
27511
|
+
async function syncProductVariants(productId, drafts, productStatus) {
|
|
27468
27512
|
const listRes = await fetch(`/api/product_variants?productId=${productId}&limit=500`);
|
|
27469
27513
|
const listData = listRes.ok ? await listRes.json() : {
|
|
27470
27514
|
data: []
|
|
27471
27515
|
};
|
|
27472
27516
|
const existing = Array.isArray(listData.data) ? listData.data : [];
|
|
27473
27517
|
const wantedIds = new Set(drafts.filter((d) => d.id != null).map((d) => d.id));
|
|
27518
|
+
const forceDraft = productStatus !== "available";
|
|
27474
27519
|
for (const row of existing) {
|
|
27475
27520
|
if (!wantedIds.has(row.id)) {
|
|
27476
27521
|
const del = await fetch(`/api/product_variants/${row.id}`, {
|
|
@@ -27480,6 +27525,7 @@ async function syncProductVariants(productId, drafts) {
|
|
|
27480
27525
|
}
|
|
27481
27526
|
}
|
|
27482
27527
|
for (const draft of drafts) {
|
|
27528
|
+
const nextStatus = forceDraft ? "draft" : draft.status === "reserved" || draft.status === "sold" ? draft.status : "available";
|
|
27483
27529
|
const payload = {
|
|
27484
27530
|
productId,
|
|
27485
27531
|
sku: draft.sku,
|
|
@@ -27487,7 +27533,7 @@ async function syncProductVariants(productId, drafts) {
|
|
|
27487
27533
|
compareAtPrice: draft.compareAtPrice,
|
|
27488
27534
|
currencyPrices: null,
|
|
27489
27535
|
inventory: draft.inventory,
|
|
27490
|
-
status:
|
|
27536
|
+
status: nextStatus,
|
|
27491
27537
|
attributes: draft.attributes,
|
|
27492
27538
|
imageUrls: draft.imageUrls.length ? draft.imageUrls : null
|
|
27493
27539
|
};
|
|
@@ -28302,7 +28348,7 @@ function ProductEditPage({ productId }) {
|
|
|
28302
28348
|
}
|
|
28303
28349
|
}
|
|
28304
28350
|
if (hasVariants) {
|
|
28305
|
-
const variantErr = await syncProductVariants(Number(savedId), variantsFromForm(variantRows, pricingConfig.defaultCurrency));
|
|
28351
|
+
const variantErr = await syncProductVariants(Number(savedId), variantsFromForm(variantRows, pricingConfig.defaultCurrency), String(savedProduct.status ?? status));
|
|
28306
28352
|
if (variantErr) {
|
|
28307
28353
|
setErrors([
|
|
28308
28354
|
variantErr
|
|
@@ -28316,7 +28362,7 @@ function ProductEditPage({ productId }) {
|
|
|
28316
28362
|
setVariantRows(variantsToForm(apiVariantsToDrafts(reloadRows, pricingConfig.defaultCurrency), pricingConfig.defaultCurrency));
|
|
28317
28363
|
}
|
|
28318
28364
|
} else {
|
|
28319
|
-
const variantErr = await syncProductVariants(Number(savedId), []);
|
|
28365
|
+
const variantErr = await syncProductVariants(Number(savedId), [], String(savedProduct.status ?? status));
|
|
28320
28366
|
if (variantErr) {
|
|
28321
28367
|
setErrors([
|
|
28322
28368
|
variantErr
|
|
@@ -28728,7 +28774,8 @@ function ProductEditPage({ productId }) {
|
|
|
28728
28774
|
variantRows,
|
|
28729
28775
|
onVariantRowsChange: setVariantRows,
|
|
28730
28776
|
defaultCurrency: pricingConfig.defaultCurrency,
|
|
28731
|
-
currencySymbol: defaultCurrencySymbol
|
|
28777
|
+
currencySymbol: defaultCurrencySymbol,
|
|
28778
|
+
lockVariantStatus: vendorPortal && (status !== "available" || approvalOn && approvalStatus !== "approved")
|
|
28732
28779
|
}), /* @__PURE__ */ React.createElement("section", null, /* @__PURE__ */ React.createElement("h2", {
|
|
28733
28780
|
className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2"
|
|
28734
28781
|
}, "Taxes & Policy"), /* @__PURE__ */ React.createElement("p", {
|
package/dist/admin.d.cts
CHANGED
|
@@ -407,8 +407,10 @@ interface UserAutocompleteProps {
|
|
|
407
407
|
onUserChange: (userId: number | null) => void;
|
|
408
408
|
placeholder?: string;
|
|
409
409
|
className?: string;
|
|
410
|
+
/** When set, only users in this group are listed (default: Administrator / super admins). */
|
|
411
|
+
groupName?: string;
|
|
410
412
|
}
|
|
411
|
-
declare function UserAutocomplete({ selectedUserId, onUserChange, placeholder, className }: UserAutocompleteProps): react_jsx_runtime.JSX.Element;
|
|
413
|
+
declare function UserAutocomplete({ selectedUserId, onUserChange, placeholder, className, groupName, }: UserAutocompleteProps): react_jsx_runtime.JSX.Element;
|
|
412
414
|
|
|
413
415
|
interface ComponentSettingsProps {
|
|
414
416
|
meta: ComponentMeta;
|
package/dist/admin.d.ts
CHANGED
|
@@ -407,8 +407,10 @@ interface UserAutocompleteProps {
|
|
|
407
407
|
onUserChange: (userId: number | null) => void;
|
|
408
408
|
placeholder?: string;
|
|
409
409
|
className?: string;
|
|
410
|
+
/** When set, only users in this group are listed (default: Administrator / super admins). */
|
|
411
|
+
groupName?: string;
|
|
410
412
|
}
|
|
411
|
-
declare function UserAutocomplete({ selectedUserId, onUserChange, placeholder, className }: UserAutocompleteProps): react_jsx_runtime.JSX.Element;
|
|
413
|
+
declare function UserAutocomplete({ selectedUserId, onUserChange, placeholder, className, groupName, }: UserAutocompleteProps): react_jsx_runtime.JSX.Element;
|
|
412
414
|
|
|
413
415
|
interface ComponentSettingsProps {
|
|
414
416
|
meta: ComponentMeta;
|
package/dist/admin.js
CHANGED
|
@@ -457,7 +457,7 @@ var init_admin_config_context = __esm({
|
|
|
457
457
|
var CMS_VERSION;
|
|
458
458
|
var init_cms_version = __esm({
|
|
459
459
|
"src/lib/cms-version.ts"() {
|
|
460
|
-
CMS_VERSION = "1.0.
|
|
460
|
+
CMS_VERSION = "1.0.44" ;
|
|
461
461
|
}
|
|
462
462
|
});
|
|
463
463
|
function useCatalogCategories(enabled = true) {
|
|
@@ -6673,9 +6673,10 @@ var init_CategoryAutocomplete = __esm({
|
|
|
6673
6673
|
__name(CategoryAutocomplete, "CategoryAutocomplete");
|
|
6674
6674
|
}
|
|
6675
6675
|
});
|
|
6676
|
-
function UserAutocomplete({ selectedUserId, onUserChange, placeholder = "Select author...", className = "" }) {
|
|
6676
|
+
function UserAutocomplete({ selectedUserId, onUserChange, placeholder = "Select author...", className = "", groupName = ADMIN_GROUP_NAME }) {
|
|
6677
6677
|
const [inputValue, setInputValue] = useState("");
|
|
6678
6678
|
const [suggestions, setSuggestions] = useState([]);
|
|
6679
|
+
const [selectedUser, setSelectedUser] = useState(null);
|
|
6679
6680
|
const [isLoading, setIsLoading] = useState(false);
|
|
6680
6681
|
const [showSuggestions, setShowSuggestions] = useState(false);
|
|
6681
6682
|
const inputRef = useRef(null);
|
|
@@ -6684,14 +6685,18 @@ function UserAutocomplete({ selectedUserId, onUserChange, placeholder = "Select
|
|
|
6684
6685
|
setIsLoading(true);
|
|
6685
6686
|
try {
|
|
6686
6687
|
const params = new URLSearchParams();
|
|
6687
|
-
if (query.trim())
|
|
6688
|
-
params.append("search", query);
|
|
6689
|
-
}
|
|
6688
|
+
if (query.trim()) params.append("search", query);
|
|
6690
6689
|
params.append("limit", "50");
|
|
6690
|
+
const group = groupName.trim() || ADMIN_GROUP_NAME;
|
|
6691
|
+
params.append("groupName", group);
|
|
6691
6692
|
const response = await fetch(`/api/users?${params}`);
|
|
6692
6693
|
if (response.ok) {
|
|
6693
6694
|
const data = await response.json();
|
|
6694
|
-
|
|
6695
|
+
const rows = Array.isArray(data.data) ? data.data : [];
|
|
6696
|
+
setSuggestions(rows.filter((u) => {
|
|
6697
|
+
const g = u.group?.name;
|
|
6698
|
+
return g == null || g === group;
|
|
6699
|
+
}));
|
|
6695
6700
|
}
|
|
6696
6701
|
} catch (error) {
|
|
6697
6702
|
console.error("Error fetching users:", error);
|
|
@@ -6705,28 +6710,57 @@ function UserAutocomplete({ selectedUserId, onUserChange, placeholder = "Select
|
|
|
6705
6710
|
}, 300);
|
|
6706
6711
|
return () => clearTimeout(timeoutId);
|
|
6707
6712
|
}, [
|
|
6708
|
-
inputValue
|
|
6713
|
+
inputValue,
|
|
6714
|
+
groupName
|
|
6715
|
+
]);
|
|
6716
|
+
useEffect(() => {
|
|
6717
|
+
if (selectedUserId == null) {
|
|
6718
|
+
setSelectedUser(null);
|
|
6719
|
+
return;
|
|
6720
|
+
}
|
|
6721
|
+
if (selectedUser?.id === selectedUserId) return;
|
|
6722
|
+
let cancelled = false;
|
|
6723
|
+
(async () => {
|
|
6724
|
+
try {
|
|
6725
|
+
const res = await fetch(`/api/users/${selectedUserId}`);
|
|
6726
|
+
if (!res.ok || cancelled) return;
|
|
6727
|
+
const data = await res.json();
|
|
6728
|
+
if (!cancelled && data?.id != null) {
|
|
6729
|
+
setSelectedUser({
|
|
6730
|
+
id: Number(data.id),
|
|
6731
|
+
name: String(data.name ?? ""),
|
|
6732
|
+
email: String(data.email ?? "")
|
|
6733
|
+
});
|
|
6734
|
+
}
|
|
6735
|
+
} catch {
|
|
6736
|
+
}
|
|
6737
|
+
})();
|
|
6738
|
+
return () => {
|
|
6739
|
+
cancelled = true;
|
|
6740
|
+
};
|
|
6741
|
+
}, [
|
|
6742
|
+
selectedUserId,
|
|
6743
|
+
selectedUser?.id
|
|
6709
6744
|
]);
|
|
6710
6745
|
const handleInputChange = /* @__PURE__ */ __name((e) => {
|
|
6711
|
-
|
|
6712
|
-
setInputValue(value);
|
|
6746
|
+
setInputValue(e.target.value);
|
|
6713
6747
|
setShowSuggestions(true);
|
|
6714
6748
|
}, "handleInputChange");
|
|
6715
6749
|
const handleSuggestionSelect = /* @__PURE__ */ __name((user) => {
|
|
6716
6750
|
onUserChange(user.id);
|
|
6751
|
+
setSelectedUser(user);
|
|
6717
6752
|
setInputValue("");
|
|
6718
6753
|
setShowSuggestions(false);
|
|
6719
6754
|
setSuggestions([]);
|
|
6720
6755
|
}, "handleSuggestionSelect");
|
|
6721
6756
|
const handleRemoveUser = /* @__PURE__ */ __name(() => {
|
|
6722
6757
|
onUserChange(null);
|
|
6758
|
+
setSelectedUser(null);
|
|
6723
6759
|
}, "handleRemoveUser");
|
|
6724
6760
|
const handleKeyPress = /* @__PURE__ */ __name((e) => {
|
|
6725
6761
|
if (e.key === "Enter") {
|
|
6726
6762
|
e.preventDefault();
|
|
6727
|
-
if (suggestions.length > 0)
|
|
6728
|
-
handleSuggestionSelect(suggestions[0]);
|
|
6729
|
-
}
|
|
6763
|
+
if (suggestions.length > 0) handleSuggestionSelect(suggestions[0]);
|
|
6730
6764
|
} else if (e.key === "Escape") {
|
|
6731
6765
|
setShowSuggestions(false);
|
|
6732
6766
|
inputRef.current?.blur();
|
|
@@ -6741,14 +6775,13 @@ function UserAutocomplete({ selectedUserId, onUserChange, placeholder = "Select
|
|
|
6741
6775
|
document.addEventListener("mousedown", handleClickOutside);
|
|
6742
6776
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
6743
6777
|
}, []);
|
|
6744
|
-
const selectedUser = suggestions.find((user) => user.id === selectedUserId);
|
|
6745
6778
|
return /* @__PURE__ */ React.createElement("div", {
|
|
6746
6779
|
className: `relative ${className}`
|
|
6747
6780
|
}, selectedUser && /* @__PURE__ */ React.createElement("div", {
|
|
6748
6781
|
className: "mb-2"
|
|
6749
6782
|
}, /* @__PURE__ */ React.createElement(Badge, {
|
|
6750
6783
|
className: "flex items-center gap-1"
|
|
6751
|
-
}, selectedUser.name
|
|
6784
|
+
}, selectedUser.name || selectedUser.email || `User #${selectedUser.id}`, /* @__PURE__ */ React.createElement(X, {
|
|
6752
6785
|
size: 12,
|
|
6753
6786
|
className: "cursor-pointer hover:text-red-500",
|
|
6754
6787
|
onClick: handleRemoveUser
|
|
@@ -6792,6 +6825,7 @@ var init_UserAutocomplete = __esm({
|
|
|
6792
6825
|
"use client";
|
|
6793
6826
|
init_input();
|
|
6794
6827
|
init_badge();
|
|
6828
|
+
init_permission_entities();
|
|
6795
6829
|
__name(UserAutocomplete, "UserAutocomplete");
|
|
6796
6830
|
}
|
|
6797
6831
|
});
|
|
@@ -7222,7 +7256,8 @@ function BlogEditor({ existingBlog, duplicateSource }) {
|
|
|
7222
7256
|
selectedUserId: authorId,
|
|
7223
7257
|
onUserChange: setAuthorId,
|
|
7224
7258
|
placeholder: "Select author...",
|
|
7225
|
-
className: "w-full"
|
|
7259
|
+
className: "w-full",
|
|
7260
|
+
groupName: "Administrator"
|
|
7226
7261
|
})), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(ImageUpload, {
|
|
7227
7262
|
value: coverImage,
|
|
7228
7263
|
onChange: setCoverImage,
|
|
@@ -13956,7 +13991,11 @@ function ScheduleAuthorSelect({ value, onChange, disabled }) {
|
|
|
13956
13991
|
(async () => {
|
|
13957
13992
|
setLoading(true);
|
|
13958
13993
|
try {
|
|
13959
|
-
const
|
|
13994
|
+
const params = new URLSearchParams({
|
|
13995
|
+
limit: "100",
|
|
13996
|
+
groupName: ADMIN_GROUP_NAME
|
|
13997
|
+
});
|
|
13998
|
+
const res = await fetch(`/api/users?${params}`);
|
|
13960
13999
|
if (!res.ok || cancelled) return;
|
|
13961
14000
|
const data = await res.json();
|
|
13962
14001
|
const rows = Array.isArray(data.data) ? data.data : [];
|
|
@@ -13989,7 +14028,7 @@ function ScheduleAuthorSelect({ value, onChange, disabled }) {
|
|
|
13989
14028
|
}, /* @__PURE__ */ React.createElement(SelectTrigger, {
|
|
13990
14029
|
className: "w-full"
|
|
13991
14030
|
}, /* @__PURE__ */ React.createElement(SelectValue, {
|
|
13992
|
-
placeholder: users.length === 0 ? "No
|
|
14031
|
+
placeholder: users.length === 0 ? "No administrators found" : "Select author"
|
|
13993
14032
|
})), /* @__PURE__ */ React.createElement(SelectContent, {
|
|
13994
14033
|
className: "max-h-72"
|
|
13995
14034
|
}, users.map((u) => /* @__PURE__ */ React.createElement(SelectItem, {
|
|
@@ -14001,6 +14040,7 @@ var init_ScheduleAuthorSelect = __esm({
|
|
|
14001
14040
|
"src/admin/ScheduleAuthorSelect.tsx"() {
|
|
14002
14041
|
"use client";
|
|
14003
14042
|
init_select();
|
|
14043
|
+
init_permission_entities();
|
|
14004
14044
|
__name(userLabel, "userLabel");
|
|
14005
14045
|
__name(ScheduleAuthorSelect, "ScheduleAuthorSelect");
|
|
14006
14046
|
}
|
|
@@ -27008,7 +27048,7 @@ function variantsFromForm(rows, defaultCurrency) {
|
|
|
27008
27048
|
};
|
|
27009
27049
|
}).filter((row) => row != null);
|
|
27010
27050
|
}
|
|
27011
|
-
function ProductVariantsSection({ hasVariants, onHasVariantsChange, variantOptionRows, onVariantOptionRowsChange, variantRows, onVariantRowsChange, defaultCurrency, currencySymbol: currencySymbol3 }) {
|
|
27051
|
+
function ProductVariantsSection({ hasVariants, onHasVariantsChange, variantOptionRows, onVariantOptionRowsChange, variantRows, onVariantRowsChange, defaultCurrency, currencySymbol: currencySymbol3, lockVariantStatus = false }) {
|
|
27012
27052
|
const parsedOptions = variantOptionsFromForm(variantOptionRows);
|
|
27013
27053
|
const baseCurrency = defaultCurrency.trim().toUpperCase() || "INR";
|
|
27014
27054
|
const setOptionName = /* @__PURE__ */ __name((index, value) => {
|
|
@@ -27243,9 +27283,11 @@ function ProductVariantsSection({ hasVariants, onHasVariantsChange, variantOptio
|
|
|
27243
27283
|
})), /* @__PURE__ */ React.createElement("td", {
|
|
27244
27284
|
className: "px-3 py-2 align-top"
|
|
27245
27285
|
}, /* @__PURE__ */ React.createElement("select", {
|
|
27246
|
-
value: row.status,
|
|
27286
|
+
value: lockVariantStatus ? "draft" : row.status,
|
|
27247
27287
|
onChange: /* @__PURE__ */ __name((e) => setVariantField(i, "status", e.target.value), "onChange"),
|
|
27248
|
-
className: inputCls2
|
|
27288
|
+
className: inputCls2,
|
|
27289
|
+
disabled: lockVariantStatus,
|
|
27290
|
+
title: lockVariantStatus ? "Variant status stays draft until the product is approved" : void 0
|
|
27249
27291
|
}, /* @__PURE__ */ React.createElement("option", {
|
|
27250
27292
|
value: "draft"
|
|
27251
27293
|
}, "Draft"), /* @__PURE__ */ React.createElement("option", {
|
|
@@ -27254,7 +27296,9 @@ function ProductVariantsSection({ hasVariants, onHasVariantsChange, variantOptio
|
|
|
27254
27296
|
value: "reserved"
|
|
27255
27297
|
}, "Reserved"), /* @__PURE__ */ React.createElement("option", {
|
|
27256
27298
|
value: "sold"
|
|
27257
|
-
}, "Sold"))
|
|
27299
|
+
}, "Sold")), lockVariantStatus ? /* @__PURE__ */ React.createElement("p", {
|
|
27300
|
+
className: "mt-1 text-[11px] text-gray-500"
|
|
27301
|
+
}, "Locked until product approval") : null), /* @__PURE__ */ React.createElement("td", {
|
|
27258
27302
|
className: "px-3 py-2 align-top min-w-[240px]"
|
|
27259
27303
|
}, (() => {
|
|
27260
27304
|
const lines = row.imageUrlsText === "" ? [
|
|
@@ -27429,13 +27473,14 @@ function apiVariantsToDrafts(rows, _defaultCurrency) {
|
|
|
27429
27473
|
};
|
|
27430
27474
|
});
|
|
27431
27475
|
}
|
|
27432
|
-
async function syncProductVariants(productId, drafts) {
|
|
27476
|
+
async function syncProductVariants(productId, drafts, productStatus) {
|
|
27433
27477
|
const listRes = await fetch(`/api/product_variants?productId=${productId}&limit=500`);
|
|
27434
27478
|
const listData = listRes.ok ? await listRes.json() : {
|
|
27435
27479
|
data: []
|
|
27436
27480
|
};
|
|
27437
27481
|
const existing = Array.isArray(listData.data) ? listData.data : [];
|
|
27438
27482
|
const wantedIds = new Set(drafts.filter((d) => d.id != null).map((d) => d.id));
|
|
27483
|
+
const forceDraft = productStatus !== "available";
|
|
27439
27484
|
for (const row of existing) {
|
|
27440
27485
|
if (!wantedIds.has(row.id)) {
|
|
27441
27486
|
const del = await fetch(`/api/product_variants/${row.id}`, {
|
|
@@ -27445,6 +27490,7 @@ async function syncProductVariants(productId, drafts) {
|
|
|
27445
27490
|
}
|
|
27446
27491
|
}
|
|
27447
27492
|
for (const draft of drafts) {
|
|
27493
|
+
const nextStatus = forceDraft ? "draft" : draft.status === "reserved" || draft.status === "sold" ? draft.status : "available";
|
|
27448
27494
|
const payload = {
|
|
27449
27495
|
productId,
|
|
27450
27496
|
sku: draft.sku,
|
|
@@ -27452,7 +27498,7 @@ async function syncProductVariants(productId, drafts) {
|
|
|
27452
27498
|
compareAtPrice: draft.compareAtPrice,
|
|
27453
27499
|
currencyPrices: null,
|
|
27454
27500
|
inventory: draft.inventory,
|
|
27455
|
-
status:
|
|
27501
|
+
status: nextStatus,
|
|
27456
27502
|
attributes: draft.attributes,
|
|
27457
27503
|
imageUrls: draft.imageUrls.length ? draft.imageUrls : null
|
|
27458
27504
|
};
|
|
@@ -28267,7 +28313,7 @@ function ProductEditPage({ productId }) {
|
|
|
28267
28313
|
}
|
|
28268
28314
|
}
|
|
28269
28315
|
if (hasVariants) {
|
|
28270
|
-
const variantErr = await syncProductVariants(Number(savedId), variantsFromForm(variantRows, pricingConfig.defaultCurrency));
|
|
28316
|
+
const variantErr = await syncProductVariants(Number(savedId), variantsFromForm(variantRows, pricingConfig.defaultCurrency), String(savedProduct.status ?? status));
|
|
28271
28317
|
if (variantErr) {
|
|
28272
28318
|
setErrors([
|
|
28273
28319
|
variantErr
|
|
@@ -28281,7 +28327,7 @@ function ProductEditPage({ productId }) {
|
|
|
28281
28327
|
setVariantRows(variantsToForm(apiVariantsToDrafts(reloadRows, pricingConfig.defaultCurrency), pricingConfig.defaultCurrency));
|
|
28282
28328
|
}
|
|
28283
28329
|
} else {
|
|
28284
|
-
const variantErr = await syncProductVariants(Number(savedId), []);
|
|
28330
|
+
const variantErr = await syncProductVariants(Number(savedId), [], String(savedProduct.status ?? status));
|
|
28285
28331
|
if (variantErr) {
|
|
28286
28332
|
setErrors([
|
|
28287
28333
|
variantErr
|
|
@@ -28693,7 +28739,8 @@ function ProductEditPage({ productId }) {
|
|
|
28693
28739
|
variantRows,
|
|
28694
28740
|
onVariantRowsChange: setVariantRows,
|
|
28695
28741
|
defaultCurrency: pricingConfig.defaultCurrency,
|
|
28696
|
-
currencySymbol: defaultCurrencySymbol
|
|
28742
|
+
currencySymbol: defaultCurrencySymbol,
|
|
28743
|
+
lockVariantStatus: vendorPortal && (status !== "available" || approvalOn && approvalStatus !== "approved")
|
|
28697
28744
|
}), /* @__PURE__ */ React.createElement("section", null, /* @__PURE__ */ React.createElement("h2", {
|
|
28698
28745
|
className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2"
|
|
28699
28746
|
}, "Taxes & Policy"), /* @__PURE__ */ React.createElement("p", {
|