ToyShare/src/app/toys/[id]/page.tsx

137 lines
5.0 KiB
TypeScript

import Image from 'next/image';
import { mockToys } from '@/lib/mockData';
import type { Toy } from '@/types';
import { Button } from '@/components/ui/button';
import AvailabilityCalendar from '@/components/toys/AvailabilityCalendar';
import { ArrowLeft, CalendarDays, DollarSign, MapPin, ShoppingBag, UserCircle2 } from 'lucide-react';
import Link from 'next/link';
import { Badge } from '@/components/ui/badge';
import { Separator } from '@/components/ui/separator';
interface ToyPageProps {
params: { id: string };
}
// Server Component to fetch toy data (mocked for now)
async function getToyById(id: string): Promise<Toy | undefined> {
// In a real app, this would fetch from a database
await new Promise(resolve => setTimeout(resolve, 200)); // Simulate network delay
return mockToys.find(toy => toy.id === id);
}
export default async function ToyPage({ params }: ToyPageProps) {
const toy = await getToyById(params.id);
if (!toy) {
return (
<div className="text-center py-12">
<h1 className="text-2xl font-bold mb-4">Toy Not Found</h1>
<p className="text-muted-foreground mb-6">Sorry, the toy you are looking for does not exist or has been removed.</p>
<Link href="/" passHref>
<Button variant="outline">
<ArrowLeft className="mr-2 h-4 w-4" />
Back to All Toys
</Button>
</Link>
</div>
);
}
const placeholderHint = toy.category.toLowerCase() || "toy detail";
return (
<div className="container mx-auto py-8 px-4">
<Link href="/" className="inline-flex items-center text-primary hover:underline mb-6 group">
<ArrowLeft className="mr-2 h-4 w-4 transition-transform group-hover:-translate-x-1" />
Back to All Toys
</Link>
<div className="grid md:grid-cols-2 gap-8 lg:gap-12 items-start">
{/* Image Gallery Section */}
<div className="space-y-4">
<div className="aspect-video relative w-full rounded-lg overflow-hidden shadow-lg">
<Image
src={toy.images[0] || 'https://placehold.co/600x400.png'}
alt={toy.name}
layout="fill"
objectFit="cover"
data-ai-hint={placeholderHint + " main"}
priority
/>
</div>
{toy.images.length > 1 && (
<div className="grid grid-cols-3 gap-2">
{toy.images.slice(1, 4).map((img, index) => (
<div key={index} className="aspect-square relative w-full rounded-md overflow-hidden shadow">
<Image
src={img}
alt={`${toy.name} - image ${index + 2}`}
layout="fill"
objectFit="cover"
data-ai-hint={placeholderHint + " thumbnail"}
/>
</div>
))}
</div>
)}
</div>
{/* Toy Details Section */}
<div className="space-y-6">
<Badge variant="secondary" className="text-sm">{toy.category}</Badge>
<h1 className="text-4xl font-bold font-headline text-primary">{toy.name}</h1>
<div className="text-lg text-foreground/90 leading-relaxed">
<p>{toy.description}</p>
</div>
<Separator />
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm">
<div className="flex items-center">
<UserCircle2 className="h-5 w-5 mr-2 text-accent" />
<div>
<span className="font-medium text-muted-foreground">Owner: </span>
<span className="text-foreground">{toy.ownerName}</span>
</div>
</div>
{toy.location && (
<div className="flex items-center">
<MapPin className="h-5 w-5 mr-2 text-accent" />
<div>
<span className="font-medium text-muted-foreground">Location: </span>
<span className="text-foreground">{toy.location}</span>
</div>
</div>
)}
{toy.pricePerDay !== undefined && (
<div className="flex items-center col-span-full sm:col-span-1">
<DollarSign className="h-5 w-5 mr-2 text-accent" />
<div>
<span className="font-medium text-muted-foreground">Price: </span>
<span className="text-foreground font-semibold">{toy.pricePerDay > 0 ? `$${toy.pricePerDay}/day` : 'Free'}</span>
</div>
</div>
)}
</div>
<Separator />
<AvailabilityCalendar availability={toy.availability} />
<Button size="lg" className="w-full mt-6 transition-transform transform hover:scale-105">
<ShoppingBag className="mr-2 h-5 w-5" /> Request to Rent
</Button>
</div>
</div>
</div>
);
}
// Generate static paths for all toys
export async function generateStaticParams() {
return mockToys.map((toy) => ({
id: toy.id,
}));
}