138 lines
5.1 KiB
TypeScript
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,
|
|
}));
|
|
}
|