import React from 'react' import { avatarSrc } from '../../utils/avatarSrc' import { Share2, Users, Link2, Pencil } from 'lucide-react' import type { CollectionMember, CollectionLink } from '@trek/shared' import type { TranslationFn } from '../../types' import CollectionExportMenu from './CollectionExportMenu' import type { CollectionExportFormat } from './collectionFile' const AV_COLORS = ['#6366f1', '#ec4899', '#14b8a6', '#f97316', '#8b5cf6', '#3b82f6', '#ef4444', '#22c55e'] function initials(name: string): string { return name.trim().split(/\s+/).slice(0, 2).map(w => w[0]?.toUpperCase() ?? '').join('') || '?' } interface CollectionHeroProps { eyebrow: string title: string /** List colour — drives the gradient wash (or tints the cover image). */ color: string coverImage?: string | null description?: string | null links?: CollectionLink[] /** Accepted members (owner first) — shown as an avatar stack when shared. */ members: CollectionMember[] canShare: boolean isOwner: boolean canEdit: boolean onEdit: () => void shareMemberCount: number onShare: () => void /** Absent on the "All saved" pseudo-list, which is a view rather than a list. */ onExport?: (format: CollectionExportFormat) => void exporting?: boolean t: TranslationFn } /** * The page header — a colour-washed (or cover-image) glass hero that gives the * active list an identity: an eyebrow with the sharing state + member avatars, * the big list name, an optional description + link chips, and the Edit, * Export and Share actions top-right. Filtering lives in the toolbar above the * places, not here. * Modelled on the dashboard hero-trip. */ function linkHost(url: string): string { try { return new URL(url).hostname.replace(/^www\./, '') } catch { return url } } export default function CollectionHero({ eyebrow, title, color, coverImage, description, links, members, canShare, isOwner, canEdit, onEdit, shareMemberCount, onShare, onExport, exporting, t, }: CollectionHeroProps): React.ReactElement { const accepted = members.filter(m => m.status === 'accepted' || m.is_owner) const showAvatars = accepted.length > 1 const shown = accepted.slice(0, 5) const extra = accepted.length - shown.length return (
{coverImage ? ( <>
) : (
)}
{eyebrow} {showAvatars && ( {shown.map(m => ( m.avatar ? {m.username} : {initials(m.username)} ))} {extra > 0 && +{extra}} )} {links && links.length > 0 && ( {links.map((l, i) => ( e.stopPropagation()}> {l.label || linkHost(l.url)} ))} )}

{title}

{canEdit && ( )} {onExport && } {canShare && ( )}
{description &&

{description}

}
) }