diff --git a/app/[locale]/[category]/[slug]/DetailTracker.tsx b/app/[locale]/[category]/[slug]/DetailTracker.tsx new file mode 100644 index 0000000..3cd6355 --- /dev/null +++ b/app/[locale]/[category]/[slug]/DetailTracker.tsx @@ -0,0 +1,42 @@ +'use client' + +import { useEffect } from 'react' + +export default function DetailTracker({ listingId }: { listingId: string }) { + useEffect(() => { + // Send fire-and-forget page view tracking event on load + fetch('/api/events', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ listingId, actionType: 'views' }) + }).catch(err => console.error('Tracking views error:', err)) + + const trackClick = (action: 'phone' | 'whatsapp' | 'menu') => { + fetch('/api/events', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ listingId, actionType: action }) + }).catch(err => console.error(`Tracking ${action} error:`, err)) + } + + const telBtn = document.getElementById('listing-contact-phone') + const waBtn = document.getElementById('listing-contact-whatsapp') + const menuBtn = document.getElementById('listing-contact-menu') + + const handleTel = () => trackClick('phone') + const handleWa = () => trackClick('whatsapp') + const handleMenu = () => trackClick('menu') + + if (telBtn) telBtn.addEventListener('click', handleTel) + if (waBtn) waBtn.addEventListener('click', handleWa) + if (menuBtn) menuBtn.addEventListener('click', handleMenu) + + return () => { + if (telBtn) telBtn.removeEventListener('click', handleTel) + if (waBtn) waBtn.removeEventListener('click', handleWa) + if (menuBtn) menuBtn.removeEventListener('click', handleMenu) + } + }, [listingId]) + + return null +} diff --git a/app/[locale]/[category]/[slug]/page.tsx b/app/[locale]/[category]/[slug]/page.tsx index 8efa494..8f1f006 100644 --- a/app/[locale]/[category]/[slug]/page.tsx +++ b/app/[locale]/[category]/[slug]/page.tsx @@ -6,16 +6,19 @@ import Image from 'next/image' import { Link } from '@/i18n/routing' import { Phone, Globe, MapPin, Clock, Star, MessageSquare, Share2 } from 'lucide-react' import SaveButton from './SaveButton' +import DetailTracker from './DetailTracker' interface DetailPageProps { params: Promise<{ locale: string; category: string; slug: string }> } +export const dynamic = 'force-dynamic' + export async function generateMetadata({ params }: DetailPageProps) { const { slug } = await params const listing = await mockDb.getListingBySlug(slug) if (!listing) return {} - + return { title: `${listing.nameTr} — Marmaris Local`, description: listing.descriptionTr @@ -27,7 +30,7 @@ export default async function ListingDetailPage({ params }: DetailPageProps) { setRequestLocale(locale) const t = await getTranslations('detail') - + const listing = await mockDb.getListingBySlug(slug) if (!listing) { notFound() @@ -56,19 +59,21 @@ export default async function ListingDetailPage({ params }: DetailPageProps) { locale === 'ru' ? listing.nameRu : locale === 'en' - ? listing.nameEn - : listing.nameTr + ? listing.nameEn + : listing.nameTr const description = locale === 'ru' ? listing.descriptionRu : locale === 'en' - ? listing.descriptionEn - : listing.descriptionTr + ? listing.descriptionEn + : listing.descriptionTr const priceSymbols = '₺'.repeat(listing.priceRange) const categorySlug = listing.category?.slug || 'isletme' - + const rawId = listing.id; // örn: "gm-ChIJY_2Q8tbJvxQRs7xwaSne0is" + const hasGooglePlaceId = rawId.startsWith('gm-'); + const placeId = hasGooglePlaceId ? rawId.replace('gm-', '') : null; // Format WhatsApp Link const getWhatsAppLink = (number: string) => { const cleanNum = number.replace(/\D/g, '') @@ -83,9 +88,10 @@ export default async function ListingDetailPage({ params }: DetailPageProps) { return (
+
- + {/* Breadcrumb */}
marmaris local @@ -100,7 +106,7 @@ export default async function ListingDetailPage({ params }: DetailPageProps) { {/* Hero Details Block */}
- + {/* Left: Gallery Panel */}
@@ -137,7 +143,7 @@ export default async function ListingDetailPage({ params }: DetailPageProps) { {locale === 'ru' ? listing.category?.nameRu : locale === 'en' ? listing.category?.nameEn : listing.category?.nameTr} - + {listing.isLocalApproved && ( ★ {t('approved')} @@ -165,16 +171,50 @@ export default async function ListingDetailPage({ params }: DetailPageProps) { {/* Description */}
- {description} + {description ? description : {t('no_description', { defaultValue: 'Bu işletme için henüz bir açıklama eklenmemiştir.' })}}
+ {/* Contact Info (Only if at least one exists) */} + {(listing.phone || listing.website || listing.instagram) && ( + + )} + {/* Contact & Actions Grid */}

{t('contact')}

- +
{listing.phone && ( @@ -185,6 +225,7 @@ export default async function ListingDetailPage({ params }: DetailPageProps) { {listing.whatsapp && ( {/* Map Frame */} - {listing.latitude && listing.longitude && ( + {((listing.latitude && listing.longitude) || hasGooglePlaceId) && (
{t('location')}
-
+