Files
frontend/src/app/contact/page.tsx

390 lines
15 KiB
TypeScript

'use client';
import Image from 'next/image';
import Link from 'next/link';
import { useState, useEffect } from 'react';
import { useSession } from 'next-auth/react';
import { CommonHeader } from '@/components/layout/CommonHeader';
import { Footer } from '@/components/layout/Footer';
import { cmsService } from '@/services/cms.service';
import api from '@/services/api';
interface ContactDetails {
title: string;
description: string;
email: string;
phone: string;
phoneHours: string;
officeAddress: string;
officeCity: string;
mapUrl: string;
directionsUrl: string;
}
interface ContactCta {
title: string;
description: string;
buttonText: string;
buttonLink: string;
}
const defaultContactDetails: ContactDetails = {
title: 'Get In Touch',
description: 'Have a question about a property or need assistance? Fill out the form below and our team will get back to you shortly.',
email: '123support@gmail.com',
phone: '1234567890',
phoneHours: 'Mon-Fri 9am-6pm',
officeAddress: '123 Market Street',
officeCity: 'New York CA 234737',
mapUrl: '',
directionsUrl: 'https://maps.google.com/?q=123+Market+Street+New+York+CA+234737',
};
const defaultCta: ContactCta = {
title: 'Ready to find an agent?',
description: 'Discover trusted agents and start your property journey with confidence.',
buttonText: 'Start Your Search',
buttonLink: '/user/profiles',
};
export default function ContactPage() {
const { data: session } = useSession();
const isAgent = (session?.user as any)?.role === 'AGENT';
const [formData, setFormData] = useState({
name: '',
phone: '',
email: '',
message: '',
});
const [contactDetails, setContactDetails] = useState<ContactDetails>(defaultContactDetails);
const [cta, setCta] = useState<ContactCta>(defaultCta);
const [isSubmitting, setIsSubmitting] = useState(false);
const [submitStatus, setSubmitStatus] = useState<'idle' | 'success' | 'error'>('idle');
useEffect(() => {
const loadCms = async () => {
const [details, ctaData] = await Promise.all([
cmsService.getSectionContent<ContactDetails>('contact', 'contactDetails'),
cmsService.getSectionContent<ContactCta>('contact', 'cta'),
]);
if (details) setContactDetails({ ...defaultContactDetails, ...details });
if (ctaData) setCta({ ...defaultCta, ...ctaData });
};
loadCms();
}, []);
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
const { name, value } = e.target;
setFormData(prev => ({ ...prev, [name]: value }));
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!formData.name.trim() || !formData.email.trim() || !formData.message.trim()) return;
setIsSubmitting(true);
setSubmitStatus('idle');
try {
await api.post('/contact', {
name: formData.name.trim(),
email: formData.email.trim(),
phone: formData.phone.trim() || undefined,
message: formData.message.trim(),
});
setSubmitStatus('success');
setFormData({ name: '', phone: '', email: '', message: '' });
setTimeout(() => setSubmitStatus('idle'), 5000);
} catch {
setSubmitStatus('error');
} finally {
setIsSubmitting(false);
}
};
const handleCancel = () => {
setFormData({ name: '', phone: '', email: '', message: '' });
};
return (
<div className="min-h-screen bg-white flex flex-col">
{/* Header */}
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6 w-full">
<CommonHeader />
</div>
{/* Main Content */}
<main className="flex-1 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-8 w-full">
{/* Contact Section */}
<div className="border border-[#00293d]/20 rounded-[15px] p-8 mb-10">
{/* Title */}
<div className="text-center mb-8">
<h1 className="font-fractul font-bold text-[25px] text-[#00293d] mb-4">
{contactDetails.title}
</h1>
<p className="font-serif text-[14px] text-[#00293d] max-w-[633px] mx-auto">
{contactDetails.description}
</p>
</div>
<div className="flex flex-col lg:flex-row gap-8">
{/* Contact Form */}
<div className="flex-1">
<form onSubmit={handleSubmit} className="space-y-6">
{/* Your Name */}
<div>
<label className="block font-fractul font-medium text-[14px] text-[#00293d] mb-2">
Your Name
</label>
<div className="border border-[#00293d]/10 rounded-[15px] h-[52px] px-4 flex items-center">
<input
type="text"
name="name"
value={formData.name}
onChange={handleInputChange}
placeholder="Brian Neeland"
className="w-full font-fractul text-[14px] text-black placeholder:text-black/50 bg-transparent outline-none"
/>
</div>
</div>
{/* Phone Number */}
<div>
<label className="block font-fractul font-medium text-[14px] text-[#00293d] mb-2">
Phone Number
</label>
<div className="border border-[#00293d]/10 rounded-[15px] h-[52px] px-4 flex items-center gap-3">
<Image
src="/assets/icons/phone-orange-icon.svg"
alt="Phone"
width={22}
height={22}
/>
<input
type="tel"
name="phone"
value={formData.phone}
onChange={handleInputChange}
placeholder="12345678990"
className="w-full font-fractul text-[14px] text-black placeholder:text-black/50 bg-transparent outline-none"
/>
</div>
</div>
{/* Email Address */}
<div>
<label className="block font-fractul font-medium text-[14px] text-[#00293d] mb-2">
Email Address
</label>
<div className="border border-[#00293d]/10 rounded-[15px] h-[52px] px-4 flex items-center gap-3">
<Image
src="/assets/icons/email-orange-icon.svg"
alt="Email"
width={22}
height={22}
/>
<input
type="email"
name="email"
value={formData.email}
onChange={handleInputChange}
placeholder="123@gmail.com"
className="w-full font-fractul text-[14px] text-black placeholder:text-black/50 bg-transparent outline-none"
/>
</div>
</div>
{/* Message */}
<div>
<label className="block font-fractul font-medium text-[14px] text-[#00293d] mb-2">
Message
</label>
<div className="border border-[#00293d]/10 rounded-[15px] h-[149px] p-4">
<textarea
name="message"
value={formData.message}
onChange={handleInputChange}
placeholder="Type your message here..."
className="w-full h-full font-fractul text-[14px] text-black placeholder:text-black/50 bg-transparent outline-none resize-none"
/>
</div>
</div>
{/* Buttons */}
{submitStatus === 'success' && (
<div className="bg-green-50 border border-green-200 rounded-[15px] p-3 text-center">
<p className="font-serif text-[14px] text-green-700">Message sent successfully! We'll get back to you shortly.</p>
</div>
)}
{submitStatus === 'error' && (
<div className="bg-red-50 border border-red-200 rounded-[15px] p-3 text-center">
<p className="font-serif text-[14px] text-red-700">Failed to send message. Please try again.</p>
</div>
)}
<div className="flex items-center justify-center gap-4 pt-4">
<button
type="button"
onClick={handleCancel}
disabled={isSubmitting}
className="w-[163px] h-[46px] border border-[#00293d]/10 rounded-[15px] font-fractul font-bold text-[14px] text-[#00293d] hover:bg-gray-50 transition-colors disabled:opacity-50"
>
Cancel
</button>
<button
type="submit"
disabled={isSubmitting}
className="w-[163px] h-[46px] bg-[#e58625] rounded-[15px] font-fractul font-bold text-[14px] text-[#00293d] hover:bg-[#d47720] transition-colors disabled:opacity-50"
>
{isSubmitting ? 'Sending...' : 'Send Message'}
</button>
</div>
</form>
</div>
{/* Contact Details Sidebar */}
<div className="lg:w-[319px]">
<div className="border border-[#00293d]/10 rounded-[20px] overflow-hidden">
{/* Header */}
<div className="p-4 border-b border-[#00293d]/10">
<h2 className="font-fractul font-medium text-[14px] text-[#00293d] text-center">
Contact Details
</h2>
</div>
{/* Email Support */}
<div className="p-4 border-b border-[#00293d]/10">
<div className="flex items-start gap-3">
<Image
src="/assets/icons/email-orange-icon.svg"
alt="Email"
width={20}
height={20}
className="mt-0.5"
/>
<div>
<p className="font-serif font-light text-[14px] text-[#00293d]">
Email Support
</p>
<p className="font-serif text-[14px] text-[#00293d]">
{contactDetails.email}
</p>
</div>
</div>
</div>
{/* Phone */}
<div className="p-4 border-b border-[#00293d]/10">
<div className="flex items-start gap-3">
<Image
src="/assets/icons/phone-orange-icon.svg"
alt="Phone"
width={20}
height={20}
className="mt-0.5"
/>
<div>
<p className="font-serif font-light text-[14px] text-[#00293d]">
Phone
</p>
<p className="font-serif text-[14px] text-[#00293d]">
{contactDetails.phone}
</p>
<p className="font-serif text-[10px] text-[#00293d]">
{contactDetails.phoneHours}
</p>
</div>
</div>
</div>
{/* Office */}
<div className="p-4">
<div className="flex items-start gap-3">
<Image
src="/assets/icons/location-orange-icon.svg"
alt="Location"
width={20}
height={20}
className="mt-0.5"
/>
<div>
<p className="font-serif font-light text-[14px] text-[#00293d]">
Office
</p>
<p className="font-serif text-[14px] text-[#00293d]">
{contactDetails.officeAddress}
</p>
<p className="font-serif text-[14px] text-[#00293d]">
{contactDetails.officeCity}
</p>
</div>
</div>
</div>
{/* Map */}
<div className="px-4 pb-4">
<div className="rounded-[20px] overflow-hidden h-[166px] bg-gray-200">
<Image
src="/assets/images/contact-map.jpg"
alt="Office location map"
width={260}
height={166}
className="w-full h-full object-cover"
/>
</div>
</div>
{/* Get Directions Button */}
<div className="px-4 pb-4">
<Link
href={contactDetails.directionsUrl || '#'}
target={contactDetails.directionsUrl ? '_blank' : undefined}
className="w-[117px] h-[35px] border border-[#e58625] rounded-[15px] font-serif text-[14px] text-[#e58625] hover:bg-[#e58625]/10 transition-colors mx-auto flex items-center justify-center"
>
Get Directions
</Link>
</div>
</div>
</div>
</div>
</div>
{/* CTA Section */}
<div className="max-w-4xl mx-auto border border-[#00293d]/20 rounded-[15px] p-8 lg:p-10 mb-10">
<div className="flex flex-col lg:flex-row items-center justify-between gap-6">
<div className="lg:max-w-[400px]">
<h2 className="font-fractul font-bold text-[24px] lg:text-[28px] text-[#00293d] mb-3">
{isAgent ? 'Manage your profile' : cta.title}
</h2>
<p className="font-serif text-[13px] text-[#00293d] mb-5">
{isAgent ? 'Keep your profile updated and connect with potential clients.' : cta.description}
</p>
<Link
href={isAgent ? '/agent/dashboard' : cta.buttonLink}
className="inline-flex items-center gap-2 bg-[#e58625] text-white px-5 py-2.5 rounded-full font-fractul font-medium text-[13px] hover:bg-[#d47720] transition-colors"
>
{isAgent ? 'Go to Dashboard' : cta.buttonText}
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
</Link>
</div>
<div className="w-[140px] lg:w-[160px]">
<Image
src="/assets/images/agent-illustration.png"
alt="Find an agent"
width={160}
height={160}
className="w-full h-auto"
/>
</div>
</div>
</div>
</main>
{/* Footer */}
<Footer />
</div>
);
}