https://github.com/willsams/example-js-react-with-python
JavaScript + Python full stack example application using React + Redux Sagas for the frontend and a GraphQL API backend using FastAPI + AsyncPG.
https://github.com/willsams/example-js-react-with-python
ariadne asyncpg bootstrap4 direnv docker fastapi graphql jwt-authorization knexjs nodejs nvm postgresql pytest pytest-mock python reactjs redux-sagas
Last synced: 2 months ago
JSON representation
JavaScript + Python full stack example application using React + Redux Sagas for the frontend and a GraphQL API backend using FastAPI + AsyncPG.
- Host: GitHub
- URL: https://github.com/willsams/example-js-react-with-python
- Owner: WillSams
- License: other
- Created: 2024-01-11T21:26:39.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-02-24T14:58:46.000Z (3 months ago)
- Last Synced: 2025-03-29T04:32:18.218Z (2 months ago)
- Topics: ariadne, asyncpg, bootstrap4, direnv, docker, fastapi, graphql, jwt-authorization, knexjs, nodejs, nvm, postgresql, pytest, pytest-mock, python, reactjs, redux-sagas
- Language: JavaScript
- Homepage:
- Size: 3.04 MB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 20
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# Hotel Reservation React + Redux Sagas Example - JavaScript/Python
**JavaScript, Vite, Reactjs, Redux Toolkit, Redux Sagas, Python, FastAPI, GraphQL, AsyncPG, Postgres**
[](https://github.com/WillSams/eexample-js-react-with-python/actions/workflows/pr-validate.yml)
This example contains a frontend and backend:
- The frontend is a [React](https://react.dev) application using [Bootstrap4](https://getbootstrap.com/docs/4.6/getting-started/introduction/) for view designs.
- The backend is a [GraphQL API](https://graphql.org) providing the ability to create, delete, and list reservatios plus available rooms for a given date range.React [Typescript](https://github.com/WillSams/example-ts-react-with-python) and [Express MVC](https://github.com/WillSams/example-mvc-expressjs-with-python) versions of this same idea are available.
An [abandoned](https://github.com/WillSams/example-mvc-expressjs-with-python/tree/abandoned) branch for the previous version of this repository includes the usage of TortoiseORM.
**Context**:
- When a room is reserved, it cannot be reserved by another guest on overlapping dates.
- Whenever there are multiple available rooms for a request, the room with the lower final price is assigned.
- Whenever a request is made for a single room, a double bed room may be assigned (if no single is available?).
- Smokers are not placed in non-smoking rooms.
- Non-smokers are not placed in allowed smoking rooms.
- Final price for reservations are determined by daily price * num of days requested, plus the cleaning fee.**Web UI Usage**:

**API Usage**:
Example usage via [curl](https://curl.se/download.html):
```bash
# First, grab an access token provided by the API
ACCESS_TOKEN=$(curl -s -X POST \
-H 'accept: application/json' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=password&username=example-user&password=example-user' \
"http://localhost:$RESERVATION_PORT/development/token" | jq -r '.access_token')# List all existing booked reservations
curl http://localhost:$RESERVATION_PORT/development/graphql \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-d '{"query": "query { getAllReservations { reservations { room_id checkin_date checkout_date } } }"}'# Create a new reservation
# Note: if there is an overlap, you'll see a
# 'Reservation dates overlap with an existing reservation' error message
# To see the aforementioned error, run this mutation a multiple times
curl http://localhost:$RESERVATION_PORT/development/graphql \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-d '{ "query": "mutation { createReservation( input: { room_id: \"91754a14-4885-4200-a052-e4042431ffb8\", checkin_date: \"2023-12-31\", checkout_date: \"2024-01-02\" }) { success errors reservation { id room_id checkin_date checkout_date total_charge } } }" }'# List Available Rooms for a given date range
curl http://localhost:$RESERVATION_PORT/development/graphql \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-d '{"query": "query { getAvailableRooms( input: { checkin_date: \"2023-12-31\", checkout_date: \"2024-01-02\" }) { success errors rooms { id num_beds allow_smoking daily_rate cleaning_fee } } }" }'
```**Open API UI Usage**:
Navigate to [http://localhost:$RESERVATION_PORT/docs](http://localhost:$RESERVATION_PORT/docs).

## Pre-requisites
To run the service, you will need to install the following tools.
- [NodeJS](https://nodejs.org/en/)
- [Docker](https://www.docker.com/)The below are optional but highly recommended:
- [nvm](https://github.com/nvm-sh/nvm) - Used to manage NodeJS versions.
- [Direnv](https://direnv.net/) - Used to manage environment variables.
- Install [direnv](https://direnv.net) for persisting environment variables needed for development.## Getting Started
First, we'll need to set up our environment variables. You can do this by either any of the methods mentioned in [/tools/ENV.md](./tools/ENV.md) but I recommend using [Direnv](https://direnv.net/).
### Install Python Packages
Execute the following in your terminal:
```bash
python -m venv venv
source venv/bin/activate # for Windows, source venv/Scripts/activate
python -m pip install --upgrade pip
pip install -r requirements.txt
```### Install Node.js Packages
Execute the following within your terminal:
```bash
nvm use # To eliminate any issues, install/use the version listed in .nvmrc.
npm i # install the packages needed for project
cd ../frontend && npm i # install the packages needed for the frontend
cd ../db && npm i # install the packages needed for database migrations
cd .. # navigate back to the root of the repostiory
```### Create the database
Finally, let's create and seed the databases and our Reservations and Rooms tables:
```bash
# Create the databases and seed them
NODE_ENV=development | npm run refresh && npm run seed
```During development, you can just execute `npm run dev:db-baseline` to refresh the database back to the original seed data.
## Development
To run both the frontend and backend concurrently:
```bash
docker-compose up -d # runs the database in the background
npm run dev
```Also, you just execute the backend via `npm run dev:backend`. to verify the backend is working:
```bash
curl http://localhost:$RESERVATION_PORT/$ENV/about
```You can also acces the Ariadne GraphiQL (interactive test playground) instance at [http://localhost:$RESERVATION_PORT/$ENV/graphql](http://localhost:$PLAYGROUND_PORT/$ENV/graphql).
## Testing
The backend uses [Pytest](https://docs.pytest.org) and the frontend uses [Jest](https://jestjs.io/). To run these tests, simply execute `npm run test:backend` or `npm run test:frontend', respectively.
## Containerization
### Building the Backend Container
```bash
docker build backend/. -t acme-hotel-example-backend:latest \
--build-arg RESERVATION_PORT="80" \
--build-arg ENV="${ENV}" \
--build-arg IS_DEBUG="${IS_DEBUG}" \
--build-arg SECRET_KEY="$SECRET_KEY" \
--build-arg REFRESH_SECRET_KEY="$REFRESH_SECRET_KEY" \
--build-arg PG_URL="$PG_URL"# finally, to run a named container
docker run --name backend-dev -p 8000:80 acme-hotel-example-backend
```To verify the environment variables set, you can execute the following on the named container by:
```bash
CONTAINER_ID=$(docker ps -qf "name=backend-dev" -n 1)# this will display the container's environment variables in console
docker exec $CONTAINER_ID printenv
```If you need to re-create the container with the same name, do **docker rm ** (i.e., backend-dev) first.
### Building the Frontend Container
```bash
docker build frontend/. -t acme-hotel-example-frontend:latest \
--build-arg FRONTEND_PORT="80" \
--build-arg NODE_ENV=${NODE_ENV}# finally, to run a named container
docker run --name frontend-dev -p 3000:80 acme-hotel-example-frontend
```To verify, follow similar steps also explained in the above [Building the Backend Container](#building-the-backend-container) section.