import type { APIRoute } from 'astro'; import puppeteer from 'puppeteer'; export const GET: APIRoute = async ({ url }) => { try { const searchParams = new URL(url).searchParams; const status = searchParams.get('status') || 'submitted'; const width = parseInt(searchParams.get('width') || '600'); const height = parseInt(searchParams.get('height') || '200'); const emailOptimized = searchParams.get('email') === 'true'; // New email optimization flag console.log('🎨 Generating status image for:', { status, width, height, emailOptimized }); // Generate status progress bar HTML (email-optimized version for transparent backgrounds) function generateEmailOptimizedProgressBar(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); return `

Request Progress

${statuses.map((statusName, index) => { const isActive = index <= currentIndex; const isCurrent = statusName === currentStatus; let backgroundColor, textColor; if (isCurrent) { if (statusName === 'rejected') { backgroundColor = '#ef4444'; textColor = 'white'; } else if (statusName === 'paid') { backgroundColor = '#10b981'; textColor = 'white'; } else if (statusName === 'in_progress') { backgroundColor = '#f59e0b'; textColor = 'white'; } else { backgroundColor = '#3b82f6'; textColor = 'white'; } } else if (isActive) { backgroundColor = '#e2e8f0'; textColor = '#475569'; } else { backgroundColor = '#f8fafc'; textColor = '#94a3b8'; } const labelColor = isCurrent ? (statusName === 'rejected' ? '#ef4444' : statusName === 'paid' ? '#10b981' : statusName === 'in_progress' ? '#f59e0b' : '#3b82f6') : isActive ? '#475569' : '#94a3b8'; return `
${statusIcons[statusName]}
${statusLabels[statusName]}
`; }).join('')}
`; } // Generate status progress bar HTML (based on the email template) function generateStatusProgressBarHTML(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'; } // Status circle progressBarHtml += ` `; // Connecting line (except for the last status) if (index < statuses.length - 1) { const nextIsActive = (index + 1) <= currentIndex; const connectionColor = nextIsActive ? lineColor : '#e2e8f0'; progressBarHtml += ` `; } }); progressBarHtml += `
${statusIcons[status]}
${statusLabels[status]}
`; return progressBarHtml; } // Choose which HTML to use based on email optimization flag const html = emailOptimized ? generateEmailOptimizedProgressBar(status) : generateStatusProgressBarHTML(status); // Launch Puppeteer with high quality settings const browser = await puppeteer.launch({ headless: true, args: [ '--no-sandbox', '--disable-setuid-sandbox', '--force-device-scale-factor=2' // Higher DPI for better quality ] }); const page = await browser.newPage(); // Set high-resolution viewport for better quality await page.setViewport({ width: width * 2, // Double resolution for crisp images height: height * 2, deviceScaleFactor: 2 }); // Set HTML content await page.setContent(html, { waitUntil: 'networkidle0' }); // Take high-quality screenshot with transparent background const screenshot = await page.screenshot({ type: 'png', fullPage: false, omitBackground: true, // Transparent background clip: { x: 0, y: 0, width: width * 2, height: height * 2 } }); await browser.close(); console.log('✅ Status image generated successfully'); return new Response(screenshot, { headers: { 'Content-Type': 'image/png', 'Cache-Control': 'public, max-age=3600', }, }); } catch (error) { console.error('❌ Error generating status image:', error); return new Response('Error generating image', { status: 500 }); } };