Jobs list and notification centre
Two header controls, never merged (FEEDBACK-B-r1). Jobs opens a 600px list (right edge on the Jobs button) grouped Running · Queued · Needs attention · Done today, each row three lines of the real fields: title + type tag, target · initiator or source · id, then progress with counts, the dispatch / print / send line or the error. Open all jobs is a 960px side sheet with the full error and the failed queue payload. The notification centre is its own 520px bell menu (2-day window, grouped by day, bodies clamp to two lines) with a 760px sheet. Kit v2 after Frank 2026-10-18; fields: phase-2/truth/TRUTH-JOBS.md.
Covers: M01. Exports: JobsButton, JobsDropdown, JobRow, JobActions, JobsSheet, NotificationCentre, NotificationsSheet, JobToast.
Anatomy
The component as it sits in the product: English, compact, real data shapes.
States
13 states, left to right, top to bottom. A mock poll never finishes, so each state is drawn on purpose.
Density
The phone shell is always comfortable (POWERUPS #15): 44px tap targets, 16px inputs. Compact exists on desktop only; see the desktop page.
English · 中文
Staff pick en or cn (T001 Q25). Labels arrive localised; CJK falls back to PingFang SC / Noto Sans SC.
Long string · permission denied
Long titles, targets and a full exception (PL-063), and the support role: own queue batches + print / agent jobs, no Failed jobs link (TRUTH-JOBS §0 #5).
Contract
The @rj/admin-kit API for this family. Mirrored in CONTRACT.md.
- Export
JobsButton·@rj/admin-kit- Props
counts{running, failed} fromGET /admin/nav-badges(running_job_batchesown ·failed_jobsifmanage failed jobs) + print / agent in-flight ·pollMs3000 while open, 15000 closed- States
- idle · running · failed · stale
- shadcn / Radix
- Popover (align end, sideOffset 6)
- Package underneath
- @tanstack/react-query refetchInterval
- Accessibility
- button names the counts (“3 running, 3 need attention”); Esc returns focus
- Phone variant
- app-bar icon → full-screen sheet
- Export
JobsDropdown·@rj/admin-kit- Props
widthvar(--dropdown-w-lg) 600px, clampedmin(600px, 100vw − 32px), right edge = button right edge ·maxHeightvar(--dropdown-max-h)min(78vh, 720px), body scrolls, header + tabs + footer fixed ·groupBystate (Running · Queued · Needs attention · Done today) ·filterstate tab + type select (Queue batch · Cloud print · Cloud agent type · Fabric photos) ·onOpenAll- States
- default · many (internal scroll, sticky group heads) · attention · partial · stale · empty · own-only (role)
- shadcn / Radix
- Popover + ScrollArea + Tabs + Select
- API operations
- admin.notifications.batches (own) · admin.dashboard.job-batches?shape=v2 · admin.orders.print-jobs.index?status=in_flight|failed · admin.orders.fabric-jobs.index · admin.pricing.exports.show · print-studio photo_batch_status
- Permission
- own batches always; print + agent jobs need
view orders; the full batch list needsjob_batches; Failed jobs link needsmanage failed jobs
- Export
JobRow·@rj/admin-kit- Props
title·typeTag(batch name label · printjob_type· CloudJobtype_label) ·target(order + retailer · supplier · WeChat target · file) ·initiator(batches: user) orsource(cloud · manual · reprint) ·shortId·progress{processed, total, failed} ·statusLine(dispatch · print / send) ·elapsed·eta·error(2-line clamp, More expands in place) ·messagePreview·actions- Variants
- 3 lines: title + type tag + time · one meta line · progress / status / error
- States
- queued · running % · partial (green + red bar) · failed · done
- Accessibility
- row is a listitem; error is a native details/summary; actions are buttons with labels
- Phone variant
- same row, full width
- Export
JobActions·@rj/admin-kit- Props
- only real ones:
Download(pricing export file · orders export link) ·Open PDF(signed, 15 min) ·Reprint label(can_dhl_reprint) ·Page-range reprint(can_kanban_reprint) ·Retry send(WeChat send, admin) ·Results CSV(photo batch) ·Details - States
- no Cancel and no generic Retry: no REST route cancels a batch or retries a print / Cloud Order row (TRUTH-JOBS §1–§3)
- Export
JobsSheet·@rj/admin-kit- Props
widthvar(--sheet-w-xl) 960px, clamped to 100vw − 48px · list (360px) + detail ·jobId- Variants
- detail = every field of the row + full
last_error+ the matching failed queue job (exception + payload inJsonViewer, raw for super-admin, redacted otherwise) - shadcn / Radix
- Sheet (side right)
- API operations
- admin.failed-jobs.show · admin.orders.print-jobs.pdf-url · admin.orders.print-jobs.index?highlight
- Phone variant
- full-screen page
- Export
NotificationCentre·@rj/admin-kit- Props
widthvar(--dropdown-w-md) 520px, clamped, right edge = bell right edge ·maxHeightvar(--dropdown-max-h) ·items(id, type, message, link, links[], read, created_at) ·groupByday (2-day window) ·filterAll · Unread + type- States
- unread · read · hover (mark read · delete) · long body (clamp 2 lines, More) · empty · error
- shadcn / Radix
- Popover + ScrollArea
- Accessibility
- bell names the unread count
- API operations
- admin.notifications.index · .unread-count · .read · .unread · .toggle · .read-all · .unread-all · .destroy · .destroy-all · .destroy-old
- Phone variant
- full-screen sheet
- Export
NotificationsSheet·@rj/admin-kit- Props
widthvar(--sheet-w-lg) 760px · type chips (All · Failures · Tickets · Orders · Exports · Shipping) · overflow: mark all unread · delete read · delete older than 2 days- shadcn / Radix
- Sheet (side right)
- Export
JobToast·@rj/admin-kit- Props
job- States
- success with Download · failure with Details
- shadcn / Radix
- Sonner
- Package underneath
- sonner