payload-plugin-newsletter 0.12.2 → 0.13.0

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/CHANGELOG.md CHANGED
@@ -1,3 +1,24 @@
1
+ ## [0.13.0] - 2025-07-21
2
+
3
+ ### Changed
4
+ - **BREAKING**: Broadcasts collection field structure has been updated for improved layout
5
+ - Fields `subject`, `preheader`, and `content` are now nested under `contentSection` group
6
+ - Email preview is now displayed side-by-side with content fields on desktop screens
7
+ - Responsive design switches to vertical layout on screens smaller than 1024px
8
+
9
+ ### Migration Guide
10
+ If you have existing broadcast data, you'll need to migrate the field structure:
11
+ - `subject` → `contentSection.subject`
12
+ - `preheader` → `contentSection.preheader`
13
+ - `content` → `contentSection.content`
14
+
15
+ ## [0.12.3] - 2025-07-20
16
+
17
+ ### Fixed
18
+ - Fixed import map component path references to use package exports instead of file paths
19
+ - Resolved "PayloadComponent not found in importMap" errors in Payload v3 projects
20
+ - Added missing component exports (StatusBadge, ActionsCell, EmptyField)
21
+
1
22
  ## [0.12.2] - 2025-07-20
2
23
 
3
24
  ### Documentation
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/exports/components.ts
32
32
  var components_exports = {};
33
33
  __export(components_exports, {
34
+ ActionsCell: () => ActionsCell,
34
35
  BroadcastEditor: () => BroadcastEditor,
35
36
  BroadcastInlinePreview: () => BroadcastInlinePreview,
36
37
  BroadcastPreviewField: () => BroadcastPreviewField,
@@ -38,10 +39,12 @@ __export(components_exports, {
38
39
  EmailPreview: () => EmailPreview,
39
40
  EmailPreviewField: () => EmailPreviewField,
40
41
  EmailRenderer: () => EmailRenderer,
42
+ EmptyField: () => EmptyField,
41
43
  MagicLinkVerify: () => MagicLinkVerify,
42
44
  NewsletterForm: () => NewsletterForm,
43
45
  PreferencesForm: () => PreferencesForm,
44
46
  PreviewControls: () => PreviewControls,
47
+ StatusBadge: () => StatusBadge,
45
48
  createMagicLinkVerify: () => createMagicLinkVerify,
46
49
  createNewsletterForm: () => createNewsletterForm,
47
50
  createPreferencesForm: () => createPreferencesForm,
@@ -1443,9 +1446,9 @@ var EmailPreviewField = () => {
1443
1446
  const [isValid, setIsValid] = (0, import_react6.useState)(true);
1444
1447
  const [validationSummary, setValidationSummary] = (0, import_react6.useState)("");
1445
1448
  const fields = (0, import_ui.useFormFields)(([fields2]) => ({
1446
- content: fields2.content,
1447
- subject: fields2.subject,
1448
- preheader: fields2.preheader,
1449
+ content: fields2["contentSection.content"],
1450
+ subject: fields2["contentSection.subject"],
1451
+ preheader: fields2["contentSection.preheader"],
1449
1452
  channel: fields2.channel
1450
1453
  }));
1451
1454
  const handleValidation = (result) => {
@@ -1585,8 +1588,8 @@ var BroadcastEditor = (props) => {
1585
1588
  const [isValid, setIsValid] = (0, import_react7.useState)(true);
1586
1589
  const [validationSummary, setValidationSummary] = (0, import_react7.useState)("");
1587
1590
  const fields = (0, import_ui2.useFormFields)(([fields2]) => ({
1588
- subject: fields2.subject,
1589
- preheader: fields2.preheader
1591
+ subject: fields2["contentSection.subject"],
1592
+ preheader: fields2["contentSection.preheader"]
1590
1593
  }));
1591
1594
  const handleValidation = (0, import_react7.useCallback)((result) => {
1592
1595
  setIsValid(result.valid);
@@ -2028,9 +2031,9 @@ var BroadcastInlinePreview = () => {
2028
2031
  const [previewData, setPreviewData] = (0, import_react9.useState)(null);
2029
2032
  const [error, setError] = (0, import_react9.useState)(null);
2030
2033
  const fields = (0, import_ui3.useFormFields)(([fields2]) => ({
2031
- subject: fields2.subject?.value,
2032
- preheader: fields2.preheader?.value,
2033
- content: fields2.content?.value
2034
+ subject: fields2["contentSection.subject"]?.value,
2035
+ preheader: fields2["contentSection.preheader"]?.value,
2036
+ content: fields2["contentSection.content"]?.value
2034
2037
  }));
2035
2038
  const updatePreview = (0, import_react9.useCallback)(async () => {
2036
2039
  if (!fields.content) {
@@ -2061,10 +2064,12 @@ var BroadcastInlinePreview = () => {
2061
2064
  }
2062
2065
  }, [fields]);
2063
2066
  const containerStyle = {
2064
- marginTop: "2rem",
2065
2067
  border: "1px solid #e5e7eb",
2066
2068
  borderRadius: "8px",
2067
- overflow: "hidden"
2069
+ overflow: "hidden",
2070
+ height: "100%",
2071
+ display: "flex",
2072
+ flexDirection: "column"
2068
2073
  };
2069
2074
  const headerStyle = {
2070
2075
  display: "flex",
@@ -2081,10 +2086,11 @@ var BroadcastInlinePreview = () => {
2081
2086
  margin: 0
2082
2087
  };
2083
2088
  const previewContainerStyle = {
2084
- height: "600px",
2089
+ flex: 1,
2085
2090
  display: "flex",
2086
2091
  flexDirection: "column",
2087
- background: "#f3f4f6"
2092
+ background: "#f3f4f6",
2093
+ minHeight: "600px"
2088
2094
  };
2089
2095
  const errorStyle = {
2090
2096
  padding: "2rem",
@@ -2163,8 +2169,517 @@ var BroadcastPreviewField = () => {
2163
2169
  color: "#6b7280"
2164
2170
  }, children: "Email preview is available inline below the content editor." });
2165
2171
  };
2172
+
2173
+ // src/components/Broadcasts/StatusBadge.tsx
2174
+ var import_jsx_runtime12 = require("react/jsx-runtime");
2175
+ var statusConfig = {
2176
+ ["draft" /* DRAFT */]: {
2177
+ label: "Draft",
2178
+ color: "#6B7280",
2179
+ // gray
2180
+ backgroundColor: "#F3F4F6"
2181
+ },
2182
+ ["scheduled" /* SCHEDULED */]: {
2183
+ label: "Scheduled",
2184
+ color: "#2563EB",
2185
+ // blue
2186
+ backgroundColor: "#DBEAFE"
2187
+ },
2188
+ ["sending" /* SENDING */]: {
2189
+ label: "Sending",
2190
+ color: "#D97706",
2191
+ // yellow/orange
2192
+ backgroundColor: "#FEF3C7"
2193
+ },
2194
+ ["sent" /* SENT */]: {
2195
+ label: "Sent",
2196
+ color: "#059669",
2197
+ // green
2198
+ backgroundColor: "#D1FAE5"
2199
+ },
2200
+ ["failed" /* FAILED */]: {
2201
+ label: "Failed",
2202
+ color: "#DC2626",
2203
+ // red
2204
+ backgroundColor: "#FEE2E2"
2205
+ },
2206
+ ["paused" /* PAUSED */]: {
2207
+ label: "Paused",
2208
+ color: "#9333EA",
2209
+ // purple
2210
+ backgroundColor: "#EDE9FE"
2211
+ },
2212
+ ["canceled" /* CANCELED */]: {
2213
+ label: "Canceled",
2214
+ color: "#6B7280",
2215
+ // gray
2216
+ backgroundColor: "#F3F4F6"
2217
+ }
2218
+ };
2219
+ var StatusBadge = ({ cellData }) => {
2220
+ const status = cellData;
2221
+ const config = statusConfig[status] || statusConfig["draft" /* DRAFT */];
2222
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2223
+ "span",
2224
+ {
2225
+ style: {
2226
+ display: "inline-flex",
2227
+ alignItems: "center",
2228
+ padding: "2px 10px",
2229
+ borderRadius: "12px",
2230
+ fontSize: "12px",
2231
+ fontWeight: "500",
2232
+ color: config.color,
2233
+ backgroundColor: config.backgroundColor
2234
+ },
2235
+ children: config.label
2236
+ }
2237
+ );
2238
+ };
2239
+
2240
+ // src/components/Broadcasts/ActionsCell.tsx
2241
+ var import_react11 = require("react");
2242
+
2243
+ // src/components/Broadcasts/SendBroadcastModal.tsx
2244
+ var import_react10 = require("react");
2245
+ var import_jsx_runtime13 = require("react/jsx-runtime");
2246
+ var SendBroadcastModal = ({
2247
+ broadcast,
2248
+ onClose,
2249
+ onSuccess
2250
+ }) => {
2251
+ const [loading, setLoading] = (0, import_react10.useState)(false);
2252
+ const [error, setError] = (0, import_react10.useState)(null);
2253
+ const [selectedAudiences, setSelectedAudiences] = (0, import_react10.useState)([]);
2254
+ const [audiences, setAudiences] = (0, import_react10.useState)([]);
2255
+ const [providerCapabilities, setProviderCapabilities] = (0, import_react10.useState)(null);
2256
+ const [sendMode, setSendMode] = (0, import_react10.useState)("now");
2257
+ const [scheduledDate, setScheduledDate] = (0, import_react10.useState)("");
2258
+ const [scheduledTime, setScheduledTime] = (0, import_react10.useState)("");
2259
+ (0, import_react10.useEffect)(() => {
2260
+ const fetchData = async () => {
2261
+ try {
2262
+ setAudiences([
2263
+ { id: "all", name: "All Subscribers", subscriberCount: 1e3 },
2264
+ { id: "active", name: "Active Subscribers", subscriberCount: 850 }
2265
+ ]);
2266
+ if (broadcast.channel?.providerType === "broadcast") {
2267
+ setProviderCapabilities({ supportsScheduling: true });
2268
+ } else {
2269
+ setProviderCapabilities({ supportsScheduling: false });
2270
+ }
2271
+ } catch (err) {
2272
+ console.error("Failed to fetch modal data:", err);
2273
+ }
2274
+ };
2275
+ fetchData();
2276
+ }, [broadcast.channel]);
2277
+ const handleSubmit = async (e) => {
2278
+ e.preventDefault();
2279
+ setError(null);
2280
+ setLoading(true);
2281
+ try {
2282
+ if (sendMode === "now") {
2283
+ const response = await fetch(`/api/broadcasts/${broadcast.id}/send`, {
2284
+ method: "POST",
2285
+ headers: {
2286
+ "Content-Type": "application/json"
2287
+ },
2288
+ body: JSON.stringify({
2289
+ audienceIds: selectedAudiences.length > 0 ? selectedAudiences : void 0
2290
+ })
2291
+ });
2292
+ if (!response.ok) {
2293
+ const data = await response.json();
2294
+ throw new Error(data.error || "Failed to send broadcast");
2295
+ }
2296
+ alert(`Broadcast "${broadcast.name}" has been sent successfully`);
2297
+ } else {
2298
+ if (!scheduledDate || !scheduledTime) {
2299
+ throw new Error("Please select both date and time for scheduling");
2300
+ }
2301
+ const scheduledAt = (/* @__PURE__ */ new Date(`${scheduledDate}T${scheduledTime}`)).toISOString();
2302
+ const response = await fetch(`/api/broadcasts/${broadcast.id}/schedule`, {
2303
+ method: "POST",
2304
+ headers: {
2305
+ "Content-Type": "application/json"
2306
+ },
2307
+ body: JSON.stringify({
2308
+ scheduledAt,
2309
+ audienceIds: selectedAudiences.length > 0 ? selectedAudiences : void 0
2310
+ })
2311
+ });
2312
+ if (!response.ok) {
2313
+ const data = await response.json();
2314
+ throw new Error(data.error || "Failed to schedule broadcast");
2315
+ }
2316
+ alert(`Broadcast "${broadcast.name}" has been scheduled successfully`);
2317
+ }
2318
+ onSuccess();
2319
+ } catch (err) {
2320
+ setError(err instanceof Error ? err.message : "An error occurred");
2321
+ } finally {
2322
+ setLoading(false);
2323
+ }
2324
+ };
2325
+ const handleAudienceToggle = (audienceId) => {
2326
+ setSelectedAudiences(
2327
+ (prev) => prev.includes(audienceId) ? prev.filter((id) => id !== audienceId) : [...prev, audienceId]
2328
+ );
2329
+ };
2330
+ const now = /* @__PURE__ */ new Date();
2331
+ const minDate = now.toISOString().split("T")[0];
2332
+ const minTime = now.toTimeString().slice(0, 5);
2333
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: {
2334
+ position: "fixed",
2335
+ top: 0,
2336
+ left: 0,
2337
+ right: 0,
2338
+ bottom: 0,
2339
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
2340
+ display: "flex",
2341
+ alignItems: "center",
2342
+ justifyContent: "center",
2343
+ zIndex: 9999
2344
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: {
2345
+ backgroundColor: "white",
2346
+ borderRadius: "8px",
2347
+ padding: "32px",
2348
+ maxWidth: "500px",
2349
+ width: "90%",
2350
+ maxHeight: "90vh",
2351
+ overflowY: "auto"
2352
+ }, children: [
2353
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("h2", { style: { marginTop: 0, marginBottom: "24px" }, children: [
2354
+ "Send Broadcast: ",
2355
+ broadcast.name
2356
+ ] }),
2357
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("form", { onSubmit: handleSubmit, children: [
2358
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { marginBottom: "24px" }, children: [
2359
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: { fontWeight: "bold", display: "block", marginBottom: "8px" }, children: "When to send:" }),
2360
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { display: "flex", gap: "16px" }, children: [
2361
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { style: { display: "flex", alignItems: "center", cursor: "pointer" }, children: [
2362
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2363
+ "input",
2364
+ {
2365
+ type: "radio",
2366
+ value: "now",
2367
+ checked: sendMode === "now",
2368
+ onChange: (e) => setSendMode(e.target.value),
2369
+ style: { marginRight: "8px" }
2370
+ }
2371
+ ),
2372
+ "Send Now"
2373
+ ] }),
2374
+ providerCapabilities?.supportsScheduling && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { style: { display: "flex", alignItems: "center", cursor: "pointer" }, children: [
2375
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2376
+ "input",
2377
+ {
2378
+ type: "radio",
2379
+ value: "schedule",
2380
+ checked: sendMode === "schedule",
2381
+ onChange: (e) => setSendMode(e.target.value),
2382
+ style: { marginRight: "8px" }
2383
+ }
2384
+ ),
2385
+ "Schedule for Later"
2386
+ ] })
2387
+ ] })
2388
+ ] }),
2389
+ sendMode === "schedule" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { marginBottom: "24px" }, children: [
2390
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: { fontWeight: "bold", display: "block", marginBottom: "8px" }, children: "Schedule Date & Time:" }),
2391
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
2392
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2393
+ "input",
2394
+ {
2395
+ type: "date",
2396
+ value: scheduledDate,
2397
+ onChange: (e) => setScheduledDate(e.target.value),
2398
+ min: minDate,
2399
+ required: sendMode === "schedule",
2400
+ style: {
2401
+ padding: "8px 12px",
2402
+ border: "1px solid #D1D5DB",
2403
+ borderRadius: "4px",
2404
+ flex: 1
2405
+ }
2406
+ }
2407
+ ),
2408
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2409
+ "input",
2410
+ {
2411
+ type: "time",
2412
+ value: scheduledTime,
2413
+ onChange: (e) => setScheduledTime(e.target.value),
2414
+ min: scheduledDate === minDate ? minTime : void 0,
2415
+ required: sendMode === "schedule",
2416
+ style: {
2417
+ padding: "8px 12px",
2418
+ border: "1px solid #D1D5DB",
2419
+ borderRadius: "4px",
2420
+ flex: 1
2421
+ }
2422
+ }
2423
+ )
2424
+ ] })
2425
+ ] }),
2426
+ audiences.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { marginBottom: "24px" }, children: [
2427
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: { fontWeight: "bold", display: "block", marginBottom: "8px" }, children: "Target Audiences (optional):" }),
2428
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: {
2429
+ border: "1px solid #D1D5DB",
2430
+ borderRadius: "4px",
2431
+ maxHeight: "200px",
2432
+ overflowY: "auto"
2433
+ }, children: audiences.map((audience) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2434
+ "label",
2435
+ {
2436
+ style: {
2437
+ display: "flex",
2438
+ alignItems: "center",
2439
+ padding: "12px",
2440
+ borderBottom: "1px solid #E5E7EB",
2441
+ cursor: "pointer",
2442
+ backgroundColor: selectedAudiences.includes(audience.id) ? "#F3F4F6" : "transparent"
2443
+ },
2444
+ children: [
2445
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2446
+ "input",
2447
+ {
2448
+ type: "checkbox",
2449
+ checked: selectedAudiences.includes(audience.id),
2450
+ onChange: () => handleAudienceToggle(audience.id),
2451
+ style: { marginRight: "12px" }
2452
+ }
2453
+ ),
2454
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { flex: 1 }, children: [
2455
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { fontWeight: 500 }, children: audience.name }),
2456
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { fontSize: "14px", color: "#6B7280" }, children: [
2457
+ audience.subscriberCount.toLocaleString(),
2458
+ " subscribers"
2459
+ ] })
2460
+ ] })
2461
+ ]
2462
+ },
2463
+ audience.id
2464
+ )) }),
2465
+ selectedAudiences.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { style: { fontSize: "14px", color: "#6B7280", marginTop: "8px" }, children: "If no audiences are selected, the broadcast will be sent to all subscribers." })
2466
+ ] }),
2467
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: {
2468
+ backgroundColor: "#F3F4F6",
2469
+ padding: "16px",
2470
+ borderRadius: "4px",
2471
+ marginBottom: "24px"
2472
+ }, children: [
2473
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h4", { style: { marginTop: 0, marginBottom: "8px" }, children: "Summary" }),
2474
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("p", { style: { margin: 0, fontSize: "14px" }, children: [
2475
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("strong", { children: "Subject:" }),
2476
+ " ",
2477
+ broadcast.subject,
2478
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("br", {}),
2479
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("strong", { children: "Channel:" }),
2480
+ " ",
2481
+ broadcast.channel?.name || "Unknown",
2482
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("br", {}),
2483
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("strong", { children: "Provider:" }),
2484
+ " ",
2485
+ broadcast.channel?.providerType || "Unknown",
2486
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("br", {}),
2487
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("strong", { children: "When:" }),
2488
+ " ",
2489
+ sendMode === "now" ? "Immediately" : `${scheduledDate} at ${scheduledTime}`,
2490
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("br", {}),
2491
+ selectedAudiences.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
2492
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("strong", { children: "Audiences:" }),
2493
+ " ",
2494
+ selectedAudiences.length,
2495
+ " selected"
2496
+ ] })
2497
+ ] })
2498
+ ] }),
2499
+ error && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: {
2500
+ backgroundColor: "#FEE2E2",
2501
+ border: "1px solid #FCA5A5",
2502
+ color: "#DC2626",
2503
+ padding: "12px",
2504
+ borderRadius: "4px",
2505
+ marginBottom: "24px"
2506
+ }, children: error }),
2507
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: "12px" }, children: [
2508
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2509
+ "button",
2510
+ {
2511
+ type: "button",
2512
+ onClick: onClose,
2513
+ disabled: loading,
2514
+ style: {
2515
+ padding: "8px 24px",
2516
+ backgroundColor: "#E5E7EB",
2517
+ color: "#1F2937",
2518
+ border: "none",
2519
+ borderRadius: "4px",
2520
+ fontSize: "16px",
2521
+ cursor: loading ? "not-allowed" : "pointer",
2522
+ opacity: loading ? 0.6 : 1
2523
+ },
2524
+ children: "Cancel"
2525
+ }
2526
+ ),
2527
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2528
+ "button",
2529
+ {
2530
+ type: "submit",
2531
+ disabled: loading,
2532
+ style: {
2533
+ padding: "8px 24px",
2534
+ backgroundColor: "#2563EB",
2535
+ color: "white",
2536
+ border: "none",
2537
+ borderRadius: "4px",
2538
+ fontSize: "16px",
2539
+ cursor: loading ? "not-allowed" : "pointer",
2540
+ opacity: loading ? 0.6 : 1
2541
+ },
2542
+ children: loading ? "Processing..." : sendMode === "now" ? "Send Now" : "Schedule"
2543
+ }
2544
+ )
2545
+ ] })
2546
+ ] })
2547
+ ] }) });
2548
+ };
2549
+
2550
+ // src/components/Broadcasts/ActionsCell.tsx
2551
+ var import_jsx_runtime14 = require("react/jsx-runtime");
2552
+ var ActionsCell = ({ rowData }) => {
2553
+ const [loading, setLoading] = (0, import_react11.useState)(false);
2554
+ const [showSendModal, setShowSendModal] = (0, import_react11.useState)(false);
2555
+ const broadcast = rowData;
2556
+ const handleSend = () => {
2557
+ if (!broadcast.providerId) {
2558
+ alert("This broadcast has not been synced with the provider yet");
2559
+ return;
2560
+ }
2561
+ setShowSendModal(true);
2562
+ };
2563
+ const handleSchedule = () => {
2564
+ if (!broadcast.providerId) {
2565
+ alert("This broadcast has not been synced with the provider yet");
2566
+ return;
2567
+ }
2568
+ setShowSendModal(true);
2569
+ };
2570
+ const handleDuplicate = async () => {
2571
+ try {
2572
+ setLoading(true);
2573
+ const response = await fetch(`/api/broadcasts/${broadcast.id}`);
2574
+ const data = await response.json();
2575
+ delete data.id;
2576
+ delete data.createdAt;
2577
+ delete data.updatedAt;
2578
+ delete data.providerId;
2579
+ delete data.sentAt;
2580
+ delete data.scheduledAt;
2581
+ delete data.analytics;
2582
+ data.name = `${data.name} (Copy)`;
2583
+ data.status = "draft" /* DRAFT */;
2584
+ const createResponse = await fetch("/api/broadcasts", {
2585
+ method: "POST",
2586
+ headers: {
2587
+ "Content-Type": "application/json"
2588
+ },
2589
+ body: JSON.stringify(data)
2590
+ });
2591
+ if (!createResponse.ok) {
2592
+ throw new Error("Failed to duplicate broadcast");
2593
+ }
2594
+ alert("Broadcast duplicated successfully");
2595
+ window.location.reload();
2596
+ } catch (error) {
2597
+ alert(error instanceof Error ? error.message : "Failed to duplicate broadcast");
2598
+ } finally {
2599
+ setLoading(false);
2600
+ }
2601
+ };
2602
+ const canSend = broadcast.status === "draft" /* DRAFT */;
2603
+ const canSchedule = broadcast.status === "draft" /* DRAFT */;
2604
+ const canDuplicate = true;
2605
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
2606
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
2607
+ canSend && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2608
+ "button",
2609
+ {
2610
+ onClick: handleSend,
2611
+ disabled: loading,
2612
+ style: {
2613
+ padding: "4px 12px",
2614
+ backgroundColor: "#2563EB",
2615
+ color: "white",
2616
+ border: "none",
2617
+ borderRadius: "4px",
2618
+ fontSize: "12px",
2619
+ cursor: loading ? "not-allowed" : "pointer",
2620
+ opacity: loading ? 0.6 : 1
2621
+ },
2622
+ children: "Send"
2623
+ }
2624
+ ),
2625
+ canSchedule && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2626
+ "button",
2627
+ {
2628
+ onClick: handleSchedule,
2629
+ disabled: loading,
2630
+ style: {
2631
+ padding: "4px 12px",
2632
+ backgroundColor: "#6366F1",
2633
+ color: "white",
2634
+ border: "none",
2635
+ borderRadius: "4px",
2636
+ fontSize: "12px",
2637
+ cursor: loading ? "not-allowed" : "pointer",
2638
+ opacity: loading ? 0.6 : 1
2639
+ },
2640
+ children: "Schedule"
2641
+ }
2642
+ ),
2643
+ canDuplicate && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2644
+ "button",
2645
+ {
2646
+ onClick: handleDuplicate,
2647
+ disabled: loading,
2648
+ style: {
2649
+ padding: "4px 12px",
2650
+ backgroundColor: "#6B7280",
2651
+ color: "white",
2652
+ border: "none",
2653
+ borderRadius: "4px",
2654
+ fontSize: "12px",
2655
+ cursor: loading ? "not-allowed" : "pointer",
2656
+ opacity: loading ? 0.6 : 1
2657
+ },
2658
+ children: "Duplicate"
2659
+ }
2660
+ )
2661
+ ] }),
2662
+ showSendModal && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2663
+ SendBroadcastModal,
2664
+ {
2665
+ broadcast,
2666
+ onClose: () => setShowSendModal(false),
2667
+ onSuccess: () => {
2668
+ setShowSendModal(false);
2669
+ window.location.reload();
2670
+ }
2671
+ }
2672
+ )
2673
+ ] });
2674
+ };
2675
+
2676
+ // src/components/Broadcasts/EmptyField.tsx
2677
+ var EmptyField = () => {
2678
+ return null;
2679
+ };
2166
2680
  // Annotate the CommonJS export names for ESM import in node:
2167
2681
  0 && (module.exports = {
2682
+ ActionsCell,
2168
2683
  BroadcastEditor,
2169
2684
  BroadcastInlinePreview,
2170
2685
  BroadcastPreviewField,
@@ -2172,10 +2687,12 @@ var BroadcastPreviewField = () => {
2172
2687
  EmailPreview,
2173
2688
  EmailPreviewField,
2174
2689
  EmailRenderer,
2690
+ EmptyField,
2175
2691
  MagicLinkVerify,
2176
2692
  NewsletterForm,
2177
2693
  PreferencesForm,
2178
2694
  PreviewControls,
2695
+ StatusBadge,
2179
2696
  createMagicLinkVerify,
2180
2697
  createNewsletterForm,
2181
2698
  createPreferencesForm,