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,94 @@
|
||||
"use client";
|
||||
|
||||
import { memo, useState, type FormEvent } from "react";
|
||||
import {
|
||||
EMPTY_WORKSHOP_FORM_VALUES,
|
||||
WORKSHOP_HONEYPOT_FIELD,
|
||||
WORKSHOP_STARTED_AT_FIELD,
|
||||
} from "../../../../lib/workshopSignup";
|
||||
import WorkshopSignupView from "./WorkshopSignup.view";
|
||||
import type { WorkshopSignupProps, WorkshopSignupStatus } from "./WorkshopSignup.types";
|
||||
|
||||
/** Figma: "Section / Workshop Signup" (24323:55538). Full field set at every width. */
|
||||
function WorkshopSignupContainer({
|
||||
className,
|
||||
issuedAt,
|
||||
schedulingUrl = "",
|
||||
sourceUrl = "",
|
||||
initialStatus = "idle",
|
||||
initialLarge = false,
|
||||
initialValues = EMPTY_WORKSHOP_FORM_VALUES,
|
||||
initialFieldErrors = {},
|
||||
}: WorkshopSignupProps) {
|
||||
const [status, setStatus] = useState<WorkshopSignupStatus>(initialStatus);
|
||||
const [largeOrganization, setLargeOrganization] = useState(initialLarge);
|
||||
const [fieldErrors, setFieldErrors] = useState(initialFieldErrors);
|
||||
|
||||
const onSubmit = async (event: FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
const data = new FormData(event.currentTarget);
|
||||
setStatus("sending");
|
||||
try {
|
||||
const response = await fetch("/api/workshop-signup", {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/json", accept: "application/json" },
|
||||
body: JSON.stringify({
|
||||
challenges: data.getAll("challenges"),
|
||||
challengeOther: data.get("challengeOther"),
|
||||
unspokenQuestion: data.get("unspokenQuestion"),
|
||||
organizationName: data.get("organizationName"),
|
||||
organizationKind: data.get("organizationKind"),
|
||||
memberCount: data.get("memberCount"),
|
||||
contactName: data.get("contactName"),
|
||||
email: data.get("email"),
|
||||
role: data.get("role"),
|
||||
sourcePage: "/workshops",
|
||||
sourceUrl,
|
||||
[WORKSHOP_HONEYPOT_FIELD]: data.get(WORKSHOP_HONEYPOT_FIELD),
|
||||
[WORKSHOP_STARTED_AT_FIELD]: Number(data.get(WORKSHOP_STARTED_AT_FIELD) ?? issuedAt),
|
||||
}),
|
||||
});
|
||||
const body = (await response.json()) as {
|
||||
status?: string;
|
||||
largeOrganization?: boolean;
|
||||
fieldErrors?: WorkshopSignupProps["initialFieldErrors"];
|
||||
};
|
||||
if (body.status === "sent") {
|
||||
setLargeOrganization(Boolean(body.largeOrganization));
|
||||
setFieldErrors({});
|
||||
setStatus("sent");
|
||||
return;
|
||||
}
|
||||
if (body.status === "invalid") {
|
||||
setFieldErrors(body.fieldErrors ?? {});
|
||||
setStatus("invalid");
|
||||
return;
|
||||
}
|
||||
if (body.status === "rate_limited" || response.status === 429) {
|
||||
setStatus("rate_limited");
|
||||
return;
|
||||
}
|
||||
setStatus("failed");
|
||||
} catch {
|
||||
setStatus("failed");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<WorkshopSignupView
|
||||
className={className ?? ""}
|
||||
issuedAt={issuedAt}
|
||||
schedulingUrl={schedulingUrl}
|
||||
sourceUrl={sourceUrl}
|
||||
status={status}
|
||||
largeOrganization={largeOrganization}
|
||||
values={initialValues}
|
||||
fieldErrors={fieldErrors}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
WorkshopSignupContainer.displayName = "WorkshopSignup";
|
||||
|
||||
export default memo(WorkshopSignupContainer);
|
||||
Reference in new issue
Block a user