Yew's Renderer::new() renders into <body>, not #app, so the flex
column layout on #app had no effect. Move display:flex and
flex-direction:column to body so .main-content{flex:1} correctly
pushes .site-footer to the bottom of the viewport.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove captcha-gated disabled state on report submit button — Turnstile
does not fire a DOM input event so captcha_solved never became true; rate
limiting is handled at the WAF layer so the gate was incorrect
- Token is still read from the hidden Turnstile input at submit time if present
- Add explanatory hint below "Enter Auth Code" heading in AuthModal explaining
the code was provided or generated when the quote was created
- Add .auth-modal__hint CSS class for the hint text
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a Moderation tab to the admin page (visible after unlock) showing a
paginated list of reported quotes. Clicking a row opens a detail modal with
the full quote, all individual reports, and action buttons to delete the
quote, hide it, or dismiss the reports.
- api.rs: add ReportSummary, ReportListResponse, ReportRow, QuoteReports types
and five admin_* async functions for the reports endpoints
- components/moderation_tab.rs: new ModerationTab function_component with
paginated list, row-click loading state, and an inline detail modal
- components/mod.rs: expose moderation_tab module
- pages/admin.rs: introduce AdminTab enum and tab bar; wrap existing settings
content in the Settings tab; add Moderation tab rendering ModerationTab
- style.css: add styles for admin tabs, moderation list table, and detail modal
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add HideAuth action variant to the Action enum
- Show yellow badge when quote.hidden is true
- Add Hide/Make Public toggle button in the actions bar
- Reuse AuthModal for the hide/unhide auth prompt
- Call POST /api/quotes/:id with { hidden: !current } and X-Auth-Code
- Update quote state on success; re-prompt on 403
- Add .page-quote__hidden-badge CSS styles
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a Report button to /quotes/:id that opens a modal containing:
- Optional reason textarea (max 256 chars) with live character counter
- Cloudflare Turnstile CAPTCHA widget (always-passes test sitekey as const)
- Submit button disabled until CAPTCHA token is non-empty
- Cancel button
On submit POSTs { reason?, captcha_token } to POST /api/quotes/:id/report.
Shows a success banner on 201 or an error via ErrorDisplay on failure.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add a toggle button ("Filters ▼ / ▲") above the quote list on the
browse page. Filter controls are hidden by default and expand when
clicked. Each filter (Author, Tag, Date range) is on its own labelled
row with consistent styling. Existing API query logic is unchanged.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Check GET /api/status on mount; if submissions_locked is true, hide the
form and show a .submissions-closed-banner instead. Fail-open: on error,
treat as unlocked and display the form normally.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>