"use client" import { cn } from "@mdxui/primitives/lib/utils" import { Button } from "@mdxui/primitives/button" import { Input } from "@mdxui/primitives/input" import { Textarea } from "@mdxui/primitives/textarea" import { Label } from "@mdxui/primitives/label" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@mdxui/primitives/select" import { useState, useEffect } from "react" import type { ContactData, ContactUser } from "./types" const DEFAULT_TOPICS = ['Sales', 'Support', 'Partnership', 'Other'] const DEFAULT_COMPANY_SIZE_OPTIONS = ['1-10', '11-50', '51-200', '201-500', '500+'] interface ContactContentProps { showName?: boolean showEmail?: boolean showCompanyName?: boolean showCompanySize?: boolean showTopic?: boolean showMessage?: boolean showAdditionalInfo?: boolean requireName?: boolean requireEmail?: boolean requireCompanyName?: boolean requireCompanySize?: boolean requireTopic?: boolean requireMessage?: boolean requireAdditionalInfo?: boolean topics?: string[] companySizeOptions?: string[] rows?: string[][] user?: ContactUser context?: Record captureMetadata?: boolean sessionId?: string correlationId?: string appVersion?: string environment?: string onSubmit?: (data: ContactData) => Promise | void apiEndpoint?: string submitLabel?: string onSuccess: () => void onError: (error: string) => void } interface MetadataOptions { sessionId?: string correlationId?: string appVersion?: string environment?: string } // Track page load time for timeOnPage calculation const pageLoadTime = typeof window !== 'undefined' ? Date.now() : 0 function captureCurrentMetadata(options: MetadataOptions = {}) { const timeOnPage = Date.now() - pageLoadTime return { // Page context url: window.location.href, timestamp: new Date().toISOString(), viewport: { width: window.innerWidth, height: window.innerHeight }, userAgent: navigator.userAgent, // Navigation context referrer: document.referrer || undefined, pageTitle: document.title || undefined, timeOnPage, // Device details locale: navigator.language, timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, screenResolution: { width: screen.width, height: screen.height }, // Session tracking (from props) sessionId: options.sessionId, correlationId: options.correlationId, // App context (from props) appVersion: options.appVersion, environment: options.environment, } } function isValidEmail(email: string): boolean { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email) } type FieldName = 'name' | 'email' | 'companyName' | 'companySize' | 'topic' | 'message' | 'additionalInfo' export function ContactContent({ showName = true, showEmail = true, showCompanyName = false, showCompanySize = false, showTopic = true, showMessage = true, showAdditionalInfo = false, requireName = true, requireEmail = true, requireCompanyName = false, requireCompanySize = false, requireTopic = false, requireMessage = true, requireAdditionalInfo = false, topics = DEFAULT_TOPICS, companySizeOptions = DEFAULT_COMPANY_SIZE_OPTIONS, rows, user, context, captureMetadata = true, sessionId, correlationId, appVersion, environment, onSubmit, apiEndpoint, submitLabel = "Send", onSuccess, onError, }: ContactContentProps) { const [name, setName] = useState(user?.name || "") const [email, setEmail] = useState(user?.email || "") const [companyName, setCompanyName] = useState("") const [companySize, setCompanySize] = useState("") const [topic, setTopic] = useState("") const [message, setMessage] = useState("") const [additionalInfo, setAdditionalInfo] = useState("") const [isSubmitting, setIsSubmitting] = useState(false) const [errors, setErrors] = useState>({}) // Update fields when user prop changes useEffect(() => { if (user?.name && !name) setName(user.name) if (user?.email && !email) setEmail(user.email) }, [user]) const validate = (): boolean => { const newErrors: Record = {} if (showName && requireName && name.trim().length < 2) { newErrors.name = "Name must be at least 2 characters" } if (showEmail && requireEmail && !isValidEmail(email)) { newErrors.email = "Please enter a valid email" } // Validate email format if provided, even when not required if (showEmail && !requireEmail && email.trim() && !isValidEmail(email)) { newErrors.email = "Please enter a valid email" } if (showCompanyName && requireCompanyName && companyName.trim().length < 2) { newErrors.companyName = "Company name must be at least 2 characters" } if (showCompanySize && requireCompanySize && !companySize) { newErrors.companySize = "Please select a company size" } if (showTopic && requireTopic && !topic) { newErrors.topic = "Please select a topic" } if (showMessage && requireMessage && message.trim().length < 10) { newErrors.message = "Message must be at least 10 characters" } if (showAdditionalInfo && requireAdditionalInfo && additionalInfo.trim().length < 10) { newErrors.additionalInfo = "Additional info must be at least 10 characters" } setErrors(newErrors) return Object.keys(newErrors).length === 0 } const handleSubmit = async () => { if (!validate()) return setIsSubmitting(true) const data: ContactData = { name: showName ? name.trim() : undefined, email: showEmail ? email.trim() : undefined, companyName: showCompanyName ? companyName.trim() : undefined, companySize: showCompanySize ? companySize : undefined, topic: showTopic ? topic : undefined, message: message.trim(), additionalInfo: showAdditionalInfo ? additionalInfo.trim() : undefined, user, context, metadata: captureMetadata ? captureCurrentMetadata({ sessionId, correlationId, appVersion, environment }) : undefined, } try { if (onSubmit) { await onSubmit(data) } else if (apiEndpoint) { const response = await fetch(apiEndpoint, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data), }) if (!response.ok) { throw new Error(`Failed to submit: ${response.statusText}`) } } onSuccess() } catch (err) { onError(err instanceof Error ? err.message : "Failed to submit") } finally { setIsSubmitting(false) } } const isValid = (!showName || !requireName || name.trim().length >= 2) && (!showEmail || !requireEmail || isValidEmail(email)) && (!showEmail || !email.trim() || isValidEmail(email)) && // Validate format if provided (!showCompanyName || !requireCompanyName || companyName.trim().length >= 2) && (!showCompanySize || !requireCompanySize || companySize) && (!showTopic || !requireTopic || topic) && (!showMessage || !requireMessage || message.trim().length >= 10) && (!showAdditionalInfo || !requireAdditionalInfo || additionalInfo.trim().length >= 10) // Field components const nameField = showName && (
setName(e.target.value)} placeholder="Your name" className={cn(errors.name && "border-destructive")} /> {errors.name && (

{errors.name}

)}
) const emailField = showEmail && (
setEmail(e.target.value)} placeholder="your@email.com" className={cn(errors.email && "border-destructive")} /> {errors.email && (

{errors.email}

)}
) const companyNameField = showCompanyName && (
setCompanyName(e.target.value)} placeholder="Your company" className={cn(errors.companyName && "border-destructive")} /> {errors.companyName && (

{errors.companyName}

)}
) const companySizeField = showCompanySize && (
{errors.companySize && (

{errors.companySize}

)}
) const topicField = showTopic && (
{errors.topic && (

{errors.topic}

)}
) const messageField = showMessage && (