Files
descrybe/docs/admin-roles-support/01-ux-research.md
T
greeneclipse 8580c996c3 Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
2026-08-09 22:47:43 +02:00

224 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# UX research: Admin, roles/plans, support desk
**Product:** Descrybe — product feed / AI catalog SaaS (Go API + SvelteKit admin).
**Scope:** Clean ops panels, plan/role permission matrices, support queue with assignment + CSAT.
**Date:** 2026-08-05
**Method:** Web research (admin tables, RBAC/entitlements, support SLA/CSAT) + codehelper skim of existing admin UI.
---
## Existing Descrybe surface (baseline)
| Area | What exists today | Paths / symbols |
| --- | --- | --- |
| Admin chrome | Fixed left nav, dark shell (`.dark`), brand “Descrybe” + Admin pill | `AdminNav.svelte` |
| Page frame | `PageShell` → title + description + actions; `max-w-7xl` | `PageShell.svelte` |
| Tables | `TableShell` = bordered `bg-card` + scroll; row hover `muted/40` | `TableShell.svelte` |
| Support queue | Status chip filters, search, Badge status map, click-through rows | `/admin/support`, `listAdminSupportTickets` |
| Ticket model | status, priority, category, `assignee_admin_user_id`, message thread | `support/admin-api.ts` |
| Plan features | Package select + section filter + search; checkbox matrix; package Badges | `PlanPermissionsPanel.svelte` |
| Tokens | Majorelle primary, russian-violet ink, slate-friendly cards; semantic Badge variants | `layout.css` (`--primary` 247°, success/warning Badges) |
**Implication:** Do not invent a second admin visual system. Extend `PageShell` + `Card` + `TableShell` + `Badge` + filter chips already used on Support. Prefer semantic tokens (`border-border`, `bg-primary/15`, `text-muted-foreground`) over one-off `slate-*` where the rest of admin already uses tokens (Support does; PlanPermissions still hardcodes some slate).
---
## A) Clean admin / ops panels
### Patterns to apply
1. **Job-first hierarchy (3 levels)**
- L1: entity/queue purpose + critical alerts + primary actions (Refresh, Assign, Resolve).
- L2: filters + operational table.
- L3: audit / history / advanced settings on demand (drawer or sub-route).
Source pattern: SaaS admin hierarchy guides (Taqwah, PyColors).
2. **Density as a tool, not a vibe**
- Ops tables: comfortable default (~4048px rows); optional compact for power users later.
- Cap overview KPI cards at **35** (admin overview already leans summary + tool grid — keep that restraint).
- Sticky table headers; freeze identity column (subject / company name) when horizontal scroll appears.
3. **Queue-shaped tables**
Useful traits: strong status, workflow filters, clear row entry, stable column order.
Weak traits: ambiguous state, decorative charts instead of work, actions buried in kebab menus for primary work.
4. **Filter UX**
- Removable filter chips + result count (“12 of 240 · status open · priority high”).
- Global search + a few workflow filters (status / assignee / plan tier / SLA risk) — not a filter drawer per column on day one.
- Persist key filters in URL (`?status=open`) — Support already does this; extend to assignee/SLA.
5. **Layout zones for ticket / user detail**
Entity header (state + plan + SLA) → primary thread/table → side sheet for assignment / meta → audit strip.
Prefer split pane or side sheet over full-page form for assignment so the queue context stays visible.
### DO / DON'T — avoiding the “ugly admin” look (Descrybe-native)
| DO | DON'T |
| --- | --- |
| Reuse `PageShell`, `Card`, `TableShell`, Lucide icons at `h-4`/`h-5` | New dashboard kits, glassmorphism, neon charts, multi-shadow cards |
| Use majorelle **sparingly**: active nav, selected filter, primary CTA | Purple-to-indigo hero gradients, glow rings, “AI sparkle” chrome on every control |
| Semantic status via `Badge` (`warning`/`success`/`secondary`) | Rainbow row backgrounds or emoji status columns |
| One composition per page: title → filters → table | KPI strip + chart wall + three card grids above every queue |
| Tabular nums + truncate with tooltip for IDs/emails | Wrapping every cell; monospace walls of UUID |
| Destructive actions visually separate + confirm | Red “Delete” next to “Reply” without consequence copy |
| Match admin dark shell tokens from `layout.css` | Flat gray Bootstrap admin or cream/serif “editorial” admin |
Brand note: Descrybes primary *is* majorelle blue. “Not purple AI slop” means **dont decorate** — use brand as selection/affordance, not as atmosphere.
---
## B) Plan / role permission matrices
### Model (separate two axes)
Research consensus (Stripe-style entitlements + B2B RBAC UX):
| Axis | Question | Descrybe mapping |
| --- | --- | --- |
| **Role** | What can this *person* do? | Platform admin vs company admin vs member; future scoped ops roles |
| **Plan / entitlement** | What has this *account* bought? | Plans + `PlanPermissionsPanel` feature catalog + feature gates |
| **Scope** | Where does it apply? | Company / catalog / feed — keep visible if multi-tenant ops act across companies |
| **Lifecycle** | Trial, past_due, suspended, custom deal | Already surfaced in billing helpers (`billing-display`, package Badges) |
**Never blur** “member can export” (role) with “Advanced export is on Enterprise” (plan). UI should explain *which* layer blocked an action.
### Matrix UX patterns
1. **Read matrix for audit; edit via focused builder**
Full checkbox grids are good for platform ops (current Plan features panel). For end-customer role assignment, prefer named roles + plain-language summary, not a wall of toggles.
2. **Group by task domain**
Sections already in `PLAN_FEATURE_SECTIONS` — keep section headers, global gate Badge (“Globally disabled”), and search. Add “affected companies / seats” count before bulk enable/disable.
3. **Honest gating states**
Hide vs disable vs upgrade CTA vs “ask admin” — pick per feature. Support/billing should show *why* (plan vs role vs lifecycle).
4. **Role chips**
Compact chips: plan name, `is_custom`, trial, platform-admin. Use `Badge variant="outline"` for ladder defaults and `secondary` for custom deals (already started in PlanPermissionsPanel). Avoid inventing 8 near-identical admin role names.
5. **Exceptions expire**
Support overrides and custom deals need owner, reason, expiry, audit — otherwise Support becomes the policy engine.
### DO / DON'T — permissions UI
| DO | DON'T |
| --- | --- |
| Label packages in customer language (Free / Pro / Enterprise / Custom deal) | Internal flags as the only label (`is_custom` alone) |
| Show count enabled / total; section + search filters | Unfiltered 80-row checkbox dump with no scan path |
| Confirm bulk “Disable all” with blast radius | Silent global section flips |
| Log who changed plan features | Toggles with no success/error feedback (panel already alerts — keep it) |
| Separate “AI roles” (provider keys) from user RBAC | Mixing `admin-ai-roles` (LLM slots) into the human permission matrix naming |
---
## C) Support desk: assignment, queues, SLA, CSAT
### Current hooks
- Queue: status filters + search; columns subject/status/priority/company/requester/updated.
- API update already allows `assignee_admin_user_id` / `clear_assignee`.
- Priorities: `low | normal | high`. Categories: `billing | bug | account | other`.
- Gap vs research: no SLA timers, no assignee column/filter, no CSAT fields, no “my queue” / unassigned views.
### Ticket queue patterns
1. **Ownership model**
Default for B2B SaaS: route by **product area / category** + **customer plan tier**, then assign.
Assignment modes to support:
- Unassigned pool → claim
- Round-robin / load-balance for general
- Skill / category for billing vs bug
- VIP / Enterprise bypass for high impact
2. **Queue views (filters, not separate apps)**
- All open · Unassigned · Mine · SLA at risk · Waiting on customer (`pending`)
Keep chip style from Support page (`border-primary bg-primary/15` when active).
3. **Row information hierarchy**
Primary: subject + company. Secondary: status Badge, priority, assignee avatar/initials, last message age. Tertiary: category under subject (already). Add SLA countdown only when defined.
4. **SLA as timers + events**
- Tier by priority (and optionally plan): first response + resolution targets.
- States: on track → **at risk** (e.g. 80% elapsed) → breached.
- Pause when waiting on customer.
- UI: subtle text for on-track; `Badge variant="warning"` at risk; `destructive` only for breach — not red rows.
5. **Assignment UX**
- Inline assignee control on detail header; optional bulk assign from queue.
- Show workload (open count) in assignee picker.
- Reassignment reason for misroutes (feeds quality metrics).
### CSAT patterns
1. **One rating question + optional comment** (15 or Good/Neutral/Bad). Extra questions kill response rate.
2. **Ask in-thread or embed in resolution email** — avoid “click this survey link” as primary path.
3. **Timing:** immediate on resolve for highest response; optional short delay (14h) if you need confirmation the fix stuck. Cap frequency (~1 survey / customer / 1430 days).
4. **Closed loop:** rating ≤2 → auto follow-up task for lead/manager within 24h; do not only score the agent.
5. **Ops dashboard:** weekly CSAT trend, by category and by assignee — not a vanity gauge on every ticket list row (show star only when rated).
### DO / DON'T — support UX
| DO | DON'T |
| --- | --- |
| Explicit assignee + unassigned queue | Tickets that only change status with no owner |
| Concrete priority definitions (impact × urgency) | “High” used for every billing question |
| Pair speed (FRT/SLA) with CSAT / reopen rate | Optimize SLA alone until quality collapses |
| Internal notes distinct from customer replies | Agents accidentally sending notes to customers |
| Macros that sound human; show company plan on ticket | Generic AI purple assist panel auto-replying without gate (`support` AI role stays off until product gate) |
---
## Concrete patterns checklist (build against this)
| Pattern | Apply on |
| --- | --- |
| Density | Support + Users + Billing tables via shared table cell padding |
| Hierarchy | PageShell title → chip filters → TableShell → detail |
| Tables | Sticky header; identity first; Badge for state; truncate + title |
| Filters | Chips + URL params + count; search left-icon Input |
| Role / plan chips | Badge outline vs secondary; plan name humanized |
| Ticket queues | Unassigned / Mine / At risk views; assignee column |
| SLA | Timer + at-risk Badge; pause on `pending` |
| Ratings | Post-resolve 15; optional comment; closed-loop on lows |
---
## Top 8 recommendations
1. **Standardize ops pages on one skeleton**`PageShell` + filter chip bar + `TableShell` + empty/forbidden/unavailable states (copy Support; retire ad-hoc slate-only cards where tokens suffice).
2. **Ship assignee-centric queues next** — column + filter + “Unassigned / Mine”; wire existing `assignee_admin_user_id` before adding SLA or CSAT chrome.
3. **Keep plan entitlements and human roles as two panels** — extend `PlanPermissionsPanel` for packages; separate company/platform RBAC; never merge with `admin-ai-roles` LLM slots in the same matrix.
4. **Permission matrix = grouped sections + search + blast-radius confirms** — preserve section gates and package Badges; add “who is affected” on enable/disable all.
5. **Add SLA as a thin operational layer** — first-response + resolution by priority (optionally × plan tier); show at-risk/breach Badges; pause on `pending`.
6. **CSAT: one click in the resolution path** — 15 (or 3-point) in ticket UI / resolution email; optional comment on low scores only; frequency cap; manager follow-up automation for ≤2.
7. **Visual discipline = brand as signal, not decoration** — majorelle for selection/CTA only; semantic Badges for state; no gradient dashboards, glow, or decorative KPI walls.
8. **Measure ops health with a short metric set** — FRT, SLA at-risk/breach, misroute/reassign rate, reopen rate, CSAT weekly by category — surface on Support overview, not as chart spam on the queue.
---
## Sources (web)
- [SaaS Admin Panel Design — hierarchy & density](https://taqwah.agency/blog/saas-admin-panel-design-guide)
- [Admin tables & queues](https://pycolors.io/guides/saas-admin-panels)
- [Data table density, chips, sticky headers](https://www.setproduct.com/blog/data-table-ui-design)
- [Permission matrix as product surface (roles vs entitlements)](https://0r8it.com/blog/the-permission-matrix-is-a-product-surface)
- [Multi-role B2B SaaS — role / plan / scope](https://dardesign.io/blog/multi-role-b2b-saas-ux-roles-permissions-flows)
- [Support triage, routing, SLA events](https://thinkbot.agency/blog/support-ticket-automation-playbook-triage-routing-slas-knowledge-qa)
- [Queue strategy & SLA milestones](https://www.supportbench.com/support-queue-strategy-triage-routing-ownership/)
- [CSAT timing, one-question surveys, closed loop](https://supp.support/blog/how-to-set-up-csat-surveys)
---
## Open follow-ups (out of scope for this note)
- Exact SLA targets (minutes/hours) per priority × plan — needs ops decision.
- Whether CSAT is in-app only, email-embedded, or both.
- Company-side roles matrix vs platform-admin-only for v1.