{data.entry?.title || data.title.replace(/^Propose:\s*/, '')}
Decline proposal
Proposed entry
{/* #26: the optional ground-truth use case the proposer supplied. */}Intended use case
{data.proposed_use_case ? :Left blank by the proposer.
}// ProposalView.jsx — §9.3 pending-idea view. // // Renders the proposed entry's body and frontmatter (read-only) with a // status banner ("Pending idea — awaiting review"). The header strip // carries Merge / Decline / Withdraw per the viewer's affordances. The // decline two-step composer-then-preview from §9.3 ships in Slice 1 // as a single-step required-comment input; the preview-confirm ceremony // can land with the rest of §9.3's UX polish in the §19.2 "pending-idea // view's interaction design (remainder)" topic. import { useEffect, useState } from 'react' import { useParams, useNavigate } from 'react-router-dom' import { renderMarkdown } from '../lib/sanitizeHtml' import { getProposal, mergeProposal, declineProposal, withdrawProposal } from '../api' import { entryPath, useProjectId } from '../lib/entryPaths' export default function ProposalView({ viewer, onChange }) { const { prNumber } = useParams() const [data, setData] = useState(null) const [error, setError] = useState(null) const [acting, setActing] = useState(false) const [declineOpen, setDeclineOpen] = useState(false) const [declineComment, setDeclineComment] = useState('') const navigate = useNavigate() const pid = useProjectId() function refresh() { setData(null); setError(null) getProposal(prNumber).then(setData).catch(err => setError(err.message)) } useEffect(refresh, [prNumber]) if (error) return
Error: {error}
Left blank by the proposer.
}