@infuro/cms-core 1.0.60 → 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 +579 -47
- package/dist/admin.js +580 -48
- package/dist/api.cjs +33 -33
- package/dist/api.js +1 -1
- package/dist/{chunk-BSLNXKV2.cjs → chunk-CNAHVRRU.cjs} +251 -39
- package/dist/{chunk-JAEUYYGA.js → chunk-UHT4INVW.js} +251 -39
- package/dist/index.cjs +489 -246
- package/dist/index.js +277 -34
- 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, ShieldCheck, EyeOff, Smartphone, QrCode, Car, Send, Settings2, DollarSign, Hash, Circle, ChevronLeft, Bell, Share2, HardDrive, Folder, Film } 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, 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';
|
|
@@ -861,7 +861,7 @@ var init_admin_config_context = __esm({
|
|
|
861
861
|
var CMS_VERSION;
|
|
862
862
|
var init_cms_version = __esm({
|
|
863
863
|
"src/lib/cms-version.ts"() {
|
|
864
|
-
CMS_VERSION = "1.0.
|
|
864
|
+
CMS_VERSION = "1.0.61" ;
|
|
865
865
|
}
|
|
866
866
|
});
|
|
867
867
|
function useCatalogCategories(enabled = true) {
|
|
@@ -2192,6 +2192,11 @@ function FileUpload({ onUploadSuccess }) {
|
|
|
2192
2192
|
if (!selectedFile) return;
|
|
2193
2193
|
setUploading(true);
|
|
2194
2194
|
setProgress(10);
|
|
2195
|
+
console.info("[upload] file-upload start", {
|
|
2196
|
+
name: selectedFile.name,
|
|
2197
|
+
type: selectedFile.type,
|
|
2198
|
+
size: selectedFile.size
|
|
2199
|
+
});
|
|
2195
2200
|
const formData = new FormData();
|
|
2196
2201
|
formData.append("file", selectedFile);
|
|
2197
2202
|
try {
|
|
@@ -2200,20 +2205,47 @@ function FileUpload({ onUploadSuccess }) {
|
|
|
2200
2205
|
body: formData
|
|
2201
2206
|
});
|
|
2202
2207
|
setProgress(60);
|
|
2203
|
-
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
|
+
});
|
|
2204
2222
|
if (response.ok) {
|
|
2205
|
-
|
|
2223
|
+
const url = data.url ?? data.filePath;
|
|
2224
|
+
setFileUrl(url);
|
|
2206
2225
|
setProgress(100);
|
|
2207
|
-
|
|
2226
|
+
console.info("[upload] file-upload ok", {
|
|
2227
|
+
url,
|
|
2228
|
+
name: selectedFile.name
|
|
2229
|
+
});
|
|
2230
|
+
onUploadSuccess(url);
|
|
2208
2231
|
} else {
|
|
2209
2232
|
console.error("[upload] API error", {
|
|
2210
2233
|
status: response.status,
|
|
2211
2234
|
error: data.error,
|
|
2212
|
-
details: data.details
|
|
2235
|
+
details: data.details,
|
|
2236
|
+
name: selectedFile.name,
|
|
2237
|
+
type: selectedFile.type,
|
|
2238
|
+
size: selectedFile.size
|
|
2213
2239
|
});
|
|
2214
2240
|
}
|
|
2215
2241
|
} catch (error) {
|
|
2216
|
-
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
|
+
});
|
|
2217
2249
|
}
|
|
2218
2250
|
setUploading(false);
|
|
2219
2251
|
}, "handleUpload");
|
|
@@ -2345,28 +2377,64 @@ function ImageOrUrlField({ label, value, onChange, placeholder = "https://\u2026
|
|
|
2345
2377
|
return;
|
|
2346
2378
|
}
|
|
2347
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
|
+
});
|
|
2348
2387
|
try {
|
|
2349
2388
|
const formData = new FormData();
|
|
2350
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
|
+
});
|
|
2351
2395
|
const response = await fetch("/api/upload", {
|
|
2352
2396
|
method: "POST",
|
|
2353
2397
|
body: formData
|
|
2354
2398
|
});
|
|
2355
|
-
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
|
+
});
|
|
2356
2413
|
if (!response.ok) {
|
|
2357
2414
|
console.error("[upload] API error", {
|
|
2358
2415
|
status: response.status,
|
|
2359
2416
|
error: data.error,
|
|
2360
|
-
details: data.details
|
|
2417
|
+
details: data.details,
|
|
2418
|
+
fileName: file.name,
|
|
2419
|
+
fileType: file.type,
|
|
2420
|
+
fileSize: file.size
|
|
2361
2421
|
});
|
|
2362
2422
|
throw new Error(data.details || data.error || "Upload failed");
|
|
2363
2423
|
}
|
|
2364
2424
|
console.info("[upload] API ok", {
|
|
2365
|
-
filePath: data.filePath
|
|
2425
|
+
filePath: data.filePath,
|
|
2426
|
+
name: file.name,
|
|
2427
|
+
type: file.type
|
|
2366
2428
|
});
|
|
2367
2429
|
onChange(data.filePath ?? "");
|
|
2368
2430
|
} catch (err) {
|
|
2369
|
-
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
|
+
});
|
|
2370
2438
|
setError(err instanceof Error ? err.message : "Upload failed");
|
|
2371
2439
|
} finally {
|
|
2372
2440
|
setIsUploading(false);
|
|
@@ -5065,6 +5133,9 @@ function AdminCRUD({ title, apiEndpoint, columns, addEditPageUrl, customViewPage
|
|
|
5065
5133
|
});
|
|
5066
5134
|
if (cancelled) return;
|
|
5067
5135
|
if (!res.ok) {
|
|
5136
|
+
if (res.status === 403) {
|
|
5137
|
+
throw new Error("You don't have access to this section");
|
|
5138
|
+
}
|
|
5068
5139
|
throw new Error(`HTTP error! status: ${res.status}`);
|
|
5069
5140
|
}
|
|
5070
5141
|
const result = await res.json();
|
|
@@ -5481,15 +5552,26 @@ function AdminCRUD({ title, apiEndpoint, columns, addEditPageUrl, customViewPage
|
|
|
5481
5552
|
}, "Loading...")));
|
|
5482
5553
|
}
|
|
5483
5554
|
if (error) {
|
|
5555
|
+
const isForbidden = error.toLowerCase().includes("don't have access") || error.toLowerCase().includes("forbidden") || error.includes("403");
|
|
5484
5556
|
return /* @__PURE__ */ React.createElement("div", {
|
|
5485
5557
|
className: embedded ? "p-4" : "rounded-lg bg-white p-6 shadow-md"
|
|
5486
5558
|
}, /* @__PURE__ */ React.createElement("div", {
|
|
5487
|
-
className: "text-center py-
|
|
5488
|
-
}, /* @__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", {
|
|
5489
5571
|
className: "text-red-600 mb-4"
|
|
5490
5572
|
}, "Error loading data: ", error), /* @__PURE__ */ React.createElement(Button, {
|
|
5491
5573
|
onClick: /* @__PURE__ */ __name(() => window.location.reload(), "onClick")
|
|
5492
|
-
}, "Retry")));
|
|
5574
|
+
}, "Retry"))));
|
|
5493
5575
|
}
|
|
5494
5576
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", {
|
|
5495
5577
|
className: shellCls
|
|
@@ -6853,26 +6935,63 @@ function ImageUpload({ value, onChange, onRemove, label, required = false, class
|
|
|
6853
6935
|
return;
|
|
6854
6936
|
}
|
|
6855
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
|
+
});
|
|
6856
6944
|
try {
|
|
6857
6945
|
const formData = new FormData();
|
|
6858
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
|
+
});
|
|
6859
6952
|
const response = await fetch("/api/upload", {
|
|
6860
6953
|
method: "POST",
|
|
6861
6954
|
body: formData
|
|
6862
6955
|
});
|
|
6863
|
-
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
|
+
});
|
|
6864
6970
|
if (!response.ok) {
|
|
6865
6971
|
console.error("[upload] API error", {
|
|
6866
6972
|
status: response.status,
|
|
6867
6973
|
error: data.error,
|
|
6868
|
-
details: data.details
|
|
6974
|
+
details: data.details,
|
|
6975
|
+
fileName: file.name,
|
|
6976
|
+
fileType: file.type,
|
|
6977
|
+
fileSize: file.size
|
|
6869
6978
|
});
|
|
6870
6979
|
throw new Error(data.details || data.error || "Upload failed");
|
|
6871
6980
|
}
|
|
6981
|
+
console.info("[upload] client image-upload ok", {
|
|
6982
|
+
filePath: data.filePath,
|
|
6983
|
+
name: file.name
|
|
6984
|
+
});
|
|
6872
6985
|
onChange(data.filePath);
|
|
6873
6986
|
setUploadProgress(100);
|
|
6874
6987
|
} catch (error2) {
|
|
6875
|
-
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
|
+
});
|
|
6876
6995
|
setError(error2 instanceof Error ? error2.message : "Failed to upload image");
|
|
6877
6996
|
} finally {
|
|
6878
6997
|
setIsUploading(false);
|
|
@@ -33251,6 +33370,252 @@ var init_EventProductsSection = __esm({
|
|
|
33251
33370
|
__name(EventProductsSection, "EventProductsSection");
|
|
33252
33371
|
}
|
|
33253
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
|
+
});
|
|
33254
33619
|
|
|
33255
33620
|
// src/lib/social-media-links.ts
|
|
33256
33621
|
function isValidHttpUrl(value) {
|
|
@@ -34744,10 +35109,13 @@ function EventEditPage({ eventId }) {
|
|
|
34744
35109
|
onClick: goToNextTab,
|
|
34745
35110
|
className: "rounded-md bg-gray-900 px-4 py-2 text-sm font-medium text-white hover:bg-gray-800"
|
|
34746
35111
|
}, "Next") : /* @__PURE__ */ React.createElement("div", null)), showEventProducts ? /* @__PURE__ */ React.createElement("div", {
|
|
34747
|
-
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"
|
|
34748
35113
|
}, /* @__PURE__ */ React.createElement(EventProductsSection, {
|
|
34749
35114
|
eventId: eventRecordId,
|
|
34750
35115
|
returnUrl: eventEditUrl
|
|
35116
|
+
}), /* @__PURE__ */ React.createElement(EventCombosSection, {
|
|
35117
|
+
eventId: eventRecordId,
|
|
35118
|
+
returnUrl: eventEditUrl
|
|
34751
35119
|
})) : null);
|
|
34752
35120
|
}
|
|
34753
35121
|
var ADDITIONAL_VENUE_MAX_CHARS, DEFAULT_EVENT_TIMEZONE, DEFAULT_EVENT_CURRENCY, EVENT_SOCIAL_KEYS, isCreate4, sectionCls4, labelCls6, inputCls6, ENTITY_TYPE_OPTIONS;
|
|
@@ -34762,6 +35130,7 @@ var init_EventEditPage = __esm({
|
|
|
34762
35130
|
init_media_url();
|
|
34763
35131
|
init_JoditRichText();
|
|
34764
35132
|
init_EventProductsSection();
|
|
35133
|
+
init_EventCombosSection();
|
|
34765
35134
|
init_admin_config_context();
|
|
34766
35135
|
init_dialog();
|
|
34767
35136
|
init_button();
|
|
@@ -34799,7 +35168,13 @@ function formatDateTimeLocal(value) {
|
|
|
34799
35168
|
if (value == null) return "";
|
|
34800
35169
|
const date = new Date(String(value));
|
|
34801
35170
|
if (isNaN(date.getTime())) return "";
|
|
34802
|
-
|
|
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}`;
|
|
34803
35178
|
}
|
|
34804
35179
|
async function fetchEventDefaultCurrency(eventId) {
|
|
34805
35180
|
try {
|
|
@@ -34846,13 +35221,14 @@ function ComboEditPage({ comboId }) {
|
|
|
34846
35221
|
const create = isCreate5(comboId);
|
|
34847
35222
|
const duplicateFrom = searchParams.get("duplicateFrom")?.trim();
|
|
34848
35223
|
const duplicateSourceId = create && duplicateFrom && /^\d+$/.test(duplicateFrom) ? duplicateFrom : null;
|
|
35224
|
+
const initialEventId = create ? searchParams.get("eventId")?.trim() || "" : "";
|
|
34849
35225
|
const [loading, setLoading] = useState(!create || !!duplicateSourceId);
|
|
34850
35226
|
const [saving, setSaving] = useState(false);
|
|
34851
35227
|
const [errors, setErrors] = useState([]);
|
|
34852
35228
|
const [name, setName] = useState("");
|
|
34853
35229
|
const [slug, setSlug] = useState("");
|
|
34854
35230
|
const [desc, setDesc] = useState("");
|
|
34855
|
-
const [eventId, setEventId] = useState(
|
|
35231
|
+
const [eventId, setEventId] = useState(initialEventId);
|
|
34856
35232
|
const [priceStr, setPriceStr] = useState("");
|
|
34857
35233
|
const [defaultCurrency, setDefaultCurrency] = useState("INR");
|
|
34858
35234
|
const [minSelectableItems, setMinSelectableItems] = useState(1);
|
|
@@ -35089,15 +35465,9 @@ function ComboEditPage({ comboId }) {
|
|
|
35089
35465
|
]);
|
|
35090
35466
|
return;
|
|
35091
35467
|
}
|
|
35092
|
-
if (
|
|
35468
|
+
if (startsAt && endsAt && new Date(endsAt).getTime() < new Date(startsAt).getTime()) {
|
|
35093
35469
|
setErrors([
|
|
35094
|
-
"
|
|
35095
|
-
]);
|
|
35096
|
-
return;
|
|
35097
|
-
}
|
|
35098
|
-
if (!endsAt) {
|
|
35099
|
-
setErrors([
|
|
35100
|
-
"Ends at is required"
|
|
35470
|
+
"Ends at cannot be earlier than Starts at"
|
|
35101
35471
|
]);
|
|
35102
35472
|
return;
|
|
35103
35473
|
}
|
|
@@ -35165,8 +35535,8 @@ function ComboEditPage({ comboId }) {
|
|
|
35165
35535
|
minSelectableItems,
|
|
35166
35536
|
maxSelectableItems,
|
|
35167
35537
|
status,
|
|
35168
|
-
startsAt: startsAt
|
|
35169
|
-
endsAt: endsAt
|
|
35538
|
+
startsAt: startsAt ? new Date(startsAt).toISOString() : null,
|
|
35539
|
+
endsAt: endsAt ? new Date(endsAt).toISOString() : null,
|
|
35170
35540
|
comboItems: [
|
|
35171
35541
|
...fixedItems.map((i) => ({
|
|
35172
35542
|
productId: Number(i.productId),
|
|
@@ -35390,21 +35760,23 @@ function ComboEditPage({ comboId }) {
|
|
|
35390
35760
|
className: "grid grid-cols-2 gap-4"
|
|
35391
35761
|
}, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("label", {
|
|
35392
35762
|
className: "block text-xs font-medium text-gray-600 mb-1"
|
|
35393
|
-
}, "Starts at
|
|
35763
|
+
}, "Starts at (optional)"), /* @__PURE__ */ React.createElement("input", {
|
|
35394
35764
|
type: "datetime-local",
|
|
35395
35765
|
value: startsAt,
|
|
35396
35766
|
onChange: /* @__PURE__ */ __name((e) => setStartsAt(e.target.value), "onChange"),
|
|
35397
|
-
className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm"
|
|
35398
|
-
|
|
35399
|
-
|
|
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", {
|
|
35400
35771
|
className: "block text-xs font-medium text-gray-600 mb-1"
|
|
35401
|
-
}, "Ends at
|
|
35772
|
+
}, "Ends at (optional)"), /* @__PURE__ */ React.createElement("input", {
|
|
35402
35773
|
type: "datetime-local",
|
|
35403
35774
|
value: endsAt,
|
|
35404
35775
|
onChange: /* @__PURE__ */ __name((e) => setEndsAt(e.target.value), "onChange"),
|
|
35405
|
-
className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm"
|
|
35406
|
-
|
|
35407
|
-
|
|
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.")))))),
|
|
35408
35780
|
sidebar: /* @__PURE__ */ React.createElement(React.Fragment, null)
|
|
35409
35781
|
}));
|
|
35410
35782
|
}
|
|
@@ -35520,6 +35892,130 @@ function VendorEditPage({ vendorId }) {
|
|
|
35520
35892
|
const [inviteDialog, setInviteDialog] = useState(null);
|
|
35521
35893
|
const [sendingInviteEmail, setSendingInviteEmail] = useState(false);
|
|
35522
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
|
+
]);
|
|
35523
36019
|
const vendorPayload = /* @__PURE__ */ __name(() => ({
|
|
35524
36020
|
name: name.trim(),
|
|
35525
36021
|
legalName: legalName.trim() || null,
|
|
@@ -35763,12 +36259,15 @@ function VendorEditPage({ vendorId }) {
|
|
|
35763
36259
|
setSaving(false);
|
|
35764
36260
|
return;
|
|
35765
36261
|
}
|
|
36262
|
+
const abortController = new AbortController();
|
|
36263
|
+
const timeoutId = setTimeout(() => abortController.abort(), 15e3);
|
|
35766
36264
|
try {
|
|
35767
36265
|
const res = await fetch("/api/admin/vendors/onboard", {
|
|
35768
36266
|
method: "POST",
|
|
35769
36267
|
headers: {
|
|
35770
36268
|
"Content-Type": "application/json"
|
|
35771
36269
|
},
|
|
36270
|
+
signal: abortController.signal,
|
|
35772
36271
|
body: JSON.stringify({
|
|
35773
36272
|
activation: "invite",
|
|
35774
36273
|
sendOwnerEmail: false,
|
|
@@ -35789,15 +36288,20 @@ function VendorEditPage({ vendorId }) {
|
|
|
35789
36288
|
}
|
|
35790
36289
|
})
|
|
35791
36290
|
});
|
|
35792
|
-
|
|
36291
|
+
clearTimeout(timeoutId);
|
|
36292
|
+
const data = await res.json().catch(() => ({}));
|
|
35793
36293
|
if (!res.ok) {
|
|
35794
36294
|
setErrors([
|
|
35795
36295
|
data.error || "Onboarding failed"
|
|
35796
36296
|
]);
|
|
35797
36297
|
return;
|
|
35798
36298
|
}
|
|
36299
|
+
try {
|
|
36300
|
+
sessionStorage.removeItem(VENDOR_CREATE_DRAFT_KEY);
|
|
36301
|
+
} catch {
|
|
36302
|
+
}
|
|
35799
36303
|
const vendorIdNum = Number(data.vendor?.id);
|
|
35800
|
-
const inviteLink = typeof data.inviteLink === "string" && data.inviteLink
|
|
36304
|
+
const inviteLink = typeof data.inviteLink === "string" && data.inviteLink?.trim() ? data.inviteLink.trim() : "";
|
|
35801
36305
|
if (!Number.isFinite(vendorIdNum) || vendorIdNum <= 0 || !inviteLink) {
|
|
35802
36306
|
toast.success(data.message || "Vendor created");
|
|
35803
36307
|
router.push(listReturnUrl);
|
|
@@ -35809,11 +36313,18 @@ function VendorEditPage({ vendorId }) {
|
|
|
35809
36313
|
vendorId: vendorIdNum,
|
|
35810
36314
|
inviteLink
|
|
35811
36315
|
});
|
|
35812
|
-
} catch {
|
|
35813
|
-
|
|
35814
|
-
|
|
35815
|
-
|
|
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
|
+
}
|
|
35816
36326
|
} finally {
|
|
36327
|
+
clearTimeout(timeoutId);
|
|
35817
36328
|
setSaving(false);
|
|
35818
36329
|
}
|
|
35819
36330
|
}, "handleCreate");
|
|
@@ -35852,12 +36363,15 @@ function VendorEditPage({ vendorId }) {
|
|
|
35852
36363
|
setSaving(false);
|
|
35853
36364
|
return;
|
|
35854
36365
|
}
|
|
36366
|
+
const abortController = new AbortController();
|
|
36367
|
+
const timeoutId = setTimeout(() => abortController.abort(), 15e3);
|
|
35855
36368
|
try {
|
|
35856
36369
|
const res = await fetch(`/api/vendors/${vendorId}`, {
|
|
35857
36370
|
method: "PUT",
|
|
35858
36371
|
headers: {
|
|
35859
36372
|
"Content-Type": "application/json"
|
|
35860
36373
|
},
|
|
36374
|
+
signal: abortController.signal,
|
|
35861
36375
|
body: JSON.stringify({
|
|
35862
36376
|
...vendorPayload(),
|
|
35863
36377
|
slug: slug.trim(),
|
|
@@ -35873,6 +36387,7 @@ function VendorEditPage({ vendorId }) {
|
|
|
35873
36387
|
})
|
|
35874
36388
|
});
|
|
35875
36389
|
if (!res.ok) {
|
|
36390
|
+
clearTimeout(timeoutId);
|
|
35876
36391
|
const data = await res.json().catch(() => ({}));
|
|
35877
36392
|
setErrors([
|
|
35878
36393
|
data.error || "Failed to save"
|
|
@@ -35886,6 +36401,7 @@ function VendorEditPage({ vendorId }) {
|
|
|
35886
36401
|
headers: {
|
|
35887
36402
|
"Content-Type": "application/json"
|
|
35888
36403
|
},
|
|
36404
|
+
signal: abortController.signal,
|
|
35889
36405
|
body: JSON.stringify({
|
|
35890
36406
|
name: ownerName.trim(),
|
|
35891
36407
|
email: ownerEmail.trim(),
|
|
@@ -35893,6 +36409,7 @@ function VendorEditPage({ vendorId }) {
|
|
|
35893
36409
|
})
|
|
35894
36410
|
});
|
|
35895
36411
|
if (!userRes.ok) {
|
|
36412
|
+
clearTimeout(timeoutId);
|
|
35896
36413
|
const data = await userRes.json().catch(() => ({}));
|
|
35897
36414
|
setErrors([
|
|
35898
36415
|
data.error || "Vendor saved, but updating owner details failed"
|
|
@@ -35900,13 +36417,21 @@ function VendorEditPage({ vendorId }) {
|
|
|
35900
36417
|
return;
|
|
35901
36418
|
}
|
|
35902
36419
|
}
|
|
36420
|
+
clearTimeout(timeoutId);
|
|
35903
36421
|
toast.success("Vendor saved");
|
|
35904
36422
|
router.push(listReturnUrl);
|
|
35905
|
-
} catch {
|
|
35906
|
-
|
|
35907
|
-
|
|
35908
|
-
|
|
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
|
+
}
|
|
35909
36433
|
} finally {
|
|
36434
|
+
clearTimeout(timeoutId);
|
|
35910
36435
|
setSaving(false);
|
|
35911
36436
|
}
|
|
35912
36437
|
}, "handleSave");
|
|
@@ -41312,6 +41837,8 @@ var init_AdminPageResolver = __esm({
|
|
|
41312
41837
|
submissions: {
|
|
41313
41838
|
title: "Submissions",
|
|
41314
41839
|
apiEndpoint: "/api/form-submissions",
|
|
41840
|
+
defaultSortField: "createdAt",
|
|
41841
|
+
defaultSortOrder: "desc",
|
|
41315
41842
|
columns: [
|
|
41316
41843
|
{
|
|
41317
41844
|
field: "form.name",
|
|
@@ -41857,6 +42384,10 @@ function EventDetailPage({ eventId }) {
|
|
|
41857
42384
|
eventId: String(event.id),
|
|
41858
42385
|
returnUrl: detailUrl,
|
|
41859
42386
|
readOnly: true
|
|
42387
|
+
}), /* @__PURE__ */ React.createElement(EventCombosSection, {
|
|
42388
|
+
eventId: String(event.id),
|
|
42389
|
+
returnUrl: detailUrl,
|
|
42390
|
+
readOnly: true
|
|
41860
42391
|
}))
|
|
41861
42392
|
}));
|
|
41862
42393
|
}
|
|
@@ -41872,6 +42403,7 @@ var init_EventDetailPage = __esm({
|
|
|
41872
42403
|
init_DetailPageLayout();
|
|
41873
42404
|
init_DetailPageHeader();
|
|
41874
42405
|
init_EventProductsSection();
|
|
42406
|
+
init_EventCombosSection();
|
|
41875
42407
|
sectionCls6 = "border border-gray-200 rounded-lg p-4 bg-gray-50/50";
|
|
41876
42408
|
labelCls7 = "text-xs font-medium text-gray-500";
|
|
41877
42409
|
valueCls = "text-sm text-gray-900 mt-0.5";
|