Files
novalon-website/src/app/(marketing)/contact/page.tsx
T
张翔 4a616fe96e refactor: complete website optimization - unified navigation, colors, and structure
- Created service detail pages with storytelling style
- Created service list page
- Removed service modal interactions
- Simplified homepage About section
- Added homepage Cases section
- Updated navigation to use page links instead of anchors
- Created products list page
- Updated footer links
- Unified color scheme to brand red (#C41E3A)
- Fixed TypeScript errors (removed unused imports)
- Fixed JSX syntax errors
- Split About page into server and client components
- All tests passing: typecheck and build successful
2026-02-26 21:43:44 +08:00

211 lines
8.6 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, useRef } from 'react';
import { useInView } from 'framer-motion';
import { motion } from 'framer-motion';
import { COMPANY_INFO } from '@/lib/constants';
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 { PageHeader } from '@/components/ui/page-header';
import { Mail, Phone, MapPin, Send, Loader2 } from 'lucide-react';
export default function ContactPage() {
const [isSubmitting, setIsSubmitting] = useState(false);
const [isSubmitted, setIsSubmitted] = useState(false);
const contentRef = useRef(null);
const isContentInView = useInView(contentRef, { once: true, margin: '-100px' });
async function handleSubmit(_formData: FormData) {
setIsSubmitting(true);
await new Promise(resolve => setTimeout(resolve, 1500));
setIsSubmitting(false);
setIsSubmitted(true);
}
return (
<div className="min-h-screen bg-white">
<PageHeader
badge="联系我们"
title="与我们取得联系"
description="无论您有任何问题或合作意向,我们都很乐意与您交流"
/>
<div className="container-wide relative z-10 py-16" ref={contentRef}>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6 }}
className="grid grid-cols-1 lg:grid-cols-2 gap-12 max-w-6xl mx-auto"
>
{/* Contact Info */}
<div className="space-y-8">
<Card className="border-[#E5E5E5]">
<CardHeader>
<CardTitle className="text-[#1C1C1C]"></CardTitle>
</CardHeader>
<CardContent className="space-y-6">
<div className="flex items-start gap-4">
<div className="w-10 h-10 bg-[#C41E3A] rounded-lg flex items-center justify-center flex-shrink-0">
<MapPin className="w-5 h-5 text-white" />
</div>
<div>
<h3 className="font-semibold text-[#1C1C1C]"></h3>
<p className="text-[#5C5C5C]">{COMPANY_INFO.address}</p>
</div>
</div>
<div className="flex items-start gap-4">
<div className="w-10 h-10 bg-[#C41E3A] rounded-lg flex items-center justify-center flex-shrink-0">
<Phone className="w-5 h-5 text-white" />
</div>
<div>
<h3 className="font-semibold text-[#1C1C1C]"></h3>
<p className="text-[#5C5C5C]">{COMPANY_INFO.phone}</p>
</div>
</div>
<div className="flex items-start gap-4">
<div className="w-10 h-10 bg-[#C41E3A] rounded-lg flex items-center justify-center flex-shrink-0">
<Mail className="w-5 h-5 text-white" />
</div>
<div>
<h3 className="font-semibold text-[#1C1C1C]"></h3>
<p className="text-[#5C5C5C]">{COMPANY_INFO.email}</p>
</div>
</div>
</CardContent>
</Card>
<Card className="border-[#E5E5E5]">
<CardHeader>
<CardTitle className="text-[#1C1C1C]"></CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-2">
<div className="flex justify-between">
<span className="text-[#5C5C5C]"></span>
<span className="text-[#1C1C1C] font-medium">9:00 - 18:00</span>
</div>
<div className="flex justify-between">
<span className="text-[#5C5C5C]"></span>
<span className="text-[#1C1C1C] font-medium">9:00 - 12:00</span>
</div>
<div className="flex justify-between">
<span className="text-[#5C5C5C]"></span>
<span className="text-[#8C8C8C]"></span>
</div>
</div>
</CardContent>
</Card>
</div>
{/* Contact Form */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={isContentInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, delay: 0.2 }}
>
<Card className="border-[#E5E5E5]">
<CardHeader>
<CardTitle className="text-[#1C1C1C]"></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-[#1C1C1C] mb-2"></h3>
<p className="text-[#5C5C5C]"></p>
</div>
) : (
<form action={handleSubmit} className="space-y-6">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label htmlFor="name" className="block text-sm font-medium text-[#1C1C1C] mb-2">
*
</label>
<Input
id="name"
name="name"
placeholder="请输入您的姓名"
required
/>
</div>
<div>
<label htmlFor="phone" className="block text-sm font-medium text-[#1C1C1C] mb-2">
</label>
<Input
id="phone"
name="phone"
type="tel"
placeholder="请输入您的电话"
/>
</div>
</div>
<div>
<label htmlFor="email" className="block text-sm font-medium text-[#1C1C1C] mb-2">
*
</label>
<Input
id="email"
name="email"
type="email"
placeholder="请输入您的邮箱"
required
/>
</div>
<div>
<label htmlFor="subject" className="block text-sm font-medium text-[#1C1C1C] mb-2">
*
</label>
<Input
id="subject"
name="subject"
placeholder="请输入消息主题"
required
/>
</div>
<div>
<label htmlFor="message" className="block text-sm font-medium text-[#1C1C1C] mb-2">
*
</label>
<Textarea
id="message"
name="message"
placeholder="请输入您想要咨询的内容"
rows={5}
required
/>
</div>
<Button
type="submit"
className="w-full bg-[#C41E3A] hover:bg-[#A01830] text-white"
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>
</motion.div>
</div>
</div>
);
}