Add the Workshops page and keep each sign-up on the site.
The form is built once to the settled field set, and a valid send is saved before anyone is emailed. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
974a5ace4c
commit
c0ba3a3798
50 files changed
+2773
-1
No files matched your search
@@ -0,0 +1,90 @@
|
||||
import type { WorkshopFormValues } from "./workshopSignup";
|
||||
|
||||
export interface WorkshopInquiryMailInput {
|
||||
values: WorkshopFormValues;
|
||||
routeNote: string;
|
||||
largeOrganization: boolean;
|
||||
requestId: string;
|
||||
schedulingUrl: string;
|
||||
}
|
||||
|
||||
function line(label: string, value: string): string {
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length > 0 ? `${label}: ${trimmed}` : `${label}:`;
|
||||
}
|
||||
|
||||
/** Inbox note for the team. Includes the answers and a route. No price. */
|
||||
export function buildWorkshopInboxMail(input: WorkshopInquiryMailInput): {
|
||||
subject: string;
|
||||
text: string;
|
||||
html: string;
|
||||
} {
|
||||
const { values } = input;
|
||||
const challenges = values.challenges.join(", ");
|
||||
const text = [
|
||||
`Request ID: ${input.requestId}`,
|
||||
line("Organization", values.organizationName),
|
||||
line("Kind", values.organizationKind),
|
||||
line("Members", values.memberCount),
|
||||
`Large organization: ${input.largeOrganization ? "yes" : "no"}`,
|
||||
line("Route", input.routeNote),
|
||||
line("Name", values.contactName),
|
||||
line("Email", values.email),
|
||||
line("Role", values.role),
|
||||
line("Challenges", challenges),
|
||||
line("Something else", values.challengeOther),
|
||||
line("Unspoken question", values.unspokenQuestion),
|
||||
line("Page", values.sourcePage),
|
||||
line("Link", values.sourceUrl),
|
||||
].join("\n");
|
||||
|
||||
const html = text
|
||||
.split("\n")
|
||||
.map((row) => `<p>${escapeHtml(row)}</p>`)
|
||||
.join("");
|
||||
|
||||
return {
|
||||
subject: `Workshop inquiry from ${values.organizationName}`,
|
||||
text,
|
||||
html,
|
||||
};
|
||||
}
|
||||
|
||||
/** Confirmation to the person who wrote. Promises two working days and names no price. */
|
||||
export function buildWorkshopConfirmationMail(input: {
|
||||
largeOrganization: boolean;
|
||||
schedulingUrl: string;
|
||||
}): { subject: string; text: string; html: string } {
|
||||
const subject = "We received your workshop note";
|
||||
const intro =
|
||||
"Thank you. A facilitator will read this closely and write back within two working days.";
|
||||
const next = input.largeOrganization
|
||||
? "Organizations of this size start with a call."
|
||||
: "The kit has the four questions and the thirteen templates if you want a head start.";
|
||||
const schedule =
|
||||
input.largeOrganization && input.schedulingUrl.trim().length > 0
|
||||
? `Choose a time: ${input.schedulingUrl.trim()}`
|
||||
: "";
|
||||
const text = [intro, next, schedule].filter((part) => part.length > 0).join("\n\n");
|
||||
const html =
|
||||
`<div style="background:#141414;padding:24px 32px;">` +
|
||||
`<p style="margin:0;font-family:Inter,Arial,sans-serif;font-size:14px;letter-spacing:0.08em;color:#ffffff;">COMMUNITYRULE</p>` +
|
||||
`</div>` +
|
||||
`<div style="background:#ffffff;padding:32px;font-family:Inter,Arial,sans-serif;color:#141414;">` +
|
||||
`<p>${escapeHtml(intro)}</p>` +
|
||||
`<p>${escapeHtml(next)}</p>` +
|
||||
(schedule
|
||||
? `<p><a href="${escapeHtml(input.schedulingUrl.trim())}">Choose a time</a></p>`
|
||||
: "") +
|
||||
`</div>`;
|
||||
|
||||
return { subject, text, html };
|
||||
}
|
||||
|
||||
function escapeHtml(value: string): string {
|
||||
return value
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """);
|
||||
}
|
||||
Reference in new issue
Block a user