You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

168 lines
6.7 KiB

"use client";
import React from "react";
import type { ContactData, ContactField } from "../types";
interface ContactSectionProps {
data: ContactData;
}
type FormValues = Record<string, string>;
function resolveFieldType(field: ContactField) {
if (field.type) return field.type;
return "text";
}
export function ContactSection({ data }: ContactSectionProps) {
const fields = data.form.fields;
const [values, setValues] = React.useState<FormValues>(() =>
fields.reduce<FormValues>((acc, field) => {
acc[field.id] = "";
return acc;
}, {})
);
const [submitting, setSubmitting] = React.useState(false);
const [submitted, setSubmitted] = React.useState(false);
const handleChange = (fieldId: string) => (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
setValues((prev) => ({
...prev,
[fieldId]: event.target.value,
}));
};
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
setSubmitting(true);
setTimeout(() => {
setSubmitting(false);
setSubmitted(true);
}, 800);
};
return (
<section id="contact" className="relative bg-[#f3f6fc] py-12 md:py-20">
<div className="absolute inset-0 pointer-events-none">
<div className="h-full w-full bg-[radial-gradient(circle_at_top_left,_rgba(88,133,255,0.08),_transparent_55%)]" />
</div>
<div className="relative mx-auto flex max-w-5xl flex-col gap-10 px-4 md:px-8">
<div className="w-full rounded-3xl bg-white p-6 shadow-[0_20px_60px_-25px_rgba(72,99,178,0.35)] md:p-10">
<div className="mb-8 border-b border-[#e1e7f5] pb-8">
<p className="text-sm font-medium uppercase tracking-[0.2em] text-[#7090ff]">
{data.hero?.title ?? "Business Partnership"}
</p>
<h2 className="mt-3 text-2xl font-semibold text-[#102052] md:text-[30px]">
{data.form.title}
</h2>
{data.form.description && (
<p className="mt-3 max-w-3xl text-sm leading-relaxed text-[#5c6b91] md:text-base">
{data.form.description}
</p>
)}
{data.form.note && (
<p className="mt-4 rounded-2xl bg-[#f6f8ff] px-4 py-3 text-xs text-[#6b7ba8] md:text-sm">
{data.form.note}
</p>
)}
</div>
<form onSubmit={handleSubmit} className="grid grid-cols-1 gap-6 md:grid-cols-2">
{fields.map((field) => {
const type = resolveFieldType(field);
const value = values[field.id] ?? "";
const hasCounter = typeof field.maxLength === "number" && field.maxLength > 0;
const counter = hasCounter ? `${value.length}/${field.maxLength}` : undefined;
const baseClassName =
"w-full rounded-2xl border border-[#dde5f7] bg-[#f9fbff] px-4 py-3 text-sm text-[#1b2559] placeholder:text-[#9aa7ca] shadow-[0_10px_30px_-20px_rgba(38,71,150,0.45)] transition focus:border-[#4a7dff] focus:bg-white focus:outline-none focus:ring-4 focus:ring-[#4a7dff]/10";
return (
<div
key={field.id}
className={`flex flex-col gap-2 ${field.span === "full" ? "md:col-span-2" : ""}`}
>
{field.label && (
<label
htmlFor={field.id}
className="text-sm font-medium text-[#374570]"
>
{field.label}
</label>
)}
<div className="relative">
{type === "textarea" ? (
<textarea
id={field.id}
name={field.id}
value={value}
onChange={handleChange(field.id)}
placeholder={field.placeholder}
maxLength={field.maxLength}
rows={6}
className={`${baseClassName} resize-none md:min-h-[168px]`}
/>
) : type === "select" ? (
<div className="relative">
<select
id={field.id}
name={field.id}
value={value}
onChange={handleChange(field.id)}
className={`${baseClassName} appearance-none`}
>
<option value="" disabled>
{field.placeholder}
</option>
{(field.options ?? []).map((option) => (
<option key={option} value={option}>
{option}
</option>
))}
</select>
<span className="pointer-events-none absolute inset-y-0 right-4 flex items-center text-[#7c8db8]">
</span>
</div>
) : (
<input
id={field.id}
name={field.id}
type={type}
value={value}
onChange={handleChange(field.id)}
placeholder={field.placeholder}
maxLength={field.maxLength}
className={baseClassName}
/>
)}
{counter && (
<span className="pointer-events-none absolute bottom-3 right-4 text-xs font-medium text-[#8e9ec9]">
{counter}
</span>
)}
</div>
</div>
);
})}
<div className="flex flex-col gap-3 md:col-span-2 md:flex-row md:items-center md:justify-between">
<p className="text-sm text-[#7381ab]">
{submitted
? "感谢您的提交!我们将尽快与您联系。"
: "提交后,我们的商务团队将在一个工作日内回复。"}
</p>
<button
type="submit"
disabled={submitting}
className="inline-flex items-center justify-center rounded-full bg-[#2f6bff] px-8 py-3 text-sm font-semibold text-white transition hover:bg-[#2556d6] disabled:cursor-not-allowed disabled:opacity-70"
>
{submitting ? "提交中..." : data.form.submit}
</button>
</div>
</form>
</div>
</div>
</section>
);
}