feat: intern batch self-selection onboarding screen
Description
Display a batch selection screen when an intern logs in for the first time and
has no batch_id assigned. The screen fetches available batches from
GET /api/batches/, lets the intern pick one, and persists the choice via
PATCH /api/me/batch. After selection, the profile is re-fetched and the
intern proceeds to the main app.
Related Issue
Closes #
Type of Change
-
New feature (non-breaking change which adds functionality) -
Bug fix (non-breaking change which fixes an issue) -
Breaking change (fix or feature that would cause existing functionality to not work as expected) -
Documentation update
Changes Made
| File | Change |
|---|---|
src/api/index.ts |
Added setMyBatch() — calls PATCH /api/me/batch
|
src/contexts/AuthContext.tsx |
Exposed refetchMe() so the app can re-fetch the user profile after batch selection |
src/components/auth/BatchSelectionPage.tsx |
New component — full-screen batch picker with radio buttons, loading/error/empty states |
src/App.tsx |
Added guard: if authenticated intern has batchId == null, renders BatchSelectionPage instead of the main app |
Component: BatchSelectionPage
- Loading state: Shows "Loading batches…" while fetching
- Empty state: "No batches are available yet. Ask an admin to create one."
- Error state: Displays the API error message inline
- Selection state: Radio-button list with visual highlight for selected batch
-
Success flow: Calls
setMyBatch()→refetchMe()→ component disappears → main app renders - Reuses the existing
.portal-login-page/.portal-login-shellCSS classes fromCorpusLoginPage
How It Works
-
App.tsxchecks:role === 'intern' && batchId === null→ rendersBatchSelectionPage -
BatchSelectionPagemounts → callsgetBatches()→ renders radio buttons - Intern picks a batch → clicks "Confirm Selection"
- Calls
setMyBatch(batchId)→PATCH /api/me/batch - On success → calls
refetchMe()→ auth context updates →batchIdis no longer null -
App.tsxre-renders →BatchSelectionPageis hidden → main app shown
How Has This Been Tested?
-
TypeScript compiles clean: tsc --noEmit— zero errors -
Vite production build succeeds: 452 KB JS, 48 KB CSS -
Manual testing with backend running locally -
End-to-end test: login → batch selection → standup workspace
Screenshots (if appropriate)
Checklist
-
My code follows the project's coding conventions -
I have performed a self-review of my own code -
I have commented my code where necessary -
I have added corresponding tests (if applicable) -
My changes generate no new TypeScript errors or warnings -
The production build completes without errors
Companion MR
-
Backend:
intern-activity-tracker→ MR title:feat: intern batch self-selection endpoint and service -
Branch:
feat/intern-batch-self-selectionin both repos
Semantic Versioning Impact
-
Patch -
Minor -
Major
Reviewer Notes
-
BatchResponsecount fields (team_count,member_count) are nownullin the intern response from the backend. TheBatchSelectionPageonly readsid,name, anddate— it does not display counts — so this change has no impact on this component. - The
AuthContext.refetchMe()addition is minimal — it simply exposes the existinguseQuery.refetch(). No new state handling is required.