Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Build React App

on:
push:
branches: [ main, optimised-codebase, master ]
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout Code
uses: actions/checkout@v3

- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: 18

- name: Install dependencies
run: npm ci
working-directory: ./frontend

# --- THIS IS THE STEP TO FIX ---
- name: Build React app
run: CI=false npm run build
working-directory: ./frontend
env:
REACT_APP_API_BASE_URL: /api # <-- Add this line

- name: Upload production-ready build
uses: actions/upload-artifact@v4
with:
name: react-build
path: frontend/build
127 changes: 21 additions & 106 deletions app/main.py
Original file line number Diff line number Diff line change
@@ -1,130 +1,45 @@
from fastapi import FastAPI, Request, Depends
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponse, RedirectResponse, FileResponse
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session
import uvicorn
import os

from .database import get_db, create_tables
from .database import create_tables
from .routers import chef, customer, admin, feedback, loyalty, selection_offer, table, analytics, settings
from .middleware import SessionMiddleware

# Create FastAPI app
app = FastAPI(title="Tabble - Hotel Management App")
app = FastAPI(title="Tabble - API")

# Add CORS middleware to allow cross-origin requests
# Add CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Allow all origins
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"], # Allow all methods
allow_headers=["*"], # Allow all headers
allow_methods=["*"],
allow_headers=["*"],
)

# Add session middleware for database management
# Add session middleware
app.add_middleware(SessionMiddleware, require_database=True)

# Mount static files
app.mount("/static", StaticFiles(directory="app/static"), name="static")

# Setup templates
templates = Jinja2Templates(directory="templates")

# Include routers
app.include_router(chef.router)
app.include_router(customer.router)
app.include_router(admin.router)
app.include_router(feedback.router)
app.include_router(loyalty.router)
app.include_router(selection_offer.router)
app.include_router(table.router)
app.include_router(analytics.router)
app.include_router(settings.router)

# Create database tables
# Include all API routers with the /api prefix
app.include_router(chef.router, prefix="/api")
app.include_router(customer.router, prefix="/api")
app.include_router(admin.router, prefix="/api")
app.include_router(feedback.router, prefix="/api")
app.include_router(loyalty.router, prefix="/api")
app.include_router(selection_offer.router, prefix="/api")
app.include_router(table.router, prefix="/api")
app.include_router(analytics.router, prefix="/api")
app.include_router(settings.router, prefix="/api")

# Create database tables on startup
create_tables()

# Check if we have the React build folder
react_build_dir = "frontend/build"
has_react_build = os.path.isdir(react_build_dir)

if has_react_build:
# Mount the React build folder
app.mount("/", StaticFiles(directory=react_build_dir, html=True), name="react")


# Root route - serve React app in production, otherwise serve index.html template
@app.get("/", response_class=HTMLResponse)
async def root(request: Request):
if has_react_build:
return FileResponse(f"{react_build_dir}/index.html")
return templates.TemplateResponse("index.html", {"request": request})


# Chef page
@app.get("/chef", response_class=HTMLResponse)
async def chef_page(request: Request):
return templates.TemplateResponse("chef/index.html", {"request": request})


# Chef orders page
@app.get("/chef/orders", response_class=HTMLResponse)
async def chef_orders_page(request: Request):
return templates.TemplateResponse("chef/orders.html", {"request": request})


# Customer login page
@app.get("/customer", response_class=HTMLResponse)
async def customer_login_page(request: Request):
return templates.TemplateResponse("customer/login.html", {"request": request})


# Customer menu page
@app.get("/customer/menu", response_class=HTMLResponse)
async def customer_menu_page(request: Request, table_number: int, unique_id: str):
return templates.TemplateResponse(
"customer/menu.html",
{"request": request, "table_number": table_number, "unique_id": unique_id},
)


# Admin page
@app.get("/admin", response_class=HTMLResponse)
async def admin_page(request: Request):
return templates.TemplateResponse("admin/index.html", {"request": request})


# Admin dishes page
@app.get("/admin/dishes", response_class=HTMLResponse)
async def admin_dishes_page(request: Request):
return templates.TemplateResponse("admin/dishes.html", {"request": request})


# Analysis page
@app.get("/analysis", response_class=HTMLResponse)
async def analysis_page(request: Request):
return templates.TemplateResponse("analysis/index.html", {"request": request})


# Chef analysis page
@app.get("/analysis/chef", response_class=HTMLResponse)
async def chef_analysis_page(request: Request):
return templates.TemplateResponse("analysis/chef.html", {"request": request})


# Customer analysis page
@app.get("/analysis/customer", response_class=HTMLResponse)
async def customer_analysis_page(request: Request):
return templates.TemplateResponse("analysis/customer.html", {"request": request})


# Dish analysis page
@app.get("/analysis/dish", response_class=HTMLResponse)
async def dish_analysis_page(request: Request):
return templates.TemplateResponse("analysis/dish.html", {"request": request})


# For running locally
if __name__ == "__main__":
uvicorn.run("app.main:app", host="0.0.0.0", port=8000, reload=True)
Loading