Files
MeetPaprika/components/forms/SubmissionForm.tsx

151 lines
5.6 KiB
TypeScript

"use client";
import { useRouter } from "next/navigation";
import { useState, type FormEvent } from "react";
type FormType = "start" | "ask";
type FieldErrors = Record<string, string[] | undefined>;
export function SubmissionForm({ type }: { type: FormType }) {
const router = useRouter();
const [errors, setErrors] = useState<FieldErrors>({});
const [status, setStatus] = useState<"idle" | "submitting" | "error">("idle");
async function handleSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
setErrors({});
setStatus("submitting");
const form = new FormData(event.currentTarget);
const payload = Object.fromEntries(form.entries());
const response = await fetch("/api/submissions", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
...payload,
type,
consentAccepted: form.get("consentAccepted") === "on",
sourcePath: type === "start" ? "/start" : "/ask"
})
});
const result = await response.json().catch(() => ({}));
if (!response.ok) {
setErrors(result.issues || { form: [result.error || "Submission failed"] });
setStatus("error");
return;
}
router.push(`/thanks?submission_id=${encodeURIComponent(result.submission_id)}`);
}
return (
<form className="form-wrap" onSubmit={handleSubmit}>
<label className="field">
Name <span className="req">*</span>
<input className="field-control" name="name" autoComplete="name" required />
<FieldError errors={errors} name="name" />
</label>
<label className="field">
Email <span className="req">*</span>
<input className="field-control" name="email" type="email" autoComplete="email" required />
<FieldError errors={errors} name="email" />
</label>
<label className="field">
LinkedIn {type === "ask" ? <span>(optional)</span> : null}
<input className="field-control" name="linkedin" type="url" placeholder="https://linkedin.com/in/..." />
<FieldError errors={errors} name="linkedin" />
</label>
{type === "start" ? <StartFields errors={errors} /> : <AskFields errors={errors} />}
<label className="field large checkbox-field">
<input name="consentAccepted" type="checkbox" required />
<span>
I understand that submitting this form does not create an attorney-client relationship or
constitute legal advice. Paprika is not a law firm and does not provide legal services.
</span>
<FieldError errors={errors} name="consentAccepted" />
</label>
{errors.form?.length ? <div className="form-error">{errors.form[0]}</div> : null}
<button className="button primary" type="submit" disabled={status === "submitting"}>
{status === "submitting" ? "Submitting..." : type === "start" ? "Submit Profile" : "Send Question"}
</button>
<div className="form-note">
File upload is intentionally disabled until storage, size limits, access control, and privacy
handling are approved.
</div>
</form>
);
}
function StartFields({ errors }: { errors: FieldErrors }) {
return (
<>
<label className="field">
Company Website
<input className="field-control" name="companyWebsite" type="url" placeholder="https://..." />
<FieldError errors={errors} name="companyWebsite" />
</label>
<label className="field">
Current Role / Company
<input className="field-control" name="currentRoleCompany" />
</label>
<label className="field">
Field or Industry
<input className="field-control" name="fieldOrIndustry" />
</label>
<label className="field large start-question-field">
<strong>
What brings you to Paprika? <span className="req">*</span>
</strong>
<span>
Tell us where you are in your O-1 journey. Whether you have a specific goal, are building
evidence early, or are just exploring, a quick summary is enough.
</span>
<textarea className="field-control" name="reason" required />
<FieldError errors={errors} name="reason" />
</label>
<label className="field large start-question-field">
<strong>What recognition have you already built, if any?</strong>
<span>
Press, interviews, judging roles, awards, speaking, scholarly articles, patents, funding,
major projects, or other recognition.
</span>
<textarea className="field-control" name="existingRecognition" />
</label>
<label className="field large start-question-field">
<strong>Is there a timeline on your mind?</strong>
<span>
Whether it is urgent, months away, or just a future possibility, an approximate timeline
helps us recommend the right pace.
</span>
<textarea className="field-control" name="timeline" />
</label>
</>
);
}
function AskFields({ errors }: { errors: FieldErrors }) {
return (
<label className="field large question-field">
<strong>
Your question <span className="req">*</span>
</strong>
<span>Ask us anything about our services, your situation, or where to start.</span>
<textarea className="field-control" name="question" required />
<FieldError errors={errors} name="question" />
</label>
);
}
function FieldError({ errors, name }: { errors: FieldErrors; name: string }) {
const message = errors[name]?.[0];
return message ? <span className="form-error">{message}</span> : null;
}