@bernierllc/email-ui
Version:
React UI components for email management, templates, scheduling, and analytics
69 lines (67 loc) • 6.75 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/*
Copyright (c) 2025 Bernier LLC
This file is licensed to the client under a limited-use license.
The client may use and modify this code *only within the scope of the project it was delivered for*.
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
*/
import { useState } from 'react';
export const EmailComposer = ({ templates = [], onSend, onSchedule, onSaveDraft, isLoading = false, className = '', style, }) => {
const [formData, setFormData] = useState({
to: [],
cc: [],
bcc: [],
subject: '',
content: '',
});
const [scheduleTime, setScheduleTime] = useState(null);
const [showSchedule, setShowSchedule] = useState(false);
const [attachments, setAttachments] = useState([]);
const [variables, setVariables] = useState({});
const handleTemplateSelect = (templateId) => {
const template = templates.find(t => t.id === templateId);
if (template) {
setFormData(prev => ({
...prev,
subject: template.subject,
content: template.content,
templateId: templateId,
}));
const templateVars = {};
template.variables.forEach(variable => {
templateVars[variable] = '';
});
setVariables(templateVars);
}
};
const handleSubmit = async (e) => {
e.preventDefault();
const emailData = {
...formData,
attachments,
variables: Object.keys(variables).length > 0 ? variables : undefined,
scheduleTime: scheduleTime || undefined,
};
if (scheduleTime && onSchedule) {
await onSchedule(emailData);
}
else {
await onSend(emailData);
}
};
const handleFileAttachment = (event) => {
if (event.target.files) {
setAttachments(prev => [...prev, ...Array.from(event.target.files)]);
}
};
const removeAttachment = (index) => {
setAttachments(prev => prev.filter((_, i) => i !== index));
};
const selectedTemplate = templates.find(t => t.id === formData.templateId);
return (_jsxs("div", { className: `email-composer ${className}`, style: style, children: [_jsxs("div", { className: "email-composer__header", children: [_jsx("h2", { className: "email-composer__title", children: "Compose Email" }), templates.length > 0 && (_jsxs("div", { className: "template-selector", children: [_jsx("label", { htmlFor: "template-select", children: "Use Template:" }), _jsxs("select", { id: "template-select", onChange: (e) => handleTemplateSelect(e.target.value), className: "form-select", children: [_jsx("option", { value: "", children: "Select a template" }), templates.map((template) => (_jsx("option", { value: template.id, children: template.name }, template.id)))] })] }))] }), _jsxs("form", { onSubmit: handleSubmit, className: "email-composer__form", children: [_jsxs("div", { className: "form-group", children: [_jsx("label", { htmlFor: "to", className: "form-label", children: "To" }), _jsx("input", { id: "to", type: "email", value: formData.to[0] || '', onChange: (e) => setFormData(prev => ({ ...prev, to: [e.target.value] })), className: "form-input", placeholder: "Enter recipient email", required: true })] }), _jsxs("div", { className: "form-group", children: [_jsx("label", { htmlFor: "subject", className: "form-label", children: "Subject" }), _jsx("input", { id: "subject", type: "text", value: formData.subject, onChange: (e) => setFormData(prev => ({ ...prev, subject: e.target.value })), className: "form-input", placeholder: "Enter email subject", required: true })] }), selectedTemplate?.variables && selectedTemplate.variables.length > 0 && (_jsxs("div", { className: "template-variables", children: [_jsx("h3", { children: "Template Variables" }), selectedTemplate.variables.map((variable) => (_jsxs("div", { className: "form-group", children: [_jsx("label", { htmlFor: `var-${variable}`, className: "form-label", children: variable }), _jsx("input", { id: `var-${variable}`, type: "text", value: variables[variable] || '', onChange: (e) => setVariables(prev => ({ ...prev, [variable]: e.target.value })), className: "form-input", placeholder: `Enter value for ${variable}` })] }, variable)))] })), _jsxs("div", { className: "form-group", children: [_jsx("label", { htmlFor: "content", className: "form-label", children: "Message" }), _jsx("textarea", { id: "content", rows: 10, value: formData.content, onChange: (e) => setFormData(prev => ({ ...prev, content: e.target.value })), className: "form-textarea", placeholder: "Enter your email message", required: true })] }), _jsxs("div", { className: "form-group", children: [_jsx("label", { htmlFor: "attachments", className: "form-label", children: "Attachments" }), _jsx("input", { id: "attachments", type: "file", multiple: true, onChange: handleFileAttachment, className: "form-input" }), attachments.length > 0 && (_jsx("div", { className: "attachments-list", children: attachments.map((file, index) => (_jsxs("div", { className: "attachment-item", children: [_jsx("span", { children: file.name }), _jsx("button", { type: "button", onClick: () => removeAttachment(index), className: "btn btn--small btn--danger", children: "Remove" })] }, index))) }))] }), _jsxs("div", { className: "email-composer__scheduling", children: [_jsxs("label", { className: "checkbox-label", children: [_jsx("input", { type: "checkbox", checked: showSchedule, onChange: (e) => setShowSchedule(e.target.checked) }), "Schedule for later"] }), showSchedule && (_jsx("div", { className: "schedule-picker", children: _jsx("input", { type: "datetime-local", value: scheduleTime ? scheduleTime.toISOString().slice(0, -8) : '', onChange: (e) => setScheduleTime(e.target.value ? new Date(e.target.value) : null), className: "form-input", min: new Date().toISOString().slice(0, -8) }) }))] }), _jsxs("div", { className: "email-composer__footer", children: [onSaveDraft && (_jsx("button", { type: "button", onClick: () => onSaveDraft({
to: formData.to,
subject: formData.subject,
content: formData.content,
attachments
}), className: "btn btn--secondary", disabled: isLoading, children: "Save Draft" })), _jsx("button", { type: "submit", className: "btn btn--primary", disabled: isLoading, children: isLoading ? 'Sending...' : showSchedule ? 'Schedule' : 'Send' })] })] })] }));
};