Skip to content

[Feedback] /admin/feedback triage page (gated by requireRole admin) #178

Description

@ProfessorPolymorphic

What to build

An admin-only triage view for incoming user feedback. Lists rows from `product_feedback`, lets an admin filter by status, mark items `in-progress` / `done`, and paste a GitHub issue URL once a report has been exported to the engineering tracker.

End-to-end behavior: an admin signs in, navigates to `/admin/feedback`, sees newest `new` rows first, can change status inline and attach a `github_url`. A non-admin (editor / viewer / unauthenticated) hitting the route is rejected by `requireRole("admin")`.

Files

File Change
`app/admin/feedback/page.tsx` (new) Server component. Calls `requireRole("admin")` from `lib/auth.ts`. Reads `listFeedback({ status })` from `lib/feedback-db.ts`. Renders a table grouped by status with Bug/Idea badges, route + browser context expandable, contact email shown if present.
`app/admin/feedback/actions.ts` (new) Server actions: `markFeedbackStatus(id, status)` and `attachFeedbackGithubUrl(id, url)`. Both re-check `requireRole("admin")` server-side (don't trust the page gate alone).
Inline UI Status select (`new` / `in-progress` / `done` / `wontfix`) + a small text input for GitHub URL. Native HTML + Tailwind, brand tokens, no component library.

UX notes

  • Default filter shows `new` rows; tabs/segmented control to switch to `in-progress` / `done` / `all`.
  • Display the auto-captured context (route, environment, host, browser, viewport) in a collapsed `
    Details` block — not the primary read.
  • `updated_at` updates automatically via the trigger / column default; the action only writes `status` or `github_url`.

Acceptance criteria

  • `/admin/feedback` is reachable only with role=admin; non-admins get a 403 (or are redirected) — verified by direct URL hit while authenticated as editor and viewer
  • Page lists `new` feedback rows by default, newest first
  • Filter switches between `new` / `in-progress` / `done` / `all`
  • Admin can change a row's status inline; server action re-checks role and updates the row
  • Admin can attach a `github_url` inline; URL format validated (must start with `https://github.com/\`)
  • Bug vs Idea is visually distinct (badge / chip)
  • Auto-captured context (route, host, browser, viewport) is in a collapsed `
    Details` block, not the primary read
  • Brand tokens only (rule 6); no component library (rule 8); page is server-rendered, only the form controls are client (rule 7)
  • `npm run build` and `npm run lint` clean

Blocked by

  • #176 — needs `requireRole("admin")` from `lib/auth.ts`
  • #177 — needs the `product_feedback` table and `lib/feedback-db.ts`

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpriority-mediumMedium prioritytechnicalTechnical improvements for agentic development

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions