feat(ux): helpful empty states with CTAs across list pages (PMS-354) #251
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/pms-354-empty-state-cta"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Makes empty states consistent across the SPA (PMS-354). The shared
EmptyStatecomponent already existed (components/layout.rs:title/description/actions: Option<Element>) but was unused; list tables rendered the message-onlyTableEmpty.Extended
TableEmptywith optionaltitle/description/actions: whentitleis set it renders the sharedEmptyState(title + next-action body + optional CTA) inside the table's colspan cell. Back-compat: calls passing onlymessageare unchanged.Converted (primary entity lists, with CTA)
Tickets (New Ticket), Contracts (New Contract), Rate Cards (New Rate Card, gated on
can_edit), Companies (New Company), Contacts (New Contact), Invoices (New Invoice), Payments (Record Payment), Tax Rates (New Tax Rate), Payment Gateways (Configure Gateway), Knowledge Base articles (New Article), Projects (New Project - rendered viaEmptyStatedirectly since the project list is a card grid, not a table).No-CTA cases (AC4)
SLA policies / business-hours / holiday calendars (create is an inline header button, so title + "use New X above" body), Admin tenants, Team invitations, Audit log ("No activity yet" - entries are system-recorded).
Untouched (by design)
AC mapping
actions: Option<Element>); used for audit log, admin, SLA, team.Verification
wasm
cargo check,cargo clippy --target wasm32-unknown-unknown --lib -- -D warnings, andcargo fmt --all --checkall pass.#PMS-354
External review found empty states inconsistent: Contracts guided the next action while Tickets and others showed a bare "No X yet" line with no CTA. A shared EmptyState component already existed (components/layout.rs) but was unused; list tables rendered the message-only TableEmpty. Extend TableEmpty with optional title/description/actions: when title is set it renders the shared EmptyState (title + next-action body + optional CTA) inside the table's colspan cell, so every list's empty state follows the same pattern. Back-compat: calls passing only `message` are unchanged (sub-resource tables, error rows, filtered-to-nothing states keep their one-liner). Converted the primary entity lists to title + next-action body + a "New X" CTA where a create affordance exists: - Tickets (New Ticket), Contracts (New Contract), Rate Cards (New Rate Card, gated on can_edit), Companies (New Company), Contacts (New Contact), Invoices (New Invoice), Payments (Record Payment), Tax Rates (New Tax Rate), Payment Gateways (Configure Gateway), Knowledge Base articles (New Article), Projects (New Project, rendered via EmptyState directly since the project list is a card grid). - No-CTA cases (AC4): SLA policies / business-hours / holiday calendars (create is an inline header button, so title + "use New X above" body), Admin tenants, Team invitations, Audit log ("No activity yet"; entries are system-recorded). Filtered-to-nothing branches get a title + "adjust your filters" body without a CTA; error rows and sub-resource tables keep their plain message. Out of scope: the settings lookup sub-tables (work types, ticket statuses, etc.) keep their message-only TableEmpty - they are config sub-tables with inline add-buttons, not primary entity lists. #PMS-354