1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
import { and, eq, gte, sql } from "drizzle-orm";
import { db } from "../db/index.js";
import { CardState, cards, reviewLogs } from "../db/schema.js";
import type { ReviewLog, ReviewLogRepository } from "./types.js";
export const reviewLogRepository: ReviewLogRepository = {
async create(data: {
cardId: string;
userId: string;
rating: number;
state: number;
scheduledDays: number;
elapsedDays: number;
durationMs?: number | null;
}): Promise<ReviewLog> {
const [reviewLog] = await db
.insert(reviewLogs)
.values({
cardId: data.cardId,
userId: data.userId,
rating: data.rating,
state: data.state,
scheduledDays: data.scheduledDays,
elapsedDays: data.elapsedDays,
durationMs: data.durationMs ?? null,
})
.returning();
if (!reviewLog) {
throw new Error("Failed to create review log");
}
return reviewLog;
},
async countTodayNewCardReviews(deckId: string, now: Date): Promise<number> {
const startOfDay = new Date(now);
startOfDay.setHours(0, 0, 0, 0);
const result = await db
.select({ count: sql<number>`count(distinct ${reviewLogs.cardId})::int` })
.from(reviewLogs)
.innerJoin(cards, eq(reviewLogs.cardId, cards.id))
.where(
and(
eq(cards.deckId, deckId),
eq(reviewLogs.state, CardState.New),
gte(reviewLogs.reviewedAt, startOfDay),
),
);
return result[0]?.count ?? 0;
},
};
|