Files
novalon-website/src/components/sections/contact-section.tsx
T
张翔 cc55146ba6 feat(contact-section): 更新联系方式卡片为服务承诺卡片
将联系方式卡片重新设计为服务承诺卡片,展示专业响应、免费咨询和定制方案等优势
更新卡片样式和图标,使用更友好的视觉设计
保持工作时间卡片和消息发送卡片的基本布局
2026-02-03 08:02:09 +08:00

196 lines
8.1 KiB
TypeScript
Raw 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 { motion } from 'framer-motion';
import { useInView } from 'framer-motion';
import { useRef } from 'react';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Mail, Phone, MapPin, Send, Loader2, Clock, MessageCircle, HeadphonesIcon, Sparkles } from 'lucide-react';
import { COMPANY_INFO } from '@/lib/constants';
export function ContactSection() {
const ref = useRef(null);
const isInView = useInView(ref, { once: true, margin: '-100px' });
const [isSubmitting, setIsSubmitting] = useState(false);
const [isSubmitted, setIsSubmitted] = useState(false);
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
setIsSubmitting(true);
// Simulate form submission
await new Promise(resolve => setTimeout(resolve, 1500));
setIsSubmitting(false);
setIsSubmitted(true);
}
return (
<section id="contact" className="py-24 bg-gray-50" ref={ref}>
<div className="container-custom">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={isInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6 }}
className="text-center max-w-3xl mx-auto mb-16"
>
<Badge variant="outline" className="mb-4">
</Badge>
<h2 className="text-3xl sm:text-4xl lg:text-5xl font-bold text-black mb-6">
</h2>
<p className="text-lg text-gray-600">
</p>
</motion.div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 max-w-6xl mx-auto">
{/* Contact Info */}
<motion.div
initial={{ opacity: 0, x: -20 }}
animate={isInView ? { opacity: 1, x: 0 } : {}}
transition={{ duration: 0.6, delay: 0.2 }}
className="flex flex-col gap-6 h-full"
>
<Card className="flex-1 flex flex-col">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Sparkles className="w-5 h-5 text-gray-600" />
</CardTitle>
</CardHeader>
<CardContent className="space-y-6 flex-1">
<div className="flex items-start gap-4">
<div className="w-10 h-10 bg-gray-100 rounded-lg flex items-center justify-center flex-shrink-0">
<HeadphonesIcon className="w-5 h-5 text-gray-700" />
</div>
<div>
<h3 className="font-semibold text-black"></h3>
<p className="text-gray-600"> 2 </p>
</div>
</div>
<div className="flex items-start gap-4">
<div className="w-10 h-10 bg-gray-100 rounded-lg flex items-center justify-center flex-shrink-0">
<MessageCircle className="w-5 h-5 text-gray-700" />
</div>
<div>
<h3 className="font-semibold text-black"></h3>
<p className="text-gray-600"></p>
</div>
</div>
<div className="flex items-start gap-4">
<div className="w-10 h-10 bg-gray-100 rounded-lg flex items-center justify-center flex-shrink-0">
<Sparkles className="w-5 h-5 text-gray-700" />
</div>
<div>
<h3 className="font-semibold text-black"></h3>
<p className="text-gray-600"></p>
</div>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Clock className="w-5 h-5 text-gray-600" />
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-2">
<div className="flex justify-between">
<span className="text-gray-600"></span>
<span className="text-black font-medium">9:00 - 18:00</span>
</div>
</div>
</CardContent>
</Card>
</motion.div>
{/* Contact Form */}
<motion.div
initial={{ opacity: 0, x: 20 }}
animate={isInView ? { opacity: 1, x: 0 } : {}}
transition={{ duration: 0.6, delay: 0.3 }}
className="h-full"
>
<Card className="h-full flex flex-col">
<CardHeader>
<CardTitle></CardTitle>
</CardHeader>
<CardContent>
{isSubmitted ? (
<div className="text-center py-12">
<div className="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4">
<Send className="w-8 h-8 text-green-600" />
</div>
<h3 className="text-xl font-semibold text-black mb-2"></h3>
<p className="text-gray-600"></p>
</div>
) : (
<form onSubmit={handleSubmit} className="space-y-6">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div className="space-y-2">
<label htmlFor="name" className="text-sm font-medium text-black">
</label>
<Input id="name" placeholder="请输入您的姓名" required />
</div>
<div className="space-y-2">
<label htmlFor="phone" className="text-sm font-medium text-black">
</label>
<Input id="phone" type="tel" placeholder="请输入您的电话" required />
</div>
</div>
<div className="space-y-2">
<label htmlFor="email" className="text-sm font-medium text-black">
</label>
<Input id="email" type="email" placeholder="请输入您的邮箱" required />
</div>
<div className="space-y-2">
<label htmlFor="message" className="text-sm font-medium text-black">
</label>
<Textarea
id="message"
placeholder="请输入您想咨询的内容"
rows={5}
required
/>
</div>
<Button
type="submit"
className="w-full bg-black text-white hover:bg-gray-800"
disabled={isSubmitting}
>
{isSubmitting ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
...
</>
) : (
<>
<Send className="mr-2 h-4 w-4" />
</>
)}
</Button>
</form>
)}
</CardContent>
</Card>
</motion.div>
</div>
</div>
</section>
);
}