feat(web): add /requests user-facing request history

Renders the caller's Lidarr requests as rows with kind pill,
StatusPill, and per-status actions: Cancel on pending (which
calls cancelRequest then invalidates qk.myRequests()), Listen
link on completed (deepest match wins: track > album > artist),
admin notes on rejected. Empty state uses the voice-rule
"Nothing requested yet." copy. Shell nav gains /requests
between /discover and /playlists, visible to all authed users
since the view is per-user.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-29 22:24:17 -04:00
parent a7506d9413
commit ad904afaf6
4 changed files with 302 additions and 1 deletions
+1
View File
@@ -26,6 +26,7 @@
{ href: '/library/liked', label: 'Liked' },
{ href: '/search', label: 'Search' },
{ href: '/discover', label: 'Discover' },
{ href: '/requests', label: 'Requests' },
{ href: '/playlists', label: 'Playlists' },
{ href: '/settings', label: 'Settings' }
];
+2 -1
View File
@@ -28,11 +28,12 @@ describe('Shell', () => {
expect(screen.getByText('alice')).toBeInTheDocument();
});
test('renders nav items including Discover between Search and Playlists', () => {
test('renders nav items including Discover and Requests between Search and Playlists', () => {
render(Shell);
expect(screen.getByRole('link', { name: 'Library' })).toHaveAttribute('href', '/');
expect(screen.getByRole('link', { name: 'Search' })).toHaveAttribute('href', '/search');
expect(screen.getByRole('link', { name: 'Discover' })).toHaveAttribute('href', '/discover');
expect(screen.getByRole('link', { name: 'Requests' })).toHaveAttribute('href', '/requests');
expect(screen.getByRole('link', { name: 'Playlists' })).toHaveAttribute('href', '/playlists');
});