payload-plugin-newsletter
Version:
Complete newsletter management plugin for Payload CMS with subscriber management, magic link authentication, and email service integration
196 lines (192 loc) • 6.26 kB
JavaScript
"use client";
"use client";
// src/admin/components/BroadcastInlinePreview.tsx
import { useState, useCallback } from "react";
import { useFormFields } from "@payloadcms/ui";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
var BroadcastInlinePreview = () => {
const [preview, setPreview] = useState("");
const [loading, setLoading] = useState(false);
const [showPreview, setShowPreview] = useState(false);
const [error, setError] = useState(null);
const fields = useFormFields(([fields2]) => fields2);
const generatePreview = useCallback(async () => {
try {
setLoading(true);
setError(null);
const contentField = fields?.["contentSection.content"];
const contentValue = contentField?.value;
if (!contentValue) {
setError("No content available to preview");
setLoading(false);
return;
}
const documentData = {};
Object.entries(fields || {}).forEach(([key, field]) => {
if (field && typeof field === "object" && "value" in field) {
documentData[key] = field.value;
}
});
const response = await fetch("/api/broadcasts/preview", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
content: contentValue,
documentData
// Pass all form data
})
});
if (!response.ok) {
throw new Error(`Preview failed: ${response.statusText}`);
}
const data = await response.json();
setPreview(data.html || "");
setShowPreview(true);
} catch (err) {
console.error("Preview generation error:", err);
setError(err instanceof Error ? err.message : "Failed to generate preview");
} finally {
setLoading(false);
}
}, [fields]);
return /* @__PURE__ */ jsxs("div", { className: "field-type", children: [
/* @__PURE__ */ jsx("div", { className: "field-label", children: "Email Preview" }),
!showPreview ? /* @__PURE__ */ jsxs("div", { className: "preview-controls", children: [
/* @__PURE__ */ jsx(
"button",
{
type: "button",
onClick: generatePreview,
disabled: loading,
className: "btn btn--style-primary btn--icon-style-without-border btn--size-small",
style: { marginBottom: "1rem" },
children: loading ? "Generating Preview..." : "Generate Preview"
}
),
error && /* @__PURE__ */ jsx("div", { className: "error-message", style: { color: "#dc2626", marginTop: "0.5rem" }, children: error })
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs("div", { className: "preview-controls", style: { marginBottom: "1rem" }, children: [
/* @__PURE__ */ jsx(
"button",
{
type: "button",
onClick: () => setShowPreview(false),
className: "btn btn--style-secondary btn--icon-style-without-border btn--size-small",
style: { marginRight: "0.5rem" },
children: "Hide Preview"
}
),
/* @__PURE__ */ jsx(
"button",
{
type: "button",
onClick: generatePreview,
disabled: loading,
className: "btn btn--style-primary btn--icon-style-without-border btn--size-small",
children: loading ? "Regenerating..." : "Refresh Preview"
}
)
] }),
/* @__PURE__ */ jsx("div", { className: "email-preview-container", children: /* @__PURE__ */ jsx(
"iframe",
{
srcDoc: preview,
style: {
width: "100%",
height: "600px",
border: "1px solid #e5e7eb",
borderRadius: "0.375rem",
backgroundColor: "white"
},
title: "Email Preview"
}
) })
] })
] });
};
// src/admin/components/StatusBadge.tsx
import { jsx as jsx2 } from "react/jsx-runtime";
var StatusBadge = (props) => {
const status = props.cellData || "draft";
const getStatusColor = (status2) => {
switch (status2) {
case "sent":
return "#22c55e";
case "scheduled":
return "#3b82f6";
case "draft":
return "#6b7280";
case "failed":
return "#ef4444";
default:
return "#6b7280";
}
};
const getStatusLabel = (status2) => {
switch (status2) {
case "sent":
return "Sent";
case "scheduled":
return "Scheduled";
case "draft":
return "Draft";
case "failed":
return "Failed";
default:
return status2;
}
};
return /* @__PURE__ */ jsx2(
"span",
{
style: {
display: "inline-block",
padding: "4px 8px",
borderRadius: "12px",
fontSize: "12px",
fontWeight: "500",
color: "#fff",
backgroundColor: getStatusColor(status),
textTransform: "capitalize"
},
children: getStatusLabel(status)
}
);
};
// src/admin/components/EmailPreview.tsx
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
var EmailPreview = ({
content,
subject,
preheader
}) => {
return /* @__PURE__ */ jsxs2("div", { className: "email-preview", style: { padding: "1rem" }, children: [
/* @__PURE__ */ jsxs2("div", { style: { marginBottom: "1rem" }, children: [
/* @__PURE__ */ jsx3("strong", { children: "Subject:" }),
" ",
subject || "No subject"
] }),
preheader && /* @__PURE__ */ jsxs2("div", { style: { marginBottom: "1rem", color: "#666" }, children: [
/* @__PURE__ */ jsx3("strong", { children: "Preheader:" }),
" ",
preheader
] }),
/* @__PURE__ */ jsxs2("div", { style: {
border: "1px solid #e0e0e0",
borderRadius: "4px",
padding: "1rem",
backgroundColor: "#f9f9f9"
}, children: [
/* @__PURE__ */ jsx3("div", { children: "Email content will be rendered here" }),
content && /* @__PURE__ */ jsxs2("div", { style: { marginTop: "1rem", fontSize: "14px", color: "#666" }, children: [
"Content type: ",
typeof content
] })
] })
] });
};
export {
BroadcastInlinePreview,
EmailPreview,
StatusBadge
};