send email on claim requests

This commit is contained in:
JCEEE
2026-09-10 11:31:40 +01:00
parent 897e203dab
commit 27492b1558
2 changed files with 64 additions and 5 deletions
+31 -2
View File
@@ -123,7 +123,36 @@ export async function sendMentionEmail(opts: {
<p><strong>${escHtml(authorName)}</strong> mentioned you in your family chat:</p>
<blockquote style="margin:1rem 0;padding:0.6rem 1rem;border-left:3px solid #6366f1;background:#f5f5ff;color:#374151;border-radius:6px">${escHtml(message)}</blockquote>
<p><a href="${dashboardUrl}">Open your family dashboard</a> to read and reply.</p>
<p>Talk soon,<br />The FamDone team</p>
`
<p>Talk soon,<br />The FamDone team</p>
`
});
}
// A child asked to collect a reward — ping the parent(s) with the ask and a
// link straight to the Claims card on the admin dashboard.
export async function sendClaimRequestEmail(opts: {
to: string;
parentName: string;
childName: string;
rewardName: string;
rewardValue: string;
dashboardUrl: string;
}) {
const { to, parentName, childName, rewardName, rewardValue, dashboardUrl } = opts;
await resend.emails.send({
from: 'no-reply@walthamstow.xyz',
to,
subject: `${childName} asked to claim ${rewardName}`,
html: `
<p>Hi ${escHtml(parentName)},</p>
<p><strong>${escHtml(childName)}</strong> asked to collect a reward:</p>
<p>
<strong>${escHtml(rewardName)}</strong>
${rewardValue ? `— ${escHtml(rewardValue)}` : ''}
</p>
<p><a href="${dashboardUrl}">Open the Claims card on your dashboard</a> to review and issue it.</p>
<p>Talk soon,<br />The FamDone team</p>
`
});
}
@@ -1,7 +1,9 @@
import { json, error } from '@sveltejs/kit';
import type { RequestEvent } from '@sveltejs/kit';
import { createPbClient } from '$lib/server/pocketbase';
import { createPbClient, pbAdmin } from '$lib/server/pocketbase';
import { createServices } from '$lib/server/services';
import { sendClaimRequestEmail } from '$lib/server/email';
import { handleOf } from '@shared/slugify';
export async function POST(event: RequestEvent) {
const u = event.locals.user;
@@ -10,7 +12,35 @@ export async function POST(event: RequestEvent) {
const id = event.params.id!;
try {
const s = createServices(pb, { id: u.id, role: u.role });
return json(await s.rewards.claim(u.famId, id));
const record = await s.rewards.claim(u.famId, id);
// Tell the parent(s) a claim was requested — best-effort, so a mail
// outage can never fail the claim itself.
try {
const [parents, fam] = await Promise.all([
pbAdmin.getList('users', `famId = '${u.famId}' && role = 'parent'`),
pbAdmin.getOne('fams', u.famId)
]);
const label = record?.label || 'a reward';
const idx = label.indexOf(' – ');
const rewardName = idx === -1 ? label : label.slice(0, idx);
const rewardValue = idx === -1 ? '' : label.slice(idx + 3);
for (const parent of parents) {
if (!parent.email) continue;
await sendClaimRequestEmail({
to: parent.email,
parentName: parent.name || 'there',
childName: u.name || 'Someone',
rewardName,
rewardValue,
dashboardUrl: `${event.url.origin}/${fam?.slug || u.famId}/${handleOf(parent.username)}`
});
}
} catch {
// Best-effort only — the claim already succeeded.
}
return json(record);
} catch (e) {
return json({ error: e instanceof Error ? e.message : 'claim failed' }, { status: 400 });
}