diff --git a/src/pages/api/email/send-reimbursement-email.ts b/src/pages/api/email/send-reimbursement-email.ts index 13b0d01..5b29bcd 100644 --- a/src/pages/api/email/send-reimbursement-email.ts +++ b/src/pages/api/email/send-reimbursement-email.ts @@ -177,6 +177,125 @@ async function sendStatusChangeEmail(pb: any, resend: any, fromEmail: string, re status: data.newStatus }); + // Helper function to generate status progress bar HTML + function generateStatusProgressBar(currentStatus: string): string { + const statusOrder = ['submitted', 'under_review', 'approved', 'in_progress', 'paid']; + const rejectedStatus = ['submitted', 'under_review', 'rejected']; + + const isRejected = currentStatus === 'rejected'; + const statuses = isRejected ? rejectedStatus : statusOrder; + + const statusIcons: Record = { + submitted: '→', + under_review: '○', + approved: '✓', + rejected: '✗', + in_progress: '◐', + paid: '✓' + }; + + const statusLabels: Record = { + submitted: 'Submitted', + under_review: 'Under Review', + approved: 'Approved', + rejected: 'Rejected', + in_progress: 'In Progress', + paid: 'Paid' + }; + + const currentIndex = statuses.indexOf(currentStatus); + + let progressBarHtml = ` +
+

Request Progress

+
+
+ `; + + statuses.forEach((status, index) => { + const isActive = index <= currentIndex; + const isCurrent = status === currentStatus; + + let backgroundColor, textColor, lineColor; + if (isCurrent) { + if (status === 'rejected') { + backgroundColor = '#ef4444'; + textColor = 'white'; + lineColor = '#ef4444'; + } else if (status === 'paid') { + backgroundColor = '#10b981'; + textColor = 'white'; + lineColor = '#10b981'; + } else if (status === 'in_progress') { + backgroundColor = '#f59e0b'; + textColor = 'white'; + lineColor = '#f59e0b'; + } else { + backgroundColor = '#3b82f6'; + textColor = 'white'; + lineColor = '#3b82f6'; + } + } else if (isActive) { + backgroundColor = '#e2e8f0'; + textColor = '#475569'; + lineColor = '#cbd5e1'; + } else { + backgroundColor = '#f8fafc'; + textColor = '#94a3b8'; + lineColor = '#e2e8f0'; + } + + progressBarHtml += ` +
+
+ ${statusIcons[status]} +
+ + ${statusLabels[status]} + +
+ `; + + // Add colored line segment for active states + if (index < statuses.length - 1 && isActive) { + progressBarHtml += ` +
+ `; + } + }); + + progressBarHtml += ` +
+
+ `; + + return progressBarHtml; + } + const html = ` @@ -195,6 +314,8 @@ async function sendStatusChangeEmail(pb: any, resend: any, fromEmail: string, re

Hello ${user.name},

Your reimbursement request "${reimbursement.title}" has been updated.

+ ${generateStatusProgressBar(data.newStatus)} +
Status: @@ -259,7 +380,7 @@ async function sendStatusChangeEmail(pb: any, resend: any, fromEmail: string, re `; - console.log('📤 Attempting to send email via Resend...'); + console.log('Attempting to send email via Resend...'); const result = await resend.emails.send({ from: fromEmail, to: [user.email], @@ -268,11 +389,11 @@ async function sendStatusChangeEmail(pb: any, resend: any, fromEmail: string, re html, }); - console.log('✅ Resend response:', result); - console.log('🎉 Status change email sent successfully!'); + console.log('Resend response:', result); + console.log('Status change email sent successfully!'); return true; } catch (error) { - console.error('❌ Failed to send status change email:', error); + console.error('Failed to send status change email:', error); console.error('Error details:', { name: error instanceof Error ? error.name : 'Unknown', message: error instanceof Error ? error.message : String(error), @@ -284,7 +405,7 @@ async function sendStatusChangeEmail(pb: any, resend: any, fromEmail: string, re async function sendCommentEmail(pb: any, resend: any, fromEmail: string, replyToEmail: string, data: any): Promise { try { - console.log('💬 Starting comment email process...'); + console.log('Starting comment email process...'); console.log('Comment data received:', { reimbursementId: data.reimbursementId, commentByUserId: data.commentByUserId, @@ -294,49 +415,49 @@ async function sendCommentEmail(pb: any, resend: any, fromEmail: string, replyTo // Don't send emails for private comments if (data.isPrivate) { - console.log('🔒 Comment is private, skipping email notification'); + console.log('Comment is private, skipping email notification'); return true; } // Get reimbursement details - console.log('🔍 Fetching reimbursement details for:', data.reimbursementId); + console.log('Fetching reimbursement details for:', data.reimbursementId); const reimbursement = await pb.collection('reimbursement').getOne(data.reimbursementId); - console.log('✅ Reimbursement fetched:', { + console.log('Reimbursement fetched:', { id: reimbursement.id, title: reimbursement.title, submitted_by: reimbursement.submitted_by }); // Get submitter user details - console.log('👤 Fetching submitter user details for:', reimbursement.submitted_by); + console.log('Fetching submitter user details for:', reimbursement.submitted_by); const user = await pb.collection('users').getOne(reimbursement.submitted_by); if (!user || !user.email) { - console.error('❌ User not found or no email:', reimbursement.submitted_by); + console.error('User not found or no email:', reimbursement.submitted_by); return false; } - console.log('✅ Submitter user fetched:', { + console.log('Submitter user fetched:', { id: user.id, name: user.name, email: user.email }); // Get commenter user name - console.log('👤 Fetching commenter user details for:', data.commentByUserId); + console.log('Fetching commenter user details for:', data.commentByUserId); let commentByName = 'Unknown User'; try { const commentByUser = await pb.collection('users').getOne(data.commentByUserId); commentByName = commentByUser?.name || 'Unknown User'; - console.log('✅ Commenter user fetched:', { + console.log('Commenter user fetched:', { id: commentByUser?.id, name: commentByName }); } catch (error) { - console.warn('⚠️ Could not get commenter user name:', error); + console.warn('Could not get commenter user name:', error); } const subject = `New Comment on Reimbursement: ${reimbursement.title}`; - console.log('📝 Comment email details:', { + console.log('Comment email details:', { to: user.email, subject, commentBy: commentByName, @@ -401,7 +522,7 @@ async function sendCommentEmail(pb: any, resend: any, fromEmail: string, replyTo `; - console.log('📤 Attempting to send comment email via Resend...'); + console.log('Attempting to send comment email via Resend...'); const result = await resend.emails.send({ from: fromEmail, to: [user.email], @@ -410,11 +531,11 @@ async function sendCommentEmail(pb: any, resend: any, fromEmail: string, replyTo html, }); - console.log('✅ Resend comment email response:', result); - console.log('🎉 Comment email sent successfully!'); + console.log('Resend comment email response:', result); + console.log('Comment email sent successfully!'); return true; } catch (error) { - console.error('❌ Failed to send comment email:', error); + console.error('Failed to send comment email:', error); console.error('Comment email error details:', { name: error instanceof Error ? error.name : 'Unknown', message: error instanceof Error ? error.message : String(error), @@ -449,7 +570,7 @@ async function sendSubmissionEmail(pb: any, resend: any, fromEmail: string, repl
-

✅ Reimbursement Submitted Successfully

+

Reimbursement Submitted Successfully

@@ -523,7 +644,7 @@ async function sendSubmissionEmail(pb: any, resend: any, fromEmail: string, repl
-

📋 New Reimbursement Request

+

New Reimbursement Request

@@ -583,7 +704,7 @@ async function sendSubmissionEmail(pb: any, resend: any, fromEmail: string, repl
-

📋 Next Steps:

+

Next Steps:

  • Review the submitted receipts and documentation
  • Log into the reimbursement portal to approve or request changes
  • @@ -630,7 +751,7 @@ async function sendSubmissionEmail(pb: any, resend: any, fromEmail: string, repl async function sendTestEmail(resend: any, fromEmail: string, replyToEmail: string, email: string): Promise { try { - console.log('🧪 Starting test email process...'); + console.log('Starting test email process...'); console.log('Test email configuration:', { fromEmail, replyToEmail, @@ -650,7 +771,7 @@ async function sendTestEmail(resend: any, fromEmail: string, replyToEmail: strin
    -

    🧪 Test Email

    +

    Test Email

    @@ -659,7 +780,7 @@ async function sendTestEmail(resend: any, fromEmail: string, replyToEmail: strin

    If you receive this email, the notification system is working correctly!

    -

    ✅ Email delivery successful

    +

    Email delivery successful

    @@ -671,7 +792,7 @@ async function sendTestEmail(resend: any, fromEmail: string, replyToEmail: strin `; - console.log('📤 Sending test email via Resend...'); + console.log('Sending test email via Resend...'); const result = await resend.emails.send({ from: fromEmail, to: [email], @@ -680,11 +801,11 @@ async function sendTestEmail(resend: any, fromEmail: string, replyToEmail: strin html, }); - console.log('✅ Resend test email response:', result); - console.log('🎉 Test email sent successfully!'); + console.log('Resend test email response:', result); + console.log('Test email sent successfully!'); return true; } catch (error) { - console.error('❌ Failed to send test email:', error); + console.error('Failed to send test email:', error); console.error('Test email error details:', { name: error instanceof Error ? error.name : 'Unknown', message: error instanceof Error ? error.message : String(error),