a39e06ff07
Deliver P5.2 writing day logs, cockpit heatmap, streak tracking, and chapter knowledge auto-extraction with merge review. Co-authored-by: Cursor <cursoragent@cursor.com>
36 lines
1.2 KiB
TypeScript
36 lines
1.2 KiB
TypeScript
import type { SqliteDb } from '../types'
|
|
|
|
export interface ChapterWritingSnapshot {
|
|
loggedWordCount: number
|
|
finishSupplemented: boolean
|
|
}
|
|
|
|
export class ChapterWritingSnapshotRepository {
|
|
constructor(private db: SqliteDb) {}
|
|
|
|
get(chapterId: string): ChapterWritingSnapshot | null {
|
|
const row = this.db
|
|
.prepare(
|
|
'SELECT logged_word_count, finish_supplemented FROM chapter_writing_snapshots WHERE chapter_id = ?'
|
|
)
|
|
.get(chapterId) as { logged_word_count: number; finish_supplemented: number } | undefined
|
|
if (!row) return null
|
|
return {
|
|
loggedWordCount: row.logged_word_count,
|
|
finishSupplemented: row.finish_supplemented === 1
|
|
}
|
|
}
|
|
|
|
upsert(chapterId: string, loggedWordCount: number, finishSupplemented = false): void {
|
|
this.db
|
|
.prepare(
|
|
`INSERT INTO chapter_writing_snapshots (chapter_id, logged_word_count, finish_supplemented)
|
|
VALUES (?, ?, ?)
|
|
ON CONFLICT(chapter_id) DO UPDATE SET
|
|
logged_word_count = excluded.logged_word_count,
|
|
finish_supplemented = excluded.finish_supplemented`
|
|
)
|
|
.run(chapterId, loggedWordCount, finishSupplemented ? 1 : 0)
|
|
}
|
|
}
|