Adds a sysadmin-configurable toggle so sites can disable online ordering on the public QR menu until it's fully supported, plus editable tagline/hours and a header image (replacing the hardcoded "Our Menu" placeholder) — all previously hardcoded frontend strings. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
63 lines
2.7 KiB
Python
63 lines
2.7 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, Header, status
|
|
from passlib.context import CryptContext
|
|
from sqlalchemy.orm import Session
|
|
|
|
from database import get_db
|
|
from models.site import Site
|
|
from models.menu_snapshot import MenuSnapshot
|
|
from schemas.menu import MenuSyncRequest, MenuSyncResponse
|
|
|
|
router = APIRouter()
|
|
_pwd = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
|
|
|
|
|
def _require_site(
|
|
x_site_id: str = Header(..., alias="X-Site-ID"),
|
|
x_site_key: str = Header(..., alias="X-Site-Key"),
|
|
db: Session = Depends(get_db),
|
|
) -> Site:
|
|
site = db.query(Site).filter(Site.site_id == x_site_id).first()
|
|
if not site or not _pwd.verify(x_site_key, site.secret_key_hash):
|
|
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid site credentials")
|
|
return site
|
|
|
|
|
|
# ── Public ────────────────────────────────────────────────────────────────────
|
|
|
|
@router.get("/{site_slug}")
|
|
def get_menu(site_slug: str, db: Session = Depends(get_db)):
|
|
"""Return the latest menu snapshot for a site. Used by the public menu SPA."""
|
|
site = db.query(Site).filter(Site.site_id == site_slug).first()
|
|
if not site:
|
|
raise HTTPException(status_code=404, detail="Site not found")
|
|
|
|
snapshot = db.query(MenuSnapshot).filter(MenuSnapshot.site_id == site.id).first()
|
|
if not snapshot:
|
|
raise HTTPException(status_code=404, detail="No menu published yet")
|
|
|
|
import json
|
|
data = json.loads(snapshot.snapshot_json)
|
|
data["menu_mode"] = site.menu_mode
|
|
data["restaurant"] = {
|
|
"name": site.name,
|
|
"tagline": {"en": site.menu_tagline_en, "gr": site.menu_tagline_gr},
|
|
"hours": {"en": site.menu_hours_en, "gr": site.menu_hours_gr},
|
|
"headerImageUrl": site.menu_header_image_url,
|
|
}
|
|
return data
|
|
|
|
|
|
# ── Internal (site API key) ───────────────────────────────────────────────────
|
|
|
|
@router.post("/sync", response_model=MenuSyncResponse)
|
|
def sync_menu(body: MenuSyncRequest, site: Site = Depends(_require_site), db: Session = Depends(get_db)):
|
|
"""Upsert the menu snapshot for this site. Called by local_backend on each sync."""
|
|
snapshot = db.query(MenuSnapshot).filter(MenuSnapshot.site_id == body.site_id).first()
|
|
if snapshot:
|
|
snapshot.snapshot_json = body.snapshot_json
|
|
else:
|
|
snapshot = MenuSnapshot(site_id=body.site_id, snapshot_json=body.snapshot_json)
|
|
db.add(snapshot)
|
|
db.commit()
|
|
return MenuSyncResponse(ok=True)
|