Files
2026-08-05 19:40:55 +03:00

190 lines
8.1 KiB
TypeScript

'use client'
import { useRef, useState } from 'react'
import { useTranslations } from 'next-intl'
import { motion, useInView } from 'framer-motion'
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { Phone, Mail, Instagram, Send } from 'lucide-react'
import { ContactSchema, type ContactInput } from '@/lib/validations'
export default function ContactSection() {
const t = useTranslations('contact')
const ref = useRef<HTMLDivElement>(null)
const isInView = useInView(ref, { once: true, margin: '-80px' })
const [status, setStatus] = useState<'idle' | 'loading' | 'success' | 'error'>('idle')
const { register, handleSubmit, reset, formState: { errors } } = useForm<ContactInput>({
resolver: zodResolver(ContactSchema),
})
const onSubmit = async (data: ContactInput) => {
setStatus('loading')
try {
const res = await fetch('/api/contact', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
})
if (!res.ok) throw new Error()
setStatus('success')
reset()
} catch {
setStatus('error')
}
}
return (
<section id="iletisim" className="bg-vesta-cream py-24 md:py-32">
<div ref={ref} className="container mx-auto px-6">
<div className="grid md:grid-cols-2 gap-16 items-start">
{/* Sol: Bilgi */}
<div>
<motion.p
initial={{ opacity: 0, y: 15 }}
animate={isInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.5 }}
className="text-vesta-earth text-xs tracking-[0.3em] uppercase mb-4"
>
{t('label')}
</motion.p>
<motion.h2
initial={{ opacity: 0, y: 20 }}
animate={isInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, delay: 0.1 }}
className="text-vesta-dark text-3xl md:text-4xl font-serif font-light leading-snug mb-4"
>
{t('title')}
</motion.h2>
<motion.p
initial={{ opacity: 0, y: 20 }}
animate={isInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, delay: 0.2 }}
className="text-vesta-dark/50 text-base mb-10"
>
{t('subtitle')}
</motion.p>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={isInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, delay: 0.3 }}
className="space-y-4"
>
<a
href={`tel:+904443145`}
className="flex items-center gap-4 text-vesta-dark hover:text-vesta-earth transition-colors group"
>
<div className="w-10 h-10 rounded-full bg-vesta-dark/10 flex items-center justify-center group-hover:bg-vesta-earth/20 transition-colors">
<Phone className="w-4 h-4" />
</div>
<span className="text-lg">{t('phone')}</span>
</a>
<a
href={`mailto:${t('email')}`}
className="flex items-center gap-4 text-vesta-dark hover:text-vesta-earth transition-colors group"
>
<div className="w-10 h-10 rounded-full bg-vesta-dark/10 flex items-center justify-center group-hover:bg-vesta-earth/20 transition-colors">
<Mail className="w-4 h-4" />
</div>
<span className="text-lg">{t('email')}</span>
</a>
<a
href="https://www.instagram.com/vestamugla/"
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-4 text-vesta-dark hover:text-vesta-earth transition-colors group"
>
<div className="w-10 h-10 rounded-full bg-vesta-dark/10 flex items-center justify-center group-hover:bg-vesta-earth/20 transition-colors">
<Instagram className="w-4 h-4" />
</div>
<span className="text-lg">{t('instagram')}</span>
</a>
{/* Sanal Tur */}
<a
href="https://emtisiinsaat.com/vr.html"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 mt-4 border border-vesta-dark/20 text-vesta-dark px-5 py-2.5 rounded-full text-sm hover:bg-vesta-dark hover:text-white transition-colors"
>
360° Sanal Tur
</a>
</motion.div>
</div>
{/* Sağ: Form */}
<motion.div
initial={{ opacity: 0, x: 30 }}
animate={isInView ? { opacity: 1, x: 0 } : {}}
transition={{ duration: 0.7, delay: 0.2 }}
className="bg-white rounded-2xl p-8 shadow-sm"
>
{status === 'success' ? (
<div className="text-center py-8">
<div className="w-12 h-12 rounded-full bg-vesta-forest/20 flex items-center justify-center mx-auto mb-4">
<Send className="w-5 h-5 text-vesta-forest" />
</div>
<p className="text-vesta-dark font-medium">{t('form.success')}</p>
</div>
) : (
<form onSubmit={handleSubmit(onSubmit)} className="space-y-5">
<div>
<input
{...register('fullName')}
placeholder={t('form.name')}
className="w-full border border-gray-200 rounded-xl px-4 py-3 text-sm text-vesta-dark placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-vesta-earth/30 focus:border-vesta-earth"
/>
{errors.fullName && (
<p className="text-red-500 text-xs mt-1">{errors.fullName.message}</p>
)}
</div>
<div>
<input
{...register('email')}
type="email"
placeholder={t('form.email')}
className="w-full border border-gray-200 rounded-xl px-4 py-3 text-sm text-vesta-dark placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-vesta-earth/30 focus:border-vesta-earth"
/>
{errors.email && (
<p className="text-red-500 text-xs mt-1">{errors.email.message}</p>
)}
</div>
<div>
<input
{...register('phone')}
type="tel"
placeholder={t('form.phone')}
className="w-full border border-gray-200 rounded-xl px-4 py-3 text-sm text-vesta-dark placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-vesta-earth/30 focus:border-vesta-earth"
/>
</div>
<div>
<textarea
{...register('message')}
placeholder={t('form.message')}
rows={4}
className="w-full border border-gray-200 rounded-xl px-4 py-3 text-sm text-vesta-dark placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-vesta-earth/30 focus:border-vesta-earth resize-none"
/>
{errors.message && (
<p className="text-red-500 text-xs mt-1">{errors.message.message}</p>
)}
</div>
{status === 'error' && (
<p className="text-red-500 text-xs">{t('form.error')}</p>
)}
<button
type="submit"
disabled={status === 'loading'}
className="w-full bg-vesta-dark text-white py-3.5 rounded-xl text-sm tracking-wide hover:bg-vesta-forest transition-colors disabled:opacity-50"
>
{status === 'loading' ? t('form.sending') : t('form.send')}
</button>
</form>
)}
</motion.div>
</div>
</div>
</section>
)
}