import { useState } from 'react'; import { Link } from 'react-router-dom'; import { Card, CardContent, CardFooter, CardHeader } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; import { Skeleton } from '@/components/ui/skeleton'; import { Button } from '@/components/ui/button'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { MapPin, Store, Bookmark, MoreVertical, Flag, ShieldCheck } from 'lucide-react'; import { useAuthor } from '@/hooks/useAuthor'; import { useCurrentUser } from '@/hooks/useCurrentUser'; import { useVenuesWithPasses } from '@/hooks/useRiderCard'; import type { SpotCommunityMini } from '@/hooks/useBatchSpotCommunityScores'; import { genUserName } from '@/lib/genUserName'; import { ZapButton } from '@/components/ZapButton'; import { TrustBadge } from '@/components/TrustBadge'; import { OfficialBadge } from '@/components/OfficialBadge'; import { AddToCollectionDialog } from '@/components/AddToCollectionDialog'; import { ReportDialog } from '@/components/ReportDialog'; import { SpotStatusBadge } from '@/components/SpotStatusBadge'; import type { SkateSpot } from '@/lib/types'; import { ACCESS_TYPE_INFO, SHELTER_INFO, SKATE_SHOP_KIND } from '@/lib/types'; import { spotTypeLabel } from '@/lib/spotTypeLabel'; import { ACCESS_TYPE_KEYS, SHELTER_SHORT_KEYS } from '@/lib/labelKeys'; import type { AggregatedSpotStatus } from '@/hooks/useSpotStatus'; import { useTranslation } from '@/contexts/language'; import { cn } from '@/lib/utils'; interface SpotCardProps { spot: SkateSpot; /** Optional community status, passed in batched from the parent list/map. */ status?: AggregatedSpotStatus | null; /** Optional community confidence, passed in batched from the parent list/map. */ community?: SpotCommunityMini; } export function SpotCard({ spot, status, community }: SpotCardProps) { const { t } = useTranslation(); const author = useAuthor(spot.pubkey); const { user } = useCurrentUser(); const metadata = author.data?.metadata; const displayName = metadata?.name ?? genUserName(spot.pubkey); const [showCollectionDialog, setShowCollectionDialog] = useState(false); const [showReportDialog, setShowReportDialog] = useState(false); // Determine if this is a shop or a spot const isShop = spot.types.includes('shop'); const isOwner = user?.pubkey === spot.pubkey; const route = isShop ? `/shop/${spot.pubkey}/${spot.identifier}` : `/spot/${spot.pubkey}/${spot.identifier}`; // Shops that actually issue access passes get a badge (one shared, cached query). const { data: passIndex } = useVenuesWithPasses(); const hasPasses = isShop && !!passIndex?.coords.has(`${SKATE_SHOP_KIND}:${spot.pubkey}:${spot.identifier}`); // Dim spots the community has reported as gone/demolished. const isGone = status?.status === 'gone'; return ( {/* Image */}
{spot.images[0] ? ( {spot.title} ) : (
{isShop ? ( ) : ( )}
)} {/* Community status badge (non-shop) */} {!isShop && status?.status && (
)} {/* Shop badge or Type badges overlay */}
{isShop ? ( <> 🏪 {t('mapUi.skateShop')} {hasPasses && ( 🎟️ {t('venueAccess.badge')} )} ) : ( <> {spot.accessType && ( {ACCESS_TYPE_INFO[spot.accessType].emoji} {(ACCESS_TYPE_KEYS[spot.accessType] ? t(ACCESS_TYPE_KEYS[spot.accessType]) : ACCESS_TYPE_INFO[spot.accessType].label).split(' - ')[0]} )} {spot.shelter && spot.shelter !== 'outdoor' && SHELTER_INFO[spot.shelter] && ( {SHELTER_INFO[spot.shelter].emoji} {SHELTER_SHORT_KEYS[spot.shelter] ? t(SHELTER_SHORT_KEYS[spot.shelter]) : SHELTER_INFO[spot.shelter].short} )} {spot.types.length > 0 && (
{spot.types.slice(0, 2).map((type) => ( {spotTypeLabel(t, type)} ))}
)} )}

{spot.title}

{spot.location && (

{isShop ? ( ) : ( )} {spot.location}

)}
{spot.description && (

{spot.description}

)}
{displayName.slice(0, 2).toUpperCase()} {displayName} {/* Trust Badge */} {/* Official badge — only shown for verified founder */} {/* Community confidence — batched in by the parent list/map. */} {community?.level === 'community' && ( {t('spotUi.communityChip')} )} {community?.level === 'seen' && ( {t('spotUi.seenChip')} )}
e.preventDefault()}> {user && !isShop && ( )} {/* More options menu */} {!isOwner && ( { e.preventDefault(); e.stopPropagation(); setShowReportDialog(true); }} className="text-red-500 focus:text-red-500" > {t('mapUi.report')} )}
{/* Collection Dialog */} {!isShop && ( )} {/* Report Dialog */} ); } export function SpotCardSkeleton() { return (
); }