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

138 lines
5.1 KiB
TypeScript

import Image from 'next/image';
import { getToyById, getAllToys } from '@/data/operations';
import type { Toy } from '@/types';
import { Button } from '@/components/ui/button';
import { ArrowLeft, DollarSign, MapPin, ShoppingBag, UserCircle2 } from 'lucide-react';
import Link from 'next/link';
import { Badge } from '@/components/ui/badge';
import { Separator } from '@/components/ui/separator';
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
interface ToyPageProps {
params: { id: string };
}
export default async function ToyPage({ params }: ToyPageProps) {
const toy = 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">
<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>
<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 gap-2">
<Link href={`/owner/${toy.ownerId}/toys`} className="flex-shrink-0">
<Avatar className="h-8 w-8">
<AvatarImage src={toy.ownerAvatarUrl} alt={toy.ownerName} data-ai-hint="owner avatar" />
<AvatarFallback>{toy.ownerName.split(' ').map(n => n[0]).join('').toUpperCase()}</AvatarFallback>
</Avatar>
</Link>
<div>
<span className="font-medium text-muted-foreground">Owner: </span>
<Link href={`/owner/${toy.ownerId}/toys`} className="text-foreground hover:underline">
{toy.ownerName}
</Link>
</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 />
<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() {
const toys = getAllToys();
return toys.map((toy) => ({
id: toy.id,
}));
}