Claiming This Task
Before you start working, check the Assignees section. If no one is assigned, leave a comment claiming the issue and assign it to yourself. This prevents duplicate work.
See the Community Wiki for contributing guidelines and git workflow.
Problem
The Course Detail Page's "Add Module" modal currently shows a "coming soon" placeholder. We need a proper UX that lets teachers select a module type and then search for / pick content to attach to their course.
The old modal asked for raw content_type and object_id fields — completely unusable. The new flow should feel intuitive: pick a type, search for content, select it, done.
Requirements
Step 1: Module Type Selection
- Type picker screen — when the modal opens, show a grid/list of available module types:
- Slideshow (icon + label) — the first and currently only supported type
- Future types (Quiz, Notes, Assignment, etc.) can be shown as disabled/greyed "coming soon" cards
- Clicking a type moves to the search screen for that type
Step 2: Search & Select Content (Slideshow)
- Search input — debounced text input (300ms) that queries
GET /api/slideshows/search/?q=<query>&mine=true (searches user's own slideshows)
- Toggle: "My Slideshows" / "All Slideshows" — lets teachers switch between searching their own slideshows and all public slideshows
- Results list — show title, description (truncated), visibility badge, published status for each slideshow
- Selecting a slideshow — clicking a result selects it, showing its title in a confirmation view
- Module title — optional text input for the module title (defaults to the slideshow title)
Step 3: Confirm & Add
- Add button — calls the existing
addModule(courseId, data) API from coursesApi.ts with the correct content_type and object_id
- Back button — go back to type selection or search
- Success — close modal and refresh the modules list
General
- Dark mode — full dark mode support matching the existing glass-morphism styling
- Responsive — works on mobile with touch-friendly list items
- Error handling — show errors inline (module already exists, slideshow not found, etc.)
- Empty state — if no slideshows found, show a helpful message ("No slideshows found. Create one first!")
Architecture Context
- The modal lives at
src/components/courses/AddModuleModal.tsx and is rendered from ModulesTab.tsx
- It uses
createPortal(... , document.body) to escape the backdrop-blur container
- The existing
coursesApi.ts already has addModule() for creating modules
- The
content_type value for slideshows needs to be resolved — either hardcode the Django ContentType ID or add a lookup. The backend accepts content_type as the ContentType model ID. Consider adding a GET /api/courses/module-types/ endpoint (separate backend issue) or looking it up from content_type app_label/model.
- Consider building the search/select as a step-based flow within the modal (type → search → confirm)
API Dependencies
Needs to be built first (separate backend issue):
GET /api/slideshows/search/?q=<query> — text search across title/description, with visibility filtering and pagination. Supports mine=true filter.
Already built:
GET /api/slideshows/?mine=true — can be used as a fallback for listing user's slideshows (no text search, but has filtering)
POST /api/courses/<id>/modules/ — creates a module (already wired in coursesApi.ts)
ContentType resolution:
The addModule call needs a content_type ID (Django's ContentType PK for the Slideshow model). Options:
- Backend provides a
GET /api/courses/module-types/ endpoint returning supported types with their content_type IDs (cleanest, but needs backend work)
- Hardcode the content_type ID (fragile across environments)
- Use
GET /api/content-types/?app_label=slideshows&model=slideshow if such an endpoint exists (it doesn't currently)
Recommendation: Option 1 is cleanest long-term but adds backend scope. For an MVP, the backend could accept app_label + model strings instead of a raw content_type ID in the module creation endpoint — that's a small backend change worth considering.
Files to be Altered
src/components/courses/AddModuleModal.tsx — replace placeholder with multi-step type selection + search + confirm flow
src/services/slideshowApi.ts — add function for slideshow search endpoint (or extend existing)
src/types/slideshows.types.ts — TypeScript types for slideshow search results (if not existing)
src/i18n/locales/en.json — add module modal translations (type labels, search placeholder, empty state, etc.)
src/i18n/locales/ar.json — Arabic translations
Testing Requirements
- Unit tests for
AddModuleModal (type selection → search → select → confirm flow)
- Test the debounced search behavior (verify API not called on every keystroke)
- Test "My Slideshows" vs "All Slideshows" toggle
- Test empty state when no results found
- Test error handling (API failure, module already attached)
- Manual: verify dark mode and mobile responsiveness
- Manual: verify the full flow end-to-end with a real backend
Additional Context (Optional)
- Depends on: Backend slideshow search API issue (must be built first for text search, but the existing list endpoint with
?mine=true filtering can be used for an initial version)
- The
CourseModule model uses Django's GenericForeignKey, so it can link to any model — the type selection UI is designed to scale as new content types are added
- The slideshow list endpoint already returns a lightweight serializer (
SlideshowListSerializer) with title, description, visibility, subject, language, country, is_published — perfect for search results
- Consider caching the content_type ID resolution to avoid repeated lookups
Claiming This Task
Before you start working, check the Assignees section. If no one is assigned, leave a comment claiming the issue and assign it to yourself. This prevents duplicate work.
See the Community Wiki for contributing guidelines and git workflow.
Problem
The Course Detail Page's "Add Module" modal currently shows a "coming soon" placeholder. We need a proper UX that lets teachers select a module type and then search for / pick content to attach to their course.
The old modal asked for raw
content_typeandobject_idfields — completely unusable. The new flow should feel intuitive: pick a type, search for content, select it, done.Requirements
Step 1: Module Type Selection
Step 2: Search & Select Content (Slideshow)
GET /api/slideshows/search/?q=<query>&mine=true(searches user's own slideshows)Step 3: Confirm & Add
addModule(courseId, data)API fromcoursesApi.tswith the correctcontent_typeandobject_idGeneral
Architecture Context
src/components/courses/AddModuleModal.tsxand is rendered fromModulesTab.tsxcreatePortal(... , document.body)to escape thebackdrop-blurcontainercoursesApi.tsalready hasaddModule()for creating modulescontent_typevalue for slideshows needs to be resolved — either hardcode the DjangoContentTypeID or add a lookup. The backend acceptscontent_typeas the ContentType model ID. Consider adding aGET /api/courses/module-types/endpoint (separate backend issue) or looking it up fromcontent_typeapp_label/model.API Dependencies
Needs to be built first (separate backend issue):
GET /api/slideshows/search/?q=<query>— text search across title/description, with visibility filtering and pagination. Supportsmine=truefilter.Already built:
GET /api/slideshows/?mine=true— can be used as a fallback for listing user's slideshows (no text search, but has filtering)POST /api/courses/<id>/modules/— creates a module (already wired incoursesApi.ts)ContentType resolution:
The
addModulecall needs acontent_typeID (Django's ContentType PK for the Slideshow model). Options:GET /api/courses/module-types/endpoint returning supported types with their content_type IDs (cleanest, but needs backend work)GET /api/content-types/?app_label=slideshows&model=slideshowif such an endpoint exists (it doesn't currently)Recommendation: Option 1 is cleanest long-term but adds backend scope. For an MVP, the backend could accept
app_label+modelstrings instead of a raw content_type ID in the module creation endpoint — that's a small backend change worth considering.Files to be Altered
src/components/courses/AddModuleModal.tsx— replace placeholder with multi-step type selection + search + confirm flowsrc/services/slideshowApi.ts— add function for slideshow search endpoint (or extend existing)src/types/slideshows.types.ts— TypeScript types for slideshow search results (if not existing)src/i18n/locales/en.json— add module modal translations (type labels, search placeholder, empty state, etc.)src/i18n/locales/ar.json— Arabic translationsTesting Requirements
AddModuleModal(type selection → search → select → confirm flow)Additional Context (Optional)
?mine=truefiltering can be used for an initial version)CourseModulemodel uses Django'sGenericForeignKey, so it can link to any model — the type selection UI is designed to scale as new content types are addedSlideshowListSerializer) with title, description, visibility, subject, language, country, is_published — perfect for search results