Implement add toy and edit toy functions to sqlite database
This commit is contained in:
parent
a6ccc6a5f4
commit
0b22c28dfa
|
|
@ -1,5 +1,6 @@
|
||||||
|
|
||||||
import AddToyForm from '@/components/toys/AddToyForm';
|
import AddToyForm from '@/components/toys/AddToyForm';
|
||||||
import { mockToys } from '@/lib/mockData';
|
import { getToyById } from '@/data/operations';
|
||||||
import type { Toy } from '@/types';
|
import type { Toy } from '@/types';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
|
@ -9,14 +10,8 @@ interface EditToyPageProps {
|
||||||
params: { id: string };
|
params: { id: string };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server Component to fetch toy data (mocked for now)
|
|
||||||
async function getToyForEdit(id: string): Promise<Partial<Toy> | undefined> {
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 100)); // Simulate fetch
|
|
||||||
return mockToys.find(toy => toy.id === id);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default async function EditToyPage({ params }: EditToyPageProps) {
|
export default async function EditToyPage({ params }: EditToyPageProps) {
|
||||||
const toyData = await getToyForEdit(params.id);
|
const toyData = getToyById(params.id);
|
||||||
|
|
||||||
if (!toyData) {
|
if (!toyData) {
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,18 @@
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import ToyCard from "@/components/toys/ToyCard";
|
import { getToysByOwner } from "@/data/operations";
|
||||||
import { mockToys } from "@/lib/mockData"; // Using all toys for now, filter by ownerId in real app
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { PlusCircle, Edit3, Trash2, Eye } from "lucide-react";
|
import { PlusCircle, Edit3, Trash2, Eye, ToyBrick as ToyBrickIcon } from "lucide-react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import type { Toy } from "@/types";
|
import type { Toy } from "@/types";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
|
||||||
// Assume this is the logged-in user's ID
|
const currentUserId = 1;
|
||||||
const currentUserId = 'user1';
|
|
||||||
|
|
||||||
// Filter toys by current user
|
export default async function MyToysPage() {
|
||||||
const userToys = mockToys.filter(toy => toy.ownerId === currentUserId);
|
const userToys = getToysByOwner(currentUserId);
|
||||||
|
|
||||||
export default function MyToysPage() {
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
|
|
@ -33,7 +31,7 @@ export default function MyToysPage() {
|
||||||
{userToys.length === 0 ? (
|
{userToys.length === 0 ? (
|
||||||
<Card className="text-center py-12 shadow-md">
|
<Card className="text-center py-12 shadow-md">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<ToyBrick className="h-16 w-16 mx-auto text-muted-foreground mb-4" />
|
<ToyBrickIcon className="h-16 w-16 mx-auto text-muted-foreground mb-4" />
|
||||||
<CardTitle>No Toys Listed Yet</CardTitle>
|
<CardTitle>No Toys Listed Yet</CardTitle>
|
||||||
<CardDescription>Share your first toy and spread the joy!</CardDescription>
|
<CardDescription>Share your first toy and spread the joy!</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
@ -99,14 +97,14 @@ function ListedToyItem({ toy }: ListedToyItemProps) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-muted-foreground mt-2 text-sm line-clamp-2">{toy.description}</p>
|
<p className="text-muted-foreground mt-2 text-sm line-clamp-2">{toy.description}</p>
|
||||||
<div className="mt-4 text-sm">
|
<div className="mt-4 text-sm space-y-1">
|
||||||
|
<div>
|
||||||
<span className="font-semibold">Price: </span>
|
<span className="font-semibold">Price: </span>
|
||||||
{toy.pricePerDay !== undefined ? (toy.pricePerDay > 0 ? `$${toy.pricePerDay}/day` : 'Free') : 'Not set'}
|
{toy.pricePerDay !== undefined ? (toy.pricePerDay > 0 ? `$${toy.pricePerDay}/day` : 'Free') : 'Not set'}
|
||||||
</div>
|
</div>
|
||||||
{/* Could add more stats like number of rentals, views etc. here */}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,21 @@
|
||||||
|
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { ToyBrick, PlusCircle, ListOrdered, User, ShoppingBag } from "lucide-react";
|
import { ToyBrick, PlusCircle, ListOrdered, User, ShoppingBag } from "lucide-react";
|
||||||
|
import { getToysByOwner } from "@/data/operations";
|
||||||
|
|
||||||
|
const currentUserId = 1; // Mock logged-in user ID
|
||||||
|
|
||||||
|
export default async function DashboardOverviewPage() {
|
||||||
|
const userToys = getToysByOwner(currentUserId);
|
||||||
|
|
||||||
// Mock data for dashboard overview
|
|
||||||
const userStats = {
|
const userStats = {
|
||||||
listedToys: 3,
|
listedToys: userToys.length, // Real data from DB
|
||||||
activeRentals: 1, // Toys I'm renting
|
activeRentals: 1, // Mock data
|
||||||
pendingRequests: 2, // Requests for my toys
|
pendingRequests: 2, // Mock data
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function DashboardOverviewPage() {
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
<Card className="shadow-lg">
|
<Card className="shadow-lg">
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,24 @@
|
||||||
|
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { ShoppingBag, ToyBrick } from "lucide-react";
|
import { ShoppingBag, ToyBrick } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import type { Toy } from "@/types";
|
import type { Toy } from "@/types";
|
||||||
import { mockToys } from "@/lib/mockData"; // Using all toys for now
|
import { getAllToys } from "@/data/operations";
|
||||||
|
|
||||||
// Mock data: toys rented by the current user
|
|
||||||
// In a real app, this would come from a database query based on rental records
|
|
||||||
const rentedToys: (Toy & { rentalEndDate?: string, dataAiHint?: string })[] = [
|
|
||||||
{ ...mockToys[1], rentalEndDate: "2024-08-15", dataAiHint: mockToys[1]?.category.toLowerCase() }, // Remote Control Car
|
|
||||||
{ ...mockToys[4], rentalEndDate: "2024-09-01", dataAiHint: mockToys[4]?.category.toLowerCase() }, // Beginner Guitar
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
export default function MyRentalsPage() {
|
export default function MyRentalsPage() {
|
||||||
|
const allToys = getAllToys();
|
||||||
|
// Mock data: toys rented by the current user
|
||||||
|
// In a real app, this would come from a database query based on rental records
|
||||||
|
const rentedToys: (Toy & { rentalEndDate?: string })[] = [];
|
||||||
|
if (allToys.length > 1) {
|
||||||
|
rentedToys.push({ ...allToys[1], rentalEndDate: "2024-12-15" });
|
||||||
|
}
|
||||||
|
if (allToys.length > 4) {
|
||||||
|
rentedToys.push({ ...allToys[4], rentalEndDate: "2025-01-01" });
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -50,7 +54,7 @@ export default function MyRentalsPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RentalItemCardProps {
|
interface RentalItemCardProps {
|
||||||
toy: Toy & { rentalEndDate?: string, dataAiHint?: string };
|
toy: Toy & { rentalEndDate?: string };
|
||||||
}
|
}
|
||||||
|
|
||||||
function RentalItemCard({ toy }: RentalItemCardProps) {
|
function RentalItemCard({ toy }: RentalItemCardProps) {
|
||||||
|
|
|
||||||
|
|
@ -1,58 +1,55 @@
|
||||||
|
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { ListOrdered, Check, X } from "lucide-react";
|
import { ListOrdered, Check, X } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import type { Toy } from "@/types";
|
import type { Toy, RentalRequest } from "@/types";
|
||||||
import { mockToys } from "@/lib/mockData";
|
import { getAllToys } from "@/data/operations";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
|
||||||
interface RentalRequest {
|
// This is still mock data. In a real app, this would come from the database.
|
||||||
id: string;
|
function getMockRequests(): RentalRequest[] {
|
||||||
toy: Toy;
|
const allToys = getAllToys();
|
||||||
requesterName: string;
|
const myToys = allToys.filter(t => t.ownerId === 1);
|
||||||
requesterId: string;
|
|
||||||
requestedDates: string; // e.g., "Aug 5, 2024 - Aug 10, 2024"
|
if (myToys.length === 0) return [];
|
||||||
status: 'pending' | 'approved' | 'declined';
|
|
||||||
message?: string;
|
|
||||||
dataAiHint?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mock data: rental requests for the current user's toys
|
|
||||||
const rentalRequests: RentalRequest[] = [
|
const rentalRequests: RentalRequest[] = [
|
||||||
{
|
{
|
||||||
id: 'req1',
|
id: 'req1',
|
||||||
toy: mockToys[0], // Colorful Building Blocks Set (owned by user1)
|
toy: myToys[0],
|
||||||
requesterName: 'Charlie Brown',
|
requesterName: 'Charlie Brown',
|
||||||
requesterId: 'user4',
|
requesterId: 4,
|
||||||
requestedDates: 'August 10, 2024 - August 17, 2024',
|
requestedDates: 'August 10, 2024 - August 17, 2024',
|
||||||
status: 'pending',
|
status: 'pending',
|
||||||
message: 'My son would love to play with these for his birthday week!',
|
message: 'My son would love to play with these for his birthday week!',
|
||||||
dataAiHint: mockToys[0]?.category.toLowerCase(),
|
dataAiHint: myToys[0]?.category.toLowerCase(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'req2',
|
id: 'req2',
|
||||||
toy: mockToys[3], // Plush Teddy Bear (owned by user1)
|
toy: myToys.length > 1 ? myToys[1] : myToys[0],
|
||||||
requesterName: 'Diana Prince',
|
requesterName: 'Diana Prince',
|
||||||
requesterId: 'user5',
|
requesterId: 5,
|
||||||
requestedDates: 'September 1, 2024 - September 5, 2024',
|
requestedDates: 'September 1, 2024 - September 5, 2024',
|
||||||
status: 'approved',
|
status: 'approved',
|
||||||
dataAiHint: mockToys[3]?.category.toLowerCase(),
|
dataAiHint: (myToys.length > 1 ? myToys[1] : myToys[0])?.category.toLowerCase(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'req3',
|
id: 'req3',
|
||||||
toy: mockToys[0],
|
toy: myToys[0],
|
||||||
requesterName: 'Edward Nigma',
|
requesterName: 'Edward Nigma',
|
||||||
requesterId: 'user6',
|
requesterId: 6,
|
||||||
requestedDates: 'July 20, 2024 - July 22, 2024',
|
requestedDates: 'July 20, 2024 - July 22, 2024',
|
||||||
status: 'declined',
|
status: 'declined',
|
||||||
message: 'Looking for a weekend rental.',
|
message: 'Looking for a weekend rental.',
|
||||||
dataAiHint: mockToys[0]?.category.toLowerCase(),
|
dataAiHint: myToys[0]?.category.toLowerCase(),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
return rentalRequests;
|
||||||
|
}
|
||||||
|
|
||||||
// Assuming current user is user1 for whom these requests are relevant
|
const currentUserToyRequests = getMockRequests();
|
||||||
const currentUserToyRequests = rentalRequests.filter(req => req.toy.ownerId === 'user1');
|
|
||||||
|
|
||||||
|
|
||||||
export default function RentalRequestsPage() {
|
export default function RentalRequestsPage() {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,28 @@
|
||||||
|
|
||||||
import ToyList from '@/components/toys/ToyList';
|
import ToyList from '@/components/toys/ToyList';
|
||||||
import { mockToys } from '@/lib/mockData';
|
import { getAllToys } from '@/data/operations';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { PlusCircle } from 'lucide-react';
|
import { PlusCircle } from 'lucide-react';
|
||||||
|
|
||||||
export default function HomePage() {
|
export default async function HomePage() {
|
||||||
|
const toys = getAllToys();
|
||||||
|
const t = (key: string, params?: any) => {
|
||||||
|
// Basic mock t function for non-localized pages
|
||||||
|
const keyParts = key.split('.');
|
||||||
|
let text = keyParts.pop() || key;
|
||||||
|
text = text.replace(/_/g, ' ');
|
||||||
|
text = text.charAt(0).toUpperCase() + text.slice(1);
|
||||||
|
|
||||||
|
if (params) {
|
||||||
|
Object.keys(params).forEach(pKey => {
|
||||||
|
text = text.replace(`{${pKey}}`, params[pKey]);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
<section className="text-center py-12 bg-gradient-to-r from-primary/10 via-background to-accent/10 rounded-lg shadow">
|
<section className="text-center py-12 bg-gradient-to-r from-primary/10 via-background to-accent/10 rounded-lg shadow">
|
||||||
|
|
@ -33,7 +51,7 @@ export default function HomePage() {
|
||||||
<h2 className="text-3xl font-bold font-headline text-center mb-8 text-primary">
|
<h2 className="text-3xl font-bold font-headline text-center mb-8 text-primary">
|
||||||
Available Toys
|
Available Toys
|
||||||
</h2>
|
</h2>
|
||||||
<ToyList toys={mockToys.map(toy => ({...toy, dataAiHint: toy.category.toLowerCase()}))} />
|
<ToyList toys={toys} t={t} />
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,24 @@
|
||||||
|
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import { mockToys } from '@/lib/mockData';
|
import { getToyById, getAllToys } from '@/data/operations';
|
||||||
import type { Toy } from '@/types';
|
import type { Toy } from '@/types';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import AvailabilityCalendar from '@/components/toys/AvailabilityCalendar';
|
import { Calendar } from '@/components/ui/calendar';
|
||||||
import { ArrowLeft, CalendarDays, DollarSign, MapPin, ShoppingBag, UserCircle2 } from 'lucide-react';
|
import { ArrowLeft, DollarSign, MapPin, ShoppingBag, UserCircle2 } from 'lucide-react';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Separator } from '@/components/ui/separator';
|
import { Separator } from '@/components/ui/separator';
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
|
import { addDays, parseISO } from 'date-fns';
|
||||||
|
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
||||||
|
|
||||||
|
|
||||||
interface ToyPageProps {
|
interface ToyPageProps {
|
||||||
params: { id: string };
|
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) {
|
export default async function ToyPage({ params }: ToyPageProps) {
|
||||||
const toy = await getToyById(params.id);
|
const toy = getToyById(params.id);
|
||||||
|
|
||||||
if (!toy) {
|
if (!toy) {
|
||||||
return (
|
return (
|
||||||
|
|
@ -39,6 +37,12 @@ export default async function ToyPage({ params }: ToyPageProps) {
|
||||||
|
|
||||||
const placeholderHint = toy.category.toLowerCase() || "toy detail";
|
const placeholderHint = toy.category.toLowerCase() || "toy detail";
|
||||||
|
|
||||||
|
const disabledDates = toy.unavailableRanges.map(range => {
|
||||||
|
const from = parseISO(range.startDate);
|
||||||
|
const to = parseISO(range.endDate);
|
||||||
|
return { from, to };
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto py-8 px-4">
|
<div className="container mx-auto py-8 px-4">
|
||||||
<Link href="/" className="inline-flex items-center text-primary hover:underline mb-6 group">
|
<Link href="/" className="inline-flex items-center text-primary hover:underline mb-6 group">
|
||||||
|
|
@ -47,7 +51,6 @@ export default async function ToyPage({ params }: ToyPageProps) {
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<div className="grid md:grid-cols-2 gap-8 lg:gap-12 items-start">
|
<div className="grid md:grid-cols-2 gap-8 lg:gap-12 items-start">
|
||||||
{/* Image Gallery Section */}
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="aspect-video relative w-full rounded-lg overflow-hidden shadow-lg">
|
<div className="aspect-video relative w-full rounded-lg overflow-hidden shadow-lg">
|
||||||
<Image
|
<Image
|
||||||
|
|
@ -76,7 +79,6 @@ export default async function ToyPage({ params }: ToyPageProps) {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Toy Details Section */}
|
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<Badge variant="secondary" className="text-sm">{toy.category}</Badge>
|
<Badge variant="secondary" className="text-sm">{toy.category}</Badge>
|
||||||
<h1 className="text-4xl font-bold font-headline text-primary">{toy.name}</h1>
|
<h1 className="text-4xl font-bold font-headline text-primary">{toy.name}</h1>
|
||||||
|
|
@ -88,11 +90,18 @@ export default async function ToyPage({ params }: ToyPageProps) {
|
||||||
<Separator />
|
<Separator />
|
||||||
|
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm">
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center gap-2">
|
||||||
<UserCircle2 className="h-5 w-5 mr-2 text-accent" />
|
<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>
|
<div>
|
||||||
<span className="font-medium text-muted-foreground">Owner: </span>
|
<span className="font-medium text-muted-foreground">Owner: </span>
|
||||||
<span className="text-foreground">{toy.ownerName}</span>
|
<Link href={`/owner/${toy.ownerId}/toys`} className="text-foreground hover:underline">
|
||||||
|
{toy.ownerName}
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{toy.location && (
|
{toy.location && (
|
||||||
|
|
@ -109,7 +118,9 @@ export default async function ToyPage({ params }: ToyPageProps) {
|
||||||
<DollarSign className="h-5 w-5 mr-2 text-accent" />
|
<DollarSign className="h-5 w-5 mr-2 text-accent" />
|
||||||
<div>
|
<div>
|
||||||
<span className="font-medium text-muted-foreground">Price: </span>
|
<span className="font-medium text-muted-foreground">Price: </span>
|
||||||
<span className="text-foreground font-semibold">{toy.pricePerDay > 0 ? `$${toy.pricePerDay}/day` : 'Free'}</span>
|
<span className="text-foreground font-semibold">
|
||||||
|
{toy.pricePerDay > 0 ? `$${toy.pricePerDay}/day` : 'Free'}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -117,7 +128,22 @@ export default async function ToyPage({ params }: ToyPageProps) {
|
||||||
|
|
||||||
<Separator />
|
<Separator />
|
||||||
|
|
||||||
<AvailabilityCalendar availability={toy.availability} />
|
<Card className="shadow-md">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="text-xl font-headline text-primary">Availability Calendar</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="flex justify-center">
|
||||||
|
<Calendar
|
||||||
|
mode="single"
|
||||||
|
disabled={disabledDates}
|
||||||
|
month={new Date()}
|
||||||
|
className="rounded-md border"
|
||||||
|
/>
|
||||||
|
</CardContent>
|
||||||
|
<p className="text-xs text-muted-foreground mt-0 pb-4 text-center">
|
||||||
|
Dates shown in gray or crossed out are unavailable.
|
||||||
|
</p>
|
||||||
|
</Card>
|
||||||
|
|
||||||
<Button size="lg" className="w-full mt-6 transition-transform transform hover:scale-105">
|
<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
|
<ShoppingBag className="mr-2 h-5 w-5" /> Request to Rent
|
||||||
|
|
@ -130,7 +156,8 @@ export default async function ToyPage({ params }: ToyPageProps) {
|
||||||
|
|
||||||
// Generate static paths for all toys
|
// Generate static paths for all toys
|
||||||
export async function generateStaticParams() {
|
export async function generateStaticParams() {
|
||||||
return mockToys.map((toy) => ({
|
const toys = getAllToys();
|
||||||
|
return toys.map((toy) => ({
|
||||||
id: toy.id,
|
id: toy.id,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
toyshare.db
BIN
toyshare.db
Binary file not shown.
BIN
toyshare.db-shm
BIN
toyshare.db-shm
Binary file not shown.
BIN
toyshare.db-wal
BIN
toyshare.db-wal
Binary file not shown.
Loading…
Reference in New Issue