feat(dashboard): GuruConnect v2 Support Codes view
Generate, list, and cancel attended-support codes (XXX-XXX-XXX), built on the v2 codes API and existing UI primitives. - Codes table: code in mono, status badge (pending+pulse/connected/ completed/cancelled), bound client/machine, created-by, created (relative + absolute tooltip). Sticky header, skeleton load, actionable empty/error states. - Generate opens a focused reveal modal showing the code large in JetBrains Mono with copy and a read-aloud instruction; the code is announced character-by-character for screen readers. Mint is ref- guarded so it creates exactly one code per open (no StrictMode dupe). - Cancel via confirm dialog (POST /api/codes/:code/cancel), disabled for non-cancellable statuses; invalidates the codes query. List polls 7s. - Shared API client now tolerates non-JSON 200 bodies, so the cancel endpoint's plain-text "Code cancelled" success no longer surfaces as a failure. Error-envelope handling unchanged. Passed Code Review (no blockers after fixes) and local gates (tsc/lint/build green). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -46,3 +46,43 @@ export function consentLabel(state: string): string {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a support-code lifecycle status to a tone. `pending` is the live,
|
||||
* waiting-to-be-redeemed state and gets the same `warn` pulse the
|
||||
* awaiting-consent state uses — it reads as "active, watch this". A redeemed
|
||||
* (`connected`) code is a positive terminal-for-the-tech outcome -> `ok`.
|
||||
* `completed`/`cancelled` are spent and read as muted `neutral`.
|
||||
*/
|
||||
export function codeTone(status: string): StatusTone {
|
||||
switch (status) {
|
||||
case "pending":
|
||||
return "warn";
|
||||
case "connected":
|
||||
return "ok";
|
||||
case "completed":
|
||||
case "cancelled":
|
||||
default:
|
||||
return "neutral";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Human label for a support-code status. Next to `codeTone` so wording and
|
||||
* color never drift. `pending` is phrased as the active wait (the tech is
|
||||
* watching for the end user to redeem it).
|
||||
*/
|
||||
export function codeLabel(status: string): string {
|
||||
switch (status) {
|
||||
case "pending":
|
||||
return "Awaiting redeem";
|
||||
case "connected":
|
||||
return "Redeemed";
|
||||
case "completed":
|
||||
return "Completed";
|
||||
case "cancelled":
|
||||
return "Cancelled";
|
||||
default:
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user