// Share view — read-only client gallery (used both for internal preview and public share) // Responsive column count hook function useColumns() { const [cols, setCols] = React.useState(() => { const w = window.innerWidth; return w < 540 ? 1 : w < 800 ? 2 : w < 1100 ? 3 : 4; }); React.useEffect(() => { const fn = () => { const w = window.innerWidth; setCols(w < 540 ? 1 : w < 800 ? 2 : w < 1100 ? 3 : 4); }; window.addEventListener('resize', fn); return () => window.removeEventListener('resize', fn); }, []); return cols; } // Pin icon (thumbtack) function IconPin({ size = 14, filled = false }) { return ( ); } const MAX_PINS = 10; function ShareView({ files, share, onOpen, onClose, onFeedback, feedback, onApprove, approvals, token, pins, onPin }) { const [photoErr, setPhotoErr] = React.useState(false); const [logoErr, setLogoErr] = React.useState(false); const [noteTarget, setNoteTarget] = React.useState(null); // filename for note modal const [noteText, setNoteText] = React.useState(''); const [showMoodBoard, setShowMoodBoard] = React.useState(false); const cols = useColumns(); const hasLogo = share.has_logo && !logoErr; const studioName = share.studio_name || ''; const tagline = share.tagline || ''; const photographer = share.photographer || ''; const likedCount = feedback ? feedback.size : 0; const approvedCount = approvals ? Object.values(approvals).filter(a => a.status === 'approved').length : 0; const changesCount = approvals ? Object.values(approvals).filter(a => a.status === 'changes').length : 0; const pinCount = pins ? pins.size : 0; const atPinLimit = pinCount >= MAX_PINS; const submitNote = () => { if (onApprove && noteTarget) { onApprove(noteTarget, 'changes', noteText.trim()); } setNoteTarget(null); setNoteText(''); }; return (