fix: require email on registration, BCC contact@ on confirmations, update OG image

- Add required email field to registration form (was missing entirely,
  causing "N/A" emails in booking notifications)
- Pass email through full chain: form → API → Google Sheet → Mollie
  metadata → webhook (with Mollie billingAddress as fallback)
- BCC contact@cryptocommonsgather.ing on all payment confirmation
  emails so team is notified of every successful registration
- Replace OG image with alpine mountain card including event name,
  dates, and URL for better Twitter/social sharing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-03-10 10:58:46 -07:00
parent 45b94e4ed2
commit eaf2c0ac31
6 changed files with 25 additions and 3 deletions

View File

@ -53,6 +53,7 @@ export async function POST(request: NextRequest) {
const metadata: Record<string, string> = {}
if (registrationData) {
metadata.name = registrationData.name || ""
metadata.email = registrationData.email || ""
metadata.contact = registrationData.contact || ""
metadata.contributions = (registrationData.contributions || "").substring(0, 500)
metadata.expectations = (registrationData.expectations || "").substring(0, 500)

View File

@ -5,10 +5,10 @@ export async function POST(request: NextRequest) {
try {
const body = await request.json()
const { name, contact, contributions, expectations, howHeard, dietary, crewConsent } = body
const { name, email, contact, contributions, expectations, howHeard, dietary, crewConsent } = body
// Validate required fields
if (!name || !contact || !contributions || !expectations || !crewConsent) {
if (!name || !email || !contact || !contributions || !expectations || !crewConsent) {
return NextResponse.json(
{ error: "Missing required fields" },
{ status: 400 }
@ -21,6 +21,7 @@ export async function POST(request: NextRequest) {
// Add registration to Google Sheet
const rowNumber = await addRegistration({
name,
email,
contact,
contributions,
expectations,

View File

@ -33,7 +33,7 @@ export async function POST(request: NextRequest) {
console.log(`[Webhook] Payment ${paymentId} status: ${payment.status}`)
if (payment.status === "paid") {
const customerEmail = payment.billingAddress?.email || ""
const customerEmail = metadata.email || payment.billingAddress?.email || ""
const amountPaid = `${payment.amount.value}`
const accommodationType = metadata.accommodation || "none"

View File

@ -20,6 +20,7 @@ export default function RegisterPage() {
const [accommodationType, setAccommodationType] = useState("ch-multi")
const [formData, setFormData] = useState({
name: "",
email: "",
contact: "",
contributions: "",
expectations: "",
@ -50,6 +51,7 @@ export default function RegisterPage() {
// Validate required fields
if (
!formData.name ||
!formData.email ||
!formData.contact ||
!formData.contributions ||
!formData.expectations ||
@ -74,6 +76,7 @@ export default function RegisterPage() {
},
body: JSON.stringify({
name: formData.name,
email: formData.email,
contact: formData.contact,
contributions: formData.contributions,
expectations: formData.expectations,
@ -494,6 +497,22 @@ export default function RegisterPage() {
/>
</div>
{/* Email */}
<div className="space-y-2">
<Label htmlFor="email">Email address *</Label>
<Input
id="email"
type="email"
required
placeholder="your@email.com"
value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
/>
<p className="text-sm text-muted-foreground">
We&apos;ll send your registration confirmation and event updates here.
</p>
</div>
{/* Contact */}
<div className="space-y-2">
<Label htmlFor="contact">How can we contact you besides via email? *</Label>

View File

@ -179,6 +179,7 @@ export async function sendPaymentConfirmation(
const info = await transport.sendMail({
from: EMAIL_FROM,
to: data.email,
bcc: INTERNAL_NOTIFY_EMAIL,
subject: "Registration Confirmed - Crypto Commons Gathering 2026",
html,
})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 266 KiB

After

Width:  |  Height:  |  Size: 101 KiB