feat(intake): review, edit and publish drafts from the admin (#225)

The screen that makes the intake pipeline usable. Until now a draft existed only in item_drafts and nothing rendered it, so a successful draft and a failed one looked identical from the admin — the item shows its placeholder submission-timestamp name either way, and telling them apart needed SQL.

The price carries the weight the schema no longer does. It is labelled with where the number came from, anything not set by a person is marked unconfirmed, and publishing at an unconfirmed price asks first rather than reporting afterwards. Editing the field is what confirms it, so opening the card and leaving the price alone is not recorded as approval — the same rule the server applies, which this only has to agree with.

Discard is offered rather than delete, and a discarded card offers Restore in its place.

The e2e page object's AdminTab union is extended alongside the tab itself. It is a closed union, so admin.open('Review queue') would not type-check without it — and the tab strip and that union have to be changed together or the next spec to use it fails to compile.

Both frontend lint and build clean, still at zero warnings.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-01 14:19:49 -05:00
co-authored by Claude Opus 5
parent d8a7588685
commit 2b06538ef9
4 changed files with 272 additions and 1 deletions
+2
View File
@@ -34,6 +34,7 @@ import Settings from './Settings';
import Categories from './Categories';
import Tags from './Tags';
import UploadLinks from './UploadLinks';
import DraftQueue from './DraftQueue';
import BuildStamp from './BuildStamp';
import CategoryTreeSelect from './CategoryTreeSelect';
import ItemCard from '../components/ItemCard';
@@ -393,6 +394,7 @@ export default function Admin() {
{ key: 'categories', label: 'Categories', children: <Categories /> },
{ key: 'tags', label: 'Tags', children: <Tags /> },
{ key: 'upload-links', label: 'Upload links', children: <UploadLinks /> },
{ key: 'review-queue', label: 'Review queue', children: <DraftQueue /> },
{ key: 'customers', label: 'Customers', children: <Customers /> },
{ key: 'emails', label: 'Emails', children: <Emails /> },
{ key: 'settings', label: 'Settings', children: <Settings /> }