@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 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.42" ;
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
- setSuggestions(data.data || []);
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
- const value = e.target.value;
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, /* @__PURE__ */ React.createElement(LucideIcons.X, {
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 res = await fetch("/api/users?limit=500");
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 users found" : "Select author"
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"))), /* @__PURE__ */ React.createElement("td", {
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: draft.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.42" ;
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
- setSuggestions(data.data || []);
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
- const value = e.target.value;
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, /* @__PURE__ */ React.createElement(X, {
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 res = await fetch("/api/users?limit=500");
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 users found" : "Select author"
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"))), /* @__PURE__ */ React.createElement("td", {
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: draft.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", {