161 lines
4.9 KiB
TypeScript
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" } },
|
|
);
|
|
}
|
|
},
|
|
});
|