"use client" import { useEffect, useMemo, useState } from "react" import { useForm } from "react-hook-form" import { AlertCircle, CheckCircle, ClipboardCheck, PhoneCall, } from "lucide-react" import { FormButton } from "./form-button" import { FormInput } from "./form-input" import { FormTextarea } from "./form-textarea" import { SmsConsentFields } from "./sms-consent-fields" import { Checkbox } from "@/components/ui/checkbox" import { PublicSectionHeader } from "@/components/public-surface" import { businessConfig } from "@/lib/seo-config" import { SMS_CONSENT_VERSION } from "@/lib/sms-compliance" interface RequestMachineFormData { firstName: string lastName: string email: string phone: string company: string employeeCount: string machineType: string machineCount: string message?: string serviceTextConsent: boolean marketingTextConsent: boolean consentVersion: string consentCapturedAt: string consentSourcePage: string confirmEmail?: string source?: string page?: string } interface RequestMachineFormProps { onSubmit?: (data: RequestMachineFormData) => void className?: string } const MACHINE_TYPE_OPTIONS = [ { label: "Snack vending machine", value: "snack" }, { label: "Beverage vending machine", value: "beverage" }, { label: "Combo snack + beverage", value: "combo" }, { label: "Cold food vending machine", value: "cold-food" }, { label: "Hot food vending machine", value: "hot-food" }, { label: "Coffee vending machine", value: "coffee" }, { label: "Micro market", value: "micro-market" }, { label: "Other / not sure yet", value: "other" }, ] as const export function RequestMachineForm({ onSubmit, className, }: RequestMachineFormProps) { const [isSubmitting, setIsSubmitting] = useState(false) const [isSubmitted, setIsSubmitted] = useState(false) const [submitError, setSubmitError] = useState(null) const { register, handleSubmit, formState: { errors }, reset, setValue, watch, } = useForm({ defaultValues: { source: "website", page: "", serviceTextConsent: false, marketingTextConsent: false, consentVersion: SMS_CONSENT_VERSION, consentCapturedAt: "", consentSourcePage: "", machineType: "", }, }) const watchedValues = watch() const canSubmit = Boolean(watchedValues.serviceTextConsent) const selectedMachineTypes = useMemo( () => watchedValues.machineType ? watchedValues.machineType.split(",").filter(Boolean) : [], [watchedValues.machineType] ) useEffect(() => { if (typeof window !== "undefined") { const pathname = window.location.pathname setValue("page", pathname) setValue("consentSourcePage", pathname) setValue("consentVersion", SMS_CONSENT_VERSION) } }, [setValue]) const buildResetValues = () => ({ source: "website", page: typeof window !== "undefined" ? window.location.pathname : "", serviceTextConsent: false, marketingTextConsent: false, consentVersion: SMS_CONSENT_VERSION, consentCapturedAt: "", consentSourcePage: typeof window !== "undefined" ? window.location.pathname : "", machineType: "", firstName: "", lastName: "", email: "", phone: "", company: "", employeeCount: "", machineCount: "", message: "", confirmEmail: "", }) const updateMachineType = (value: string, checked: boolean) => { const nextValues = checked ? [...selectedMachineTypes, value] : selectedMachineTypes.filter((item) => item !== value) setValue("machineType", Array.from(new Set(nextValues)).join(","), { shouldValidate: true, }) } const onFormSubmit = async (data: RequestMachineFormData) => { setIsSubmitting(true) setSubmitError(null) try { const consentCapturedAt = new Date().toISOString() const formData = { ...data, consentCapturedAt, consentSourcePage: data.consentSourcePage || data.page || window.location.pathname, consentVersion: data.consentVersion || SMS_CONSENT_VERSION, timestamp: consentCapturedAt, url: window.location.href, } const response = await fetch("/api/request-machine", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(formData), }) const result = await response.json() if (!response.ok || !result.success) { throw new Error( result.error || result.message || "Failed to submit form" ) } setIsSubmitted(true) reset(buildResetValues()) if (onSubmit) { onSubmit(formData) } } catch (error) { console.error("Form submission error:", error) setSubmitError( "We couldn't send that right now. Please try again or call us." ) } finally { setIsSubmitting(false) } } const onFormReset = () => { setIsSubmitted(false) setSubmitError(null) reset(buildResetValues()) } if (isSubmitted) { return (

Your request is in.

We'll review your location details and call you within one business day.

Submit Another Location
) } return (
{ const phoneDigits = value.replace(/\D/g, "") return phoneDigits.length >= 10 && phoneDigits.length <= 15 ? true : "Please enter a valid phone number" }, })} /> { const num = Number(value) return num >= 1 && num <= 10000 ? true : "Please enter a number between 1 and 10,000" }, })} />
{MACHINE_TYPE_OPTIONS.map((option) => { const isChecked = selectedMachineTypes.includes(option.value) return ( ) })}
{errors.machineType ? (

{errors.machineType.message}

) : null}
{ const num = Number(value) return num >= 1 && num <= 100 ? true : "Please enter a number between 1 and 100" }, })} />
What we look at

We'll review your foot traffic, the type of location, and the mix of machines that fits best before we schedule the consultation.

setValue("serviceTextConsent", checked, { shouldValidate: true }) } serviceError={errors.serviceTextConsent?.message} />
{submitError ? (
{submitError}
) : null}
{isSubmitting ? "Submitting..." : "Request Free Placement"} Call
value || "Please agree to receive service-related SMS for this request", })} />
) }