import { Link } from 'react-router-dom'; import { Users } from 'lucide-react'; import { nip19 } from 'nostr-tools'; import { CommunityModerationOverlay } from '@/components/CommunityModerationMenu'; import { Card } from '@/components/ui/card'; import { Skeleton } from '@/components/ui/skeleton'; import { useAuthor } from '@/hooks/useAuthor'; import { genUserName } from '@/lib/genUserName'; import { sanitizeUrl } from '@/lib/sanitizeUrl'; import { cn } from '@/lib/utils'; import { COMMUNITY_DEFINITION_KIND, type ParsedCommunity, } from '@/lib/communityUtils'; interface CommunityMiniCardProps { community: ParsedCommunity; className?: string; } /** * Compact, fixed-width community card for the Discover page's "Find your * people" shelf. Whole card is a `` to the community's naddr-based * route. Visual hierarchy: * * - 16:9 banner image (or warm gradient + Users icon when missing), * - bold community name, * - one-line description, * - founder avatar + display name in a muted row. * * Kept narrow enough to fit ~4 cards across a desktop content column. * * Moderators (Team Soapbox pack members) see a kebab menu overlaid on the * banner exposing the Feature / Hide actions plus a Hidden badge when the * org is currently hidden. Non-moderators see no overlay — the whole * moderation pipeline (including the heavy `useOrganizationModeration` * query) is bypassed for them so grids of dozens of cards don't fan out * a per-card cache subscription on every viewer. */ export function CommunityMiniCard({ community, className }: CommunityMiniCardProps) { const founder = useAuthor(community.founderPubkey); const banner = sanitizeUrl(community.image); const founderName = founder.data?.metadata?.display_name || founder.data?.metadata?.name || genUserName(community.founderPubkey); const founderAvatar = sanitizeUrl(founder.data?.metadata?.picture); const naddr = nip19.naddrEncode({ kind: COMMUNITY_DEFINITION_KIND, pubkey: community.founderPubkey, identifier: community.dTag, }); return (
{banner ? ( ) : (
)} {/* Moderator overlay (Hidden badge + kebab). Renders `null` for non-moderators, which is why this component owns the `useOrganizationModeration` subscription rather than the card — keeps non-mod grids free of the heavy label query. */}

{community.name}

{community.description && (

{community.description}

)}
{founderAvatar ? ( ) : (
)} by {founderName}
); } /** Skeleton placeholder matching `CommunityMiniCard` dimensions. */ export function CommunityMiniCardSkeleton({ className }: { className?: string }) { return (
); }