156 lines
4.9 KiB
Python
156 lines
4.9 KiB
Python
"""Baby Monitor Main Application"""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from typing import Annotated
|
|
from contextlib import asynccontextmanager
|
|
from collections.abc import AsyncIterator
|
|
from fastapi import FastAPI, Depends
|
|
from fastapi.responses import FileResponse
|
|
from fastapi.staticfiles import StaticFiles
|
|
|
|
from baby_monitor.routers.auth import router as auth_router
|
|
from baby_monitor.routers.auth import verify_token
|
|
from baby_monitor.routers.admin import router as admin_router
|
|
from baby_monitor.routers.child import router as child_router
|
|
from baby_monitor.routers.feeding import router as feeding_router
|
|
from baby_monitor.routers.diaper_change import router as diaper_change_router
|
|
from baby_monitor.routers.sleep import router as sleep_router
|
|
from baby_monitor.routers.health import router as health_router
|
|
from baby_monitor.repositories.dependencies.get_database import init_db
|
|
|
|
# Disable docs in production
|
|
ENVIRONMENT = os.getenv("ENVIRONMENT", "production")
|
|
docs_url = "/docs" if ENVIRONMENT == "development" else None
|
|
redoc_url = "/redoc" if ENVIRONMENT == "development" else None
|
|
openapi_url = "/openapi.json" if ENVIRONMENT == "development" else None
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app_instance: FastAPI) -> AsyncIterator[None]:
|
|
"""Lifespan event handler for startup and shutdown."""
|
|
# Startup: Initialize database tables
|
|
init_db()
|
|
yield
|
|
# Shutdown: Add cleanup code here if needed
|
|
|
|
|
|
# Instantiate app
|
|
app = FastAPI(
|
|
docs_url=docs_url,
|
|
redoc_url=redoc_url,
|
|
openapi_url=openapi_url,
|
|
lifespan=lifespan,
|
|
)
|
|
|
|
|
|
# Mount static files
|
|
static_path = Path(__file__).parent / "static"
|
|
app.mount("/static", StaticFiles(directory=str(static_path)), name="static")
|
|
|
|
# Include routers
|
|
app.include_router(auth_router)
|
|
app.include_router(admin_router)
|
|
app.include_router(child_router)
|
|
app.include_router(feeding_router)
|
|
app.include_router(diaper_change_router)
|
|
app.include_router(sleep_router)
|
|
app.include_router(health_router)
|
|
|
|
|
|
# Serve HTML pages at root level
|
|
@app.get("/", include_in_schema=False)
|
|
def serve_home() -> FileResponse:
|
|
"""Serve the home page (handles auth check client-side)."""
|
|
return FileResponse(static_path / "index.html")
|
|
|
|
|
|
@app.get("/login.html", include_in_schema=False)
|
|
def serve_login() -> FileResponse:
|
|
"""Serve the login page."""
|
|
return FileResponse(static_path / "login.html")
|
|
|
|
|
|
@app.get("/register.html", include_in_schema=False)
|
|
def serve_register() -> FileResponse:
|
|
"""Serve the registration page."""
|
|
return FileResponse(static_path / "register.html")
|
|
|
|
|
|
@app.get("/admin.html", include_in_schema=False)
|
|
def serve_admin() -> FileResponse:
|
|
"""Serve the admin page."""
|
|
return FileResponse(static_path / "admin.html")
|
|
|
|
|
|
@app.get("/add-child.html", include_in_schema=False)
|
|
def serve_add_child() -> FileResponse:
|
|
"""Serve the add child page."""
|
|
return FileResponse(static_path / "add-child.html")
|
|
|
|
|
|
@app.get("/log-feeding.html", include_in_schema=False)
|
|
def serve_log_feeding() -> FileResponse:
|
|
"""Serve the log feeding page."""
|
|
return FileResponse(static_path / "log-feeding.html")
|
|
|
|
|
|
@app.get("/feedings.html", include_in_schema=False)
|
|
def serve_feedings() -> FileResponse:
|
|
"""Serve the feedings overview page."""
|
|
return FileResponse(static_path / "feedings.html")
|
|
|
|
|
|
@app.get("/diapers.html", include_in_schema=False)
|
|
def serve_diapers() -> FileResponse:
|
|
"""Serve the diaper changes overview page."""
|
|
return FileResponse(static_path / "diapers.html")
|
|
|
|
|
|
@app.get("/log-diaper.html", include_in_schema=False)
|
|
def serve_log_diaper() -> FileResponse:
|
|
"""Serve the log diaper change page."""
|
|
return FileResponse(static_path / "log-diaper.html")
|
|
|
|
|
|
@app.get("/sleep.html", include_in_schema=False)
|
|
def serve_sleep() -> FileResponse:
|
|
"""Serve the sleep overview page."""
|
|
return FileResponse(static_path / "sleep.html")
|
|
|
|
|
|
@app.get("/log-sleep.html", include_in_schema=False)
|
|
def serve_log_sleep() -> FileResponse:
|
|
"""Serve the log sleep page."""
|
|
return FileResponse(static_path / "log-sleep.html")
|
|
|
|
|
|
@app.get("/settings.html", include_in_schema=False)
|
|
def serve_settings() -> FileResponse:
|
|
"""Serve the settings page."""
|
|
return FileResponse(static_path / "settings.html")
|
|
|
|
|
|
@app.get("/menu.css", include_in_schema=False)
|
|
def serve_menu_css() -> FileResponse:
|
|
"""Serve the shared menu CSS."""
|
|
return FileResponse(static_path / "menu.css")
|
|
|
|
|
|
@app.get("/menu.js", include_in_schema=False)
|
|
def serve_menu_js() -> FileResponse:
|
|
"""Serve the shared menu JavaScript."""
|
|
return FileResponse(static_path / "menu.js")
|
|
|
|
|
|
@app.get("/auth-utils.js", include_in_schema=False)
|
|
def serve_auth_utils_js() -> FileResponse:
|
|
"""Serve the shared auth utilities JavaScript."""
|
|
return FileResponse(static_path / "auth-utils.js")
|
|
|
|
|
|
@app.get("/api/")
|
|
def read_root(token: Annotated[str, Depends(verify_token)]) -> dict:
|
|
"""API root endpoint (requires authentication)."""
|
|
return {"message": "Hello World", "authenticated": True}
|