Skip to content

SkeletonMan2k21/newrich-coding-challenge-node

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NestJS + React Coding Challenge

How to Run

Option A — locally

Backend

cd api
npm install
npm run start:dev
# API available at http://localhost:3001

Frontend

cd web
npm install
npm run dev
# UI available at http://localhost:3000
# Vite proxies /api/* → http://localhost:3001/* (strips the /api prefix)

Option B — Docker (dev containers)

docker compose up --build
# UI at http://localhost:3002
# API at http://localhost:3001

Both containers run dev servers with live reloading. The web container's Vite proxy is pointed at the api service via the BACKEND_URL environment variable set in docker-compose.yml.


How to Run Tests

Backend (Jest + ts-jest, 26 tests)

cd api
npm test
# or with coverage:
npm run test:cov

Frontend (Vitest + Testing Library, 19 tests)

cd web
npm test
# or in watch mode:
npm run test:watch

Assumptions

  • The dataset is small and static (in-memory), so all filtering and sorting is done server-side on every request rather than introducing a database. ItemsService.fetchItems() is intentionally async so the interface matches what an HttpService call to a real upstream would look like — swapping the stub for a live HTTP request requires no changes outside that method.
  • The active filter uses string values "true" / "false" / "all" over HTTP query params rather than a boolean, which is idiomatic for query strings and matches the original baseline intent.
  • Drag-and-drop reordering is a local UI concern only — it does not persist to the backend. A real implementation would need a PATCH endpoint to save the new order.
  • Category values (core, ops, growth) are treated as a known, finite set in the frontend dropdown. A production app would fetch distinct categories from the API.

Design Decisions

Backend

  • Feature modules (ItemsModule, HealthModule) rather than registering everything directly on AppModule. Each module is self-contained and independently testable.
  • DTO with class-validator (ListItemsQueryDto) replaces the original plain object type. The ValidationPipe with whitelist: true rejects invalid values and strips unknown properties at the framework boundary, so the service never receives bad input.
  • Typed sortBySORTABLE_FIELDS is a const tuple used to derive the SortField union type and the @IsIn validator. This makes the whitelist the single source of truth shared across runtime validation and TypeScript types.
  • getSortableValue removed — the original method used an unsafe as unknown as Record<string, ...> cast to allow arbitrary string keys. With SortField typed to keyof ItemRecord, item[sortField] is fully type-safe.
  • Two test levels: unit tests on ItemsService (fast, no framework overhead) and integration tests on ItemsController using @nestjs/testing + supertest to verify the full HTTP layer including validation responses.

Frontend

  • @dnd-kit for drag-and-drop. It is pointer- and keyboard-accessible, works well with React 19, and has no DOM manipulation side effects that complicate testing — unlike react-beautiful-dnd which requires a working getBoundingClientRect.
  • Vitest instead of Jest for frontend tests. It shares the same Vite config and transform pipeline, has native ESM support, and is significantly faster for a Vite-based project.
  • Server-side filtering and sorting on every fetch, debounced search input (300 ms). This keeps the frontend stateless with respect to data — the displayed list is always what the API returns, except for drag-and-drop reordering which is purely local.
  • Tailwind CSS for styling. Utility-first keeps component files self-contained and responsive layout (flex-col sm:flex-row) straightforward without a separate stylesheet.

Trade-offs

  • No persistence for drag order. The reordered list resets on the next fetch (filter/sort change). A PATCH /items/order endpoint with optimistic UI would be the right fix but is out of scope here.
  • Categories hardcoded in the frontend. Fetching distinct categories from the API would be more robust but adds a second request on load for marginal benefit given the fixed dataset.
  • No pagination. Acceptable for 6 items; would need a limit/offset or cursor strategy at scale.
  • ts-node-dev is used for the API dev server (--transpile-only skips type-checking on reload for speed; the TypeScript compiler still catches errors at build time and in-editor). Source directories are mounted as volumes so changes on the host reflect immediately without rebuilding the image.

What I Would Improve With More Time

  • Persist drag order — add a PATCH /items/order endpoint and an optimistic update in the frontend with rollback on error.
  • Type-checking on reloadts-node-dev --transpile-only skips full type checking for speed. A separate tsc --watch sidecar would surface type errors faster during development.
  • Dynamic category list — fetch categories from GET /items/categories or derive them from the items response.
  • E2E tests — add Playwright tests covering the full filter + sort + drag workflow against the running app.
  • OpenAPI / Swagger — add @nestjs/swagger decorators to generate API documentation automatically.
  • Error boundary in the frontend — wrap the app in a React error boundary for unexpected render errors separate from fetch errors.

About

Coding Challenge for Node.js + React

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • JavaScript 62.3%
  • TypeScript 36.0%
  • Other 1.7%