import { useState, useEffect } from 'react'; import Link from 'next/link'; import Head from 'next/head'; import { useRouter } from 'next/router'; interface Listing { id: string; title: string; description: string; price: number; currency: string; quantity: number; category: string; status: string; sellerId: string; sellerName?: string; location?: { city?: string; region?: string }; tags: string[]; viewCount: number; createdAt: string; updatedAt: string; } const categoryLabels: Record = { seeds: 'Seeds', seedlings: 'Seedlings', mature_plants: 'Mature Plants', cuttings: 'Cuttings', produce: 'Produce', supplies: 'Supplies', }; const categoryIcons: Record = { seeds: '🌰', seedlings: '🌱', mature_plants: '🪴', cuttings: '✂️', produce: '🥬', supplies: '🧰', }; const statusColors: Record = { draft: 'bg-gray-100 text-gray-800', active: 'bg-green-100 text-green-800', sold: 'bg-blue-100 text-blue-800', expired: 'bg-yellow-100 text-yellow-800', cancelled: 'bg-red-100 text-red-800', }; export default function ListingDetailPage() { const router = useRouter(); const { id } = router.query; const [listing, setListing] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const [showOfferModal, setShowOfferModal] = useState(false); const [offerAmount, setOfferAmount] = useState(''); const [offerMessage, setOfferMessage] = useState(''); const [submitting, setSubmitting] = useState(false); useEffect(() => { if (id) { fetchListing(); } }, [id]); const fetchListing = async () => { try { const response = await fetch(`/api/marketplace/listings/${id}`); const data = await response.json(); if (!response.ok) { throw new Error(data.error || 'Failed to fetch listing'); } setListing(data); } catch (err) { setError(err instanceof Error ? err.message : 'Something went wrong'); } finally { setLoading(false); } }; const handleMakeOffer = async (e: React.FormEvent) => { e.preventDefault(); setSubmitting(true); try { const response = await fetch(`/api/marketplace/listings/${id}/offers`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-user-id': 'demo-buyer', 'x-user-name': 'Demo Buyer', }, body: JSON.stringify({ amount: parseFloat(offerAmount), message: offerMessage, }), }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || 'Failed to submit offer'); } alert('Offer submitted successfully!'); setShowOfferModal(false); setOfferAmount(''); setOfferMessage(''); } catch (err) { alert(err instanceof Error ? err.message : 'Failed to submit offer'); } finally { setSubmitting(false); } }; if (loading) { return (

Loading listing...

); } if (error || !listing) { return (

Listing Not Found

{error || 'The listing you are looking for does not exist.'}

Back to Marketplace
); } return (
{listing.title} - LocalGreenChain Marketplace {/* Header */}
{/* Main Content */}
{/* Listing Details */}
{/* Image Placeholder */}
{categoryIcons[listing.category] || '🌿'}
{/* Details */}
{listing.status.charAt(0).toUpperCase() + listing.status.slice(1)} {categoryLabels[listing.category]}
{listing.viewCount} views

{listing.title}

{listing.description}

{/* Tags */} {listing.tags.length > 0 && (

Tags

{listing.tags.map((tag) => ( {tag} ))}
)} {/* Additional Info */}
Listed
{new Date(listing.createdAt).toLocaleDateString()}
Last Updated
{new Date(listing.updatedAt).toLocaleDateString()}
{listing.location && (
Location
{[listing.location.city, listing.location.region].filter(Boolean).join(', ')}
)}
{/* Sidebar */}
{/* Price Card */}
${listing.price.toFixed(2)} {listing.currency}
{listing.quantity} available
{listing.status === 'active' && ( <> )} {listing.status === 'sold' && (
This item has been sold
)} {/* Seller Info */}

Seller

🧑‍🌾
{listing.sellerName || 'Anonymous Seller'}
Member
{/* Offer Modal */} {showOfferModal && (

Make an Offer

$ setOfferAmount(e.target.value)} required min="0.01" step="0.01" placeholder={listing.price.toFixed(2)} className="w-full pl-8 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent" />

Asking price: ${listing.price.toFixed(2)}