refactor(webui): simplify stats artist detail handoff
- remove the stats page timeout and library pre-navigation hack - hand artist detail opening directly to the legacy shell bridge - add a route test covering the direct artist navigation bridge call
This commit is contained in:
parent
1e052373a4
commit
92e86527c3
2 changed files with 19 additions and 23 deletions
|
|
@ -114,6 +114,17 @@ describe('stats route', () => {
|
|||
await waitFor(() => expect(history.location.search).toContain('range=30d'));
|
||||
});
|
||||
|
||||
it('hands artist detail navigation directly to the shell bridge', async () => {
|
||||
renderStatsRoute();
|
||||
|
||||
fireEvent.click(await screen.findByRole('button', { name: 'Artist A' }));
|
||||
|
||||
expect(window.SoulSyncWebShellBridge?.navigateToArtistDetail).toHaveBeenCalledWith(
|
||||
7,
|
||||
'Artist A',
|
||||
);
|
||||
});
|
||||
|
||||
it('redirects back home when the page is not allowed', async () => {
|
||||
window.SoulSyncWebShellBridge = createShellBridge({
|
||||
isPageAllowed: vi.fn((pageId) => pageId !== 'stats'),
|
||||
|
|
|
|||
|
|
@ -135,6 +135,10 @@ export function StatsPage() {
|
|||
});
|
||||
};
|
||||
|
||||
const openArtistDetail = (artistId: string | number, artistName: string) => {
|
||||
bridge.navigateToArtistDetail(artistId, artistName);
|
||||
};
|
||||
|
||||
return (
|
||||
<div id="stats-container" className={styles.statsContainer} data-testid="stats-page">
|
||||
<header className={styles.statsHeader}>
|
||||
|
|
@ -214,31 +218,23 @@ export function StatsPage() {
|
|||
<StatsSectionCard title="Top Artists">
|
||||
<TopArtistsVisual
|
||||
artists={cachedStats?.top_artists ?? []}
|
||||
onArtistSelect={(artistId, artistName) =>
|
||||
void openArtistDetail(bridge, artistId, artistName)
|
||||
}
|
||||
onArtistSelect={(artistId, artistName) => openArtistDetail(artistId, artistName)}
|
||||
/>
|
||||
<StatsRankedArtists
|
||||
artists={cachedStats?.top_artists ?? []}
|
||||
onArtistSelect={(artistId, artistName) =>
|
||||
void openArtistDetail(bridge, artistId, artistName)
|
||||
}
|
||||
onArtistSelect={(artistId, artistName) => openArtistDetail(artistId, artistName)}
|
||||
/>
|
||||
</StatsSectionCard>
|
||||
<StatsSectionCard title="Top Albums">
|
||||
<StatsRankedAlbums
|
||||
albums={cachedStats?.top_albums ?? []}
|
||||
onArtistSelect={(artistId, artistName) =>
|
||||
void openArtistDetail(bridge, artistId, artistName)
|
||||
}
|
||||
onArtistSelect={(artistId, artistName) => openArtistDetail(artistId, artistName)}
|
||||
/>
|
||||
</StatsSectionCard>
|
||||
<StatsSectionCard title="Top Tracks">
|
||||
<StatsRankedTracks
|
||||
tracks={cachedStats?.top_tracks ?? []}
|
||||
onArtistSelect={(artistId, artistName) =>
|
||||
void openArtistDetail(bridge, artistId, artistName)
|
||||
}
|
||||
onArtistSelect={(artistId, artistName) => openArtistDetail(artistId, artistName)}
|
||||
onPlay={(track) => playStatsTrack(bridge, track)}
|
||||
/>
|
||||
</StatsSectionCard>
|
||||
|
|
@ -877,17 +873,6 @@ function EmptyListState({ message }: { message: string }) {
|
|||
return <div className={styles.emptyListState}>{message}</div>;
|
||||
}
|
||||
|
||||
async function openArtistDetail(
|
||||
bridge: ShellBridge,
|
||||
artistId: string | number,
|
||||
artistName: string,
|
||||
) {
|
||||
await window.SoulSyncWebRouter?.navigateToPage('library');
|
||||
window.setTimeout(() => {
|
||||
bridge.navigateToArtistDetail(artistId, artistName);
|
||||
}, 300);
|
||||
}
|
||||
|
||||
async function playStatsTrack(
|
||||
bridge: ShellBridge,
|
||||
track: { title: string; artist: string; album: string },
|
||||
|
|
|
|||
Loading…
Reference in a new issue