- Add dynamic sitemap.ts, robots.ts, and llms.txt route - Add metadataBase and JSON-LD Organization schema to layout - Set canonical alternates for all routes - Migrate raw img tags to next/image for LCP optimization - Add SEO dictionary strings to tr.json and en.json
199 lines
9.2 KiB
TypeScript
199 lines
9.2 KiB
TypeScript
import { MapPin, Phone, Mail } from "lucide-react";
|
||
import { Input, Textarea } from "@/app/components/ui/input";
|
||
import { Button } from "@/app/components/ui/button";
|
||
import { SectionHeader } from "@/app/components/ui/section-header";
|
||
import { Badge } from "@/app/components/ui/badge";
|
||
import { getDictionary, Locale } from "../../dictionaries";
|
||
|
||
const LOCATIONS = [
|
||
{
|
||
name: "Moy Beach",
|
||
tag: "Beach & Bar",
|
||
address: "Akyaka, Atatürk 1. Cd No:86, 48640 Ula/Muğla",
|
||
phones: ["+90 534 465 62 35"],
|
||
email: "beach@moygroup.com.tr",
|
||
variant: "gold" as const,
|
||
},
|
||
{
|
||
name: "Kite Beach Hotel",
|
||
tag: "Hotel",
|
||
address: "Akçapınar Mah. Akçapınar Sok. Kiteboard Sahili, Muğla",
|
||
phones: ["+90 533 081 61 81"],
|
||
email: "hotel@moygroup.com.tr",
|
||
variant: "blue" as const,
|
||
},
|
||
{
|
||
name: "Volkswagen Kite (Surfing)",
|
||
tag: "Kite Surf",
|
||
address: "Akçapınar kite sahili, Ula, Turkey 48640",
|
||
phones: ["+90 537 882 31 37", "+90 505 204 98 56"],
|
||
email: "kite@moygroup.com.tr",
|
||
variant: "green" as const,
|
||
},
|
||
];
|
||
|
||
export async function generateMetadata({ params }: { params: Promise<{ lang: string }> }) {
|
||
const { lang } = await params;
|
||
const dict = await getDictionary(lang as Locale);
|
||
return {
|
||
title: dict.seo.contact.title,
|
||
description: dict.seo.contact.description,
|
||
alternates: {
|
||
canonical: `/${lang}/iletisim`,
|
||
},
|
||
};
|
||
}
|
||
|
||
export default async function IletisimPage({
|
||
params,
|
||
}: {
|
||
params: Promise<{ lang: string }>;
|
||
}) {
|
||
const { lang } = await params;
|
||
const locale = lang as Locale;
|
||
const dict = await getDictionary(locale);
|
||
const t = dict.contact;
|
||
|
||
return (
|
||
<div className="min-h-screen bg-[var(--color-moy-light)]">
|
||
{/* Hero */}
|
||
<div className="bg-[var(--color-moy-dark)] pt-40 pb-20">
|
||
<div className="max-w-3xl mx-auto px-6 text-center">
|
||
<p className="text-[10px] uppercase tracking-[0.28em] text-[var(--color-moy-gold)] mb-4">
|
||
{t.eyebrow}
|
||
</p>
|
||
<h1 className="text-5xl md:text-6xl font-serif text-white mb-6 leading-tight">
|
||
{t.title}
|
||
</h1>
|
||
<p className="text-gray-400 text-base leading-relaxed max-w-lg mx-auto">
|
||
{t.subtitle}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Locations */}
|
||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 -mt-10 pb-24">
|
||
<div className="grid grid-cols-1 md:grid-cols-3 gap-5 mb-24">
|
||
{LOCATIONS.map((loc) => (
|
||
<div
|
||
key={loc.name}
|
||
className="bg-white border border-gray-100 p-8 shadow-[var(--shadow-sm)] hover:shadow-[var(--shadow-md)] transition-shadow duration-300"
|
||
>
|
||
<Badge variant={loc.variant} className="mb-5">{loc.tag}</Badge>
|
||
<h3 className="text-xl font-serif text-[var(--color-moy-dark)] mb-5">{loc.name}</h3>
|
||
<ul className="space-y-3">
|
||
<li className="flex items-start gap-3">
|
||
<MapPin size={15} className="text-[var(--color-moy-gold)] mt-0.5 shrink-0" />
|
||
<span className="text-sm text-gray-500">{loc.address}</span>
|
||
</li>
|
||
<li className="flex items-start gap-3">
|
||
<Phone size={15} className="text-[var(--color-moy-gold)] shrink-0 mt-0.5" />
|
||
<div className="flex flex-col gap-1">
|
||
{loc.phones.map((phone, i) => (
|
||
<a key={i} href={`tel:${phone.replace(/\s/g, "")}`} className="text-sm text-gray-500 hover:text-[var(--color-moy-gold)] transition-colors">
|
||
{phone}
|
||
</a>
|
||
))}
|
||
</div>
|
||
</li>
|
||
<li className="flex items-center gap-3">
|
||
<Mail size={15} className="text-[var(--color-moy-gold)] shrink-0" />
|
||
<a href={`mailto:${loc.email}`} className="text-sm text-gray-500 hover:text-[var(--color-moy-gold)] transition-colors">
|
||
{loc.email}
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
))}
|
||
</div>
|
||
|
||
{/* Contact Form + Info */}
|
||
<div className="grid grid-cols-1 lg:grid-cols-5 gap-12">
|
||
{/* Form */}
|
||
<div className="lg:col-span-3 bg-white border border-gray-100 p-10 shadow-[var(--shadow-sm)]">
|
||
<SectionHeader
|
||
eyebrow={t.formEyebrow}
|
||
title={t.formTitle}
|
||
align="left"
|
||
className="mb-10"
|
||
/>
|
||
<form className="space-y-5">
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-5">
|
||
<Input label={t.name} placeholder={t.namePlaceholder} id="name" />
|
||
<Input label={t.email} type="email" placeholder={t.emailPlaceholder} id="email" />
|
||
</div>
|
||
<Input label={t.phone} type="tel" placeholder={t.phonePlaceholder} id="phone" />
|
||
<div>
|
||
<label className="text-[10px] font-medium uppercase tracking-[0.16em] text-gray-500 block mb-1.5">
|
||
{t.subject}
|
||
</label>
|
||
<select className="w-full px-4 py-3.5 bg-white border border-gray-200 text-sm text-[var(--color-moy-dark)] focus:outline-none focus:ring-2 focus:ring-[var(--color-moy-gold)]/40 focus:border-[var(--color-moy-gold)] transition-all duration-200">
|
||
{t.subjectOptions.map((opt: string, i: number) => (
|
||
<option key={i} value={i === 0 ? "" : opt}>{opt}</option>
|
||
))}
|
||
</select>
|
||
</div>
|
||
<Textarea label={t.message} placeholder={t.messagePlaceholder} id="message" rows={5} />
|
||
<Button variant="primary" size="lg" shimmer className="w-full group mt-2">
|
||
{t.send}
|
||
</Button>
|
||
</form>
|
||
</div>
|
||
|
||
{/* Sidebar info */}
|
||
<div className="lg:col-span-2 space-y-8">
|
||
<div className="bg-[var(--color-moy-dark)] p-8">
|
||
<h3 className="font-serif text-xl text-white mb-6">{t.generalContact}</h3>
|
||
<ul className="space-y-4">
|
||
<li className="flex items-center gap-3">
|
||
<Phone size={16} className="text-[var(--color-moy-gold)]" />
|
||
<div>
|
||
<p className="text-[10px] uppercase tracking-[0.15em] text-gray-500 mb-0.5">{t.phoneText}</p>
|
||
<a href="tel:+905344656235" className="text-sm text-gray-300 hover:text-[var(--color-moy-gold)] transition-colors">+90 534 465 62 35</a>
|
||
</div>
|
||
</li>
|
||
<li className="flex items-center gap-3">
|
||
<Mail size={16} className="text-[var(--color-moy-gold)]" />
|
||
<div>
|
||
<p className="text-[10px] uppercase tracking-[0.15em] text-gray-500 mb-0.5">{t.emailText}</p>
|
||
<a href="mailto:info@moygroup.com.tr" className="text-sm text-gray-300 hover:text-[var(--color-moy-gold)] transition-colors">info@moygroup.com.tr</a>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div className="bg-white border border-gray-100 p-8">
|
||
<h3 className="font-serif text-xl text-[var(--color-moy-dark)] mb-6">{t.hours}</h3>
|
||
<ul className="space-y-2 text-sm">
|
||
{[
|
||
[t.monFri, "09:00 – 23:00"],
|
||
[t.sat, "10:00 – 24:00"],
|
||
[t.sun, "10:00 – 23:00"],
|
||
].map(([day, hours]) => (
|
||
<li key={day as string} className="flex justify-between text-gray-500">
|
||
<span>{day as string}</span>
|
||
<span className="font-medium text-[var(--color-moy-dark)]">{hours as string}</span>
|
||
</li>
|
||
))}
|
||
</ul>
|
||
<p className="text-xs text-[var(--color-moy-gold-dark)] mt-4">{t.hoursNote}</p>
|
||
</div>
|
||
|
||
<div className="bg-white border border-gray-100 p-8">
|
||
<h3 className="font-serif text-xl text-[var(--color-moy-dark)] mb-4">{t.social}</h3>
|
||
<div className="flex gap-4">
|
||
<a href="#" aria-label="Instagram" className="w-10 h-10 border border-gray-200 flex items-center justify-center hover:border-[var(--color-moy-gold)] hover:text-[var(--color-moy-gold)] text-gray-400 transition-all duration-200">
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect width="20" height="20" x="2" y="2" rx="5" ry="5"/><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"/><line x1="17.5" x2="17.51" y1="6.5" y2="6.5"/></svg>
|
||
</a>
|
||
<a href="#" aria-label="Facebook" className="w-10 h-10 border border-gray-200 flex items-center justify-center hover:border-[var(--color-moy-gold)] hover:text-[var(--color-moy-gold)] text-gray-400 transition-all duration-200">
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"/></svg>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|