import { useEffect, useState } from 'react'; import { useMediaDetail } from '../../hooks/useMediaDetail'; import { apiClient } from '../../lib/api-client'; import { confirmSessionDelete } from '../../lib/delete-confirm'; import { getSessionDisplayWordCount } from '../../lib/session-word-count'; import { MediaHeader } from './MediaHeader'; import { MediaSessionList } from './MediaSessionList'; import type { MediaDetailData, SessionSummary } from '../../types/stats'; export function getRelatedCollectionLabel(detail: MediaDetailData['detail']): string { if (detail?.channelName?.trim()) { return 'View Channel'; } return 'View Anime'; } interface MediaDetailViewProps { videoId: number; initialExpandedSessionId?: number | null; onConsumeInitialExpandedSession?: () => void; onBack: () => void; backLabel?: string; onNavigateToAnime?: (animeId: number) => void; } export function MediaDetailView({ videoId, initialExpandedSessionId = null, onConsumeInitialExpandedSession, onBack, backLabel = 'Back to Library', onNavigateToAnime, }: MediaDetailViewProps) { const { data, loading, error } = useMediaDetail(videoId); const [localSessions, setLocalSessions] = useState(null); const [deleteError, setDeleteError] = useState(null); const [deletingSessionId, setDeletingSessionId] = useState(null); useEffect(() => { setLocalSessions(data?.sessions ?? null); }, [data?.sessions]); if (loading) return
Loading...
; if (error) return
Error: {error}
; if (!data?.detail) return
Media not found
; const sessions = localSessions ?? data.sessions; const animeId = data.detail.animeId; const detail = { ...data.detail, totalSessions: sessions.length, totalActiveMs: sessions.reduce((sum, session) => sum + session.activeWatchedMs, 0), totalCards: sessions.reduce((sum, session) => sum + session.cardsMined, 0), totalTokensSeen: sessions.reduce( (sum, session) => sum + getSessionDisplayWordCount(session), 0, ), totalLinesSeen: sessions.reduce((sum, session) => sum + session.linesSeen, 0), totalLookupCount: sessions.reduce((sum, session) => sum + session.lookupCount, 0), totalLookupHits: sessions.reduce((sum, session) => sum + session.lookupHits, 0), totalYomitanLookupCount: sessions.reduce((sum, session) => sum + session.yomitanLookupCount, 0), }; const relatedCollectionLabel = getRelatedCollectionLabel(detail); const handleDeleteSession = async (session: SessionSummary) => { if (!confirmSessionDelete()) return; setDeleteError(null); setDeletingSessionId(session.sessionId); try { await apiClient.deleteSession(session.sessionId); setLocalSessions((prev) => (prev ?? data.sessions).filter((item) => item.sessionId !== session.sessionId), ); } catch (err) { setDeleteError(err instanceof Error ? err.message : 'Failed to delete session.'); } finally { setDeletingSessionId(null); } }; return (
{onNavigateToAnime != null && animeId != null ? ( ) : null}
{deleteError ?
{deleteError}
: null}
); }