Improve UX with merged run view, method badges, grouped encounters, and mobile nav
Merges the run dashboard into the encounters page as a unified view at /runs/:runId, adds encounter method grouping in the modal and badges on route rows, improves the home page with recent runs, adds mobile hamburger nav, and polishes empty states. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@ from sqlalchemy.orm import selectinload
|
||||
from app.core.database import get_session
|
||||
from app.models.game import Game
|
||||
from app.models.route import Route
|
||||
from app.models.route_encounter import RouteEncounter
|
||||
from app.schemas.game import (
|
||||
GameCreate,
|
||||
GameDetailResponse,
|
||||
@@ -66,35 +67,43 @@ async def list_game_routes(
|
||||
result = await session.execute(
|
||||
select(Route)
|
||||
.where(Route.game_id == game_id)
|
||||
.options(selectinload(Route.route_encounters))
|
||||
.order_by(Route.order)
|
||||
)
|
||||
all_routes = result.scalars().all()
|
||||
|
||||
def route_to_dict(route: Route) -> dict:
|
||||
methods = sorted({re.encounter_method for re in route.route_encounters})
|
||||
return {
|
||||
"id": route.id,
|
||||
"name": route.name,
|
||||
"game_id": route.game_id,
|
||||
"order": route.order,
|
||||
"parent_route_id": route.parent_route_id,
|
||||
"encounter_methods": methods,
|
||||
}
|
||||
|
||||
if flat:
|
||||
return all_routes
|
||||
return [route_to_dict(r) for r in all_routes]
|
||||
|
||||
# Build hierarchical structure
|
||||
# Group children by parent_route_id
|
||||
children_by_parent: dict[int, list[Route]] = {}
|
||||
children_by_parent: dict[int, list[dict]] = {}
|
||||
top_level_routes: list[Route] = []
|
||||
|
||||
for route in all_routes:
|
||||
if route.parent_route_id is None:
|
||||
top_level_routes.append(route)
|
||||
else:
|
||||
children_by_parent.setdefault(route.parent_route_id, []).append(route)
|
||||
children_by_parent.setdefault(route.parent_route_id, []).append(
|
||||
route_to_dict(route)
|
||||
)
|
||||
|
||||
# Build response with nested children
|
||||
response = []
|
||||
for route in top_level_routes:
|
||||
route_dict = {
|
||||
"id": route.id,
|
||||
"name": route.name,
|
||||
"game_id": route.game_id,
|
||||
"order": route.order,
|
||||
"parent_route_id": route.parent_route_id,
|
||||
"children": children_by_parent.get(route.id, []),
|
||||
}
|
||||
route_dict = route_to_dict(route)
|
||||
route_dict["children"] = children_by_parent.get(route.id, [])
|
||||
response.append(route_dict)
|
||||
|
||||
return response
|
||||
|
||||
@@ -7,6 +7,7 @@ class RouteResponse(CamelModel):
|
||||
game_id: int
|
||||
order: int
|
||||
parent_route_id: int | None = None
|
||||
encounter_methods: list[str] = []
|
||||
|
||||
|
||||
class GameResponse(CamelModel):
|
||||
|
||||
Reference in New Issue
Block a user