GRV-Summit-Site/components/exhibit/ExhibitorBoothForm.tsx
kirukib cb404ec079
Some checks failed
Deploy to Cloudflare Workers (OpenNext) / deploy (push) Has been cancelled
Align site colors with GRV brand book palette.
Centralize primary, secondary, tertiary, and neutral tokens and apply them across theme variables and UI components.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 14:45:22 +03:00

265 lines
9.6 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { useState } from "react";
import { boothSizes, exhibitorSectors } from "@/content/exhibit";
import { DataConsentField } from "@/components/forms/DataConsentField";
import { dataConsent } from "@/content/consent";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Checkbox } from "@/components/ui/checkbox";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
export function ExhibitorBoothForm() {
const [status, setStatus] = useState<"idle" | "loading" | "success" | "error">("idle");
const [error, setError] = useState("");
const [consent, setConsent] = useState(false);
const [sector, setSector] = useState("");
const [boothSize, setBoothSize] = useState("");
async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
if (!consent) {
setError(dataConsent.errorMessage);
return;
}
if (!sector) {
setError("Please select your industry / sector.");
return;
}
if (!boothSize) {
setError("Please select a preferred booth size.");
return;
}
setStatus("loading");
setError("");
const form = e.currentTarget;
const data = new FormData(form);
try {
const res = await fetch("/api/inquiry", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
intent: "exhibitor",
firstName: data.get("firstName"),
lastName: data.get("lastName"),
name: `${data.get("firstName")} ${data.get("lastName")}`,
email: data.get("email"),
phone: data.get("phone"),
jobTitle: data.get("jobTitle"),
company: data.get("company"),
companyWebsite: data.get("companyWebsite") || undefined,
companyDescription: data.get("companyDescription"),
sector,
productsToAdvertise: data.get("productsToAdvertise"),
boothSize,
powerRequired: data.get("powerRequired") === "on",
internetRequired: data.get("internetRequired") === "on",
staffCount: data.get("staffCount") || undefined,
marketingMaterials: data.get("marketingMaterials") || undefined,
specialRequirements: data.get("specialRequirements") || undefined,
message: data.get("boothGoals"),
consent: true,
}),
});
const json = await res.json();
if (!res.ok || !json.ok) {
throw new Error(json.error || "Something went wrong");
}
setStatus("success");
form.reset();
setConsent(false);
setSector("");
setBoothSize("");
} catch (err) {
setStatus("error");
setError(err instanceof Error ? err.message : "Failed to send");
}
}
return (
<form onSubmit={onSubmit} className="space-y-6 rounded-2xl border border-border bg-white p-6 shadow-sm md:p-8">
<div className="space-y-1">
<h3 className="text-xl font-bold">Reserve your booth</h3>
<p className="text-sm text-muted-foreground">
Tell us about your company and what you plan to showcase. Our team will confirm
availability and send package details.
</p>
</div>
<fieldset className="space-y-4">
<legend className="text-sm font-semibold uppercase tracking-wider text-[#30614c]">
Contact
</legend>
<div className="grid gap-4 sm:grid-cols-2">
<div className="space-y-2">
<Label htmlFor="booth-firstName">First name *</Label>
<Input id="booth-firstName" name="firstName" required autoComplete="given-name" />
</div>
<div className="space-y-2">
<Label htmlFor="booth-lastName">Last name *</Label>
<Input id="booth-lastName" name="lastName" required autoComplete="family-name" />
</div>
</div>
<div className="grid gap-4 sm:grid-cols-2">
<div className="space-y-2">
<Label htmlFor="booth-email">Work email *</Label>
<Input id="booth-email" name="email" type="email" required autoComplete="email" />
</div>
<div className="space-y-2">
<Label htmlFor="booth-phone">Phone *</Label>
<Input id="booth-phone" name="phone" type="tel" required placeholder="+251 …" />
</div>
</div>
<div className="grid gap-4 sm:grid-cols-2">
<div className="space-y-2">
<Label htmlFor="booth-jobTitle">Job title *</Label>
<Input id="booth-jobTitle" name="jobTitle" required placeholder="e.g. Marketing Director" />
</div>
<div className="space-y-2">
<Label htmlFor="booth-company">Company / organization *</Label>
<Input id="booth-company" name="company" required />
</div>
</div>
</fieldset>
<fieldset className="space-y-4">
<legend className="text-sm font-semibold uppercase tracking-wider text-[#30614c]">
Company & products
</legend>
<div className="space-y-2">
<Label htmlFor="booth-website">Company website</Label>
<Input id="booth-website" name="companyWebsite" type="url" placeholder="https://" />
</div>
<div className="space-y-2">
<Label>Industry / sector *</Label>
<Select value={sector} onValueChange={setSector}>
<SelectTrigger>
<SelectValue placeholder="Select sector" />
</SelectTrigger>
<SelectContent>
{exhibitorSectors.map((s) => (
<SelectItem key={s} value={s}>
{s}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label htmlFor="booth-companyDescription">About your company *</Label>
<Textarea
id="booth-companyDescription"
name="companyDescription"
required
rows={3}
placeholder="What does your organization do? Who is your audience?"
/>
</div>
<div className="space-y-2">
<Label htmlFor="booth-products">Products & services to advertise *</Label>
<Textarea
id="booth-products"
name="productsToAdvertise"
required
rows={4}
placeholder="List products, demos, or services you plan to promote at your booth. Include models, SKUs, or launch items if relevant."
/>
</div>
<div className="space-y-2">
<Label htmlFor="booth-marketing">Marketing materials & displays</Label>
<Textarea
id="booth-marketing"
name="marketingMaterials"
rows={3}
placeholder="Banners, brochures, samples, screens, interactive demos…"
/>
</div>
</fieldset>
<fieldset className="space-y-4">
<legend className="text-sm font-semibold uppercase tracking-wider text-[#30614c]">
Booth requirements
</legend>
<div className="space-y-2">
<Label>Preferred booth size *</Label>
<Select value={boothSize} onValueChange={setBoothSize}>
<SelectTrigger>
<SelectValue placeholder="Select booth type" />
</SelectTrigger>
<SelectContent>
{boothSizes.map((b) => (
<SelectItem key={b.value} value={b.value}>
{b.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="grid gap-4 sm:grid-cols-2">
<div className="space-y-2">
<Label htmlFor="booth-staff">Staff attending (approx.)</Label>
<Input id="booth-staff" name="staffCount" type="number" min={1} max={50} placeholder="e.g. 3" />
</div>
</div>
<div className="flex flex-wrap gap-6">
<label className="flex items-center gap-2 text-sm">
<Checkbox name="powerRequired" />
Need dedicated power
</label>
<label className="flex items-center gap-2 text-sm">
<Checkbox name="internetRequired" />
Need WiFi / internet
</label>
</div>
<div className="space-y-2">
<Label htmlFor="booth-goals">Booth goals *</Label>
<Textarea
id="booth-goals"
name="boothGoals"
required
rows={3}
placeholder="Lead generation, product launch, partnerships, hiring, etc."
/>
</div>
<div className="space-y-2">
<Label htmlFor="booth-special">Special requirements</Label>
<Textarea
id="booth-special"
name="specialRequirements"
rows={2}
placeholder="Accessibility, refrigeration, extra storage, setup time…"
/>
</div>
</fieldset>
<DataConsentField id="booth-consent" checked={consent} onCheckedChange={setConsent} />
{error && <p className="text-sm text-destructive">{error}</p>}
{status === "success" && (
<p className="text-sm text-[#30614c]">
Thank you! We received your booth request and will follow up with availability and pricing.
</p>
)}
<Button
type="submit"
className="w-full rounded-full bg-[#37a47a] text-[#ffffff] hover:bg-[#37a47a]/90 sm:w-auto"
disabled={status === "loading"}
>
{status === "loading" ? "Submitting…" : "Submit booth request"}
</Button>
</form>
);
}