all repos — caroster @ ff83faadead96731bb12e1fbcc61e8d716137f32

[Octree] Group carpool to your event https://caroster.io

feat: 💄 Improve emails ui
Simon Mulquin simon@octree.ch
Fri, 24 May 2024 11:45:34 +0000
commit

ff83faadead96731bb12e1fbcc61e8d716137f32

parent

2b7fb817e6b5f6f8cec73d78960ce1695fa318a9

M backend/src/api/email/locales/en.jsonbackend/src/api/email/locales/en.json

@@ -1,7 +1,7 @@

{ "template": { - "header": "<img src='https://app.caroster.io/uploads/Caroster_logo1_cddd3057fc.png?updated_at=2022-09-12T08:11:11.735Z' width='100%' alt='Caroster'/>", - "footer": "---\n💝 You also think Caroster is awesome? Keep it free and support us with a donation!\n\n👉 [Open collective](https://opencollective.com/caroster)\n\n<center><a href='https://caroster.io'>https://caroster.io</a></center>" + "footer": "💝 You also think Caroster is awesome? Keep it free and support us with a donation!", + "carosterLink": "https://caroster.io/en/home" }, "notifications": { "ConfirmEmail": {

@@ -38,7 +38,7 @@ "content": "You have been promoted as administrator to [<%= event.name %>](<%= host %>/e/<%= event.uuid %>)."

}, "EventCreated": { "title": "<%= event.name %> - Your Caroster is ready !", - "content": "## Hurrah, your Caroster \"<%= event.name %>\" is ready !\n\nStart organizing:\n🚗 Add trips\n💬 Invite your participants to carpool by sharing your Caroster link.\n\nShare link:\n<%= host %>/e/<%= event.uuid %>" + "content": "## Hurrah, your Caroster \"<%= event.name %>\" is ready !\n\nStart organizing:\n\n🚗 Add trips\n\n💬 Invite your participants to carpool by sharing your Caroster link.\n\nShare link:\n<%= host %>/e/<%= event.uuid %>" }, "EventEnded": { "title": "<%= event.name %> - Your event is over !",
M backend/src/api/email/locales/fr.jsonbackend/src/api/email/locales/fr.json

@@ -1,7 +1,7 @@

{ "template": { - "header": "<img src='https://app.caroster.io/uploads/Caroster_logo1_cddd3057fc.png?updated_at=2022-09-12T08:11:11.735Z' width='100%' alt='Caroster'/>", - "footer": "---\n💝 Vous pensez aussi que Caroster est génial ? Aidez-nous à le maintenir libre et gratuit en faisant une donation !\n\n👉 [Open collective](https://opencollective.com/caroster)\n\n<center><a href='https://caroster.io'>https://caroster.io</a></center>" + "footer": "💝 Vous pensez aussi que Caroster est génial ? Aidez-nous à le maintenir libre et gratuit en faisant une donation !", + "carosterLink": "https://caroster.io" }, "notifications": { "ConfirmEmail": {

@@ -38,7 +38,7 @@ "content": "Vous avez été promu administrateur sur le Caroster [<%= event.name %>](<%= host %>/e/<%= event.uuid %>)."

}, "EventCreated": { "title": "<%= event.name %> - Votre Caroster est prêt !", - "content": "## Hurrah, votre Caroster \"<%= event.name %>\" est prêt !\n\nCommencez à vous organiser:\n🚗 Ajoutez des trajets\n💬 Invitez vos participants à covoiturer en partageant le lien de votre Caroster.\n\nLien de partage:\n<%= host %>/e/<%= event.uuid %>" + "content": "## Hurrah, votre Caroster \"<%= event.name %>\" est prêt !\n\nCommencez à vous organiser:\n\n🚗 Ajoutez des trajets\n\n💬 Invitez vos participants à covoiturer en partageant le lien de votre Caroster.\n\nLien de partage:\n<%= host %>/e/<%= event.uuid %>" }, "EventEnded": { "title": "<%= event.name %> - Votre événement est terminé !",
A backend/src/api/email/locales/nl.json

@@ -0,0 +1,52 @@

+{ + "template": { + "footer": "💝 Vindt u Caroster ook zo geweldig? Help dan om de app gratis te blijven aanbieden door te doneren!", + "carosterLink": "https://caroster.io/en/home" + }, + "notifications": { + "DeletedTrip": { + "title": "<%= event.name %> - Reis verwijderd", + "content": "De reis waaraan u wilde deelnemen, <%= travel.vehicleName %>, is verwijderd. Ga naar de [Caroster](<%= host %>/e/<%= event.uuid %>)-pagina om een ander voertuig te zoeken." + }, + "NewTrip": { + "title": "<%= event.name %> - Nieuwe reis beschikbaar", + "content": "## Er is een nieuwe reis beschikbaar voor \"<%= event.name %>\"\n\n**Voertuig: <%= travel.vehicleName %>**\nAantal zitplaatsen: <%= travel.seats %>\nVertreklocatie: <%= travel.meeting %>\nInformatie: <%= travel.details %>.\n\n[Zitplaats reserveren](<%= host %>/e/<%= event.uuid %>).\n\nU ontvangt deze e-mail omdat u uzelf op de carpoolwachtlijst van deze afspraak heeft gezet." + }, + "DeletedYourTrip": { + "title": "<%= event.name %> - Uw reis is verwijderd", + "content": "Uw reis, <%= travel.vehicleName %>, is door een beheerder verwijderd uit de afspraak ‘[<%= event.name %>](<%= host %>/e/<%= event.uuid %>)’." + }, + "DeletedFromTrip": { + "title": "<%= event.name %> - U bent uit het voertuig verwijderd", + "content": "U bent uit het voertuig ‘<%= travel.vehicleName %>’ van de afspraak ‘[<%= event.name %>](<%= host %>/e/<%= event.uuid %>)’ verwijderd." + }, + "NewPassengerInYourTrip": { + "title": "<%= event.name %> - Passagier toegevoegd aan reis", + "content": "Er is een passagier toegevoegd aan ‘[<%= event.name %>](<%= host %>/e/<%= event.uuid %>)’" + }, + "AddedAsAdmin": { + "title": "U bent toegevoegd als beheerder van een afspraak", + "content": "U bent toegevoegd als beheerder van ‘[<%= event.name %>](<%= host %>/e/<%= event.uuid %>)’." + }, + "EventCreated": { + "title": "<%= event.name %> - Uw Caroster is klaar voor gebruik!", + "content": "## Hoezee! Uw Caroster, ‘<%= event.name %>’, is klaar voor gebruik!\n\nHet organiseren kan beginnen:\n\n🚗 Voeg voertuigen toe;\n\n💬 Nodig deelnemers uit door uw Caroster-link te delen.\n\nCaroster-link:\n<%= host %>/e/<%= event.uuid %>" + }, + "EventEnded": { + "title": "<%= event.name %> - De afspraak is voorbij!", + "content": "## ‘<%= event.name %>’ is voorbij!\n\n👏 Aantal passagiers: <%= event.passengers.length %>\n🚗 Aantal gebruikte voertuigen: <%= event.travels.length %>\n\nLink naar uw Caroster: <%= host %>/e/<%= event.uuid %>\n\nU ontvangt deze e-mail omdat u de afspraak hebt aangemaakt." + }, + "EventRecap": { + "title": "<%= event.name %> - Wijzigingen aan afspraak", + "content": "## Er hebben wijzigingen plaatsgevonden aan ‘<%= event.name %>’\n\n⏳ Aantal passagiers op wachtlijst: <%= waitingListCount %>\n🚗 Aantal voertuigen: <%= travelsCount %>\n🆕 Aantal nieuwe voertuigen: <%= newTravelsCount %>\n\nLink naar uw Caroster: <%= host %>/e/<%= event.uuid %>\n\nU ontvangt deze e-mail omdat u de afspraak hebt aangemaakt." + }, + "ContactTripCreator": { + "title": "<%= event.name %> - Contact opnemen met bestuurder", + "content": "Als u de reis naar ‘<%= event.name %>’ wilt organiseren, neem dan contact op met de bestuurder.\n\n**Voertuig: <%= travel.vehicleName %>**\nVertrek: <%= travel.meeting %>\nDatum/Tijd: <%= datetime %>\nTelefoonnummer: <%= travel.phone_mumber | 'Not provided' %>\nE-mailadres: <%= driver.email %>" + }, + "EnabledCarosterPlus": { + "title": "<%= event.name %> - Caroster+ is geactiveerd op uw afspraak", + "content": "De module ‘Caroster+’ is geactiveerd op uw afspraak ‘[<%= event.name %>](<%= host %>/e/<%= event.uuid %>)’." + } + } +}
M backend/src/api/email/services/email.tsbackend/src/api/email/services/email.ts

@@ -1,14 +1,14 @@

import fs from "node:fs/promises"; import _ from "lodash"; import { marked } from "marked"; -import { getHTMLMeta } from "../utils/layout"; +import { getHTML } from "../utils/layout"; const langs = ["en", "fr"]; let locales: Record< string, { - template: Record<"header" | "footer", string>; + template: Record<"footer" | "carosterLink", string>; notifications: Record<string, { title: string; content: string }>; } > = null;

@@ -79,12 +79,11 @@ const mdContent = _.template(notif.content)({

...variables, host: strapi.config.server.url, }); - const mdHeader = locales?.[lang]?.template.header; const mdFooter = locales?.[lang]?.template.footer; + const carosterLink = locales?.[lang]?.template.carosterLink; const htmlContent = await marked.parse(mdContent, { breaks: true }); - const htmlHeader = await marked.parse(mdHeader, { breaks: true }); const htmlFooter = await marked.parse(mdFooter, { breaks: true }); - const html = `<header>${htmlHeader}</header><main>${getHTMLMeta()}${htmlContent}${htmlFooter}</main>`; + const html = getHTML({htmlContent, htmlFooter, carosterLink}); return { subject,
M backend/src/api/email/utils/layout.tsbackend/src/api/email/utils/layout.ts

@@ -1,18 +1,100 @@

-export const getHTMLMeta = () => ` -<style type="text/css"> - body { - font-family: sans; - } - header { - text-align: center; - } - header img { - width: 20rem; - max-width: 100%; - } - main { - max-width: 40rem; - margin: 0 auto; - } -</style> +export const getHTML = ({ htmlContent, htmlFooter, carosterLink }) => ` +<!doctype html> +<html> + <body> + <div + style='background-color:#F5F5F5;color:#262626;font-family:"Helvetica Neue", "Arial Nova", "Nimbus Sans", Arial, sans-serif;font-size:16px;font-weight:400;letter-spacing:0.15008px;line-height:1.5;margin:0;padding:32px 0;min-height:100%;width:100%' + > + <table + align="center" + width="100%" + style="margin:0 auto;max-width:600px;background-color:#FFFFFF" + role="presentation" + cellspacing="0" + cellpadding="0" + border="0" + > + <tbody> + <style type="text/css"> + a { + color: #009688; + } + </style> + <tr style="width:100%"> + <td> + <div + style="padding:16px 24px 16px 24px;background-color:#FFEB3B;text-align:center" + > + <img + alt="Caroster" + src="https://app.caroster.io/uploads/Caroster_logo1_cddd3057fc.png?updated_at=2022-09-12T08:11:11.735Z" + height="32" + style="height:32px;outline:none;border:none;text-decoration:none;vertical-align:middle;display:inline-block;max-width:100%" + /> + </div> + <div style="font-weight:normal;padding:16px 24px 16px 24px"> + ${htmlContent} + </div> + <div style="background-color:#E5E5E5;padding:16px 24px 16px 24px"> + <div style="font-weight:normal;padding:16px 24px 16px 24px"> + ${htmlFooter} + </div> + <div style="padding:0px 0px 0px 12px"> + <a + href="https://opencollective.com/caroster" + style="color:#171717;font-size:16px;font-weight:bold;background-color:#E5E5E5;border-radius:64px;display:inline-block;padding:8px 12px;text-decoration:none" + target="_blank" + ><span + ><!--[if mso + ]><i + style="letter-spacing: 12px;mso-font-width:-100%;mso-text-raise:18" + hidden + >&nbsp;</i + ><! + [endif]--></span + ><span>👉 Open collective</span + ><span + ><!--[if mso + ]><i + style="letter-spacing: 12px;mso-font-width:-100%" + hidden + >&nbsp;</i + ><! + [endif]--></span + ></a + > + </div> + <div style="text-align:center;padding:16px 24px 16px 24px"> + <a + href="${carosterLink}" + style="color:#FFFFFF;font-size:16px;font-weight:bold;background-color:#009688;border-radius:4px;display:block;padding:12px 20px;text-decoration:none" + target="_blank" + ><span + ><!--[if mso + ]><i + style="letter-spacing: 20px;mso-font-width:-100%;mso-text-raise:30" + hidden + >&nbsp;</i + ><! + [endif]--></span + ><span>Caroster.io</span + ><span + ><!--[if mso + ]><i + style="letter-spacing: 20px;mso-font-width:-100%" + hidden + >&nbsp;</i + ><! + [endif]--></span + ></a + > + </div> + </div> + </td> + </tr> + </tbody> + </table> + </div> + </body> +</html> `;