import prisma from '@/lib/prisma' import { isCardMastered } from '@/lib/flashcards/sm2' export interface DeckSummary { id: string name: string notebookId: string | null notebookName: string | null totalCards: number dueCount: number masteredCount: number lastReviewedAt: string | null nextReviewAt: string | null createdAt: string } export async function listDeckSummaries(userId: string): Promise { const now = new Date() const decks = await prisma.flashcardDeck.findMany({ where: { userId }, include: { notebook: { select: { name: true } }, flashcards: { select: { id: true, interval: true, nextReviewAt: true, reviews: { orderBy: { reviewedAt: 'desc' }, take: 1, select: { reviewedAt: true }, }, }, }, }, orderBy: { updatedAt: 'desc' }, }) return decks.map((deck) => { const totalCards = deck.flashcards.length const dueCount = deck.flashcards.filter((c) => c.nextReviewAt <= now).length // Maîtrisée = interval >= 7 jours (une semaine de bonne mémorisation) const masteredCount = deck.flashcards.filter((c) => c.interval >= 7).length const lastReview = deck.flashcards .flatMap((c) => c.reviews.map((r) => r.reviewedAt)) .sort((a, b) => b.getTime() - a.getTime())[0] // Date de la prochaine carte à réviser (la plus proche dans le futur) const nextReviewAt = deck.flashcards .map((c) => c.nextReviewAt) .sort((a, b) => a.getTime() - b.getTime())[0] ?? null return { id: deck.id, name: deck.name, notebookId: deck.notebookId, notebookName: deck.notebook?.name ?? null, totalCards, dueCount, masteredCount, lastReviewedAt: lastReview ? lastReview.toISOString() : null, nextReviewAt: nextReviewAt ? nextReviewAt.toISOString() : null, createdAt: deck.createdAt.toISOString(), } }) } export async function getDeckDetail(userId: string, deckId: string) { const deck = await prisma.flashcardDeck.findFirst({ where: { id: deckId, userId }, include: { flashcards: { orderBy: { nextReviewAt: 'asc' }, include: { note: { select: { id: true, title: true } }, }, }, }, }) if (!deck) return null const now = new Date() return { id: deck.id, name: deck.name, notebookId: deck.notebookId, cards: deck.flashcards.map((c) => ({ id: c.id, front: c.front, back: c.back, type: c.type, interval: c.interval, easinessFactor: c.easinessFactor, nextReviewAt: c.nextReviewAt.toISOString(), noteId: c.noteId, noteTitle: c.note?.title ?? null, due: c.nextReviewAt <= now, mastered: isCardMastered(c.interval), })), } }