/** * ModerationFirstPostTab - First-post approval queue with batch actions. * Shows account age, cross-community activity, and ban warnings. * @see specs/prd-web.md Section M11 */ 'use client' import { useState } from 'react' import { ShieldCheck, Clock, Prohibit } from '@phosphor-icons/react' import { formatDate } from '@/lib/format' import type { FirstPostQueueItem } from '@/lib/api/types' interface ModerationFirstPostTabProps { items: FirstPostQueueItem[] onResolve: (id: string, action: 'approved' | 'rejected') => void onBatchResolve: (ids: string[], action: 'approved' | 'rejected') => void } export function ModerationFirstPostTab({ items, onResolve, onBatchResolve, }: ModerationFirstPostTabProps) { const [selectedIds, setSelectedIds] = useState>(new Set()) const allSelected = items.length > 0 && selectedIds.size === items.length const toggleSelectAll = () => { if (allSelected) { setSelectedIds(new Set()) } else { setSelectedIds(new Set(items.map((item) => item.id))) } } const toggleItem = (id: string) => { setSelectedIds((prev) => { const next = new Set(prev) if (next.has(id)) { next.delete(id) } else { next.add(id) } return next }) } const handleBatchAction = (action: 'approved' | 'rejected') => { const ids = Array.from(selectedIds) onBatchResolve(ids, action) setSelectedIds(new Set()) } return (
{items.length > 0 && (
{selectedIds.size > 0 && (
)}
)} {items.map((item) => (
toggleItem(item.id)} className="mt-1 rounded border-border" aria-label={`Select post by ${item.authorHandle}`} />

{item.authorHandle}

{item.crossCommunityCount > 0 && ( )} {item.bannedFromOtherCommunities > 0 && ( )}
{item.title && (

{item.title}

)}

{item.content}

{item.contentType === 'topic' ? 'Topic' : 'Reply'} ·{' '} {formatDate(item.createdAt)}

))} {items.length === 0 && (

No posts awaiting approval.

)}
) }