Feat/a11y discover subs fixes - #1542
Merged
Merged
Conversation
The creator dashboard shell had no skip navigation and never moved focus on route change, forcing keyboard/screen-reader users to tab through the full sidebar on every navigation. Add a "Skip to main content" link, give the main landmark a focusable id, and focus it whenever the route changes. Icon-only controls already had aria-labels; add a test covering the skip link, focus handoff, and labeled controls.
publicCreatorToProfile hardcoded subscriptionPrice to 0 and categories to [] even when the /creators API returned subscription_price, currency, and categories, making every discovery card look free and uncategorized. Map these fields when present (parsing the numeric-string price safely) and keep defaulting to 0/[] only when they're actually absent or unparsable. Add tests for the present, absent, and malformed cases.
… list The active-subscriptions fetch called a bare relative path with no Authorization header, so it silently depended on the dev-only Next rewrite and failed auth against the JWT-bearer backend, always falling back to a plain "no subscriptions" empty state on error or 401. Add a shared fetchActiveSubscriptions client (absolute API base, Bearer token, field-normalizing) mirroring the existing profile.ts client, wire the page to it, and surface a distinct sign-in-required / load-failed state so failures are never mistaken for a genuinely empty list.
|
@OxDev-max Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three independent frontend fixes bundled together:
1. Dashboard shell accessibility (skip-link + focus management)
The creator dashboard shell had no skip navigation and never moved focus on
route change, forcing keyboard and screen-reader users to tab through the
entire sidebar on every single navigation.
top of the dashboard shell.
<main>landmark a focusable#dashboard-mainid and move focusto it whenever the route changes (skipped on initial mount so it doesn't
steal focus on first load).
collapse toggle) already carry
aria-labels.2. Discover: map creator fields completely
publicCreatorToProfilehardcodedsubscriptionPriceto0andcategoriesto[]even when the/creatorsAPI returnedsubscription_price,currency, andcategories, making every card inthe discovery grid look free and uncategorized regardless of the actual
data.
subscription_price(parsed safely from the numeric string theAPI returns),
currency, andcategorieswhen present.0/[]only when the fields are genuinely absent orfail to parse — no fabricated data.
3. Subscriptions: authenticated client for the active list
The active-subscriptions fetch called a bare relative path
(
/api/v1/subscriptions/me/list) with noAuthorizationheader. Sincethis app authenticates with a stored JWT (not cookies), the request would
fail auth against the real backend and any failure — network error or
401 — silently rendered the same "No subscriptions found" empty state,
indistinguishable from a user who genuinely has none.
src/lib/api/subscriptions.ts: a client mirroring the existingprofile.tspattern — absolute, config-driven API base URL, Bearertoken attached from
auth-storage, response normalization withfallback field names, and a
SubscriptionsUnauthorizedErrorthrown (andstale token cleared) on 401.
and the post-renewal refetch.
(401), "couldn't load subscriptions" (other errors), and the genuine
empty state — so failures are never mistaken for an empty list.
Changes
frontend/src/app/dashboard/layout.tsx— skip link, focusable mainlandmark, focus-on-navigate
frontend/src/app/dashboard/layout.test.tsx— new: skip link, focushandoff, labeled controls
frontend/src/lib/api/creators.ts— mapsubscription_price,currency,categorieswith safe defaultsfrontend/src/lib/api/creators.test.ts— coverage for present/absent/malformed field cases
frontend/src/lib/api/subscriptions.ts— new: authenticatedfetchActiveSubscriptionsclientfrontend/src/lib/api/subscriptions.test.ts— new: URL, auth header,normalization, 401 handling
frontend/src/app/subscriptions/page.tsx— use the new client, adddistinct error/unauthorized UI states
Test plan
pnpm testinfrontend/(new/updated:layout.test.tsx,creators.test.ts,subscriptions.test.ts)pnpm buildto confirm no type errors/dashboard— confirm the skip link appears onfirst Tab press and jumps focus into main content
main content region each time
/discoverwith a creator that hassubscription_price/categoriesset — confirm the card shows the real price and tagsinstead of "Free" / no categories
/subscriptionswhile signed in — confirm the active listloads (previously would fail auth silently)
/subscriptionswith an expired/missing token — confirm the"Sign in required" state appears instead of a blank "No
subscriptions found"
Changes
Test Plan
Automated tests added or updated
backend/src/**/*.spec.ts) — service/guard/decorator logic in isolationbackend/test/**/*.e2e-spec.ts) — HTTP round-trips with mocked infrastructurefrontend/src/**/*.test.{ts,tsx}) — React component behaviourfrontend/e2e/**/*.spec.ts) — Playwright browser flowscontract/) — Soroban/Rust unit tests viacargo testHow to run the tests locally
Manual verification checklist
cd backend && npm run lint/cd frontend && npm run lintRelated issues
Notes for reviewers
Closes #1489
Closes #1490
Closes #1491