From 0b22c28dfabb94460fbb3bc0624bb73e85de4e58 Mon Sep 17 00:00:00 2001 From: Indigo Tang Date: Sun, 6 Jul 2025 13:46:36 +0000 Subject: [PATCH] Implement add toy and edit toy functions to sqlite database --- src/app/dashboard/my-toys/edit/[id]/page.tsx | 11 +-- src/app/dashboard/my-toys/page.tsx | 26 +++--- src/app/dashboard/page.tsx | 19 ++-- src/app/dashboard/rentals/page.tsx | 24 ++--- src/app/dashboard/requests/page.tsx | 89 +++++++++---------- src/app/page.tsx | 24 ++++- src/app/toys/[id]/page.tsx | 75 +++++++++++----- toyshare.db | Bin 24576 -> 24576 bytes toyshare.db-shm | Bin 32768 -> 32768 bytes toyshare.db-wal | Bin 4136512 -> 4136512 bytes 10 files changed, 156 insertions(+), 112 deletions(-) diff --git a/src/app/dashboard/my-toys/edit/[id]/page.tsx b/src/app/dashboard/my-toys/edit/[id]/page.tsx index 82461ce..a6ad6f7 100644 --- a/src/app/dashboard/my-toys/edit/[id]/page.tsx +++ b/src/app/dashboard/my-toys/edit/[id]/page.tsx @@ -1,5 +1,6 @@ + import AddToyForm from '@/components/toys/AddToyForm'; -import { mockToys } from '@/lib/mockData'; +import { getToyById } from '@/data/operations'; import type { Toy } from '@/types'; import { Button } from '@/components/ui/button'; import Link from 'next/link'; @@ -9,14 +10,8 @@ interface EditToyPageProps { params: { id: string }; } -// Server Component to fetch toy data (mocked for now) -async function getToyForEdit(id: string): Promise | undefined> { - await new Promise(resolve => setTimeout(resolve, 100)); // Simulate fetch - return mockToys.find(toy => toy.id === id); -} - export default async function EditToyPage({ params }: EditToyPageProps) { - const toyData = await getToyForEdit(params.id); + const toyData = getToyById(params.id); if (!toyData) { return ( diff --git a/src/app/dashboard/my-toys/page.tsx b/src/app/dashboard/my-toys/page.tsx index 7801b32..b8cf869 100644 --- a/src/app/dashboard/my-toys/page.tsx +++ b/src/app/dashboard/my-toys/page.tsx @@ -1,20 +1,18 @@ + import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; -import ToyCard from "@/components/toys/ToyCard"; -import { mockToys } from "@/lib/mockData"; // Using all toys for now, filter by ownerId in real app +import { getToysByOwner } from "@/data/operations"; 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 type { Toy } from "@/types"; import { Badge } from "@/components/ui/badge"; -// Assume this is the logged-in user's ID -const currentUserId = 'user1'; +const currentUserId = 1; -// Filter toys by current user -const userToys = mockToys.filter(toy => toy.ownerId === currentUserId); +export default async function MyToysPage() { + const userToys = getToysByOwner(currentUserId); -export default function MyToysPage() { return (
@@ -33,7 +31,7 @@ export default function MyToysPage() { {userToys.length === 0 ? ( - + No Toys Listed Yet Share your first toy and spread the joy! @@ -99,14 +97,14 @@ function ListedToyItem({ toy }: ListedToyItemProps) {

{toy.description}

-
- Price: - {toy.pricePerDay !== undefined ? (toy.pricePerDay > 0 ? `$${toy.pricePerDay}/day` : 'Free') : 'Not set'} +
+
+ Price: + {toy.pricePerDay !== undefined ? (toy.pricePerDay > 0 ? `$${toy.pricePerDay}/day` : 'Free') : 'Not set'} +
- {/* Could add more stats like number of rentals, views etc. here */}
); } - diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index d21f2c6..11f861c 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -1,16 +1,21 @@ + import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import Link from "next/link"; import { ToyBrick, PlusCircle, ListOrdered, User, ShoppingBag } from "lucide-react"; +import { getToysByOwner } from "@/data/operations"; -// Mock data for dashboard overview -const userStats = { - listedToys: 3, - activeRentals: 1, // Toys I'm renting - pendingRequests: 2, // Requests for my toys -}; +const currentUserId = 1; // Mock logged-in user ID + +export default async function DashboardOverviewPage() { + const userToys = getToysByOwner(currentUserId); + + const userStats = { + listedToys: userToys.length, // Real data from DB + activeRentals: 1, // Mock data + pendingRequests: 2, // Mock data + }; -export default function DashboardOverviewPage() { return (
diff --git a/src/app/dashboard/rentals/page.tsx b/src/app/dashboard/rentals/page.tsx index c1676ba..c0cc6fa 100644 --- a/src/app/dashboard/rentals/page.tsx +++ b/src/app/dashboard/rentals/page.tsx @@ -1,20 +1,24 @@ + import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { ShoppingBag, ToyBrick } from "lucide-react"; import Link from "next/link"; import { Button } from "@/components/ui/button"; import Image from "next/image"; import type { Toy } from "@/types"; -import { mockToys } from "@/lib/mockData"; // Using all toys for now - -// 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 -]; - +import { getAllToys } from "@/data/operations"; 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 (
@@ -50,7 +54,7 @@ export default function MyRentalsPage() { } interface RentalItemCardProps { - toy: Toy & { rentalEndDate?: string, dataAiHint?: string }; + toy: Toy & { rentalEndDate?: string }; } function RentalItemCard({ toy }: RentalItemCardProps) { diff --git a/src/app/dashboard/requests/page.tsx b/src/app/dashboard/requests/page.tsx index 93a8fe1..8b41d83 100644 --- a/src/app/dashboard/requests/page.tsx +++ b/src/app/dashboard/requests/page.tsx @@ -1,58 +1,55 @@ + import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { ListOrdered, Check, X } from "lucide-react"; import Link from "next/link"; import { Button } from "@/components/ui/button"; import Image from "next/image"; -import type { Toy } from "@/types"; -import { mockToys } from "@/lib/mockData"; +import type { Toy, RentalRequest } from "@/types"; +import { getAllToys } from "@/data/operations"; import { Badge } from "@/components/ui/badge"; -interface RentalRequest { - id: string; - toy: Toy; - requesterName: string; - requesterId: string; - requestedDates: string; // e.g., "Aug 5, 2024 - Aug 10, 2024" - status: 'pending' | 'approved' | 'declined'; - message?: string; - dataAiHint?: string; +// This is still mock data. In a real app, this would come from the database. +function getMockRequests(): RentalRequest[] { + const allToys = getAllToys(); + const myToys = allToys.filter(t => t.ownerId === 1); + + if (myToys.length === 0) return []; + + const rentalRequests: RentalRequest[] = [ + { + id: 'req1', + toy: myToys[0], + requesterName: 'Charlie Brown', + requesterId: 4, + requestedDates: 'August 10, 2024 - August 17, 2024', + status: 'pending', + message: 'My son would love to play with these for his birthday week!', + dataAiHint: myToys[0]?.category.toLowerCase(), + }, + { + id: 'req2', + toy: myToys.length > 1 ? myToys[1] : myToys[0], + requesterName: 'Diana Prince', + requesterId: 5, + requestedDates: 'September 1, 2024 - September 5, 2024', + status: 'approved', + dataAiHint: (myToys.length > 1 ? myToys[1] : myToys[0])?.category.toLowerCase(), + }, + { + id: 'req3', + toy: myToys[0], + requesterName: 'Edward Nigma', + requesterId: 6, + requestedDates: 'July 20, 2024 - July 22, 2024', + status: 'declined', + message: 'Looking for a weekend rental.', + dataAiHint: myToys[0]?.category.toLowerCase(), + }, + ]; + return rentalRequests; } -// Mock data: rental requests for the current user's toys -const rentalRequests: RentalRequest[] = [ - { - id: 'req1', - toy: mockToys[0], // Colorful Building Blocks Set (owned by user1) - requesterName: 'Charlie Brown', - requesterId: 'user4', - requestedDates: 'August 10, 2024 - August 17, 2024', - status: 'pending', - message: 'My son would love to play with these for his birthday week!', - dataAiHint: mockToys[0]?.category.toLowerCase(), - }, - { - id: 'req2', - toy: mockToys[3], // Plush Teddy Bear (owned by user1) - requesterName: 'Diana Prince', - requesterId: 'user5', - requestedDates: 'September 1, 2024 - September 5, 2024', - status: 'approved', - dataAiHint: mockToys[3]?.category.toLowerCase(), - }, - { - id: 'req3', - toy: mockToys[0], - requesterName: 'Edward Nigma', - requesterId: 'user6', - requestedDates: 'July 20, 2024 - July 22, 2024', - status: 'declined', - message: 'Looking for a weekend rental.', - dataAiHint: mockToys[0]?.category.toLowerCase(), - }, -]; - -// Assuming current user is user1 for whom these requests are relevant -const currentUserToyRequests = rentalRequests.filter(req => req.toy.ownerId === 'user1'); +const currentUserToyRequests = getMockRequests(); export default function RentalRequestsPage() { diff --git a/src/app/page.tsx b/src/app/page.tsx index 082b1be..dbf52bc 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,10 +1,28 @@ + import ToyList from '@/components/toys/ToyList'; -import { mockToys } from '@/lib/mockData'; +import { getAllToys } from '@/data/operations'; import { Button } from '@/components/ui/button'; import Link from 'next/link'; 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 (
@@ -33,7 +51,7 @@ export default function HomePage() {

Available Toys

- ({...toy, dataAiHint: toy.category.toLowerCase()}))} /> +
); diff --git a/src/app/toys/[id]/page.tsx b/src/app/toys/[id]/page.tsx index 3e45e44..ebc6423 100644 --- a/src/app/toys/[id]/page.tsx +++ b/src/app/toys/[id]/page.tsx @@ -1,26 +1,24 @@ + import Image from 'next/image'; -import { mockToys } from '@/lib/mockData'; +import { getToyById, getAllToys } from '@/data/operations'; 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 { Calendar } from '@/components/ui/calendar'; +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 { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +import { addDays, parseISO } from 'date-fns'; +import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; + interface ToyPageProps { params: { id: string }; } -// Server Component to fetch toy data (mocked for now) -async function getToyById(id: string): Promise { - // 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); + const toy = getToyById(params.id); if (!toy) { return ( @@ -39,6 +37,12 @@ export default async function ToyPage({ params }: ToyPageProps) { 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 (
@@ -47,7 +51,6 @@ export default async function ToyPage({ params }: ToyPageProps) {
- {/* Image Gallery Section */}
- {/* Toy Details Section */}
{toy.category}

{toy.name}

@@ -88,12 +90,19 @@ export default async function ToyPage({ params }: ToyPageProps) {
-
- -
- Owner: - {toy.ownerName} -
+
+ + + + {toy.ownerName.split(' ').map(n => n[0]).join('').toUpperCase()} + + +
+ Owner: + + {toy.ownerName} + +
{toy.location && (
@@ -109,7 +118,9 @@ export default async function ToyPage({ params }: ToyPageProps) {
Price: - {toy.pricePerDay > 0 ? `$${toy.pricePerDay}/day` : 'Free'} + + {toy.pricePerDay > 0 ? `$${toy.pricePerDay}/day` : 'Free'} +
)} @@ -117,7 +128,22 @@ export default async function ToyPage({ params }: ToyPageProps) { - + + + Availability Calendar + + + + +

+ Dates shown in gray or crossed out are unavailable. +

+