Templating for names and surnames
This commit is contained in:
@@ -16,6 +16,16 @@ interface EmailResult {
|
|||||||
error?: string;
|
error?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces template variables in a string with participant data
|
||||||
|
* Currently supports {name} and {surname} placeholders
|
||||||
|
*/
|
||||||
|
function replaceTemplateVariables(template: string, participant: Participant): string {
|
||||||
|
return template
|
||||||
|
.replace(/{name}/gi, participant.name || '')
|
||||||
|
.replace(/{surname}/gi, participant.surname || '');
|
||||||
|
}
|
||||||
|
|
||||||
async function generateQRCode(participantId: string): Promise<string> {
|
async function generateQRCode(participantId: string): Promise<string> {
|
||||||
const qrCodeBase64 = await QRCode.toDataURL(participantId, {
|
const qrCodeBase64 = await QRCode.toDataURL(participantId, {
|
||||||
type: 'image/png',
|
type: 'image/png',
|
||||||
@@ -38,11 +48,15 @@ async function sendEmailToParticipant(
|
|||||||
try {
|
try {
|
||||||
const qrCodeBase64Data = await generateQRCode(participant.id);
|
const qrCodeBase64Data = await generateQRCode(participant.id);
|
||||||
|
|
||||||
|
// Replace template variables in subject and body
|
||||||
|
const personalizedSubject = replaceTemplateVariables(subject, participant);
|
||||||
|
const personalizedText = replaceTemplateVariables(text, participant);
|
||||||
|
|
||||||
// Send email with QR code
|
// Send email with QR code
|
||||||
await sendGmail(refreshToken, {
|
await sendGmail(refreshToken, {
|
||||||
to: participant.email,
|
to: participant.email,
|
||||||
subject: subject,
|
subject: personalizedSubject,
|
||||||
text: text,
|
text: personalizedText,
|
||||||
qr_code: qrCodeBase64Data
|
qr_code: qrCodeBase64Data
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -6,38 +6,69 @@
|
|||||||
};
|
};
|
||||||
errors: Record<string, string>;
|
errors: Record<string, string>;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const templateVariables = [
|
||||||
|
{ name: '{name}', description: "Participant's first name" },
|
||||||
|
{ name: '{surname}', description: "Participant's last name" }
|
||||||
|
];
|
||||||
|
|
||||||
|
const subjectTemplatesDetected = $derived(
|
||||||
|
templateVariables.filter((v) => emailData.subject && emailData.subject.includes(v.name))
|
||||||
|
);
|
||||||
|
const bodyTemplatesDetected = $derived(
|
||||||
|
templateVariables.filter((v) => emailData.body && emailData.body.includes(v.name))
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="space-y-6">
|
<div class="space-y-6">
|
||||||
<div>
|
<div>
|
||||||
<label for="emailSubject" class="block text-sm font-medium text-gray-700 mb-2">
|
<label for="emailSubject" class="mb-2 block text-sm font-medium text-gray-700">
|
||||||
Email Subject *
|
Email Subject *
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="emailSubject"
|
id="emailSubject"
|
||||||
type="text"
|
type="text"
|
||||||
bind:value={emailData.subject}
|
bind:value={emailData.subject}
|
||||||
class="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
class="w-full rounded border border-gray-300 px-3 py-2 focus:border-transparent focus:ring-2 focus:ring-blue-500 focus:outline-none"
|
||||||
placeholder="Event invitation subject"
|
placeholder="Event invitation subject"
|
||||||
/>
|
/>
|
||||||
|
{#if subjectTemplatesDetected.length > 0}
|
||||||
|
<p class="mt-1 text-xs text-gray-500">
|
||||||
|
Detected templates: {subjectTemplatesDetected.map((v) => v.name).join(', ')}
|
||||||
|
</p>
|
||||||
|
{/if}
|
||||||
{#if errors.subject}
|
{#if errors.subject}
|
||||||
<p class="mt-1 text-sm text-red-600">{errors.subject}</p>
|
<p class="text-sm text-red-600">{errors.subject}</p>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label for="emailBody" class="block text-sm font-medium text-gray-700 mb-2">
|
<label for="emailBody" class="mb-2 block text-sm font-medium text-gray-700">
|
||||||
Email Body *
|
Email Body *
|
||||||
</label>
|
</label>
|
||||||
<textarea
|
<textarea
|
||||||
id="emailBody"
|
id="emailBody"
|
||||||
bind:value={emailData.body}
|
bind:value={emailData.body}
|
||||||
rows="8"
|
rows="8"
|
||||||
class="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
class="w-full rounded border border-gray-300 px-3 py-2 focus:border-transparent focus:ring-2 focus:ring-blue-500 focus:outline-none"
|
||||||
placeholder="Email message content..."
|
placeholder="Email message content..."
|
||||||
></textarea>
|
></textarea>
|
||||||
|
{#if bodyTemplatesDetected.length > 0}
|
||||||
|
<p class="text-xs text-gray-500">
|
||||||
|
Detected templates: {bodyTemplatesDetected.map((v) => v.name).join(', ')}
|
||||||
|
</p>
|
||||||
|
{/if}
|
||||||
{#if errors.body}
|
{#if errors.body}
|
||||||
<p class="mt-1 text-sm text-red-600">{errors.body}</p>
|
<p class="mt-1 text-sm text-red-600">{errors.body}</p>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p class="mt-2 mb-2 block text-sm font-medium text-gray-700">Tip:</p>
|
||||||
|
<p class="text-xs text-gray-500">
|
||||||
|
Use <code class="rounded bg-gray-100 px-1 py-0.5 text-xs">{name}</code> and
|
||||||
|
<code class="rounded bg-gray-100 px-1 py-0.5 text-xs">{surname}</code> to personalize
|
||||||
|
your message. Works for both subject and body. (e.g., "Hello {name}, welcome to our event!")
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ export async function getEvents(supabase: SupabaseClient, searchTerm: string = '
|
|||||||
try {
|
try {
|
||||||
const searchPattern = searchTerm.trim() ? `%${searchTerm}%` : null;
|
const searchPattern = searchTerm.trim() ? `%${searchTerm}%` : null;
|
||||||
|
|
||||||
console.log('Actually fetching!');
|
|
||||||
|
|
||||||
// Build regular events query
|
// Build regular events query
|
||||||
let regularQuery = supabase
|
let regularQuery = supabase
|
||||||
.from('events')
|
.from('events')
|
||||||
|
|||||||
Reference in New Issue
Block a user