Skip to content

261 frontend build invite member ux with user search autocomplete#278

Merged
smattymatty merged 2 commits into
mainfrom
261-frontend-build-invite-member-ux-with-user-search-autocomplete
Feb 13, 2026
Merged

261 frontend build invite member ux with user search autocomplete#278
smattymatty merged 2 commits into
mainfrom
261-frontend-build-invite-member-ux-with-user-search-autocomplete

Conversation

@smattymatty

Copy link
Copy Markdown
Collaborator

Build Invite Member UX with User Search Autocomplete

Description

Replaces the placeholder "Coming Soon" invite modal with a fully functional invite flow. Teachers can now search for users by username or name, select a result from an autocomplete dropdown, pick a role, and send an invitation — all without leaving the course detail page.

Closes #261

Mandatory Checklist

  • I have read and followed the CONTRIBUTING.md
  • I have linked the related issue above
  • My branch is up to date with main
  • I have tested my changes locally
  • I have added or updated tests where applicable
  • I have not introduced any new linting errors
  • My commit messages are clear and descriptive
  • I have updated documentation if my changes affect public APIs, setup steps, or user-facing behavior

What Changed

New Files

src/types/users.types.ts

  • UserSearchResult — mirrors backend UserSearchSerializer with optional privacy-filtered fields (email, first_name, last_name, full_name)
  • UserSearchParams — query parameters (q, page, page_size)
  • UserSearchPaginatedResponse — standard DRF pagination shape (count, next, previous, results)

src/services/usersApi.ts

  • searchUsers(params) — GET /api/users/search/ with 10s timeout and getSafeErrorMessage error handling, matching the existing coursesApi pattern

src/components/common/UserSearchInput.tsx

Reusable autocomplete combobox component with:

  • Debounced search — 300ms debounce via existing useDebounce hook, minimum 2 characters
  • Race condition handlingcancelled flag pattern (same as useCourses.ts) prevents stale responses
  • Keyboard navigation — ArrowUp/Down to highlight, Enter to select, Escape to close dropdown
  • Accessibilityrole="combobox", aria-expanded, aria-activedescendant, role="listbox"/role="option" on dropdown items
  • Click-outside-to-closemousedown listener on document
  • Escape key layering — dropdown captures Escape with stopPropagation() when open, so the parent modal only receives Escape when the dropdown is closed
  • Privacy-safe rendering — shows only username when full_name is hidden by privacy settings
  • Selected user pill — displays username + full name with a clear (X) button
  • RTL support — all logical properties (start-/end-/ps-/pe-)

Modified Files

src/components/courses/InviteMemberModal.tsx (rewrite)

Full invite flow replacing the placeholder:

  • UserSearchInput for user selection
  • HardLoadSelect for role picker (student/assistant/teacher, defaults to student)
  • Submit button disabled until a user is selected, shows spinner during submission
  • Error messages displayed inline on submit failure
  • State resets when modal closes and reopens
  • Responsive: max-w-sm sm:max-w-md, flex-col-reverse sm:flex-row button layout
  • Props interface unchanged ({ isOpen, onClose, onSubmit }) — no changes needed to MembersTab.tsx

src/i18n/locales/en.json

Replaced old placeholder keys (comingSoon, userIdLabel, userIdPlaceholder) with new search UX keys: searchLabel, searchPlaceholder, searchResults, noResults, searchMinChars, searchError, selectedUser, clearSelection, cancel

src/i18n/locales/ar.json

Matching Arabic translations for all new keys

src/pages/__tests__/CourseDetailPage.test.tsx

Updated existing "opens invite modal" test to verify the search input and Send Invite button instead of the old "Coming Soon" text

New Test Files

src/services/__tests__/usersApi.test.ts (7 tests)

  • Searches with query parameter, pagination params, empty results, privacy-hidden fields, 400/500/network errors

src/components/common/__tests__/UserSearchInput.test.tsx (21 tests)

  • Rendering: input, label, selected pill, disabled state, error message
  • Search behavior: min chars guard, debounce timing, results display, no results, API error, privacy rendering
  • Selection: click to select, dropdown closes, clear button
  • Keyboard navigation: ArrowDown/Up highlight, wrap at boundaries, Enter to select, Escape to close
  • Click outside: closes dropdown
  • Accessibility: combobox role, aria-expanded, listbox role, option roles

src/components/courses/__tests__/InviteMemberModal.test.tsx (14 tests)

  • Rendering: hidden when closed, title, search + role selector, disabled submit button, cancel button
  • Full invite flow: search → select → pick role → submit succeeds, submit error shown, sending state
  • Close and reset: cancel, close button, state resets on reopen
  • Role selection: defaults to student, change to assistant/teacher

How to Test

  1. Start the app: make up or cd Frontend/EduLiteFrontend && npm run dev
  2. Log in as a teacher of any course
  3. Navigate to the course detail page → Members tab
  4. Click "Invite Member" button

Invite Flow

  • Type 1 character — should show "Type at least 2 characters to search" hint
  • Type 2+ characters — should show loading spinner, then results dropdown
  • Click a result — dropdown closes, selected user pill appears with username + full name
  • Click X on the pill — clears selection, input reappears
  • Change role dropdown to "Assistant" or "Teacher"
  • Click "Send Invite" — spinner on button, modal closes on success, toast appears
  • If user is already a member — error message shown inline, modal stays open

Keyboard Navigation

  • Type a search, then use ArrowDown/Up to highlight results
  • Press Enter to select the highlighted result
  • Press Escape to close dropdown (modal stays open)
  • Press Escape again to close modal

RTL Testing

  • Switch language to Arabic
  • Verify search icon on correct side, clear button on correct side
  • Dropdown items aligned properly
  • Button layout flows correctly

Run Tests

cd Frontend/EduLiteFrontend
npx tsc --noEmit    # No type errors
npm run lint        # No lint errors
npm run test        # 682 tests pass (33 files)
npx vite build      # Build succeeds

Screenshots (if applicable)

image image

@smattymatty smattymatty linked an issue Feb 13, 2026 that may be closed by this pull request
@vercel

vercel Bot commented Feb 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
edulite Ready Ready Preview, Comment Feb 13, 2026 0:54am

@github-actions

Copy link
Copy Markdown

PR Template Check

All checks passed.

@smattymatty smattymatty merged commit e7f1173 into main Feb 13, 2026
7 checks passed
@smattymatty smattymatty deleted the 261-frontend-build-invite-member-ux-with-user-search-autocomplete branch February 13, 2026 00:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FRONTEND] Build Invite Member UX with User Search Autocomplete

1 participant