import { useSeoMeta } from '@unhead/react'; import { useParams, Link, useNavigate } from 'react-router-dom'; import { Layout } from '@/components/Layout'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; import { Skeleton } from '@/components/ui/skeleton'; import { useTour } from '@/hooks/useTours'; import { useAuthor } from '@/hooks/useAuthor'; import { useCurrentUser } from '@/hooks/useCurrentUser'; import { genUserName } from '@/lib/genUserName'; import { TOUR_SKILL_LEVELS, TOUR_SPOT_TYPES, SKATE_TOUR_KIND } from '@/lib/types'; import { ZapButton } from '@/components/ZapButton'; import { ProBadge } from '@/components/ProBadge'; import { ArrowLeft, Route, MapPin, Clock, Users, Zap, Globe, MessageCircle, Calendar, Star, Share2, Flag, Store, Percent, } from 'lucide-react'; import { cn } from '@/lib/utils'; import { SponsorSlot } from '@/components/SponsorSlot'; export default function TourDetailPage() { const { pubkey, identifier } = useParams<{ pubkey: string; identifier: string }>(); const navigate = useNavigate(); const { user } = useCurrentUser(); const { data: tour, isLoading, error } = useTour(identifier || '', pubkey); const author = useAuthor(tour?.pubkey || ''); const metadata = author.data?.metadata; const guideName = metadata?.name ?? genUserName(tour?.pubkey || ''); useSeoMeta({ title: tour ? `${tour.title} - Local Tour - SkateSpots` : 'Local Tour - SkateSpots', description: tour?.description || 'Discover hidden skate spots with a local guide', }); const handleBookTour = () => { if (!tour) return; // Navigate to messages/DM with the guide // For now, navigate to messages page - in future can open DM composer navigate(`/messages?to=${tour.pubkey}`); }; const handleShare = async () => { if (!tour) return; const url = window.location.href; if (navigator.share) { try { await navigator.share({ title: tour.title, text: `Check out this local skate tour: ${tour.title}`, url, }); } catch { // User cancelled or error } } else { await navigator.clipboard.writeText(url); } }; if (isLoading) { return (
); } if (error || !tour) { return (

Tour Not Found

This tour may have been removed or doesn't exist.

); } const skillInfo = tour.skillLevel ? TOUR_SKILL_LEVELS[tour.skillLevel as keyof typeof TOUR_SKILL_LEVELS] : null; return (
{/* Back link */} Back to Map {/* Main card */} {/* Tour image */} {tour.image && (
{tour.title}
)}
LOCAL TOUR
{tour.title} {tour.location && (

{tour.location}

)}
{/* Guide info */}
{guideName.slice(0, 2).toUpperCase()}

{guideName}

Local Guide

{/* Description */} {tour.description && (

About This Tour

{tour.description}

)} {/* Tour details grid */}
{tour.duration && (
Duration

{tour.duration} hours

)} {tour.maxGroupSize && (
Max Group

{tour.maxGroupSize} people

)} {skillInfo && (
Skill Level

{skillInfo.emoji} {skillInfo.label}

)} {tour.price && (
Price

{tour.price.toLocaleString()} sats

per person

)} {tour.availability && (
Availability

{tour.availability}

)} {tour.languages && tour.languages.length > 0 && (
Languages

{tour.languages.map(l => l.toUpperCase()).join(', ')}

)}
{/* Spot types */} {tour.spotTypes.length > 0 && (

Types of Spots

{tour.spotTypes.map((type) => { const typeInfo = TOUR_SPOT_TYPES[type as keyof typeof TOUR_SPOT_TYPES]; return ( {typeInfo?.emoji || '🛹'} {typeInfo?.label || type} ); })}
)} {/* Partner Shop Discount */} {tour.shopDiscount && tour.shopName && (
Partner Shop Discount

{tour.shopDiscount}% OFF at {tour.shopName}

Book this tour to receive a discount at the partner skate shop. Show your booking confirmation to the shop staff.

)} {/* Tour Sponsors - invisible placeholder until sponsors are added */} {/* Meeting point */} {tour.meetingPoint && (
Meeting Point

{tour.meetingPoint}

{tour.meetingPointCoords && (

{tour.meetingPointCoords.lat.toFixed(4)}, {tour.meetingPointCoords.lon.toFixed(4)}

)}
)} {/* Actions */}
{!user && (

Login to contact the guide and book this tour

)}
); }