Files
sitarapart/app/[locale]/dairelerimiz/[slug]/page.tsx
T

184 lines
7.4 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.
import { getTranslations, setRequestLocale } from 'next-intl/server'
import { Link } from '@/i18n/routing'
import Image from 'next/image'
import { notFound } from 'next/navigation'
import { CheckCircle2, Maximize, Users, BedDouble, ArrowRight } from 'lucide-react'
import { db } from '@/lib/db'
import openinaryLoader from '@/lib/openinary-loader'
// Bu sayfa parametre olarak dinamik slug alacak
export default async function RoomDetailPage({ params }: { params: Promise<{ locale: string, slug: string }> }) {
const { locale, slug } = await params
setRequestLocale(locale)
const tRooms = await getTranslations('rooms')
const room = await db.room.findUnique({
where: { slug }
})
if (!room || !room.available) {
notFound();
}
const name = locale === 'tr' ? room.nameTr : locale === 'de' ? room.nameDe : room.nameEn
const description = locale === 'tr' ? room.descriptionTr : locale === 'de' ? room.descriptionDe : room.descriptionEn
const image = room.imageUrl || 'https://images.unsplash.com/photo-1631049307264-da0ec9d70304?auto=format&fit=crop&q=80'
const isExternalImage = image.startsWith('http') && !image.includes('media.ayris.tech')
const gallery = room.images && room.images.length > 0 ? room.images : [image]
// Size helper mapping based on room type
const getRoomSize = (type: string) => {
if (type === 'STUDIO_1_0') return '25m²'
if (type === 'SUITE_1_1') return '45m²'
return '20m²'
}
// Bed helper based on capacity/type roughly
const getBeds = (type: string, capacity: number) => {
if (type === 'STUDIO_1_0') return '1'
if (type === 'SUITE_1_1') return '2'
if (capacity === 3) return '1 + Ek Yatak'
return '1'
}
return (
<div className="bg-background min-h-screen text-on-surface">
{/* Hero Section */}
<section className="relative h-[60vh] md:h-[70vh] w-full">
{isExternalImage ? (
<img
src={image}
alt={name}
className="object-cover w-full h-full"
/>
) : (
<Image
src={image}
alt={name}
fill
loader={openinaryLoader}
sizes="100vw"
className="object-cover"
priority
/>
)}
<div className="absolute inset-0 bg-black/40" />
<div className="absolute inset-0 flex items-center justify-center">
<div className="text-center">
<h1 className="font-serif text-[48px] md:text-[64px] text-white font-bold drop-shadow-md">
{name}
</h1>
</div>
</div>
</section>
{/* Main Content */}
<section className="max-w-container-max mx-auto px-margin-mobile md:px-gutter py-16">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-12">
{/* Left Column - Details */}
<div className="lg:col-span-2 space-y-12">
{/* Badges */}
<div className="flex flex-wrap gap-4">
<div className="flex items-center gap-2 bg-surface-container px-4 py-2 rounded-full text-secondary font-medium">
<Users className="w-5 h-5 text-primary" />
<span>Maks {room.capacity} Kişi</span>
</div>
<div className="flex items-center gap-2 bg-surface-container px-4 py-2 rounded-full text-secondary font-medium">
<Maximize className="w-5 h-5 text-primary" />
<span>{getRoomSize(room.type)}</span>
</div>
<div className="flex items-center gap-2 bg-surface-container px-4 py-2 rounded-full text-secondary font-medium">
<BedDouble className="w-5 h-5 text-primary" />
<span>{getBeds(room.type, room.capacity)}</span>
</div>
</div>
{/* Description */}
<div className="prose prose-lg text-on-surface-variant">
<p className="text-[18px] leading-relaxed whitespace-pre-wrap">
{description}
</p>
</div>
{/* Amenities */}
{room.amenities.length > 0 && (
<div>
<h3 className="font-serif text-[28px] text-secondary font-semibold mb-6">
{tRooms('details.features')}
</h3>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
{room.amenities.map((amenity, index) => (
<div key={index} className="flex items-center gap-3">
<CheckCircle2 className="w-5 h-5 text-accent-green flex-shrink-0" />
<span className="text-on-surface-variant">{amenity}</span>
</div>
))}
</div>
</div>
)}
{/* Mini Gallery */}
{gallery.length > 0 && (
<div>
<h3 className="font-serif text-[28px] text-secondary font-semibold mb-6">
{tRooms('details.gallery')}
</h3>
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
{gallery.map((img, i) => {
const isGalleryExternal = img.startsWith('http') && !img.includes('media.ayris.tech')
return (
<div key={i} className="relative aspect-square rounded-2xl overflow-hidden shadow-sm hover:shadow-md transition-shadow">
{isGalleryExternal ? (
<img
src={img}
alt={`${name} gallery ${i + 1}`}
className="object-cover w-full h-full hover:scale-105 transition-transform duration-500"
/>
) : (
<Image
src={img}
alt={`${name} gallery ${i + 1}`}
fill
loader={openinaryLoader}
sizes="(max-width: 640px) 100vw, 33vw"
className="object-cover hover:scale-105 transition-transform duration-500"
/>
)}
</div>
)
})}
</div>
</div>
)}
</div>
{/* Right Column - Sticky Sidebar */}
<div className="lg:col-span-1">
<div className="sticky top-32 bg-surface-container rounded-[24px] p-8 shadow-sm border border-outline/10">
<h4 className="font-serif text-[24px] text-secondary font-semibold mb-2">
Bilgi Alın
</h4>
<p className="text-on-surface-variant text-[15px] mb-8">
Tarihlerinize uygun fiyat ve müsaitlik durumunu öğrenmek için bizimle iletişime geçin.
</p>
<Link
href="/iletisim"
className="w-full flex items-center justify-center gap-2 bg-primary hover:bg-primary-hover text-white py-4 rounded-full font-bold transition-all duration-300 shadow-md hover:shadow-lg cursor-pointer focus:outline-none focus-visible:ring-4 focus-visible:ring-primary/50 focus-visible:ring-offset-2"
>
{tRooms('details.book_now_cta')}
<ArrowRight className="w-5 h-5" />
</Link>
</div>
</div>
</div>
</section>
</div>
)
}