+ {/* Header */}
+
+
+
+
+
+ {displayTitle}
+
+
+
+
+ {/* Metadata */}
+ {(transcript.channel || transcript.duration_s != null) && (
+
+ {transcript.channel && (
+ {transcript.channel}
+ )}
+ {transcript.duration_s != null && (
+
+
+ {formatDuration(transcript.duration_s)}
+
+ )}
+
+ )}
+
+ {/* Summary */}
+
+
+ {transcript.summary}
+
+ {transcript.summary.length > 160 && (
+
+ )}
+
+
+ {/* Key Points */}
+ {transcript.key_points.length > 0 && (
+
+ {transcript.key_points
+ .slice(0, expanded ? undefined : 3)
+ .map((point, i) => (
+ -
+
+ {point}
+
+ ))}
+ {!expanded && transcript.key_points.length > 3 && (
+ -
+ +{transcript.key_points.length - 3} more
+
+ )}
+
+ )}
+
+ {/* Footer */}
+
{relativeTime}
+
+ {/* Delete confirmation dialog */}
+
+
+ Delete transcript?
+
+ This will permanently delete “{displayTitle}” and its
+ cross-indexed memory entry. This action cannot be undone.
+
+
+
+ }
+ >
+ Cancel
+
+
+
+
+
+
+ );
+};
+
+export default VideoTranscriptCard;
diff --git a/frontend/features/youtube/hooks/useYoutube.ts b/frontend/features/youtube/hooks/useYoutube.ts
new file mode 100644
index 0000000..680d5ca
--- /dev/null
+++ b/frontend/features/youtube/hooks/useYoutube.ts
@@ -0,0 +1,44 @@
+'use client';
+
+import { useEffect, useState } from 'react';
+import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
+import { deleteVideoTranscript, listVideoTranscripts } from '@/lib/api';
+import { createClient } from '@/lib/supabase/client';
+import type { VideoTranscriptOut } from '@/features/youtube/types';
+
+// Broad prefix for mutation invalidation — matches all user variants.
+export const VIDEO_TRANSCRIPTS_KEY = ['video-transcripts'] as const;
+
+function videoTranscriptsKey(userId: string) {
+ return ['video-transcripts', userId] as const;
+}
+
+function useUserId(): string {
+ const [userId, setUserId] = useState('');
+ useEffect(() => {
+ createClient()
+ .auth.getSession()
+ .then(({ data }) => setUserId(data.session?.user.id ?? ''));
+ }, []);
+ return userId;
+}
+
+export function useVideoTranscripts() {
+ const userId = useUserId();
+ return useQuery