Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x | /**
* Progression Deferrals
*
* Server-side functions for managing skill progression deferrals.
* When a teacher clicks "Not yet, ask again later", the system defers
* the progression recommendation for 7 days.
*/
import { and, eq, gt } from 'drizzle-orm'
import { db, schema } from '@/db'
import type { ProgressionDeferral } from '@/db/schema/progression-deferrals'
/** Default deferral duration: 7 days in milliseconds */
const DEFERRAL_DURATION_MS = 7 * 24 * 60 * 60 * 1000
/**
* Check if there is an active (non-expired) deferral for a skill.
*/
export async function getActiveDeferral(
playerId: string,
skillId: string
): Promise<ProgressionDeferral | null> {
const now = Date.now()
const result = await db
.select()
.from(schema.progressionDeferrals)
.where(
and(
eq(schema.progressionDeferrals.playerId, playerId),
eq(schema.progressionDeferrals.skillId, skillId),
gt(schema.progressionDeferrals.expiresAt, now)
)
)
.limit(1)
return result[0] ?? null
}
/**
* Create or update a progression deferral for a skill.
* Uses INSERT OR REPLACE since there's a unique constraint on (playerId, skillId).
*/
export async function deferProgression(
playerId: string,
skillId: string,
durationMs: number = DEFERRAL_DURATION_MS
): Promise<ProgressionDeferral> {
const now = Date.now()
// Delete existing deferral first (upsert pattern for SQLite)
await db
.delete(schema.progressionDeferrals)
.where(
and(
eq(schema.progressionDeferrals.playerId, playerId),
eq(schema.progressionDeferrals.skillId, skillId)
)
)
const [result] = await db
.insert(schema.progressionDeferrals)
.values({
playerId,
skillId,
deferredAt: now,
expiresAt: now + durationMs,
})
.returning()
return result
}
/**
* Remove a progression deferral (e.g., teacher changes their mind).
*/
export async function clearDeferral(playerId: string, skillId: string): Promise<void> {
await db
.delete(schema.progressionDeferrals)
.where(
and(
eq(schema.progressionDeferrals.playerId, playerId),
eq(schema.progressionDeferrals.skillId, skillId)
)
)
}
|