React 18 + Material UI front-end for the Online Exam API.
This is a clean rewrite of the original college-era project: a typed-feeling component layout, a centralised API client, an Auth context, and a refreshed Material design system.
- React 18 with
createRoot, React Router v6 - Centralised
axiosclient with auth interceptors AuthContext+useAuth()hook (login / register / logout / refresh)- Protected routes with redirects
- Custom Material UI theme (typography, palette, shape, components)
- Pages: Login / Register, Home (exam catalog), Exam (timed), Result
- Beautiful, modern UI: card-based dashboard, animated countdown, question navigator
- Tab-switch detection with a soft warning
- Auto-submit when the timer ends
- Tests with React Testing Library (Login flow, App routes, Question component, utils)
- Production-ready build (
npm run build)
online-exam-portal/
|-- public/
|-- src/
| |-- api/ axios client + per-resource APIs
| | |-- client.js
| | |-- authApi.js
| | |-- examApi.js
| | `-- submissionApi.js
| |-- components/
| | |-- common/ AppHeader, ProtectedRoute, ErrorBoundary, LoadingScreen
| | `-- exam/ Clock, Question, QuestionNavigator, Instructions
| |-- context/
| | `-- AuthContext.js
| |-- hooks/
| | `-- useCountdown.js
| |-- pages/
| | |-- LoginPage.js
| | |-- HomePage.js
| | |-- ExamPage.js
| | `-- ResultPage.js
| |-- routes/
| | `-- AppRoutes.js
| |-- theme/
| | `-- theme.js
| |-- utils/
| | |-- storage.js
| | `-- time.js
| |-- __tests__/ App, LoginPage, Question, utils
| |-- App.js
| |-- index.js createRoot entry
| `-- index.css
|-- .env.example
|-- package.json
`-- README.md
npm install --legacy-peer-deps
cp .env.example .env # set REACT_APP_API_BASE_URL
npm start # http://localhost:3000Make sure the API is running on
http://localhost:8081(or updateREACT_APP_API_BASE_URL).
Demo credentials seeded by the API:
| Role | Password | |
|---|---|---|
| admin | admin@example.com | Admin@12345 |
| student | student@example.com | Student@12345 |
| Command | Description |
|---|---|
npm start |
Run dev server with hot reload |
npm run build |
Production build |
npm test |
Run the Jest test suite |
npm run test:watch |
Run tests in watch mode |
src/api/client.js builds a single axios instance:
- Base URL from
REACT_APP_API_BASE_URL - Adds
Authorization: Bearer <token>fromlocalStorage - On 401 responses, clears the local session and redirects to
/login - Normalises errors into
{ message, status, details }
Each resource has a thin module (authApi, examApi, submissionApi) that returns plain objects.
LoginPagecallsauthApi.login(), stores the token + user viastorage.js.AuthContextrehydrates the user withauthApi.me()whenever the token changes.ProtectedRouteredirects unauthenticated users to/login(preserving the return path inlocation.state.from).
HomePagelists exams viaexamApi.list().- Clicking "Start exam" routes to
/exam/:examId. ExamPageloads exam + questions, shows a per-question card with a navigator and live countdown clock.useCountdowntriggers auto-submit when time runs out.- On submit, the result is sent to
/resultvia router state for an instant view.
src/theme/theme.js centralises colours, typography, shape, and per-component overrides. Tweak it once and every component in the portal follows.
MIT