feat(campaigns): CSV report, manual recipients, template polish
Ops UI - CampaignDetailPage: "CSV" button — downloads per-recipient report (shortlinks, status, opened/clicked timestamps, mailjet UUID) - CampaignNewPage: "Saisie manuelle (sans CSV)" on Step 1 and "Ajouter manuellement" on Step 2 — both open the same dialog with firstname / email / gift_url / city / postal_code / language / amount override. Indigo "manuel" chip in the recipients table. - New "Ville" column shows city OR postal_code as fallback. Hub - GET /campaigns/:id/report.csv — RFC 4180 CSV with UTF-8 BOM so Excel auto-detects encoding. 20 columns including new "city". - Worker honours per-recipient amount override: r.amount > derive from r.gift_value_cents > params.amount > "50 $". Fixes manual-add showing campaign default instead of typed value. - Default subject "Un cadeau pour toi" (tutoyer). Templates - Order: Intro → ✅ Option 1 → 🎁 marques → CTA → prorata → ⏭️ Option 2. - New EN intro (manifesto): "Thank you for choosing local. Your support helps keep our community connected. / Because great connections aren't just about fiber — they're about people too." - Amazon logo removed (incongruent with "achat local" framing). - Body paragraphs: text-align justify (greeting/labels stay left). - Support line: "N'hésite pas à nous écrire / Feel free to email us" + dash format 514-448-0773, drop "Support 7j/7" overpromise. - Logo style fix: inline width:32px to beat Unlayer canvas CSS that was rendering brand pills full-width. Ignore template converter .bak-*.json backups. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
40a2e4e8f2
commit
2bc9715485
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -43,3 +43,7 @@ scripts/migration/ref_invoice.pdf
|
|||
|
||||
# Playwright snapshots
|
||||
.playwright-mcp/
|
||||
|
||||
# Auto-generated backups from scripts/convert-html-to-unlayer.js
|
||||
services/targo-hub/templates/*.bak-*.json
|
||||
services/targo-hub/templates/*.bak-*.html
|
||||
|
|
|
|||
|
|
@ -69,6 +69,13 @@ export function sendCampaign (id) {
|
|||
})
|
||||
}
|
||||
|
||||
// Build the URL the browser hits to download the per-recipient CSV report
|
||||
// (giftbit shortlink ↔ email ↔ name ↔ status). The hub serves it with the
|
||||
// proper Content-Disposition so an <a download> click triggers a save.
|
||||
export function campaignReportCsvUrl (id) {
|
||||
return `${HUB_URL}/campaigns/${encodeURIComponent(id)}/report.csv`
|
||||
}
|
||||
|
||||
// ── Image assets (self-hosted on the hub, for GrapesJS asset manager) ───────
|
||||
|
||||
export function listAssets () {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,13 @@
|
|||
<div class="text-h5">{{ campaign?.name || id }}</div>
|
||||
<q-chip dense class="q-ml-md" :color="statusColor(campaign?.status)" text-color="white" :label="statusLabel(campaign?.status)" />
|
||||
<q-space />
|
||||
<q-btn
|
||||
v-if="campaign?.recipients?.length"
|
||||
flat dense icon="file_download" label="CSV" class="q-mr-sm"
|
||||
:href="reportCsvUrl" download
|
||||
>
|
||||
<q-tooltip>Télécharger le rapport (shortlinks Giftbit, emails, statuts d'envoi)</q-tooltip>
|
||||
</q-btn>
|
||||
<q-btn v-if="campaign?.status === 'draft'" unelevated color="primary" icon="send" label="Lancer l'envoi"
|
||||
:loading="resending" @click="relaunch" />
|
||||
</div>
|
||||
|
|
@ -92,7 +99,7 @@
|
|||
import { ref, computed, onMounted, onBeforeUnmount } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useQuasar } from 'quasar'
|
||||
import { getCampaign, sendCampaign, campaignSseUrl } from 'src/api/campaigns'
|
||||
import { getCampaign, sendCampaign, campaignSseUrl, campaignReportCsvUrl } from 'src/api/campaigns'
|
||||
|
||||
const route = useRoute()
|
||||
const $q = useQuasar()
|
||||
|
|
@ -131,6 +138,8 @@ function statusLabel (s) {
|
|||
}
|
||||
function shortLink (u) { return (u || '').replace(/^https?:\/\//, '').slice(0, 28) + ((u || '').length > 35 ? '…' : '') }
|
||||
|
||||
const reportCsvUrl = computed(() => campaignReportCsvUrl(id))
|
||||
|
||||
const sentRatio = computed(() => {
|
||||
const total = campaign.value?.counters?.total || 1
|
||||
const done = counterFor('sent') + counterFor('opened') + counterFor('clicked')
|
||||
|
|
|
|||
|
|
@ -73,6 +73,9 @@
|
|||
</q-card>
|
||||
|
||||
<q-stepper-navigation>
|
||||
<q-btn flat color="primary" icon="person_add" label="Saisie manuelle (sans CSV)" @click="goManual" class="q-mr-sm">
|
||||
<q-tooltip>Sauter l'import CSV et ajouter les destinataires un par un à l'étape suivante</q-tooltip>
|
||||
</q-btn>
|
||||
<q-btn unelevated color="primary" label="Suivant — Aperçu" icon-right="arrow_forward"
|
||||
:disable="!mapPreview || !giftPreview || parsing"
|
||||
:loading="parsing" @click="goPreview" />
|
||||
|
|
@ -157,9 +160,15 @@
|
|||
</q-banner>
|
||||
|
||||
<!-- ✓ Paired recipients (will be sent) ────────────────────────── -->
|
||||
<div class="text-subtitle1 q-mb-xs">
|
||||
<q-icon name="link" /> Association contact ↔ lien-cadeau
|
||||
<span class="text-caption text-grey-7">— vérifier avant d'approuver</span>
|
||||
<div class="row items-center q-mb-xs">
|
||||
<div class="text-subtitle1">
|
||||
<q-icon name="link" /> Association contact ↔ lien-cadeau
|
||||
<span class="text-caption text-grey-7">— vérifier avant d'approuver</span>
|
||||
</div>
|
||||
<q-space />
|
||||
<q-btn unelevated dense color="primary" icon="person_add" label="Ajouter manuellement" @click="openManualDialog">
|
||||
<q-tooltip>Ajouter un destinataire en saisissant les champs (sans passer par CSV)</q-tooltip>
|
||||
</q-btn>
|
||||
</div>
|
||||
<q-table
|
||||
:rows="recipients" :columns="recipientColumns" row-key="row_index"
|
||||
|
|
@ -232,7 +241,8 @@
|
|||
</template>
|
||||
<template v-slot:body-cell-match="props">
|
||||
<q-td :props="props">
|
||||
<q-chip v-if="props.row.customer_id" dense color="positive" text-color="white" size="sm" :label="props.row.match_method" />
|
||||
<q-chip v-if="props.row.manual" dense color="indigo-5" text-color="white" size="sm" icon="edit" label="manuel" />
|
||||
<q-chip v-else-if="props.row.customer_id" dense color="positive" text-color="white" size="sm" :label="props.row.match_method" />
|
||||
<q-chip v-else dense color="warning" text-color="white" size="sm" label="non lié" />
|
||||
</q-td>
|
||||
</template>
|
||||
|
|
@ -335,6 +345,71 @@
|
|||
|
||||
</q-stepper>
|
||||
|
||||
<!-- Manual-add dialog — push a recipient into recipients[] without going
|
||||
through CSV parsing. Useful for ad-hoc gifts, retroactive top-ups,
|
||||
or test sends to internal stakeholders. The matchCustomer() lookup
|
||||
that the CSV path does is skipped here — customer_id stays empty
|
||||
unless the user manually pastes it. -->
|
||||
<q-dialog v-model="manualOpen" persistent>
|
||||
<q-card style="min-width: 480px; max-width: 640px;">
|
||||
<q-card-section class="row items-center q-pb-none">
|
||||
<div class="text-h6"><q-icon name="person_add" class="q-mr-sm" />Ajouter un destinataire</div>
|
||||
<q-space />
|
||||
<q-btn flat dense round icon="close" v-close-popup />
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-form @submit="submitManualRow" class="q-gutter-sm">
|
||||
<div class="row q-col-gutter-sm">
|
||||
<q-input v-model="manualRow.firstname" label="Prénom *" outlined dense
|
||||
class="col-12 col-sm-6" :rules="[v => !!v || 'requis']" autofocus />
|
||||
<q-input v-model="manualRow.lastname" label="Nom" outlined dense
|
||||
class="col-12 col-sm-6" />
|
||||
</div>
|
||||
<q-input v-model="manualRow.email" label="Email *" outlined dense type="email"
|
||||
:rules="[v => !!v || 'requis', v => /.+@.+\..+/.test(v) || 'email invalide']" />
|
||||
<q-input v-model="manualRow.gift_url" label="Lien-cadeau Giftbit *" outlined dense
|
||||
placeholder="https://gft.link/..."
|
||||
:rules="[v => !!v || 'requis', v => /^https?:\/\//.test(v) || 'doit commencer par http:// ou https://']" />
|
||||
<q-input v-model="manualRow.civic_address" label="Adresse civique (pour {{description}})" outlined dense
|
||||
placeholder="25 Rue des Hirondelles" />
|
||||
<div class="row q-col-gutter-sm">
|
||||
<q-input v-model="manualRow.city" label="Ville" outlined dense
|
||||
placeholder="Ste-Clotilde" class="col-12 col-sm-7" />
|
||||
<q-input v-model="manualRow.postal_code" label="Code postal" outlined dense
|
||||
placeholder="J0L 1W0" class="col-12 col-sm-5" />
|
||||
</div>
|
||||
<div class="row q-col-gutter-sm">
|
||||
<q-select v-model="manualRow.language" :options="languageOptions" emit-value map-options
|
||||
label="Langue du template" outlined dense class="col-12 col-sm-6" />
|
||||
<q-input v-model="manualRow.phone" label="Téléphone (optionnel)" outlined dense class="col-12 col-sm-6" />
|
||||
</div>
|
||||
<div class="row q-col-gutter-sm">
|
||||
<q-input v-model="manualRow.amount" label="Montant affiché dans le courriel" outlined dense
|
||||
:placeholder="`défaut: ${params.amount}`" class="col-12 col-sm-6">
|
||||
<q-tooltip><span v-pre>Texte qui apparaîtra à la place de la variable {{amount}}. Laisse vide pour utiliser le montant de la campagne.</span></q-tooltip>
|
||||
</q-input>
|
||||
<q-input v-model.number="manualRow.gift_value_cents" type="number"
|
||||
label="Valeur en cents (rapport)" outlined dense placeholder="5000"
|
||||
class="col-12 col-sm-6" /></div>
|
||||
<div class="text-caption text-grey-7 q-mt-xs">
|
||||
<q-icon name="info" size="14px" /> Ville et code postal ne s'affichent pas dans le courriel —
|
||||
ils servent à éviter une confusion entre deux clients du même nom dans le tableau ci-dessous
|
||||
et dans le rapport CSV.
|
||||
</div>
|
||||
<div class="text-caption text-grey-7 q-mt-xs">
|
||||
<q-icon name="info" size="14px" /> Aucun match ERPNext n'est tenté.
|
||||
<span v-pre>Seule l'adresse civique apparaît dans le courriel (variable <code>{{description}}</code>).</span>
|
||||
</div>
|
||||
<div class="row q-mt-md">
|
||||
<q-space />
|
||||
<q-btn flat label="Annuler" v-close-popup class="q-mr-sm" />
|
||||
<q-btn unelevated color="primary" type="submit" icon="add" label="Ajouter" />
|
||||
</div>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
<!-- Preview dialog — renders the actual template with the first sendable
|
||||
recipient's data + the campaign params. Lets the user verify the
|
||||
visual + content WITHOUT firing any emails. Toggleable FR/EN since
|
||||
|
|
@ -386,7 +461,7 @@ const params = ref({
|
|||
name: `Campagne ${new Date().toISOString().slice(0,10)}`,
|
||||
amount: '60 $',
|
||||
commitment_months: 3,
|
||||
subject: '🎁 Un cadeau pour vous, de la part de TARGO',
|
||||
subject: '🎁 Un cadeau pour toi, de la part de TARGO',
|
||||
from: 'TARGO <support@targointernet.com>',
|
||||
expiry: '',
|
||||
throttle_ms: 600,
|
||||
|
|
@ -415,6 +490,7 @@ const recipientColumns = [
|
|||
{ name: 'lastname', label: 'Nom', field: 'lastname', align: 'left' },
|
||||
{ name: 'email', label: 'Email', field: 'email', align: 'left' },
|
||||
{ name: 'civic_address', label: 'Adresse', field: 'civic_address', align: 'left' },
|
||||
{ name: 'city', label: 'Ville', field: r => r.city || r.postal_code || '', align: 'left' },
|
||||
{ name: 'gift_url', label: 'Lien-cadeau', field: 'gift_url', align: 'left' },
|
||||
{ name: 'language', label: 'Langue', field: 'language', align: 'left' },
|
||||
{ name: 'match', label: 'Match', field: 'match_method', align: 'left' },
|
||||
|
|
@ -609,6 +685,74 @@ async function goPreview () {
|
|||
}
|
||||
}
|
||||
|
||||
// Skip CSV parsing entirely — empty recipients list, user adds rows manually
|
||||
// via the "Ajouter manuellement" button on Step 2. The Suivant button is
|
||||
// disabled if no rows, so the user can't accidentally proceed with nothing.
|
||||
function goManual () {
|
||||
recipients.value = []
|
||||
unpairedContacts.value = []
|
||||
unusedGifts.value = []
|
||||
step.value = 2
|
||||
// Open the dialog immediately — the most likely next action is adding a row
|
||||
openManualDialog()
|
||||
}
|
||||
|
||||
// ── Manual recipient entry ────────────────────────────────────────────────
|
||||
// Lets the user add a recipient by typing the fields directly instead of
|
||||
// importing from CSV. Useful for: small ad-hoc gifts, replacement sends after
|
||||
// a bounce, internal QA test sends, or topping up an existing CSV import
|
||||
// with a missed contact. No ERPNext matching is attempted on these rows.
|
||||
const manualOpen = ref(false)
|
||||
const languageOptions = [
|
||||
{ label: '🇫🇷 Français', value: 'fr' },
|
||||
{ label: '🇺🇸 English', value: 'en' },
|
||||
]
|
||||
function emptyManualRow () {
|
||||
return {
|
||||
firstname: '', lastname: '', email: '', phone: '',
|
||||
civic_address: '', city: '', postal_code: '', language: 'fr',
|
||||
gift_url: '', gift_value_cents: null, amount: '',
|
||||
}
|
||||
}
|
||||
const manualRow = ref(emptyManualRow())
|
||||
|
||||
function openManualDialog () {
|
||||
manualRow.value = emptyManualRow()
|
||||
manualOpen.value = true
|
||||
}
|
||||
|
||||
function submitManualRow () {
|
||||
// Determine next row_index. CSV-imported rows start at 1; manuals continue
|
||||
// the sequence so #N reads naturally regardless of source.
|
||||
const maxIdx = recipients.value.reduce((m, r) => Math.max(m, r.row_index || 0), 0)
|
||||
recipients.value.push({
|
||||
row_index: maxIdx + 1,
|
||||
firstname: (manualRow.value.firstname || '').trim(),
|
||||
lastname: (manualRow.value.lastname || '').trim(),
|
||||
email: (manualRow.value.email || '').trim().toLowerCase(),
|
||||
phone: (manualRow.value.phone || '').trim(),
|
||||
civic_address: (manualRow.value.civic_address || '').trim(),
|
||||
city: (manualRow.value.city || '').trim(),
|
||||
postal_code: (manualRow.value.postal_code || '').trim().toUpperCase(),
|
||||
language: manualRow.value.language || 'fr',
|
||||
gift_url: (manualRow.value.gift_url || '').trim(),
|
||||
gift_value_cents: manualRow.value.gift_value_cents || null,
|
||||
// Per-recipient amount override. Empty string → falls back to campaign
|
||||
// params.amount in the worker. Useful for manuals on a mixed-amount campaign.
|
||||
amount: (manualRow.value.amount || '').trim() || null,
|
||||
giftbit_uuid: null,
|
||||
// Flag for downstream code + table display so a "manuel" chip can be shown
|
||||
// and the match-method column doesn't read "non lié" misleadingly.
|
||||
manual: true,
|
||||
match_method: 'manuel',
|
||||
customer_id: null,
|
||||
status: 'pending',
|
||||
excluded: false,
|
||||
})
|
||||
manualOpen.value = false
|
||||
$q.notify({ type: 'positive', message: 'Destinataire ajouté' })
|
||||
}
|
||||
|
||||
async function launchSend () {
|
||||
sending.value = true
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
<tbody>
|
||||
<tr>
|
||||
<td style="display:none !important;visibility:hidden;mso-hide:all;font-size:1px;color:#ffffff;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;">
|
||||
Like you, we believe in steady connections — both the fiber kind and the human kind.
|
||||
Because great connections aren't just about fiber — they're about people too.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
|
@ -102,7 +102,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
<td style="overflow-wrap:break-word;word-break:break-word;padding:0px;font-family:'Plus Jakarta Sans', sans-serif;" align="left">
|
||||
|
||||
<div>
|
||||
<div style="display:none;font-size:1px;color:#ffffff;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;">Like you, we believe in steady connections — both the fiber kind and the human kind.</div>
|
||||
<div style="display:none;font-size:1px;color:#ffffff;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;">Because great connections aren't just about fiber — they're about people too.</div>
|
||||
|
||||
<div
|
||||
aria-label="Your exclusive offer from TARGO" aria-roledescription="email" role="article" lang="und" dir="auto" style="word-spacing:normal;background-color:#F5FAF7;"
|
||||
|
|
@ -221,12 +221,12 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
align="left" style="font-size:0px;padding:10px 25px;padding-bottom:14px;word-break:break-word;"
|
||||
>
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#374151;"
|
||||
>Summer's here, and we've got something special just for you — but only for a little while.</div>
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:justify;color:#374151;"
|
||||
>Summer is here, and so is something special — for a limited time.</div>
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;font-weight:500;line-height:1.5;text-align:left;color:#1B2E24;"
|
||||
>Thanks for keeping it local — it means more than you think.<br />
|
||||
Like you, we believe in steady connections — both the fiber kind and the human kind.</div>
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;font-weight:500;line-height:1.5;text-align:justify;color:#1B2E24;"
|
||||
>Thank you for choosing local. Your support helps keep our community connected.<br />
|
||||
Because great connections aren't just about fiber — they're about people too.</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -237,7 +237,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
align="left" style="font-size:0px;padding:10px 25px;padding-bottom:0;word-break:break-word;"
|
||||
>
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#374151;">Because our customers trust us, we're now able to offer the <strong>fastest plans around</strong>, with speeds up to <strong>3.5 Gbit/s</strong>.<br />
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:justify;color:#374151;">Because our customers trust us, we're now able to offer the <strong>fastest plans around</strong>, with speeds up to <strong>3.5 Gbit/s</strong>.<br />
|
||||
Whether you're looking for more speed, want to beat another offer, or just need to optimize your gear, don't be shy! We're right next door — and we genuinely love lending a hand.</div>
|
||||
|
||||
</td>
|
||||
|
|
@ -257,6 +257,60 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
</div>
|
||||
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
|
||||
<!-- ════════ OPTION 1 CHIP ════════ -->
|
||||
|
||||
<!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:600px;" width="600" bgcolor="#ffffff" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
|
||||
|
||||
|
||||
<div style="background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:600px;">
|
||||
|
||||
<table
|
||||
align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#ffffff;background-color:#ffffff;width:100%;"
|
||||
>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td
|
||||
style="border-left:1px solid #e5e7eb;border-right:1px solid #e5e7eb;border-top:1px solid #eef0ee;direction:ltr;font-size:0px;padding:18px 36px 8px;text-align:center;"
|
||||
>
|
||||
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td style="vertical-align:top;width:526px;" ><![endif]-->
|
||||
|
||||
<div
|
||||
class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"
|
||||
>
|
||||
|
||||
<table
|
||||
border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"
|
||||
>
|
||||
<tbody>
|
||||
|
||||
<tr>
|
||||
<td
|
||||
align="left" style="font-size:0px;padding:0;word-break:break-word;"
|
||||
>
|
||||
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#1B2E24;"
|
||||
><span style="display:inline-block;background:#E6F9EE;color:#00C853;font-size:13px;font-weight:700;padding:5px 12px;border-radius:6px;">✅ Option 1</span></div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
|
||||
<!-- ════════ COMPACT INFO CARD (was 3 pills) ════════ -->
|
||||
|
|
@ -299,7 +353,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;font-weight:700;line-height:1.5;text-align:left;color:#1B2E24;"
|
||||
>🎁 {{amount}} to spend at hundreds of your favorite stores<br><br><span style="display:inline-block;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/31ffdf91-d2de-4ced-8b99-ad2221695abe/content" width="32" alt="Amazon" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/4b0b2a4a-5f99-416c-8873-8d3e4389b6f7/content" width="32" alt="Tim Hortons" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/14df433d-583c-4602-a403-d47ee84966a6/content" width="32" alt="Walmart" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/b8d3db5a-d39e-43ce-a84a-2f5dddbf0192/content" width="32" alt="Home Depot" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/9c9dfa18-2a3a-414a-b5ad-16d490c961b5/content" width="32" alt="IGA" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/a1e5f032-a192-4499-97ba-53b939712fa9/content" width="32" alt="Home Hardware" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><span style="font-size:13px;color:#64748B;vertical-align:middle;font-weight:400;">and more</span></span></div>
|
||||
>🎁 {{amount}} to spend at hundreds of your favorite stores<br><br><span style="display:inline-block;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/4b0b2a4a-5f99-416c-8873-8d3e4389b6f7/content" width="32" alt="Tim Hortons" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/14df433d-583c-4602-a403-d47ee84966a6/content" width="32" alt="Walmart" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/b8d3db5a-d39e-43ce-a84a-2f5dddbf0192/content" width="32" alt="Home Depot" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/9c9dfa18-2a3a-414a-b5ad-16d490c961b5/content" width="32" alt="IGA" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/a1e5f032-a192-4499-97ba-53b939712fa9/content" width="32" alt="Home Hardware" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><span style="font-size:13px;color:#64748B;vertical-align:middle;font-weight:400;">and more</span></span></div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -347,60 +401,6 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
</div>
|
||||
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
|
||||
<!-- ════════ OPTION 1 CHIP ════════ -->
|
||||
|
||||
<!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:600px;" width="600" bgcolor="#ffffff" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
|
||||
|
||||
|
||||
<div style="background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:600px;">
|
||||
|
||||
<table
|
||||
align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#ffffff;background-color:#ffffff;width:100%;"
|
||||
>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td
|
||||
style="border-left:1px solid #e5e7eb;border-right:1px solid #e5e7eb;border-top:1px solid #eef0ee;direction:ltr;font-size:0px;padding:18px 36px 8px;text-align:center;"
|
||||
>
|
||||
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td style="vertical-align:top;width:526px;" ><![endif]-->
|
||||
|
||||
<div
|
||||
class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"
|
||||
>
|
||||
|
||||
<table
|
||||
border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"
|
||||
>
|
||||
<tbody>
|
||||
|
||||
<tr>
|
||||
<td
|
||||
align="left" style="font-size:0px;padding:0;word-break:break-word;"
|
||||
>
|
||||
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#1B2E24;"
|
||||
><span style="display:inline-block;background:#E6F9EE;color:#00C853;font-size:13px;font-weight:700;padding:5px 12px;border-radius:6px;">✅ Option 1</span></div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
|
||||
<!-- ════════ BIG GREEN CTA BUTTON ════════ -->
|
||||
|
|
@ -744,11 +744,10 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:12px;line-height:1.55;text-align:center;color:#64748B;"
|
||||
>You're getting this email because you're a TARGO customer at <strong style="color:#1B2E24;">{{description}}</strong>.<br />
|
||||
Got a question? Shoot us an email at
|
||||
Got a question? Feel free to email us at
|
||||
<a href="mailto:support@targo.ca" style="color:#00C853;text-decoration:none;">support@targo.ca</a>
|
||||
or give us a call at
|
||||
<a href="tel:5144480773" style="color:#00C853;text-decoration:none;">514 448-0773</a>.
|
||||
We're here 7 days/week to help!</div>
|
||||
or call us at
|
||||
<a href="tel:5144480773" style="color:#00C853;text-decoration:none;">514-448-0773</a>.</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -221,10 +221,10 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
align="left" style="font-size:0px;padding:10px 25px;padding-bottom:14px;word-break:break-word;"
|
||||
>
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#374151;"
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:justify;color:#374151;"
|
||||
>Avec l'arrivée de l'été, voici un <strong>cadeau pour toi, disponible pour un temps limité</strong>.</div>
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;font-weight:500;line-height:1.5;text-align:left;color:#1B2E24;"
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;font-weight:500;line-height:1.5;text-align:justify;color:#1B2E24;"
|
||||
>On veut te remercier pour ta loyauté envers l'achat local.<br />
|
||||
Comme toi, on aime les connexions stables et les relations durables.</div>
|
||||
|
||||
|
|
@ -237,7 +237,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
align="left" style="font-size:0px;padding:10px 25px;padding-bottom:0;word-break:break-word;"
|
||||
>
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#374151;">Grâce à la confiance de nos clients, on offre maintenant les forfaits à <strong>la plus haute vitesse dans le secteur</strong>, jusqu'à <strong>3.5 Gbit/s</strong>.<br />
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:justify;color:#374151;">Grâce à la confiance de nos clients, on offre maintenant les forfaits à <strong>la plus haute vitesse dans le secteur</strong>, jusqu'à <strong>3.5 Gbit/s</strong>.<br />
|
||||
Que tu souhaites plus de vitesse, battre une autre offre ou faire optimiser des équipements, n'hésite pas. On est juste à côté et on aime aider.</div>
|
||||
|
||||
</td>
|
||||
|
|
@ -257,6 +257,60 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
</div>
|
||||
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
|
||||
<!-- ════════ OPTION 1 CHIP ════════ -->
|
||||
|
||||
<!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:600px;" width="600" bgcolor="#ffffff" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
|
||||
|
||||
|
||||
<div style="background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:600px;">
|
||||
|
||||
<table
|
||||
align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#ffffff;background-color:#ffffff;width:100%;"
|
||||
>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td
|
||||
style="border-left:1px solid #e5e7eb;border-right:1px solid #e5e7eb;border-top:1px solid #eef0ee;direction:ltr;font-size:0px;padding:18px 36px 8px;text-align:center;"
|
||||
>
|
||||
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td style="vertical-align:top;width:526px;" ><![endif]-->
|
||||
|
||||
<div
|
||||
class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"
|
||||
>
|
||||
|
||||
<table
|
||||
border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"
|
||||
>
|
||||
<tbody>
|
||||
|
||||
<tr>
|
||||
<td
|
||||
align="left" style="font-size:0px;padding:0;word-break:break-word;"
|
||||
>
|
||||
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#1B2E24;"
|
||||
><span style="display:inline-block;background:#E6F9EE;color:#00C853;font-size:13px;font-weight:700;padding:5px 12px;border-radius:6px;">✅ Option 1</span></div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
|
||||
<!-- ════════ COMPACT INFO CARD (was 3 pills) ════════ -->
|
||||
|
|
@ -299,7 +353,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;font-weight:700;line-height:1.5;text-align:left;color:#1B2E24;"
|
||||
>🎁 {{amount}} chez des centaines de marques<br><br><span style="display:inline-block;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/31ffdf91-d2de-4ced-8b99-ad2221695abe/content" width="32" alt="Amazon" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/4b0b2a4a-5f99-416c-8873-8d3e4389b6f7/content" width="32" alt="Tim Hortons" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/14df433d-583c-4602-a403-d47ee84966a6/content" width="32" alt="Walmart" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/b8d3db5a-d39e-43ce-a84a-2f5dddbf0192/content" width="32" alt="Home Depot" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/9c9dfa18-2a3a-414a-b5ad-16d490c961b5/content" width="32" alt="IGA" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/a1e5f032-a192-4499-97ba-53b939712fa9/content" width="32" alt="Home Hardware" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><span style="font-size:13px;color:#64748B;vertical-align:middle;font-weight:400;">et plus</span></span></div>
|
||||
>🎁 {{amount}} chez des centaines de marques<br><br><span style="display:inline-block;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/4b0b2a4a-5f99-416c-8873-8d3e4389b6f7/content" width="32" alt="Tim Hortons" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/14df433d-583c-4602-a403-d47ee84966a6/content" width="32" alt="Walmart" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/b8d3db5a-d39e-43ce-a84a-2f5dddbf0192/content" width="32" alt="Home Depot" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/9c9dfa18-2a3a-414a-b5ad-16d490c961b5/content" width="32" alt="IGA" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/a1e5f032-a192-4499-97ba-53b939712fa9/content" width="32" alt="Home Hardware" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><span style="font-size:13px;color:#64748B;vertical-align:middle;font-weight:400;">et plus</span></span></div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -347,60 +401,6 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
</div>
|
||||
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
|
||||
<!-- ════════ OPTION 1 CHIP ════════ -->
|
||||
|
||||
<!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:600px;" width="600" bgcolor="#ffffff" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
|
||||
|
||||
|
||||
<div style="background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:600px;">
|
||||
|
||||
<table
|
||||
align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#ffffff;background-color:#ffffff;width:100%;"
|
||||
>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td
|
||||
style="border-left:1px solid #e5e7eb;border-right:1px solid #e5e7eb;border-top:1px solid #eef0ee;direction:ltr;font-size:0px;padding:18px 36px 8px;text-align:center;"
|
||||
>
|
||||
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td style="vertical-align:top;width:526px;" ><![endif]-->
|
||||
|
||||
<div
|
||||
class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"
|
||||
>
|
||||
|
||||
<table
|
||||
border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"
|
||||
>
|
||||
<tbody>
|
||||
|
||||
<tr>
|
||||
<td
|
||||
align="left" style="font-size:0px;padding:0;word-break:break-word;"
|
||||
>
|
||||
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#1B2E24;"
|
||||
><span style="display:inline-block;background:#E6F9EE;color:#00C853;font-size:13px;font-weight:700;padding:5px 12px;border-radius:6px;">✅ Option 1</span></div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
|
||||
<!-- ════════ BIG GREEN CTA BUTTON ════════ -->
|
||||
|
|
@ -744,11 +744,10 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:12px;line-height:1.55;text-align:center;color:#64748B;"
|
||||
>Tu reçois ce courriel parce que tu es client(e) TARGO à <strong style="color:#1B2E24;">{{description}}</strong>.<br />
|
||||
Une question ? Écris à
|
||||
Une question ? N'hésite pas à nous écrire à
|
||||
<a href="mailto:support@targo.ca" style="color:#00C853;text-decoration:none;">support@targo.ca</a>
|
||||
ou appelle au
|
||||
<a href="tel:5144480773" style="color:#00C853;text-decoration:none;">514 448-0773</a>.
|
||||
Support 7j/7.</div>
|
||||
ou nous appeler au
|
||||
<a href="tel:5144480773" style="color:#00C853;text-decoration:none;">514-448-0773</a>.</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -805,13 +805,30 @@ async function sendCampaignAsync (id) {
|
|||
|
||||
const lang = (r.language || 'fr').toLowerCase().split('-')[0]
|
||||
const tplText = getTpl(lang)
|
||||
// Per-recipient amount override. Precedence:
|
||||
// 1. r.amount — explicit override typed in the manual-add dialog
|
||||
// 2. r.gift_value_cents → "$X" formatted (when CSV import set this)
|
||||
// 3. p.amount — campaign default ("60 $" etc.)
|
||||
// 4. "50 $" hard fallback
|
||||
// This matters for manual recipients where a user pastes a $50 Giftbit
|
||||
// link into a campaign whose params.amount defaults to "60 $".
|
||||
let displayAmount = p.amount || '50 $'
|
||||
if (r.amount) {
|
||||
displayAmount = r.amount
|
||||
} else if (r.gift_value_cents) {
|
||||
const cents = Number(r.gift_value_cents) || 0
|
||||
// Cents are exact dollars when divisible, else 2-decimal
|
||||
displayAmount = cents % 100 === 0
|
||||
? `${cents / 100} $`
|
||||
: `${(cents / 100).toFixed(2)} $`
|
||||
}
|
||||
const vars = {
|
||||
firstname: r.firstname || (lang === 'en' ? 'dear customer' : 'cher client'),
|
||||
lastname: r.lastname || '',
|
||||
email: r.email,
|
||||
description: r.civic_address || '',
|
||||
gift_url: r.gift_url,
|
||||
amount: p.amount || '50 $',
|
||||
amount: displayAmount,
|
||||
expiry: p.expiry || '',
|
||||
commitment_months: p.commitment_months || '3',
|
||||
year: new Date().getFullYear(),
|
||||
|
|
@ -834,7 +851,7 @@ async function sendCampaignAsync (id) {
|
|||
try {
|
||||
sendRes = await email.sendEmail({
|
||||
to,
|
||||
subject: p.subject || 'Un cadeau pour vous, de la part de TARGO',
|
||||
subject: p.subject || 'Un cadeau pour toi, de la part de TARGO',
|
||||
html,
|
||||
from: p.from || cfg.MAIL_FROM,
|
||||
headers: { 'X-MJ-CustomID': customId },
|
||||
|
|
@ -1488,6 +1505,47 @@ async function handle (req, res, method, path) {
|
|||
// ── Per-campaign wildcard routes (MUST stay below the /templates and
|
||||
// /webhook fixed paths above, otherwise the wildcard captures them) ─────
|
||||
|
||||
// GET /campaigns/:id/report.csv — per-recipient report download
|
||||
// Columns chosen for operational follow-up (resend, refund, support):
|
||||
// row, firstname, lastname, email, phone, language, customer_id, civic_address,
|
||||
// postal_code, gift_value_cents, gift_url, giftbit_uuid, status, excluded,
|
||||
// sent_at, opened_at, clicked_at, mailjet_uuid, error
|
||||
// RFC 4180: comma-separated, CRLF endings, fields with comma/quote/newline get
|
||||
// wrapped in double quotes with embedded " doubled up. We prepend a UTF-8 BOM
|
||||
// so Excel auto-detects encoding and renders accents correctly.
|
||||
const reportMatch = path.match(/^\/campaigns\/([^/]+)\/report\.csv$/)
|
||||
if (reportMatch && method === 'GET') {
|
||||
const c = loadCampaign(reportMatch[1])
|
||||
if (!c) return json(res, 404, { error: 'not found' })
|
||||
const headers = [
|
||||
'row', 'firstname', 'lastname', 'email', 'phone', 'language', 'customer_id',
|
||||
'civic_address', 'city', 'postal_code', 'gift_value_cents', 'gift_url', 'giftbit_uuid',
|
||||
'status', 'excluded', 'sent_at', 'opened_at', 'clicked_at', 'mailjet_uuid', 'error',
|
||||
]
|
||||
const esc = (v) => {
|
||||
if (v == null) return ''
|
||||
const s = String(v)
|
||||
return /[",\r\n]/.test(s) ? '"' + s.replace(/"/g, '""') + '"' : s
|
||||
}
|
||||
const lines = [headers.join(',')]
|
||||
for (const r of (c.recipients || [])) {
|
||||
lines.push([
|
||||
r.row_index, r.firstname, r.lastname, r.email, r.phone, r.language, r.customer_id,
|
||||
r.civic_address, r.city, r.postal_code, r.gift_value_cents, r.gift_url, r.giftbit_uuid,
|
||||
r.status, r.excluded ? 'true' : 'false', r.sent_at, r.opened_at, r.clicked_at,
|
||||
r.mailjet_uuid, r.error,
|
||||
].map(esc).join(','))
|
||||
}
|
||||
const csv = '' + lines.join('\r\n') + '\r\n'
|
||||
const safeName = (c.name || c.id).replace(/[^a-zA-Z0-9._-]+/g, '_').slice(0, 80)
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'text/csv; charset=utf-8',
|
||||
'Content-Disposition': `attachment; filename="campaign-${safeName}.csv"`,
|
||||
'Cache-Control': 'no-store',
|
||||
})
|
||||
return res.end(csv)
|
||||
}
|
||||
|
||||
// GET /campaigns/:id — full detail
|
||||
const detailMatch = path.match(/^\/campaigns\/([^/]+)$/)
|
||||
if (detailMatch && method === 'GET') {
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
<tbody>
|
||||
<tr>
|
||||
<td style="display:none !important;visibility:hidden;mso-hide:all;font-size:1px;color:#ffffff;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;">
|
||||
Like you, we believe in steady connections — both the fiber kind and the human kind.
|
||||
Because great connections aren't just about fiber — they're about people too.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
|
@ -102,7 +102,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
<td style="overflow-wrap:break-word;word-break:break-word;padding:0px;font-family:'Plus Jakarta Sans', sans-serif;" align="left">
|
||||
|
||||
<div>
|
||||
<div style="display:none;font-size:1px;color:#ffffff;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;">Like you, we believe in steady connections — both the fiber kind and the human kind.</div>
|
||||
<div style="display:none;font-size:1px;color:#ffffff;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;">Because great connections aren't just about fiber — they're about people too.</div>
|
||||
|
||||
<div
|
||||
aria-label="Your exclusive offer from TARGO" aria-roledescription="email" role="article" lang="und" dir="auto" style="word-spacing:normal;background-color:#F5FAF7;"
|
||||
|
|
@ -221,12 +221,12 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
align="left" style="font-size:0px;padding:10px 25px;padding-bottom:14px;word-break:break-word;"
|
||||
>
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#374151;"
|
||||
>Summer's here, and we've got something special just for you — but only for a little while.</div>
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:justify;color:#374151;"
|
||||
>Summer is here, and so is something special — for a limited time.</div>
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;font-weight:500;line-height:1.5;text-align:left;color:#1B2E24;"
|
||||
>Thanks for keeping it local — it means more than you think.<br />
|
||||
Like you, we believe in steady connections — both the fiber kind and the human kind.</div>
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;font-weight:500;line-height:1.5;text-align:justify;color:#1B2E24;"
|
||||
>Thank you for choosing local. Your support helps keep our community connected.<br />
|
||||
Because great connections aren't just about fiber — they're about people too.</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -237,7 +237,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
align="left" style="font-size:0px;padding:10px 25px;padding-bottom:0;word-break:break-word;"
|
||||
>
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#374151;">Because our customers trust us, we're now able to offer the <strong>fastest plans around</strong>, with speeds up to <strong>3.5 Gbit/s</strong>.<br />
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:justify;color:#374151;">Because our customers trust us, we're now able to offer the <strong>fastest plans around</strong>, with speeds up to <strong>3.5 Gbit/s</strong>.<br />
|
||||
Whether you're looking for more speed, want to beat another offer, or just need to optimize your gear, don't be shy! We're right next door — and we genuinely love lending a hand.</div>
|
||||
|
||||
</td>
|
||||
|
|
@ -257,6 +257,60 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
</div>
|
||||
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
|
||||
<!-- ════════ OPTION 1 CHIP ════════ -->
|
||||
|
||||
<!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:600px;" width="600" bgcolor="#ffffff" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
|
||||
|
||||
|
||||
<div style="background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:600px;">
|
||||
|
||||
<table
|
||||
align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#ffffff;background-color:#ffffff;width:100%;"
|
||||
>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td
|
||||
style="border-left:1px solid #e5e7eb;border-right:1px solid #e5e7eb;border-top:1px solid #eef0ee;direction:ltr;font-size:0px;padding:18px 36px 8px;text-align:center;"
|
||||
>
|
||||
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td style="vertical-align:top;width:526px;" ><![endif]-->
|
||||
|
||||
<div
|
||||
class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"
|
||||
>
|
||||
|
||||
<table
|
||||
border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"
|
||||
>
|
||||
<tbody>
|
||||
|
||||
<tr>
|
||||
<td
|
||||
align="left" style="font-size:0px;padding:0;word-break:break-word;"
|
||||
>
|
||||
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#1B2E24;"
|
||||
><span style="display:inline-block;background:#E6F9EE;color:#00C853;font-size:13px;font-weight:700;padding:5px 12px;border-radius:6px;">✅ Option 1</span></div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
|
||||
<!-- ════════ COMPACT INFO CARD (was 3 pills) ════════ -->
|
||||
|
|
@ -299,7 +353,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;font-weight:700;line-height:1.5;text-align:left;color:#1B2E24;"
|
||||
>🎁 {{amount}} to spend at hundreds of your favorite stores<br><br><span style="display:inline-block;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/31ffdf91-d2de-4ced-8b99-ad2221695abe/content" width="32" alt="Amazon" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/4b0b2a4a-5f99-416c-8873-8d3e4389b6f7/content" width="32" alt="Tim Hortons" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/14df433d-583c-4602-a403-d47ee84966a6/content" width="32" alt="Walmart" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/b8d3db5a-d39e-43ce-a84a-2f5dddbf0192/content" width="32" alt="Home Depot" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/9c9dfa18-2a3a-414a-b5ad-16d490c961b5/content" width="32" alt="IGA" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/a1e5f032-a192-4499-97ba-53b939712fa9/content" width="32" alt="Home Hardware" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><span style="font-size:13px;color:#64748B;vertical-align:middle;font-weight:400;">and more</span></span></div>
|
||||
>🎁 {{amount}} to spend at hundreds of your favorite stores<br><br><span style="display:inline-block;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/4b0b2a4a-5f99-416c-8873-8d3e4389b6f7/content" width="32" alt="Tim Hortons" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/14df433d-583c-4602-a403-d47ee84966a6/content" width="32" alt="Walmart" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/b8d3db5a-d39e-43ce-a84a-2f5dddbf0192/content" width="32" alt="Home Depot" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/9c9dfa18-2a3a-414a-b5ad-16d490c961b5/content" width="32" alt="IGA" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/a1e5f032-a192-4499-97ba-53b939712fa9/content" width="32" alt="Home Hardware" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><span style="font-size:13px;color:#64748B;vertical-align:middle;font-weight:400;">and more</span></span></div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -347,60 +401,6 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
</div>
|
||||
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
|
||||
<!-- ════════ OPTION 1 CHIP ════════ -->
|
||||
|
||||
<!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:600px;" width="600" bgcolor="#ffffff" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
|
||||
|
||||
|
||||
<div style="background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:600px;">
|
||||
|
||||
<table
|
||||
align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#ffffff;background-color:#ffffff;width:100%;"
|
||||
>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td
|
||||
style="border-left:1px solid #e5e7eb;border-right:1px solid #e5e7eb;border-top:1px solid #eef0ee;direction:ltr;font-size:0px;padding:18px 36px 8px;text-align:center;"
|
||||
>
|
||||
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td style="vertical-align:top;width:526px;" ><![endif]-->
|
||||
|
||||
<div
|
||||
class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"
|
||||
>
|
||||
|
||||
<table
|
||||
border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"
|
||||
>
|
||||
<tbody>
|
||||
|
||||
<tr>
|
||||
<td
|
||||
align="left" style="font-size:0px;padding:0;word-break:break-word;"
|
||||
>
|
||||
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#1B2E24;"
|
||||
><span style="display:inline-block;background:#E6F9EE;color:#00C853;font-size:13px;font-weight:700;padding:5px 12px;border-radius:6px;">✅ Option 1</span></div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
|
||||
<!-- ════════ BIG GREEN CTA BUTTON ════════ -->
|
||||
|
|
@ -744,11 +744,10 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:12px;line-height:1.55;text-align:center;color:#64748B;"
|
||||
>You're getting this email because you're a TARGO customer at <strong style="color:#1B2E24;">{{description}}</strong>.<br />
|
||||
Got a question? Shoot us an email at
|
||||
Got a question? Feel free to email us at
|
||||
<a href="mailto:support@targo.ca" style="color:#00C853;text-decoration:none;">support@targo.ca</a>
|
||||
or give us a call at
|
||||
<a href="tel:5144480773" style="color:#00C853;text-decoration:none;">514 448-0773</a>.
|
||||
We're here 7 days/week to help!</div>
|
||||
or call us at
|
||||
<a href="tel:5144480773" style="color:#00C853;text-decoration:none;">514-448-0773</a>.</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -221,10 +221,10 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
align="left" style="font-size:0px;padding:10px 25px;padding-bottom:14px;word-break:break-word;"
|
||||
>
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#374151;"
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:justify;color:#374151;"
|
||||
>Avec l'arrivée de l'été, voici un <strong>cadeau pour toi, disponible pour un temps limité</strong>.</div>
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;font-weight:500;line-height:1.5;text-align:left;color:#1B2E24;"
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;font-weight:500;line-height:1.5;text-align:justify;color:#1B2E24;"
|
||||
>On veut te remercier pour ta loyauté envers l'achat local.<br />
|
||||
Comme toi, on aime les connexions stables et les relations durables.</div>
|
||||
|
||||
|
|
@ -237,7 +237,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
align="left" style="font-size:0px;padding:10px 25px;padding-bottom:0;word-break:break-word;"
|
||||
>
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#374151;">Grâce à la confiance de nos clients, on offre maintenant les forfaits à <strong>la plus haute vitesse dans le secteur</strong>, jusqu'à <strong>3.5 Gbit/s</strong>.<br />
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:justify;color:#374151;">Grâce à la confiance de nos clients, on offre maintenant les forfaits à <strong>la plus haute vitesse dans le secteur</strong>, jusqu'à <strong>3.5 Gbit/s</strong>.<br />
|
||||
Que tu souhaites plus de vitesse, battre une autre offre ou faire optimiser des équipements, n'hésite pas. On est juste à côté et on aime aider.</div>
|
||||
|
||||
</td>
|
||||
|
|
@ -257,6 +257,60 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
</div>
|
||||
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
|
||||
<!-- ════════ OPTION 1 CHIP ════════ -->
|
||||
|
||||
<!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:600px;" width="600" bgcolor="#ffffff" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
|
||||
|
||||
|
||||
<div style="background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:600px;">
|
||||
|
||||
<table
|
||||
align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#ffffff;background-color:#ffffff;width:100%;"
|
||||
>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td
|
||||
style="border-left:1px solid #e5e7eb;border-right:1px solid #e5e7eb;border-top:1px solid #eef0ee;direction:ltr;font-size:0px;padding:18px 36px 8px;text-align:center;"
|
||||
>
|
||||
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td style="vertical-align:top;width:526px;" ><![endif]-->
|
||||
|
||||
<div
|
||||
class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"
|
||||
>
|
||||
|
||||
<table
|
||||
border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"
|
||||
>
|
||||
<tbody>
|
||||
|
||||
<tr>
|
||||
<td
|
||||
align="left" style="font-size:0px;padding:0;word-break:break-word;"
|
||||
>
|
||||
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#1B2E24;"
|
||||
><span style="display:inline-block;background:#E6F9EE;color:#00C853;font-size:13px;font-weight:700;padding:5px 12px;border-radius:6px;">✅ Option 1</span></div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
|
||||
<!-- ════════ COMPACT INFO CARD (was 3 pills) ════════ -->
|
||||
|
|
@ -299,7 +353,7 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;font-weight:700;line-height:1.5;text-align:left;color:#1B2E24;"
|
||||
>🎁 {{amount}} chez des centaines de marques<br><br><span style="display:inline-block;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/31ffdf91-d2de-4ced-8b99-ad2221695abe/content" width="32" alt="Amazon" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/4b0b2a4a-5f99-416c-8873-8d3e4389b6f7/content" width="32" alt="Tim Hortons" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/14df433d-583c-4602-a403-d47ee84966a6/content" width="32" alt="Walmart" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/b8d3db5a-d39e-43ce-a84a-2f5dddbf0192/content" width="32" alt="Home Depot" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/9c9dfa18-2a3a-414a-b5ad-16d490c961b5/content" width="32" alt="IGA" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/a1e5f032-a192-4499-97ba-53b939712fa9/content" width="32" alt="Home Hardware" style="display:inline-block;border:0;margin-right:6px;vertical-align:middle;height:auto;"><span style="font-size:13px;color:#64748B;vertical-align:middle;font-weight:400;">et plus</span></span></div>
|
||||
>🎁 {{amount}} chez des centaines de marques<br><br><span style="display:inline-block;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/4b0b2a4a-5f99-416c-8873-8d3e4389b6f7/content" width="32" alt="Tim Hortons" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/14df433d-583c-4602-a403-d47ee84966a6/content" width="32" alt="Walmart" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/b8d3db5a-d39e-43ce-a84a-2f5dddbf0192/content" width="32" alt="Home Depot" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/9c9dfa18-2a3a-414a-b5ad-16d490c961b5/content" width="32" alt="IGA" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/a1e5f032-a192-4499-97ba-53b939712fa9/content" width="32" alt="Home Hardware" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><span style="font-size:13px;color:#64748B;vertical-align:middle;font-weight:400;">et plus</span></span></div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -347,60 +401,6 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
</div>
|
||||
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
|
||||
<!-- ════════ OPTION 1 CHIP ════════ -->
|
||||
|
||||
<!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:600px;" width="600" bgcolor="#ffffff" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
|
||||
|
||||
|
||||
<div style="background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:600px;">
|
||||
|
||||
<table
|
||||
align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#ffffff;background-color:#ffffff;width:100%;"
|
||||
>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td
|
||||
style="border-left:1px solid #e5e7eb;border-right:1px solid #e5e7eb;border-top:1px solid #eef0ee;direction:ltr;font-size:0px;padding:18px 36px 8px;text-align:center;"
|
||||
>
|
||||
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td style="vertical-align:top;width:526px;" ><![endif]-->
|
||||
|
||||
<div
|
||||
class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"
|
||||
>
|
||||
|
||||
<table
|
||||
border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"
|
||||
>
|
||||
<tbody>
|
||||
|
||||
<tr>
|
||||
<td
|
||||
align="left" style="font-size:0px;padding:0;word-break:break-word;"
|
||||
>
|
||||
|
||||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#1B2E24;"
|
||||
><span style="display:inline-block;background:#E6F9EE;color:#00C853;font-size:13px;font-weight:700;padding:5px 12px;border-radius:6px;">✅ Option 1</span></div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
|
||||
<!-- ════════ BIG GREEN CTA BUTTON ════════ -->
|
||||
|
|
@ -744,11 +744,10 @@ table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: under
|
|||
<div
|
||||
style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:12px;line-height:1.55;text-align:center;color:#64748B;"
|
||||
>Tu reçois ce courriel parce que tu es client(e) TARGO à <strong style="color:#1B2E24;">{{description}}</strong>.<br />
|
||||
Une question ? Écris à
|
||||
Une question ? N'hésite pas à nous écrire à
|
||||
<a href="mailto:support@targo.ca" style="color:#00C853;text-decoration:none;">support@targo.ca</a>
|
||||
ou appelle au
|
||||
<a href="tel:5144480773" style="color:#00C853;text-decoration:none;">514 448-0773</a>.
|
||||
Support 7j/7.</div>
|
||||
ou nous appeler au
|
||||
<a href="tel:5144480773" style="color:#00C853;text-decoration:none;">514-448-0773</a>.</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user