@infuro/cms-core 1.0.59 → 1.0.61
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 +1020 -83
- package/dist/admin.js +1021 -84
- package/dist/api.cjs +38 -38
- package/dist/api.js +5 -5
- package/dist/auth.cjs +51 -51
- package/dist/auth.js +3 -3
- package/dist/{chunk-3EOM4V2M.cjs → chunk-4U6DATGZ.cjs} +7 -7
- package/dist/{chunk-BNKZNLEX.js → chunk-6DBDJ4VD.js} +2 -2
- package/dist/{chunk-UQWZUZ5X.cjs → chunk-73WVHINE.cjs} +30 -6
- package/dist/{chunk-UCKN4BBY.cjs → chunk-77I3KS7V.cjs} +4 -1
- package/dist/{chunk-MCCA7WLQ.cjs → chunk-CNAHVRRU.cjs} +533 -167
- package/dist/{chunk-77NUXO6A.cjs → chunk-J7FMZK66.cjs} +10 -2
- package/dist/{chunk-BC22I7C7.cjs → chunk-KM2I6AFP.cjs} +9 -9
- package/dist/{chunk-JIWUVQ6B.js → chunk-MVHDC3XF.js} +10 -2
- package/dist/{chunk-RK5ETF2I.js → chunk-NR44CK5E.js} +1 -1
- package/dist/{chunk-MXIWUFBP.js → chunk-O2642WVS.js} +28 -4
- package/dist/{chunk-HCIRL37O.js → chunk-T3HPSF7K.js} +4 -1
- package/dist/{chunk-BTUEUA5H.js → chunk-UHT4INVW.js} +453 -87
- package/dist/{chunk-HYW3MUXT.js → chunk-URN7GS23.js} +30 -16
- package/dist/{chunk-HXLC56ZK.cjs → chunk-YSYX4GUD.cjs} +32 -18
- package/dist/{emit-order-notification-trigger-HZQPPSFB.js → emit-order-notification-trigger-CZU3V2WE.js} +2 -2
- package/dist/{emit-order-notification-trigger-NR3VN6C6.cjs → emit-order-notification-trigger-TNEZOYEE.cjs} +4 -4
- package/dist/index.cjs +614 -333
- package/dist/index.d.cts +31 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +329 -48
- package/dist/migrations/1782800000000-AddPaymentSuccessFailedRefundTriggers.ts +32 -0
- package/dist/migrations/1782900000000-AddEnableTurnstileToForms.ts +29 -0
- package/dist/{order-notification-dispatcher-2FCZFZUD.cjs → order-notification-dispatcher-KJVGLK5E.cjs} +5 -5
- package/dist/{order-notification-dispatcher-64WDCHHG.js → order-notification-dispatcher-ZSFKEYMP.js} +2 -2
- package/dist/{rbac-debug-db-6EMIVMGF.js → rbac-debug-db-5R6XFPSV.js} +1 -1
- package/dist/{rbac-debug-db-6PWTLBEL.cjs → rbac-debug-db-JKK2MCWF.cjs} +2 -2
- package/package.json +1 -1
package/dist/admin.js
CHANGED
|
@@ -10,7 +10,7 @@ import { Slot } from '@radix-ui/react-slot';
|
|
|
10
10
|
import { cva } from 'class-variance-authority';
|
|
11
11
|
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
12
12
|
import * as LucideIcons from 'lucide-react';
|
|
13
|
-
import { ChevronDown, User, Settings, LogOut, LayoutDashboard, Store, FolderTree, Layers, Building2, CalendarDays, ShoppingBag, Package, Receipt, BadgePercent, ShoppingCart, CreditCard, Users, Inbox, File, LinkIcon, ClipboardList, MessageSquare, Image as Image$1, Shield, FileText, Puzzle, X, Plus, MoreVertical, Upload, Download, Edit, Copy, RefreshCw, Trash2, Mail, Check, Save, Search, AlertCircle, MapPin, BarChart3, TrendingUp, UserCheck, Activity, Globe, Eye, MousePointer, ArrowLeftRight, RotateCcw, KeyRound, Loader2, CalendarClock, CheckSquare, Square, XSquare, Rss, ArrowLeft, Pencil, FolderPlus, LayoutGrid, List, Move, Archive, Edit2, ExternalLink, Power, Star, ChevronUp, Zap, Filter, CheckCircle2, ImageIcon, GripVertical, ChevronRight, ArrowRight, ArrowUpRight, IndianRupee, XCircle, Clock, Play, MessageCircle, Bot, FileUp, Tag, Box, SlidersHorizontal, Calculator, Link2 as Link2$1, Unlink, Gift, MoreHorizontal,
|
|
13
|
+
import { ChevronDown, User, Settings, LogOut, LayoutDashboard, Store, FolderTree, Layers, Building2, CalendarDays, ShoppingBag, Package, Receipt, BadgePercent, ShoppingCart, CreditCard, Users, Inbox, File, LinkIcon, ClipboardList, MessageSquare, Image as Image$1, Shield, FileText, Puzzle, X, ShieldAlert, Plus, MoreVertical, Upload, Download, Edit, Copy, RefreshCw, Trash2, Mail, Check, Save, Search, AlertCircle, MapPin, BarChart3, TrendingUp, UserCheck, Activity, Globe, Eye, MousePointer, ArrowLeftRight, RotateCcw, KeyRound, Loader2, CalendarClock, CheckSquare, Square, XSquare, Rss, ArrowLeft, Pencil, FolderPlus, LayoutGrid, List, Move, Archive, Edit2, ExternalLink, Power, Star, ChevronUp, Zap, Filter, CheckCircle2, ImageIcon, GripVertical, ChevronRight, ArrowRight, ArrowUpRight, IndianRupee, XCircle, Clock, Play, MessageCircle, Bot, FileUp, Tag, Box, SlidersHorizontal, Calculator, Link2 as Link2$1, Unlink, Gift, MoreHorizontal, ShieldCheck, EyeOff, Smartphone, QrCode, Car, Send, Settings2, DollarSign, Hash, Circle, ChevronLeft, Bell, Share2, HardDrive, Folder, Film } from 'lucide-react';
|
|
14
14
|
import Image from 'next/image';
|
|
15
15
|
import Link2 from 'next/link';
|
|
16
16
|
import { usePathname, useSearchParams, useRouter } from 'next/navigation';
|
|
@@ -327,7 +327,15 @@ var init_vendor_scope = __esm({
|
|
|
327
327
|
...VENDOR_SCOPED_STORE_ENTITIES,
|
|
328
328
|
"order_discounts",
|
|
329
329
|
"order_addresses",
|
|
330
|
-
"event_products"
|
|
330
|
+
"event_products",
|
|
331
|
+
"attendees",
|
|
332
|
+
"order-attendees",
|
|
333
|
+
"order_attendees",
|
|
334
|
+
"scan",
|
|
335
|
+
"verify-attendee-qr",
|
|
336
|
+
"verify_attendee_qr",
|
|
337
|
+
"forms",
|
|
338
|
+
"cms-forms"
|
|
331
339
|
]);
|
|
332
340
|
__name(isVendorGroupName, "isVendorGroupName");
|
|
333
341
|
__name(isPlatformAdministrator, "isPlatformAdministrator");
|
|
@@ -853,7 +861,7 @@ var init_admin_config_context = __esm({
|
|
|
853
861
|
var CMS_VERSION;
|
|
854
862
|
var init_cms_version = __esm({
|
|
855
863
|
"src/lib/cms-version.ts"() {
|
|
856
|
-
CMS_VERSION = "1.0.
|
|
864
|
+
CMS_VERSION = "1.0.61" ;
|
|
857
865
|
}
|
|
858
866
|
});
|
|
859
867
|
function useCatalogCategories(enabled = true) {
|
|
@@ -1575,6 +1583,15 @@ var init_builtin_plugin_descriptors = __esm({
|
|
|
1575
1583
|
enabled: true,
|
|
1576
1584
|
icon: "auth_providers",
|
|
1577
1585
|
settingsGroup: "auth_providers"
|
|
1586
|
+
},
|
|
1587
|
+
{
|
|
1588
|
+
name: "turnstile",
|
|
1589
|
+
label: "Cloudflare Turnstile",
|
|
1590
|
+
version: "1.0.0",
|
|
1591
|
+
description: "Protect forms, registration, and authentication from spam and bots with Cloudflare Turnstile.",
|
|
1592
|
+
enabled: true,
|
|
1593
|
+
icon: "turnstile",
|
|
1594
|
+
settingsGroup: "turnstile"
|
|
1578
1595
|
}
|
|
1579
1596
|
];
|
|
1580
1597
|
}
|
|
@@ -2175,6 +2192,11 @@ function FileUpload({ onUploadSuccess }) {
|
|
|
2175
2192
|
if (!selectedFile) return;
|
|
2176
2193
|
setUploading(true);
|
|
2177
2194
|
setProgress(10);
|
|
2195
|
+
console.info("[upload] file-upload start", {
|
|
2196
|
+
name: selectedFile.name,
|
|
2197
|
+
type: selectedFile.type,
|
|
2198
|
+
size: selectedFile.size
|
|
2199
|
+
});
|
|
2178
2200
|
const formData = new FormData();
|
|
2179
2201
|
formData.append("file", selectedFile);
|
|
2180
2202
|
try {
|
|
@@ -2183,20 +2205,47 @@ function FileUpload({ onUploadSuccess }) {
|
|
|
2183
2205
|
body: formData
|
|
2184
2206
|
});
|
|
2185
2207
|
setProgress(60);
|
|
2186
|
-
const data = await response.json()
|
|
2208
|
+
const data = await response.json().catch((parseErr) => {
|
|
2209
|
+
console.error("[upload] file-upload JSON parse failed", {
|
|
2210
|
+
status: response.status,
|
|
2211
|
+
parseErr
|
|
2212
|
+
});
|
|
2213
|
+
return {};
|
|
2214
|
+
});
|
|
2215
|
+
console.info("[upload] file-upload response", {
|
|
2216
|
+
status: response.status,
|
|
2217
|
+
ok: response.ok,
|
|
2218
|
+
url: data.url ?? data.filePath ?? null,
|
|
2219
|
+
error: data.error ?? null,
|
|
2220
|
+
details: data.details ?? null
|
|
2221
|
+
});
|
|
2187
2222
|
if (response.ok) {
|
|
2188
|
-
|
|
2223
|
+
const url = data.url ?? data.filePath;
|
|
2224
|
+
setFileUrl(url);
|
|
2189
2225
|
setProgress(100);
|
|
2190
|
-
|
|
2226
|
+
console.info("[upload] file-upload ok", {
|
|
2227
|
+
url,
|
|
2228
|
+
name: selectedFile.name
|
|
2229
|
+
});
|
|
2230
|
+
onUploadSuccess(url);
|
|
2191
2231
|
} else {
|
|
2192
2232
|
console.error("[upload] API error", {
|
|
2193
2233
|
status: response.status,
|
|
2194
2234
|
error: data.error,
|
|
2195
|
-
details: data.details
|
|
2235
|
+
details: data.details,
|
|
2236
|
+
name: selectedFile.name,
|
|
2237
|
+
type: selectedFile.type,
|
|
2238
|
+
size: selectedFile.size
|
|
2196
2239
|
});
|
|
2197
2240
|
}
|
|
2198
2241
|
} catch (error) {
|
|
2199
|
-
console.error("
|
|
2242
|
+
console.error("[upload] file-upload failed", {
|
|
2243
|
+
name: selectedFile.name,
|
|
2244
|
+
type: selectedFile.type,
|
|
2245
|
+
size: selectedFile.size,
|
|
2246
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2247
|
+
stack: error instanceof Error ? error.stack : void 0
|
|
2248
|
+
});
|
|
2200
2249
|
}
|
|
2201
2250
|
setUploading(false);
|
|
2202
2251
|
}, "handleUpload");
|
|
@@ -2328,28 +2377,64 @@ function ImageOrUrlField({ label, value, onChange, placeholder = "https://\u2026
|
|
|
2328
2377
|
return;
|
|
2329
2378
|
}
|
|
2330
2379
|
setIsUploading(true);
|
|
2380
|
+
console.info("[upload] ImageOrUrlField start", {
|
|
2381
|
+
name: file.name,
|
|
2382
|
+
type: file.type,
|
|
2383
|
+
size: file.size,
|
|
2384
|
+
isVideo: isVideo2,
|
|
2385
|
+
maxSizeMb
|
|
2386
|
+
});
|
|
2331
2387
|
try {
|
|
2332
2388
|
const formData = new FormData();
|
|
2333
2389
|
formData.append("file", file);
|
|
2390
|
+
console.info("[upload] ImageOrUrlField POST /api/upload", {
|
|
2391
|
+
name: file.name,
|
|
2392
|
+
type: file.type,
|
|
2393
|
+
size: file.size
|
|
2394
|
+
});
|
|
2334
2395
|
const response = await fetch("/api/upload", {
|
|
2335
2396
|
method: "POST",
|
|
2336
2397
|
body: formData
|
|
2337
2398
|
});
|
|
2338
|
-
const data = await response.json().catch(() =>
|
|
2399
|
+
const data = await response.json().catch((parseErr) => {
|
|
2400
|
+
console.error("[upload] ImageOrUrlField JSON parse failed", {
|
|
2401
|
+
status: response.status,
|
|
2402
|
+
parseErr
|
|
2403
|
+
});
|
|
2404
|
+
return {};
|
|
2405
|
+
});
|
|
2406
|
+
console.info("[upload] ImageOrUrlField response", {
|
|
2407
|
+
status: response.status,
|
|
2408
|
+
ok: response.ok,
|
|
2409
|
+
filePath: data.filePath ?? null,
|
|
2410
|
+
error: data.error ?? null,
|
|
2411
|
+
details: data.details ?? null
|
|
2412
|
+
});
|
|
2339
2413
|
if (!response.ok) {
|
|
2340
2414
|
console.error("[upload] API error", {
|
|
2341
2415
|
status: response.status,
|
|
2342
2416
|
error: data.error,
|
|
2343
|
-
details: data.details
|
|
2417
|
+
details: data.details,
|
|
2418
|
+
fileName: file.name,
|
|
2419
|
+
fileType: file.type,
|
|
2420
|
+
fileSize: file.size
|
|
2344
2421
|
});
|
|
2345
2422
|
throw new Error(data.details || data.error || "Upload failed");
|
|
2346
2423
|
}
|
|
2347
2424
|
console.info("[upload] API ok", {
|
|
2348
|
-
filePath: data.filePath
|
|
2425
|
+
filePath: data.filePath,
|
|
2426
|
+
name: file.name,
|
|
2427
|
+
type: file.type
|
|
2349
2428
|
});
|
|
2350
2429
|
onChange(data.filePath ?? "");
|
|
2351
2430
|
} catch (err) {
|
|
2352
|
-
console.error("[upload] client failed",
|
|
2431
|
+
console.error("[upload] client failed", {
|
|
2432
|
+
name: file.name,
|
|
2433
|
+
type: file.type,
|
|
2434
|
+
size: file.size,
|
|
2435
|
+
error: err instanceof Error ? err.message : String(err),
|
|
2436
|
+
stack: err instanceof Error ? err.stack : void 0
|
|
2437
|
+
});
|
|
2353
2438
|
setError(err instanceof Error ? err.message : "Upload failed");
|
|
2354
2439
|
} finally {
|
|
2355
2440
|
setIsUploading(false);
|
|
@@ -5048,6 +5133,9 @@ function AdminCRUD({ title, apiEndpoint, columns, addEditPageUrl, customViewPage
|
|
|
5048
5133
|
});
|
|
5049
5134
|
if (cancelled) return;
|
|
5050
5135
|
if (!res.ok) {
|
|
5136
|
+
if (res.status === 403) {
|
|
5137
|
+
throw new Error("You don't have access to this section");
|
|
5138
|
+
}
|
|
5051
5139
|
throw new Error(`HTTP error! status: ${res.status}`);
|
|
5052
5140
|
}
|
|
5053
5141
|
const result = await res.json();
|
|
@@ -5464,15 +5552,26 @@ function AdminCRUD({ title, apiEndpoint, columns, addEditPageUrl, customViewPage
|
|
|
5464
5552
|
}, "Loading...")));
|
|
5465
5553
|
}
|
|
5466
5554
|
if (error) {
|
|
5555
|
+
const isForbidden = error.toLowerCase().includes("don't have access") || error.toLowerCase().includes("forbidden") || error.includes("403");
|
|
5467
5556
|
return /* @__PURE__ */ React.createElement("div", {
|
|
5468
5557
|
className: embedded ? "p-4" : "rounded-lg bg-white p-6 shadow-md"
|
|
5469
5558
|
}, /* @__PURE__ */ React.createElement("div", {
|
|
5470
|
-
className: "text-center py-
|
|
5471
|
-
}, /* @__PURE__ */ React.createElement("
|
|
5559
|
+
className: "text-center py-10"
|
|
5560
|
+
}, isForbidden ? /* @__PURE__ */ React.createElement("div", {
|
|
5561
|
+
className: "max-w-md mx-auto"
|
|
5562
|
+
}, /* @__PURE__ */ React.createElement("div", {
|
|
5563
|
+
className: "mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-red-100 mb-3"
|
|
5564
|
+
}, /* @__PURE__ */ React.createElement(ShieldAlert, {
|
|
5565
|
+
className: "h-6 w-6 text-red-600"
|
|
5566
|
+
})), /* @__PURE__ */ React.createElement("h3", {
|
|
5567
|
+
className: "text-base font-semibold text-gray-900 mb-1"
|
|
5568
|
+
}, "You don't have access"), /* @__PURE__ */ React.createElement("p", {
|
|
5569
|
+
className: "text-sm text-gray-500"
|
|
5570
|
+
}, "You don't have permission to view or manage this tab.")) : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("p", {
|
|
5472
5571
|
className: "text-red-600 mb-4"
|
|
5473
5572
|
}, "Error loading data: ", error), /* @__PURE__ */ React.createElement(Button, {
|
|
5474
5573
|
onClick: /* @__PURE__ */ __name(() => window.location.reload(), "onClick")
|
|
5475
|
-
}, "Retry")));
|
|
5574
|
+
}, "Retry"))));
|
|
5476
5575
|
}
|
|
5477
5576
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", {
|
|
5478
5577
|
className: shellCls
|
|
@@ -6309,6 +6408,7 @@ function FormBuilder({ formId, duplicateFromId }) {
|
|
|
6309
6408
|
campaign: "",
|
|
6310
6409
|
slug: "",
|
|
6311
6410
|
published: false,
|
|
6411
|
+
enableTurnstile: false,
|
|
6312
6412
|
fields: []
|
|
6313
6413
|
});
|
|
6314
6414
|
const [errors, setErrors] = useState([]);
|
|
@@ -6342,6 +6442,7 @@ function FormBuilder({ formId, duplicateFromId }) {
|
|
|
6342
6442
|
campaign: data.campaign || "",
|
|
6343
6443
|
slug: slugNext,
|
|
6344
6444
|
published: isDup ? false : data.published,
|
|
6445
|
+
enableTurnstile: Boolean(data.enableTurnstile ?? data.enable_turnstile),
|
|
6345
6446
|
fields: (data.fields ?? []).map((field, index) => ({
|
|
6346
6447
|
...field,
|
|
6347
6448
|
id: isDup ? `field_dup_${Date.now()}_${index}` : field?.id != null ? String(field.id) : `field_${Date.now()}_${index}`,
|
|
@@ -6650,7 +6751,21 @@ function FormBuilder({ formId, duplicateFromId }) {
|
|
|
6650
6751
|
})), "onCheckedChange")
|
|
6651
6752
|
}), /* @__PURE__ */ React.createElement("label", {
|
|
6652
6753
|
className: "text-sm font-medium text-gray-700"
|
|
6653
|
-
}, "Published"))
|
|
6754
|
+
}, "Published")), /* @__PURE__ */ React.createElement("div", {
|
|
6755
|
+
className: "flex items-center space-x-2 pt-2 border-t border-gray-100"
|
|
6756
|
+
}, /* @__PURE__ */ React.createElement(Switch, {
|
|
6757
|
+
checked: formData.enableTurnstile ?? false,
|
|
6758
|
+
onCheckedChange: /* @__PURE__ */ __name((checked) => setFormData((prev) => ({
|
|
6759
|
+
...prev,
|
|
6760
|
+
enableTurnstile: checked
|
|
6761
|
+
})), "onCheckedChange")
|
|
6762
|
+
}), /* @__PURE__ */ React.createElement("div", {
|
|
6763
|
+
className: "flex flex-col"
|
|
6764
|
+
}, /* @__PURE__ */ React.createElement("label", {
|
|
6765
|
+
className: "text-sm font-medium text-gray-700"
|
|
6766
|
+
}, "Enable Cloudflare Turnstile"), /* @__PURE__ */ React.createElement("span", {
|
|
6767
|
+
className: "text-xs text-gray-500"
|
|
6768
|
+
}, "Requires user verification before submission (when Turnstile plugin is active)")))))), /* @__PURE__ */ React.createElement("div", {
|
|
6654
6769
|
className: "lg:col-span-2"
|
|
6655
6770
|
}, /* @__PURE__ */ React.createElement("div", {
|
|
6656
6771
|
className: "bg-white rounded-lg shadow"
|
|
@@ -6820,26 +6935,63 @@ function ImageUpload({ value, onChange, onRemove, label, required = false, class
|
|
|
6820
6935
|
return;
|
|
6821
6936
|
}
|
|
6822
6937
|
setIsUploading(true);
|
|
6938
|
+
console.info("[upload] client image-upload start", {
|
|
6939
|
+
name: file.name,
|
|
6940
|
+
type: file.type,
|
|
6941
|
+
size: file.size,
|
|
6942
|
+
maxSizeMb: maxSize
|
|
6943
|
+
});
|
|
6823
6944
|
try {
|
|
6824
6945
|
const formData = new FormData();
|
|
6825
6946
|
formData.append("file", file);
|
|
6947
|
+
console.info("[upload] client POST /api/upload", {
|
|
6948
|
+
name: file.name,
|
|
6949
|
+
type: file.type,
|
|
6950
|
+
size: file.size
|
|
6951
|
+
});
|
|
6826
6952
|
const response = await fetch("/api/upload", {
|
|
6827
6953
|
method: "POST",
|
|
6828
6954
|
body: formData
|
|
6829
6955
|
});
|
|
6830
|
-
const data = await response.json()
|
|
6956
|
+
const data = await response.json().catch((parseErr) => {
|
|
6957
|
+
console.error("[upload] client failed to parse JSON response", {
|
|
6958
|
+
status: response.status,
|
|
6959
|
+
parseErr
|
|
6960
|
+
});
|
|
6961
|
+
return {};
|
|
6962
|
+
});
|
|
6963
|
+
console.info("[upload] client response", {
|
|
6964
|
+
status: response.status,
|
|
6965
|
+
ok: response.ok,
|
|
6966
|
+
filePath: data.filePath ?? null,
|
|
6967
|
+
error: data.error ?? null,
|
|
6968
|
+
details: data.details ?? null
|
|
6969
|
+
});
|
|
6831
6970
|
if (!response.ok) {
|
|
6832
6971
|
console.error("[upload] API error", {
|
|
6833
6972
|
status: response.status,
|
|
6834
6973
|
error: data.error,
|
|
6835
|
-
details: data.details
|
|
6974
|
+
details: data.details,
|
|
6975
|
+
fileName: file.name,
|
|
6976
|
+
fileType: file.type,
|
|
6977
|
+
fileSize: file.size
|
|
6836
6978
|
});
|
|
6837
6979
|
throw new Error(data.details || data.error || "Upload failed");
|
|
6838
6980
|
}
|
|
6981
|
+
console.info("[upload] client image-upload ok", {
|
|
6982
|
+
filePath: data.filePath,
|
|
6983
|
+
name: file.name
|
|
6984
|
+
});
|
|
6839
6985
|
onChange(data.filePath);
|
|
6840
6986
|
setUploadProgress(100);
|
|
6841
6987
|
} catch (error2) {
|
|
6842
|
-
console.error("
|
|
6988
|
+
console.error("[upload] client image-upload failed", {
|
|
6989
|
+
name: file.name,
|
|
6990
|
+
type: file.type,
|
|
6991
|
+
size: file.size,
|
|
6992
|
+
error: error2 instanceof Error ? error2.message : String(error2),
|
|
6993
|
+
stack: error2 instanceof Error ? error2.stack : void 0
|
|
6994
|
+
});
|
|
6843
6995
|
setError(error2 instanceof Error ? error2.message : "Failed to upload image");
|
|
6844
6996
|
} finally {
|
|
6845
6997
|
setIsUploading(false);
|
|
@@ -16143,6 +16295,7 @@ var init_order_notification_bindings_shared = __esm({
|
|
|
16143
16295
|
"orderNumber",
|
|
16144
16296
|
"customerName",
|
|
16145
16297
|
"customerPhone",
|
|
16298
|
+
"customerEmail",
|
|
16146
16299
|
"eventName",
|
|
16147
16300
|
"vendorName",
|
|
16148
16301
|
"total",
|
|
@@ -16150,7 +16303,8 @@ var init_order_notification_bindings_shared = __esm({
|
|
|
16150
16303
|
"vendorId",
|
|
16151
16304
|
"refundAmount",
|
|
16152
16305
|
"invoiceNumber",
|
|
16153
|
-
"
|
|
16306
|
+
"invoiceAttachment",
|
|
16307
|
+
"orderDetails"
|
|
16154
16308
|
];
|
|
16155
16309
|
__name(useNotificationVariables, "useNotificationVariables");
|
|
16156
16310
|
EMAIL_TRIGGER_DEFAULTS = {
|
|
@@ -16182,6 +16336,43 @@ If you have any questions, please contact us.
|
|
|
16182
16336
|
|
|
16183
16337
|
Thank you!`,
|
|
16184
16338
|
bodyPlaceholder: "Hi {{customerName}},\n\nYour order {{orderNumber}} has been cancelled.\n\nIf a refund is due, it will be returned to your original payment method."
|
|
16339
|
+
},
|
|
16340
|
+
payment_success: {
|
|
16341
|
+
subject: "Payment Successful for Order {{orderNumber}}",
|
|
16342
|
+
subjectPlaceholder: "e.g. Payment Successful for Order {{orderNumber}}",
|
|
16343
|
+
body: `Hi {{customerName}},
|
|
16344
|
+
|
|
16345
|
+
We have received your payment for order {{orderNumber}} of {{total}} {{currency}}.
|
|
16346
|
+
|
|
16347
|
+
Order Details:
|
|
16348
|
+
{{orderDetails}}
|
|
16349
|
+
|
|
16350
|
+
Thank you!`,
|
|
16351
|
+
bodyPlaceholder: "Hi {{customerName}},\n\nPayment for order {{orderNumber}} was successful.\n\nThank you!"
|
|
16352
|
+
},
|
|
16353
|
+
payment_failed: {
|
|
16354
|
+
subject: "Payment Failed for Order {{orderNumber}}",
|
|
16355
|
+
subjectPlaceholder: "e.g. Payment Failed for Order {{orderNumber}}",
|
|
16356
|
+
body: `Hi {{customerName}},
|
|
16357
|
+
|
|
16358
|
+
Your payment for order {{orderNumber}} of {{total}} {{currency}} could not be completed or remains unpaid.
|
|
16359
|
+
|
|
16360
|
+
If you were charged, please contact us with your order number {{orderNumber}}.
|
|
16361
|
+
|
|
16362
|
+
Thank you!`,
|
|
16363
|
+
bodyPlaceholder: "Hi {{customerName}},\n\nPayment for order {{orderNumber}} failed or remains unpaid.\n\nThank you!"
|
|
16364
|
+
},
|
|
16365
|
+
payment_refund_initiated: {
|
|
16366
|
+
subject: "Refund Initiated for Order {{orderNumber}}",
|
|
16367
|
+
subjectPlaceholder: "e.g. Refund Initiated for Order {{orderNumber}}",
|
|
16368
|
+
body: `Hi {{customerName}},
|
|
16369
|
+
|
|
16370
|
+
Your order {{orderNumber}} has been cancelled and a refund of {{refundAmount}} {{currency}} has been initiated.
|
|
16371
|
+
|
|
16372
|
+
The amount will be credited back to your original payment method.
|
|
16373
|
+
|
|
16374
|
+
Thank you!`,
|
|
16375
|
+
bodyPlaceholder: "Hi {{customerName}},\n\nRefund of {{refundAmount}} {{currency}} for order {{orderNumber}} has been initiated."
|
|
16185
16376
|
}
|
|
16186
16377
|
};
|
|
16187
16378
|
VENDOR_EMAIL_TRIGGER_DEFAULTS = {
|
|
@@ -16206,12 +16397,48 @@ Thank you!`,
|
|
|
16206
16397
|
|
|
16207
16398
|
Order {{orderNumber}} for {{total}} {{currency}} has been cancelled.
|
|
16208
16399
|
|
|
16209
|
-
Customer: {{customerName}
|
|
16400
|
+
Customer: {{customerName}}
|
|
16210
16401
|
Order Items:
|
|
16211
16402
|
{{orderDetails}}
|
|
16212
16403
|
|
|
16213
16404
|
Thank you.`,
|
|
16214
16405
|
bodyPlaceholder: "Hi {{vendorName}},\n\nOrder {{orderNumber}} was cancelled."
|
|
16406
|
+
},
|
|
16407
|
+
payment_success: {
|
|
16408
|
+
subject: "Payment Confirmed for Order {{orderNumber}} - {{customerName}}",
|
|
16409
|
+
subjectPlaceholder: "e.g. Payment Confirmed for Order {{orderNumber}}",
|
|
16410
|
+
body: `Hi {{vendorName}},
|
|
16411
|
+
|
|
16412
|
+
Payment has been confirmed for order {{orderNumber}} ({{total}} {{currency}}).
|
|
16413
|
+
|
|
16414
|
+
Customer: {{customerName}}
|
|
16415
|
+
Order Items:
|
|
16416
|
+
{{orderDetails}}
|
|
16417
|
+
|
|
16418
|
+
Thank you!`,
|
|
16419
|
+
bodyPlaceholder: "Hi {{vendorName}},\n\nPayment for order {{orderNumber}} confirmed."
|
|
16420
|
+
},
|
|
16421
|
+
payment_failed: {
|
|
16422
|
+
subject: "Payment Unpaid / Failed for Order {{orderNumber}}",
|
|
16423
|
+
subjectPlaceholder: "e.g. Payment Unpaid for Order {{orderNumber}}",
|
|
16424
|
+
body: `Hi {{vendorName}},
|
|
16425
|
+
|
|
16426
|
+
Payment for order {{orderNumber}} ({{total}} {{currency}}) is unpaid or failed.
|
|
16427
|
+
|
|
16428
|
+
Customer: {{customerName}}
|
|
16429
|
+
|
|
16430
|
+
Thank you.`,
|
|
16431
|
+
bodyPlaceholder: "Hi {{vendorName}},\n\nPayment for order {{orderNumber}} failed or unpaid."
|
|
16432
|
+
},
|
|
16433
|
+
payment_refund_initiated: {
|
|
16434
|
+
subject: "Refund Initiated for Order {{orderNumber}}",
|
|
16435
|
+
subjectPlaceholder: "e.g. Refund Initiated for Order {{orderNumber}}",
|
|
16436
|
+
body: `Hi {{vendorName}},
|
|
16437
|
+
|
|
16438
|
+
Order {{orderNumber}} has been cancelled and a refund of {{refundAmount}} {{currency}} has been initiated for {{customerName}}.
|
|
16439
|
+
|
|
16440
|
+
Thank you.`,
|
|
16441
|
+
bodyPlaceholder: "Hi {{vendorName}},\n\nRefund initiated for order {{orderNumber}}."
|
|
16215
16442
|
}
|
|
16216
16443
|
};
|
|
16217
16444
|
ADMIN_EMAIL_TRIGGER_DEFAULTS = {
|
|
@@ -16243,6 +16470,42 @@ Customer: {{customerName}}
|
|
|
16243
16470
|
Vendor: {{vendorName}}
|
|
16244
16471
|
Refund Due: {{refundAmount}} {{currency}}`,
|
|
16245
16472
|
bodyPlaceholder: "Hi Admin,\n\nOrder {{orderNumber}} cancelled."
|
|
16473
|
+
},
|
|
16474
|
+
payment_success: {
|
|
16475
|
+
subject: "Payment Success Alert: Order {{orderNumber}} ({{total}} {{currency}})",
|
|
16476
|
+
subjectPlaceholder: "e.g. Payment Success Alert: Order {{orderNumber}}",
|
|
16477
|
+
body: `Hi Admin,
|
|
16478
|
+
|
|
16479
|
+
Payment of {{total}} {{currency}} was successfully captured for order {{orderNumber}}.
|
|
16480
|
+
|
|
16481
|
+
Customer: {{customerName}}
|
|
16482
|
+
Vendor: {{vendorName}}
|
|
16483
|
+
|
|
16484
|
+
Order Summary:
|
|
16485
|
+
{{orderDetails}}`,
|
|
16486
|
+
bodyPlaceholder: "Payment received for order {{orderNumber}}."
|
|
16487
|
+
},
|
|
16488
|
+
payment_failed: {
|
|
16489
|
+
subject: "Payment Failed / Unpaid Alert: Order {{orderNumber}}",
|
|
16490
|
+
subjectPlaceholder: "e.g. Payment Failed Alert: Order {{orderNumber}}",
|
|
16491
|
+
body: `Hi Admin,
|
|
16492
|
+
|
|
16493
|
+
Payment for order {{orderNumber}} ({{total}} {{currency}}) is unpaid or failed.
|
|
16494
|
+
|
|
16495
|
+
Customer: {{customerName}}
|
|
16496
|
+
Vendor: {{vendorName}}`,
|
|
16497
|
+
bodyPlaceholder: "Payment failed/unpaid for order {{orderNumber}}."
|
|
16498
|
+
},
|
|
16499
|
+
payment_refund_initiated: {
|
|
16500
|
+
subject: "Refund Initiated Alert: Order {{orderNumber}}",
|
|
16501
|
+
subjectPlaceholder: "e.g. Refund Initiated Alert: Order {{orderNumber}}",
|
|
16502
|
+
body: `Hi Admin,
|
|
16503
|
+
|
|
16504
|
+
Order {{orderNumber}} was cancelled and refund of {{refundAmount}} {{currency}} was initiated.
|
|
16505
|
+
|
|
16506
|
+
Customer: {{customerName}}
|
|
16507
|
+
Vendor: {{vendorName}}`,
|
|
16508
|
+
bodyPlaceholder: "Refund initiated for order {{orderNumber}}."
|
|
16246
16509
|
}
|
|
16247
16510
|
};
|
|
16248
16511
|
__name(getEmailTriggerDefaults, "getEmailTriggerDefaults");
|
|
@@ -16258,6 +16521,24 @@ Refund Due: {{refundAmount}} {{currency}}`,
|
|
|
16258
16521
|
subjectPlaceholder: "e.g. Order {{orderNumber}} Cancelled",
|
|
16259
16522
|
body: `Hi {{customerName}}, your order {{orderNumber}} for {{total}} {{currency}} has been cancelled.`,
|
|
16260
16523
|
bodyPlaceholder: "Hi {{customerName}}, your order {{orderNumber}} has been cancelled."
|
|
16524
|
+
},
|
|
16525
|
+
payment_success: {
|
|
16526
|
+
subject: "Payment Successful!",
|
|
16527
|
+
subjectPlaceholder: "e.g. Payment Successful!",
|
|
16528
|
+
body: `Hi {{customerName}}, payment for order {{orderNumber}} ({{total}} {{currency}}) was successful.`,
|
|
16529
|
+
bodyPlaceholder: "Payment for order {{orderNumber}} successful."
|
|
16530
|
+
},
|
|
16531
|
+
payment_failed: {
|
|
16532
|
+
subject: "Payment Unpaid / Failed",
|
|
16533
|
+
subjectPlaceholder: "e.g. Payment Unpaid / Failed",
|
|
16534
|
+
body: `Hi {{customerName}}, payment for order {{orderNumber}} failed or remains unpaid.`,
|
|
16535
|
+
bodyPlaceholder: "Payment for order {{orderNumber}} failed."
|
|
16536
|
+
},
|
|
16537
|
+
payment_refund_initiated: {
|
|
16538
|
+
subject: "Refund Initiated",
|
|
16539
|
+
subjectPlaceholder: "e.g. Refund Initiated",
|
|
16540
|
+
body: `Hi {{customerName}}, a refund of {{refundAmount}} {{currency}} for order {{orderNumber}} has been initiated.`,
|
|
16541
|
+
bodyPlaceholder: "Refund for order {{orderNumber}} initiated."
|
|
16261
16542
|
}
|
|
16262
16543
|
};
|
|
16263
16544
|
VENDOR_PUSH_TRIGGER_DEFAULTS = {
|
|
@@ -16272,6 +16553,24 @@ Refund Due: {{refundAmount}} {{currency}}`,
|
|
|
16272
16553
|
subjectPlaceholder: "e.g. Order {{orderNumber}} Cancelled",
|
|
16273
16554
|
body: `Hi {{vendorName}}, order {{orderNumber}} from {{customerName}} has been cancelled.`,
|
|
16274
16555
|
bodyPlaceholder: "Hi {{vendorName}}, order {{orderNumber}} was cancelled."
|
|
16556
|
+
},
|
|
16557
|
+
payment_success: {
|
|
16558
|
+
subject: "Payment Confirmed: {{orderNumber}}",
|
|
16559
|
+
subjectPlaceholder: "e.g. Payment Confirmed: {{orderNumber}}",
|
|
16560
|
+
body: `Hi {{vendorName}}, payment for order {{orderNumber}} from {{customerName}} has been confirmed.`,
|
|
16561
|
+
bodyPlaceholder: "Payment for order {{orderNumber}} confirmed."
|
|
16562
|
+
},
|
|
16563
|
+
payment_failed: {
|
|
16564
|
+
subject: "Payment Unpaid: {{orderNumber}}",
|
|
16565
|
+
subjectPlaceholder: "e.g. Payment Unpaid: {{orderNumber}}",
|
|
16566
|
+
body: `Hi {{vendorName}}, payment for order {{orderNumber}} from {{customerName}} is unpaid or failed.`,
|
|
16567
|
+
bodyPlaceholder: "Payment for order {{orderNumber}} unpaid."
|
|
16568
|
+
},
|
|
16569
|
+
payment_refund_initiated: {
|
|
16570
|
+
subject: "Refund Initiated: {{orderNumber}}",
|
|
16571
|
+
subjectPlaceholder: "e.g. Refund Initiated: {{orderNumber}}",
|
|
16572
|
+
body: `Hi {{vendorName}}, refund initiated for order {{orderNumber}} ({{customerName}}).`,
|
|
16573
|
+
bodyPlaceholder: "Refund initiated for order {{orderNumber}}."
|
|
16275
16574
|
}
|
|
16276
16575
|
};
|
|
16277
16576
|
ADMIN_PUSH_TRIGGER_DEFAULTS = {
|
|
@@ -16303,6 +16602,24 @@ Customer: {{customerName}}
|
|
|
16303
16602
|
Vendor: {{vendorName}}
|
|
16304
16603
|
Refund Due: {{refundAmount}} {{currency}}`,
|
|
16305
16604
|
bodyPlaceholder: "Hi Admin,\n\nOrder {{orderNumber}} cancelled."
|
|
16605
|
+
},
|
|
16606
|
+
payment_success: {
|
|
16607
|
+
subject: "Payment Success: {{orderNumber}}",
|
|
16608
|
+
subjectPlaceholder: "e.g. Payment Success: {{orderNumber}}",
|
|
16609
|
+
body: `Payment of {{total}} {{currency}} captured for order {{orderNumber}} ({{customerName}}).`,
|
|
16610
|
+
bodyPlaceholder: "Payment captured for order {{orderNumber}}."
|
|
16611
|
+
},
|
|
16612
|
+
payment_failed: {
|
|
16613
|
+
subject: "Payment Failed/Unpaid: {{orderNumber}}",
|
|
16614
|
+
subjectPlaceholder: "e.g. Payment Failed: {{orderNumber}}",
|
|
16615
|
+
body: `Payment for order {{orderNumber}} ({{customerName}}) is unpaid or failed.`,
|
|
16616
|
+
bodyPlaceholder: "Payment failed for order {{orderNumber}}."
|
|
16617
|
+
},
|
|
16618
|
+
payment_refund_initiated: {
|
|
16619
|
+
subject: "Refund Initiated: {{orderNumber}}",
|
|
16620
|
+
subjectPlaceholder: "e.g. Refund Initiated: {{orderNumber}}",
|
|
16621
|
+
body: `Refund of {{refundAmount}} {{currency}} initiated for order {{orderNumber}}.`,
|
|
16622
|
+
bodyPlaceholder: "Refund initiated for order {{orderNumber}}."
|
|
16306
16623
|
}
|
|
16307
16624
|
};
|
|
16308
16625
|
__name(getPushTriggerDefaults, "getPushTriggerDefaults");
|
|
@@ -16956,6 +17273,7 @@ var init_emailTriggersBindingsPage = __esm({
|
|
|
16956
17273
|
orderNumber: "Display order number",
|
|
16957
17274
|
customerName: "Customer full name",
|
|
16958
17275
|
customerPhone: "Customer phone",
|
|
17276
|
+
customerEmail: "Customer email address",
|
|
16959
17277
|
eventName: "Event title / product name",
|
|
16960
17278
|
vendorName: "Vendor / store name",
|
|
16961
17279
|
total: "Order total amount",
|
|
@@ -16963,7 +17281,8 @@ var init_emailTriggersBindingsPage = __esm({
|
|
|
16963
17281
|
vendorId: "Vendor / store ID",
|
|
16964
17282
|
refundAmount: "Refund amount (refund triggers)",
|
|
16965
17283
|
invoiceNumber: "Generated invoice number",
|
|
16966
|
-
|
|
17284
|
+
invoiceAttachment: "Include this variable to attach Tax Invoice PDF to email",
|
|
17285
|
+
orderDetails: "Formatted item details summary"
|
|
16967
17286
|
};
|
|
16968
17287
|
__name(EmailTriggerBindings, "EmailTriggerBindings");
|
|
16969
17288
|
__name(TriggerEmailEditor, "TriggerEmailEditor");
|
|
@@ -17261,6 +17580,7 @@ var init_pushTriggersBindingsPage = __esm({
|
|
|
17261
17580
|
orderNumber: "Display order number",
|
|
17262
17581
|
customerName: "Customer full name",
|
|
17263
17582
|
customerPhone: "Customer phone",
|
|
17583
|
+
customerEmail: "Customer email address",
|
|
17264
17584
|
eventName: "Event title / product name",
|
|
17265
17585
|
vendorName: "Vendor / store name",
|
|
17266
17586
|
total: "Order total amount",
|
|
@@ -17268,7 +17588,8 @@ var init_pushTriggersBindingsPage = __esm({
|
|
|
17268
17588
|
vendorId: "Vendor / store ID",
|
|
17269
17589
|
refundAmount: "Refund amount (refund triggers)",
|
|
17270
17590
|
invoiceNumber: "Generated invoice number",
|
|
17271
|
-
|
|
17591
|
+
invoiceAttachment: "Include this variable to attach Tax Invoice PDF to email",
|
|
17592
|
+
orderDetails: "Formatted item details summary"
|
|
17272
17593
|
};
|
|
17273
17594
|
__name(PushTriggerBindings, "PushTriggerBindings");
|
|
17274
17595
|
}
|
|
@@ -18106,6 +18427,177 @@ var init_AuthProvidersPluginSettings = __esm({
|
|
|
18106
18427
|
__name(AuthProvidersPluginSettings, "AuthProvidersPluginSettings");
|
|
18107
18428
|
}
|
|
18108
18429
|
});
|
|
18430
|
+
function TurnstilePluginSettings({ settingsGroup, onEnabledChange }) {
|
|
18431
|
+
const [loading, setLoading] = useState(true);
|
|
18432
|
+
const [saving, setSaving] = useState(false);
|
|
18433
|
+
const [enabled, setEnabled] = useState(false);
|
|
18434
|
+
const [siteKey, setSiteKey] = useState("");
|
|
18435
|
+
const [secretKey, setSecretKey] = useState("");
|
|
18436
|
+
const [hasSavedSecret, setHasSavedSecret] = useState(false);
|
|
18437
|
+
const [showSecret, setShowSecret] = useState(false);
|
|
18438
|
+
const onEnabledChangeRef = useRef(onEnabledChange);
|
|
18439
|
+
onEnabledChangeRef.current = onEnabledChange;
|
|
18440
|
+
useEffect(() => {
|
|
18441
|
+
let cancelled = false;
|
|
18442
|
+
(async () => {
|
|
18443
|
+
setLoading(true);
|
|
18444
|
+
try {
|
|
18445
|
+
const res = await fetch(`/api/settings/${settingsGroup}`, {
|
|
18446
|
+
cache: "no-store"
|
|
18447
|
+
});
|
|
18448
|
+
const data = res.ok ? await res.json() : {};
|
|
18449
|
+
if (cancelled) return;
|
|
18450
|
+
const isEnabled = data.enabled === "true" || data.enabled === "1";
|
|
18451
|
+
setEnabled(isEnabled);
|
|
18452
|
+
setSiteKey(String(data.siteKey ?? data.TURNSTILE_SITE_KEY ?? "").trim());
|
|
18453
|
+
const secret = String(data.secretKey ?? data.TURNSTILE_SECRET_KEY ?? "").trim();
|
|
18454
|
+
setSecretKey("");
|
|
18455
|
+
setHasSavedSecret(Boolean(secret));
|
|
18456
|
+
} catch {
|
|
18457
|
+
} finally {
|
|
18458
|
+
if (!cancelled) setLoading(false);
|
|
18459
|
+
}
|
|
18460
|
+
})();
|
|
18461
|
+
return () => {
|
|
18462
|
+
cancelled = true;
|
|
18463
|
+
};
|
|
18464
|
+
}, [
|
|
18465
|
+
settingsGroup
|
|
18466
|
+
]);
|
|
18467
|
+
const handleSave = /* @__PURE__ */ __name(async () => {
|
|
18468
|
+
setSaving(true);
|
|
18469
|
+
try {
|
|
18470
|
+
const payload = {
|
|
18471
|
+
enabled: {
|
|
18472
|
+
value: enabled ? "true" : "false",
|
|
18473
|
+
type: "public"
|
|
18474
|
+
},
|
|
18475
|
+
siteKey: {
|
|
18476
|
+
value: siteKey.trim(),
|
|
18477
|
+
type: "public"
|
|
18478
|
+
}
|
|
18479
|
+
};
|
|
18480
|
+
if (secretKey.trim()) {
|
|
18481
|
+
payload.secretKey = {
|
|
18482
|
+
value: secretKey.trim(),
|
|
18483
|
+
type: "private",
|
|
18484
|
+
encrypted: true
|
|
18485
|
+
};
|
|
18486
|
+
}
|
|
18487
|
+
const res = await fetch(`/api/settings/${settingsGroup}`, {
|
|
18488
|
+
method: "PUT",
|
|
18489
|
+
headers: {
|
|
18490
|
+
"Content-Type": "application/json"
|
|
18491
|
+
},
|
|
18492
|
+
body: JSON.stringify(payload)
|
|
18493
|
+
});
|
|
18494
|
+
if (res.ok) {
|
|
18495
|
+
toast.success("Turnstile settings saved");
|
|
18496
|
+
if (secretKey.trim()) {
|
|
18497
|
+
setHasSavedSecret(true);
|
|
18498
|
+
setSecretKey("");
|
|
18499
|
+
}
|
|
18500
|
+
onEnabledChangeRef.current?.(enabled);
|
|
18501
|
+
} else {
|
|
18502
|
+
const err = await res.json().catch(() => ({}));
|
|
18503
|
+
toast.error(err?.message || "Failed to save settings");
|
|
18504
|
+
}
|
|
18505
|
+
} catch {
|
|
18506
|
+
toast.error("Failed to save settings");
|
|
18507
|
+
} finally {
|
|
18508
|
+
setSaving(false);
|
|
18509
|
+
}
|
|
18510
|
+
}, "handleSave");
|
|
18511
|
+
if (loading) {
|
|
18512
|
+
return /* @__PURE__ */ React.createElement("div", {
|
|
18513
|
+
className: "flex items-center justify-center p-8 text-muted-foreground text-sm"
|
|
18514
|
+
}, /* @__PURE__ */ React.createElement(Loader2, {
|
|
18515
|
+
className: "mr-2 h-4 w-4 animate-spin"
|
|
18516
|
+
}), "Loading settings\u2026");
|
|
18517
|
+
}
|
|
18518
|
+
return /* @__PURE__ */ React.createElement("div", {
|
|
18519
|
+
className: "space-y-6"
|
|
18520
|
+
}, /* @__PURE__ */ React.createElement("div", {
|
|
18521
|
+
className: "rounded-lg border border-gray-200 bg-gray-50/80 p-4 dark:border-gray-700 dark:bg-gray-800/40"
|
|
18522
|
+
}, /* @__PURE__ */ React.createElement("div", {
|
|
18523
|
+
className: "flex items-center justify-between"
|
|
18524
|
+
}, /* @__PURE__ */ React.createElement("div", {
|
|
18525
|
+
className: "space-y-0.5"
|
|
18526
|
+
}, /* @__PURE__ */ React.createElement(Label3, {
|
|
18527
|
+
htmlFor: `${settingsGroup}-enabled`,
|
|
18528
|
+
className: "text-sm font-semibold text-gray-900 dark:text-white"
|
|
18529
|
+
}, "Enable Cloudflare Turnstile"), /* @__PURE__ */ React.createElement("p", {
|
|
18530
|
+
className: "text-xs text-muted-foreground"
|
|
18531
|
+
}, "Master switch for bot protection. When enabled, helps protect supported forms from automated bots, while forms can apply their configured bot protection settings.")), /* @__PURE__ */ React.createElement(Switch, {
|
|
18532
|
+
id: `${settingsGroup}-enabled`,
|
|
18533
|
+
checked: enabled,
|
|
18534
|
+
onCheckedChange: setEnabled
|
|
18535
|
+
}))), /* @__PURE__ */ React.createElement("div", {
|
|
18536
|
+
className: "space-y-4"
|
|
18537
|
+
}, /* @__PURE__ */ React.createElement("div", {
|
|
18538
|
+
className: "space-y-1.5"
|
|
18539
|
+
}, /* @__PURE__ */ React.createElement(Label3, {
|
|
18540
|
+
htmlFor: `${settingsGroup}-siteKey`,
|
|
18541
|
+
className: "text-sm font-medium"
|
|
18542
|
+
}, "Turnstile Site Key (Public)"), /* @__PURE__ */ React.createElement(Input, {
|
|
18543
|
+
id: `${settingsGroup}-siteKey`,
|
|
18544
|
+
value: siteKey,
|
|
18545
|
+
onChange: /* @__PURE__ */ __name((e) => setSiteKey(e.target.value), "onChange"),
|
|
18546
|
+
placeholder: "0x4AAAAAA...",
|
|
18547
|
+
className: "h-9 font-mono text-sm"
|
|
18548
|
+
}), /* @__PURE__ */ React.createElement("p", {
|
|
18549
|
+
className: "text-xs text-muted-foreground"
|
|
18550
|
+
}, "Obtained from your Cloudflare dashboard under Turnstile Sites. Safe to expose to the frontend.")), /* @__PURE__ */ React.createElement("div", {
|
|
18551
|
+
className: "space-y-1.5"
|
|
18552
|
+
}, /* @__PURE__ */ React.createElement("div", {
|
|
18553
|
+
className: "flex items-center justify-between"
|
|
18554
|
+
}, /* @__PURE__ */ React.createElement(Label3, {
|
|
18555
|
+
htmlFor: `${settingsGroup}-secretKey`,
|
|
18556
|
+
className: "text-sm font-medium"
|
|
18557
|
+
}, "Turnstile Secret Key (Private)"), hasSavedSecret && /* @__PURE__ */ React.createElement("span", {
|
|
18558
|
+
className: "inline-flex items-center gap-1 text-xs font-medium text-emerald-600 dark:text-emerald-400"
|
|
18559
|
+
}, /* @__PURE__ */ React.createElement(ShieldCheck, {
|
|
18560
|
+
className: "h-3.5 w-3.5"
|
|
18561
|
+
}), "Secret key configured")), /* @__PURE__ */ React.createElement("div", {
|
|
18562
|
+
className: "relative"
|
|
18563
|
+
}, /* @__PURE__ */ React.createElement(Input, {
|
|
18564
|
+
id: `${settingsGroup}-secretKey`,
|
|
18565
|
+
type: showSecret ? "text" : "password",
|
|
18566
|
+
value: secretKey,
|
|
18567
|
+
onChange: /* @__PURE__ */ __name((e) => setSecretKey(e.target.value), "onChange"),
|
|
18568
|
+
placeholder: hasSavedSecret ? "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022 (leave blank to keep unchanged)" : "0x4AAAAAA...",
|
|
18569
|
+
className: "h-9 font-mono text-sm pr-10"
|
|
18570
|
+
}), /* @__PURE__ */ React.createElement("button", {
|
|
18571
|
+
type: "button",
|
|
18572
|
+
className: "absolute right-2.5 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200",
|
|
18573
|
+
onClick: /* @__PURE__ */ __name(() => setShowSecret(!showSecret), "onClick")
|
|
18574
|
+
}, showSecret ? /* @__PURE__ */ React.createElement(EyeOff, {
|
|
18575
|
+
className: "h-4 w-4"
|
|
18576
|
+
}) : /* @__PURE__ */ React.createElement(Eye, {
|
|
18577
|
+
className: "h-4 w-4"
|
|
18578
|
+
}))), /* @__PURE__ */ React.createElement("p", {
|
|
18579
|
+
className: "text-xs text-muted-foreground"
|
|
18580
|
+
}, "Used only on the server to verify tokens with Cloudflare Siteverify API. Never sent to browsers."))), /* @__PURE__ */ React.createElement(Button, {
|
|
18581
|
+
onClick: handleSave,
|
|
18582
|
+
disabled: saving,
|
|
18583
|
+
size: "sm",
|
|
18584
|
+
className: "gap-2"
|
|
18585
|
+
}, saving ? /* @__PURE__ */ React.createElement(Loader2, {
|
|
18586
|
+
className: "h-4 w-4 animate-spin"
|
|
18587
|
+
}) : /* @__PURE__ */ React.createElement(Save, {
|
|
18588
|
+
className: "h-4 w-4"
|
|
18589
|
+
}), "Save Settings"));
|
|
18590
|
+
}
|
|
18591
|
+
var init_TurnstilePluginSettings = __esm({
|
|
18592
|
+
"src/admin/components/TurnstilePluginSettings.tsx"() {
|
|
18593
|
+
"use client";
|
|
18594
|
+
init_button();
|
|
18595
|
+
init_input();
|
|
18596
|
+
init_label();
|
|
18597
|
+
init_switch();
|
|
18598
|
+
__name(TurnstilePluginSettings, "TurnstilePluginSettings");
|
|
18599
|
+
}
|
|
18600
|
+
});
|
|
18109
18601
|
|
|
18110
18602
|
// src/plugins/llm/chat-email-intent.ts
|
|
18111
18603
|
function normalizeIntentKey(raw) {
|
|
@@ -18484,6 +18976,7 @@ function PluginSettingsPanel({ descriptor, onSaved }) {
|
|
|
18484
18976
|
const isSocialMedia = settingsGroup === "social_media";
|
|
18485
18977
|
const isMultiVendor = settingsGroup === "multi_vendor";
|
|
18486
18978
|
const isAuthProviders = settingsGroup === "auth_providers";
|
|
18979
|
+
const isTurnstile = settingsGroup === "turnstile";
|
|
18487
18980
|
const [enabled, setEnabled] = useState(true);
|
|
18488
18981
|
const [botName, setBotName] = useState("");
|
|
18489
18982
|
const [icon, setIcon] = useState("");
|
|
@@ -19827,6 +20320,15 @@ function PluginSettingsPanel({ descriptor, onSaved }) {
|
|
|
19827
20320
|
}, "onEnabledChange")
|
|
19828
20321
|
});
|
|
19829
20322
|
}
|
|
20323
|
+
if (isTurnstile) {
|
|
20324
|
+
return /* @__PURE__ */ React.createElement(TurnstilePluginSettings, {
|
|
20325
|
+
settingsGroup,
|
|
20326
|
+
onEnabledChange: /* @__PURE__ */ __name((value) => {
|
|
20327
|
+
setEnabled(value);
|
|
20328
|
+
onSaved?.();
|
|
20329
|
+
}, "onEnabledChange")
|
|
20330
|
+
});
|
|
20331
|
+
}
|
|
19830
20332
|
if (loading) return /* @__PURE__ */ React.createElement("div", {
|
|
19831
20333
|
className: "text-sm text-gray-500 dark:text-gray-400"
|
|
19832
20334
|
}, "Loading...");
|
|
@@ -21167,6 +21669,10 @@ function PluginsPage() {
|
|
|
21167
21669
|
const ap = pluginDescriptors.find((p) => p.name === "auth_providers");
|
|
21168
21670
|
if (ap) setSelectedName(ap.name);
|
|
21169
21671
|
}
|
|
21672
|
+
if (q === "turnstile" || q === "cloudflare_turnstile" || q === "captcha") {
|
|
21673
|
+
const ts = pluginDescriptors.find((p) => p.name === "turnstile");
|
|
21674
|
+
if (ts) setSelectedName(ts.name);
|
|
21675
|
+
}
|
|
21170
21676
|
}, [
|
|
21171
21677
|
searchParams,
|
|
21172
21678
|
pluginDescriptors
|
|
@@ -21279,6 +21785,7 @@ var init_PluginsPage = __esm({
|
|
|
21279
21785
|
init_select();
|
|
21280
21786
|
init_EventNotificationsPluginSettings();
|
|
21281
21787
|
init_AuthProvidersPluginSettings();
|
|
21788
|
+
init_TurnstilePluginSettings();
|
|
21282
21789
|
init_ImageOrUrlField();
|
|
21283
21790
|
init_chat_email_intent();
|
|
21284
21791
|
init_llm_agent_scope();
|
|
@@ -21298,7 +21805,8 @@ var init_PluginsPage = __esm({
|
|
|
21298
21805
|
share: Share2,
|
|
21299
21806
|
whatsapp: MessageCircle,
|
|
21300
21807
|
event_notifications: Bell,
|
|
21301
|
-
auth_providers: KeyRound
|
|
21808
|
+
auth_providers: KeyRound,
|
|
21809
|
+
turnstile: ShieldCheck
|
|
21302
21810
|
};
|
|
21303
21811
|
__name(normalizeSmsProviderChoice, "normalizeSmsProviderChoice");
|
|
21304
21812
|
__name(normalizeMsg91ApiMode, "normalizeMsg91ApiMode");
|
|
@@ -22260,7 +22768,7 @@ function VendorTeamPage() {
|
|
|
22260
22768
|
}
|
|
22261
22769
|
}, []);
|
|
22262
22770
|
useEffect(() => {
|
|
22263
|
-
if (canManage) load();
|
|
22771
|
+
if (canManage) void load();
|
|
22264
22772
|
else setLoading(false);
|
|
22265
22773
|
}, [
|
|
22266
22774
|
canManage,
|
|
@@ -22318,10 +22826,18 @@ function VendorTeamPage() {
|
|
|
22318
22826
|
}, "closeInviteDialog");
|
|
22319
22827
|
if (!canManage) {
|
|
22320
22828
|
return /* @__PURE__ */ React25__default.createElement("div", {
|
|
22321
|
-
className: "
|
|
22829
|
+
className: "min-w-0 rounded-lg bg-white shadow-md"
|
|
22830
|
+
}, /* @__PURE__ */ React25__default.createElement("div", {
|
|
22831
|
+
className: "rounded-t-lg border-b border-gray-700 bg-gray-800 px-4 py-2.5"
|
|
22832
|
+
}, /* @__PURE__ */ React25__default.createElement("h1", {
|
|
22833
|
+
className: "text-base font-semibold text-white"
|
|
22834
|
+
}, "Vendor Team"), /* @__PURE__ */ React25__default.createElement("p", {
|
|
22835
|
+
className: "mt-0.5 text-xs text-gray-300"
|
|
22836
|
+
}, "Invite members and assign a store role")), /* @__PURE__ */ React25__default.createElement("div", {
|
|
22837
|
+
className: "p-6"
|
|
22322
22838
|
}, /* @__PURE__ */ React25__default.createElement("p", {
|
|
22323
22839
|
className: "text-sm text-red-600"
|
|
22324
|
-
}, "Only the store owner can manage the vendor team."));
|
|
22840
|
+
}, "Only the store owner can manage the vendor team.")));
|
|
22325
22841
|
}
|
|
22326
22842
|
const handleAdd = /* @__PURE__ */ __name(async (e) => {
|
|
22327
22843
|
e.preventDefault();
|
|
@@ -22423,17 +22939,21 @@ function VendorTeamPage() {
|
|
|
22423
22939
|
}
|
|
22424
22940
|
}, "handleRemove");
|
|
22425
22941
|
return /* @__PURE__ */ React25__default.createElement("div", {
|
|
22426
|
-
className: "
|
|
22942
|
+
className: "min-w-0 rounded-lg bg-white shadow-md"
|
|
22943
|
+
}, /* @__PURE__ */ React25__default.createElement("div", {
|
|
22944
|
+
className: "rounded-t-lg border-b border-gray-700 bg-gray-800 px-4 py-2.5"
|
|
22427
22945
|
}, /* @__PURE__ */ React25__default.createElement("h1", {
|
|
22428
|
-
className: "text-
|
|
22946
|
+
className: "text-base font-semibold text-white"
|
|
22429
22947
|
}, "Vendor Team"), /* @__PURE__ */ React25__default.createElement("p", {
|
|
22430
|
-
className: "mt-
|
|
22431
|
-
}, "Invite member and assign a store role
|
|
22432
|
-
className: "
|
|
22948
|
+
className: "mt-0.5 text-xs text-gray-300"
|
|
22949
|
+
}, "Invite member and assign a store role")), /* @__PURE__ */ React25__default.createElement("div", {
|
|
22950
|
+
className: "p-6 space-y-6"
|
|
22951
|
+
}, /* @__PURE__ */ React25__default.createElement("div", {
|
|
22952
|
+
className: "rounded-lg border border-gray-200 overflow-hidden"
|
|
22433
22953
|
}, /* @__PURE__ */ React25__default.createElement("table", {
|
|
22434
22954
|
className: "min-w-full text-sm"
|
|
22435
22955
|
}, /* @__PURE__ */ React25__default.createElement("thead", {
|
|
22436
|
-
className: "bg-gray-50 text-left text-gray-600"
|
|
22956
|
+
className: "bg-gray-50 text-left text-gray-600 border-b border-gray-200"
|
|
22437
22957
|
}, /* @__PURE__ */ React25__default.createElement("tr", null, /* @__PURE__ */ React25__default.createElement("th", {
|
|
22438
22958
|
className: "px-3 py-2 font-medium"
|
|
22439
22959
|
}, "Name"), /* @__PURE__ */ React25__default.createElement("th", {
|
|
@@ -22443,8 +22963,10 @@ function VendorTeamPage() {
|
|
|
22443
22963
|
}, "Phone"), /* @__PURE__ */ React25__default.createElement("th", {
|
|
22444
22964
|
className: "px-3 py-2 font-medium"
|
|
22445
22965
|
}, "Store role"), /* @__PURE__ */ React25__default.createElement("th", {
|
|
22446
|
-
className: "px-3 py-2 font-medium"
|
|
22447
|
-
}))), /* @__PURE__ */ React25__default.createElement("tbody",
|
|
22966
|
+
className: "px-3 py-2 font-medium text-right"
|
|
22967
|
+
}))), /* @__PURE__ */ React25__default.createElement("tbody", {
|
|
22968
|
+
className: "divide-y divide-gray-100"
|
|
22969
|
+
}, loading ? /* @__PURE__ */ React25__default.createElement("tr", null, /* @__PURE__ */ React25__default.createElement("td", {
|
|
22448
22970
|
colSpan: 5,
|
|
22449
22971
|
className: "px-3 py-4 text-gray-500"
|
|
22450
22972
|
}, "Loading\u2026")) : members.length === 0 ? /* @__PURE__ */ React25__default.createElement("tr", null, /* @__PURE__ */ React25__default.createElement("td", {
|
|
@@ -22454,15 +22976,17 @@ function VendorTeamPage() {
|
|
|
22454
22976
|
key: m.vendorUserId,
|
|
22455
22977
|
className: "border-t border-gray-100"
|
|
22456
22978
|
}, /* @__PURE__ */ React25__default.createElement("td", {
|
|
22457
|
-
className: "px-3 py-2"
|
|
22979
|
+
className: "px-3 py-2 font-medium text-gray-900"
|
|
22458
22980
|
}, m.name ?? "\u2014"), /* @__PURE__ */ React25__default.createElement("td", {
|
|
22459
|
-
className: "px-3 py-2"
|
|
22981
|
+
className: "px-3 py-2 text-gray-600"
|
|
22460
22982
|
}, m.email), /* @__PURE__ */ React25__default.createElement("td", {
|
|
22461
|
-
className: "px-3 py-2"
|
|
22983
|
+
className: "px-3 py-2 text-gray-600"
|
|
22462
22984
|
}, m.phone ?? "\u2014"), /* @__PURE__ */ React25__default.createElement("td", {
|
|
22463
22985
|
className: "px-3 py-2"
|
|
22464
|
-
}, m.isOwnerRole ? /* @__PURE__ */ React25__default.createElement("span",
|
|
22465
|
-
className: "
|
|
22986
|
+
}, m.isOwnerRole ? /* @__PURE__ */ React25__default.createElement("span", {
|
|
22987
|
+
className: "text-gray-900 font-medium"
|
|
22988
|
+
}, m.vendorRoleName ?? "Owner") : /* @__PURE__ */ React25__default.createElement("select", {
|
|
22989
|
+
className: "rounded border border-gray-200 px-2 py-1 text-sm bg-white",
|
|
22466
22990
|
value: m.vendorRoleId ?? "",
|
|
22467
22991
|
disabled: roleUpdating === m.userId,
|
|
22468
22992
|
onChange: /* @__PURE__ */ __name((e) => handleRoleChange(m.userId, Number(e.target.value)), "onChange")
|
|
@@ -22478,7 +23002,7 @@ function VendorTeamPage() {
|
|
|
22478
23002
|
onClick: /* @__PURE__ */ __name(() => handleRemove(m.userId), "onClick")
|
|
22479
23003
|
}, "Remove"))))))), /* @__PURE__ */ React25__default.createElement("form", {
|
|
22480
23004
|
onSubmit: handleAdd,
|
|
22481
|
-
className: "
|
|
23005
|
+
className: "space-y-4 rounded-lg border border-gray-200 p-4"
|
|
22482
23006
|
}, /* @__PURE__ */ React25__default.createElement("h2", {
|
|
22483
23007
|
className: "text-sm font-medium text-gray-900"
|
|
22484
23008
|
}, "Invite team member"), /* @__PURE__ */ React25__default.createElement("div", {
|
|
@@ -22512,7 +23036,7 @@ function VendorTeamPage() {
|
|
|
22512
23036
|
htmlFor: "teamRole"
|
|
22513
23037
|
}, "Store role"), /* @__PURE__ */ React25__default.createElement("select", {
|
|
22514
23038
|
id: "teamRole",
|
|
22515
|
-
className: "mt-1 w-full rounded-md border border-gray-200 px-3 py-2 text-sm",
|
|
23039
|
+
className: "mt-1 w-full rounded-md border border-gray-200 px-3 py-2 text-sm bg-white",
|
|
22516
23040
|
value: vendorRoleId,
|
|
22517
23041
|
onChange: /* @__PURE__ */ __name((e) => setVendorRoleId(e.target.value ? Number(e.target.value) : ""), "onChange")
|
|
22518
23042
|
}, assignableRoles.map((r) => /* @__PURE__ */ React25__default.createElement("option", {
|
|
@@ -22551,7 +23075,7 @@ function VendorTeamPage() {
|
|
|
22551
23075
|
}, message), /* @__PURE__ */ React25__default.createElement(Button, {
|
|
22552
23076
|
type: "submit",
|
|
22553
23077
|
disabled: submitting
|
|
22554
|
-
}, submitting ? "Inviting\u2026" : "Invite member")), /* @__PURE__ */ React25__default.createElement(Dialog, {
|
|
23078
|
+
}, submitting ? "Inviting\u2026" : "Invite member"))), /* @__PURE__ */ React25__default.createElement(Dialog, {
|
|
22555
23079
|
open: inviteDialog != null,
|
|
22556
23080
|
onOpenChange: /* @__PURE__ */ __name((open) => {
|
|
22557
23081
|
if (!open) closeInviteDialog();
|
|
@@ -22571,7 +23095,7 @@ function VendorTeamPage() {
|
|
|
22571
23095
|
variant: "outline",
|
|
22572
23096
|
onClick: /* @__PURE__ */ __name(() => void copyInviteLink(), "onClick")
|
|
22573
23097
|
}, linkCopied ? /* @__PURE__ */ React25__default.createElement(Check, {
|
|
22574
|
-
className: "h-4 w-4 mr-2"
|
|
23098
|
+
className: "h-4 w-4 mr-2 text-green-600"
|
|
22575
23099
|
}) : /* @__PURE__ */ React25__default.createElement(Copy, {
|
|
22576
23100
|
className: "h-4 w-4 mr-2"
|
|
22577
23101
|
}), linkCopied ? "Copied" : "Copy invite link")), /* @__PURE__ */ React25__default.createElement(DialogFooter, null, /* @__PURE__ */ React25__default.createElement(Button, {
|
|
@@ -30586,15 +31110,15 @@ function ProductEditPage({ productId }) {
|
|
|
30586
31110
|
})));
|
|
30587
31111
|
}
|
|
30588
31112
|
}
|
|
30589
|
-
|
|
30590
|
-
|
|
30591
|
-
|
|
30592
|
-
|
|
30593
|
-
|
|
30594
|
-
|
|
30595
|
-
|
|
30596
|
-
|
|
30597
|
-
}
|
|
31113
|
+
const formsResActual = formsRes.ok ? formsRes : await fetch("/api/admin/cms-forms/product-options").catch(() => null);
|
|
31114
|
+
if (!cancelled && formsResActual && formsResActual.ok) {
|
|
31115
|
+
const d = await formsResActual.json();
|
|
31116
|
+
const rows = Array.isArray(d.data) ? d.data : Array.isArray(d) ? d : [];
|
|
31117
|
+
setContactForms(rows.filter((row) => row.id != null || row.value != null).map((row) => ({
|
|
31118
|
+
id: Number(row.id ?? row.value),
|
|
31119
|
+
name: row.name?.trim() || row.label?.trim() || `Form #${row.id ?? row.value}`,
|
|
31120
|
+
slug: row.slug
|
|
31121
|
+
})));
|
|
30598
31122
|
}
|
|
30599
31123
|
if (!cancelled && refundRes.ok) {
|
|
30600
31124
|
const d = await refundRes.json();
|
|
@@ -32846,6 +33370,252 @@ var init_EventProductsSection = __esm({
|
|
|
32846
33370
|
__name(EventProductsSection, "EventProductsSection");
|
|
32847
33371
|
}
|
|
32848
33372
|
});
|
|
33373
|
+
function AttachComboModal({ open, onOpenChange, excludeComboIds = [], onAttach }) {
|
|
33374
|
+
const [attachingId, setAttachingId] = useState(null);
|
|
33375
|
+
const [error, setError] = useState(null);
|
|
33376
|
+
const comboColumns = useMemo(() => STORE_CRUD_CONFIGS.combos.columns.filter((c) => c.field !== "eventId"), []);
|
|
33377
|
+
const comboFilterColumns = useMemo(() => STORE_CRUD_CONFIGS.combos.columns.filter((c) => c.field !== "eventId"), []);
|
|
33378
|
+
const comboFilters = useMemo(() => STORE_CRUD_CONFIGS.combos.filters?.filter((f) => f.param !== "eventId"), []);
|
|
33379
|
+
const extraListParams = useMemo(() => {
|
|
33380
|
+
const params = {};
|
|
33381
|
+
if (excludeComboIds.length > 0) {
|
|
33382
|
+
params.excludeIds = excludeComboIds.join(",");
|
|
33383
|
+
}
|
|
33384
|
+
return params;
|
|
33385
|
+
}, [
|
|
33386
|
+
excludeComboIds
|
|
33387
|
+
]);
|
|
33388
|
+
const handleAttach = /* @__PURE__ */ __name(async (comboId) => {
|
|
33389
|
+
setError(null);
|
|
33390
|
+
setAttachingId(comboId);
|
|
33391
|
+
try {
|
|
33392
|
+
await onAttach(comboId);
|
|
33393
|
+
onOpenChange(false);
|
|
33394
|
+
} catch (err) {
|
|
33395
|
+
setError(err instanceof Error ? err.message : "Failed to attach combo");
|
|
33396
|
+
} finally {
|
|
33397
|
+
setAttachingId(null);
|
|
33398
|
+
}
|
|
33399
|
+
}, "handleAttach");
|
|
33400
|
+
return /* @__PURE__ */ React.createElement(Dialog, {
|
|
33401
|
+
open,
|
|
33402
|
+
onOpenChange
|
|
33403
|
+
}, /* @__PURE__ */ React.createElement(DialogContent, {
|
|
33404
|
+
className: "max-w-4xl max-h-[90vh] overflow-y-auto"
|
|
33405
|
+
}, /* @__PURE__ */ React.createElement(DialogHeader, null, /* @__PURE__ */ React.createElement(DialogTitle, null, "Attach Event Combo"), /* @__PURE__ */ React.createElement(DialogDescription, null, "Choose a combo to link to this event.")), error ? /* @__PURE__ */ React.createElement("p", {
|
|
33406
|
+
className: "text-sm text-red-600 bg-red-50 rounded-md px-3 py-2"
|
|
33407
|
+
}, error) : null, /* @__PURE__ */ React.createElement(AdminCRUD, {
|
|
33408
|
+
key: `attach-combos-${excludeComboIds.join(",")}-${open}`,
|
|
33409
|
+
title: "Combos",
|
|
33410
|
+
apiEndpoint: "/api/combos",
|
|
33411
|
+
columns: comboColumns,
|
|
33412
|
+
filterColumns: comboFilterColumns,
|
|
33413
|
+
addEditPageUrl: "",
|
|
33414
|
+
defaultSortField: STORE_CRUD_CONFIGS.combos.defaultSortField,
|
|
33415
|
+
defaultSortOrder: STORE_CRUD_CONFIGS.combos.defaultSortOrder,
|
|
33416
|
+
filters: comboFilters,
|
|
33417
|
+
extraListParams,
|
|
33418
|
+
embedded: true,
|
|
33419
|
+
disableRowClick: true,
|
|
33420
|
+
emptyState: {
|
|
33421
|
+
title: "No combos available",
|
|
33422
|
+
description: excludeComboIds.length ? "All existing combos are already attached to this event, or none exist yet." : "Create a combo first, then attach it here."
|
|
33423
|
+
},
|
|
33424
|
+
customRowActions: /* @__PURE__ */ __name((item) => {
|
|
33425
|
+
const id = Number(item.id);
|
|
33426
|
+
const busy = attachingId === id;
|
|
33427
|
+
return /* @__PURE__ */ React.createElement(Button, {
|
|
33428
|
+
type: "button",
|
|
33429
|
+
size: "sm",
|
|
33430
|
+
variant: "outline",
|
|
33431
|
+
disabled: !Number.isFinite(id) || busy,
|
|
33432
|
+
className: "h-7 text-xs",
|
|
33433
|
+
onClick: /* @__PURE__ */ __name(() => void handleAttach(id), "onClick")
|
|
33434
|
+
}, /* @__PURE__ */ React.createElement(Link2$1, {
|
|
33435
|
+
className: "h-3.5 w-3.5 mr-1"
|
|
33436
|
+
}), busy ? "Attaching\u2026" : "Attach");
|
|
33437
|
+
}, "customRowActions")
|
|
33438
|
+
})));
|
|
33439
|
+
}
|
|
33440
|
+
var init_AttachComboModal = __esm({
|
|
33441
|
+
"src/components/Admin/AttachComboModal.tsx"() {
|
|
33442
|
+
"use client";
|
|
33443
|
+
init_dialog();
|
|
33444
|
+
init_button();
|
|
33445
|
+
init_CRUD();
|
|
33446
|
+
init_store_crud_configs();
|
|
33447
|
+
__name(AttachComboModal, "AttachComboModal");
|
|
33448
|
+
}
|
|
33449
|
+
});
|
|
33450
|
+
function EventCombosSection({ eventId, returnUrl, readOnly = false }) {
|
|
33451
|
+
const [rows, setRows] = useState([]);
|
|
33452
|
+
const [loading, setLoading] = useState(true);
|
|
33453
|
+
const [attachModalOpen, setAttachModalOpen] = useState(false);
|
|
33454
|
+
const [listRefreshKey, setListRefreshKey] = useState(0);
|
|
33455
|
+
const [detachingId, setDetachingId] = useState(null);
|
|
33456
|
+
const comboColumns = useMemo(() => STORE_CRUD_CONFIGS.combos.columns.filter((c) => c.field !== "eventId"), []);
|
|
33457
|
+
const comboFilterColumns = useMemo(() => STORE_CRUD_CONFIGS.combos.columns.filter((c) => c.field !== "eventId"), []);
|
|
33458
|
+
const comboFilters = useMemo(() => STORE_CRUD_CONFIGS.combos.filters?.filter((f) => f.param !== "eventId"), []);
|
|
33459
|
+
const loadRows = useCallback(async () => {
|
|
33460
|
+
setLoading(true);
|
|
33461
|
+
try {
|
|
33462
|
+
const res = await fetch(`/api/combos?eventId=${encodeURIComponent(eventId)}&limit=200`);
|
|
33463
|
+
if (!res.ok) throw new Error("Failed to load");
|
|
33464
|
+
const data = await res.json();
|
|
33465
|
+
const list = Array.isArray(data.data) ? data.data : [];
|
|
33466
|
+
setRows(list);
|
|
33467
|
+
} catch {
|
|
33468
|
+
setRows([]);
|
|
33469
|
+
} finally {
|
|
33470
|
+
setLoading(false);
|
|
33471
|
+
}
|
|
33472
|
+
}, [
|
|
33473
|
+
eventId
|
|
33474
|
+
]);
|
|
33475
|
+
useEffect(() => {
|
|
33476
|
+
void loadRows();
|
|
33477
|
+
}, [
|
|
33478
|
+
loadRows
|
|
33479
|
+
]);
|
|
33480
|
+
const attachedComboIds = useMemo(() => rows.map((r) => Number(r.id)).filter((id) => Number.isFinite(id) && id > 0), [
|
|
33481
|
+
rows
|
|
33482
|
+
]);
|
|
33483
|
+
const attachToEvent = /* @__PURE__ */ __name(async (comboId) => {
|
|
33484
|
+
const res = await fetch(`/api/combos/${comboId}`, {
|
|
33485
|
+
method: "PUT",
|
|
33486
|
+
headers: {
|
|
33487
|
+
"Content-Type": "application/json"
|
|
33488
|
+
},
|
|
33489
|
+
body: JSON.stringify({
|
|
33490
|
+
eventId: Number(eventId)
|
|
33491
|
+
})
|
|
33492
|
+
});
|
|
33493
|
+
if (!res.ok) {
|
|
33494
|
+
const data = await res.json().catch(() => ({}));
|
|
33495
|
+
throw new Error(data.error ?? "Failed to attach combo");
|
|
33496
|
+
}
|
|
33497
|
+
await loadRows();
|
|
33498
|
+
setListRefreshKey((k) => k + 1);
|
|
33499
|
+
}, "attachToEvent");
|
|
33500
|
+
const detachFromEvent = /* @__PURE__ */ __name(async (comboId) => {
|
|
33501
|
+
if (!window.confirm("Remove this combo from the event?")) return;
|
|
33502
|
+
setDetachingId(comboId);
|
|
33503
|
+
try {
|
|
33504
|
+
const res = await fetch(`/api/combos/${comboId}`, {
|
|
33505
|
+
method: "PUT",
|
|
33506
|
+
headers: {
|
|
33507
|
+
"Content-Type": "application/json"
|
|
33508
|
+
},
|
|
33509
|
+
body: JSON.stringify({
|
|
33510
|
+
eventId: null
|
|
33511
|
+
})
|
|
33512
|
+
});
|
|
33513
|
+
if (res.ok) {
|
|
33514
|
+
await loadRows();
|
|
33515
|
+
setListRefreshKey((k) => k + 1);
|
|
33516
|
+
}
|
|
33517
|
+
} finally {
|
|
33518
|
+
setDetachingId(null);
|
|
33519
|
+
}
|
|
33520
|
+
}, "detachFromEvent");
|
|
33521
|
+
const comboCreateHref = !readOnly ? `/admin/combos/create?eventId=${encodeURIComponent(eventId)}${returnUrl ? `&from=${encodeURIComponent(returnUrl)}` : ""}` : null;
|
|
33522
|
+
if (loading) {
|
|
33523
|
+
return /* @__PURE__ */ React.createElement("section", {
|
|
33524
|
+
className: "border border-gray-200 rounded-lg p-8 text-center text-sm text-gray-500"
|
|
33525
|
+
}, "Loading combos\u2026");
|
|
33526
|
+
}
|
|
33527
|
+
if (readOnly && rows.length === 0) {
|
|
33528
|
+
return /* @__PURE__ */ React.createElement("section", {
|
|
33529
|
+
className: "border border-gray-200 rounded-lg p-6"
|
|
33530
|
+
}, /* @__PURE__ */ React.createElement("h2", {
|
|
33531
|
+
className: "text-sm font-semibold text-gray-900"
|
|
33532
|
+
}, "Event Combos"), /* @__PURE__ */ React.createElement("p", {
|
|
33533
|
+
className: "mt-2 text-sm text-gray-600"
|
|
33534
|
+
}, "No combos are linked to this event yet."));
|
|
33535
|
+
}
|
|
33536
|
+
return /* @__PURE__ */ React.createElement("div", {
|
|
33537
|
+
className: "space-y-4"
|
|
33538
|
+
}, /* @__PURE__ */ React.createElement("section", {
|
|
33539
|
+
className: "border border-gray-200 rounded-lg overflow-hidden bg-white"
|
|
33540
|
+
}, /* @__PURE__ */ React.createElement("div", {
|
|
33541
|
+
className: "flex flex-wrap items-center justify-between gap-3 px-4 py-3 border-b border-gray-200"
|
|
33542
|
+
}, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("h2", {
|
|
33543
|
+
className: "text-sm font-semibold text-gray-900"
|
|
33544
|
+
}, "Event Combos"), /* @__PURE__ */ React.createElement("p", {
|
|
33545
|
+
className: "text-xs text-gray-500"
|
|
33546
|
+
}, "Event Combos linked to this event.")), !readOnly ? /* @__PURE__ */ React.createElement("div", {
|
|
33547
|
+
className: "flex flex-wrap items-center gap-2"
|
|
33548
|
+
}, /* @__PURE__ */ React.createElement(Button, {
|
|
33549
|
+
type: "button",
|
|
33550
|
+
variant: "outline",
|
|
33551
|
+
size: "sm",
|
|
33552
|
+
className: "h-8 text-xs",
|
|
33553
|
+
onClick: /* @__PURE__ */ __name(() => setAttachModalOpen(true), "onClick")
|
|
33554
|
+
}, /* @__PURE__ */ React.createElement(Link2$1, {
|
|
33555
|
+
className: "h-3.5 w-3.5 mr-1"
|
|
33556
|
+
}), "Attach event combo"), comboCreateHref ? /* @__PURE__ */ React.createElement(Link2, {
|
|
33557
|
+
href: comboCreateHref,
|
|
33558
|
+
className: "inline-flex items-center gap-1.5 rounded-md border border-gray-300 bg-white px-2.5 py-1.5 text-xs font-medium text-gray-700 hover:bg-gray-50 h-8"
|
|
33559
|
+
}, /* @__PURE__ */ React.createElement(Plus, {
|
|
33560
|
+
className: "h-3.5 w-3.5"
|
|
33561
|
+
}), "New event combo") : null) : null), /* @__PURE__ */ React.createElement("div", {
|
|
33562
|
+
className: "[&>div]:shadow-none [&>div]:rounded-none"
|
|
33563
|
+
}, rows.length === 0 ? /* @__PURE__ */ React.createElement("div", {
|
|
33564
|
+
className: "px-4 py-8 text-center text-sm text-gray-500"
|
|
33565
|
+
}, "No combos attached to this event yet.") : /* @__PURE__ */ React.createElement(AdminCRUD, {
|
|
33566
|
+
key: `event-combos-${eventId}-${attachedComboIds.join(",")}-${listRefreshKey}`,
|
|
33567
|
+
title: "Event Combos",
|
|
33568
|
+
apiEndpoint: "/api/combos",
|
|
33569
|
+
columns: comboColumns,
|
|
33570
|
+
filterColumns: comboFilterColumns,
|
|
33571
|
+
addEditPageUrl: "/admin/combos",
|
|
33572
|
+
defaultSortField: STORE_CRUD_CONFIGS.combos.defaultSortField,
|
|
33573
|
+
defaultSortOrder: STORE_CRUD_CONFIGS.combos.defaultSortOrder,
|
|
33574
|
+
filters: comboFilters,
|
|
33575
|
+
extraListParams: {
|
|
33576
|
+
eventId: String(eventId)
|
|
33577
|
+
},
|
|
33578
|
+
embedded: true,
|
|
33579
|
+
disableRowClick: readOnly,
|
|
33580
|
+
emptyState: {
|
|
33581
|
+
title: "No combos attached",
|
|
33582
|
+
description: "Attach or create a combo for this event.",
|
|
33583
|
+
action: !readOnly && comboCreateHref ? /* @__PURE__ */ React.createElement(Link2, {
|
|
33584
|
+
href: comboCreateHref,
|
|
33585
|
+
className: "inline-flex items-center rounded-md bg-gray-900 px-3 py-1.5 text-sm font-medium text-white hover:bg-gray-800"
|
|
33586
|
+
}, "Create combo") : void 0
|
|
33587
|
+
},
|
|
33588
|
+
customRowActions: readOnly ? void 0 : (item) => {
|
|
33589
|
+
const comboId = Number(item.id);
|
|
33590
|
+
const busy = detachingId === comboId;
|
|
33591
|
+
return /* @__PURE__ */ React.createElement(Button, {
|
|
33592
|
+
type: "button",
|
|
33593
|
+
size: "sm",
|
|
33594
|
+
variant: "outline",
|
|
33595
|
+
disabled: !Number.isFinite(comboId) || busy,
|
|
33596
|
+
className: "h-7 text-xs border-red-200 text-red-600 hover:text-red-700",
|
|
33597
|
+
onClick: /* @__PURE__ */ __name(() => void detachFromEvent(comboId), "onClick")
|
|
33598
|
+
}, /* @__PURE__ */ React.createElement(Unlink, {
|
|
33599
|
+
className: "h-3.5 w-3.5 mr-1"
|
|
33600
|
+
}), busy ? "Removing\u2026" : "Detach");
|
|
33601
|
+
}
|
|
33602
|
+
}))), attachModalOpen ? /* @__PURE__ */ React.createElement(AttachComboModal, {
|
|
33603
|
+
open: attachModalOpen,
|
|
33604
|
+
onOpenChange: setAttachModalOpen,
|
|
33605
|
+
excludeComboIds: attachedComboIds,
|
|
33606
|
+
onAttach: attachToEvent
|
|
33607
|
+
}) : null);
|
|
33608
|
+
}
|
|
33609
|
+
var init_EventCombosSection = __esm({
|
|
33610
|
+
"src/admin/pages/EventCombosSection.tsx"() {
|
|
33611
|
+
"use client";
|
|
33612
|
+
init_button();
|
|
33613
|
+
init_CRUD();
|
|
33614
|
+
init_AttachComboModal();
|
|
33615
|
+
init_store_crud_configs();
|
|
33616
|
+
__name(EventCombosSection, "EventCombosSection");
|
|
33617
|
+
}
|
|
33618
|
+
});
|
|
32849
33619
|
|
|
32850
33620
|
// src/lib/social-media-links.ts
|
|
32851
33621
|
function isValidHttpUrl(value) {
|
|
@@ -34339,10 +35109,13 @@ function EventEditPage({ eventId }) {
|
|
|
34339
35109
|
onClick: goToNextTab,
|
|
34340
35110
|
className: "rounded-md bg-gray-900 px-4 py-2 text-sm font-medium text-white hover:bg-gray-800"
|
|
34341
35111
|
}, "Next") : /* @__PURE__ */ React.createElement("div", null)), showEventProducts ? /* @__PURE__ */ React.createElement("div", {
|
|
34342
|
-
className: "border-t border-gray-200 px-4 py-4 sm:px-6"
|
|
35112
|
+
className: "border-t border-gray-200 px-4 py-4 sm:px-6 space-y-6"
|
|
34343
35113
|
}, /* @__PURE__ */ React.createElement(EventProductsSection, {
|
|
34344
35114
|
eventId: eventRecordId,
|
|
34345
35115
|
returnUrl: eventEditUrl
|
|
35116
|
+
}), /* @__PURE__ */ React.createElement(EventCombosSection, {
|
|
35117
|
+
eventId: eventRecordId,
|
|
35118
|
+
returnUrl: eventEditUrl
|
|
34346
35119
|
})) : null);
|
|
34347
35120
|
}
|
|
34348
35121
|
var ADDITIONAL_VENUE_MAX_CHARS, DEFAULT_EVENT_TIMEZONE, DEFAULT_EVENT_CURRENCY, EVENT_SOCIAL_KEYS, isCreate4, sectionCls4, labelCls6, inputCls6, ENTITY_TYPE_OPTIONS;
|
|
@@ -34357,6 +35130,7 @@ var init_EventEditPage = __esm({
|
|
|
34357
35130
|
init_media_url();
|
|
34358
35131
|
init_JoditRichText();
|
|
34359
35132
|
init_EventProductsSection();
|
|
35133
|
+
init_EventCombosSection();
|
|
34360
35134
|
init_admin_config_context();
|
|
34361
35135
|
init_dialog();
|
|
34362
35136
|
init_button();
|
|
@@ -34394,7 +35168,13 @@ function formatDateTimeLocal(value) {
|
|
|
34394
35168
|
if (value == null) return "";
|
|
34395
35169
|
const date = new Date(String(value));
|
|
34396
35170
|
if (isNaN(date.getTime())) return "";
|
|
34397
|
-
|
|
35171
|
+
const pad = /* @__PURE__ */ __name((n) => String(n).padStart(2, "0"), "pad");
|
|
35172
|
+
const y = date.getFullYear();
|
|
35173
|
+
const m = pad(date.getMonth() + 1);
|
|
35174
|
+
const d = pad(date.getDate());
|
|
35175
|
+
const hh = pad(date.getHours());
|
|
35176
|
+
const mm = pad(date.getMinutes());
|
|
35177
|
+
return `${y}-${m}-${d}T${hh}:${mm}`;
|
|
34398
35178
|
}
|
|
34399
35179
|
async function fetchEventDefaultCurrency(eventId) {
|
|
34400
35180
|
try {
|
|
@@ -34441,13 +35221,14 @@ function ComboEditPage({ comboId }) {
|
|
|
34441
35221
|
const create = isCreate5(comboId);
|
|
34442
35222
|
const duplicateFrom = searchParams.get("duplicateFrom")?.trim();
|
|
34443
35223
|
const duplicateSourceId = create && duplicateFrom && /^\d+$/.test(duplicateFrom) ? duplicateFrom : null;
|
|
35224
|
+
const initialEventId = create ? searchParams.get("eventId")?.trim() || "" : "";
|
|
34444
35225
|
const [loading, setLoading] = useState(!create || !!duplicateSourceId);
|
|
34445
35226
|
const [saving, setSaving] = useState(false);
|
|
34446
35227
|
const [errors, setErrors] = useState([]);
|
|
34447
35228
|
const [name, setName] = useState("");
|
|
34448
35229
|
const [slug, setSlug] = useState("");
|
|
34449
35230
|
const [desc, setDesc] = useState("");
|
|
34450
|
-
const [eventId, setEventId] = useState(
|
|
35231
|
+
const [eventId, setEventId] = useState(initialEventId);
|
|
34451
35232
|
const [priceStr, setPriceStr] = useState("");
|
|
34452
35233
|
const [defaultCurrency, setDefaultCurrency] = useState("INR");
|
|
34453
35234
|
const [minSelectableItems, setMinSelectableItems] = useState(1);
|
|
@@ -34684,15 +35465,9 @@ function ComboEditPage({ comboId }) {
|
|
|
34684
35465
|
]);
|
|
34685
35466
|
return;
|
|
34686
35467
|
}
|
|
34687
|
-
if (
|
|
35468
|
+
if (startsAt && endsAt && new Date(endsAt).getTime() < new Date(startsAt).getTime()) {
|
|
34688
35469
|
setErrors([
|
|
34689
|
-
"
|
|
34690
|
-
]);
|
|
34691
|
-
return;
|
|
34692
|
-
}
|
|
34693
|
-
if (!endsAt) {
|
|
34694
|
-
setErrors([
|
|
34695
|
-
"Ends at is required"
|
|
35470
|
+
"Ends at cannot be earlier than Starts at"
|
|
34696
35471
|
]);
|
|
34697
35472
|
return;
|
|
34698
35473
|
}
|
|
@@ -34760,8 +35535,8 @@ function ComboEditPage({ comboId }) {
|
|
|
34760
35535
|
minSelectableItems,
|
|
34761
35536
|
maxSelectableItems,
|
|
34762
35537
|
status,
|
|
34763
|
-
startsAt: startsAt
|
|
34764
|
-
endsAt: endsAt
|
|
35538
|
+
startsAt: startsAt ? new Date(startsAt).toISOString() : null,
|
|
35539
|
+
endsAt: endsAt ? new Date(endsAt).toISOString() : null,
|
|
34765
35540
|
comboItems: [
|
|
34766
35541
|
...fixedItems.map((i) => ({
|
|
34767
35542
|
productId: Number(i.productId),
|
|
@@ -34985,21 +35760,23 @@ function ComboEditPage({ comboId }) {
|
|
|
34985
35760
|
className: "grid grid-cols-2 gap-4"
|
|
34986
35761
|
}, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("label", {
|
|
34987
35762
|
className: "block text-xs font-medium text-gray-600 mb-1"
|
|
34988
|
-
}, "Starts at
|
|
35763
|
+
}, "Starts at (optional)"), /* @__PURE__ */ React.createElement("input", {
|
|
34989
35764
|
type: "datetime-local",
|
|
34990
35765
|
value: startsAt,
|
|
34991
35766
|
onChange: /* @__PURE__ */ __name((e) => setStartsAt(e.target.value), "onChange"),
|
|
34992
|
-
className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm"
|
|
34993
|
-
|
|
34994
|
-
|
|
35767
|
+
className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm"
|
|
35768
|
+
}), /* @__PURE__ */ React.createElement("p", {
|
|
35769
|
+
className: "text-xs text-gray-400 mt-1"
|
|
35770
|
+
}, "Leave empty to be available immediately.")), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("label", {
|
|
34995
35771
|
className: "block text-xs font-medium text-gray-600 mb-1"
|
|
34996
|
-
}, "Ends at
|
|
35772
|
+
}, "Ends at (optional)"), /* @__PURE__ */ React.createElement("input", {
|
|
34997
35773
|
type: "datetime-local",
|
|
34998
35774
|
value: endsAt,
|
|
34999
35775
|
onChange: /* @__PURE__ */ __name((e) => setEndsAt(e.target.value), "onChange"),
|
|
35000
|
-
className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm"
|
|
35001
|
-
|
|
35002
|
-
|
|
35776
|
+
className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm"
|
|
35777
|
+
}), /* @__PURE__ */ React.createElement("p", {
|
|
35778
|
+
className: "text-xs text-gray-400 mt-1"
|
|
35779
|
+
}, "Leave empty if no expiration date.")))))),
|
|
35003
35780
|
sidebar: /* @__PURE__ */ React.createElement(React.Fragment, null)
|
|
35004
35781
|
}));
|
|
35005
35782
|
}
|
|
@@ -35115,6 +35892,130 @@ function VendorEditPage({ vendorId }) {
|
|
|
35115
35892
|
const [inviteDialog, setInviteDialog] = useState(null);
|
|
35116
35893
|
const [sendingInviteEmail, setSendingInviteEmail] = useState(false);
|
|
35117
35894
|
const [linkCopied, setLinkCopied] = useState(false);
|
|
35895
|
+
const VENDOR_CREATE_DRAFT_KEY = "cms_vendor_create_draft";
|
|
35896
|
+
useEffect(() => {
|
|
35897
|
+
if (!create || typeof window === "undefined") return;
|
|
35898
|
+
try {
|
|
35899
|
+
const saved = sessionStorage.getItem(VENDOR_CREATE_DRAFT_KEY);
|
|
35900
|
+
if (saved) {
|
|
35901
|
+
const draft = JSON.parse(saved);
|
|
35902
|
+
if (draft && typeof draft === "object") {
|
|
35903
|
+
if (draft.name) setName(draft.name);
|
|
35904
|
+
if (draft.legalName) setLegalName(draft.legalName);
|
|
35905
|
+
if (draft.slug) setSlug(draft.slug);
|
|
35906
|
+
if (draft.businessType) setBusinessType(draft.businessType);
|
|
35907
|
+
if (draft.description) setDescription(draft.description);
|
|
35908
|
+
if (draft.website) setWebsite(draft.website);
|
|
35909
|
+
if (draft.logo) setLogo(draft.logo);
|
|
35910
|
+
if (draft.email) setEmail(draft.email);
|
|
35911
|
+
if (draft.storePhoneCode) setStorePhoneCode(draft.storePhoneCode);
|
|
35912
|
+
if (draft.storePhoneNum) setStorePhoneNum(draft.storePhoneNum);
|
|
35913
|
+
if (draft.addressLine1) setAddressLine1(draft.addressLine1);
|
|
35914
|
+
if (draft.addressLine2) setAddressLine2(draft.addressLine2);
|
|
35915
|
+
if (draft.city) setCity(draft.city);
|
|
35916
|
+
if (draft.state) setState(draft.state);
|
|
35917
|
+
if (draft.country) setCountry(draft.country);
|
|
35918
|
+
if (draft.postalCode) setPostalCode(draft.postalCode);
|
|
35919
|
+
if (draft.gstin) setGstin(draft.gstin);
|
|
35920
|
+
if (typeof draft.active === "boolean") setActive(draft.active);
|
|
35921
|
+
if (draft.registrationStatus) setRegistrationStatus(draft.registrationStatus);
|
|
35922
|
+
if (draft.ownerName) setOwnerName(draft.ownerName);
|
|
35923
|
+
if (draft.ownerEmail) setOwnerEmail(draft.ownerEmail);
|
|
35924
|
+
if (draft.ownerPhoneCode) setOwnerPhoneCode(draft.ownerPhoneCode);
|
|
35925
|
+
if (draft.ownerPhoneNum) setOwnerPhoneNum(draft.ownerPhoneNum);
|
|
35926
|
+
if (draft.ownerDesignation) setOwnerDesignation(draft.ownerDesignation);
|
|
35927
|
+
if (draft.ownerAadhaarNo) setOwnerAadhaarNo(draft.ownerAadhaarNo);
|
|
35928
|
+
if (draft.ownerPanNo) setOwnerPanNo(draft.ownerPanNo);
|
|
35929
|
+
if (draft.ownerAddressLine1) setOwnerAddressLine1(draft.ownerAddressLine1);
|
|
35930
|
+
if (draft.ownerAddressLine2) setOwnerAddressLine2(draft.ownerAddressLine2);
|
|
35931
|
+
if (draft.ownerCity) setOwnerCity(draft.ownerCity);
|
|
35932
|
+
if (draft.ownerState) setOwnerState(draft.ownerState);
|
|
35933
|
+
if (draft.ownerPostalCode) setOwnerPostalCode(draft.ownerPostalCode);
|
|
35934
|
+
if (typeof draft.termsAccepted === "boolean") setTermsAccepted(draft.termsAccepted);
|
|
35935
|
+
}
|
|
35936
|
+
}
|
|
35937
|
+
} catch {
|
|
35938
|
+
}
|
|
35939
|
+
}, [
|
|
35940
|
+
create
|
|
35941
|
+
]);
|
|
35942
|
+
useEffect(() => {
|
|
35943
|
+
if (!create || typeof window === "undefined") return;
|
|
35944
|
+
const hasAnyData = Boolean(name || legalName || gstin || ownerName || ownerEmail || ownerPhoneNum || ownerAadhaarNo || ownerPanNo || ownerAddressLine1);
|
|
35945
|
+
if (!hasAnyData) return;
|
|
35946
|
+
try {
|
|
35947
|
+
const draft = {
|
|
35948
|
+
name,
|
|
35949
|
+
legalName,
|
|
35950
|
+
slug,
|
|
35951
|
+
businessType,
|
|
35952
|
+
description,
|
|
35953
|
+
website,
|
|
35954
|
+
logo,
|
|
35955
|
+
email,
|
|
35956
|
+
storePhoneCode,
|
|
35957
|
+
storePhoneNum,
|
|
35958
|
+
addressLine1,
|
|
35959
|
+
addressLine2,
|
|
35960
|
+
city,
|
|
35961
|
+
state,
|
|
35962
|
+
country,
|
|
35963
|
+
postalCode,
|
|
35964
|
+
gstin,
|
|
35965
|
+
active,
|
|
35966
|
+
registrationStatus,
|
|
35967
|
+
ownerName,
|
|
35968
|
+
ownerEmail,
|
|
35969
|
+
ownerPhoneCode,
|
|
35970
|
+
ownerPhoneNum,
|
|
35971
|
+
ownerDesignation,
|
|
35972
|
+
ownerAadhaarNo,
|
|
35973
|
+
ownerPanNo,
|
|
35974
|
+
ownerAddressLine1,
|
|
35975
|
+
ownerAddressLine2,
|
|
35976
|
+
ownerCity,
|
|
35977
|
+
ownerState,
|
|
35978
|
+
ownerPostalCode,
|
|
35979
|
+
termsAccepted
|
|
35980
|
+
};
|
|
35981
|
+
sessionStorage.setItem(VENDOR_CREATE_DRAFT_KEY, JSON.stringify(draft));
|
|
35982
|
+
} catch {
|
|
35983
|
+
}
|
|
35984
|
+
}, [
|
|
35985
|
+
create,
|
|
35986
|
+
name,
|
|
35987
|
+
legalName,
|
|
35988
|
+
slug,
|
|
35989
|
+
businessType,
|
|
35990
|
+
description,
|
|
35991
|
+
website,
|
|
35992
|
+
logo,
|
|
35993
|
+
email,
|
|
35994
|
+
storePhoneCode,
|
|
35995
|
+
storePhoneNum,
|
|
35996
|
+
addressLine1,
|
|
35997
|
+
addressLine2,
|
|
35998
|
+
city,
|
|
35999
|
+
state,
|
|
36000
|
+
country,
|
|
36001
|
+
postalCode,
|
|
36002
|
+
gstin,
|
|
36003
|
+
active,
|
|
36004
|
+
registrationStatus,
|
|
36005
|
+
ownerName,
|
|
36006
|
+
ownerEmail,
|
|
36007
|
+
ownerPhoneCode,
|
|
36008
|
+
ownerPhoneNum,
|
|
36009
|
+
ownerDesignation,
|
|
36010
|
+
ownerAadhaarNo,
|
|
36011
|
+
ownerPanNo,
|
|
36012
|
+
ownerAddressLine1,
|
|
36013
|
+
ownerAddressLine2,
|
|
36014
|
+
ownerCity,
|
|
36015
|
+
ownerState,
|
|
36016
|
+
ownerPostalCode,
|
|
36017
|
+
termsAccepted
|
|
36018
|
+
]);
|
|
35118
36019
|
const vendorPayload = /* @__PURE__ */ __name(() => ({
|
|
35119
36020
|
name: name.trim(),
|
|
35120
36021
|
legalName: legalName.trim() || null,
|
|
@@ -35358,12 +36259,15 @@ function VendorEditPage({ vendorId }) {
|
|
|
35358
36259
|
setSaving(false);
|
|
35359
36260
|
return;
|
|
35360
36261
|
}
|
|
36262
|
+
const abortController = new AbortController();
|
|
36263
|
+
const timeoutId = setTimeout(() => abortController.abort(), 15e3);
|
|
35361
36264
|
try {
|
|
35362
36265
|
const res = await fetch("/api/admin/vendors/onboard", {
|
|
35363
36266
|
method: "POST",
|
|
35364
36267
|
headers: {
|
|
35365
36268
|
"Content-Type": "application/json"
|
|
35366
36269
|
},
|
|
36270
|
+
signal: abortController.signal,
|
|
35367
36271
|
body: JSON.stringify({
|
|
35368
36272
|
activation: "invite",
|
|
35369
36273
|
sendOwnerEmail: false,
|
|
@@ -35384,15 +36288,20 @@ function VendorEditPage({ vendorId }) {
|
|
|
35384
36288
|
}
|
|
35385
36289
|
})
|
|
35386
36290
|
});
|
|
35387
|
-
|
|
36291
|
+
clearTimeout(timeoutId);
|
|
36292
|
+
const data = await res.json().catch(() => ({}));
|
|
35388
36293
|
if (!res.ok) {
|
|
35389
36294
|
setErrors([
|
|
35390
36295
|
data.error || "Onboarding failed"
|
|
35391
36296
|
]);
|
|
35392
36297
|
return;
|
|
35393
36298
|
}
|
|
36299
|
+
try {
|
|
36300
|
+
sessionStorage.removeItem(VENDOR_CREATE_DRAFT_KEY);
|
|
36301
|
+
} catch {
|
|
36302
|
+
}
|
|
35394
36303
|
const vendorIdNum = Number(data.vendor?.id);
|
|
35395
|
-
const inviteLink = typeof data.inviteLink === "string" && data.inviteLink
|
|
36304
|
+
const inviteLink = typeof data.inviteLink === "string" && data.inviteLink?.trim() ? data.inviteLink.trim() : "";
|
|
35396
36305
|
if (!Number.isFinite(vendorIdNum) || vendorIdNum <= 0 || !inviteLink) {
|
|
35397
36306
|
toast.success(data.message || "Vendor created");
|
|
35398
36307
|
router.push(listReturnUrl);
|
|
@@ -35404,11 +36313,18 @@ function VendorEditPage({ vendorId }) {
|
|
|
35404
36313
|
vendorId: vendorIdNum,
|
|
35405
36314
|
inviteLink
|
|
35406
36315
|
});
|
|
35407
|
-
} catch {
|
|
35408
|
-
|
|
35409
|
-
|
|
35410
|
-
|
|
36316
|
+
} catch (err) {
|
|
36317
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
36318
|
+
setErrors([
|
|
36319
|
+
"Request timed out. Your entered data is preserved. Please click submit again."
|
|
36320
|
+
]);
|
|
36321
|
+
} else {
|
|
36322
|
+
setErrors([
|
|
36323
|
+
err instanceof Error && err.message || "Request failed"
|
|
36324
|
+
]);
|
|
36325
|
+
}
|
|
35411
36326
|
} finally {
|
|
36327
|
+
clearTimeout(timeoutId);
|
|
35412
36328
|
setSaving(false);
|
|
35413
36329
|
}
|
|
35414
36330
|
}, "handleCreate");
|
|
@@ -35447,12 +36363,15 @@ function VendorEditPage({ vendorId }) {
|
|
|
35447
36363
|
setSaving(false);
|
|
35448
36364
|
return;
|
|
35449
36365
|
}
|
|
36366
|
+
const abortController = new AbortController();
|
|
36367
|
+
const timeoutId = setTimeout(() => abortController.abort(), 15e3);
|
|
35450
36368
|
try {
|
|
35451
36369
|
const res = await fetch(`/api/vendors/${vendorId}`, {
|
|
35452
36370
|
method: "PUT",
|
|
35453
36371
|
headers: {
|
|
35454
36372
|
"Content-Type": "application/json"
|
|
35455
36373
|
},
|
|
36374
|
+
signal: abortController.signal,
|
|
35456
36375
|
body: JSON.stringify({
|
|
35457
36376
|
...vendorPayload(),
|
|
35458
36377
|
slug: slug.trim(),
|
|
@@ -35468,6 +36387,7 @@ function VendorEditPage({ vendorId }) {
|
|
|
35468
36387
|
})
|
|
35469
36388
|
});
|
|
35470
36389
|
if (!res.ok) {
|
|
36390
|
+
clearTimeout(timeoutId);
|
|
35471
36391
|
const data = await res.json().catch(() => ({}));
|
|
35472
36392
|
setErrors([
|
|
35473
36393
|
data.error || "Failed to save"
|
|
@@ -35481,6 +36401,7 @@ function VendorEditPage({ vendorId }) {
|
|
|
35481
36401
|
headers: {
|
|
35482
36402
|
"Content-Type": "application/json"
|
|
35483
36403
|
},
|
|
36404
|
+
signal: abortController.signal,
|
|
35484
36405
|
body: JSON.stringify({
|
|
35485
36406
|
name: ownerName.trim(),
|
|
35486
36407
|
email: ownerEmail.trim(),
|
|
@@ -35488,6 +36409,7 @@ function VendorEditPage({ vendorId }) {
|
|
|
35488
36409
|
})
|
|
35489
36410
|
});
|
|
35490
36411
|
if (!userRes.ok) {
|
|
36412
|
+
clearTimeout(timeoutId);
|
|
35491
36413
|
const data = await userRes.json().catch(() => ({}));
|
|
35492
36414
|
setErrors([
|
|
35493
36415
|
data.error || "Vendor saved, but updating owner details failed"
|
|
@@ -35495,13 +36417,21 @@ function VendorEditPage({ vendorId }) {
|
|
|
35495
36417
|
return;
|
|
35496
36418
|
}
|
|
35497
36419
|
}
|
|
36420
|
+
clearTimeout(timeoutId);
|
|
35498
36421
|
toast.success("Vendor saved");
|
|
35499
36422
|
router.push(listReturnUrl);
|
|
35500
|
-
} catch {
|
|
35501
|
-
|
|
35502
|
-
|
|
35503
|
-
|
|
36423
|
+
} catch (err) {
|
|
36424
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
36425
|
+
setErrors([
|
|
36426
|
+
"Request timed out. Please try saving again."
|
|
36427
|
+
]);
|
|
36428
|
+
} else {
|
|
36429
|
+
setErrors([
|
|
36430
|
+
err instanceof Error && err.message || "Failed to save"
|
|
36431
|
+
]);
|
|
36432
|
+
}
|
|
35504
36433
|
} finally {
|
|
36434
|
+
clearTimeout(timeoutId);
|
|
35505
36435
|
setSaving(false);
|
|
35506
36436
|
}
|
|
35507
36437
|
}, "handleSave");
|
|
@@ -40907,6 +41837,8 @@ var init_AdminPageResolver = __esm({
|
|
|
40907
41837
|
submissions: {
|
|
40908
41838
|
title: "Submissions",
|
|
40909
41839
|
apiEndpoint: "/api/form-submissions",
|
|
41840
|
+
defaultSortField: "createdAt",
|
|
41841
|
+
defaultSortOrder: "desc",
|
|
40910
41842
|
columns: [
|
|
40911
41843
|
{
|
|
40912
41844
|
field: "form.name",
|
|
@@ -41452,6 +42384,10 @@ function EventDetailPage({ eventId }) {
|
|
|
41452
42384
|
eventId: String(event.id),
|
|
41453
42385
|
returnUrl: detailUrl,
|
|
41454
42386
|
readOnly: true
|
|
42387
|
+
}), /* @__PURE__ */ React.createElement(EventCombosSection, {
|
|
42388
|
+
eventId: String(event.id),
|
|
42389
|
+
returnUrl: detailUrl,
|
|
42390
|
+
readOnly: true
|
|
41455
42391
|
}))
|
|
41456
42392
|
}));
|
|
41457
42393
|
}
|
|
@@ -41467,6 +42403,7 @@ var init_EventDetailPage = __esm({
|
|
|
41467
42403
|
init_DetailPageLayout();
|
|
41468
42404
|
init_DetailPageHeader();
|
|
41469
42405
|
init_EventProductsSection();
|
|
42406
|
+
init_EventCombosSection();
|
|
41470
42407
|
sectionCls6 = "border border-gray-200 rounded-lg p-4 bg-gray-50/50";
|
|
41471
42408
|
labelCls7 = "text-xs font-medium text-gray-500";
|
|
41472
42409
|
valueCls = "text-sm text-gray-900 mt-0.5";
|