Further work on the email background

This commit is contained in:
Corey Blais
2026-04-21 17:21:23 -04:00
parent e5e9477452
commit 36e074c1fd
+17 -1
View File
@@ -854,6 +854,14 @@ const getFlockPalLogoAttachment = () => {
}; };
}; };
const getEmailTrackPatternAttachment = () => ({
filename: 'flockpal-x-pattern.svg',
content: `<svg xmlns="http://www.w3.org/2000/svg" width="680" height="188" viewBox="0 0 680 188"><defs><linearGradient id="wash" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#fef5e7"/><stop offset=".52" stop-color="#e9ddba"/><stop offset="1" stop-color="#d9eadf"/></linearGradient><symbol id="track" viewBox="0 0 160 160"><rect x="66" y="12" width="28" height="136" rx="14" transform="rotate(30 80 80)"/><rect x="66" y="12" width="28" height="136" rx="14" transform="rotate(-30 80 80)"/></symbol></defs><rect width="680" height="188" fill="url(#wash)"/><g opacity=".68"><use href="#track" x="20" y="16" width="88" height="88" fill="#5bb3b7" transform="rotate(-12 64 60)"/><use href="#track" x="126" y="74" width="78" height="78" fill="#7eb773" transform="rotate(18 165 113)"/><use href="#track" x="232" y="20" width="104" height="104" fill="#f3a24a" transform="rotate(-26 284 72)"/><use href="#track" x="378" y="72" width="86" height="86" fill="#898b93" transform="rotate(28 421 115)"/><use href="#track" x="492" y="18" width="98" height="98" fill="#b9c945" transform="rotate(-18 541 67)"/><use href="#track" x="592" y="84" width="66" height="66" fill="#5bb3b7" transform="rotate(34 625 117)"/></g><g opacity=".32"><use href="#track" x="66" y="112" width="46" height="46" fill="#f3a24a" transform="rotate(36 89 135)"/><use href="#track" x="190" y="122" width="42" height="42" fill="#5bb3b7" transform="rotate(-20 211 143)"/><use href="#track" x="344" y="18" width="44" height="44" fill="#7eb773" transform="rotate(18 366 40)"/><use href="#track" x="474" y="126" width="48" height="48" fill="#f3a24a" transform="rotate(-34 498 150)"/><use href="#track" x="626" y="18" width="42" height="42" fill="#898b93" transform="rotate(22 647 39)"/></g></svg>`,
contentType: 'image/svg+xml',
cid: 'flockpal-x-pattern',
contentDisposition: 'inline' as const,
});
const parseDataImage = (dataUrl: string) => { const parseDataImage = (dataUrl: string) => {
const match = /^data:(image\/[a-zA-Z0-9.+-]+);base64,(.+)$/.exec(dataUrl); const match = /^data:(image\/[a-zA-Z0-9.+-]+);base64,(.+)$/.exec(dataUrl);
if (!match) { if (!match) {
@@ -1142,6 +1150,7 @@ const sendBirdMilestoneReminderNotification = async ({
const copy = buildBirdMilestoneReminderCopy(reminder); const copy = buildBirdMilestoneReminderCopy(reminder);
const attachments: NonNullable<SendMailOptions['attachments']> = []; const attachments: NonNullable<SendMailOptions['attachments']> = [];
const logoAttachment = getFlockPalLogoAttachment(); const logoAttachment = getFlockPalLogoAttachment();
const trackPatternAttachment = getEmailTrackPatternAttachment();
const uploadedBirdPhoto = reminder.photo_data_url ? parseDataImage(reminder.photo_data_url) : null; const uploadedBirdPhoto = reminder.photo_data_url ? parseDataImage(reminder.photo_data_url) : null;
const defaultBirdPhoto = uploadedBirdPhoto ? null : getDefaultBirdPhotoAttachment(); const defaultBirdPhoto = uploadedBirdPhoto ? null : getDefaultBirdPhotoAttachment();
const birdPhotoCid = uploadedBirdPhoto ? 'bird-photo' : defaultBirdPhoto ? defaultBirdPhoto.cid : ''; const birdPhotoCid = uploadedBirdPhoto ? 'bird-photo' : defaultBirdPhoto ? defaultBirdPhoto.cid : '';
@@ -1149,6 +1158,7 @@ const sendBirdMilestoneReminderNotification = async ({
if (logoAttachment) { if (logoAttachment) {
attachments.push(logoAttachment); attachments.push(logoAttachment);
} }
attachments.push(trackPatternAttachment);
if (uploadedBirdPhoto) { if (uploadedBirdPhoto) {
attachments.push({ attachments.push({
@@ -1191,7 +1201,10 @@ const sendBirdMilestoneReminderNotification = async ({
text: lines.join('\n'), text: lines.join('\n'),
attachments, attachments,
html: ` html: `
<div style="margin: 0; padding: 28px; background-color: #fef5e7; background-image: url('data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%22160%22 height=%22160%22 viewBox=%220 0 160 160%22%3E%3Cg fill=%22%235bb3b7%22 opacity=%220.18%22%3E%3Crect x=%2270%22 y=%2224%22 width=%2220%22 height=%22112%22 rx=%2210%22 transform=%22rotate(32 80 80)%22/%3E%3Crect x=%2270%22 y=%2224%22 width=%2220%22 height=%22112%22 rx=%2210%22 transform=%22rotate(-32 80 80)%22/%3E%3C/g%3E%3Cg fill=%22%23f3a24a%22 opacity=%220.12%22 transform=%22translate(88 18) scale(.48)%22%3E%3Crect x=%2270%22 y=%2224%22 width=%2220%22 height=%22112%22 rx=%2210%22 transform=%22rotate(32 80 80)%22/%3E%3Crect x=%2270%22 y=%2224%22 width=%2220%22 height=%22112%22 rx=%2210%22 transform=%22rotate(-32 80 80)%22/%3E%3C/g%3E%3Cg fill=%22%237eb773%22 opacity=%220.14%22 transform=%22translate(-26 92) scale(.56)%22%3E%3Crect x=%2270%22 y=%2224%22 width=%2220%22 height=%22112%22 rx=%2210%22 transform=%22rotate(32 80 80)%22/%3E%3Crect x=%2270%22 y=%2224%22 width=%2220%22 height=%22112%22 rx=%2210%22 transform=%22rotate(-32 80 80)%22/%3E%3C/g%3E%3C/svg%3E'), radial-gradient(circle at 14% 10%, rgba(222, 124, 58, 0.24), transparent 22%), radial-gradient(circle at 82% 12%, rgba(53, 136, 110, 0.22), transparent 20%), linear-gradient(180deg, #fef5e7 0%, #e9ddba 46%, #d9eadf 100%); background-repeat: repeat, no-repeat, no-repeat, no-repeat; font-family: Arial, sans-serif; color: #1f2a2a; line-height: 1.6;"> <div style="margin: 0; padding: 28px; background-color: #fef5e7; background-image: url('cid:flockpal-x-pattern'), radial-gradient(circle at 14% 10%, rgba(222, 124, 58, 0.24), transparent 22%), radial-gradient(circle at 82% 12%, rgba(53, 136, 110, 0.22), transparent 20%), linear-gradient(180deg, #fef5e7 0%, #e9ddba 46%, #d9eadf 100%); background-repeat: repeat, no-repeat, no-repeat, no-repeat; font-family: Arial, sans-serif; color: #1f2a2a; line-height: 1.6;">
<div style="max-width: 680px; margin: 0 auto 18px;">
<img src="cid:flockpal-x-pattern" alt="" style="display: block; width: 100%; max-width: 680px; height: auto; border-radius: 26px;" />
</div>
<div style="max-width: 680px; margin: 0 auto; overflow: hidden; border-radius: 30px; background-color: #e7f4e9; background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.44), transparent 42%), linear-gradient(180deg, rgba(235, 247, 237, 0.98), rgba(211, 235, 220, 0.96)); border: 1px solid rgba(53, 129, 98, 0.34); box-shadow: 0 22px 44px rgba(89, 48, 42, 0.14);"> <div style="max-width: 680px; margin: 0 auto; overflow: hidden; border-radius: 30px; background-color: #e7f4e9; background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.44), transparent 42%), linear-gradient(180deg, rgba(235, 247, 237, 0.98), rgba(211, 235, 220, 0.96)); border: 1px solid rgba(53, 129, 98, 0.34); box-shadow: 0 22px 44px rgba(89, 48, 42, 0.14);">
<div style="padding: 24px 28px; background-color: #edf8ef; background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.46), transparent 46%), linear-gradient(180deg, rgba(242, 250, 243, 0.98), rgba(220, 241, 226, 0.94)); border-bottom: 1px solid rgba(53, 129, 98, 0.18);"> <div style="padding: 24px 28px; background-color: #edf8ef; background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.46), transparent 46%), linear-gradient(180deg, rgba(242, 250, 243, 0.98), rgba(220, 241, 226, 0.94)); border-bottom: 1px solid rgba(53, 129, 98, 0.18);">
${ ${
@@ -1218,6 +1231,9 @@ const sendBirdMilestoneReminderNotification = async ({
</p> </p>
</div> </div>
</div> </div>
<div style="max-width: 680px; margin: 18px auto 0;">
<img src="cid:flockpal-x-pattern" alt="" style="display: block; width: 100%; max-width: 680px; height: auto; border-radius: 26px;" />
</div>
</div> </div>
`, `,
}); });