// screens/inbox.jsx — Conversation list // Localized via window.tr() / window.useLang(). Falls back to EN literals // when used standalone in the design canvas (no i18n). // // Mirrors the real app's two-source inbox: DMs *and* post/reel Comments, // switched with the segmented control at the top. const _trI = (k, fb) => (window.tr ? window.tr(k, fb) : fb); const _useLangI = () => (window.useLang ? window.useLang() : 'en'); // Inbox row. `kind` is 'dm' (default) or 'comment'. Comment rows show a // small swatch standing in for the post/reel thumbnail + a "commented on" // subhead so the source is unambiguous at a glance. function InboxRow({ theme, name, handle, preview, time, unread, drafted, lastFromYou, kind = 'dm', postTint }) { const t = useT(theme); const isComment = kind === 'comment'; return (
{/* Leading visual — avatar for DMs, or a tile that pairs the commenter's avatar with a post thumbnail for comments. */} {isComment ? (
{/* Subtle pattern to suggest content without faking imagery */}
{/* small avatar tucked in the corner */}
) : ( )}
{name}
{isComment ? _trI('inbox.commentedOn', 'commented on a post') : `@${handle}`}
{drafted && ( {_trI('inbox.row.drafted', 'Drafted ·')} )} {lastFromYou && !drafted && {_trI('inbox.row.you', 'You: ')}} {preview}
{time}
{drafted ? (
{_trI('inbox.row.replyReady', 'Reply ready')}
) : unread ? (
) : (
)}
); } // Top-level source switcher: All / DMs / Comments. iOS-style filled pill // on a tinted track. The whole control sits on one row, full width. function SourceSegmentedControl({ theme, active = 'all' }) { const t = useT(theme); const items = [ { id: 'all', label: _trI('inbox.source.all', 'All') }, { id: 'dms', label: _trI('inbox.source.dms', 'DMs') }, { id: 'comments', label: _trI('inbox.source.comments', 'Comments') }, ]; return (
{items.map(it => { const sel = it.id === active; return (
{it.label}
); })}
); } function InboxFilters({ theme, active = 'all' }) { const t = useT(theme); const items = [ { id: 'all', label: _trI('inbox.filter.all', 'All'), count: 24 }, { id: 'ai', label: _trI('inbox.filter.ai', 'AI drafted'), count: 6, sparkle: true }, { id: 'mine', label: _trI('inbox.filter.mine', 'Needs me'), count: 4 }, { id: 'closed', label: _trI('inbox.filter.closed', 'Resolved'), count: 132 }, ]; return (
{items.map(it => { const sel = it.id === active; return (
{it.sparkle && } {it.label} {it.count}
); })}
); } // `source` picks which segmented-control tab is active so callers can // screenshot "Comments" view too. Mixed rows in 'all', filtered otherwise. function ConversationList({ theme = 'light', source = 'all' }) { _useLangI(); // subscribe to language changes const t = useT(theme); const dms = [ { kind: 'dm', name: 'Marina Costa', handle: 'marinacostaa', preview: _trI('inbox.preview.marina'), time: '2:18 PM', unread: true, drafted: true }, { kind: 'dm', name: 'Theo Mendez', handle: 'theo.builds', preview: _trI('inbox.preview.theo'), time: '1:52 PM', unread: true, drafted: true }, { kind: 'dm', name: 'Priya Raman', handle: 'priya.r', preview: _trI('inbox.preview.priya'), time: '1:14 PM', lastFromYou: true }, { kind: 'dm', name: 'Júlia Almeida', handle: 'juliaaa', preview: _trI('inbox.preview.julia'), time: '12:40 PM', unread: true }, { kind: 'dm', name: 'Sam Okafor', handle: 'samo.k', preview: _trI('inbox.preview.sam'), time: '11:22 AM', lastFromYou: true }, { kind: 'dm', name: 'Noor Ahmadi', handle: 'noor.studio', preview: _trI('inbox.preview.noor'), time: _trI('inbox.time.yesterday') }, ]; const comments = [ { kind: 'comment', name: 'Lila Romero', handle: 'lilaa', preview: _trI('inbox.comment.lila'), time: '2:05 PM', unread: true, drafted: true, postTint: { bg: '#FFE7E2', fg: '#C25540' } }, { kind: 'comment', name: 'Beto Silva', handle: 'beto.s', preview: _trI('inbox.comment.beto'), time: '1:40 PM', unread: true, postTint: { bg: '#E0E7F2', fg: '#3F5680' } }, { kind: 'comment', name: 'Ana Vidal', handle: 'anavidall', preview: _trI('inbox.comment.ana'), time: '12:08 PM', drafted: true, postTint: { bg: '#EDE3D2', fg: '#7A5520' } }, { kind: 'comment', name: 'Rafa Tavares', handle: 'rafatav', preview: _trI('inbox.comment.rafa'), time: _trI('inbox.time.yesterday'), postTint: { bg: '#F1E1E8', fg: '#8B3F66' } }, ]; // 'all' interleaves to demonstrate that both sources land in one place. // Source-specific tabs show only that type. let rows; if (source === 'dms') rows = dms; else if (source === 'comments') rows = comments; else rows = [ dms[0], comments[0], dms[1], comments[1], dms[2], dms[3], comments[2], dms[4], comments[3], dms[5], ]; return (
{/* Large title header */}
{_trI('inbox.repliesReady', '6 replies ready')}
{_trI('inbox.title', 'Inbox')}
{/* search */}
{_trI('inbox.search', 'Search conversations')}
{/* Source switcher — DMs vs. post/reel Comments. */} {/* Secondary filters (drafted / needs me / resolved) */}
{rows.map((r, i) => )}
{/* Tab bar */}
); } function TabBar({ theme, active }) { const t = useT(theme); const tabs = [ { id: 'inbox', label: _trI('tab.inbox', 'Inbox'), icon: Icons.chat }, { id: 'approvals', label: _trI('tab.approvals', 'Approvals'), icon: Icons.sparkle }, { id: 'rules', label: _trI('tab.rules', 'Rules'), icon: Icons.flow }, { id: 'settings', label: _trI('tab.settings', 'Account'), icon: Icons.settings }, ]; return (
{tabs.map(tab => { const sel = tab.id === active; const I = tab.icon; const col = sel ? t.accent : t.secondary; return (
{tab.label}
); })}
); } window.ConversationList = ConversationList; window.TabBar = TabBar;