import { useState } from 'react'; import { Link, useNavigate } from 'react-router-dom'; import { nip19 } from 'nostr-tools'; import { Card, CardContent } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; import { useAuthor } from '@/hooks/useAuthor'; import { useCurrentUser } from '@/hooks/useCurrentUser'; import { genUserName } from '@/lib/genUserName'; import { getSkateboardRating, getTrustLevel, SELLER_TRUST_BADGES } from '@/lib/skateboardRating'; import { GEAR_CONDITIONS, GEAR_CATEGORIES, PRICE_TYPES, formatPrice, type MarketplaceItem } from '@/lib/types'; import { MessageCircle, MapPin, Search, Tag, CheckCircle, ShieldCheck, AlertTriangle, MoreVertical, Flag, } from 'lucide-react'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { ReportDialog } from '@/components/ReportDialog'; import { formatDistanceToNow } from 'date-fns'; interface GearSwapItemCardProps { item: MarketplaceItem; trustScore?: number; salesCount: number; isFollowing?: boolean; } export function GearSwapItemCard({ item, trustScore, salesCount, isFollowing }: GearSwapItemCardProps) { const { user } = useCurrentUser(); const navigate = useNavigate(); const author = useAuthor(item.pubkey); const metadata = author.data?.metadata; const displayName = metadata?.name ?? genUserName(item.pubkey); const avatar = metadata?.picture; const [showReportDialog, setShowReportDialog] = useState(false); const npub = nip19.npubEncode(item.pubkey); const isOwnListingCheck = user?.pubkey === item.pubkey; // Format price display const priceDisplay = formatPrice(item.price, item.priceType); const timeAgo = formatDistanceToNow(new Date(item.createdAt * 1000), { addSuffix: true }); const primaryImage = item.images[0]; const isWTB = item.listingType === 'wtb'; // Get condition info const conditionInfo = item.condition ? GEAR_CONDITIONS[item.condition] : null; // Get category label const categoryLabel = item.category?.find((c) => GEAR_CATEGORIES[c as keyof typeof GEAR_CATEGORIES]) ? GEAR_CATEGORIES[item.category.find((c) => GEAR_CATEGORIES[c as keyof typeof GEAR_CATEGORIES]) as keyof typeof GEAR_CATEGORIES] : null; // Get price type label const priceTypeLabel = item.priceType ? PRICE_TYPES[item.priceType]?.label : null; // Skateboard rating for seller const sellerRating = getSkateboardRating(salesCount); // Trust level const trustLevel = getTrustLevel(trustScore); const trustBadge = SELLER_TRUST_BADGES[trustLevel]; const isOwnListing = user?.pubkey === item.pubkey; return ( navigate(`/messages/${npub}`)} > {/* Image */}
{primaryImage ? ( {item.title} ) : (
{isWTB ? '🔍' : '🛹'}
)} {/* WTB Badge */} {isWTB && ( WTB )} {/* Price Badge */}
{priceDisplay}
{/* Condition Badge (bottom left) */} {conditionInfo && ( {conditionInfo.emoji} {conditionInfo.label} )} {/* More options menu */} {!isOwnListingCheck && (
{ e.stopPropagation(); setShowReportDialog(true); }} className="text-red-500 focus:text-red-500" > Report
)}
{/* Content */}
{/* Title */}

{item.title}

{/* Category + Size */}
{categoryLabel && ( {categoryLabel} )} {item.size && ( {item.size} )}
{/* Location */} {item.location && (
{item.location}
)} {/* Divider */}
{/* Seller Info */}
{displayName.slice(0, 2).toUpperCase()} {displayName} {/* Trust Badge */} {trustLevel === 'verified' && } {trustLevel === 'trusted' && } {trustLevel === 'new' && } {trustBadge.label}

{trustBadge.description}

{/* Skateboard Rating */}
{sellerRating.rating > 0 ? ( {sellerRating.display} ) : ( 🛹 New seller )}

{salesCount} sale{salesCount !== 1 ? 's' : ''}

{sellerRating.label}

{timeAgo}
{/* Contact Button */}
{/* Report Dialog */}
); }