- Fixed NaN in online stats by using nullish coalescing (?? 0) - Added members_online, zone, room_type to /api/v1/city/rooms response - Added DAARWIZZ chat CTA section on homepage with link to city-lobby - Created task files for next phases: - TASK_PHASE_CITY_ROOMS_FINISH_v2.md - TASK_PHASE_AGENT_MANAGEMENT_v1.md - TASK_PHASE_CITIZENS_DIRECTORY_v1.md
6.3 KiB
6.3 KiB
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:
-
City Rooms page:
- Map + List already work.
- Fix
NaNfor online users count.
-
MicroDAO Rooms:
- Each MicroDAO must have its own rooms section.
- Ability to create new rooms from MicroDAO cabinet.
-
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.pycreates ~31 rooms (district rooms, lobbies, city lobby, etc.).city-serviceexposes/api/v1/city/rooms(already used by UI).- Rooms table already contains:
idslugname(title)descriptionzone(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
-
Fix online counter:
- Never show
NaNon the City Rooms page.
- Never show
-
MicroDAO Rooms UI:
- On
/microdao/[slug]display:- List of rooms belonging to this MicroDAO.
- Button "Створити кімнату".
- On
-
City Lobby CTA:
- On homepage and/or main menu:
- Button "Поспілкуватися з DAARWIZZ" that opens
DAARION City Lobby.
- Button "Поспілкуватися з DAARWIZZ" that opens
- On homepage and/or main menu:
4. Backend Tasks
4.1. Room model & repository
Files:
services/city-service/models_city.pyservices/city-service/repo_city.pyservices/city-service/routes_city.py
- Ensure Room model exposes needed fields:
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)
-
Repo method for city rooms:
get_all_rooms()must:- Return
members_onlineas integer (useCOALESCE(..., 0)).
- Return
-
Repo method for MicroDAO rooms: Add/verify method:
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'
- API routes:
- Verify endpoint:
GET /api/v1/city/roomsreturnsmembers_online: int. - Verify endpoint:
GET /city/microdao/{slug}/roomsreturns MicroDAO rooms. - Add endpoint for room creation:
- Verify endpoint:
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
- Online stats summary:
- Add/verify endpoint:
GET /api/v1/city/rooms/summary - Returns:
{"rooms_total": int, "online_total": int}
- Add/verify endpoint:
5. Frontend Tasks
Files:
apps/web/src/app/city/page.tsxapps/web/src/app/microdao/[slug]/page.tsxapps/web/src/app/page.tsx(homepage)apps/web/src/components/microdao/MicrodaoRoomsSection.tsx(new)
5.1. Fix NaN online stats
- In
city/page.tsx:- Ensure online count uses fallback:
const onlineTotal = summary?.online_total ?? 0;
// or
const onlineTotal = Number(summary?.online_total) || 0;
- If API returns
nullorundefined, display0.
5.2. MicroDAO Rooms section
In apps/web/src/app/microdao/[slug]/page.tsx:
- Add API call:
const rooms = await fetchMicrodaoRooms(slug); // GET /city/microdao/{slug}/rooms
- Render new section:
<section className="space-y-4">
<div className="flex items-center justify-between">
<h2 className="text-xl font-semibold">Кімнати MicroDAO</h2>
<Button onClick={openCreateRoomModal}>
<Plus className="w-4 h-4 mr-2" />
Створити кімнату
</Button>
</div>
{rooms.length === 0 ? (
<p className="text-muted-foreground">
Ще немає кімнат. Створіть першу кімнату для цієї платформи.
</p>
) : (
<div className="grid gap-3">
{rooms.map((room) => (
<MicrodaoRoomCard key={room.slug} room={room} />
))}
</div>
)}
</section>
-
MicrodaoRoomCardcomponent:- title
- description
- room_type (badge)
- visibility (Public/Private badge)
- members_online
-
"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
- On homepage (
apps/web/src/app/page.tsx):
<section className="py-12 text-center">
<h2 className="text-2xl font-bold mb-4">
Головний публічний чат DAARION City
</h2>
<p className="text-muted-foreground mb-6">
Поспілкуватися з DAARWIZZ та іншими громадянами міста.
</p>
<Link href="/city?room=city-lobby">
<Button size="lg" className="gap-2">
<MessageCircle className="w-5 h-5" />
Поспілкуватися з DAARWIZZ
</Button>
</Link>
</section>
- Optionally add to navigation header:
- New item: "City Lobby" →
/city?room=city-lobby
- New item: "City Lobby" →
6. Acceptance Criteria
-
City Rooms page shows:
- Correct number of rooms.
- Online count is integer (0 allowed), never
NaN.
-
MicroDAO page (
/microdao/daarion, etc.) shows:- "Кімнати MicroDAO" section.
- Ability to create a room.
- Newly created room appears in list.
-
Homepage shows:
- CTA "Поспілкуватися з DAARWIZZ".
- Clicking the button opens City Lobby room.
-
All routes work both on NODE1 and NODE2.