diff --git a/dev.db b/dev.db new file mode 100644 index 0000000..ec19c6a Binary files /dev/null and b/dev.db differ diff --git a/dev/.env.local b/dev/.env.local new file mode 100644 index 0000000..a17bd82 --- /dev/null +++ b/dev/.env.local @@ -0,0 +1,2 @@ +USE_MEMORY_DB=true +PAYLOAD_SECRET=YOUR_SECRET_HERE diff --git a/dev/app/(frontend)/dashboard/page.tsx b/dev/app/(frontend)/dashboard/page.tsx new file mode 100644 index 0000000..79d7f3d --- /dev/null +++ b/dev/app/(frontend)/dashboard/page.tsx @@ -0,0 +1,310 @@ +'use client' + +import { useState, useEffect } from 'react' +import Link from 'next/link' + +interface EmailStats { + total: number + sent: number + pending: number + failed: number + processing: number +} + +export default function HomePage() { + const [emailStats, setEmailStats] = useState({ + total: 0, + sent: 0, + pending: 0, + failed: 0, + processing: 0 + }) + const [loading, setLoading] = useState(true) + + useEffect(() => { + fetchEmailStats() + }, []) + + const fetchEmailStats = async () => { + try { + const response = await fetch('/api/test-email') + const data = await response.json() + + if (data.outbox?.emails) { + const emails = data.outbox.emails + const stats: EmailStats = { + total: emails.length, + sent: emails.filter((email: any) => email.status === 'sent').length, + pending: emails.filter((email: any) => email.status === 'pending').length, + failed: emails.filter((email: any) => email.status === 'failed').length, + processing: emails.filter((email: any) => email.status === 'processing').length + } + setEmailStats(stats) + } + } catch (error) { + console.error('Error fetching email statistics:', error) + } finally { + setLoading(false) + } + } + + const StatCard = ({ label, value, color, description }: { label: string; value: number; color: string; description: string }) => ( +
+
+ {value} +
+
+ {label} +
+
+ {description} +
+
+ ) + + return ( +
+
+ {/* Header */} +
+

+ ๐Ÿ“ง PayloadCMS Mailing Plugin +

+

+ Development Dashboard +

+ +
+ + ๐Ÿ“Š Admin Panel + + + ๐Ÿงช Test Interface + +
+
+ + {/* Email Statistics */} +
+
+

+ Email Statistics +

+ +
+ + {loading ? ( +
+
Loading email statistics...
+
+ ) : ( +
+ + + + + {emailStats.processing > 0 && ( + + )} +
+ )} +
+ + {/* Quick Actions */} +
+

+ Quick Actions +

+
+
+

๐ŸŽฏ Test Email Sending

+

+ Send test emails using templates with the interactive testing interface. +

+ + Open Test Interface โ†’ + +
+ +
+

๐Ÿ“ Manage Templates

+

+ Create and edit email templates in the Payload admin interface. +

+ + Manage Templates โ†’ + +
+ +
+

๐Ÿ“ฌ Email Queue

+

+ View and manage the email outbox and delivery status. +

+ + View Email Queue โ†’ + +
+
+
+ + {/* Footer */} +
+ PayloadCMS Mailing Plugin Development Environment +
+
+
+ ) +} \ No newline at end of file diff --git a/dev/app/(frontend)/layout.tsx b/dev/app/(frontend)/layout.tsx new file mode 100644 index 0000000..9db289a --- /dev/null +++ b/dev/app/(frontend)/layout.tsx @@ -0,0 +1,24 @@ +import type { Metadata } from 'next' + +export const metadata: Metadata = { + title: 'PayloadCMS Mailing Plugin - Development', + description: 'Development environment for PayloadCMS Mailing Plugin', +} + +export default function FrontendLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + + {children} + + + ) +} \ No newline at end of file diff --git a/dev/app/mailing-test/page.tsx b/dev/app/(frontend)/mailing-test/page.tsx similarity index 82% rename from dev/app/mailing-test/page.tsx rename to dev/app/(frontend)/mailing-test/page.tsx index acb394e..2a9faa7 100644 --- a/dev/app/mailing-test/page.tsx +++ b/dev/app/(frontend)/mailing-test/page.tsx @@ -33,6 +33,8 @@ export default function MailingTestPage() { const [selectedTemplate, setSelectedTemplate] = useState('') const [toEmail, setToEmail] = useState('test@example.com') const [variables, setVariables] = useState>({}) + const [jsonVariables, setJsonVariables] = useState('{}') + const [jsonError, setJsonError] = useState('') const [emailType, setEmailType] = useState<'send' | 'schedule'>('send') const [scheduleDate, setScheduleDate] = useState('') const [loading, setLoading] = useState(false) @@ -58,6 +60,23 @@ export default function MailingTestPage() { const template = templates.find(t => t.slug === templateSlug) if (template?.previewData) { setVariables(template.previewData) + setJsonVariables(JSON.stringify(template.previewData, null, 2)) + } else { + setVariables({}) + setJsonVariables('{}') + } + setJsonError('') + } + + const handleJsonVariablesChange = (jsonString: string) => { + setJsonVariables(jsonString) + setJsonError('') + + try { + const parsed = JSON.parse(jsonString) + setVariables(parsed) + } catch (error) { + setJsonError(error instanceof Error ? error.message : 'Invalid JSON') } } @@ -67,6 +86,11 @@ export default function MailingTestPage() { return } + if (jsonError) { + setMessage('Please fix the JSON syntax error before sending') + return + } + setLoading(true) setMessage('') @@ -88,7 +112,8 @@ export default function MailingTestPage() { const result = await response.json() if (result.success) { - setMessage(`โœ… ${result.message} (ID: ${result.emailId})`) + const statusIcon = result.status === 'sent' ? '๐Ÿ“ง' : '๐Ÿ“ซ' + setMessage(`โœ… ${statusIcon} ${result.message} (ID: ${result.emailId})`) fetchData() // Refresh email queue } else { setMessage(`โŒ Error: ${result.error}`) @@ -204,28 +229,43 @@ export default function MailingTestPage() { )} - {selectedTemplateData?.variables && ( + {selectedTemplate && (
-

Template Variables:

- {selectedTemplateData.variables.map(variable => ( -
- - setVariables({ - ...variables, - [variable.name]: variable.type === 'number' ? Number(e.target.value) : - variable.type === 'boolean' ? e.target.checked : - e.target.value - })} - style={{ width: '100%', padding: '8px', borderRadius: '4px', border: '1px solid #ddd' }} - /> + +