@infuro/cms-core 1.0.45 → 1.0.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +19 -2
  2. package/dist/admin.cjs +873 -214
  3. package/dist/admin.d.cts +7 -1
  4. package/dist/admin.d.ts +7 -1
  5. package/dist/admin.js +874 -215
  6. package/dist/api.cjs +40 -37
  7. package/dist/api.d.cts +1 -1
  8. package/dist/api.d.ts +1 -1
  9. package/dist/api.js +8 -5
  10. package/dist/auth.cjs +23 -23
  11. package/dist/auth.d.cts +1 -0
  12. package/dist/auth.d.ts +1 -0
  13. package/dist/auth.js +2 -2
  14. package/dist/chunk-2KUCQVAQ.js +936 -0
  15. package/dist/chunk-3K5AIEIZ.js +256 -0
  16. package/dist/{chunk-I6NH72MO.js → chunk-57O3HZPG.js} +9 -1
  17. package/dist/chunk-7PMHZRF3.cjs +872 -0
  18. package/dist/chunk-BXYZDMTZ.cjs +953 -0
  19. package/dist/chunk-CQHXW4TR.js +107 -0
  20. package/dist/{chunk-NNQBWDCI.js → chunk-CRYKVJTO.js} +55 -959
  21. package/dist/chunk-DBPSJYLZ.js +47 -0
  22. package/dist/{chunk-TAHX46EI.cjs → chunk-FBKDMRQL.cjs} +9 -1
  23. package/dist/chunk-GUSHM5HN.js +862 -0
  24. package/dist/chunk-HY3AXLOI.cjs +265 -0
  25. package/dist/chunk-L3525VXI.js +243 -0
  26. package/dist/{chunk-ZMRQ72F6.cjs → chunk-NBY4NVTY.cjs} +3 -3
  27. package/dist/chunk-OY2YTBMP.cjs +50 -0
  28. package/dist/{chunk-BLR6H5GL.js → chunk-SF2XKMCI.js} +3 -3
  29. package/dist/{chunk-22FFHLTO.cjs → chunk-TCSGFAWB.cjs} +56 -970
  30. package/dist/{chunk-F5XFHYTG.cjs → chunk-UDVLFVEC.cjs} +661 -382
  31. package/dist/{chunk-MVXLRANV.js → chunk-UKC3HYXI.js} +591 -323
  32. package/dist/chunk-V25RDUOU.cjs +248 -0
  33. package/dist/chunk-XMRMZ6NQ.cjs +109 -0
  34. package/dist/cli.cjs +9 -4
  35. package/dist/cli.js +9 -4
  36. package/dist/{email-queue-TPZWLTIV.cjs → email-queue-6NJY6HNM.cjs} +7 -5
  37. package/dist/email-queue-OI2HSCGE.js +4 -0
  38. package/dist/erp-order-invoice-3GXDE443.js +3 -0
  39. package/dist/erp-order-invoice-EYYNR526.cjs +24 -0
  40. package/dist/index.cjs +391 -364
  41. package/dist/index.d.cts +267 -14
  42. package/dist/index.d.ts +267 -14
  43. package/dist/index.js +12 -110
  44. package/dist/migrations/1781810000000-OrderItemsVariantId.ts +44 -0
  45. package/dist/migrations/1781900000000-UserInviteStatusToken.ts +46 -0
  46. package/dist/migrations/1782000000000-ComboSlug.ts +58 -0
  47. package/dist/migrations/1782100000000-DiscountDeviceType.ts +20 -0
  48. package/dist/order-inventory-2MYRKEPC.cjs +39 -0
  49. package/dist/order-inventory-76V4XIGW.js +2 -0
  50. package/dist/order-notification-dispatcher-SBQAMM5V.cjs +21 -0
  51. package/dist/{order-notification-dispatcher-XWIJYDGA.js → order-notification-dispatcher-ZJZB2HUN.js} +5 -2
  52. package/dist/retire-soft-deleted-unique-5VXBA5XX.cjs +15 -0
  53. package/dist/retire-soft-deleted-unique-NXQIH4BC.js +2 -0
  54. package/dist/send-order-placed-emails-B5ZVJT7T.cjs +15 -0
  55. package/dist/send-order-placed-emails-WPI37KRZ.js +6 -0
  56. package/package.json +5 -4
  57. package/src/admin/admin.css +27 -24
  58. package/dist/chunk-5ELSW2UP.js +0 -150
  59. package/dist/chunk-PNOKNSG2.cjs +0 -222
  60. package/dist/chunk-WEMDMVHQ.js +0 -216
  61. package/dist/chunk-XW5ATPRW.cjs +0 -155
  62. package/dist/email-queue-CGZBVVAS.js +0 -2
  63. package/dist/erp-order-invoice-3YISSOWW.js +0 -3
  64. package/dist/erp-order-invoice-ZR5F2KTA.cjs +0 -12
  65. package/dist/order-notification-dispatcher-RU7BTGGX.cjs +0 -18
package/dist/admin.cjs CHANGED
@@ -494,7 +494,7 @@ var init_admin_config_context = __esm({
494
494
  var CMS_VERSION;
495
495
  var init_cms_version = __esm({
496
496
  "src/lib/cms-version.ts"() {
497
- CMS_VERSION = "1.0.45" ;
497
+ CMS_VERSION = "1.0.46" ;
498
498
  }
499
499
  });
500
500
  function useCatalogCategories(enabled = true) {
@@ -1096,8 +1096,10 @@ var init_admin_theme = __esm({
1096
1096
  "src/admin/admin-theme.ts"() {
1097
1097
  ADMIN_THEME_CSS = `
1098
1098
  @import url("https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap");
1099
+ html{color-scheme:light}
1099
1100
  :root{--background:0 0% 100%;--foreground:0 0% 9%;--card:0 0% 100%;--card-foreground:0 0% 9%;--popover:0 0% 100%;--popover-foreground:0 0% 9%;--primary:0 0% 9%;--primary-foreground:0 0% 98%;--secondary:0 0% 96.1%;--secondary-foreground:0 0% 9%;--muted:0 0% 96.1%;--muted-foreground:0 0% 45.1%;--accent:0 0% 96.1%;--accent-foreground:0 0% 9%;--destructive:0 84.2% 60.2%;--destructive-foreground:0 0% 98%;--border:0 0% 89.8%;--input:0 0% 89.8%;--ring:0 0% 3.9%;--chart-1:0 0% 40%;--chart-2:0 0% 55%;--chart-3:0 0% 70%;--chart-4:0 0% 45%;--chart-5:0 0% 60%;--radius:0.375rem;--sidebar-background:0 0% 100%;--sidebar-foreground:0 0% 9%;--sidebar-primary:0 0% 9%;--sidebar-primary-foreground:0 0% 98%;--sidebar-accent:0 0% 96.1%;--sidebar-accent-foreground:0 0% 9%;--sidebar-border:0 0% 89.8%;--sidebar-ring:0 0% 9%}
1100
- .dark{--background:0 0% 3.9%;--foreground:0 0% 98%;--card:0 0% 3.9%;--card-foreground:0 0% 98%;--primary:0 0% 98%;--primary-foreground:0 0% 9%;--secondary:0 0% 14.9%;--secondary-foreground:0 0% 98%;--muted:0 0% 14.9%;--muted-foreground:0 0% 63.9%;--border:0 0% 14.9%;--input:0 0% 14.9%;--ring:0 0% 83.1%;--sidebar-background:0 0% 9%;--sidebar-foreground:0 0% 98%;--sidebar-primary:0 0% 98%;--sidebar-primary-foreground:0 0% 9%;--sidebar-accent:0 0% 14.9%;--sidebar-accent-foreground:0 0% 98%;--sidebar-border:0 0% 14.9%;--sidebar-ring:0 0% 83.1%}
1101
+ /* Dark mode disabled: keep light tokens even if a host app adds .dark on <html> */
1102
+ .dark{--background:0 0% 100%;--foreground:0 0% 9%;--card:0 0% 100%;--card-foreground:0 0% 9%;--popover:0 0% 100%;--popover-foreground:0 0% 9%;--primary:0 0% 9%;--primary-foreground:0 0% 98%;--secondary:0 0% 96.1%;--secondary-foreground:0 0% 9%;--muted:0 0% 96.1%;--muted-foreground:0 0% 45.1%;--accent:0 0% 96.1%;--accent-foreground:0 0% 9%;--destructive:0 84.2% 60.2%;--destructive-foreground:0 0% 98%;--border:0 0% 89.8%;--input:0 0% 89.8%;--ring:0 0% 3.9%;--sidebar-background:0 0% 100%;--sidebar-foreground:0 0% 9%;--sidebar-primary:0 0% 9%;--sidebar-primary-foreground:0 0% 98%;--sidebar-accent:0 0% 96.1%;--sidebar-accent-foreground:0 0% 9%;--sidebar-border:0 0% 89.8%;--sidebar-ring:0 0% 9%}
1101
1103
  *,*::before,*::after{border-color:hsl(var(--border))}
1102
1104
  body{font-family:"Inter",ui-sans-serif,system-ui,sans-serif;font-size:14px}
1103
1105
  .admin-app{font-size:13.5px}
@@ -1212,6 +1214,39 @@ var init_auth_debug = __esm({
1212
1214
  __name(summarizeSessionUserForLog, "summarizeSessionUserForLog");
1213
1215
  }
1214
1216
  });
1217
+ function useForceAdminLightMode() {
1218
+ React26.useEffect(() => {
1219
+ const root = document.documentElement;
1220
+ const hadDark = root.classList.contains("dark");
1221
+ const prevColorScheme = root.style.colorScheme;
1222
+ const applyLight = /* @__PURE__ */ __name(() => {
1223
+ root.classList.remove("dark");
1224
+ root.style.colorScheme = "light";
1225
+ }, "applyLight");
1226
+ applyLight();
1227
+ const observer = new MutationObserver(() => {
1228
+ if (root.classList.contains("dark")) applyLight();
1229
+ });
1230
+ observer.observe(root, {
1231
+ attributes: true,
1232
+ attributeFilter: [
1233
+ "class"
1234
+ ]
1235
+ });
1236
+ return () => {
1237
+ observer.disconnect();
1238
+ root.style.colorScheme = prevColorScheme;
1239
+ if (hadDark) root.classList.add("dark");
1240
+ else root.classList.remove("dark");
1241
+ };
1242
+ }, []);
1243
+ }
1244
+ var init_force_light_mode = __esm({
1245
+ "src/admin/force-light-mode.ts"() {
1246
+ "use client";
1247
+ __name(useForceAdminLightMode, "useForceAdminLightMode");
1248
+ }
1249
+ });
1215
1250
  function useAdminViewSettings() {
1216
1251
  React26.useEffect(() => {
1217
1252
  fetch("/api/settings/admin_view").then((r) => r.ok ? r.json() : null).then((data) => {
@@ -1233,6 +1268,7 @@ function AdminLayoutInner({ children }) {
1233
1268
  const isMobile = useIsMobile();
1234
1269
  const vendorBlockRedirectRef = React26.useRef(false);
1235
1270
  useAdminViewSettings();
1271
+ useForceAdminLightMode();
1236
1272
  const isPublicPath = PUBLIC_ADMIN_PATHS.includes(pathname);
1237
1273
  const isVendorOnlySession = session?.user?.isVendorPortal === true && session?.user?.isRBACAdmin !== true;
1238
1274
  React26.useEffect(() => {
@@ -1521,6 +1557,7 @@ var init_AdminLayout = __esm({
1521
1557
  init_admin_config_context();
1522
1558
  init_builtin_plugin_descriptors();
1523
1559
  init_auth_debug();
1560
+ init_force_light_mode();
1524
1561
  PUBLIC_ADMIN_PATHS = [
1525
1562
  "/admin/signin",
1526
1563
  "/admin/forgot-password",
@@ -1771,6 +1808,225 @@ var init_file_upload = __esm({
1771
1808
  __name(FileUpload, "FileUpload");
1772
1809
  }
1773
1810
  });
1811
+
1812
+ // src/lib/media-url.ts
1813
+ function isVideoUploadMime(mime) {
1814
+ const t = String(mime ?? "").trim().toLowerCase();
1815
+ return VIDEO_UPLOAD_MIME_TYPES.includes(t);
1816
+ }
1817
+ function isVideoMediaUrl(url) {
1818
+ if (!url || typeof url !== "string") return false;
1819
+ const trimmed = url.trim();
1820
+ if (!trimmed) return false;
1821
+ try {
1822
+ if (/^https?:\/\//i.test(trimmed)) {
1823
+ return VIDEO_EXT_RE.test(new URL(trimmed).pathname);
1824
+ }
1825
+ } catch {
1826
+ }
1827
+ const path = trimmed.split("?")[0]?.split("#")[0] ?? trimmed;
1828
+ return VIDEO_EXT_RE.test(path);
1829
+ }
1830
+ var VIDEO_EXT_RE, IMAGE_UPLOAD_MIME_TYPES, VIDEO_UPLOAD_MIME_TYPES, MEDIA_UPLOAD_MIME_TYPES, VIDEO_UPLOAD_MAX_BYTES;
1831
+ var init_media_url = __esm({
1832
+ "src/lib/media-url.ts"() {
1833
+ VIDEO_EXT_RE = /\.(mp4|webm|mov)(?:$|[?#])/i;
1834
+ IMAGE_UPLOAD_MIME_TYPES = [
1835
+ "image/jpeg",
1836
+ "image/png",
1837
+ "image/gif",
1838
+ "image/webp"
1839
+ ];
1840
+ VIDEO_UPLOAD_MIME_TYPES = [
1841
+ "video/mp4",
1842
+ "video/webm",
1843
+ "video/quicktime"
1844
+ ];
1845
+ MEDIA_UPLOAD_MIME_TYPES = [
1846
+ ...IMAGE_UPLOAD_MIME_TYPES,
1847
+ ...VIDEO_UPLOAD_MIME_TYPES
1848
+ ];
1849
+ VIDEO_UPLOAD_MAX_BYTES = 100 * 1024 * 1024;
1850
+ __name(isVideoUploadMime, "isVideoUploadMime");
1851
+ __name(isVideoMediaUrl, "isVideoMediaUrl");
1852
+ }
1853
+ });
1854
+ function ImageOrUrlField({ label, value, onChange, placeholder = "https://\u2026", inputClassName = "w-full rounded-md border border-gray-300 px-2 py-1.5 text-sm", labelClassName = "block text-xs font-medium text-gray-600 mb-1", previewVariant = "banner", maxSizeMb = 10 }) {
1855
+ const fileInputRef = React26.useRef(null);
1856
+ const [isUploading, setIsUploading] = React26.useState(false);
1857
+ const [error, setError] = React26.useState(null);
1858
+ const [lightboxOpen, setLightboxOpen] = React26.useState(false);
1859
+ const previewCls = previewVariant === "logo" ? "h-20 w-20 rounded-md border border-gray-200 bg-white object-contain cursor-pointer" : "max-h-32 w-full rounded-md border border-gray-200 bg-gray-50 object-cover cursor-pointer";
1860
+ const closeLightbox = React26.useCallback(() => setLightboxOpen(false), []);
1861
+ React26.useEffect(() => {
1862
+ if (!lightboxOpen) return;
1863
+ const onKeyDown = /* @__PURE__ */ __name((e) => {
1864
+ if (e.key === "Escape") closeLightbox();
1865
+ }, "onKeyDown");
1866
+ window.addEventListener("keydown", onKeyDown);
1867
+ const prevOverflow = document.body.style.overflow;
1868
+ document.body.style.overflow = "hidden";
1869
+ return () => {
1870
+ window.removeEventListener("keydown", onKeyDown);
1871
+ document.body.style.overflow = prevOverflow;
1872
+ };
1873
+ }, [
1874
+ lightboxOpen,
1875
+ closeLightbox
1876
+ ]);
1877
+ const handleUpload = React26.useCallback(async (file) => {
1878
+ setError(null);
1879
+ if (!MEDIA_UPLOAD_MIME_TYPES.includes(file.type)) {
1880
+ setError("Unsupported type. Use JPG, PNG, GIF, WEBP, or video MP4 / WebM / MOV");
1881
+ return;
1882
+ }
1883
+ const isVideo2 = isVideoUploadMime(file.type);
1884
+ const limit = isVideo2 ? VIDEO_UPLOAD_MAX_BYTES : maxSizeMb * 1024 * 1024;
1885
+ if (file.size > limit) {
1886
+ setError(isVideo2 ? `Video must be under ${VIDEO_UPLOAD_MAX_BYTES / (1024 * 1024)}MB` : `File must be under ${Math.round(limit / (1024 * 1024))}MB`);
1887
+ return;
1888
+ }
1889
+ setIsUploading(true);
1890
+ try {
1891
+ const formData = new FormData();
1892
+ formData.append("file", file);
1893
+ const response = await fetch("/api/upload", {
1894
+ method: "POST",
1895
+ body: formData
1896
+ });
1897
+ const data = await response.json();
1898
+ if (!response.ok) {
1899
+ throw new Error(data.error || data.details || "Upload failed");
1900
+ }
1901
+ onChange(data.filePath ?? "");
1902
+ } catch (err) {
1903
+ setError(err instanceof Error ? err.message : "Upload failed");
1904
+ } finally {
1905
+ setIsUploading(false);
1906
+ if (fileInputRef.current) fileInputRef.current.value = "";
1907
+ }
1908
+ }, [
1909
+ maxSizeMb,
1910
+ onChange
1911
+ ]);
1912
+ const onFileChange = React26.useCallback((e) => {
1913
+ const file = e.target.files?.[0];
1914
+ if (file) void handleUpload(file);
1915
+ }, [
1916
+ handleUpload
1917
+ ]);
1918
+ const trimmed = value.trim();
1919
+ const isVideo = isVideoMediaUrl(trimmed);
1920
+ return /* @__PURE__ */ React.createElement("div", {
1921
+ className: "space-y-2"
1922
+ }, /* @__PURE__ */ React.createElement("label", {
1923
+ className: labelClassName
1924
+ }, label), trimmed ? /* @__PURE__ */ React.createElement("div", {
1925
+ className: "flex items-start gap-3"
1926
+ }, isVideo ? (
1927
+ // eslint-disable-next-line jsx-a11y/media-has-caption
1928
+ /* @__PURE__ */ React.createElement("video", {
1929
+ src: trimmed,
1930
+ className: previewCls,
1931
+ muted: true,
1932
+ playsInline: true,
1933
+ preload: "metadata",
1934
+ onClick: /* @__PURE__ */ __name(() => setLightboxOpen(true), "onClick"),
1935
+ title: "Click to enlarge"
1936
+ })
1937
+ ) : (
1938
+ // eslint-disable-next-line @next/next/no-img-element
1939
+ /* @__PURE__ */ React.createElement("img", {
1940
+ src: trimmed,
1941
+ alt: label,
1942
+ className: previewCls,
1943
+ role: "button",
1944
+ tabIndex: 0,
1945
+ title: "Click to enlarge",
1946
+ onClick: /* @__PURE__ */ __name(() => setLightboxOpen(true), "onClick"),
1947
+ onKeyDown: /* @__PURE__ */ __name((e) => {
1948
+ if (e.key === "Enter" || e.key === " ") {
1949
+ e.preventDefault();
1950
+ setLightboxOpen(true);
1951
+ }
1952
+ }, "onKeyDown"),
1953
+ onError: /* @__PURE__ */ __name((e) => {
1954
+ e.currentTarget.style.display = "none";
1955
+ }, "onError")
1956
+ })
1957
+ ), /* @__PURE__ */ React.createElement("button", {
1958
+ type: "button",
1959
+ onClick: /* @__PURE__ */ __name(() => onChange(""), "onClick"),
1960
+ className: "inline-flex items-center gap-1 rounded border border-gray-300 bg-white px-2 py-1 text-xs text-gray-600 hover:bg-gray-50"
1961
+ }, /* @__PURE__ */ React.createElement(LucideIcons.X, {
1962
+ className: "h-3 w-3"
1963
+ }), "Clear")) : null, /* @__PURE__ */ React.createElement("div", {
1964
+ className: "flex flex-wrap gap-2"
1965
+ }, /* @__PURE__ */ React.createElement("input", {
1966
+ type: "text",
1967
+ inputMode: "url",
1968
+ autoComplete: "off",
1969
+ value,
1970
+ onChange: /* @__PURE__ */ __name((e) => {
1971
+ setError(null);
1972
+ onChange(e.target.value);
1973
+ }, "onChange"),
1974
+ placeholder,
1975
+ className: `${inputClassName} min-w-0 flex-1`
1976
+ }), /* @__PURE__ */ React.createElement("input", {
1977
+ ref: fileInputRef,
1978
+ type: "file",
1979
+ accept: ACCEPT,
1980
+ onChange: onFileChange,
1981
+ className: "hidden",
1982
+ disabled: isUploading
1983
+ }), /* @__PURE__ */ React.createElement("button", {
1984
+ type: "button",
1985
+ onClick: /* @__PURE__ */ __name(() => fileInputRef.current?.click(), "onClick"),
1986
+ disabled: isUploading,
1987
+ className: "inline-flex shrink-0 items-center gap-1.5 rounded-md border border-gray-300 bg-white px-3 py-1.5 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:opacity-50"
1988
+ }, /* @__PURE__ */ React.createElement(LucideIcons.Upload, {
1989
+ className: "h-3.5 w-3.5"
1990
+ }), isUploading ? "Uploading\u2026" : "Upload")), error ? /* @__PURE__ */ React.createElement("p", {
1991
+ className: "flex items-center gap-1.5 text-xs text-red-600"
1992
+ }, /* @__PURE__ */ React.createElement(LucideIcons.AlertCircle, {
1993
+ className: "h-3.5 w-3.5 shrink-0"
1994
+ }), error) : /* @__PURE__ */ React.createElement("p", {
1995
+ className: "text-xs text-gray-500"
1996
+ }, "Paste a URL or upload an image (PNG, JPG, GIF, WEBP up to ", maxSizeMb, "MB) or video (MP4, WebM, MOV up to", " ", VIDEO_UPLOAD_MAX_BYTES / (1024 * 1024), "MB)"), lightboxOpen && trimmed ? /* @__PURE__ */ React.createElement("div", {
1997
+ className: "fixed inset-0 z-[100] flex items-center justify-center bg-black/70 p-4",
1998
+ role: "dialog",
1999
+ "aria-modal": "true",
2000
+ "aria-label": `${label} preview`,
2001
+ onClick: closeLightbox
2002
+ }, isVideo ? (
2003
+ // eslint-disable-next-line jsx-a11y/media-has-caption
2004
+ /* @__PURE__ */ React.createElement("video", {
2005
+ src: trimmed,
2006
+ controls: true,
2007
+ autoPlay: true,
2008
+ className: "max-h-[90vh] max-w-[90vw] rounded-md shadow-lg",
2009
+ onClick: /* @__PURE__ */ __name((e) => e.stopPropagation(), "onClick")
2010
+ })
2011
+ ) : (
2012
+ // eslint-disable-next-line @next/next/no-img-element
2013
+ /* @__PURE__ */ React.createElement("img", {
2014
+ src: trimmed,
2015
+ alt: label,
2016
+ className: "max-h-[90vh] max-w-[90vw] rounded-md object-contain shadow-lg",
2017
+ onClick: /* @__PURE__ */ __name((e) => e.stopPropagation(), "onClick")
2018
+ })
2019
+ )) : null);
2020
+ }
2021
+ var ACCEPT;
2022
+ var init_ImageOrUrlField = __esm({
2023
+ "src/components/Admin/ImageOrUrlField.tsx"() {
2024
+ "use client";
2025
+ init_media_url();
2026
+ ACCEPT = MEDIA_UPLOAD_MIME_TYPES.join(",");
2027
+ __name(ImageOrUrlField, "ImageOrUrlField");
2028
+ }
2029
+ });
1774
2030
  function RelationAutocomplete({ apiEndpoint, value, onChange, labelField = "name", valueField = "id", placeholder = "Select\u2026", disabled = false, queryParams }) {
1775
2031
  const [open, setOpen] = React26.useState(false);
1776
2032
  const [search, setSearch] = React26.useState("");
@@ -2359,12 +2615,7 @@ function CreateEditForm({ isOpen, onClose, onSaveSuccess, apiEndpoint, columns,
2359
2615
  return;
2360
2616
  }
2361
2617
  const result = await res.json();
2362
- if (result.inviteLink) {
2363
- sonner.toast.success(`User invite created! Invite link: ${result.inviteLink}
2364
-
2365
- Note: ${result.note}`);
2366
- }
2367
- onSaveSuccess?.();
2618
+ onSaveSuccess?.(result);
2368
2619
  onClose();
2369
2620
  } catch (error) {
2370
2621
  console.error("Error saving data:", error);
@@ -2374,6 +2625,7 @@ Note: ${result.note}`);
2374
2625
  const visibleColumns = columns.filter((col) => {
2375
2626
  if (col.hideInForm) return false;
2376
2627
  if (!existingData && col.hideInCreate) return false;
2628
+ if (existingData && col.hideInEdit) return false;
2377
2629
  return true;
2378
2630
  });
2379
2631
  const isFieldDisabled = /* @__PURE__ */ __name((path) => {
@@ -2410,7 +2662,7 @@ Note: ${result.note}`);
2410
2662
  const selectValue = optionSet && rawStr !== "" && optionSet.has(rawStr) ? rawStr : void 0;
2411
2663
  return /* @__PURE__ */ React26__namespace.default.createElement(React26__namespace.default.Fragment, {
2412
2664
  key: path
2413
- }, /* @__PURE__ */ React26__namespace.default.createElement("div", null, /* @__PURE__ */ React26__namespace.default.createElement(Label3, {
2665
+ }, /* @__PURE__ */ React26__namespace.default.createElement("div", null, col.type !== "image" && /* @__PURE__ */ React26__namespace.default.createElement(Label3, {
2414
2666
  className: "block text-sm font-medium mb-1"
2415
2667
  }, col.displayName, [
2416
2668
  "subtotal",
@@ -2537,6 +2789,16 @@ Note: ${result.note}`);
2537
2789
  disabled
2538
2790
  }) : col.type === "file" ? /* @__PURE__ */ React26__namespace.default.createElement(FileUpload, {
2539
2791
  onUploadSuccess: /* @__PURE__ */ __name((url) => handleFileUpload(path, url), "onUploadSuccess")
2792
+ }) : col.type === "image" ? /* @__PURE__ */ React26__namespace.default.createElement(ImageOrUrlField, {
2793
+ label: col.displayName,
2794
+ value: typeof formData[path] === "string" ? formData[path] : "",
2795
+ onChange: /* @__PURE__ */ __name((url) => setFormData((prev) => ({
2796
+ ...prev,
2797
+ [path]: url
2798
+ })), "onChange"),
2799
+ placeholder: col.placeholder ?? "Image URL or upload",
2800
+ previewVariant: "logo",
2801
+ labelClassName: "block text-sm font-medium mb-1"
2540
2802
  }) : /* @__PURE__ */ React26__namespace.default.createElement(Input, {
2541
2803
  type: col.type || "text",
2542
2804
  placeholder: [
@@ -2582,6 +2844,7 @@ var init_CreateEditForm = __esm({
2582
2844
  init_switch();
2583
2845
  init_label();
2584
2846
  init_file_upload();
2847
+ init_ImageOrUrlField();
2585
2848
  init_RelationAutocomplete();
2586
2849
  init_RelationMultiSelect();
2587
2850
  init_use_mobile();
@@ -3933,11 +4196,7 @@ function formatArrayListCell(value, col) {
3933
4196
  return items.join(", ");
3934
4197
  }
3935
4198
  function formatCellValue(value, col) {
3936
- if (col.type === "boolean") return value ? /* @__PURE__ */ React.createElement(LucideIcons.Check, {
3937
- className: "h-4 w-4 text-green-600"
3938
- }) : /* @__PURE__ */ React.createElement(LucideIcons.X, {
3939
- className: "h-4 w-4 text-red-600"
3940
- });
4199
+ if (col.type === "boolean") return value ? "Yes" : "No";
3941
4200
  if (col.type === "date") return formatDate(value);
3942
4201
  if (col.type === "datetime") return formatDateTime(value);
3943
4202
  if (col.type === "multiSelect" || Array.isArray(value) || typeof value === "string" && value.trim().startsWith("[")) {
@@ -4118,6 +4377,9 @@ function AdminCRUD({ title, apiEndpoint, columns, addEditPageUrl, customViewPage
4118
4377
  const [bulkDialogOpen, setBulkDialogOpen] = React26.useState(false);
4119
4378
  const [isRefetching, setIsRefetching] = React26.useState(false);
4120
4379
  const [roleOptions, setRoleOptions] = React26.useState([]);
4380
+ const [inviteDialog, setInviteDialog] = React26.useState(null);
4381
+ const [sendingInviteEmail, setSendingInviteEmail] = React26.useState(false);
4382
+ const [linkCopied, setLinkCopied] = React26.useState(false);
4121
4383
  const hasLoadedRef = React26.useRef(false);
4122
4384
  const isMobile = useIsMobile();
4123
4385
  const showGroupColumn = !!manageUserGroups && roleOptions.length > 0;
@@ -4576,22 +4838,77 @@ function AdminCRUD({ title, apiEndpoint, columns, addEditPageUrl, customViewPage
4576
4838
  method: "POST",
4577
4839
  headers: {
4578
4840
  "Content-Type": "application/json"
4579
- }
4841
+ },
4842
+ body: JSON.stringify({
4843
+ sendEmail: true,
4844
+ rotate: true
4845
+ })
4580
4846
  });
4581
4847
  if (!res.ok) {
4582
4848
  const error2 = await res.json();
4583
- throw new Error(error2.error || "Failed to regenerate invite");
4849
+ throw new Error(error2.error || "Failed to resend invite");
4584
4850
  }
4585
4851
  const result = await res.json();
4586
- if (result.inviteLink) {
4587
- const note = result.note ? ` ${result.note}` : "";
4588
- sonner.toast.success(`New invite link generated.${note}`);
4589
- }
4852
+ sonner.toast.success(result.message || "Invite resent. Previous invite link is no longer valid.");
4853
+ setRefreshKey((k) => k + 1);
4590
4854
  } catch (error2) {
4591
4855
  console.error("Error regenerating invite:", error2);
4592
- sonner.toast.error(error2 instanceof Error ? error2.message : "Failed to regenerate invite");
4856
+ sonner.toast.error(error2 instanceof Error ? error2.message : "Failed to resend invite");
4593
4857
  }
4594
4858
  }, "handleRegenerateInvite");
4859
+ const copyInviteLink = /* @__PURE__ */ __name(async () => {
4860
+ const inviteLink = inviteDialog?.inviteLink;
4861
+ if (!inviteLink) {
4862
+ sonner.toast.error("Invite link is not available");
4863
+ return;
4864
+ }
4865
+ try {
4866
+ await navigator.clipboard.writeText(inviteLink);
4867
+ setLinkCopied(true);
4868
+ sonner.toast.success("Invite link copied");
4869
+ window.setTimeout(() => setLinkCopied(false), 2e3);
4870
+ } catch {
4871
+ sonner.toast.error("Could not copy invite link");
4872
+ }
4873
+ }, "copyInviteLink");
4874
+ const sendInviteEmailFromDialog = /* @__PURE__ */ __name(async () => {
4875
+ if (!inviteDialog) return;
4876
+ setSendingInviteEmail(true);
4877
+ try {
4878
+ const res = await fetch(`/api/users/${inviteDialog.userId}/regenerate-invite`, {
4879
+ method: "POST",
4880
+ headers: {
4881
+ "Content-Type": "application/json"
4882
+ },
4883
+ body: JSON.stringify({
4884
+ sendEmail: true,
4885
+ rotate: false
4886
+ })
4887
+ });
4888
+ const data2 = await res.json();
4889
+ if (!res.ok) {
4890
+ sonner.toast.error(data2.error || data2.message || "Failed to send invite email");
4891
+ return;
4892
+ }
4893
+ const nextLink = typeof data2.inviteLink === "string" ? data2.inviteLink.trim() : "";
4894
+ if (nextLink) {
4895
+ setInviteDialog((prev) => prev ? {
4896
+ ...prev,
4897
+ inviteLink: nextLink
4898
+ } : prev);
4899
+ }
4900
+ sonner.toast.success(data2.emailSent ? "Invite email sent" : data2.message || "Invite email queued");
4901
+ } catch {
4902
+ sonner.toast.error("Failed to send invite email");
4903
+ } finally {
4904
+ setSendingInviteEmail(false);
4905
+ }
4906
+ }, "sendInviteEmailFromDialog");
4907
+ const closeInviteDialog = /* @__PURE__ */ __name(() => {
4908
+ setInviteDialog(null);
4909
+ setLinkCopied(false);
4910
+ setRefreshKey((k) => k + 1);
4911
+ }, "closeInviteDialog");
4595
4912
  const addEditPage = addEditPageUrl && addEditPageUrl.length > 0;
4596
4913
  const createQueryString = React26.useMemo(() => {
4597
4914
  if (!createQueryParams || Object.keys(createQueryParams).length === 0) return "";
@@ -4869,11 +5186,11 @@ function AdminCRUD({ title, apiEndpoint, columns, addEditPageUrl, customViewPage
4869
5186
  onClick: /* @__PURE__ */ __name(() => handleDuplicateClick(item), "onClick")
4870
5187
  }, /* @__PURE__ */ React.createElement(LucideIcons.Copy, {
4871
5188
  className: "h-4 w-4 mr-2"
4872
- }), "Duplicate")), resourceName === "users" && /* @__PURE__ */ React.createElement(DropdownMenuItem, {
5189
+ }), "Duplicate")), resourceName === "users" && String(item.inviteStatus ?? "") === "pending" && /* @__PURE__ */ React.createElement(DropdownMenuItem, {
4873
5190
  onClick: /* @__PURE__ */ __name(() => handleRegenerateInvite(Number(item.id)), "onClick")
4874
5191
  }, /* @__PURE__ */ React.createElement(LucideIcons.RefreshCw, {
4875
5192
  className: "h-4 w-4 mr-2"
4876
- }), "Regenerate Invite"), /* @__PURE__ */ React.createElement(DropdownMenuItem, {
5193
+ }), "Resend invite"), /* @__PURE__ */ React.createElement(DropdownMenuItem, {
4877
5194
  onClick: /* @__PURE__ */ __name(() => handleDeleteClick(item), "onClick"),
4878
5195
  className: "text-red-600 focus:text-red-600"
4879
5196
  }, /* @__PURE__ */ React.createElement(LucideIcons.Trash2, {
@@ -4977,17 +5294,17 @@ function AdminCRUD({ title, apiEndpoint, columns, addEditPageUrl, customViewPage
4977
5294
  className: "h-3.5 w-3.5"
4978
5295
  }), /* @__PURE__ */ React.createElement("span", {
4979
5296
  className: "sr-only"
4980
- }, "Duplicate")), resourceName === "users" && /* @__PURE__ */ React.createElement(Button, {
5297
+ }, "Duplicate")), resourceName === "users" && String(item.inviteStatus ?? "") === "pending" && /* @__PURE__ */ React.createElement(Button, {
4981
5298
  variant: "outline",
4982
5299
  size: "icon",
4983
5300
  className: "h-7 w-7",
4984
5301
  onClick: /* @__PURE__ */ __name(() => handleRegenerateInvite(Number(item.id)), "onClick"),
4985
- title: "Regenerate Invite"
5302
+ title: "Resend invite"
4986
5303
  }, /* @__PURE__ */ React.createElement(LucideIcons.RefreshCw, {
4987
5304
  className: "h-3.5 w-3.5"
4988
5305
  }), /* @__PURE__ */ React.createElement("span", {
4989
5306
  className: "sr-only"
4990
- }, "Regenerate Invite")), /* @__PURE__ */ React.createElement(Button, {
5307
+ }, "Resend invite")), /* @__PURE__ */ React.createElement(Button, {
4991
5308
  variant: "outline",
4992
5309
  size: "icon",
4993
5310
  className: "h-7 w-7 border-red-300 text-red-600 hover:text-red-700",
@@ -5036,12 +5353,55 @@ function AdminCRUD({ title, apiEndpoint, columns, addEditPageUrl, customViewPage
5036
5353
  setIsFormOpen(false);
5037
5354
  setRefreshKey((k) => k + 1);
5038
5355
  }, "onClose"),
5356
+ onSaveSuccess: /* @__PURE__ */ __name((result) => {
5357
+ if (resourceName === "users" && result && typeof result.inviteLink === "string" && result.inviteLink.trim() && !editingItem) {
5358
+ const userId = Number(result.user?.id ?? result.id);
5359
+ const inviteLink = result.inviteLink.trim();
5360
+ if (Number.isFinite(userId) && userId > 0) {
5361
+ setLinkCopied(false);
5362
+ setInviteDialog({
5363
+ userId,
5364
+ inviteLink
5365
+ });
5366
+ sonner.toast.success(typeof result.message === "string" ? result.message : "User created successfully");
5367
+ return;
5368
+ }
5369
+ }
5370
+ setRefreshKey((k) => k + 1);
5371
+ }, "onSaveSuccess"),
5039
5372
  apiEndpoint,
5040
5373
  columns,
5041
5374
  existingData: editingItem,
5042
5375
  duplicateSeed,
5043
5376
  resource: resourceName
5044
5377
  }), /* @__PURE__ */ React.createElement(Dialog, {
5378
+ open: inviteDialog != null,
5379
+ onOpenChange: /* @__PURE__ */ __name((open) => {
5380
+ if (!open) closeInviteDialog();
5381
+ }, "onOpenChange")
5382
+ }, /* @__PURE__ */ React.createElement(DialogContent, {
5383
+ className: "max-w-md"
5384
+ }, /* @__PURE__ */ React.createElement(DialogHeader, null, /* @__PURE__ */ React.createElement(DialogTitle, null, "User created"), /* @__PURE__ */ React.createElement(DialogDescription, null, "Send an invite email, or copy the invite link to share another way. The link is not shown here.")), /* @__PURE__ */ React.createElement("div", {
5385
+ className: "flex flex-col gap-2 py-2"
5386
+ }, /* @__PURE__ */ React.createElement(Button, {
5387
+ type: "button",
5388
+ disabled: sendingInviteEmail,
5389
+ onClick: /* @__PURE__ */ __name(() => void sendInviteEmailFromDialog(), "onClick")
5390
+ }, /* @__PURE__ */ React.createElement(LucideIcons.Mail, {
5391
+ className: "h-4 w-4 mr-2"
5392
+ }), sendingInviteEmail ? "Sending\u2026" : "Send email"), /* @__PURE__ */ React.createElement(Button, {
5393
+ type: "button",
5394
+ variant: "outline",
5395
+ onClick: /* @__PURE__ */ __name(() => void copyInviteLink(), "onClick")
5396
+ }, linkCopied ? /* @__PURE__ */ React.createElement(LucideIcons.Check, {
5397
+ className: "h-4 w-4 mr-2"
5398
+ }) : /* @__PURE__ */ React.createElement(LucideIcons.Copy, {
5399
+ className: "h-4 w-4 mr-2"
5400
+ }), linkCopied ? "Copied" : "Copy invite link")), /* @__PURE__ */ React.createElement(DialogFooter, null, /* @__PURE__ */ React.createElement(Button, {
5401
+ type: "button",
5402
+ variant: "secondary",
5403
+ onClick: closeInviteDialog
5404
+ }, "Done")))), /* @__PURE__ */ React.createElement(Dialog, {
5045
5405
  open: deleteDialogOpen,
5046
5406
  onOpenChange: /* @__PURE__ */ __name((open) => {
5047
5407
  console.debug("[CRUD][delete] dialog onOpenChange", {
@@ -7767,155 +8127,6 @@ var init_ComponentSettings = __esm({
7767
8127
  __name(ComponentSettings, "ComponentSettings");
7768
8128
  }
7769
8129
  });
7770
- function ImageOrUrlField({ label, value, onChange, placeholder = "https://\u2026", inputClassName = "w-full rounded-md border border-gray-300 px-2 py-1.5 text-sm", labelClassName = "block text-xs font-medium text-gray-600 mb-1", previewVariant = "banner", maxSizeMb = 10 }) {
7771
- const fileInputRef = React26.useRef(null);
7772
- const [isUploading, setIsUploading] = React26.useState(false);
7773
- const [error, setError] = React26.useState(null);
7774
- const [lightboxOpen, setLightboxOpen] = React26.useState(false);
7775
- const previewCls = previewVariant === "logo" ? "h-20 w-20 rounded-md border border-gray-200 bg-white object-contain cursor-pointer" : "max-h-32 w-full rounded-md border border-gray-200 bg-gray-50 object-cover cursor-pointer";
7776
- const closeLightbox = React26.useCallback(() => setLightboxOpen(false), []);
7777
- React26.useEffect(() => {
7778
- if (!lightboxOpen) return;
7779
- const onKeyDown = /* @__PURE__ */ __name((e) => {
7780
- if (e.key === "Escape") closeLightbox();
7781
- }, "onKeyDown");
7782
- window.addEventListener("keydown", onKeyDown);
7783
- const prevOverflow = document.body.style.overflow;
7784
- document.body.style.overflow = "hidden";
7785
- return () => {
7786
- window.removeEventListener("keydown", onKeyDown);
7787
- document.body.style.overflow = prevOverflow;
7788
- };
7789
- }, [
7790
- lightboxOpen,
7791
- closeLightbox
7792
- ]);
7793
- const handleUpload = React26.useCallback(async (file) => {
7794
- setError(null);
7795
- if (!ACCEPTED_TYPES.includes(file.type)) {
7796
- setError(`Unsupported file type. Use: ${ACCEPTED_TYPES.map((t) => t.replace("image/", "")).join(", ")}`);
7797
- return;
7798
- }
7799
- if (file.size > maxSizeMb * 1024 * 1024) {
7800
- setError(`File must be under ${maxSizeMb}MB`);
7801
- return;
7802
- }
7803
- setIsUploading(true);
7804
- try {
7805
- const formData = new FormData();
7806
- formData.append("file", file);
7807
- const response = await fetch("/api/upload", {
7808
- method: "POST",
7809
- body: formData
7810
- });
7811
- const data = await response.json();
7812
- if (!response.ok) {
7813
- throw new Error(data.error || data.details || "Upload failed");
7814
- }
7815
- onChange(data.filePath ?? "");
7816
- } catch (err) {
7817
- setError(err instanceof Error ? err.message : "Upload failed");
7818
- } finally {
7819
- setIsUploading(false);
7820
- if (fileInputRef.current) fileInputRef.current.value = "";
7821
- }
7822
- }, [
7823
- maxSizeMb,
7824
- onChange
7825
- ]);
7826
- const onFileChange = React26.useCallback((e) => {
7827
- const file = e.target.files?.[0];
7828
- if (file) void handleUpload(file);
7829
- }, [
7830
- handleUpload
7831
- ]);
7832
- const trimmed = value.trim();
7833
- return /* @__PURE__ */ React.createElement("div", {
7834
- className: "space-y-2"
7835
- }, /* @__PURE__ */ React.createElement("label", {
7836
- className: labelClassName
7837
- }, label), trimmed ? /* @__PURE__ */ React.createElement("div", {
7838
- className: "flex items-start gap-3"
7839
- }, /* @__PURE__ */ React.createElement("img", {
7840
- src: trimmed,
7841
- alt: label,
7842
- className: previewCls,
7843
- role: "button",
7844
- tabIndex: 0,
7845
- title: "Click to enlarge",
7846
- onClick: /* @__PURE__ */ __name(() => setLightboxOpen(true), "onClick"),
7847
- onKeyDown: /* @__PURE__ */ __name((e) => {
7848
- if (e.key === "Enter" || e.key === " ") {
7849
- e.preventDefault();
7850
- setLightboxOpen(true);
7851
- }
7852
- }, "onKeyDown"),
7853
- onError: /* @__PURE__ */ __name((e) => {
7854
- e.currentTarget.style.display = "none";
7855
- }, "onError")
7856
- }), /* @__PURE__ */ React.createElement("button", {
7857
- type: "button",
7858
- onClick: /* @__PURE__ */ __name(() => onChange(""), "onClick"),
7859
- className: "inline-flex items-center gap-1 rounded border border-gray-300 bg-white px-2 py-1 text-xs text-gray-600 hover:bg-gray-50"
7860
- }, /* @__PURE__ */ React.createElement(LucideIcons.X, {
7861
- className: "h-3 w-3"
7862
- }), "Clear")) : null, /* @__PURE__ */ React.createElement("div", {
7863
- className: "flex flex-wrap gap-2"
7864
- }, /* @__PURE__ */ React.createElement("input", {
7865
- type: "url",
7866
- value,
7867
- onChange: /* @__PURE__ */ __name((e) => {
7868
- setError(null);
7869
- onChange(e.target.value);
7870
- }, "onChange"),
7871
- placeholder,
7872
- className: `${inputClassName} min-w-0 flex-1`
7873
- }), /* @__PURE__ */ React.createElement("input", {
7874
- ref: fileInputRef,
7875
- type: "file",
7876
- accept: ACCEPTED_TYPES.join(","),
7877
- onChange: onFileChange,
7878
- className: "hidden",
7879
- disabled: isUploading
7880
- }), /* @__PURE__ */ React.createElement("button", {
7881
- type: "button",
7882
- onClick: /* @__PURE__ */ __name(() => fileInputRef.current?.click(), "onClick"),
7883
- disabled: isUploading,
7884
- className: "inline-flex shrink-0 items-center gap-1.5 rounded-md border border-gray-300 bg-white px-3 py-1.5 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:opacity-50"
7885
- }, /* @__PURE__ */ React.createElement(LucideIcons.Upload, {
7886
- className: "h-3.5 w-3.5"
7887
- }), isUploading ? "Uploading\u2026" : "Upload")), error ? /* @__PURE__ */ React.createElement("p", {
7888
- className: "flex items-center gap-1.5 text-xs text-red-600"
7889
- }, /* @__PURE__ */ React.createElement(LucideIcons.AlertCircle, {
7890
- className: "h-3.5 w-3.5 shrink-0"
7891
- }), error) : /* @__PURE__ */ React.createElement("p", {
7892
- className: "text-xs text-gray-500"
7893
- }, "Paste a URL or upload an image (PNG, JPG, GIF, WEBP up to ", maxSizeMb, "MB)"), lightboxOpen && trimmed ? /* @__PURE__ */ React.createElement("div", {
7894
- className: "fixed inset-0 z-[100] flex items-center justify-center bg-black/70 p-4",
7895
- role: "dialog",
7896
- "aria-modal": "true",
7897
- "aria-label": `${label} preview`,
7898
- onClick: closeLightbox
7899
- }, /* @__PURE__ */ React.createElement("img", {
7900
- src: trimmed,
7901
- alt: label,
7902
- className: "max-h-[90vh] max-w-[90vw] rounded-md object-contain shadow-lg",
7903
- onClick: /* @__PURE__ */ __name((e) => e.stopPropagation(), "onClick")
7904
- })) : null);
7905
- }
7906
- var ACCEPTED_TYPES;
7907
- var init_ImageOrUrlField = __esm({
7908
- "src/components/Admin/ImageOrUrlField.tsx"() {
7909
- "use client";
7910
- ACCEPTED_TYPES = [
7911
- "image/jpeg",
7912
- "image/png",
7913
- "image/gif",
7914
- "image/webp"
7915
- ];
7916
- __name(ImageOrUrlField, "ImageOrUrlField");
7917
- }
7918
- });
7919
8130
  function generateId() {
7920
8131
  return `nav_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
7921
8132
  }
@@ -8915,7 +9126,7 @@ var init_AuthFooter = __esm({
8915
9126
  });
8916
9127
  function AuthPageLayout({ children }) {
8917
9128
  return /* @__PURE__ */ React.createElement("div", {
8918
- className: "min-h-screen flex flex-col bg-gray-50 dark:bg-dark"
9129
+ className: "min-h-screen flex flex-col bg-gray-50"
8919
9130
  }, /* @__PURE__ */ React.createElement("div", {
8920
9131
  className: "flex-1 flex items-center justify-center px-4 py-6"
8921
9132
  }, /* @__PURE__ */ React.createElement("div", {
@@ -8956,6 +9167,7 @@ var init_SignInPage = __esm({
8956
9167
  const [email, setEmail] = React26.useState("");
8957
9168
  const [password, setPassword] = React26.useState("");
8958
9169
  const [error, setError] = React26.useState("");
9170
+ const [success, setSuccess] = React26.useState("");
8959
9171
  const [loading, setLoading] = React26.useState(false);
8960
9172
  const { status } = react.useSession();
8961
9173
  const searchParams = navigation.useSearchParams();
@@ -8963,6 +9175,9 @@ var init_SignInPage = __esm({
8963
9175
  if (searchParams.get("error")) {
8964
9176
  setError("Invalid email or password");
8965
9177
  }
9178
+ if (searchParams.get("activated") === "1") {
9179
+ setSuccess("Account activated. Sign in with your new password.");
9180
+ }
8966
9181
  }, [
8967
9182
  searchParams
8968
9183
  ]);
@@ -9023,41 +9238,45 @@ var init_SignInPage = __esm({
9023
9238
  }
9024
9239
  }, "handleSubmit");
9025
9240
  return /* @__PURE__ */ React.createElement(AuthPageLayout, null, /* @__PURE__ */ React.createElement("div", {
9026
- className: "w-full shadow-md rounded-lg bg-white dark:bg-dark px-4 py-6 sm:px-6 sm:py-8"
9241
+ className: "w-full shadow-md rounded-lg bg-white px-4 py-6 sm:px-6 sm:py-8"
9027
9242
  }, /* @__PURE__ */ React.createElement("h3", {
9028
- className: "mb-1 text-center text-xl font-bold text-black dark:text-white sm:text-2xl"
9243
+ className: "mb-1 text-center text-xl font-bold text-black sm:text-2xl"
9029
9244
  }, "Sign in"), /* @__PURE__ */ React.createElement("p", {
9030
9245
  className: "mb-6 text-center text-sm text-body-color"
9031
- }, "Enter your credentials"), error && /* @__PURE__ */ React.createElement("div", {
9032
- className: "mb-4 rounded-md bg-red-50 p-3 text-sm text-red-600 dark:bg-red-900/20 dark:text-red-400"
9246
+ }, "Enter your credentials"), success && /* @__PURE__ */ React.createElement("div", {
9247
+ className: "mb-4 rounded-md bg-green-50 p-3 text-sm text-green-700"
9248
+ }, success), error && /* @__PURE__ */ React.createElement("div", {
9249
+ className: "mb-4 rounded-md bg-red-50 p-3 text-sm text-red-600"
9033
9250
  }, error), /* @__PURE__ */ React.createElement("form", {
9034
9251
  onSubmit: handleSubmit
9035
9252
  }, /* @__PURE__ */ React.createElement("div", {
9036
9253
  className: "mb-4"
9037
9254
  }, /* @__PURE__ */ React.createElement("label", {
9038
9255
  htmlFor: "email",
9039
- className: "mb-1.5 block text-sm text-dark dark:text-white"
9256
+ className: "mb-1.5 block text-sm text-gray-900"
9040
9257
  }, "Email"), /* @__PURE__ */ React.createElement("input", {
9041
9258
  type: "email",
9042
9259
  name: "email",
9260
+ id: "email",
9043
9261
  value: email,
9044
9262
  onChange: /* @__PURE__ */ __name((e) => setEmail(e.target.value), "onChange"),
9045
9263
  placeholder: "Enter email",
9046
9264
  required: true,
9047
- className: "border border-gray-300 w-full rounded bg-gray-50 px-3 py-2 text-sm text-gray-900 outline-none focus:border-gray-500 focus:ring-1 focus:ring-gray-500 dark:bg-dark dark:border-gray-600"
9265
+ className: "border border-gray-300 w-full rounded bg-gray-50 px-3 py-2 text-sm text-gray-900 outline-none focus:border-gray-500 focus:ring-1 focus:ring-gray-500"
9048
9266
  })), /* @__PURE__ */ React.createElement("div", {
9049
9267
  className: "mb-4"
9050
9268
  }, /* @__PURE__ */ React.createElement("label", {
9051
9269
  htmlFor: "password",
9052
- className: "mb-1.5 block text-sm text-dark dark:text-white"
9270
+ className: "mb-1.5 block text-sm text-gray-900"
9053
9271
  }, "Password"), /* @__PURE__ */ React.createElement("input", {
9054
9272
  type: "password",
9055
9273
  name: "password",
9274
+ id: "password",
9056
9275
  value: password,
9057
9276
  onChange: /* @__PURE__ */ __name((e) => setPassword(e.target.value), "onChange"),
9058
9277
  placeholder: "Enter password",
9059
9278
  required: true,
9060
- className: "border border-gray-300 w-full rounded bg-gray-50 px-3 py-2 text-sm text-gray-900 outline-none focus:border-gray-500 focus:ring-1 focus:ring-gray-500 dark:bg-dark dark:border-gray-600"
9279
+ className: "border border-gray-300 w-full rounded bg-gray-50 px-3 py-2 text-sm text-gray-900 outline-none focus:border-gray-500 focus:ring-1 focus:ring-gray-500"
9061
9280
  })), /* @__PURE__ */ React.createElement("div", {
9062
9281
  className: "mb-4 flex items-center justify-between"
9063
9282
  }, /* @__PURE__ */ React.createElement("label", {
@@ -9071,7 +9290,7 @@ var init_SignInPage = __esm({
9071
9290
  }, "Forgot password?")), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("button", {
9072
9291
  type: "submit",
9073
9292
  disabled: loading,
9074
- className: "w-full rounded bg-gray-900 px-4 py-2 text-sm font-medium text-white hover:bg-gray-800 disabled:opacity-50 disabled:cursor-not-allowed dark:bg-gray-800 dark:hover:bg-gray-700"
9293
+ className: "w-full rounded bg-gray-900 px-4 py-2 text-sm font-medium text-white hover:bg-gray-800 disabled:opacity-50 disabled:cursor-not-allowed"
9075
9294
  }, loading ? "Signing in..." : "Sign in")))));
9076
9295
  }, "SigninPage");
9077
9296
  exports.AdminSignInPage = SigninPage;
@@ -9115,11 +9334,11 @@ function ForgotPasswordPage() {
9115
9334
  }
9116
9335
  }, "handleSubmit");
9117
9336
  return /* @__PURE__ */ React.createElement(AuthPageLayout, null, /* @__PURE__ */ React.createElement("div", {
9118
- className: "w-full space-y-4 p-5 sm:p-6 bg-white dark:bg-[#2C303B] rounded-lg shadow-md"
9337
+ className: "w-full space-y-4 p-5 sm:p-6 bg-white rounded-lg shadow-md"
9119
9338
  }, /* @__PURE__ */ React.createElement("div", {
9120
9339
  className: "text-center"
9121
9340
  }, /* @__PURE__ */ React.createElement("h2", {
9122
- className: "text-xl font-bold text-gray-900 dark:text-white"
9341
+ className: "text-xl font-bold text-gray-900"
9123
9342
  }, "Forgot password"), /* @__PURE__ */ React.createElement("p", {
9124
9343
  className: "mt-1 text-sm text-body-color"
9125
9344
  }, "Enter your email for a reset link.")), /* @__PURE__ */ React.createElement("form", {
@@ -9137,7 +9356,7 @@ function ForgotPasswordPage() {
9137
9356
  placeholder: "you@example.com",
9138
9357
  className: "mt-1 h-9 text-sm"
9139
9358
  })), message && /* @__PURE__ */ React.createElement("div", {
9140
- className: `p-2.5 rounded-md text-sm ${message.includes("receive") ? "bg-green-50 dark:bg-green-900/20 text-green-700 dark:text-green-400" : "bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-400"}`
9359
+ className: `p-2.5 rounded-md text-sm ${message.includes("receive") ? "bg-green-50 text-green-700" : "bg-red-50 text-red-700"}`
9141
9360
  }, message), /* @__PURE__ */ React.createElement(Button, {
9142
9361
  type: "submit",
9143
9362
  disabled: loading,
@@ -9220,9 +9439,9 @@ function ResetPasswordPageContent() {
9220
9439
  }, "handleSubmit");
9221
9440
  if (!token) {
9222
9441
  return /* @__PURE__ */ React.createElement(AuthPageLayout, null, /* @__PURE__ */ React.createElement("div", {
9223
- className: "w-full space-y-4 p-5 sm:p-6 bg-white dark:bg-[#2C303B] rounded-lg shadow-md text-center"
9442
+ className: "w-full space-y-4 p-5 sm:p-6 bg-white rounded-lg shadow-md text-center"
9224
9443
  }, /* @__PURE__ */ React.createElement("h2", {
9225
- className: "text-xl font-bold text-gray-900 dark:text-white"
9444
+ className: "text-xl font-bold text-gray-900"
9226
9445
  }, "Invalid reset link"), /* @__PURE__ */ React.createElement("p", {
9227
9446
  className: "text-sm text-body-color"
9228
9447
  }, message), /* @__PURE__ */ React.createElement(Link2__default.default, {
@@ -9231,11 +9450,11 @@ function ResetPasswordPageContent() {
9231
9450
  }, "Request a new link")));
9232
9451
  }
9233
9452
  return /* @__PURE__ */ React.createElement(AuthPageLayout, null, /* @__PURE__ */ React.createElement("div", {
9234
- className: "w-full space-y-4 p-5 sm:p-6 bg-white dark:bg-[#2C303B] rounded-lg shadow-md"
9453
+ className: "w-full space-y-4 p-5 sm:p-6 bg-white rounded-lg shadow-md"
9235
9454
  }, /* @__PURE__ */ React.createElement("div", {
9236
9455
  className: "text-center"
9237
9456
  }, /* @__PURE__ */ React.createElement("h2", {
9238
- className: "text-xl font-bold text-gray-900 dark:text-white"
9457
+ className: "text-xl font-bold text-gray-900"
9239
9458
  }, "Set new password"), /* @__PURE__ */ React.createElement("p", {
9240
9459
  className: "mt-1 text-sm text-body-color"
9241
9460
  }, "Enter your new password.")), /* @__PURE__ */ React.createElement("form", {
@@ -9270,7 +9489,7 @@ function ResetPasswordPageContent() {
9270
9489
  }), "onChange"),
9271
9490
  className: "mt-1 h-9 text-sm"
9272
9491
  })), message && /* @__PURE__ */ React.createElement("div", {
9273
- className: `p-2.5 rounded-md text-sm ${message.includes("successfully") || message.includes("now sign in") ? "bg-green-50 dark:bg-green-900/20 text-green-700 dark:text-green-400" : "bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-400"}`
9492
+ className: `p-2.5 rounded-md text-sm ${message.includes("successfully") || message.includes("now sign in") ? "bg-green-50 text-green-700" : "bg-red-50 text-red-700"}`
9274
9493
  }, message), /* @__PURE__ */ React.createElement(Button, {
9275
9494
  type: "submit",
9276
9495
  disabled: loading,
@@ -9285,7 +9504,7 @@ function ResetPasswordPageContent() {
9285
9504
  function ResetPasswordPage() {
9286
9505
  return /* @__PURE__ */ React.createElement(React26.Suspense, {
9287
9506
  fallback: /* @__PURE__ */ React.createElement("div", {
9288
- className: "min-h-screen flex items-center justify-center bg-gray-50 dark:bg-dark"
9507
+ className: "min-h-screen flex items-center justify-center bg-gray-50"
9289
9508
  }, /* @__PURE__ */ React.createElement("div", {
9290
9509
  className: "max-w-[400px] w-full p-6 text-center"
9291
9510
  }, /* @__PURE__ */ React.createElement("div", {
@@ -9313,6 +9532,7 @@ __export(InvitePage_exports, {
9313
9532
  default: () => InvitePage
9314
9533
  });
9315
9534
  function InvitePageContent() {
9535
+ const router = navigation.useRouter();
9316
9536
  const searchParams = navigation.useSearchParams();
9317
9537
  const token = searchParams.get("token");
9318
9538
  const [formData, setFormData] = React26.useState({
@@ -9339,8 +9559,13 @@ function InvitePageContent() {
9339
9559
  setInviteValid(true);
9340
9560
  setMessage("");
9341
9561
  } else {
9562
+ const err = typeof result.error === "string" ? result.error : "";
9563
+ if (/already (active|accepted)/i.test(err)) {
9564
+ router.replace("/admin/signin?activated=1");
9565
+ return;
9566
+ }
9342
9567
  setInviteValid(false);
9343
- setMessage(result.error || "This invitation is no longer valid.");
9568
+ setMessage(err || "This invitation is no longer valid.");
9344
9569
  }
9345
9570
  } catch {
9346
9571
  if (!cancelled) {
@@ -9382,11 +9607,8 @@ function InvitePageContent() {
9382
9607
  });
9383
9608
  const result = await res.json();
9384
9609
  if (res.ok) {
9385
- setMessage("Account activated successfully! You can now log in.");
9386
- setFormData({
9387
- password: "",
9388
- confirmPassword: ""
9389
- });
9610
+ router.replace("/admin/signin?activated=1");
9611
+ return;
9390
9612
  } else {
9391
9613
  setMessage(result.error || "Failed to activate account");
9392
9614
  }
@@ -9452,7 +9674,7 @@ function InvitePageContent() {
9452
9674
  }), "onChange"),
9453
9675
  className: "mt-1 h-9 text-sm"
9454
9676
  })), message && /* @__PURE__ */ React26__namespace.default.createElement("div", {
9455
- className: `p-2.5 rounded-md text-sm ${message.includes("successfully") ? "bg-green-50 text-green-700" : "bg-red-50 text-red-700"}`
9677
+ className: "p-2.5 rounded-md text-sm bg-red-50 text-red-700"
9456
9678
  }, message), /* @__PURE__ */ React26__namespace.default.createElement(Button, {
9457
9679
  type: "submit",
9458
9680
  disabled: loading,
@@ -11218,6 +11440,15 @@ function renderListPrice(value, item) {
11218
11440
  function renderListThumbnail(url) {
11219
11441
  const trimmed = url.trim();
11220
11442
  if (!trimmed) return "\u2014";
11443
+ if (isVideoMediaUrl(trimmed)) {
11444
+ return React26.createElement("video", {
11445
+ src: trimmed,
11446
+ muted: true,
11447
+ playsInline: true,
11448
+ preload: "metadata",
11449
+ className: "h-10 w-10 rounded border border-gray-200 bg-black object-cover"
11450
+ });
11451
+ }
11221
11452
  return React26.createElement("img", {
11222
11453
  src: trimmed,
11223
11454
  alt: "",
@@ -11238,6 +11469,7 @@ function productListImageUrl(item) {
11238
11469
  exports.STORE_CRUD_CONFIGS = void 0;
11239
11470
  var init_store_crud_configs = __esm({
11240
11471
  "src/admin/store-crud-configs.ts"() {
11472
+ init_media_url();
11241
11473
  __name(renderListPrice, "renderListPrice");
11242
11474
  __name(renderListThumbnail, "renderListThumbnail");
11243
11475
  __name(productListImageUrl, "productListImageUrl");
@@ -11450,6 +11682,10 @@ var init_store_crud_configs = __esm({
11450
11682
  field: "name",
11451
11683
  displayName: "Name"
11452
11684
  },
11685
+ {
11686
+ field: "slug",
11687
+ displayName: "Slug"
11688
+ },
11453
11689
  {
11454
11690
  field: "eventId",
11455
11691
  displayName: "Event",
@@ -11943,6 +12179,14 @@ var init_store_crud_configs = __esm({
11943
12179
  title: "Categories",
11944
12180
  apiEndpoint: "/api/product_categories",
11945
12181
  columns: [
12182
+ {
12183
+ field: "image",
12184
+ displayName: "Image",
12185
+ type: "image",
12186
+ listFilter: false,
12187
+ placeholder: "Image URL or upload",
12188
+ render: /* @__PURE__ */ __name((value) => renderListThumbnail(typeof value === "string" ? value : ""), "render")
12189
+ },
11946
12190
  {
11947
12191
  field: "name",
11948
12192
  displayName: "Name"
@@ -12549,6 +12793,134 @@ var SettingsPage_exports = {};
12549
12793
  __export(SettingsPage_exports, {
12550
12794
  default: () => SettingsPage
12551
12795
  });
12796
+ function InvoiceTemplatePreview({ id }) {
12797
+ if (id === "modern") {
12798
+ return /* @__PURE__ */ React.createElement("div", {
12799
+ className: "h-28 rounded-md border border-slate-200 bg-white overflow-hidden shadow-sm"
12800
+ }, /* @__PURE__ */ React.createElement("div", {
12801
+ className: "h-7 bg-teal-700 px-2 flex flex-col justify-center"
12802
+ }, /* @__PURE__ */ React.createElement("div", {
12803
+ className: "h-1.5 w-14 rounded bg-white/90"
12804
+ }), /* @__PURE__ */ React.createElement("div", {
12805
+ className: "h-1 w-10 rounded bg-white/50 mt-1"
12806
+ })), /* @__PURE__ */ React.createElement("div", {
12807
+ className: "p-2 space-y-1.5"
12808
+ }, /* @__PURE__ */ React.createElement("div", {
12809
+ className: "flex gap-2"
12810
+ }, /* @__PURE__ */ React.createElement("div", {
12811
+ className: "flex-1 space-y-1"
12812
+ }, /* @__PURE__ */ React.createElement("div", {
12813
+ className: "h-1 w-8 bg-teal-600/70 rounded"
12814
+ }), /* @__PURE__ */ React.createElement("div", {
12815
+ className: "h-1 w-full bg-slate-200 rounded"
12816
+ }), /* @__PURE__ */ React.createElement("div", {
12817
+ className: "h-1 w-4/5 bg-slate-200 rounded"
12818
+ })), /* @__PURE__ */ React.createElement("div", {
12819
+ className: "flex-1 space-y-1"
12820
+ }, /* @__PURE__ */ React.createElement("div", {
12821
+ className: "h-1 w-8 bg-teal-600/70 rounded"
12822
+ }), /* @__PURE__ */ React.createElement("div", {
12823
+ className: "h-1 w-full bg-slate-200 rounded"
12824
+ }))), /* @__PURE__ */ React.createElement("div", {
12825
+ className: "h-1 w-full bg-slate-100 rounded"
12826
+ }), /* @__PURE__ */ React.createElement("div", {
12827
+ className: "h-1 w-full bg-slate-100 rounded"
12828
+ }), /* @__PURE__ */ React.createElement("div", {
12829
+ className: "ml-auto h-1.5 w-12 bg-teal-700/80 rounded"
12830
+ })));
12831
+ }
12832
+ if (id === "compact") {
12833
+ return /* @__PURE__ */ React.createElement("div", {
12834
+ className: "h-28 rounded-md border border-slate-300 bg-white overflow-hidden shadow-sm p-1.5 space-y-1"
12835
+ }, /* @__PURE__ */ React.createElement("div", {
12836
+ className: "h-4 bg-slate-100 rounded flex items-center px-1"
12837
+ }, /* @__PURE__ */ React.createElement("div", {
12838
+ className: "h-1 w-10 bg-slate-700 rounded"
12839
+ })), /* @__PURE__ */ React.createElement("div", {
12840
+ className: "grid grid-cols-4 gap-0.5"
12841
+ }, Array.from({
12842
+ length: 8
12843
+ }).map((_, i) => /* @__PURE__ */ React.createElement("div", {
12844
+ key: i,
12845
+ className: "h-1 bg-slate-200 rounded"
12846
+ }))), /* @__PURE__ */ React.createElement("div", {
12847
+ className: "space-y-0.5"
12848
+ }, Array.from({
12849
+ length: 5
12850
+ }).map((_, i) => /* @__PURE__ */ React.createElement("div", {
12851
+ key: i,
12852
+ className: "flex gap-0.5"
12853
+ }, /* @__PURE__ */ React.createElement("div", {
12854
+ className: "h-1 flex-[3] bg-slate-200 rounded"
12855
+ }), /* @__PURE__ */ React.createElement("div", {
12856
+ className: "h-1 flex-1 bg-slate-300 rounded"
12857
+ }), /* @__PURE__ */ React.createElement("div", {
12858
+ className: "h-1 flex-1 bg-slate-300 rounded"
12859
+ })))), /* @__PURE__ */ React.createElement("div", {
12860
+ className: "ml-auto h-1 w-10 bg-slate-800 rounded"
12861
+ }));
12862
+ }
12863
+ if (id === "bold") {
12864
+ return /* @__PURE__ */ React.createElement("div", {
12865
+ className: "h-28 rounded-md border border-red-200 bg-white overflow-hidden shadow-sm"
12866
+ }, /* @__PURE__ */ React.createElement("div", {
12867
+ className: "h-9 bg-red-800 px-2 flex flex-col justify-center gap-1"
12868
+ }, /* @__PURE__ */ React.createElement("div", {
12869
+ className: "h-2 w-16 rounded bg-white"
12870
+ }), /* @__PURE__ */ React.createElement("div", {
12871
+ className: "h-1 w-12 rounded bg-white/60"
12872
+ })), /* @__PURE__ */ React.createElement("div", {
12873
+ className: "p-2 space-y-1.5"
12874
+ }, /* @__PURE__ */ React.createElement("div", {
12875
+ className: "h-1 w-20 bg-slate-300 rounded"
12876
+ }), /* @__PURE__ */ React.createElement("div", {
12877
+ className: "border border-red-100 rounded p-1 space-y-0.5 bg-red-50/40"
12878
+ }, /* @__PURE__ */ React.createElement("div", {
12879
+ className: "h-1 w-full bg-slate-200 rounded"
12880
+ }), /* @__PURE__ */ React.createElement("div", {
12881
+ className: "h-1 w-full bg-slate-200 rounded"
12882
+ }), /* @__PURE__ */ React.createElement("div", {
12883
+ className: "h-1.5 w-14 ml-auto bg-red-800 rounded"
12884
+ }))));
12885
+ }
12886
+ return /* @__PURE__ */ React.createElement("div", {
12887
+ className: "h-28 rounded-md border border-slate-200 bg-white overflow-hidden shadow-sm p-2 space-y-1.5"
12888
+ }, /* @__PURE__ */ React.createElement("div", {
12889
+ className: "h-5 rounded bg-slate-100 px-1.5 flex items-center justify-between"
12890
+ }, /* @__PURE__ */ React.createElement("div", {
12891
+ className: "h-1.5 w-12 bg-slate-700 rounded"
12892
+ }), /* @__PURE__ */ React.createElement("div", {
12893
+ className: "h-1 w-8 bg-slate-400 rounded"
12894
+ })), /* @__PURE__ */ React.createElement("div", {
12895
+ className: "flex gap-2"
12896
+ }, /* @__PURE__ */ React.createElement("div", {
12897
+ className: "flex-1 space-y-0.5"
12898
+ }, /* @__PURE__ */ React.createElement("div", {
12899
+ className: "h-1 w-6 bg-slate-600 rounded"
12900
+ }), /* @__PURE__ */ React.createElement("div", {
12901
+ className: "h-1 w-full bg-slate-200 rounded"
12902
+ }), /* @__PURE__ */ React.createElement("div", {
12903
+ className: "h-1 w-3/4 bg-slate-200 rounded"
12904
+ })), /* @__PURE__ */ React.createElement("div", {
12905
+ className: "flex-1 space-y-0.5"
12906
+ }, /* @__PURE__ */ React.createElement("div", {
12907
+ className: "h-1 w-6 bg-slate-600 rounded"
12908
+ }), /* @__PURE__ */ React.createElement("div", {
12909
+ className: "h-1 w-full bg-slate-200 rounded"
12910
+ }))), /* @__PURE__ */ React.createElement("div", {
12911
+ className: "border-t border-slate-200 pt-1 space-y-0.5"
12912
+ }, /* @__PURE__ */ React.createElement("div", {
12913
+ className: "h-1 w-full bg-slate-100 rounded"
12914
+ }), /* @__PURE__ */ React.createElement("div", {
12915
+ className: "h-1 w-full bg-slate-100 rounded"
12916
+ }), /* @__PURE__ */ React.createElement("div", {
12917
+ className: "h-1 w-full bg-slate-100 rounded"
12918
+ })), /* @__PURE__ */ React.createElement("div", {
12919
+ className: "flex justify-end"
12920
+ }, /* @__PURE__ */ React.createElement("div", {
12921
+ className: "h-1.5 w-10 bg-slate-700 rounded"
12922
+ })));
12923
+ }
12552
12924
  function hexToHsl(hex) {
12553
12925
  const r = parseInt(hex.slice(1, 3), 16) / 255;
12554
12926
  const g = parseInt(hex.slice(3, 5), 16) / 255;
@@ -12599,6 +12971,25 @@ function SettingsPage() {
12599
12971
  const [requireEventApproval, setRequireEventApproval] = React26.useState(false);
12600
12972
  const [storeSettingsLoading, setStoreSettingsLoading] = React26.useState(true);
12601
12973
  const [currency, setCurrency] = React26.useState(DEFAULT_CURRENCY);
12974
+ const [invoiceTemplate, setInvoiceTemplate] = React26.useState("classic");
12975
+ const [companyLogo, setCompanyLogo] = React26.useState("");
12976
+ const [companyName, setCompanyName] = React26.useState("");
12977
+ const [companyEmail, setCompanyEmail] = React26.useState("");
12978
+ const [companyPhone, setCompanyPhone] = React26.useState("");
12979
+ const [companyAddress, setCompanyAddress] = React26.useState("");
12980
+ const handleStoreLogoChange = /* @__PURE__ */ __name((newLogo) => {
12981
+ setCompanyLogo(newLogo);
12982
+ setNavbarConfig((prev) => ({
12983
+ ...prev,
12984
+ logo: newLogo
12985
+ }));
12986
+ }, "handleStoreLogoChange");
12987
+ const handleNavbarConfigChange = /* @__PURE__ */ __name((newConfig) => {
12988
+ setNavbarConfig(newConfig);
12989
+ if (newConfig.logo !== companyLogo) {
12990
+ setCompanyLogo(newConfig.logo || "");
12991
+ }
12992
+ }, "handleNavbarConfigChange");
12602
12993
  const [currencies, setCurrencies] = React26.useState([]);
12603
12994
  const [currenciesLoading, setCurrenciesLoading] = React26.useState(true);
12604
12995
  const [showAddCurrency, setShowAddCurrency] = React26.useState(false);
@@ -12643,7 +13034,11 @@ function SettingsPage() {
12643
13034
  setActiveThemeId((data.activeThemeId || "").trim());
12644
13035
  if (data.navbar) {
12645
13036
  try {
12646
- setNavbarConfig(JSON.parse(data.navbar));
13037
+ const parsed = JSON.parse(data.navbar);
13038
+ setNavbarConfig(parsed);
13039
+ if (parsed.logo) {
13040
+ setCompanyLogo((prev) => prev || parsed.logo);
13041
+ }
12647
13042
  } catch {
12648
13043
  }
12649
13044
  }
@@ -12653,6 +13048,19 @@ function SettingsPage() {
12653
13048
  fetch("/api/settings/store").then((r) => r.ok ? r.json() : {}).then((data) => {
12654
13049
  setStoreEnabled(data.enabled === "true");
12655
13050
  setCurrency(data.currency || DEFAULT_CURRENCY);
13051
+ setInvoiceTemplate(data.invoiceTemplate || "classic");
13052
+ const logo = data.invoiceLogoUrl || data.companyLogo || data.logo || "";
13053
+ setCompanyLogo((prev) => logo || prev);
13054
+ setCompanyName(data.companyName || data.invoiceCompanyName || data.name || "");
13055
+ setCompanyEmail(data.companyEmail || data.invoiceEmail || data.email || "");
13056
+ setCompanyPhone(data.companyPhone || data.invoicePhone || data.phone || "");
13057
+ setCompanyAddress(data.companyAddress || data.invoiceAddress || data.address || "");
13058
+ if (logo) {
13059
+ setNavbarConfig((prev) => ({
13060
+ ...prev,
13061
+ logo: prev.logo || logo
13062
+ }));
13063
+ }
12656
13064
  }).finally(() => setStoreSettingsLoading(false));
12657
13065
  fetch("/api/settings/multi_vendor").then((r) => r.ok ? r.json() : {}).then((data) => {
12658
13066
  setMultiVendorEnabled(data.enabled !== "false");
@@ -12757,6 +13165,27 @@ function SettingsPage() {
12757
13165
  }
12758
13166
  })
12759
13167
  });
13168
+ await fetch("/api/settings/store", {
13169
+ method: "PUT",
13170
+ headers: {
13171
+ "Content-Type": "application/json"
13172
+ },
13173
+ body: JSON.stringify({
13174
+ invoiceLogoUrl: {
13175
+ value: navbarConfig.logo || "",
13176
+ type: "public"
13177
+ },
13178
+ companyLogo: {
13179
+ value: navbarConfig.logo || "",
13180
+ type: "public"
13181
+ },
13182
+ logo: {
13183
+ value: navbarConfig.logo || "",
13184
+ type: "public"
13185
+ }
13186
+ })
13187
+ }).catch(() => {
13188
+ });
12760
13189
  sonner.toast.success("Navbar saved");
12761
13190
  } catch {
12762
13191
  sonner.toast.error("Failed to save");
@@ -12780,8 +13209,57 @@ function SettingsPage() {
12780
13209
  currency: {
12781
13210
  value: currency,
12782
13211
  type: "public"
13212
+ },
13213
+ invoiceTemplate: {
13214
+ value: invoiceTemplate || "classic",
13215
+ type: "public"
13216
+ },
13217
+ invoiceLogoUrl: {
13218
+ value: companyLogo,
13219
+ type: "public"
13220
+ },
13221
+ companyLogo: {
13222
+ value: companyLogo,
13223
+ type: "public"
13224
+ },
13225
+ logo: {
13226
+ value: companyLogo,
13227
+ type: "public"
13228
+ },
13229
+ companyName: {
13230
+ value: companyName,
13231
+ type: "public"
13232
+ },
13233
+ companyEmail: {
13234
+ value: companyEmail,
13235
+ type: "public"
13236
+ },
13237
+ companyPhone: {
13238
+ value: companyPhone,
13239
+ type: "public"
13240
+ },
13241
+ companyAddress: {
13242
+ value: companyAddress,
13243
+ type: "public"
13244
+ }
13245
+ })
13246
+ });
13247
+ const updatedNav = {
13248
+ ...navbarConfig,
13249
+ logo: companyLogo
13250
+ };
13251
+ await fetch("/api/settings/theme", {
13252
+ method: "PUT",
13253
+ headers: {
13254
+ "Content-Type": "application/json"
13255
+ },
13256
+ body: JSON.stringify({
13257
+ navbar: {
13258
+ value: JSON.stringify(updatedNav),
13259
+ type: "public"
12783
13260
  }
12784
13261
  })
13262
+ }).catch(() => {
12785
13263
  });
12786
13264
  await fetch("/api/settings/multi_vendor", {
12787
13265
  method: "PUT",
@@ -13065,7 +13543,7 @@ function SettingsPage() {
13065
13543
  className: "text-sm text-gray-500 mb-4"
13066
13544
  }, "Set logo and menu items."), /* @__PURE__ */ React.createElement(NavbarEditor, {
13067
13545
  config: navbarConfig,
13068
- onChange: setNavbarConfig
13546
+ onChange: handleNavbarConfigChange
13069
13547
  })), /* @__PURE__ */ React.createElement(Button, {
13070
13548
  onClick: handleSaveNavbar,
13071
13549
  disabled: saving
@@ -13151,7 +13629,80 @@ function SettingsPage() {
13151
13629
  className: "text-sm font-medium text-gray-700"
13152
13630
  }, "Require event approval"), /* @__PURE__ */ React.createElement("p", {
13153
13631
  className: "text-xs text-gray-500 mt-0.5"
13154
- }, "When on, new vendor events start as pending. Admins approve or reject; approval activates the event (live)."))) : null), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", {
13632
+ }, "When on, new vendor events start as pending. Admins approve or reject; approval activates the event (live)."))) : null), /* @__PURE__ */ React.createElement("div", {
13633
+ className: "space-y-4 p-4 bg-gray-50 rounded-lg border border-gray-200"
13634
+ }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("h3", {
13635
+ className: "text-base font-semibold text-gray-900"
13636
+ }, "Invoice Header & Store Details"), /* @__PURE__ */ React.createElement("p", {
13637
+ className: "text-xs text-gray-500 mt-0.5"
13638
+ }, "Configure company logo, name, email, phone, and address displayed on generated invoice headers.")), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(ImageOrUrlField, {
13639
+ label: "Company Logo",
13640
+ value: companyLogo,
13641
+ onChange: handleStoreLogoChange,
13642
+ previewVariant: "logo",
13643
+ placeholder: "Logo image URL or upload image"
13644
+ })), /* @__PURE__ */ React.createElement("div", {
13645
+ className: "grid grid-cols-1 sm:grid-cols-2 gap-4"
13646
+ }, /* @__PURE__ */ React.createElement("div", {
13647
+ className: "space-y-1.5"
13648
+ }, /* @__PURE__ */ React.createElement(Label3, {
13649
+ className: "text-xs font-medium text-gray-700"
13650
+ }, "Company Name"), /* @__PURE__ */ React.createElement(Input, {
13651
+ value: companyName,
13652
+ onChange: /* @__PURE__ */ __name((e) => setCompanyName(e.target.value), "onChange"),
13653
+ placeholder: "e.g. Acme Corp",
13654
+ className: "h-9 text-sm bg-white"
13655
+ })), /* @__PURE__ */ React.createElement("div", {
13656
+ className: "space-y-1.5"
13657
+ }, /* @__PURE__ */ React.createElement(Label3, {
13658
+ className: "text-xs font-medium text-gray-700"
13659
+ }, "Company Email"), /* @__PURE__ */ React.createElement(Input, {
13660
+ type: "email",
13661
+ value: companyEmail,
13662
+ onChange: /* @__PURE__ */ __name((e) => setCompanyEmail(e.target.value), "onChange"),
13663
+ placeholder: "e.g. support@acme.com",
13664
+ className: "h-9 text-sm bg-white"
13665
+ })), /* @__PURE__ */ React.createElement("div", {
13666
+ className: "space-y-1.5"
13667
+ }, /* @__PURE__ */ React.createElement(Label3, {
13668
+ className: "text-xs font-medium text-gray-700"
13669
+ }, "Company Phone"), /* @__PURE__ */ React.createElement(Input, {
13670
+ type: "tel",
13671
+ value: companyPhone,
13672
+ onChange: /* @__PURE__ */ __name((e) => setCompanyPhone(e.target.value), "onChange"),
13673
+ placeholder: "e.g. +1 555-0199",
13674
+ className: "h-9 text-sm bg-white"
13675
+ })), /* @__PURE__ */ React.createElement("div", {
13676
+ className: "space-y-1.5 sm:col-span-2"
13677
+ }, /* @__PURE__ */ React.createElement(Label3, {
13678
+ className: "text-xs font-medium text-gray-700"
13679
+ }, "Company Address"), /* @__PURE__ */ React.createElement(Textarea, {
13680
+ value: companyAddress,
13681
+ onChange: /* @__PURE__ */ __name((e) => setCompanyAddress(e.target.value), "onChange"),
13682
+ placeholder: "e.g. 123 Business Rd, Suite 100\nNew York, NY 10001",
13683
+ rows: 3,
13684
+ className: "text-sm bg-white"
13685
+ })))), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("label", {
13686
+ className: "block text-sm font-semibold text-gray-700 mb-1"
13687
+ }, "Invoice PDF template"), /* @__PURE__ */ React.createElement("p", {
13688
+ className: "text-xs text-gray-500 mb-3"
13689
+ }, "Used when generating invoices in the app (and as fallback when ERP invoice is unavailable). Company logo, name, email, phone, and address set above are shown in the invoice header."), /* @__PURE__ */ React.createElement("div", {
13690
+ className: "grid gap-3 sm:grid-cols-2"
13691
+ }, INVOICE_TEMPLATE_CARDS.map((opt) => {
13692
+ const selected = invoiceTemplate === opt.id;
13693
+ return /* @__PURE__ */ React.createElement("button", {
13694
+ key: opt.id,
13695
+ type: "button",
13696
+ onClick: /* @__PURE__ */ __name(() => setInvoiceTemplate(opt.id), "onClick"),
13697
+ className: `text-left rounded-lg border p-3 transition ${selected ? "border-blue-500 bg-blue-50 ring-1 ring-blue-500" : "border-gray-200 bg-white hover:border-gray-300"}`
13698
+ }, /* @__PURE__ */ React.createElement(InvoiceTemplatePreview, {
13699
+ id: opt.id
13700
+ }), /* @__PURE__ */ React.createElement("div", {
13701
+ className: "text-sm font-semibold text-gray-800 mt-2"
13702
+ }, opt.label), /* @__PURE__ */ React.createElement("div", {
13703
+ className: "text-xs text-gray-500 mt-0.5"
13704
+ }, opt.description));
13705
+ }))), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", {
13155
13706
  className: "flex items-center justify-between mb-1"
13156
13707
  }, /* @__PURE__ */ React.createElement("label", {
13157
13708
  className: "block text-sm font-semibold text-gray-700"
@@ -13339,7 +13890,7 @@ function SettingsPage() {
13339
13890
  className: "h-4 w-4 mr-2"
13340
13891
  }), saving ? "Saving..." : "Save")));
13341
13892
  }
13342
- var DEFAULT_CURRENCY, DEFAULTS;
13893
+ var DEFAULT_CURRENCY, DEFAULTS, INVOICE_TEMPLATE_CARDS;
13343
13894
  var init_SettingsPage = __esm({
13344
13895
  "src/admin/pages/SettingsPage.tsx"() {
13345
13896
  "use client";
@@ -13348,6 +13899,8 @@ var init_SettingsPage = __esm({
13348
13899
  init_switch();
13349
13900
  init_label();
13350
13901
  init_admin_config_context();
13902
+ init_textarea();
13903
+ init_ImageOrUrlField();
13351
13904
  init_NavbarEditor();
13352
13905
  DEFAULT_CURRENCY = "INR";
13353
13906
  DEFAULTS = {
@@ -13355,6 +13908,29 @@ var init_SettingsPage = __esm({
13355
13908
  secondaryColor: "#6366f1",
13356
13909
  compactView: "false"
13357
13910
  };
13911
+ INVOICE_TEMPLATE_CARDS = [
13912
+ {
13913
+ id: "classic",
13914
+ label: "Classic",
13915
+ description: "Traditional invoice with lined items and totals footer."
13916
+ },
13917
+ {
13918
+ id: "modern",
13919
+ label: "Modern",
13920
+ description: "Clean layout with accent header and open spacing."
13921
+ },
13922
+ {
13923
+ id: "compact",
13924
+ label: "Compact",
13925
+ description: "Dense layout suited to longer item lists."
13926
+ },
13927
+ {
13928
+ id: "bold",
13929
+ label: "Bold",
13930
+ description: "Strong header band and clear payment summary."
13931
+ }
13932
+ ];
13933
+ __name(InvoiceTemplatePreview, "InvoiceTemplatePreview");
13358
13934
  __name(hexToHsl, "hexToHsl");
13359
13935
  __name(genId, "genId");
13360
13936
  __name(SettingsPage, "SettingsPage");
@@ -31680,6 +32256,7 @@ function ComboEditPage({ comboId }) {
31680
32256
  const [saving, setSaving] = React26.useState(false);
31681
32257
  const [errors, setErrors] = React26.useState([]);
31682
32258
  const [name, setName] = React26.useState("");
32259
+ const [slug, setSlug] = React26.useState("");
31683
32260
  const [desc, setDesc] = React26.useState("");
31684
32261
  const [eventId, setEventId] = React26.useState("");
31685
32262
  const [priceStr, setPriceStr] = React26.useState("");
@@ -31819,6 +32396,7 @@ function ComboEditPage({ comboId }) {
31819
32396
  const data = await res.json();
31820
32397
  if (cancelled) return;
31821
32398
  setName(data.name ?? "");
32399
+ setSlug(typeof data.slug === "string" ? data.slug : "");
31822
32400
  setDesc(data.desc ?? "");
31823
32401
  setEventId(data.eventId != null ? String(data.eventId) : "");
31824
32402
  if (data.eventId != null) {
@@ -31859,6 +32437,7 @@ function ComboEditPage({ comboId }) {
31859
32437
  if (create && duplicateSourceId) {
31860
32438
  const rawName = (data.name ?? "").trim() || "Combo";
31861
32439
  setName(rawName.toLowerCase().startsWith("copy of ") ? `${rawName} (copy)` : `Copy of ${rawName}`);
32440
+ setSlug("");
31862
32441
  }
31863
32442
  } catch {
31864
32443
  if (!cancelled) setErrors([
@@ -31944,15 +32523,15 @@ function ComboEditPage({ comboId }) {
31944
32523
  ]);
31945
32524
  return;
31946
32525
  }
31947
- if (addonItems.length > 0 && addonItems.length < minSelectableItems) {
32526
+ if (addonItems.length < minSelectableItems) {
31948
32527
  setErrors([
31949
- `Please add at least ${minSelectableItems} add-on item(s). Currently ${addonItems.length} selected.`
32528
+ `Please add at least ${minSelectableItems} add-on item(s) so customers can meet the minimum. Currently ${addonItems.length} selected.`
31950
32529
  ]);
31951
32530
  return;
31952
32531
  }
31953
- if (addonItems.length > maxSelectableItems) {
32532
+ if (maxSelectableItems > addonItems.length) {
31954
32533
  setErrors([
31955
- `You can select at most ${maxSelectableItems} add-on item(s). Currently ${addonItems.length} selected.`
32534
+ `Max add-on items (${maxSelectableItems}) cannot be greater than the number of add-on items selected (${addonItems.length}).`
31956
32535
  ]);
31957
32536
  return;
31958
32537
  }
@@ -31972,6 +32551,7 @@ function ComboEditPage({ comboId }) {
31972
32551
  const resolvedEventId = trimmedEventId && /^\d+$/.test(trimmedEventId) ? Number(trimmedEventId) : null;
31973
32552
  const payload = {
31974
32553
  name: trimmedName,
32554
+ slug: slug.trim() || void 0,
31975
32555
  desc: desc || null,
31976
32556
  eventId: resolvedEventId,
31977
32557
  price,
@@ -32063,6 +32643,14 @@ function ComboEditPage({ comboId }) {
32063
32643
  className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm"
32064
32644
  })), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("label", {
32065
32645
  className: "block text-xs font-medium text-gray-600 mb-1"
32646
+ }, "Slug"), /* @__PURE__ */ React.createElement("input", {
32647
+ type: "text",
32648
+ value: slug,
32649
+ onChange: /* @__PURE__ */ __name((e) => setSlug(e.target.value), "onChange"),
32650
+ placeholder: "Auto generate from name",
32651
+ className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm"
32652
+ })), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("label", {
32653
+ className: "block text-xs font-medium text-gray-600 mb-1"
32066
32654
  }, "Description"), /* @__PURE__ */ React.createElement("textarea", {
32067
32655
  value: desc,
32068
32656
  onChange: /* @__PURE__ */ __name((e) => setDesc(e.target.value), "onChange"),
@@ -32176,7 +32764,7 @@ function ComboEditPage({ comboId }) {
32176
32764
  className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm"
32177
32765
  }))), /* @__PURE__ */ React.createElement("p", {
32178
32766
  className: "text-xs text-gray-400 mt-1"
32179
- }, "Customers must select between ", minSelectableItems, " and ", maxSelectableItems, " add-on item(s)."))), /* @__PURE__ */ React.createElement("section", null, /* @__PURE__ */ React.createElement("h2", {
32767
+ }, "List all available add-ons above. Customers choose between ", minSelectableItems, " and", " ", maxSelectableItems, " of those items (max cannot exceed the add-on list size)."))), /* @__PURE__ */ React.createElement("section", null, /* @__PURE__ */ React.createElement("h2", {
32180
32768
  className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2"
32181
32769
  }, "Availability"), /* @__PURE__ */ React.createElement("div", {
32182
32770
  className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50 space-y-4"
@@ -33675,6 +34263,7 @@ var init_DiscountDetailsPage = __esm({
33675
34263
  category: "Category",
33676
34264
  cart: "Cart",
33677
34265
  paymentMethod: "Payment method",
34266
+ deviceType: "Device type",
33678
34267
  order: "Order",
33679
34268
  quantity: "Quantity",
33680
34269
  time: "Time",
@@ -33766,6 +34355,15 @@ function conditionToRule(c) {
33766
34355
  v: c.paymentMethod ?? ""
33767
34356
  }
33768
34357
  };
34358
+ case "deviceType":
34359
+ return {
34360
+ ...base,
34361
+ type: "deviceType",
34362
+ comparisonOperator: "eq",
34363
+ value: {
34364
+ v: c.deviceType ?? ""
34365
+ }
34366
+ };
33769
34367
  case "category":
33770
34368
  return {
33771
34369
  ...base,
@@ -33938,6 +34536,12 @@ function ruleTreeToFriendly(rules) {
33938
34536
  kind: "paymentMethod",
33939
34537
  paymentMethod: v
33940
34538
  };
34539
+ case "deviceType":
34540
+ return {
34541
+ id: rule._clientId ?? uid(),
34542
+ kind: "deviceType",
34543
+ deviceType: v
34544
+ };
33941
34545
  case "category":
33942
34546
  return {
33943
34547
  id: rule._clientId ?? uid(),
@@ -34500,6 +35104,9 @@ function ConditionCard({ condition, onChange, onRemove, eventsOn }) {
34500
35104
  paymentMethod: /* @__PURE__ */ React.createElement(LucideIcons.DollarSign, {
34501
35105
  className: "h-3.5 w-3.5 text-indigo-500"
34502
35106
  }),
35107
+ deviceType: /* @__PURE__ */ React.createElement(LucideIcons.DollarSign, {
35108
+ className: "h-3.5 w-3.5 text-cyan-500"
35109
+ }),
34503
35110
  category: /* @__PURE__ */ React.createElement(LucideIcons.Package, {
34504
35111
  className: "h-3.5 w-3.5 text-teal-500"
34505
35112
  }),
@@ -34542,6 +35149,8 @@ function ConditionCard({ condition, onChange, onRemove, eventsOn }) {
34542
35149
  }, "User type"), /* @__PURE__ */ React.createElement(SelectItem, {
34543
35150
  value: "paymentMethod"
34544
35151
  }, "Payment method"), /* @__PURE__ */ React.createElement(SelectItem, {
35152
+ value: "deviceType"
35153
+ }, "Device type"), /* @__PURE__ */ React.createElement(SelectItem, {
34545
35154
  value: "category"
34546
35155
  }, "Category"), /* @__PURE__ */ React.createElement(SelectItem, {
34547
35156
  value: "customers"
@@ -34695,7 +35304,21 @@ function ConditionCard({ condition, onChange, onRemove, eventsOn }) {
34695
35304
  value: "cod"
34696
35305
  }, "Cash on Delivery"), /* @__PURE__ */ React.createElement(SelectItem, {
34697
35306
  value: "wallet"
34698
- }, "Wallet"))), condition.kind === "category" && /* @__PURE__ */ React.createElement(CategoryPicker, {
35307
+ }, "Wallet"))), condition.kind === "deviceType" && /* @__PURE__ */ React.createElement(Select, {
35308
+ value: condition.deviceType ?? "",
35309
+ onValueChange: /* @__PURE__ */ __name((v) => onChange({
35310
+ ...condition,
35311
+ deviceType: v
35312
+ }), "onValueChange")
35313
+ }, /* @__PURE__ */ React.createElement(SelectTrigger, {
35314
+ className: "h-8 text-xs"
35315
+ }, /* @__PURE__ */ React.createElement(SelectValue, {
35316
+ placeholder: "Select device type\u2026"
35317
+ })), /* @__PURE__ */ React.createElement(SelectContent, null, /* @__PURE__ */ React.createElement(SelectItem, {
35318
+ value: "web"
35319
+ }, "Web"), /* @__PURE__ */ React.createElement(SelectItem, {
35320
+ value: "mobile"
35321
+ }, "Mobile"))), condition.kind === "category" && /* @__PURE__ */ React.createElement(CategoryPicker, {
34699
35322
  value: condition.categoryId,
34700
35323
  label: condition.categoryName,
34701
35324
  onChange: /* @__PURE__ */ __name((id, name) => onChange({
@@ -37920,6 +38543,11 @@ var init_AdminPageResolver = __esm({
37920
38543
  field: "email",
37921
38544
  displayName: "Email"
37922
38545
  },
38546
+ {
38547
+ field: "inviteStatus",
38548
+ displayName: "Invite status",
38549
+ hideInForm: true
38550
+ },
37923
38551
  {
37924
38552
  field: "blocked",
37925
38553
  displayName: "Blocked",
@@ -38125,6 +38753,29 @@ function LayoutSettingsPage() {
38125
38753
  footer: JSON.stringify(footerValues)
38126
38754
  })
38127
38755
  });
38756
+ if (navbarConfig.logo) {
38757
+ await fetch("/api/settings/store", {
38758
+ method: "PUT",
38759
+ headers: {
38760
+ "Content-Type": "application/json"
38761
+ },
38762
+ body: JSON.stringify({
38763
+ invoiceLogoUrl: {
38764
+ value: navbarConfig.logo,
38765
+ type: "public"
38766
+ },
38767
+ companyLogo: {
38768
+ value: navbarConfig.logo,
38769
+ type: "public"
38770
+ },
38771
+ logo: {
38772
+ value: navbarConfig.logo,
38773
+ type: "public"
38774
+ }
38775
+ })
38776
+ }).catch(() => {
38777
+ });
38778
+ }
38128
38779
  } finally {
38129
38780
  setSaving(false);
38130
38781
  }
@@ -38551,18 +39202,26 @@ var init_config = __esm({
38551
39202
  ];
38552
39203
  }
38553
39204
  });
39205
+ function ForceAdminLightMode() {
39206
+ useForceAdminLightMode();
39207
+ return null;
39208
+ }
38554
39209
  function CmsProviders({ children }) {
38555
39210
  return /* @__PURE__ */ React.createElement(nextThemes.ThemeProvider, {
38556
39211
  attribute: "class",
38557
- defaultTheme: "system",
38558
- enableSystem: true
38559
- }, children, /* @__PURE__ */ React.createElement(sonner.Toaster, {
39212
+ defaultTheme: "light",
39213
+ forcedTheme: "light",
39214
+ enableSystem: false,
39215
+ enableColorScheme: true
39216
+ }, /* @__PURE__ */ React.createElement(ForceAdminLightMode, null), children, /* @__PURE__ */ React.createElement(sonner.Toaster, {
38560
39217
  position: "top-right"
38561
39218
  }));
38562
39219
  }
38563
39220
  var init_CmsProviders = __esm({
38564
39221
  "src/admin/CmsProviders.tsx"() {
38565
39222
  "use client";
39223
+ init_force_light_mode();
39224
+ __name(ForceAdminLightMode, "ForceAdminLightMode");
38566
39225
  __name(CmsProviders, "CmsProviders");
38567
39226
  }
38568
39227
  });