├── backend/
│ ├── api/
│ │ ├── src/
│ │ │ ├── convert.py # coords and model conversion
│ │ │ ├── crud.py # DB ORM accessors
│ │ │ ├── db.py # DB connector
│ │ │ ├── main.py # FastAPI web server entry point, HTTP->CRUD controller
│ │ │ ├── models.py # DB ORM model
│ │ │ └── schemas.py # HTTP request/response schemas (model representations)
│ │ ├── Dockerfile
│ │ ├── poetry.lock
│ │ ├── pyproject.toml
│ │ ├── setup.cfg
│ │ └── wait-for-postgres.sh # script to delay API entry command until DB is ready
│ ├── .env # DB credentials
│ └── docker-compose.yml
├── frontend/
│ ├── public/
│ │ └── index.html
│ ├── src/
│ │ ├── api/
│ │ │ └── waypoints.ts # API bindings
│ │ ├── components/ # React components
│ │ │ ├── App.tsx # collection manager (main component)
│ │ │ ├── Map.tsx # map/marker manager
│ │ │ ├── MarkerPopup.tsx # popup content for static render
│ │ │ ├── Sidebar.tsx # item list, event handler proxy
│ │ │ └── WaypointItem.tsx # editable/removable list item
│ │ ├── map/ # Leaflet objects
│ │ │ ├── InfoBox.ts # top-right message
│ │ │ ├── WaypointMarker.ts # extends marker to attach data
│ │ │ └── map.ts # map initializer
│ │ ├── models/
│ │ │ └── waypoint.ts # TS interface
│ │ ├── styles/ # body CSS and Sass consts to import in component styles
│ │ ├── utils/
│ │ │ ├── convert.ts # formatters
│ │ │ ├── http.ts # fetch() wrappers
│ │ │ └── list.ts # collection manipulation (immutable)
│ │ ├── config.ts # env vars and map config
│ │ └── index.tsx # app entry point
│ ├── .env # API root URL and Mapbox token
│ ├── package-lock.json
│ ├── package.json
│ └── tsconfig.json
├── README.md
└── assignment.md
GET /waypoints/ Get Waypoint List (latest to earliest)
GET /waypoints/{id} Get Waypoint
POST /waypoints/ Create Waypoint (name and coords)
POST /waypoints/{id} Update Waypoint (name only)
DELETE /waypoints/{id} Delete Waypoint
- Repeated worlds are not supported:
- Backend:
lat in [-90, 90]
, lng in [-180, 180]
validation is applied.
- Frontend: no coords wrapping, no markers duplication (default Leaflet behavior).
- Frontend is not containerized, since:
- Serving prod-bundled static files doesn't require a runtime.
- Platform-specific differences in build tools binaries don't affect the bundle.
- There's no CI/CD.
- Credentials are stored in
.env
files, no specific secrets-management.
- Stricter validation, allowing only specified fields.
- Mount a volume to persist DB files.
- Mount a volume to keep/rotate/stream logs, set up more elaborated logging (other than default FastAPI one).
- Set up centralized error reporting, monitoring (other than default Docker tooling) and auto-recovery.
- Functional tests against HTTP methods (with mocked DB).
- Pagination for
GET /waypoints/
(already supported by the API).
- Color-code markers depending on waypoint state: editing, failed to create/update/delete.
- Interactivity between sidebar items and map markers, as they represent same waypoints:
- Highlight on hover:
- Marker hover: change sidebar item background color.
- Sidebar item hover: enlarge the marker.
- Select on click:
- Marker click: scroll the sidebar list to the corresponding item.
- Sidebar item click: reposition the map on the marker, if it was outside of the viewport.
- More elaborated error handling and reporting, to distinguish and reflect in UI:
- Network unavailability.
- Non-2xx API responses.
- JSON parsing errors.
- Offline mode, allowing to manage waypoint collection locally until network/API becomes available.
- Vertical layout split for smaller screens in portrait mode.
- Storybook stories, component tests, functional tests (with mocked API).
- SQL engine/dialect: PostgreSQL
- spatial extension: PostGIS (an overkill for current case, but enables geometry-based queries/computations to further extend the API)
# assumes Docker version "20.10.12"
$ cd ./backend/ # contains ".env" file for docker-compose
$ poetry install # for local development, since "./api/src:/home/src" are mount via docker-compose
$ docker-compose up
# $ docker-compose up --build
# visit http://localhost:8000/docs for Swagger UI
$ docker logs -f <container-id>
$ docker-compose ps -a
$ docker-compose down
$ docker image prune
$ docker-compose exec db psql waypoints postgres
$ docker-compose exec db pg_dump waypoints -U postgres
# lint
$ docker-compose run api poetry run pycodestyle --show-source ./src/
# unit tests
$ docker-compose run api poetry run pytest ./src/
# assumes Node version "17.5.0" and NPM version "8.4.1"
$ cd ./frontend/
$ npm ci # install deps
$ npm run lint # lint TS and Sass
$ npm test # run unit tests
$ npm start # run a local CRA dev server
$ npm run build # produce a build artifact
$ npm run serve # run a local Python web server in "./build/"
- For layout responsiveness.
- Against backend unavailability/failures and slow network.
- Lighthouse reports, including accessibility recommendations.