Themes / CSS:
- Warm Brown theme: parchment cream background, dark brown navbar, Georgia serif font
beautiful and easy on eyes for reading medical content
- Default theme: slightly warmer bg, softer card shadows, 1200px container (less boxy)
- Navbar: sticky, height-fixed, overflow-x scroll on mobile (no wrapping), smaller text on mobile
- Mobile container: 14px padding for more space
Bug fixes:
- Login page: axios 401 interceptor no longer triggers window.location.href for auth endpoints
(was causing immediate page reload before error message was visible)
- Dashboard quizzes stat now shows distinct quizzes attempted (not created by user)
- PostgreSQL email collation: ALTER users.email to COLLATE "C" in migration
(prevents B-tree index corruption with en_US.utf8 locale causing user lookups to fail)
- get_current_user: verifies email on ALL protected endpoints, returns 403 with X-Unverified header
Frontend auto-logs out and redirects to /login where resend option is shown
DocumentDetailPage:
- Delete Section button with confirmation on each section row
- Create question category inline from dropdown (+ New button → prompt)
- Question Bank Category dropdown now shows question count
Dashboard:
- total_quizzes stat counts distinct attempted quizzes (not user-created quizzes)
Backend:
- DELETE /documents/{id}/sections/{section_id} endpoint added
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Question sharing (edits now propagate):
- quiz_question_links junction table: quizzes reference questions, not own copies
- Existing questions migrated to junction (idempotent ON CONFLICT DO NOTHING)
- from-bank and from-category create quiz by adding junction links (no copying)
- Editing a question via QuizEditPage or bank Edit modal updates the ONE record
visible in all quizzes that reference it
- Delete from quiz: only deletes Question record if no other quiz references it
- quiz_service: fixed position counter (was using len() incorrectly, now enumerate)
- question.quiz_id renamed to source_quiz_id in Python (DB column still quiz_id)
- All attempts/quizzes/search code updated to use junction helper or source_quiz_id
Bug fixes:
- PostgreSQL en_US.utf8 collation B-tree index corruption on users.email
Fixed by ALTERing column to COLLATE "C" in migration + immediate repair
- get_current_user now blocks unverified users on ALL endpoints (403 + X-Unverified header)
api/client.js intercepts X-Unverified=true and auto-logs out to /login
- Search (quiz + bank): correct_answer and explanation now included in matching_questions
so study modals work correctly
- Keyword search: order_by updated to use source_quiz_id
- Bulk category: changed from PATCH with body array to POST with Pydantic body
(fixes null category_id removal)
- Question bank: edit button added, answer highlighting removed from list view
- QuestionBankPage: Keyword/Semantic/Hybrid search toggle
- Login: login error message stays visible (removed immediate reload)
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- attempts.py: dashboard quiz_stats now queries by attempted quizzes not
created quizzes — regular users now see per-quiz breakdown correctly
- documents.py: moderators/admins can fetch documents by ID (were getting
404 despite seeing them in the list); also restrict section creation and
delete to moderators via require_moderator
- nextcloud.py: sanitise filename in Content-Disposition header (strip
quotes, backslashes, newlines to prevent header injection)
- UploadPage.jsx: importing from Nextcloud no longer switches tab to local,
preserving the selected-file info display
- ResultsPage.jsx: fill-blank correct answers now show correct-bg (green)
instead of always showing wrong-bg (red)
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- FastAPI backend with JWT auth, roles (admin/moderator/user)
- PDF upload (up to 500MB) with streaming, PyMuPDF text extraction
- ChromaDB vectorization per page with metadata
- LiteLLM AI question extraction from PDF (not generation)
- Image extraction from PDF pages, graceful fallback
- Quiz modes: timed (countdown timer) + learning (answers shown inline)
- Page-by-page question navigation with dot navigator
- TTS endpoint using LiteLLM (Google Vertex / OpenAI voices)
- Admin dashboard: AI model management per task, user role management
- Moderator role: upload PDFs, create sections, generate quizzes
- Spaced repetition reminders via SMTP email (SM-2 intervals)
- APScheduler daily reminder jobs
- Celery + Redis for background PDF processing
- React frontend with all pages
- Docker Compose deployment (nginx + backend + celery + redis)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>