@ideal-photography/shared
Version:
Shared MongoDB and utility logic for Ideal Photography PWAs: users, products, services, bookings, orders/cart, galleries, reviews, notifications, campaigns, settings, audit logs, minimart items/orders, and push notification subscriptions.
598 lines (530 loc) • 33.7 kB
JavaScript
export { sendMail, sendBatch } from './mail.resend.js';
export function buildVerificationEmail({ name, url }) {
const greeting = name ? `Hi ${name},` : 'Hello,';
const html = `
<p>${greeting}</p>
<p>Please verify your email by clicking the link below:</p>
<p><a href="${url}">Verify Email</a></p>
<p>This link will expire in 24 hours.</p>
`;
const text = `${greeting}\n\nPlease verify your email using the link: ${url}\nThis link will expire in 24 hours.`;
return { html, text };
}
export function buildResetPasswordEmail({ name, url }) {
const greeting = name ? `Hi ${name},` : 'Hello,';
const html = `
<p>${greeting}</p>
<p>We received a request to reset your password. Click the link below to set a new password:</p>
<p><a href="${url}">Reset Password</a></p>
<p>If you did not request this, you can safely ignore this email. The link expires in 1 hour.</p>
`;
const text = `${greeting}\n\nReset your password using the link: ${url}\nIf you did not request this, ignore this email. Link expires in 1 hour.`;
return { html, text };
}
export function buildPasswordChangedEmail({ name, timestamp, ipAddress, deviceInfo }) {
const greeting = name ? `Hi ${name},` : 'Hello,';
const formattedTime = timestamp ? new Date(timestamp).toLocaleString() : new Date().toLocaleString();
const location = ipAddress ? ` from IP address ${ipAddress}` : '';
const device = deviceInfo ? ` using ${deviceInfo}` : '';
const html = `
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<div style="background-color: #10B981; color: white; padding: 20px; text-align: center;">
<h1 style="margin: 0;">Password Changed Successfully</h1>
<p style="margin: 10px 0 0 0;">Your account security has been updated</p>
</div>
<div style="padding: 20px; background-color: #f9fafb;">
<p>${greeting}</p>
<p>Your password has been successfully changed on <strong>${formattedTime}</strong>${location}${device}.</p>
<div style="background-color: #D1FAE5; border-left: 4px solid #10B981; padding: 15px; margin: 20px 0;">
<p style="margin: 0; color: #065F46;"><strong>✅ Security Update Confirmed</strong></p>
<p style="margin: 5px 0 0 0; color: #047857;">Your account is now secured with your new password.</p>
</div>
<p><strong>What this means:</strong></p>
<ul style="color: #374151;">
<li>Your new password is now active</li>
<li>All active sessions remain valid</li>
<li>You can continue using your account normally</li>
</ul>
<div style="background-color: #FEF3C7; border-left: 4px solid #F59E0B; padding: 15px; margin: 20px 0;">
<p style="margin: 0; color: #92400E;"><strong>⚠️ Didn't make this change?</strong></p>
<p style="margin: 5px 0 0 0; color: #B45309;">If you didn't change your password, please contact our support team immediately.</p>
</div>
<p>For your security, we recommend:</p>
<ul style="color: #374151;">
<li>Using a strong, unique password</li>
<li>Enabling two-factor authentication if available</li>
<li>Regularly updating your password</li>
<li>Not sharing your login credentials</li>
</ul>
<hr style="border: none; border-top: 1px solid #E5E7EB; margin: 30px 0;">
<p style="color: #6B7280; font-size: 14px;">
This is an automated security notification from Ideas Media Company.<br>
If you have any questions, please contact our support team.
</p>
</div>
</div>
`;
const text = `${greeting}
Your password has been successfully changed on ${formattedTime}${location}${device}.
✅ Security Update Confirmed
Your account is now secured with your new password.
What this means:
- Your new password is now active
- All active sessions remain valid
- You can continue using your account normally
⚠️ Didn't make this change?
If you didn't change your password, please contact our support team immediately.
For your security, we recommend:
- Using a strong, unique password
- Enabling two-factor authentication if available
- Regularly updating your password
- Not sharing your login credentials
This is an automated security notification from Ideas Media Company.
If you have any questions, please contact our support team.`;
return { html, text };
}
export function buildWelcomeEmail({ name, email }) {
const greeting = name ? `Welcome ${name}!` : 'Welcome!';
const html = `
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<div style="background-color: #A24CF3; color: white; padding: 20px; text-align: center;">
<h1 style="margin: 0;">${greeting}</h1>
<p style="margin: 10px 0 0 0;">Welcome to IDEAS MEDIA COMPANY</p>
</div>
<div style="padding: 30px 20px;">
<p>Thank you for joining IDEAS MEDIA COMPANY! We're excited to have you as part of our community.</p>
<h3 style="color: #A24CF3;">What's Next?</h3>
<ul style="line-height: 1.6;">
<li><strong>Complete your profile</strong> - Add your details and preferences</li>
<li><strong>Verify your ID</strong> - Submit your NIN or Driver's License for account verification</li>
<li><strong>Explore our services</strong> - Browse photography, equipment rental, and more</li>
<li><strong>Book your first session</strong> - Ready to capture amazing moments?</li>
</ul>
<div style="background-color: #f8f9fa; padding: 20px; border-radius: 8px; margin: 20px 0;">
<h4 style="color: #A24CF3; margin-top: 0;">Need Help?</h4>
<p style="margin-bottom: 0;">Our support team is here to help! Contact us anytime for assistance with your account or bookings.</p>
</div>
<p style="margin-top: 30px;">
Best regards,<br>
<strong>IDEAS MEDIA COMPANY Team</strong>
</p>
</div>
<div style="background-color: #f8f9fa; padding: 15px; text-align: center; color: #666; font-size: 12px;">
<p style="margin: 0;">© 2024 IDEAS MEDIA COMPANY. All rights reserved.</p>
</div>
</div>
`;
const text = `${greeting}\n\nThank you for joining IDEAS MEDIA COMPANY! We're excited to have you as part of our community.\n\nWhat's Next?\n- Complete your profile\n- Verify your ID\n- Explore our services\n- Book your first session\n\nOur support team is here to help! Contact us anytime for assistance.\n\nBest regards,\nIDEAS MEDIA COMPANY Team`;
return { html, text };
}
export function buildBookingConfirmationEmail({ name, booking, product, client }) {
const greeting = name ? `Hi ${name},` : 'Hello,';
const bookingDate = new Date(booking.date).toLocaleDateString('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
});
const html = `
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<div style="background-color: #A24CF3; color: white; padding: 20px; text-align: center;">
<h1 style="margin: 0;">Booking Confirmed!</h1>
<p style="margin: 10px 0 0 0;">Your session is all set</p>
</div>
<div style="padding: 30px 20px;">
<p>${greeting}</p>
<p>Great news! Your booking has been confirmed. Here are the details:</p>
<div style="background-color: #f8f9fa; padding: 20px; border-radius: 8px; margin: 20px 0;">
<h3 style="color: #A24CF3; margin-top: 0;">Booking Details</h3>
<table style="width: 100%; border-collapse: collapse;">
<tr style="border-bottom: 1px solid #eee;">
<td style="padding: 8px 0; font-weight: bold; width: 30%;">Service:</td>
<td style="padding: 8px 0;">${product?.name || 'Photography Session'}</td>
</tr>
<tr style="border-bottom: 1px solid #eee;">
<td style="padding: 8px 0; font-weight: bold;">Date:</td>
<td style="padding: 8px 0;">${bookingDate}</td>
</tr>
<tr style="border-bottom: 1px solid #eee;">
<td style="padding: 8px 0; font-weight: bold;">Time:</td>
<td style="padding: 8px 0;">${booking.time}</td>
</tr>
<tr style="border-bottom: 1px solid #eee;">
<td style="padding: 8px 0; font-weight: bold;">Duration:</td>
<td style="padding: 8px 0;">${booking.duration} hour(s)</td>
</tr>
<tr style="border-bottom: 1px solid #eee;">
<td style="padding: 8px 0; font-weight: bold;">Location:</td>
<td style="padding: 8px 0;">${booking.location?.type === 'studio' ? 'Studio' : booking.location?.type === 'outdoor' ? 'Outdoor' : 'Client Location'}</td>
</tr>
<tr>
<td style="padding: 8px 0; font-weight: bold;">Total Amount:</td>
<td style="padding: 8px 0; color: #A24CF3; font-weight: bold;">₦${booking.totalAmount?.toLocaleString()}</td>
</tr>
</table>
</div>
${booking.notes ? `
<div style="background-color: #fff3cd; padding: 15px; border-radius: 8px; margin: 20px 0;">
<h4 style="color: #856404; margin-top: 0;">Special Notes:</h4>
<p style="margin-bottom: 0; color: #856404;">${booking.notes}</p>
</div>
` : ''}
<h3 style="color: #A24CF3;">What to Expect:</h3>
<ul style="line-height: 1.6;">
<li>Our team will contact you 24 hours before your session</li>
<li>Please arrive 15 minutes early for preparation</li>
<li>Bring any specific props or outfits you discussed</li>
<li>Payment can be made before or after the session</li>
</ul>
<div style="background-color: #d1ecf1; padding: 20px; border-radius: 8px; margin: 20px 0;">
<h4 style="color: #0c5460; margin-top: 0;">Need to Make Changes?</h4>
<p style="margin-bottom: 0; color: #0c5460;">Contact us at least 24 hours in advance to reschedule or modify your booking.</p>
</div>
<p style="margin-top: 30px;">
We can't wait to work with you!<br>
<strong>IDEAS MEDIA COMPANY Team</strong>
</p>
</div>
<div style="background-color: #f8f9fa; padding: 15px; text-align: center; color: #666; font-size: 12px;">
<p style="margin: 0;">© 2024 IDEAS MEDIA COMPANY. All rights reserved.</p>
</div>
</div>
`;
const text = `${greeting}\n\nGreat news! Your booking has been confirmed.\n\nBooking Details:\n- Service: ${product?.name || 'Photography Session'}\n- Date: ${bookingDate}\n- Time: ${booking.time}\n- Duration: ${booking.duration} hour(s)\n- Location: ${booking.location?.type}\n- Total Amount: ₦${booking.totalAmount?.toLocaleString()}\n\n${booking.notes ? `Special Notes: ${booking.notes}\n\n` : ''}What to Expect:\n- Our team will contact you 24 hours before\n- Arrive 15 minutes early\n- Bring discussed props/outfits\n- Payment before or after session\n\nWe can't wait to work with you!\nIDEAS MEDIA COMPANY Team`;
return { html, text };
}
export function buildIDVerificationStatusEmail({ name, type, status, reason }) {
const greeting = name ? `Hi ${name},` : 'Hello,';
const documentType = type === 'nin' ? 'NIN' : 'Driver\'s License';
let statusMessage, statusColor, statusIcon;
if (status === 'verified') {
statusMessage = `Your ${documentType} verification has been approved!`;
statusColor = '#28a745';
statusIcon = '✅';
} else if (status === 'rejected') {
statusMessage = `Your ${documentType} verification was not approved.`;
statusColor = '#dc3545';
statusIcon = '❌';
}
const html = `
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<div style="background-color: ${statusColor}; color: white; padding: 20px; text-align: center;">
<h1 style="margin: 0;">${statusIcon} Verification Update</h1>
<p style="margin: 10px 0 0 0;">${documentType} Verification Status</p>
</div>
<div style="padding: 30px 20px;">
<p>${greeting}</p>
<p><strong>${statusMessage}</strong></p>
${status === 'verified' ? `
<div style="background-color: #d4edda; padding: 20px; border-radius: 8px; margin: 20px 0;">
<h3 style="color: #155724; margin-top: 0;">✅ Verification Approved</h3>
<p style="margin-bottom: 0; color: #155724;">
Congratulations! Your ${documentType} has been successfully verified.
You now have full access to all our services and can proceed with bookings that require ID verification.
</p>
</div>
<h3 style="color: #A24CF3;">What's Next?</h3>
<ul style="line-height: 1.6;">
<li>Browse and book our premium services</li>
<li>Rent professional equipment</li>
<li>Access exclusive member benefits</li>
<li>Enjoy faster booking processes</li>
</ul>
` : `
<div style="background-color: #f8d7da; padding: 20px; border-radius: 8px; margin: 20px 0;">
<h3 style="color: #721c24; margin-top: 0;">❌ Verification Not Approved</h3>
<p style="color: #721c24; margin-bottom: 10px;">
We were unable to verify your ${documentType} at this time.
</p>
${reason ? `<p style="color: #721c24; margin-bottom: 0;"><strong>Reason:</strong> ${reason}</p>` : ''}
</div>
<h3 style="color: #A24CF3;">Next Steps:</h3>
<ul style="line-height: 1.6;">
<li>Review the feedback provided above</li>
<li>Ensure your document photo is clear and readable</li>
<li>Make sure all information matches your profile</li>
<li>Resubmit your verification with corrections</li>
</ul>
<div style="background-color: #fff3cd; padding: 15px; border-radius: 8px; margin: 20px 0;">
<h4 style="color: #856404; margin-top: 0;">Need Help?</h4>
<p style="margin-bottom: 0; color: #856404;">
Our support team is here to help! Contact us if you need assistance with your verification.
</p>
</div>
`}
<p style="margin-top: 30px;">
Best regards,<br>
<strong>IDEAS MEDIA COMPANY Team</strong>
</p>
</div>
<div style="background-color: #f8f9fa; padding: 15px; text-align: center; color: #666; font-size: 12px;">
<p style="margin: 0;">© 2024 IDEAS MEDIA COMPANY. All rights reserved.</p>
</div>
</div>
`;
const text = `${greeting}\n\n${statusMessage}\n\n${status === 'verified' ?
`Congratulations! Your ${documentType} has been successfully verified. You now have full access to all our services.\n\nWhat's Next:\n- Browse and book premium services\n- Rent professional equipment\n- Access exclusive member benefits\n- Enjoy faster booking processes` :
`We were unable to verify your ${documentType} at this time.\n${reason ? `\nReason: ${reason}\n` : ''}\nNext Steps:\n- Review the feedback\n- Ensure document is clear and readable\n- Make sure information matches your profile\n- Resubmit with corrections\n\nNeed help? Contact our support team.`
}\n\nBest regards,\nIDEAS MEDIA COMPANY Team`;
return { html, text };
}
export function buildPaymentConfirmationEmail({ name, order, booking, paymentMethod, transactionId }) {
const greeting = name ? `Hi ${name},` : 'Hello,';
const paymentDate = new Date().toLocaleDateString('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
});
const html = `
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<div style="background-color: #28a745; color: white; padding: 20px; text-align: center;">
<h1 style="margin: 0;">💳 Payment Confirmed</h1>
<p style="margin: 10px 0 0 0;">Thank you for your payment</p>
</div>
<div style="padding: 30px 20px;">
<p>${greeting}</p>
<p>Your payment has been successfully processed. Here are your payment details:</p>
<div style="background-color: #d4edda; padding: 20px; border-radius: 8px; margin: 20px 0;">
<h3 style="color: #155724; margin-top: 0;">✅ Payment Successful</h3>
<table style="width: 100%; border-collapse: collapse;">
<tr style="border-bottom: 1px solid #c3e6cb;">
<td style="padding: 8px 0; font-weight: bold; width: 40%;">Amount Paid:</td>
<td style="padding: 8px 0; color: #155724; font-weight: bold;">₦${(order?.totalAmount || booking?.totalAmount)?.toLocaleString()}</td>
</tr>
<tr style="border-bottom: 1px solid #c3e6cb;">
<td style="padding: 8px 0; font-weight: bold;">Payment Method:</td>
<td style="padding: 8px 0;">${paymentMethod || 'Online Payment'}</td>
</tr>
<tr style="border-bottom: 1px solid #c3e6cb;">
<td style="padding: 8px 0; font-weight: bold;">Transaction ID:</td>
<td style="padding: 8px 0; font-family: monospace;">${transactionId || 'N/A'}</td>
</tr>
<tr>
<td style="padding: 8px 0; font-weight: bold;">Payment Date:</td>
<td style="padding: 8px 0;">${paymentDate}</td>
</tr>
</table>
</div>
${booking ? `
<div style="background-color: #f8f9fa; padding: 20px; border-radius: 8px; margin: 20px 0;">
<h3 style="color: #A24CF3; margin-top: 0;">Booking Details</h3>
<p><strong>Service:</strong> ${booking.product?.name || 'Photography Session'}</p>
<p><strong>Date:</strong> ${new Date(booking.date).toLocaleDateString()}</p>
<p><strong>Time:</strong> ${booking.time}</p>
<p><strong>Status:</strong> <span style="color: #28a745;">Confirmed & Paid</span></p>
</div>
` : ''}
<h3 style="color: #A24CF3;">What Happens Next?</h3>
<ul style="line-height: 1.6;">
${booking ? '<li>Your booking is now confirmed and fully paid</li>' : ''}
<li>You'll receive a receipt for your records</li>
<li>Our team will contact you with further details</li>
<li>Keep this email for your reference</li>
</ul>
<div style="background-color: #d1ecf1; padding: 20px; border-radius: 8px; margin: 20px 0;">
<h4 style="color: #0c5460; margin-top: 0;">Questions About Your Payment?</h4>
<p style="margin-bottom: 0; color: #0c5460;">
If you have any questions about this payment or need a formal receipt,
please contact our support team with your transaction ID.
</p>
</div>
<p style="margin-top: 30px;">
Thank you for choosing IDEAS MEDIA COMPANY!<br>
<strong>IDEAS MEDIA COMPANY Team</strong>
</p>
</div>
<div style="background-color: #f8f9fa; padding: 15px; text-align: center; color: #666; font-size: 12px;">
<p style="margin: 0;">© 2024 IDEAS MEDIA COMPANY. All rights reserved.</p>
</div>
</div>
`;
const text = `${greeting}\n\nYour payment has been successfully processed.\n\nPayment Details:\n- Amount: ₦${(order?.totalAmount || booking?.totalAmount)?.toLocaleString()}\n- Method: ${paymentMethod || 'Online Payment'}\n- Transaction ID: ${transactionId || 'N/A'}\n- Date: ${paymentDate}\n\n${booking ? `Booking Details:\n- Service: ${booking.product?.name}\n- Date: ${new Date(booking.date).toLocaleDateString()}\n- Time: ${booking.time}\n- Status: Confirmed & Paid\n\n` : ''}What Happens Next:\n${booking ? '- Your booking is confirmed and paid\n' : ''}- You'll receive a receipt\n- Our team will contact you\n- Keep this email for reference\n\nThank you for choosing IDEAS MEDIA COMPANY!\nIDEAS MEDIA COMPANY Team`;
return { html, text };
}
export function buildReminderEmail({ name, booking, product, reminderType = '24h' }) {
const greeting = name ? `Hi ${name},` : 'Hello,';
const bookingDate = new Date(booking.date).toLocaleDateString('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
});
const reminderText = reminderType === '24h' ? 'tomorrow' : 'soon';
const reminderTitle = reminderType === '24h' ? 'Session Tomorrow' : 'Upcoming Session';
const html = `
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<div style="background-color: #ffc107; color: #212529; padding: 20px; text-align: center;">
<h1 style="margin: 0;">📅 ${reminderTitle}</h1>
<p style="margin: 10px 0 0 0;">Don't forget about your session ${reminderText}</p>
</div>
<div style="padding: 30px 20px;">
<p>${greeting}</p>
<p>This is a friendly reminder about your upcoming photography session with IDEAS MEDIA COMPANY.</p>
<div style="background-color: #fff3cd; padding: 20px; border-radius: 8px; margin: 20px 0;">
<h3 style="color: #856404; margin-top: 0;">📍 Session Details</h3>
<table style="width: 100%; border-collapse: collapse;">
<tr style="border-bottom: 1px solid #ffeaa7;">
<td style="padding: 8px 0; font-weight: bold; width: 30%;">Service:</td>
<td style="padding: 8px 0;">${product?.name || 'Photography Session'}</td>
</tr>
<tr style="border-bottom: 1px solid #ffeaa7;">
<td style="padding: 8px 0; font-weight: bold;">Date:</td>
<td style="padding: 8px 0; font-weight: bold; color: #856404;">${bookingDate}</td>
</tr>
<tr style="border-bottom: 1px solid #ffeaa7;">
<td style="padding: 8px 0; font-weight: bold;">Time:</td>
<td style="padding: 8px 0; font-weight: bold; color: #856404;">${booking.time}</td>
</tr>
<tr style="border-bottom: 1px solid #ffeaa7;">
<td style="padding: 8px 0; font-weight: bold;">Duration:</td>
<td style="padding: 8px 0;">${booking.duration} hour(s)</td>
</tr>
<tr>
<td style="padding: 8px 0; font-weight: bold;">Location:</td>
<td style="padding: 8px 0;">${booking.location?.type === 'studio' ? 'Studio' : booking.location?.type === 'outdoor' ? 'Outdoor' : 'Client Location'}</td>
</tr>
</table>
</div>
<h3 style="color: #A24CF3;">Preparation Checklist:</h3>
<ul style="line-height: 1.6;">
<li>✅ Arrive 15 minutes early for setup</li>
<li>✅ Bring any discussed props or special items</li>
<li>✅ Wear or bring your planned outfits</li>
<li>✅ Ensure your phone is charged for communication</li>
<li>✅ Prepare any specific shots or poses you want</li>
</ul>
${booking.notes ? `
<div style="background-color: #e2e3e5; padding: 15px; border-radius: 8px; margin: 20px 0;">
<h4 style="color: #383d41; margin-top: 0;">📝 Special Notes:</h4>
<p style="margin-bottom: 0; color: #383d41;">${booking.notes}</p>
</div>
` : ''}
<div style="background-color: #d1ecf1; padding: 20px; border-radius: 8px; margin: 20px 0;">
<h4 style="color: #0c5460; margin-top: 0;">Need to Reschedule?</h4>
<p style="margin-bottom: 0; color: #0c5460;">
If you need to make any changes, please contact us as soon as possible.
We appreciate at least 24 hours notice for rescheduling.
</p>
</div>
<p style="margin-top: 30px;">
We're excited to work with you ${reminderText}!<br>
<strong>IDEAS MEDIA COMPANY Team</strong>
</p>
</div>
<div style="background-color: #f8f9fa; padding: 15px; text-align: center; color: #666; font-size: 12px;">
<p style="margin: 0;">© 2024 IDEAS MEDIA COMPANY. All rights reserved.</p>
</div>
</div>
`;
const text = `${greeting}\n\nThis is a friendly reminder about your upcoming photography session ${reminderText}.\n\nSession Details:\n- Service: ${product?.name}\n- Date: ${bookingDate}\n- Time: ${booking.time}\n- Duration: ${booking.duration} hour(s)\n- Location: ${booking.location?.type}\n\n${booking.notes ? `Special Notes: ${booking.notes}\n\n` : ''}Preparation Checklist:\n- Arrive 15 minutes early\n- Bring discussed props\n- Wear/bring planned outfits\n- Ensure phone is charged\n- Prepare specific shots you want\n\nNeed to reschedule? Contact us ASAP with at least 24 hours notice.\n\nWe're excited to work with you ${reminderText}!\nIDEAS MEDIA COMPANY Team`;
return { html, text };
}
export function buildErrorNotificationEmail({
errorId,
errorMessage,
errorStack,
componentStack,
pwaType,
url,
userId,
userEmail,
timestamp,
}) {
const html = `
<div style="font-family: 'Segoe UI', Arial, sans-serif; max-width: 800px; margin: 0 auto; background-color: #f9fafb;">
<!-- Header -->
<div style="background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%); color: white; padding: 30px; text-align: center; border-radius: 8px 8px 0 0;">
<h1 style="margin: 0; font-size: 28px; font-weight: bold;">🚨 Error Boundary Triggered</h1>
<p style="margin: 10px 0 0 0; font-size: 16px; opacity: 0.9;">Critical error detected in ${pwaType?.toUpperCase?.()} PWA</p>
</div>
<!-- Error Summary -->
<div style="background-color: white; padding: 25px; border-left: 4px solid #dc2626;">
<h2 style="margin: 0 0 15px 0; color: #1f2937; font-size: 20px;">Error Summary</h2>
<table style="width: 100%; border-collapse: collapse;">
<tr style="border-bottom: 1px solid #e5e7eb;">
<td style="padding: 12px 0; color: #6b7280; font-weight: 600; width: 120px;">Error ID:</td>
<td style="padding: 12px 0; color: #1f2937; font-family: 'Courier New', monospace; font-size: 14px;">${errorId}</td>
</tr>
<tr style="border-bottom: 1px solid #e5e7eb;">
<td style="padding: 12px 0; color: #6b7280; font-weight: 600;">PWA Type:</td>
<td style="padding: 12px 0;">
<span style="background-color: ${pwaType?.toLowerCase() === 'admin' ? '#7c3aed' : '#0891b2'}; color: white; padding: 4px 12px; border-radius: 12px; font-size: 12px; font-weight: 600;">
${pwaType?.toUpperCase?.()}
</span>
</td>
</tr>
<tr style="border-bottom: 1px solid #e5e7eb;">
<td style="padding: 12px 0; color: #6b7280; font-weight: 600;">Timestamp:</td>
<td style="padding: 12px 0; color: #1f2937;">${timestamp}</td>
</tr>
<tr style="border-bottom: 1px solid #e5e7eb;">
<td style="padding: 12px 0; color: #6b7280; font-weight: 600;">URL:</td>
<td style="padding: 12px 0; color: #2563eb; word-break: break-all;">${url}</td>
</tr>
<tr style="border-bottom: 1px solid #e5e7eb;">
<td style="padding: 12px 0; color: #6b7280; font-weight: 600;">User:</td>
<td style="padding: 12px 0; color: #1f2937;">${userEmail || 'Anonymous'} ${userId ? `(ID: ${userId})` : ''}</td>
</tr>
</table>
</div>
<!-- Error Message -->
<div style="background-color: white; padding: 25px; margin-top: 2px;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
<h3 style="margin: 0; color: #1f2937; font-size: 16px;">Error Message</h3>
<button onclick="navigator.clipboard.writeText(\`${errorMessage?.replace(/`/g, '\\`')}\`)" style="background-color: #f3f4f6; border: 1px solid #d1d5db; padding: 6px 12px; border-radius: 4px; cursor: pointer; font-size: 12px; color: #374151;">
📋 Copy
</button>
</div>
<pre style="background-color: #fef2f2; border: 1px solid #fecaca; border-radius: 6px; padding: 16px; margin: 0; overflow-x: auto; font-family: 'Courier New', monospace; font-size: 13px; color: #991b1b; line-height: 1.6;">${errorMessage}</pre>
</div>
<!-- Stack Trace -->
<div style="background-color: white; padding: 25px; margin-top: 2px;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
<h3 style="margin: 0; color: #1f2937; font-size: 16px;">Stack Trace</h3>
<button onclick="navigator.clipboard.writeText(\`${errorStack?.replace(/`/g, '\\`')}\`)" style="background-color: #f3f4f6; border: 1px solid #d1d5db; padding: 6px 12px; border-radius: 4px; cursor: pointer; font-size: 12px; color: #374151;">
📋 Copy
</button>
</div>
<pre style="background-color: #f9fafb; border: 1px solid #e5e7eb; border-radius: 6px; padding: 16px; margin: 0; overflow-x: auto; font-family: 'Courier New', monospace; font-size: 12px; color: #374151; line-height: 1.6; max-height: 400px; overflow-y: auto;">${errorStack}</pre>
</div>
<!-- Component Stack -->
<div style="background-color: white; padding: 25px; margin-top: 2px; border-radius: 0 0 8px 8px;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
<h3 style="margin: 0; color: #1f2937; font-size: 16px;">Component Stack</h3>
<button onclick="navigator.clipboard.writeText(\`${componentStack?.replace(/`/g, '\\`')}\`)" style="background-color: #f3f4f6; border: 1px solid #d1d5db; padding: 6px 12px; border-radius: 4px; cursor: pointer; font-size: 12px; color: #374151;">
📋 Copy
</button>
</div>
<pre style="background-color: #eff6ff; border: 1px solid #bfdbfe; border-radius: 6px; padding: 16px; margin: 0; overflow-x: auto; font-family: 'Courier New', monospace; font-size: 12px; color: #1e40af; line-height: 1.6;">${componentStack}</pre>
</div>
<!-- Footer -->
<div style="background-color: #f3f4f6; padding: 20px; text-align: center; margin-top: 2px; border-radius: 0 0 8px 8px;">
<p style="margin: 0; color: #6b7280; font-size: 14px;">
This is an automated error notification from <strong>IDEAS MEDIA COMPANY</strong>
</p>
<p style="margin: 8px 0 0 0; color: #9ca3af; font-size: 12px;">
Please investigate and resolve this issue as soon as possible.
</p>
</div>
</div>
`;
const text = `🚨 ERROR BOUNDARY TRIGGERED
Critical error detected in ${pwaType?.toUpperCase?.()} PWA
=== ERROR SUMMARY ===
Error ID: ${errorId}
PWA Type: ${pwaType?.toUpperCase?.()}
Timestamp: ${timestamp}
URL: ${url}
User: ${userEmail || 'Anonymous'} ${userId ? `(ID: ${userId})` : ''}
=== ERROR MESSAGE ===
${errorMessage}
=== STACK TRACE ===
${errorStack}
=== COMPONENT STACK ===
${componentStack}
---
This is an automated error notification from IDEAS MEDIA COMPANY.
Please investigate and resolve this issue as soon as possible.`;
return { html, text };
}