feat(stats): add 'View Anime' navigation button in MediaDetailView

- Added onNavigateToAnime prop to MediaDetailView
- Show 'View Anime →' button in the top-right when viewing media from
  non-anime origins (overview/sessions)
- Extract animeId from available sessions to enable navigation
- Button is hidden when already viewing from anime origin

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-03-19 21:43:30 -07:00
parent 0ea1746123
commit 64a88020c9

View File

@@ -13,6 +13,7 @@ interface MediaDetailViewProps {
onConsumeInitialExpandedSession?: () => void; onConsumeInitialExpandedSession?: () => void;
onBack: () => void; onBack: () => void;
backLabel?: string; backLabel?: string;
onNavigateToAnime?: (animeId: number) => void;
} }
export function MediaDetailView({ export function MediaDetailView({
@@ -21,6 +22,7 @@ export function MediaDetailView({
onConsumeInitialExpandedSession, onConsumeInitialExpandedSession,
onBack, onBack,
backLabel = 'Back to Library', backLabel = 'Back to Library',
onNavigateToAnime,
}: MediaDetailViewProps) { }: MediaDetailViewProps) {
const { data, loading, error } = useMediaDetail(videoId); const { data, loading, error } = useMediaDetail(videoId);
const [localSessions, setLocalSessions] = useState<SessionSummary[] | null>(null); const [localSessions, setLocalSessions] = useState<SessionSummary[] | null>(null);
@@ -36,6 +38,7 @@ export function MediaDetailView({
if (!data?.detail) return <div className="text-ctp-overlay2 p-4">Media not found</div>; if (!data?.detail) return <div className="text-ctp-overlay2 p-4">Media not found</div>;
const sessions = localSessions ?? data.sessions; const sessions = localSessions ?? data.sessions;
const animeId = sessions.find((s) => s.animeId != null)?.animeId ?? null;
const detail = { const detail = {
...data.detail, ...data.detail,
totalSessions: sessions.length, totalSessions: sessions.length,
@@ -70,13 +73,24 @@ export function MediaDetailView({
return ( return (
<div className="space-y-4"> <div className="space-y-4">
<button <div className="flex items-center justify-between">
type="button" <button
onClick={onBack} type="button"
className="text-sm text-ctp-blue hover:text-ctp-sapphire transition-colors" onClick={onBack}
> className="text-sm text-ctp-blue hover:text-ctp-sapphire transition-colors"
&larr; {backLabel} >
</button> &larr; {backLabel}
</button>
{onNavigateToAnime != null && animeId != null ? (
<button
type="button"
onClick={() => onNavigateToAnime(animeId)}
className="text-sm text-ctp-blue hover:text-ctp-sapphire transition-colors"
>
View Anime &rarr;
</button>
) : null}
</div>
<MediaHeader detail={detail} /> <MediaHeader detail={detail} />
{deleteError ? <div className="text-sm text-ctp-red">{deleteError}</div> : null} {deleteError ? <div className="text-sm text-ctp-red">{deleteError}</div> : null}
<MediaSessionList <MediaSessionList