# TASK_PHASE_CITY_ROOMS_FINISH_v2 ## Title TASK_PHASE_CITY_ROOMS_FINISH_v2 — MicroDAO Rooms + City Lobby CTA + Online Stats Fix ## 1. Overview Finish the DAARION City chat layer: 1. City Rooms page: * Map + List already work. * Fix `NaN` for online users count. 2. MicroDAO Rooms: * Each MicroDAO must have its own rooms section. * Ability to create new rooms from MicroDAO cabinet. 3. City Lobby CTA: * Main public chat with DAARWIZZ should be accessible directly from the homepage and top navigation. All changes must use existing architecture: `city-service` (FastAPI + Postgres) and `apps/web` (Next.js / React). --- ## 2. Current State (as of 2025-12-01) * Backend: * `scripts/seed_city_rooms.py` creates ~31 rooms (district rooms, lobbies, city lobby, etc.). * `city-service` exposes `/api/v1/city/rooms` (already used by UI). * Rooms table already contains: * `id` * `slug` * `name` (title) * `description` * `zone` (district key) * `room_type` (e.g. `city`, `district`, `microdao`, etc.) * `is_public` (bool) * `microdao_id` (nullable, for MicroDAO rooms) * Frontend: * `/city` (City Rooms): * Map tab: grid of districts, shows total rooms and online counters. * List tab: renders all rooms with description. * At the bottom: summary cards: `Kімнат: 31`, `Онлайн: NaN`. * MicroDAO pages (`/microdao/[slug]`): * Currently have no dedicated "MicroDAO Rooms" section. * Homepage (`/`): * No direct CTA to "DAARION City Lobby". --- ## 3. Goals 1. **Fix online counter**: * Never show `NaN` on the City Rooms page. 2. **MicroDAO Rooms UI**: * On `/microdao/[slug]` display: * List of rooms belonging to this MicroDAO. * Button "Створити кімнату". 3. **City Lobby CTA**: * On homepage and/or main menu: * Button "Поспілкуватися з DAARWIZZ" that opens `DAARION City Lobby`. --- ## 4. Backend Tasks ### 4.1. Room model & repository Files: * `services/city-service/models_city.py` * `services/city-service/repo_city.py` * `services/city-service/routes_city.py` 1. **Ensure Room model exposes needed fields:** ```python class CityRoomSummary(BaseModel): id: str slug: str name: str description: Optional[str] zone: Optional[str] room_type: str microdao_id: Optional[str] is_public: bool members_online: int = 0 # ← must always be integer (0 by default) ``` 2. **Repo method for city rooms:** * `get_all_rooms()` must: * Return `members_online` as integer (use `COALESCE(..., 0)`). 3. **Repo method for MicroDAO rooms:** Add/verify method: ```python async def get_microdao_rooms(microdao_id: str) -> List[dict]: """Get rooms for specific MicroDAO""" # WHERE microdao_id = $1 AND is_public = true OR owner_type = 'microdao' ``` 4. **API routes:** * Verify endpoint: `GET /api/v1/city/rooms` returns `members_online: int`. * Verify endpoint: `GET /city/microdao/{slug}/rooms` returns MicroDAO rooms. * Add endpoint for room creation: ```python class CreateRoomRequest(BaseModel): title: str description: Optional[str] room_type: str = "microdao" is_public: bool = False @router.post("/city/microdao/{slug}/rooms") async def create_microdao_room(slug: str, body: CreateRoomRequest): # Create room for MicroDAO ``` 5. **Online stats summary:** * Add/verify endpoint: `GET /api/v1/city/rooms/summary` * Returns: `{"rooms_total": int, "online_total": int}` --- ## 5. Frontend Tasks Files: * `apps/web/src/app/city/page.tsx` * `apps/web/src/app/microdao/[slug]/page.tsx` * `apps/web/src/app/page.tsx` (homepage) * `apps/web/src/components/microdao/MicrodaoRoomsSection.tsx` (new) ### 5.1. Fix `NaN` online stats 1. In `city/page.tsx`: * Ensure online count uses fallback: ```tsx const onlineTotal = summary?.online_total ?? 0; // or const onlineTotal = Number(summary?.online_total) || 0; ``` 2. If API returns `null` or `undefined`, display `0`. ### 5.2. MicroDAO Rooms section In `apps/web/src/app/microdao/[slug]/page.tsx`: 1. Add API call: ```ts const rooms = await fetchMicrodaoRooms(slug); // GET /city/microdao/{slug}/rooms ``` 2. Render new section: ```tsx

Кімнати MicroDAO

{rooms.length === 0 ? (

Ще немає кімнат. Створіть першу кімнату для цієї платформи.

) : (
{rooms.map((room) => ( ))}
)}
``` 3. `MicrodaoRoomCard` component: * title * description * room_type (badge) * visibility (Public/Private badge) * members_online 4. "Create Room" modal: * Назва кімнати (title, required) * Опис (optional) * Тип (select: Lobby, Governance, Project, Crew) * Видимість (switch: Public / Private, default = Private) * On submit → POST `/city/microdao/{slug}/rooms` ### 5.3. City Lobby CTA 1. On homepage (`apps/web/src/app/page.tsx`): ```tsx

Головний публічний чат DAARION City

Поспілкуватися з DAARWIZZ та іншими громадянами міста.

``` 2. Optionally add to navigation header: * New item: "City Lobby" → `/city?room=city-lobby` --- ## 6. Acceptance Criteria 1. City Rooms page shows: * Correct number of rooms. * Online count is integer (0 allowed), never `NaN`. 2. MicroDAO page (`/microdao/daarion`, etc.) shows: * "Кімнати MicroDAO" section. * Ability to create a room. * Newly created room appears in list. 3. Homepage shows: * CTA "Поспілкуватися з DAARWIZZ". * Clicking the button opens City Lobby room. 4. All routes work both on NODE1 and NODE2.