mirror of
https://github.com/xlorepdarkhelm/numinar-coding-project.git
synced 2026-09-08 08:28:18 -04:00
262 lines
7.8 KiB
Markdown
262 lines
7.8 KiB
Markdown
# Online Booking Application
|
|
|
|
## Cliff Hill's Coding Project
|
|
|
|
This is a full-stack application simulating an online booking system for conference rooms.
|
|
|
|
---
|
|
|
|
## Design Decisions
|
|
|
|
- **Backend:**
|
|
- Uses Python 3.13 for modern syntax and improved debugging.
|
|
- FastAPI, SQLAlchemy, asyncpg
|
|
- Follows a modular structure: routers, services, schemas, and models are separated for maintainability.
|
|
- Dataclasses and type hints improve readability and reliability.
|
|
- Async SQLAlchemy for scalable database access.
|
|
- Robust testing with Nox and Pytest.
|
|
- **Frontend:**
|
|
- React with TypeScript for type safety and maintainability.
|
|
- Material-UI for a modern, responsive UI.
|
|
- Centralized logging
|
|
- Clear separation of concerns.
|
|
- **Containerization:**
|
|
- Docker Compose for both production and development, with hot-reload and volume mounts for rapid iteration.
|
|
- Production environment is run with a simple `docker compose up` from the root directory.
|
|
- Development environment is run with `docker compose -f compose.dev.yml up` from the root directory.
|
|
- Development compose extends the production compose, allowing for changes in the production compose to be
|
|
reflected in the development compose as well.
|
|
- **Security:**
|
|
- No authentication in this demo, but structure allows for easy integration of OpenID/JWT.
|
|
- Environment variables for secrets; in production, use a secrets manager.
|
|
- Backend dependencies are validated using `security` and other tests inside `nox`.
|
|
|
|
### AI Use
|
|
|
|
I used AI to stub out a couple of files:
|
|
|
|
- The backend/Dockerfile and frontend/Dockerfile - to speed up the process of getting docker loaded efficiently for the project.
|
|
- The compose.yml file - getting the different images gathered together quickly.
|
|
- The compose.dev.yml file - used to get a further understanding of how to hook up an extension to the previous file.
|
|
- The mermaid diagrams used in this file.
|
|
- I have the CodeGPT plugin in VSCode, and it has helped with docstrings, logging messages, and sometimes reducing the time it takes me to write out the code.
|
|
- I used AI to rapidly set up tests for each users component (router, service), then adapted it to the others independently. I believe AI is great for getting reasonable tests written quickly, and then I simply refined it, and replicated the kinds of tests across the different components.
|
|
- I was experimenting with some AI edits for debugging the tests.
|
|
- My frontend skills are less polished than my backend skills. I've been using AI along the lines of how I would use StackOverflow, answering questions to help me get the code written.
|
|
- I used AI to help clean up and better structure the CSS for the frontend project, as well as get some code documentation in place.
|
|
- AI was used to refactor code a few times to make it cleaner and better organized.
|
|
|
|
---
|
|
|
|
## Development Environment Setup
|
|
|
|
Follow these steps to get your local development environment running:
|
|
|
|
### 1. Clone the repository
|
|
|
|
You can use either HTTPS or SSH:
|
|
|
|
**HTTPS:**
|
|
|
|
```bash
|
|
git clone https://github.com/xlorepdarkhelm/numinar-coding-project.git
|
|
cd numinar-coding-project
|
|
```
|
|
|
|
**SSH:**
|
|
|
|
```bash
|
|
git clone git@github.com:xlorepdarkhelm/numinar-coding-project.git
|
|
cd numinar-coding-project
|
|
```
|
|
|
|
### 2. Copy environment variables
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
# Or, if present:
|
|
cp .env.sample .env
|
|
```
|
|
|
|
### 3. Install backend dependencies
|
|
|
|
```bash
|
|
cd backend
|
|
poetry install
|
|
```
|
|
|
|
### 4. Set up pre-commit hooks (recommended)
|
|
|
|
```bash
|
|
pre-commit install
|
|
```
|
|
|
|
### 5. Install frontend dependencies
|
|
|
|
```bash
|
|
cd ../frontend
|
|
yarn install
|
|
```
|
|
|
|
### 6. Start Docker Compose in development mode (in a separate terminal)
|
|
|
|
From the project root:
|
|
|
|
```bash
|
|
docker compose -f compose.dev.yml up
|
|
```
|
|
|
|
This will start the backend (port 8000), frontend (port 3000), and Postgres (port 5432) with hot-reload enabled for rapid development.
|
|
|
|
### 7. Run tests (backend & frontend)
|
|
|
|
#### Backend tests
|
|
|
|
```bash
|
|
cd backend
|
|
nox # Run all tests and checks (also builds API docs)
|
|
# or run only unit tests:
|
|
nox --session=tests
|
|
```
|
|
|
|
##### API Documentation
|
|
|
|
- The `nox` command above will also build the backend API documentation.
|
|
- **View the API docs in development mode:** Open [http://localhost:8000/docs](http://localhost:8000/docs) in
|
|
your browser (when running dev Docker Compose).
|
|
- **Generated static docs (after running nox):** See `backend/docs/build/index.html` relative to the project
|
|
root.
|
|
|
|
#### Frontend tests
|
|
|
|
```bash
|
|
cd frontend
|
|
yarn test
|
|
```
|
|
|
|
#### Further improvements
|
|
|
|
Integration testing, and end-to-end tests really would make this robust. Having all of the tests run in CICD before allowing code to be merged/commited to the main branch would be a mechanism to help ensure code quality. I would have set up the github project to have "feature branches" be made, to add whatever feature that a work item/issue had, and then Peer Reviews - typically set up with 2 peers reviewing 1 PR and approving it, aswell as all CICD checks/tests needing to pass before allowing the branch to be merged.
|
|
|
|
I would have templates in place for creating a PR, with a set of instructions that would give the "definition of done" - a checklist that would need to be completed before the issue could be marked as completed and a PR could then be reviewed.
|
|
|
|
## Diagrams
|
|
|
|
### Docker Compose Components
|
|
|
|
```mermaid
|
|
graph TD
|
|
subgraph Docker_Network
|
|
B[Frontend]
|
|
C[Backend]
|
|
D[PostgreSQL]
|
|
C -- "SQL: 5432" --> D
|
|
end
|
|
Client[Client] -- "HTTP: 3000" --> B
|
|
Client -- "HTTP/REST: 8000" --> C
|
|
```
|
|
|
|
---
|
|
|
|
### Database Schema Diagram
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class User {
|
|
string email
|
|
string name
|
|
}
|
|
class Room {
|
|
int id
|
|
string name
|
|
string location
|
|
string equipment
|
|
int capacity
|
|
}
|
|
class Booking {
|
|
int id
|
|
int room_id
|
|
datetime start_time
|
|
datetime end_time
|
|
string title
|
|
}
|
|
class Invitee {
|
|
int id
|
|
int booking_id
|
|
string user_email
|
|
}
|
|
|
|
User "1" <|-- "*" Invitee : user_email
|
|
Room "1" <|-- "*" Booking : room_id
|
|
Booking "1" <|-- "*" Invitee : booking_id
|
|
```
|
|
|
|
---
|
|
|
|
### Component Diagram
|
|
|
|
```mermaid
|
|
graph TD
|
|
subgraph Frontend
|
|
F1[Pages] --> F2[Components]
|
|
F2 --> F3[API Calls]
|
|
end
|
|
subgraph Backend
|
|
B1[FastAPI Routers] --> B2[Pydantic Schemas]
|
|
B1 --> B3[Service Layer]
|
|
B3 --> B4[SQLAlchemy Models]
|
|
B4 --> B5[PostgreSQL]
|
|
end
|
|
F3 -->|REST| B1
|
|
```
|
|
|
|
---
|
|
|
|
### Backend Request Data Path
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Frontend
|
|
participant FastAPI_Router as FastAPI Router
|
|
participant API_Endpoint as API Endpoint
|
|
participant Pydantic_Schema as Pydantic Schema
|
|
participant Service_Layer as Service Layer
|
|
participant DB_Model as DB Model
|
|
participant Database
|
|
|
|
Frontend->>FastAPI_Router: HTTP Request (REST)
|
|
FastAPI_Router->>API_Endpoint: Route Match
|
|
API_Endpoint->>Pydantic_Schema: Validate & Parse Input
|
|
Pydantic_Schema-->>API_Endpoint: Validated Data
|
|
API_Endpoint->>Service_Layer: Pass Data
|
|
Service_Layer->>DB_Model: Business Logic
|
|
DB_Model->>Database: DB Query/Update
|
|
Database-->>DB_Model: Query Result
|
|
DB_Model-->>Service_Layer: Data
|
|
Service_Layer-->>API_Endpoint: Response Data
|
|
API_Endpoint-->>Frontend: HTTP Response (JSON)
|
|
```
|
|
|
|
---
|
|
|
|
### SSE Update Flow (Real-Time Room Availability)
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Frontend
|
|
participant FastAPI_Router as FastAPI Router
|
|
participant SSE_Endpoint as SSE Endpoint
|
|
participant Event_Generator as Event Generator
|
|
participant Publisher as Publisher
|
|
|
|
Frontend->>SSE_Endpoint: Open EventSource /availability/stream
|
|
SSE_Endpoint->>Event_Generator: Start Async Event Loop
|
|
loop While Connected
|
|
Event_Generator->>Publisher: Wait for Event or Timeout
|
|
Publisher-->>Event_Generator: Room Availability Event | Keep-Alive
|
|
Event_Generator-->>Frontend: Send SSE Event (data: ...)
|
|
end
|
|
Frontend-->>SSE_Endpoint: Disconnect (close EventSource)
|
|
SSE_Endpoint-->>Event_Generator: Cleanup Subscriber
|
|
```
|