'use client'; import { useEffect, useState } from 'react'; import { useParams } from 'next/navigation'; import { wishlistsApi, itemsApi, claimingApi, type Wishlist, type Item } from '@/lib/api'; import Header from '@/components/header'; import Footer from '@/components/footer'; import PasswordLockGuard from '@/components/password-lock-guard'; export default function PublicWishlistPage() { const params = useParams(); const [wishlist, setWishlist] = useState(null); const [items, setItems] = useState([]); const [showClaimed, setShowClaimed] = useState(false); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(''); // Claim form state const [claimingItemId, setClaimingItemId] = useState(null); const [claimNote, setClaimNote] = useState(''); const [isClaiming, setIsClaiming] = useState(false); const [claimError, setClaimError] = useState(''); const [justClaimedItemId, setJustClaimedItemId] = useState(null); const [justClaimedNote, setJustClaimedNote] = useState(''); // Unclaim state const [isUnclaiming, setIsUnclaiming] = useState(false); const [unclaimError, setUnclaimError] = useState(''); useEffect(() => { fetchWishlist(); }, [params.slug]); const fetchWishlist = async () => { if (!params.slug) return; try { const wishlistData = await wishlistsApi.getBySlug(params.slug as string); setWishlist(wishlistData); const itemsData = await itemsApi.getAll(wishlistData.id); setItems(itemsData.sort((a, b) => a.sortOrder - b.sortOrder)); } catch (err: any) { setError(err.message || 'Wishlist not found'); } finally { setIsLoading(false); } }; const handleClaimItem = (itemId: string) => { setClaimingItemId(itemId); setClaimError(''); setClaimNote(''); setJustClaimedItemId(null); }; const handleSubmitClaim = async (e: React.FormEvent, itemId: string) => { e.preventDefault(); setIsClaiming(true); setClaimError(''); try { await claimingApi.claim(itemId, undefined, claimNote); setJustClaimedItemId(itemId); setJustClaimedNote(claimNote); setClaimingItemId(null); setClaimNote(''); fetchWishlist(); } catch (err: any) { setClaimError(err.message || 'Failed to claim item'); } finally { setIsClaiming(false); } }; const handleUnclaim = async (itemId: string) => { if (!confirm('Are you sure you want to unclaim this item?')) { return; } setIsUnclaiming(true); setUnclaimError(''); try { await claimingApi.unclaim(itemId); fetchWishlist(); } catch (err: any) { setUnclaimError(err.message || 'Failed to unclaim item'); } finally { setIsUnclaiming(false); } }; const filteredItems = showClaimed ? items : items.filter((item) => !item.claimedAt || item.id === justClaimedItemId); const formatPrice = (price: number | null, currency: string) => { if (!price) return null; return new Intl.NumberFormat('en-US', { style: 'currency', currency: currency || 'USD', }).format(price); }; if (isLoading) { return (

Loading...

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

Wishlist Not Found

{error || 'This wishlist does not exist or is not public.'}

); } return (
{/* Main Content */}
Back to Home {/* Preferences Section */} {wishlist.preferences && (

General Interests & Preferences

{ // Make all links open in new tab const target = e.target as HTMLElement; if (target.tagName === 'A') { e.preventDefault(); window.open((target as HTMLAnchorElement).href, '_blank', 'noopener,noreferrer'); } }} />
)} {/* Controls */}
{filteredItems.length} of {items.length} items
{/* Items List */} {filteredItems.length === 0 ? (

{showClaimed ? 'No items in this wishlist yet' : 'All items have been claimed!'}

) : (
{filteredItems.map((item) => (
{/* Left: Image */} {item.imageUrl && (
{item.name}
)} {/* Middle: Item Details */}

{item.name}

{item.description && (

{item.description}

)}
{/* Right: Action Area */}
{item.purchaseUrls && item.purchaseUrls.length > 0 && ( )}
{/* Claimed Badge, Success Message, or Claim Button/Form */}
{justClaimedItemId === item.id ? (

Item Claimed!

The status is now locked.

{justClaimedNote && (

Your Note: "{justClaimedNote}"

)}
) : item.claimedAt ? (

Claimed by {item.claimedByName}

{item.claimedByNote && (

Note: {item.claimedByNote}

)} {item.isPurchased && (

✓ Purchased

)} {showClaimed && ( )}
) : claimingItemId === item.id ? (
handleSubmitClaim(e, item.id)} className="space-y-3"> {claimError && (
{claimError}
)}