Enterprise-Grade Appointment Automation Platform
Objective
Create a modern, full-stack application that provides a user interface for managing automated appointment bookings. The system combines React frontend, FastAPI backend, and Selenium automation, offering a complete solution for scheduling and monitoring automated booking tasks.
Learning Outcomes
By completing this project, you will:
- Build a modern React frontend with TypeScript and Material UI
- Develop a RESTful API using FastAPI and PostgreSQL
- Implement real-time updates using WebSocket
- Create background task processing with Celery
- Design responsive and interactive user interfaces
- Manage state in a complex application
- Implement authentication and authorization
Prerequisites and Theoretical Foundations
1. Frontend Development
- React: Hooks, Context, and Components
- TypeScript: Type system and interfaces
- State Management: Redux patterns
- REST/WebSocket: API communication
2. Backend Development
- Python: Async programming with FastAPI
- Database: SQL and ORMs
- Task Queues: Celery and message brokers
- API Design: RESTful principles
3. DevOps Skills
- Docker: Containerization
- PostgreSQL: Database administration
- Redis: Caching and message queues
- Nginx: Reverse proxy
Tools Required
Frontend:
- Node.js 16+
- React 18+
- TypeScript 4+
- Material UI 5+
- Redux Toolkit
- React Query
- Socket.io-client
Backend:
- Python 3.9+
- FastAPI
- SQLAlchemy
- Alembic
- Celery
- Redis
- PostgreSQL
Development Tools:
- Docker & Docker Compose
- Git
- VS Code or WebStorm
- Postman
Project Structure
booking-system/
├── frontend/
│ ├── src/
│ │ ├── components/
│ │ ├── features/
│ │ ├── hooks/
│ │ ├── services/
│ │ ├── store/
│ │ └── types/
├── backend/
│ ├── app/
│ │ ├── api/
│ │ ├── core/
│ │ ├── db/
│ │ ├── models/
│ │ └── tasks/
├── automation/
│ ├── src/
│ │ ├── booking/
│ │ └── utils/
├── docker/
│ ├── frontend/
│ ├── backend/
│ └── automation/
└── docker-compose.yml
Steps and Tasks
1. Frontend Development
Tasks:
- Set Up React Application
- Implement UI Components
- Configure State Management
- Add Real-time Updates
Implementation:
// frontend/src/features/bookings/BookingDashboard.tsx
import React from 'react';
import { useQuery, useMutation } from '@tanstack/react-query';
import {
Grid,
Card,
CardContent,
Typography
} from '@mui/material';
import { useBookings } from '../../hooks/useBookings';
const BookingDashboard: React.FC = () => {
const { bookings, isLoading, error } = useBookings();
return (
<Grid container spacing={3}>
{bookings.map((booking) => (
<Grid item xs={12} md={6} key={booking.id}>
<Card>
<CardContent>
<Typography variant="h6">
{booking.appointmentType}
</Typography>
<Typography color="textSecondary">
Status: {booking.status}
</Typography>
<Typography>
Next Attempt: {new Date(booking.nextAttempt).toLocaleString()}
</Typography>
</CardContent>
</Card>
</Grid>
))}
</Grid>
);
};
// frontend/src/store/bookingSlice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
interface BookingState {
bookings: Booking[];
status: 'idle' | 'loading' | 'failed';
}
const initialState: BookingState = {
bookings: [],
status: 'idle',
};
export const bookingSlice = createSlice({
name: 'booking',
initialState,
reducers: {
setBookings: (state, action: PayloadAction<Booking[]>) => {
state.bookings = action.payload;
},
updateBookingStatus: (state, action: PayloadAction<BookingUpdate>) => {
const index = state.bookings.findIndex(b => b.id === action.payload.id);
if (index !== -1) {
state.bookings[index].status = action.payload.status;
}
},
},
});
2. Backend API Development
Tasks:
- Create FastAPI Application
- Set Up Database Models
- Implement API Endpoints
- Configure WebSocket Support
Implementation:
# backend/app/api/endpoints/bookings.py
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import List
from app.core.deps import get_db
from app.schemas.booking import BookingCreate, BookingResponse
from app.crud.booking import booking_crud
router = APIRouter()
@router.post("/bookings/", response_model=BookingResponse)
def create_booking(
booking: BookingCreate,
db: Session = Depends(get_db)
):
return booking_crud.create(db, obj_in=booking)
@router.get("/bookings/", response_model=List[BookingResponse])
def get_bookings(
skip: int = 0,
limit: int = 100,
db: Session = Depends(get_db)
):
return booking_crud.get_multi(db, skip=skip, limit=limit)
# backend/app/models/booking.py
from sqlalchemy import Column, Integer, String, DateTime
from app.db.base_class import Base
class Booking(Base):
__tablename__ = "bookings"
id = Column(Integer, primary_key=True, index=True)
appointment_type = Column(String, nullable=False)
target_date = Column(DateTime, nullable=False)
status = Column(String, nullable=False)
attempts = Column(Integer, default=0)
next_attempt = Column(DateTime)
3. Task Queue Implementation
Tasks:
- Set Up Celery Worker
- Create Booking Tasks
- Implement Status Updates
Implementation:
# backend/app/tasks/booking_tasks.py
from celery import Celery
from app.core.config import settings
from app.automation.booking_bot import BookingBot
celery = Celery('tasks', broker=settings.REDIS_URL)
@celery.task(bind=True)
def attempt_booking(self, booking_id: int):
try:
bot = BookingBot()
result = bot.make_booking(booking_id)
# Update booking status
update_booking_status.delay(booking_id, result)
return result
except Exception as e:
self.retry(exc=e, countdown=300) # Retry in 5 minutes
@celery.task
def update_booking_status(booking_id: int, status: str):
# Update database and notify frontend via WebSocket
from app.core.websocket import notify_clients
notify_clients(f"booking_{booking_id}", {
"status": status,
"booking_id": booking_id
})
4. WebSocket Integration
Tasks:
- Implement WebSocket Server
- Add Client-Side Integration
- Handle Real-time Updates
Implementation:
// frontend/src/hooks/useWebSocket.ts
import { useEffect, useContext } from 'react';
import { io, Socket } from 'socket.io-client';
import { useDispatch } from 'react-redux';
import { updateBookingStatus } from '../store/bookingSlice';
export const useWebSocket = () => {
const dispatch = useDispatch();
useEffect(() => {
const socket = io(process.env.REACT_APP_WS_URL);
socket.on('booking_update', (data) => {
dispatch(updateBookingStatus(data));
});
return () => {
socket.disconnect();
};
}, [dispatch]);
};
// backend/app/core/websocket.py
from fastapi import WebSocket
from typing import Dict, Set
class WebSocketManager:
def __init__(self):
self.active_connections: Dict[str, Set[WebSocket]] = {}
async def connect(self, client_id: str, websocket: WebSocket):
await websocket.accept()
if client_id not in self.active_connections:
self.active_connections[client_id] = set()
self.active_connections[client_id].add(websocket)
async def broadcast(self, message: dict):
for connections in self.active_connections.values():
for connection in connections:
await connection.send_json(message)
manager = WebSocketManager()
5. Authentication and Authorization
Tasks:
- Implement JWT Authentication
- Add User Management
- Set Up Role-Based Access
Implementation:
# backend/app/core/auth.py
from datetime import datetime, timedelta
from jose import JWTError, jwt
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
def create_access_token(data: dict):
to_encode = data.copy()
expire = datetime.utcnow() + timedelta(minutes=30)
to_encode.update({"exp": expire})
return jwt.encode(to_encode, settings.SECRET_KEY, algorithm="HS256")
async def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
except JWTError:
raise credentials_exception
return username
6. Docker Configuration
Tasks:
- Create Service Containers
- Configure Networking
- Set Up Development Environment
Implementation:
# docker-compose.yml
version: '3.8'
services:
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- REACT_APP_API_URL=http://localhost:8000
- REACT_APP_WS_URL=ws://localhost:8000/ws
backend:
build:
context: ./backend
dockerfile: Dockerfile
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://user:password@db:5432/bookings
- REDIS_URL=redis://redis:6379
depends_on:
- db
- redis
celery_worker:
build:
context: ./backend
dockerfile: Dockerfile
command: celery -A app.tasks.worker worker --loglevel=info
depends_on:
- backend
- redis
db:
image: postgres:14
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
- POSTGRES_DB=bookings
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:6
ports:
- "6379:6379"
volumes:
postgres_data:
Further Enhancements
-
Analytics Dashboard:
- Add booking success rates
- Implement performance metrics
- Create visual reports
-
Advanced Scheduling:
- Priority queue system
- Smart retry mechanisms
- Conflict resolution
-
User Experience:
- Mobile responsive design
- Push notifications
- Email alerts
-
Integration Options:
- External calendar systems
- SMS notifications
- Third-party APIs
Conclusion
This full-stack implementation provides:
- Modern UI/UX with React and Material UI
- Robust Backend using FastAPI and PostgreSQL
- Real-time Updates via WebSocket
- Scalable Architecture with containerization
- Background Processing using Celery
- Secure Authentication with JWT