// app/api/progress/all/route.ts // Everything the signed-in user has watched, in one response, so pages do not // have to ask about each video separately. import { NextResponse } from 'next/server'; import { prisma } from '@/lib/prisma'; import { getViewer } from '@/lib/video-access'; import { mergeRanges } from '@/lib/watch-progress'; type Segment = { startSec: number; endSec: number; watchedAt?: Date }; /** * GET /api/progress/all – all of the user's progress * GET /api/progress/all?playlistId – only videos in that playlist * * Returns { progress: { [videoId]: { percent, watchedSec, segments } } }. * Videos the user has never played are simply absent. */ export async function GET(req: Request) { try { const viewer = await getViewer(); if (!viewer) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); const playlistId = new URL(req.url).searchParams.get('playlistId'); const where = { userId: viewer.id, ...(playlistId ? { video: { playlistId } } : {}), }; const [progressRows, segmentRows] = await Promise.all([ prisma.videoProgress.findMany({ where, select: { videoId: true, percent: true, watchedSec: true }, }), prisma.videoWatchSegment.findMany({ where, select: { videoId: true, startSec: true, endSec: true, watchedAt: true }, }), ]); const segmentsByVideo = new Map(); for (const { videoId, ...segment } of segmentRows) { const list = segmentsByVideo.get(videoId); if (list) list.push(segment); else segmentsByVideo.set(videoId, [segment]); } const progress: Record< string, { percent: number; watchedSec: number; segments: Segment[] } > = {}; for (const row of progressRows) { progress[row.videoId] = { percent: row.percent, watchedSec: row.watchedSec, // Older data can hold many overlapping rows per video; send the merged view. segments: mergeRanges(segmentsByVideo.get(row.videoId) ?? []), }; } return NextResponse.json({ progress }); } catch (err: any) { console.error('progress/all GET error', err); return NextResponse.json({ error: err?.message ?? 'server error' }, { status: 500 }); } }