This app was basis for my CS degree thesis which revolved around a problem when a driver chooses in a specific day some kind of vehicle to commute and at the parking lot finds that all parking spaces are already taken. As a result it needs to drive out and for unknown period of time trying to find a new spot.
Inherent problem here is that driver cannot know beforehand that he would not find a parking spot in a given time. Should he knew that he would not have to make a decision to use a vehicle to commute in a given day.
Most obvious solution was to create parking space reservation system.
SPS stands for Simple Parking System (I just needed a name).
- Admin
- Driver
- Parking clerk
- Add/Display parking lots
- Change lot hours of operation
- Change lot capacity
- Display drivers
- Assign (or remove assignment) a driver to a parking lot
- Change user role
- Find a reservation based on a license plate
- Issue parking ticket
- Take in returned ticket
- Add vehicle (as a base for a reservation)
- Display assigned parking lots
- Request access to a lot (TODO)
- Make reservation
- Display reservation(s)
- Confirm reservation
- Cancel reservation
- Edit time of a reservation (as long as it's not confirmed/cancelled/past)
- backend (aka API)
- frontend
Domain holds the actual logic for handling use cases, and defines abstractions which are then implented in the outer layers (of the onion).
Application defines services, finders and DTOs (Commands, Queries). Services handles Commands by usually fetching domain object from respository, calls a method on it and gives it back for save to repository. Finders are just abstractions which operates on Queries.
Infrastructure handles REST requestes, email sending, authorization, authentication, CSRF Tokens, users etc. All flow comes through controllers which either uses finder to handle Query or service to handle Commands.
Persistence implements repositories, user store (from Infrastructure) and finders.
On frontend there are modules for dashboards for each type of user together with error module and auth module.
Core module has logic related to handling state and returning state slices, api facades, guards and interceptors and some pipes and model.
Share module mainly stores shared components.
Smart components fetches data from store by using selectors and dispatches actions. Dumb components just display the data.
- Angular
- NgXS
- Material
- Netlify
- NestJS
- PostgreSQL
- Prisma
- Docker
- Fly.io
- Doppler
- Mailgun
- Setup Google authentication, and get client ID & client secret
- Setup Mailgun account
- Setup Bcrypt
console.log(require('bcrypt').genSaltSync(10));
- Generate secrets for JWT token, refresh token & CSRF Token
const crypto = require('crypto');
[...Array(3)].map(() => crypto.randomBytes(64).toString('base64'))
- Put those into .env.example file in /api
- Create Doppler account on https://doppler.com, and install Doppler CLI: https://docs.doppler.com/docs/install-cli.
- Put those env vars into Doppler
- Generate Doppler token for local env access
- Set Doppler env var
EXPORT DOPPLER_TOKEN=someTokenValue
- Install deps in api & frontend by:
yarn --frozen-lockfile
- Install doppler cli
cd aio
chmod +x infra-up.sh
./infra-up.sh
cd api
doppler run -- yarn prisma migrate dev
cd api && yarn start:debug
cd frontend && yarn start
Users to log in to be found in api/prisma/seed.ts
- Request for parking access handling (driver->admin)
- Reservations details - admin
- Add flag to reservations dto if time has been exceeded -> blocking user
- Clear store on logout
- Bug - ongoing reservations not visible
- Bug - allows adding multiple reservations for the same license plate