PR #418 was closed without merging on 28 Sep 2026. Main already has a better version of this page: the filter bar from PR #424 (search, status, enrollment, sort, plus level, category and price filters, all saved in the URL). This work is not on beta or production and will not ship. The screenshots below are kept for reference only.
Status checked 2026-09-28 against GitHub. Index of all reports: https://skillpixel.atlassian.net/wiki/x/A4BJCw
Summary
| Check | Result |
|---|---|
| Table renders one row per course with columns Course, Status, Enrollment, Students, Lessons, Rating, Updated, Actions | Pass |
| Cell text lines up with its column header (measured left edges) | Pass 0px delta on all 8 columns; the page layout centers text, so the table sets text-start on its container |
| Status filter tabs (All 6 · Published 4 · Draft 1 · Archived 1) and result counter | Pass |
| Client-side sort on Course, Students, Lessons, Rating, Updated; direction arrow always to the right of the label | Pass |
| Row actions kebab: Manage, Settings, Archive, Open Enrollment, Duplicate (state-changing items not clicked) | Pass |
| Mobile (390px) falls back to a stacked list, no table overflow | Pass |
| Vietnamese locale: all headers translated, no raw i18n keys | Pass |
| Browser console errors / warnings during the walkthrough | None |
| Course title and meta line were centered in the cell (inherited text-align) | Found → fixed in commits dd6a8f9 → 2ea87e7, screenshots below are after the fix |
| Column widths: metric columns were ~130-143px each for 1-3 character values, spreading the row across the full 1440px | Found → fixed Students/Lessons/Rating pinned to 96px, Updated 128px, Course takes the slack (638px), table fills the container width. Every column is left-aligned, header and cells, and sort icons always trail the label. Screenshots are after the fix. |
| Search by course name or slug, case-insensitive, debounced, combines with the status tabs | Pass |
| Backend change | Scoped new name_or_slug filter + test; the broad search filter is untouched |
Desktop (1440×900)




Sorting, row menu, hover



Status filter
The All/Published/Archived/Draft tabs are gone. Multi-select chips let an instructor combine statuses, and Inactive (revoked B2B licensed copies) is now reachable directly instead of only under All. Default selection is Published; clearing every chip shows all statuses.
| Selection | Rows |
|---|---|
| Published (default) | 4 |
| Published + Draft | 5 |
| Draft only | 1 (Data Science Essentials) |
| Nothing selected | 6 — every status, including Archived |
| Archived + search "advanced" | 0 — Advanced JavaScript is Published, so the two filters correctly intersect |
Requests confirm server-side filtering: ?page=1&size=12&statuses=PUBLISHED&statuses=DRAFT. The statuses filter is applied on both the admin and instructor code paths, each covered by a test.




Search
Matches course name or slug only, case-insensitive, 300ms debounce, resets to page 1, and combines with the status tabs.
| Query | Result |
|---|---|
java | Advanced JavaScript |
JAVA / JaVaScRiPt | Advanced JavaScript (case-insensitive) |
for-beginners | Python for Beginners — slug-only match, the title has spaces |
FOR-BEGINNERS | Python for Beginners |
Draft tab + data | Data Science Essentials |
zzzz | No-results state with a Clear search action |
Why a backend filter: the existing search param also matches summary and description, so java returned Web Development Fundamentals because its description mentions Java. On a management list that reads as a bug, so the instructor endpoint got a strict name-or-slug filter. The broad filter still serves the public catalog.




Mobile (390×844)


Vietnamese locale

Test setup
- Stack:
docker compose up --build --waitin the SP-684 worktree, thenalembic upgrade headandyarn db:seed(fresh DB). - Account: skillpixeldeveloper@gmail.com (ADMIN / INSTRUCTOR), 6 seeded courses. Session injected with a minted Firebase custom token into headless Chromium (Playwright), since the local Chrome profile was not signed in on localhost.
- Screenshots: full-page at device scale 2, saved as WebP q82.
Notes and follow-ups
- Backend course tests pass (128) including a new case for the name-or-slug filter. The regenerated API client also picked up unrelated drift from the merged managed-domain delete change.
- Sorting is per page (client side). Server-side sort, ungraded / pending-review counts, owner column, admin "all instructors" toggle and bulk actions are out of scope for SP-684 and need backend work.
CourseActionCardis no longer rendered anywhere. Left in place for now; delete in a cleanup PR.- Seed data has few courses, so pagination (page size 12) was not exercised here.