96 lines
3.0 KiB
Python
96 lines
3.0 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import datetime, timedelta
|
|
from types import SimpleNamespace
|
|
|
|
from fastapi import APIRouter, Depends, Request
|
|
from fastapi.responses import HTMLResponse
|
|
from fastapi.templating import Jinja2Templates
|
|
|
|
from dependencies import get_unit_of_work
|
|
from models import MiningOperationType
|
|
from services.unit_of_work import UnitOfWork
|
|
|
|
router = APIRouter(tags=["Dashboard"])
|
|
templates = Jinja2Templates(directory="templates")
|
|
|
|
|
|
def _load_metrics(_: UnitOfWork) -> dict[str, object]:
|
|
today = datetime.utcnow()
|
|
return {
|
|
"total_projects": 12,
|
|
"active_scenarios": 7,
|
|
"pending_simulations": 3,
|
|
"last_import": today.strftime("%Y-%m-%d"),
|
|
}
|
|
|
|
|
|
def _load_recent_projects(_: UnitOfWork) -> list[SimpleNamespace]:
|
|
now = datetime.utcnow()
|
|
return [
|
|
SimpleNamespace(
|
|
id=1,
|
|
name="Copper Ridge Expansion",
|
|
operation_type=MiningOperationType.OPEN_PIT,
|
|
updated_at=now - timedelta(days=2),
|
|
),
|
|
SimpleNamespace(
|
|
id=2,
|
|
name="Lithium Basin North",
|
|
operation_type=MiningOperationType.UNDERGROUND,
|
|
updated_at=now - timedelta(days=5),
|
|
),
|
|
SimpleNamespace(
|
|
id=3,
|
|
name="Nickel Underground Phase II",
|
|
operation_type=MiningOperationType.IN_SITU_LEACH,
|
|
updated_at=now - timedelta(days=9),
|
|
),
|
|
]
|
|
|
|
|
|
def _load_simulation_updates(_: UnitOfWork) -> list[SimpleNamespace]:
|
|
now = datetime.utcnow()
|
|
return [
|
|
SimpleNamespace(
|
|
title="Monte Carlo Batch #21 completed",
|
|
description="1,000 runs processed for Lithium Basin North.",
|
|
timestamp=now - timedelta(hours=4),
|
|
),
|
|
SimpleNamespace(
|
|
title="Scenario validation queued",
|
|
description="Copper Ridge Expansion pending validation on new cost inputs.",
|
|
timestamp=now - timedelta(days=1, hours=3),
|
|
),
|
|
]
|
|
|
|
|
|
def _load_scenario_alerts(_: UnitOfWork) -> list[SimpleNamespace]:
|
|
return [
|
|
SimpleNamespace(
|
|
title="Variance exceeds threshold",
|
|
message="Nickel Underground Phase II deviates 18% from baseline forecast.",
|
|
link="/projects/3/view",
|
|
),
|
|
SimpleNamespace(
|
|
title="Simulation backlog",
|
|
message="Lithium Basin North has 2 pending simulation batches.",
|
|
link="/projects/2/view",
|
|
),
|
|
]
|
|
|
|
|
|
@router.get("/", response_class=HTMLResponse, include_in_schema=False, name="dashboard.home")
|
|
def dashboard_home(
|
|
request: Request,
|
|
uow: UnitOfWork = Depends(get_unit_of_work),
|
|
) -> HTMLResponse:
|
|
context = {
|
|
"request": request,
|
|
"metrics": _load_metrics(uow),
|
|
"recent_projects": _load_recent_projects(uow),
|
|
"simulation_updates": _load_simulation_updates(uow),
|
|
"scenario_alerts": _load_scenario_alerts(uow),
|
|
}
|
|
return templates.TemplateResponse("dashboard.html", context)
|