feat: City Rooms routing implementation

Backend:
- GET /api/v1/city/rooms - list all city rooms
- GET /api/v1/city/rooms/{slug} - get room by slug with host agents

Frontend:
- Updated /city/[slug] page with host agents section
- Added breadcrumb navigation
- Updated API client to fetch room by slug
- Added rewrite for /api/city/rooms/:slug

Task doc: TASK_PHASE_CITY_ROOMS_ROUTING_v1.md
This commit is contained in:
Apple
2025-11-30 10:54:39 -08:00
parent 36394cff55
commit 85fdcdf0be
5 changed files with 440 additions and 14 deletions

View File

@@ -1048,6 +1048,81 @@ async def create_city_room(payload: CityRoomCreate):
raise HTTPException(status_code=500, detail="Failed to create city room")
@api_router.get("/city/rooms")
async def get_city_rooms_api():
"""
Отримати список всіх City Rooms для API.
"""
try:
rooms = await repo_city.get_all_rooms(limit=100, offset=0)
result = []
for room in rooms:
result.append({
"id": room.get("id"),
"slug": room.get("slug"),
"name": room.get("name"),
"description": room.get("description"),
"scope": room.get("owner_type", "city"),
"matrix_room_id": room.get("matrix_room_id"),
"is_public": room.get("is_public", True),
"room_role": room.get("room_role"),
})
return result
except Exception as e:
logger.error(f"Failed to get city rooms: {e}")
raise HTTPException(status_code=500, detail="Failed to get city rooms")
@api_router.get("/city/rooms/{slug}")
async def get_city_room_by_slug(slug: str):
"""
Отримати деталі City Room за slug.
"""
try:
room = await repo_city.get_room_by_slug(slug)
if not room:
raise HTTPException(status_code=404, detail=f"Room not found: {slug}")
# Get host agents for this room (public agents assigned to city rooms)
host_agents = []
try:
# Get DARIO and DARIA as default hosts for city rooms
default_hosts = ["dario", "daria", "daarwizz"]
for agent_id in default_hosts:
agent = await repo_city.get_agent_by_id(agent_id)
if agent:
host_agents.append({
"id": agent.get("id"),
"display_name": agent.get("display_name"),
"avatar_url": agent.get("avatar_url"),
"kind": agent.get("kind"),
"role": "host"
})
except Exception as e:
logger.warning(f"Failed to get host agents for room {slug}: {e}")
return {
"id": room.get("id"),
"slug": room.get("slug"),
"name": room.get("name"),
"description": room.get("description"),
"scope": room.get("owner_type", "city"),
"matrix_room_id": room.get("matrix_room_id"),
"matrix_room_alias": room.get("matrix_room_alias"),
"is_public": room.get("is_public", True),
"room_role": room.get("room_role"),
"host_agents": host_agents,
"chat_available": room.get("matrix_room_id") is not None
}
except HTTPException:
raise
except Exception as e:
logger.error(f"Failed to get city room by slug {slug}: {e}")
raise HTTPException(status_code=500, detail="Failed to get city room")
@router.get("/rooms/{room_id}", response_model=CityRoomDetail)
async def get_city_room(room_id: str):
"""