payload-plugin-newsletter 0.15.1 → 0.16.1

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.
@@ -31,7 +31,6 @@ 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,
35
34
  BroadcastEditor: () => BroadcastEditor,
36
35
  BroadcastInlinePreview: () => BroadcastInlinePreview,
37
36
  BroadcastPreviewField: () => BroadcastPreviewField,
@@ -2240,449 +2239,12 @@ var StatusBadge = ({ cellData }) => {
2240
2239
  );
2241
2240
  };
2242
2241
 
2243
- // src/components/Broadcasts/ActionsCell.tsx
2244
- var import_react11 = require("react");
2245
-
2246
- // src/components/Broadcasts/SendBroadcastModal.tsx
2247
- var import_react10 = require("react");
2248
- var import_jsx_runtime13 = require("react/jsx-runtime");
2249
- var SendBroadcastModal = ({
2250
- broadcast,
2251
- onClose,
2252
- onSuccess
2253
- }) => {
2254
- const [loading, setLoading] = (0, import_react10.useState)(false);
2255
- const [error, setError] = (0, import_react10.useState)(null);
2256
- const [selectedAudiences, setSelectedAudiences] = (0, import_react10.useState)([]);
2257
- const [audiences, setAudiences] = (0, import_react10.useState)([]);
2258
- const [providerCapabilities, setProviderCapabilities] = (0, import_react10.useState)(null);
2259
- const [sendMode, setSendMode] = (0, import_react10.useState)("now");
2260
- const [scheduledDate, setScheduledDate] = (0, import_react10.useState)("");
2261
- const [scheduledTime, setScheduledTime] = (0, import_react10.useState)("");
2262
- (0, import_react10.useEffect)(() => {
2263
- const fetchData = async () => {
2264
- try {
2265
- setAudiences([
2266
- { id: "all", name: "All Subscribers", subscriberCount: 1e3 },
2267
- { id: "active", name: "Active Subscribers", subscriberCount: 850 }
2268
- ]);
2269
- if (broadcast.channel?.providerType === "broadcast") {
2270
- setProviderCapabilities({ supportsScheduling: true });
2271
- } else {
2272
- setProviderCapabilities({ supportsScheduling: false });
2273
- }
2274
- } catch (err) {
2275
- console.error("Failed to fetch modal data:", err);
2276
- }
2277
- };
2278
- fetchData();
2279
- }, [broadcast.channel]);
2280
- const handleSubmit = async (e) => {
2281
- e.preventDefault();
2282
- setError(null);
2283
- setLoading(true);
2284
- try {
2285
- if (sendMode === "now") {
2286
- const response = await fetch(`/api/broadcasts/${broadcast.id}/send`, {
2287
- method: "POST",
2288
- headers: {
2289
- "Content-Type": "application/json"
2290
- },
2291
- body: JSON.stringify({
2292
- audienceIds: selectedAudiences.length > 0 ? selectedAudiences : void 0
2293
- })
2294
- });
2295
- if (!response.ok) {
2296
- const data = await response.json();
2297
- throw new Error(data.error || "Failed to send broadcast");
2298
- }
2299
- alert(`Broadcast "${broadcast.name}" has been sent successfully`);
2300
- } else {
2301
- if (!scheduledDate || !scheduledTime) {
2302
- throw new Error("Please select both date and time for scheduling");
2303
- }
2304
- const scheduledAt = (/* @__PURE__ */ new Date(`${scheduledDate}T${scheduledTime}`)).toISOString();
2305
- const response = await fetch(`/api/broadcasts/${broadcast.id}/schedule`, {
2306
- method: "POST",
2307
- headers: {
2308
- "Content-Type": "application/json"
2309
- },
2310
- body: JSON.stringify({
2311
- scheduledAt,
2312
- audienceIds: selectedAudiences.length > 0 ? selectedAudiences : void 0
2313
- })
2314
- });
2315
- if (!response.ok) {
2316
- const data = await response.json();
2317
- throw new Error(data.error || "Failed to schedule broadcast");
2318
- }
2319
- alert(`Broadcast "${broadcast.name}" has been scheduled successfully`);
2320
- }
2321
- onSuccess();
2322
- } catch (err) {
2323
- setError(err instanceof Error ? err.message : "An error occurred");
2324
- } finally {
2325
- setLoading(false);
2326
- }
2327
- };
2328
- const handleAudienceToggle = (audienceId) => {
2329
- setSelectedAudiences(
2330
- (prev) => prev.includes(audienceId) ? prev.filter((id) => id !== audienceId) : [...prev, audienceId]
2331
- );
2332
- };
2333
- const now = /* @__PURE__ */ new Date();
2334
- const minDate = now.toISOString().split("T")[0];
2335
- const minTime = now.toTimeString().slice(0, 5);
2336
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: {
2337
- position: "fixed",
2338
- top: 0,
2339
- left: 0,
2340
- right: 0,
2341
- bottom: 0,
2342
- backgroundColor: "rgba(0, 0, 0, 0.5)",
2343
- display: "flex",
2344
- alignItems: "center",
2345
- justifyContent: "center",
2346
- zIndex: 9999
2347
- }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: {
2348
- backgroundColor: "white",
2349
- borderRadius: "8px",
2350
- padding: "32px",
2351
- maxWidth: "500px",
2352
- width: "90%",
2353
- maxHeight: "90vh",
2354
- overflowY: "auto"
2355
- }, children: [
2356
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("h2", { style: { marginTop: 0, marginBottom: "24px" }, children: [
2357
- "Send Broadcast: ",
2358
- broadcast.name
2359
- ] }),
2360
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("form", { onSubmit: handleSubmit, children: [
2361
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { marginBottom: "24px" }, children: [
2362
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: { fontWeight: "bold", display: "block", marginBottom: "8px" }, children: "When to send:" }),
2363
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { display: "flex", gap: "16px" }, children: [
2364
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { style: { display: "flex", alignItems: "center", cursor: "pointer" }, children: [
2365
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2366
- "input",
2367
- {
2368
- type: "radio",
2369
- value: "now",
2370
- checked: sendMode === "now",
2371
- onChange: (e) => setSendMode(e.target.value),
2372
- style: { marginRight: "8px" }
2373
- }
2374
- ),
2375
- "Send Now"
2376
- ] }),
2377
- providerCapabilities?.supportsScheduling && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { style: { display: "flex", alignItems: "center", cursor: "pointer" }, children: [
2378
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2379
- "input",
2380
- {
2381
- type: "radio",
2382
- value: "schedule",
2383
- checked: sendMode === "schedule",
2384
- onChange: (e) => setSendMode(e.target.value),
2385
- style: { marginRight: "8px" }
2386
- }
2387
- ),
2388
- "Schedule for Later"
2389
- ] })
2390
- ] })
2391
- ] }),
2392
- sendMode === "schedule" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { marginBottom: "24px" }, children: [
2393
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: { fontWeight: "bold", display: "block", marginBottom: "8px" }, children: "Schedule Date & Time:" }),
2394
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
2395
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2396
- "input",
2397
- {
2398
- type: "date",
2399
- value: scheduledDate,
2400
- onChange: (e) => setScheduledDate(e.target.value),
2401
- min: minDate,
2402
- required: sendMode === "schedule",
2403
- style: {
2404
- padding: "8px 12px",
2405
- border: "1px solid #D1D5DB",
2406
- borderRadius: "4px",
2407
- flex: 1
2408
- }
2409
- }
2410
- ),
2411
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2412
- "input",
2413
- {
2414
- type: "time",
2415
- value: scheduledTime,
2416
- onChange: (e) => setScheduledTime(e.target.value),
2417
- min: scheduledDate === minDate ? minTime : void 0,
2418
- required: sendMode === "schedule",
2419
- style: {
2420
- padding: "8px 12px",
2421
- border: "1px solid #D1D5DB",
2422
- borderRadius: "4px",
2423
- flex: 1
2424
- }
2425
- }
2426
- )
2427
- ] })
2428
- ] }),
2429
- audiences.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { marginBottom: "24px" }, children: [
2430
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: { fontWeight: "bold", display: "block", marginBottom: "8px" }, children: "Target Audiences (optional):" }),
2431
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: {
2432
- border: "1px solid #D1D5DB",
2433
- borderRadius: "4px",
2434
- maxHeight: "200px",
2435
- overflowY: "auto"
2436
- }, children: audiences.map((audience) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2437
- "label",
2438
- {
2439
- style: {
2440
- display: "flex",
2441
- alignItems: "center",
2442
- padding: "12px",
2443
- borderBottom: "1px solid #E5E7EB",
2444
- cursor: "pointer",
2445
- backgroundColor: selectedAudiences.includes(audience.id) ? "#F3F4F6" : "transparent"
2446
- },
2447
- children: [
2448
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2449
- "input",
2450
- {
2451
- type: "checkbox",
2452
- checked: selectedAudiences.includes(audience.id),
2453
- onChange: () => handleAudienceToggle(audience.id),
2454
- style: { marginRight: "12px" }
2455
- }
2456
- ),
2457
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { flex: 1 }, children: [
2458
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { fontWeight: 500 }, children: audience.name }),
2459
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { fontSize: "14px", color: "#6B7280" }, children: [
2460
- audience.subscriberCount.toLocaleString(),
2461
- " subscribers"
2462
- ] })
2463
- ] })
2464
- ]
2465
- },
2466
- audience.id
2467
- )) }),
2468
- 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." })
2469
- ] }),
2470
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: {
2471
- backgroundColor: "#F3F4F6",
2472
- padding: "16px",
2473
- borderRadius: "4px",
2474
- marginBottom: "24px"
2475
- }, children: [
2476
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h4", { style: { marginTop: 0, marginBottom: "8px" }, children: "Summary" }),
2477
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("p", { style: { margin: 0, fontSize: "14px" }, children: [
2478
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("strong", { children: "Subject:" }),
2479
- " ",
2480
- broadcast.subject,
2481
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("br", {}),
2482
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("strong", { children: "Channel:" }),
2483
- " ",
2484
- broadcast.channel?.name || "Unknown",
2485
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("br", {}),
2486
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("strong", { children: "Provider:" }),
2487
- " ",
2488
- broadcast.channel?.providerType || "Unknown",
2489
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("br", {}),
2490
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("strong", { children: "When:" }),
2491
- " ",
2492
- sendMode === "now" ? "Immediately" : `${scheduledDate} at ${scheduledTime}`,
2493
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("br", {}),
2494
- selectedAudiences.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
2495
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("strong", { children: "Audiences:" }),
2496
- " ",
2497
- selectedAudiences.length,
2498
- " selected"
2499
- ] })
2500
- ] })
2501
- ] }),
2502
- error && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: {
2503
- backgroundColor: "#FEE2E2",
2504
- border: "1px solid #FCA5A5",
2505
- color: "#DC2626",
2506
- padding: "12px",
2507
- borderRadius: "4px",
2508
- marginBottom: "24px"
2509
- }, children: error }),
2510
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: "12px" }, children: [
2511
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2512
- "button",
2513
- {
2514
- type: "button",
2515
- onClick: onClose,
2516
- disabled: loading,
2517
- style: {
2518
- padding: "8px 24px",
2519
- backgroundColor: "#E5E7EB",
2520
- color: "#1F2937",
2521
- border: "none",
2522
- borderRadius: "4px",
2523
- fontSize: "16px",
2524
- cursor: loading ? "not-allowed" : "pointer",
2525
- opacity: loading ? 0.6 : 1
2526
- },
2527
- children: "Cancel"
2528
- }
2529
- ),
2530
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2531
- "button",
2532
- {
2533
- type: "submit",
2534
- disabled: loading,
2535
- style: {
2536
- padding: "8px 24px",
2537
- backgroundColor: "#2563EB",
2538
- color: "white",
2539
- border: "none",
2540
- borderRadius: "4px",
2541
- fontSize: "16px",
2542
- cursor: loading ? "not-allowed" : "pointer",
2543
- opacity: loading ? 0.6 : 1
2544
- },
2545
- children: loading ? "Processing..." : sendMode === "now" ? "Send Now" : "Schedule"
2546
- }
2547
- )
2548
- ] })
2549
- ] })
2550
- ] }) });
2551
- };
2552
-
2553
- // src/components/Broadcasts/ActionsCell.tsx
2554
- var import_jsx_runtime14 = require("react/jsx-runtime");
2555
- var ActionsCell = ({ rowData }) => {
2556
- const [loading, setLoading] = (0, import_react11.useState)(false);
2557
- const [showSendModal, setShowSendModal] = (0, import_react11.useState)(false);
2558
- const broadcast = rowData;
2559
- const handleSend = () => {
2560
- if (!broadcast.providerId) {
2561
- alert("This broadcast has not been synced with the provider yet");
2562
- return;
2563
- }
2564
- setShowSendModal(true);
2565
- };
2566
- const handleSchedule = () => {
2567
- if (!broadcast.providerId) {
2568
- alert("This broadcast has not been synced with the provider yet");
2569
- return;
2570
- }
2571
- setShowSendModal(true);
2572
- };
2573
- const handleDuplicate = async () => {
2574
- try {
2575
- setLoading(true);
2576
- const response = await fetch(`/api/broadcasts/${broadcast.id}`);
2577
- const data = await response.json();
2578
- delete data.id;
2579
- delete data.createdAt;
2580
- delete data.updatedAt;
2581
- delete data.providerId;
2582
- delete data.sentAt;
2583
- delete data.scheduledAt;
2584
- delete data.analytics;
2585
- data.name = `${data.name} (Copy)`;
2586
- data.status = "draft" /* DRAFT */;
2587
- const createResponse = await fetch("/api/broadcasts", {
2588
- method: "POST",
2589
- headers: {
2590
- "Content-Type": "application/json"
2591
- },
2592
- body: JSON.stringify(data)
2593
- });
2594
- if (!createResponse.ok) {
2595
- throw new Error("Failed to duplicate broadcast");
2596
- }
2597
- alert("Broadcast duplicated successfully");
2598
- window.location.reload();
2599
- } catch (error) {
2600
- alert(error instanceof Error ? error.message : "Failed to duplicate broadcast");
2601
- } finally {
2602
- setLoading(false);
2603
- }
2604
- };
2605
- const canSend = broadcast.status === "draft" /* DRAFT */;
2606
- const canSchedule = broadcast.status === "draft" /* DRAFT */;
2607
- const canDuplicate = true;
2608
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
2609
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
2610
- canSend && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2611
- "button",
2612
- {
2613
- onClick: handleSend,
2614
- disabled: loading,
2615
- style: {
2616
- padding: "4px 12px",
2617
- backgroundColor: "#2563EB",
2618
- color: "white",
2619
- border: "none",
2620
- borderRadius: "4px",
2621
- fontSize: "12px",
2622
- cursor: loading ? "not-allowed" : "pointer",
2623
- opacity: loading ? 0.6 : 1
2624
- },
2625
- children: "Send"
2626
- }
2627
- ),
2628
- canSchedule && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2629
- "button",
2630
- {
2631
- onClick: handleSchedule,
2632
- disabled: loading,
2633
- style: {
2634
- padding: "4px 12px",
2635
- backgroundColor: "#6366F1",
2636
- color: "white",
2637
- border: "none",
2638
- borderRadius: "4px",
2639
- fontSize: "12px",
2640
- cursor: loading ? "not-allowed" : "pointer",
2641
- opacity: loading ? 0.6 : 1
2642
- },
2643
- children: "Schedule"
2644
- }
2645
- ),
2646
- canDuplicate && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2647
- "button",
2648
- {
2649
- onClick: handleDuplicate,
2650
- disabled: loading,
2651
- style: {
2652
- padding: "4px 12px",
2653
- backgroundColor: "#6B7280",
2654
- color: "white",
2655
- border: "none",
2656
- borderRadius: "4px",
2657
- fontSize: "12px",
2658
- cursor: loading ? "not-allowed" : "pointer",
2659
- opacity: loading ? 0.6 : 1
2660
- },
2661
- children: "Duplicate"
2662
- }
2663
- )
2664
- ] }),
2665
- showSendModal && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2666
- SendBroadcastModal,
2667
- {
2668
- broadcast,
2669
- onClose: () => setShowSendModal(false),
2670
- onSuccess: () => {
2671
- setShowSendModal(false);
2672
- window.location.reload();
2673
- }
2674
- }
2675
- )
2676
- ] });
2677
- };
2678
-
2679
2242
  // src/components/Broadcasts/EmptyField.tsx
2680
2243
  var EmptyField = () => {
2681
2244
  return null;
2682
2245
  };
2683
2246
  // Annotate the CommonJS export names for ESM import in node:
2684
2247
  0 && (module.exports = {
2685
- ActionsCell,
2686
2248
  BroadcastEditor,
2687
2249
  BroadcastInlinePreview,
2688
2250
  BroadcastPreviewField,