2026-01-20 09:02:26 -06:00

161 lines
4.9 KiB
TypeScript

// routes/api/brain/progress.ts
// API endpoint for Brain study progress with mode progression
import { define, State } from "../../../utils.ts";
import { SessionCookie } from "../../auth/callback.ts";
import { brainDataClient } from "../../../utils/BrainDataClient.ts";
export const handler = define.handlers({
// GET: Fetch user's brain progress stats
async GET(ctx) {
const state = ctx.state as State;
const stateData: SessionCookie = state.data ?? {
started_on: 0,
user_name: "",
user_id: "",
role: "",
user_encrypted: false,
};
if (!state.stateId || !stateData.user_id) {
return new Response(
JSON.stringify({ error: "Unauthorized" }),
{ status: 401, headers: { "Content-Type": "application/json" } },
);
}
try {
const stats = await brainDataClient.getStats(stateData.user_id);
const dueCount = await brainDataClient.getDueCount(stateData.user_id);
return new Response(
JSON.stringify({
success: true,
stats,
dueCount,
}),
{ status: 200, headers: { "Content-Type": "application/json" } },
);
} catch (error) {
console.error("Error fetching brain progress:", error);
return new Response(
JSON.stringify({ error: "Failed to fetch progress" }),
{ status: 500, headers: { "Content-Type": "application/json" } },
);
}
},
// POST: Record answer result with mode progression
async POST(ctx) {
const state = ctx.state as State;
const stateData: SessionCookie = state.data ?? {
started_on: 0,
user_name: "",
user_id: "",
role: "",
user_encrypted: false,
};
if (!state.stateId || !stateData.user_id) {
return new Response(
JSON.stringify({ error: "Unauthorized" }),
{ status: 401, headers: { "Content-Type": "application/json" } },
);
}
try {
const body = await ctx.req.json();
const { questionId, quizId, wasCorrectFirstTry } = body;
// Mode is no longer required - it's tracked per-card by the backend
if (!questionId || !quizId || typeof wasCorrectFirstTry !== "boolean") {
return new Response(
JSON.stringify({
error:
"Missing required fields: questionId, quizId, wasCorrectFirstTry",
}),
{ status: 400, headers: { "Content-Type": "application/json" } },
);
}
const progress = await brainDataClient.recordAnswer(
stateData.user_id,
questionId,
quizId,
wasCorrectFirstTry,
);
return new Response(
JSON.stringify({
success: true,
progress,
// Include mode advancement info for UI feedback
modeAdvanced: wasCorrectFirstTry && progress.mode_index > 0,
isReviewOnly: progress.is_review_only,
}),
{ status: 200, headers: { "Content-Type": "application/json" } },
);
} catch (error) {
console.error("Error recording brain progress:", error);
return new Response(
JSON.stringify({ error: "Failed to record progress" }),
{ status: 500, headers: { "Content-Type": "application/json" } },
);
}
},
// DELETE: Reset progress
async DELETE(ctx) {
const state = ctx.state as State;
const stateData: SessionCookie = state.data ?? {
started_on: 0,
user_name: "",
user_id: "",
role: "",
user_encrypted: false,
};
if (!state.stateId || !stateData.user_id) {
return new Response(
JSON.stringify({ error: "Unauthorized" }),
{ status: 401, headers: { "Content-Type": "application/json" } },
);
}
const url = new URL(ctx.req.url);
const questionId = url.searchParams.get("questionId");
const quizId = url.searchParams.get("quizId");
const resetAll = url.searchParams.get("all") === "true";
try {
if (resetAll) {
await brainDataClient.resetAllProgress(stateData.user_id);
} else if (quizId) {
await brainDataClient.resetQuizProgress(stateData.user_id, quizId);
} else if (questionId) {
// Mode is no longer needed - progress is per-question now
await brainDataClient.resetQuestionProgress(
stateData.user_id,
questionId,
);
} else {
return new Response(
JSON.stringify({ error: "Missing reset parameters" }),
{ status: 400, headers: { "Content-Type": "application/json" } },
);
}
return new Response(
JSON.stringify({ success: true }),
{ status: 200, headers: { "Content-Type": "application/json" } },
);
} catch (error) {
console.error("Error resetting brain progress:", error);
return new Response(
JSON.stringify({ error: "Failed to reset progress" }),
{ status: 500, headers: { "Content-Type": "application/json" } },
);
}
},
});