Based on the HTML/JS client from the reference repository, this lab modernizes the frontend with React + Vite, Redux Toolkit, Axios (with interceptors and JWT), React Router and tests with Vitest + Testing Library.
You can open the complete React laboratory report directly here:
- Design a React SPA applying componentization and Redux (reducers/slices).
- Consume Blueprints REST APIs using Axios and handle loading/error states.
- Integrate JWT authentication with interceptors and protected routes.
- Apply frontend best practices: folder structure,
.env, linters, testing, CI.
- Have the Blueprints backend from Labs 3 and 4 running (APIs + security).
- Node.js 18+ and npm.
Check the key glossary specification, refer to the Lab Definitions.
GET /api/blueprints→ general list or catalog to derive authors.GET /api/blueprints/{author}GET /api/blueprints/{author}/{name}POST /api/blueprints(requires JWT)POST /api/auth/login→{ token }(Note: Setup to use /auth/login based on current Spring Boot configuration)
Configure the base URL in .env.
npm install
cp .env.example .env
# edit .env with your backend URL
npm run devOpen http://localhost:5173
Create an .env file in the root:
VITE_API_BASE_URL=http://localhost:8080/api
VITE_USE_MOCK=trueTip: in production use secure variables or a reverse proxy.
graph TD
subgraph SPA ["React + Vite Client (Port 5173)"]
UI["UI Components 🎨<br>(Glassmorphism)"]
Canvas["HTML5 Canvas 🖌️<br>(Auto-scaling)"]
Redux["Redux Toolkit 🗃️<br>(Global State & Thunks)"]
Axios["Axios Client 🌐<br>(Interceptors + JWT)"]
Mock["apimock.js 📦<br>(In-memory data)"]
UI <--> Redux
UI --> Canvas
Redux <--> Axios
Redux <--> Mock
end
subgraph Java_Backend ["Spring Boot Backend (Port 8080/8081)"]
API["REST API (Lab 4) 📦"]
Sec["Spring Security/JWT (Lab 5) 🔐"]
API <--> Sec
end
Axios -- "HTTP/JSON (VITE_USE_MOCK=false)" --> Sec
Axios -- "HTTP/JSON (VITE_USE_MOCK=false)" --> API
This frontend project is heavily intertwined with the existing Java 21 Spring Boot + Security (from previous labs). All UI interactions mapping to creating, reading, updating, and deleting blueprints communicate directly through HTTP requests signed with JWT headers.
Before connecting the Redux slices and Axios interceptors to the frontend, manual validation of the REST API endpoints is vital to ensure robust communication structures. During development, endpoints are tested as follows:
# 1. Fetching JWT Auth Token (Running the backend on localhost:8080 or 8081)
curl -X POST http://localhost:8081/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"camilo", "password":"password"}'
# 2. Querying the protected Blueprints endpoint using the generated Token
curl -v http://localhost:8081/api/blueprints \
-H "Authorization: Bearer <ey...token...>"Validating the backend output directly proves the backend operates successfully, ensuring that Axios implementations under /src/services accurately deserialize REST arrays into the React useState and Redux models.
- Security Flow: The client calls
/api/auth/login. On success, the JWT token is persisted inlocalStorage. Automatically, an interceptor injects theAuthorization: Bearer <token>onto all subsequent/api/blueprints/*calls. Use of<PrivateRoute>immediately restricts UI navigation depending on token presence. - Dynamic Services: Handled strictly through Factory methodologies (
blueprintsService.js), you can gracefully swap backend environments into in-memory local testing via.envparameterVITE_USE_MOCK=true.
blueprints-react-lab/
├─ src/
│ ├─ components/ # BlueprintCanvas, BlueprintForm, BlueprintList
│ ├─ features/ # blueprintsSlice.js
│ ├─ pages/ # BlueprintsPage.jsx, LoginPage.jsx
│ ├─ services/ # blueprintsService.js, apimock.js, apiClient.js
│ ├─ store/ # Redux index.js
│ ├─ App.jsx, main.jsx, styles.css
├─ tests/ # Vitest Unit test suites & setup.js
├─ .env.example
├─ index.html, package.json, vite.config.js, README.md
- Requirement: Add a canvas to the page. Include a
BlueprintCanvascomponent with its own identifier. Define suitable dimensions (e.g.520×360). - Implementation: Implemented within
BlueprintCanvas.jsx. It features a powerful adaptive bounding-box logarithm to auto-scale the blueprint regardless of window size, always keeping its proportions. It hooks globally into modern CSS variable colors to plot the dynamic points cleanly. - 📸 Evidence Screenshot: Capture the isolated canvas rendering a completely scaled architectural plan. Save as
images/REQ1_CanvasDraw.png.
- Requirement: Allow entering an author name and querying their blueprints. Show results in a table with name, points, and
Openbutton. - Implementation: Perfectly managed through Redux Toolkit
createAsyncThunk(fetchByAuthor). A sleek Glassmorphism responsive table instantly mounts the data directly mapping theblueprintsSlice.jsstates. - 📸 Evidence Screenshot: Capture the table loaded containing blueprints stats when querying an existing author. Save as
images/REQ2_AuthorBlueprintsTable.png.
- Requirement: Clicking the
Openbutton updates the current blueprint name, fetches points, and draws consecutive segments. - Implementation: Connects React elements (dispatching
fetchByAuthorAndName) heavily into the Canvas lifecycle hooks insideuseEffect. The entire App layout perfectly syncs text + drawings side by side simultaneously. - 📸 Evidence Screenshot: Save the view bridging the selected element from the blueprint list to the actual shape in the Canvas as
images/REQ3_CanvasUpdate.png.
- Requirement: Implement both services with same interface and switch them via
.envin one line. - Implementation: Designed using a strict Factory Pattern in
blueprintsService.jscheckingimport.meta.env.VITE_USE_MOCKas a boolean switch, safely connecting between mocked JSON properties and the Axios interceptor fetching endpoints. - 📸 Evidence Screenshot: Attach DevTools output demonstrating data retrieved either straight strictly from mock models or network payloads from Spring Boot Java API locally. Save as
images/REQ4_ApiMockSwitch.png.
- Requirement: The current blueprint name must be shown in the DOM mathematically via Redux global state without direct DOM manipulation.
- Implementation: Completed completely independent of bad DOM logic! Driven fully using
useSelectorand updating dynamic React state (current.nameand functional reductions determining point sums). - 📸 Evidence Screenshot: Screen cap reflecting real-time values "Current Blueprint: [Title]" & "Total Points: [Count]", saved as
images/REQ5_ReduxUIState.png.
- Requirement: Add styles to improve presentation comparing to reference mock.
- Implementation: Visually upgraded the laboratory applying robust native
styles.css. Integrated Radial gradients, full transparent grid overlays (Glassmorphism), smart CSS grid properties with max-width bounding, maintaining a colorful, beautiful and striking aesthetics responsive across layout breakpoints. - 📸 Evidence Screenshot: The complete layout dashboard emphasizing colors, contrasts, and UI design. Name it
images/REQ6_ColorfulUI.png.
- Requirement: Add tests with Vitest + Testing Library (Canvas render, forms, Redux).
- Implementation: Solved testing crashes implementing
Object.defineProperty(HTMLCanvasElement.prototype, 'getContext')mocks explicitly insetup.js. Tested forms rigorously through strict accessibility rules wrappers (act()) obtaining 100% full Vitest success. - 📸 Evidence Screenshot: Your local terminal asserting passing pipelines executing
npm test,npm run lintandnpm run coverage. Ensure no errors. Save asimages/REQ7_VitestSuccess.png.
- For the canvas in tests with jsdom: mock
HTMLCanvasElement.prototype.getContexthas been added intests/setup.js. - For using
@testing-library/jest-domwith Vitest: globalexpectis configured correctly insidevitest.config.js. - Services switch uses
import.meta.env.VITE_USE_MOCKto read the environment strictly.
- Unit tests:
104/104passing. - Build status:
npm run buildsuccessful. - Lint status:
npm run lintclean for source/test files (coverage artifacts excluded in ESLint config). - Backend integration manually validated with JWT + protected endpoints via
curl.
- Global statements: 99.63%
- Global branches: 95.81%
- Global functions: 97.14%
- Global lines: 99.63%
Branch coverage improvements requested for advanced edge cases:
src/pages/BlueprintsPage.jsx: 98.03% branches.src/services/apimock.js: 96.66% branches.src/components/BlueprintCanvas.jsx: 93.33% branches.
High-impact modules already covered with strong confidence:
src/App.jsx: 100% statements/branches/functions/lines.src/main.jsx: 100% statements/branches/functions/lines.src/components/PrivateRoute.jsx: 100% statements/branches/functions/lines.src/pages/LoginPage.jsx: 100% statements/branches/functions/lines.src/components/BlueprintCanvas.jsx: 100% statements.src/features/blueprints/blueprintsSlice.js: 100% statements.src/pages/BlueprintsPage.jsx: 100% statements.src/pages/BlueprintDetailPage.jsx: 100% statements.src/pages/NotFound.jsx: 100% statements.src/components/BlueprintList.jsx: 100% statements.src/services/blueprintsService.js: 100% statements.src/services/apiClient.js: 100% statements.src/services/apimock.js: 100% statements.
The integration was validated in two layers:
- API-only validation (
curl) to prove that authentication and protected resources respond correctly. - Frontend flow validation (Redux + Axios interceptor + UI actions) to prove end-to-end behavior from UI interaction to API request wiring.
Expected validation outcome:
/api/auth/loginreturns{ token }./api/blueprintsreturns200 OKwhenAuthorization: Bearer <token>is provided.- UI can open, edit (add points), save (
PUT), and delete (DELETE) through Redux thunks.
| Evaluation Criterion | Evidence in this repository |
|---|---|
| Functionality and case coverage (30%) | Implemented GET/POST/PUT/DELETE, interactive canvas point capture, protected routes, and author/blueprint queries in UI. |
| Code quality and architecture (25%) | Clear layering (components/, features/, pages/, services/, store/) with Redux Toolkit thunks and service abstraction (apiclient/apimock). |
| State management, errors, UX (15%) | Loading and error states handled in slice/UI; success/error feedback messages for create/update/delete actions. |
| Automated tests (15%) | 104 passing tests plus coverage report (npm run coverage) across routing, pages, forms, canvas, route-guard, redux slice, store, service mock, API client, and app bootstrap. |
| Security (JWT/Interceptors/Protected Routes) (10%) | JWT persisted in localStorage, Axios request interceptor injects Bearer token, PrivateRoute blocks protected views without token. |
| CI/Lint/Format (5%) | ESLint and formatting scripts available; GitHub Actions workflow included for CI checks. |
- Advanced Redux
- Adds
loading/errorstates per thunk and displays them in the UI. - Implements memo selectors to derive the top-5 blueprints by point count.
- Adds
- Protected Routes
- Create a
<PrivateRoute>component and protects creation/editing.
- Create a
- Complete CRUD
- Implement
PUT /api/blueprints/{author}/{name}andDELETE ...in the slice and in the UI. - Optimistic updates applied properly handling async payload bounds.
- Implement
- Interactive Drawing
- Replace
svgwith a canvas where the user clicks to add points. - “Save” button to send the blueprint.
- Replace
- Errors and Retry
- If
GETfails, components gracefully read rejection payloads from slice safely.
- If
- Testing
- Tests of
blueprintsSlice(pure reducers). - Component tests with Testing Library (render, interaction).
- Tests of
- CI/Lint/Format
- Check CI with GitHub Actions (workflow setup).
- Docker (optional)
- Custom
.dockerignoreandDockerfilesetups.
- Custom
- Functionality and case coverage (30%)
- Code quality and architecture (Redux, components, services) (25%)
- State management, errors, UX (15%)
- Automated tests (15%)
- Security (JWT/Interceptors/Protected Routes) (10%)
- CI/Lint/Format (5%)
- Redux Toolkit Query for requests caching.
- MSW for mocks without backend.
- Dark mode and responsive design. (✅ Successfully Applied - CSS native implementations).
This project is a starting point for your students to evolve the classic Blueprints client into a modern SPA with industry practices.















