feat: schedule queries
This commit is contained in:
@@ -0,0 +1,51 @@
|
|||||||
|
import { getDb, resetDb } from '../../db';
|
||||||
|
import {
|
||||||
|
insertScheduleEntry, getScheduleByDate, updateScheduleStatus,
|
||||||
|
getUpcomingSchedule, getPendingDates,
|
||||||
|
} from '../../db/schedule';
|
||||||
|
|
||||||
|
beforeEach(() => { resetDb(); });
|
||||||
|
|
||||||
|
describe('schedule', () => {
|
||||||
|
it('inserts and retrieves a schedule entry', () => {
|
||||||
|
const db = getDb();
|
||||||
|
insertScheduleEntry(db, '2026-05-22', 60, 'Continuing current level');
|
||||||
|
const e = getScheduleByDate(db, '2026-05-22');
|
||||||
|
expect(e).not.toBeNull();
|
||||||
|
expect(e!.planned_min).toBe(60);
|
||||||
|
expect(e!.status).toBe('pending');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('updates status to completed', () => {
|
||||||
|
const db = getDb();
|
||||||
|
insertScheduleEntry(db, '2026-05-22', 60, null);
|
||||||
|
updateScheduleStatus(db, '2026-05-22', 'completed', null);
|
||||||
|
expect(getScheduleByDate(db, '2026-05-22')!.status).toBe('completed');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('updates status to skipped with reason', () => {
|
||||||
|
const db = getDb();
|
||||||
|
insertScheduleEntry(db, '2026-05-22', 60, null);
|
||||||
|
updateScheduleStatus(db, '2026-05-22', 'skipped', 'work trip');
|
||||||
|
const e = getScheduleByDate(db, '2026-05-22')!;
|
||||||
|
expect(e.status).toBe('skipped');
|
||||||
|
expect(e.skip_reason).toBe('work trip');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns upcoming entries from today onwards ordered by date', () => {
|
||||||
|
const db = getDb();
|
||||||
|
insertScheduleEntry(db, '2026-05-21', 60, null);
|
||||||
|
insertScheduleEntry(db, '2026-05-23', 75, null);
|
||||||
|
const rows = getUpcomingSchedule(db, '2026-05-21');
|
||||||
|
expect(rows).toHaveLength(2);
|
||||||
|
expect(rows[0]!.date).toBe('2026-05-21');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns only pending dates', () => {
|
||||||
|
const db = getDb();
|
||||||
|
insertScheduleEntry(db, '2026-05-21', 60, null);
|
||||||
|
insertScheduleEntry(db, '2026-05-22', 60, null);
|
||||||
|
updateScheduleStatus(db, '2026-05-21', 'completed', null);
|
||||||
|
expect(getPendingDates(db)).toEqual(['2026-05-22']);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import type { Database } from 'better-sqlite3';
|
||||||
|
|
||||||
|
export type ScheduleStatus = 'pending' | 'completed' | 'skipped';
|
||||||
|
|
||||||
|
export interface ScheduleEntry {
|
||||||
|
id: number;
|
||||||
|
date: string;
|
||||||
|
planned_min: number;
|
||||||
|
status: ScheduleStatus;
|
||||||
|
skip_reason: string | null;
|
||||||
|
ai_rationale: string | null;
|
||||||
|
created_at: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function insertScheduleEntry(
|
||||||
|
db: Database, date: string, planned_min: number, ai_rationale: string | null
|
||||||
|
): ScheduleEntry {
|
||||||
|
db.prepare(
|
||||||
|
'INSERT OR IGNORE INTO schedule (date, planned_min, ai_rationale) VALUES (?, ?, ?)'
|
||||||
|
).run(date, planned_min, ai_rationale);
|
||||||
|
return getScheduleByDate(db, date)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getScheduleByDate(db: Database, date: string): ScheduleEntry | null {
|
||||||
|
return (db.prepare('SELECT * FROM schedule WHERE date = ?').get(date) as ScheduleEntry | undefined) ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateScheduleStatus(
|
||||||
|
db: Database, date: string, status: ScheduleStatus, skip_reason: string | null
|
||||||
|
): void {
|
||||||
|
db.prepare(
|
||||||
|
'UPDATE schedule SET status = ?, skip_reason = ? WHERE date = ?'
|
||||||
|
).run(status, skip_reason, date);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getUpcomingSchedule(db: Database, fromDate: string): ScheduleEntry[] {
|
||||||
|
return db.prepare(
|
||||||
|
'SELECT * FROM schedule WHERE date >= ? ORDER BY date ASC'
|
||||||
|
).all(fromDate) as ScheduleEntry[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPendingDates(db: Database): string[] {
|
||||||
|
const rows = db.prepare(
|
||||||
|
"SELECT date FROM schedule WHERE status = 'pending' ORDER BY date ASC"
|
||||||
|
).all() as Array<{ date: string }>;
|
||||||
|
return rows.map(r => r.date);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user