Repository navigation
feat(web): add the daily quiz at /quiz - #234
a2751012962 wants to merge 1 commit into
Conversation
A per-student daily quiz built from each course's current Canvas progress, with a mistake bank that keeps missed questions coming back. - Canvas: UIUC does not issue student access tokens, so the new extensions/canvas-connect Chrome extension reads the current term in the student's own browser (GET only, sequential, 150 ms apart) and hands the page plain-text course digests. No Canvas credential reaches the Worker or the database. - Worker: /api/quiz/* (signed-in only; guests get 401 before any storage or DeepSeek call). One quiz per America/Chicago day: 8 new questions from a single DeepSeek call plus up to 4 open mistakes; a mistake closes after two correct answers in a row. Options are shuffled server-side. - Data: create_quiz_tables.sql adds quiz_courses, quiz_questions and quiz_daily with owner-only RLS; the Worker forwards the caller's token. - SPA: /quiz page, sidebar entry, and the extension download under public/downloads.
🚀 Deploying Preview to Cloudflare 🚀Preview Deployments by commit
|
|
React Doctor found 2 new issues in 2 files · 2 warnings · score 92 / 100 (Great) · 0 fixed · vs 2 warnings
Reviewed by React Doctor for commit |
| ) | ||
| } | ||
|
|
||
| export const QuizScreen: React.FC<QuizScreenProps> = ({ language }) => { |
There was a problem hiding this comment.
React Doctor · react-doctor/no-high-complexity-react-function (warning)
QuizScreen has cyclomatic complexity 15, cognitive complexity 22, and maximum nesting depth 4, so its React logic is hard to understand and change. Extract independent branches into components or hooks.
Fix → Extract independent render branches and state logic into focused components or hooks until the control flow is easy to follow.
|
|
||
| /** `YYYY-MM-DD` in Urbana-Champaign, so a quiz turns over at local midnight. */ | ||
| export function quizDate(now: Date): string { | ||
| return new Intl.DateTimeFormat("en-CA", { |
There was a problem hiding this comment.
React Doctor · react-doctor/js-hoist-intl (warning)
This is slow because new Intl.DateTimeFormat() rebuilds on every call inside a function, so move it to the top of the file, or wrap it in useMemo
Fix → Move new Intl.NumberFormat(...) to the top of the file or wrap it in useMemo. Building one is slow, so don't redo it on every call
What
A daily quiz at
iguide.chat/quiz: each signed-in student gets one quiz per day built from what their courses are covering right now on Canvas, plus a few questions they missed before.How Canvas data gets in
UIUC does not let students create Canvas access tokens, and the Worker should never hold a student's Canvas or NetID session. So a small Chrome extension (
extensions/canvas-connect) reads Canvas in the student's own browser with their normal Canvas sign-in:GETonly, one request at a time, 150 ms apart/quizpage plain-text digests, which the page uploads with the student's iGuide token (PUT /api/quiz/courses)No Canvas credential reaches the Worker or Supabase.
Worker:
/api/quiz/*GET /statusPUT /coursesPATCH /courses/:id{ enabled }POST /todayPOST /today/answers{ questionId, choice }; the first answer countsGET /mistakes401 SIGN_IN_REQUIREDbefore any storage or DeepSeek call, so no provider call is relayed without auth.deepseek-chat, JSON mode) plus up to 4 open mistakes. Explanations follow the site language.Data
apps/web/scripts/migrations/create_quiz_tables.sql(re-runnable) addsquiz_courses,quiz_questionsandquiz_daily. They are owner-only:anongets nothing,authenticatedgetsauth.uid() = user_idpolicies. The Worker uses the caller's own token, as with the dorm API; no service-role key.SPA
/quizpage (src/components/quiz/**,src/services/quizApi.ts), a sidebar entry, and the extension zip atpublic/downloads/iguide-canvas-connect.zip. With the extension installed, the page refreshes the course digests in the background at most every 20 hours (no tab opened); Connect Canvas / Sync now runs an interactive sync.Testing
node --test "worker/**/*.test.ts" "src/**/*.test.ts"(apps/web): 162/164 pass; the 2 failures are the knownloop.test.ts/loop.baseline.test.tspair from AGENTS.md. New:worker/quiz/service.test.ts(generation, daily reuse, mistake rules, upload validation, DeepSeek failure) andworker/routes/quiz.test.ts(guest 401).node --test extensions/canvas-connect/canvas.test.mjs: 6/6.vp buildpasses.vp checkreports only the 6 errors already onmaininpackages/dorm/scrapers/mapsScraper.ts.vp dev:/quizrenders with the sidebar entry and the sign-in prompt;GET /api/quiz/statusanswers 401 for a guest.Not yet verified end to end: reading a real UIUC Canvas account through the extension, real DeepSeek output, and writes against the real Supabase project. These need the migration applied and a signed-in run.
Rollout
create_quiz_tables.sqlin the Supabase SQL editor.DEEPSEEK_API_KEYis already set).extensions/canvas-connectunpacked in Chrome, sign in at/quiz, and click Connect Canvas.The extension's content script matches
iguide.chatandlocalhost:5173only, so aworkers.devpreview cannot talk to it.