feat(district): District Interface Architecture v1
## Documentation - District_Interface_Architecture_v1.md - повна архітектура District Layer - District Space, Campus Map, Sub-DAOs, Portals - Золотий трикутник: City → District → MicroDAO ## Database - Migration 028: District rooms for Energyunion & GREENFOOD - Portal rooms on City Square ## Frontend - src/api/districts.ts - Districts API client - DistrictDashboard.tsx - District Dashboard UI component ## Key concepts: - District = MicroDAO type='district' - District Lead Agent (Helion, ERP-Agent) - Campus Map (2D) - Sub-DAOs management - District-to-City portals
This commit is contained in:
758
docs/foundation/District_Interface_Architecture_v1.md
Normal file
758
docs/foundation/District_Interface_Architecture_v1.md
Normal file
@@ -0,0 +1,758 @@
|
||||
# District_Interface_Architecture_v1.md
|
||||
|
||||
## DAARION.city — District Layer & Platform Interface Architecture
|
||||
|
||||
**Version:** 1.0
|
||||
**Status:** Foundation Spec (MVP)
|
||||
**Scope:** Архітектура дистриктів (платформ) у DAARION.city: District Space, портали в місті, взаємодія з MicroDAO, Campus Map, кімнати District-рівня, District Agents, золотий трикутник (City → District → MicroDAO).
|
||||
|
||||
---
|
||||
|
||||
# 0. Мета документа
|
||||
|
||||
Цей документ визначає **повну архітектуру District Layer** — третього ключового простору DAARION.city поруч з:
|
||||
|
||||
- **City Layer** (місто),
|
||||
- **MicroDAO Layer** (організації, команди).
|
||||
|
||||
District — це **платформа / мегаспільнота / галузевий район** у DAARION.city.
|
||||
|
||||
Документ визначає:
|
||||
|
||||
- District Space (інтерфейс дистрикту),
|
||||
- District Dashboard,
|
||||
- District Rooms,
|
||||
- District Campus Map (2D та майбутній 3D),
|
||||
- District Agents (платформні агенти),
|
||||
- портал дистрикту у місті,
|
||||
- підлеглі MicroDAO,
|
||||
- архітектуру публічних зон,
|
||||
- взаємодію з City та MicroDAO interface,
|
||||
- зв'язок з DAIS, Agents та Nodes.
|
||||
|
||||
---
|
||||
|
||||
# 1. Поняття District у DAARION.city
|
||||
|
||||
## 1.1. District — це MicroDAO з розширеним типом
|
||||
|
||||
```
|
||||
microdao.type = 'district'
|
||||
```
|
||||
|
||||
Рівень District додає:
|
||||
|
||||
- власний інтерфейс «платформи»,
|
||||
- власні кімнати,
|
||||
- власну карту (Campus Map),
|
||||
- публічний портал у City Square,
|
||||
- підлеглі MicroDAO,
|
||||
- своїх агентах-представників,
|
||||
- власне міні-місто всередині великого міста.
|
||||
|
||||
## 1.2. Приклади дистриктів
|
||||
|
||||
| District | Галузь | Lead Agent | Статус |
|
||||
|----------|--------|------------|--------|
|
||||
| **Energyunion** | Енергетика | Helion | ✅ Активний |
|
||||
| **GREENFOOD** | Агро/ERP | ERP-Agent | ✅ Активний |
|
||||
| **Health** | Здоров'я | — | 🔜 Planned |
|
||||
| **Logistics** | Логістика | — | 🔜 Planned |
|
||||
| **Robotics** | Роботехніка | — | 🔜 Planned |
|
||||
|
||||
---
|
||||
|
||||
# 2. District Space — окрема екосистема всередині міста
|
||||
|
||||
## 2.1. District Space = міні-місто всередині DAARION.city
|
||||
|
||||
Кожен District має свою:
|
||||
|
||||
- **центральну площу** (District Center),
|
||||
- **групу кімнат** (District Rooms),
|
||||
- **власних публічних агентів** (District Agents),
|
||||
- **кабінети команди** (Core-Team Console),
|
||||
- **підлеглі MicroDAO** (Sub-DAOs),
|
||||
- **власну карту** (Campus Map),
|
||||
- **корпоративні/галузеві сервіси**,
|
||||
- **власні ноди** (District Infrastructure).
|
||||
|
||||
## 2.2. Ієрархія просторів
|
||||
|
||||
```
|
||||
DAARION.city (City Layer)
|
||||
│
|
||||
├── City Square (центральна площа)
|
||||
│
|
||||
├── District: Energyunion
|
||||
│ ├── District Center
|
||||
│ ├── District Rooms
|
||||
│ ├── Sub-DAO: SolarFarm1
|
||||
│ ├── Sub-DAO: WindPark2
|
||||
│ └── Campus Map
|
||||
│
|
||||
├── District: GREENFOOD
|
||||
│ ├── District Center
|
||||
│ ├── District Rooms
|
||||
│ ├── Sub-DAO: Farm1
|
||||
│ └── Campus Map
|
||||
│
|
||||
└── Standard MicroDAO (без District)
|
||||
```
|
||||
|
||||
Умовно:
|
||||
> **City** = глобальне місто
|
||||
> **District** = район площею 100+ будівель
|
||||
> **MicroDAO** = будівля / організація всередині району
|
||||
|
||||
---
|
||||
|
||||
# 3. District Portal у місті
|
||||
|
||||
## 3.1. Портал на City Square
|
||||
|
||||
Кожен District має **публічний кіоск/вітрину** на City Square:
|
||||
|
||||
```yaml
|
||||
rooms:
|
||||
- id: district-energyunion-front
|
||||
owner_type: 'microdao'
|
||||
owner_id: 'energyunion'
|
||||
type: 'front-room'
|
||||
space_scope: 'city'
|
||||
visibility: 'public-city'
|
||||
is_portal: true
|
||||
portal_target_microdao_id: 'energyunion'
|
||||
primary_agent_id: 'helion'
|
||||
map_x: 100
|
||||
map_y: 50
|
||||
zone: 'energy-sector'
|
||||
```
|
||||
|
||||
## 3.2. Що відображається на порталі
|
||||
|
||||
| Елемент | Опис |
|
||||
|---------|------|
|
||||
| District Name | Назва дистрикту |
|
||||
| District Logo | Логотип/аватар |
|
||||
| Lead Agent | Helion, ERP-Agent |
|
||||
| Public Rooms | Новини, Help, FAQ |
|
||||
| Stats | Кількість DAO, агентів |
|
||||
| "Увійти" | Кнопка переходу в District Space |
|
||||
|
||||
## 3.3. Візуальне представлення
|
||||
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ CITY SQUARE │
|
||||
│ │
|
||||
│ ┌─────────┐ ┌─────────┐ │
|
||||
│ │ENERGY │ │GREEN │ │
|
||||
│ │UNION │ │FOOD │ │
|
||||
│ │ 🔋 │ │ 🌿 │ │
|
||||
│ │ Helion │ │ ERP │ │
|
||||
│ │[Увійти] │ │[Увійти] │ │
|
||||
│ └─────────┘ └─────────┘ │
|
||||
│ │
|
||||
│ [DARIO] [DARIA] │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 4. District Dashboard
|
||||
|
||||
## 4.1. URL Structure
|
||||
|
||||
```
|
||||
/district/{id}
|
||||
/district/{id}/dashboard
|
||||
/district/{id}/rooms
|
||||
/district/{id}/subdaos
|
||||
/district/{id}/map
|
||||
/district/{id}/agents
|
||||
/district/{id}/nodes
|
||||
/district/{id}/events
|
||||
```
|
||||
|
||||
## 4.2. Елементи District Dashboard
|
||||
|
||||
### 4.2.1. Primary Agent (District Lead Agent)
|
||||
|
||||
```typescript
|
||||
interface DistrictDashboard {
|
||||
primaryAgent: {
|
||||
id: string; // 'helion'
|
||||
name: string; // 'Helion'
|
||||
role: string; // 'District Lead'
|
||||
avatar: string;
|
||||
status: 'online' | 'busy' | 'offline';
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Приклади:
|
||||
- **Helion** для Energyunion
|
||||
- **ERP-Agent** для GREENFOOD
|
||||
|
||||
### 4.2.2. Team Agents
|
||||
|
||||
| Role | Agent | Функція |
|
||||
|------|-------|---------|
|
||||
| Business Lead | BusinessBot | Бізнес-питання |
|
||||
| Tech Lead | TechBot | Технічна підтримка |
|
||||
| Analyst | DataBot | Аналітика галузі |
|
||||
| Integrations | BridgeBot | Інтеграції |
|
||||
|
||||
### 4.2.3. District Stats
|
||||
|
||||
```typescript
|
||||
interface DistrictStats {
|
||||
subDaoCount: number; // Кількість підлеглих MicroDAO
|
||||
activeAgents: number; // Активні агенти платформи
|
||||
nodeCount: number; // Кількість нод
|
||||
memberCount: number; // Загальна кількість учасників
|
||||
eventsThisWeek: number; // Активність
|
||||
gpuCapacity: string; // "120 TFLOPS"
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2.4. District Rooms Preview
|
||||
|
||||
- Центральна кімната
|
||||
- Новини
|
||||
- Help
|
||||
- Події
|
||||
- Аналітика галузі
|
||||
|
||||
### 4.2.5. Campus Map Preview
|
||||
|
||||
- Мініатюра 2D-карти
|
||||
- Позиції Sub-DAOs
|
||||
- Кнопка "Відкрити повну карту"
|
||||
|
||||
### 4.2.6. Sub-DAOs List
|
||||
|
||||
```typescript
|
||||
interface SubDAO {
|
||||
id: string;
|
||||
name: string;
|
||||
status: 'active' | 'pending' | 'archived';
|
||||
memberCount: number;
|
||||
primaryAgent: string;
|
||||
frontRoomId?: string;
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2.7. District Nodes
|
||||
|
||||
- Список нод платформи
|
||||
- GPU/CPU ресурси
|
||||
- Статус здоров'я
|
||||
|
||||
---
|
||||
|
||||
# 5. District Rooms (кімнати дистрикту)
|
||||
|
||||
## 5.1. Internal Rooms (внутрішні)
|
||||
|
||||
| Room ID | Назва | Доступ |
|
||||
|---------|-------|--------|
|
||||
| `{district}-strategy` | Стратегія | Core-team |
|
||||
| `{district}-tech` | Технічна команда | Core-team |
|
||||
| `{district}-business` | Бізнес-команда | Core-team |
|
||||
| `{district}-docs` | Документи | Members |
|
||||
|
||||
## 5.2. Public Rooms
|
||||
|
||||
| Room ID | Назва | Доступ |
|
||||
|---------|-------|--------|
|
||||
| `{district}-news` | Новини | Public |
|
||||
| `{district}-help` | Підтримка | Public |
|
||||
| `{district}-events` | Події | Public |
|
||||
| `{district}-faq` | FAQ | Public |
|
||||
| `{district}-discussions` | Обговорення | Members |
|
||||
|
||||
## 5.3. Portal Rooms (для Sub-DAOs)
|
||||
|
||||
Кожне підлегле MicroDAO може виставити свій **портал у дистрикт**:
|
||||
|
||||
```yaml
|
||||
rooms:
|
||||
- id: subdao-solarfarm1-front
|
||||
owner_type: 'microdao'
|
||||
owner_id: 'solarfarm1'
|
||||
type: 'front-room'
|
||||
space_scope: 'district'
|
||||
visibility: 'public-city'
|
||||
is_portal: true
|
||||
portal_target_microdao_id: 'solarfarm1'
|
||||
```
|
||||
|
||||
## 5.4. Room Data Model
|
||||
|
||||
```sql
|
||||
-- District rooms мають space_scope = 'district'
|
||||
INSERT INTO rooms (id, owner_type, owner_id, type, space_scope, visibility, name, primary_agent_id)
|
||||
VALUES
|
||||
('energyunion-center', 'microdao', 'energyunion', 'district-room', 'district', 'members', 'Energy Center', 'helion'),
|
||||
('energyunion-news', 'microdao', 'energyunion', 'district-room', 'district', 'public-city', 'Energy News', 'helion'),
|
||||
('energyunion-help', 'microdao', 'energyunion', 'district-room', 'district', 'public-city', 'Energy Help', 'helion');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 6. District Campus Map (2D)
|
||||
|
||||
## 6.1. Концепція
|
||||
|
||||
Карта дистрикту — це:
|
||||
|
||||
- окрема 2D-мапа платформи,
|
||||
- подібна до City Map, але локальна,
|
||||
- центральна площа District Center,
|
||||
- розташування підлеглих MicroDAO,
|
||||
- інфраструктурні ноди платформи.
|
||||
|
||||
## 6.2. Елементи карти
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────┐
|
||||
│ ENERGYUNION CAMPUS │
|
||||
│ │
|
||||
│ ┌─────┐ ┌─────┐ │
|
||||
│ │Solar│ │Wind │ │
|
||||
│ │Farm1│ │Park2│ │
|
||||
│ └──┬──┘ └──┬──┘ │
|
||||
│ │ │ │
|
||||
│ └───────┬───────┘ │
|
||||
│ │ │
|
||||
│ ┌──────┴──────┐ │
|
||||
│ │ DISTRICT │ │
|
||||
│ │ CENTER │ │
|
||||
│ │ [Helion] │ │
|
||||
│ └─────────────┘ │
|
||||
│ │
|
||||
│ ┌─────┐ ┌─────┐ ┌─────┐ │
|
||||
│ │Node1│ │Node2│ │Node3│ │
|
||||
│ │ GPU │ │ GPU │ │ IoT │ │
|
||||
│ └─────┘ └─────┘ └─────┘ │
|
||||
│ │
|
||||
│ [NEWS] [HELP] [EVENTS] [EXIT→CITY] │
|
||||
└────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 6.3. Map Data Model
|
||||
|
||||
```typescript
|
||||
interface DistrictMapElement {
|
||||
id: string;
|
||||
type: 'subdao' | 'room' | 'node' | 'agent' | 'portal';
|
||||
x: number;
|
||||
y: number;
|
||||
zone: string;
|
||||
label: string;
|
||||
icon: string;
|
||||
targetId: string; // ID для переходу
|
||||
}
|
||||
|
||||
interface DistrictMap {
|
||||
districtId: string;
|
||||
width: number;
|
||||
height: number;
|
||||
zones: string[];
|
||||
elements: DistrictMapElement[];
|
||||
background: string; // SVG або image
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 7. District Agents
|
||||
|
||||
## 7.1. District Lead Agent (primary_agent)
|
||||
|
||||
Головний агент дистрикту:
|
||||
|
||||
| District | Lead Agent | Роль |
|
||||
|----------|------------|------|
|
||||
| Energyunion | **Helion** | Energy Platform Lead |
|
||||
| GREENFOOD | **ERP-Agent** | Agro Platform Lead |
|
||||
|
||||
```typescript
|
||||
interface DistrictLeadAgent {
|
||||
id: string;
|
||||
name: string;
|
||||
districtId: string;
|
||||
role: 'district-lead';
|
||||
serviceScope: 'district';
|
||||
capabilities: string[];
|
||||
publicProfile: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
## 7.2. District Core-team Agents
|
||||
|
||||
```typescript
|
||||
const districtCoreTeam = [
|
||||
{ role: 'District CTO', agent: 'district-cto-agent' },
|
||||
{ role: 'District Analyst', agent: 'district-analyst-agent' },
|
||||
{ role: 'District Manager', agent: 'district-manager-agent' },
|
||||
{ role: 'District Integrations', agent: 'district-bridge-agent' },
|
||||
{ role: 'District Security', agent: 'district-security-agent' },
|
||||
];
|
||||
```
|
||||
|
||||
## 7.3. Public-facing Agents
|
||||
|
||||
Агенти, доступні для клієнтів/учасників платформи:
|
||||
|
||||
- Відповідають у публічних кімнатах
|
||||
- Обробляють запити з City Square
|
||||
- Консультують щодо сервісів дистрикту
|
||||
|
||||
## 7.4. Agent Hierarchy
|
||||
|
||||
```
|
||||
District Lead Agent (Helion)
|
||||
│
|
||||
├── District Core-Team
|
||||
│ ├── CTO Agent
|
||||
│ ├── Analyst Agent
|
||||
│ └── Security Agent
|
||||
│
|
||||
└── Sub-DAO Agents
|
||||
├── SolarFarm1 Orchestrator
|
||||
└── WindPark2 Orchestrator
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 8. District → MicroDAO зв'язок
|
||||
|
||||
## 8.1. Підлеглі MicroDAO
|
||||
|
||||
District володіє набором підлеглих MicroDAO:
|
||||
|
||||
```sql
|
||||
-- MicroDAO з parent_microdao_id = district_id
|
||||
SELECT * FROM microdaos
|
||||
WHERE parent_microdao_id = 'energyunion';
|
||||
```
|
||||
|
||||
## 8.2. Що отримує Sub-DAO
|
||||
|
||||
| Перевага | Опис |
|
||||
|----------|------|
|
||||
| District Rooms | Доступ до кімнат платформи |
|
||||
| Shared Marketplace | Спільний ринок послуг |
|
||||
| Campus Map | Позиція на карті дистрикту |
|
||||
| Core-team Support | Підтримка від District агентів |
|
||||
| Shared Nodes | Доступ до інфраструктури |
|
||||
|
||||
## 8.3. Sub-DAO Front-room
|
||||
|
||||
MicroDAO може мати:
|
||||
- свій front-room у District Center,
|
||||
- свого агента-представника,
|
||||
- позицію на Campus Map.
|
||||
|
||||
```yaml
|
||||
subdao_front_room:
|
||||
id: 'solarfarm1-front-in-district'
|
||||
owner_id: 'solarfarm1'
|
||||
space_scope: 'district'
|
||||
parent_district_id: 'energyunion'
|
||||
map_x: 50
|
||||
map_y: 30
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 9. District → City зв'язок
|
||||
|
||||
## 9.1. Portal на City Square
|
||||
|
||||
Головний спосіб взаємодії District з містом:
|
||||
|
||||
```typescript
|
||||
interface DistrictCityPortal {
|
||||
districtId: string;
|
||||
portalRoomId: string;
|
||||
position: { x: number; y: number };
|
||||
zone: 'energy-sector' | 'agro-sector' | 'health-sector';
|
||||
visibility: 'public-city';
|
||||
primaryAgent: string;
|
||||
}
|
||||
```
|
||||
|
||||
## 9.2. City News Integration
|
||||
|
||||
Новини та події District потрапляють до City News:
|
||||
|
||||
```typescript
|
||||
// Публікація новини в City
|
||||
await publishToCityNews({
|
||||
source: 'district',
|
||||
sourceId: 'energyunion',
|
||||
title: 'Нова сонячна станція',
|
||||
content: '...',
|
||||
agentId: 'helion',
|
||||
});
|
||||
```
|
||||
|
||||
## 9.3. District Agents у City
|
||||
|
||||
District Lead Agents доступні як публічні агенти:
|
||||
- Helion відображається в City Agents каталозі
|
||||
- Можна поговорити з Helion з City Square
|
||||
|
||||
## 9.4. District Nodes у City Infrastructure
|
||||
|
||||
```typescript
|
||||
// Ноди дистрикту видимі в City Infrastructure View
|
||||
const districtNodes = await getNodesByMicrodao('energyunion');
|
||||
// Відображаються в /city/infrastructure
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 10. District Interface API
|
||||
|
||||
## 10.1. District Routes
|
||||
|
||||
```typescript
|
||||
// GET /api/v1/districts
|
||||
// GET /api/v1/districts/:id
|
||||
// GET /api/v1/districts/:id/dashboard
|
||||
// GET /api/v1/districts/:id/rooms
|
||||
// GET /api/v1/districts/:id/subdaos
|
||||
// GET /api/v1/districts/:id/map
|
||||
// GET /api/v1/districts/:id/agents
|
||||
// GET /api/v1/districts/:id/nodes
|
||||
// GET /api/v1/districts/:id/stats
|
||||
// POST /api/v1/districts/:id/subdaos (add Sub-DAO)
|
||||
// POST /api/v1/districts/:id/rooms (create room)
|
||||
```
|
||||
|
||||
## 10.2. District Dashboard API
|
||||
|
||||
```typescript
|
||||
interface DistrictDashboardResponse {
|
||||
district: {
|
||||
id: string;
|
||||
name: string;
|
||||
type: 'district';
|
||||
primaryAgent: Agent;
|
||||
teamAgents: Agent[];
|
||||
};
|
||||
stats: DistrictStats;
|
||||
rooms: Room[];
|
||||
subdaos: Microdao[];
|
||||
map: DistrictMap;
|
||||
nodes: Node[];
|
||||
recentEvents: Event[];
|
||||
}
|
||||
```
|
||||
|
||||
## 10.3. District Map API
|
||||
|
||||
```typescript
|
||||
// GET /api/v1/districts/:id/map
|
||||
interface DistrictMapResponse {
|
||||
districtId: string;
|
||||
name: string;
|
||||
dimensions: { width: number; height: number };
|
||||
zones: Zone[];
|
||||
elements: MapElement[];
|
||||
connections: Connection[];
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 11. District Interface: UI Structure
|
||||
|
||||
## 11.1. District Navigation
|
||||
|
||||
```typescript
|
||||
const districtNavItems = [
|
||||
{ path: '/district/:id', label: 'Dashboard', icon: '🏠' },
|
||||
{ path: '/district/:id/rooms', label: 'Rooms', icon: '💬' },
|
||||
{ path: '/district/:id/subdaos', label: 'Sub-DAOs', icon: '🏢' },
|
||||
{ path: '/district/:id/map', label: 'Campus Map', icon: '🗺️' },
|
||||
{ path: '/district/:id/agents', label: 'Agents', icon: '🤖' },
|
||||
{ path: '/district/:id/nodes', label: 'Nodes', icon: '🖥️' },
|
||||
{ path: '/district/:id/events', label: 'Events', icon: '📅' },
|
||||
];
|
||||
```
|
||||
|
||||
## 11.2. District Center (головна сторінка)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ [← City] ENERGYUNION DISTRICT [Settings] │
|
||||
├─────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌─────────────────────────┐ │
|
||||
│ │ HELION │ │ District Stats │ │
|
||||
│ │ 🔋 │ │ Sub-DAOs: 12 │ │
|
||||
│ │ Lead Agent │ │ Agents: 45 │ │
|
||||
│ │ [Chat] │ │ Nodes: 8 │ │
|
||||
│ └──────────────┘ │ Members: 234 │ │
|
||||
│ └─────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────┐│
|
||||
│ │ CAMPUS MAP (preview) ││
|
||||
│ │ [Solar] [Wind] [Center] [Storage] ││
|
||||
│ │ [View Full Map →] ││
|
||||
│ └─────────────────────────────────────────────┘│
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │📰 News │ │❓ Help │ │📅 Events │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ │
|
||||
│ │
|
||||
│ Sub-DAOs: │
|
||||
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
||||
│ │SolarFarm│ │WindPark │ │Storage │ [+Add] │
|
||||
│ └─────────┘ └─────────┘ └─────────┘ │
|
||||
└─────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 12. District Registration & Lifecycle
|
||||
|
||||
## 12.1. Як створюється District
|
||||
|
||||
Дистрикт може створити:
|
||||
|
||||
1. **Оркестратор MicroDAO** — промоутить своє DAO до District
|
||||
2. **City-level процес** — рішення DAARWIZZ / City Governance
|
||||
3. **Автоматичний алгоритм** — на основі активності та масштабу
|
||||
|
||||
## 12.2. Promotion Flow
|
||||
|
||||
```
|
||||
MicroDAO (type='standard')
|
||||
│
|
||||
├── Виконано умови:
|
||||
│ ├── 5+ Sub-DAOs
|
||||
│ ├── 100+ учасників
|
||||
│ ├── Активний 3+ місяці
|
||||
│ └── Governance approval
|
||||
│
|
||||
▼
|
||||
MicroDAO (type='district')
|
||||
│
|
||||
├── Отримує:
|
||||
│ ├── District Dashboard
|
||||
│ ├── Campus Map
|
||||
│ ├── City Portal
|
||||
│ └── District Agent roles
|
||||
```
|
||||
|
||||
## 12.3. Event
|
||||
|
||||
```typescript
|
||||
// dagion.microdao.promoted_to_district
|
||||
{
|
||||
microdaoId: 'energyunion',
|
||||
promotedByAgentId: 'daarwizz',
|
||||
parentMicrodaoId: null,
|
||||
timestamp: '2025-11-29T23:30:00Z'
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 13. MVP Scope
|
||||
|
||||
## 13.1. Обов'язково для MVP
|
||||
|
||||
| Компонент | Статус |
|
||||
|-----------|--------|
|
||||
| District Dashboard | 🔜 Required |
|
||||
| District Rooms (2-3 public) | 🔜 Required |
|
||||
| District Lead Agent | 🔜 Required |
|
||||
| District Portal на City Square | 🔜 Required |
|
||||
| Список підлеглих MicroDAO | 🔜 Required |
|
||||
| District Campus Map (базова 2D) | 🔜 Required |
|
||||
| Public-facing Agent (Helion/ERP) | 🔜 Required |
|
||||
|
||||
## 13.2. Після MVP
|
||||
|
||||
| Компонент | Priority |
|
||||
|-----------|----------|
|
||||
| Інтерактивна 2D карта | Medium |
|
||||
| 3D Campus | Low |
|
||||
| District Events system | Medium |
|
||||
| Міні-економіка дистрикту | Low |
|
||||
| Графи взаємодії DAO | Low |
|
||||
| District-to-District | Low |
|
||||
|
||||
---
|
||||
|
||||
# 14. Зв'язок з іншими документами
|
||||
|
||||
| Документ | Зв'язок |
|
||||
|----------|---------|
|
||||
| `DAARION_Ontology_Core_v1.md` | District = MicroDAO type='district' |
|
||||
| `Rooms_Layer_Architecture_v1.md` | District Rooms, space_scope='district' |
|
||||
| `City_Interface_Architecture_v1.md` | District Portal на City Square |
|
||||
| `MicroDAO_Interface_Architecture_v1.md` | Sub-DAO структура |
|
||||
| `Agents_Interface_Architecture_v1.md` | District Lead Agent, team agents |
|
||||
| `Nodes_Interface_Architecture_v1.md` | District Nodes |
|
||||
| `microdao_Data_Model_UPDATE_v1.md` | parent_microdao_id, dao_type |
|
||||
|
||||
---
|
||||
|
||||
# 15. Підсумок
|
||||
|
||||
Цей документ визначає:
|
||||
|
||||
- **структуру District Space** — міні-місто в місті,
|
||||
- **District Dashboard** — центр керування платформою,
|
||||
- **District Rooms** — кімнати різних рівнів доступу,
|
||||
- **District Campus Map** — 2D карта дистрикту,
|
||||
- **District Agents** — Lead Agent + Core-team,
|
||||
- **Portal у City Square** — вітрина в місті,
|
||||
- **Sub-DAOs** — підлеглі MicroDAO,
|
||||
- **API та UI** — маршрути та інтерфейс.
|
||||
|
||||
## Золотий трикутник DAARION.city:
|
||||
|
||||
```
|
||||
┌─────────────┐
|
||||
│ CITY │
|
||||
│ (глобальне │
|
||||
│ місто) │
|
||||
└──────┬──────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
┌───▼───┐ ┌───▼───┐ ┌───▼───┐
|
||||
│DISTRICT│ │DISTRICT│ │DISTRICT│
|
||||
│Energy │ │Green │ │Health │
|
||||
│Union │ │Food │ │ │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
┌───▼───┐ ┌───▼───┐ ┌───▼───┐
|
||||
│MicroDAO│ │MicroDAO│ │MicroDAO│
|
||||
│Solar1 │ │Farm1 │ │Clinic1 │
|
||||
└────────┘ └────────┘ └────────┘
|
||||
```
|
||||
|
||||
**DAARION.city → District → MicroDAO**
|
||||
**місто → район → організація**
|
||||
|
||||
District — це «галузевий космос» у місті, що об'єднує десятки MicroDAO під спільною платформою.
|
||||
|
||||
---
|
||||
|
||||
**Документ №13 завершено.**
|
||||
|
||||
Готовий до наступного фундаментального документа:
|
||||
- **DAIS_Layer_Architecture_v1.md**, або
|
||||
- **Agent_Governance_Protocol_v1.md**
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
## Статус: ✅ FOUNDATION_UPDATE Complete
|
||||
|
||||
**Всього файлів:** 19 (12 основних + 6 helpers + 1 patch)
|
||||
**Всього файлів:** 20 (13 основних + 6 helpers + 1 patch)
|
||||
|
||||
---
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
| 6 | [`microdao_Governance_And_Permissions_v1.md`](./microdao_Governance_And_Permissions_v1.md) | Ролі, ACL, governance MicroDAO/District |
|
||||
| 7 | [`DAARION_Identity_And_Access_Draft_v1.md`](./DAARION_Identity_And_Access_Draft_v1.md) | DAIS як IAM: DID, keys, wallets, trust levels |
|
||||
|
||||
### Rooms та інтерфейси (8-12)
|
||||
### Rooms та інтерфейси (8-13)
|
||||
|
||||
| № | Файл | Опис |
|
||||
|---|------|------|
|
||||
@@ -33,6 +33,7 @@
|
||||
| 10 | [`City_Interface_Architecture_v1.md`](./City_Interface_Architecture_v1.md) | City Square, DARIO/DARIA, public rooms, portals |
|
||||
| 11 | [`Agents_Interface_Architecture_v1.md`](./Agents_Interface_Architecture_v1.md) | Agent-centric UI: primary/team agents, кабінети |
|
||||
| 12 | [`Nodes_Interface_Architecture_v1.md`](./Nodes_Interface_Architecture_v1.md) | Node dashboards, registration, health, DAGI Mesh |
|
||||
| 13 | [`District_Interface_Architecture_v1.md`](./District_Interface_Architecture_v1.md) | **NEW** District Layer: Campus Map, Sub-DAOs, Portals |
|
||||
|
||||
---
|
||||
|
||||
|
||||
69
migrations/028_district_rooms_seed.sql
Normal file
69
migrations/028_district_rooms_seed.sql
Normal file
@@ -0,0 +1,69 @@
|
||||
-- Migration 028: District Rooms Seed Data
|
||||
-- Purpose: Create initial rooms for Energyunion and GREENFOOD districts
|
||||
-- Based on: docs/foundation/District_Interface_Architecture_v1.md
|
||||
-- Date: 2025-11-29
|
||||
|
||||
-- ============================================================================
|
||||
-- 1. ENERGYUNION District Rooms
|
||||
-- ============================================================================
|
||||
|
||||
INSERT INTO rooms (id, owner_type, owner_id, type, space_scope, visibility, name, description, primary_agent_id, is_portal)
|
||||
VALUES
|
||||
-- District Center
|
||||
('energyunion-center', 'microdao', 'energyunion', 'district-room', 'district', 'members', 'Energy Center', 'Central hub of Energyunion district', 'helion', false),
|
||||
|
||||
-- Public Rooms
|
||||
('energyunion-news', 'microdao', 'energyunion', 'district-room', 'district', 'public-city', 'Energy News', 'Latest news from Energyunion', 'helion', false),
|
||||
('energyunion-help', 'microdao', 'energyunion', 'district-room', 'district', 'public-city', 'Energy Help', 'Support and assistance for energy platform', 'helion', false),
|
||||
('energyunion-events', 'microdao', 'energyunion', 'district-room', 'district', 'public-city', 'Energy Events', 'Events and activities in energy sector', 'helion', false),
|
||||
|
||||
-- District Portal on City Square
|
||||
('energyunion-city-portal', 'microdao', 'energyunion', 'front-room', 'city', 'public-city', 'Energyunion Portal', 'Energyunion district entrance on City Square', 'helion', true)
|
||||
ON CONFLICT (id) DO UPDATE SET
|
||||
name = EXCLUDED.name,
|
||||
description = EXCLUDED.description,
|
||||
primary_agent_id = EXCLUDED.primary_agent_id;
|
||||
|
||||
-- Set portal target
|
||||
UPDATE rooms SET portal_target_microdao_id = 'energyunion', map_x = 100, map_y = 50, zone = 'energy-sector'
|
||||
WHERE id = 'energyunion-city-portal';
|
||||
|
||||
-- ============================================================================
|
||||
-- 2. GREENFOOD District Rooms
|
||||
-- ============================================================================
|
||||
|
||||
INSERT INTO rooms (id, owner_type, owner_id, type, space_scope, visibility, name, description, primary_agent_id, is_portal)
|
||||
VALUES
|
||||
-- District Center
|
||||
('greenfood-center', 'microdao', 'greenfood', 'district-room', 'district', 'members', 'GreenFood Center', 'Central hub of GREENFOOD district', 'erp-agent', false),
|
||||
|
||||
-- Public Rooms
|
||||
('greenfood-news', 'microdao', 'greenfood', 'district-room', 'district', 'public-city', 'GreenFood News', 'Latest news from GREENFOOD', 'erp-agent', false),
|
||||
('greenfood-help', 'microdao', 'greenfood', 'district-room', 'district', 'public-city', 'GreenFood Help', 'Support and assistance for agro platform', 'erp-agent', false),
|
||||
('greenfood-marketplace', 'microdao', 'greenfood', 'district-room', 'district', 'public-city', 'GreenFood Marketplace', 'Agricultural products and services', 'erp-agent', false),
|
||||
|
||||
-- District Portal on City Square
|
||||
('greenfood-city-portal', 'microdao', 'greenfood', 'front-room', 'city', 'public-city', 'GREENFOOD Portal', 'GREENFOOD district entrance on City Square', 'erp-agent', true)
|
||||
ON CONFLICT (id) DO UPDATE SET
|
||||
name = EXCLUDED.name,
|
||||
description = EXCLUDED.description,
|
||||
primary_agent_id = EXCLUDED.primary_agent_id;
|
||||
|
||||
-- Set portal target
|
||||
UPDATE rooms SET portal_target_microdao_id = 'greenfood', map_x = 200, map_y = 50, zone = 'agro-sector'
|
||||
WHERE id = 'greenfood-city-portal';
|
||||
|
||||
-- ============================================================================
|
||||
-- 3. Update City Square with district portals
|
||||
-- ============================================================================
|
||||
|
||||
-- Add team_agent_ids to city rooms
|
||||
UPDATE rooms SET team_agent_ids = ARRAY['daria', 'daarwizz']
|
||||
WHERE id = 'city-square';
|
||||
|
||||
-- ============================================================================
|
||||
-- Done
|
||||
-- ============================================================================
|
||||
|
||||
SELECT 'Migration 028 completed: District rooms created for Energyunion and GREENFOOD' as result;
|
||||
|
||||
211
src/api/districts.ts
Normal file
211
src/api/districts.ts
Normal file
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
* Districts API Client
|
||||
* Based on: docs/foundation/District_Interface_Architecture_v1.md
|
||||
*/
|
||||
|
||||
import { apiClient } from './client';
|
||||
import type {
|
||||
Microdao,
|
||||
Room,
|
||||
Node,
|
||||
Agent,
|
||||
AgentAssignment
|
||||
} from '../types/ontology';
|
||||
|
||||
const BASE_URL = '/api/v1/districts';
|
||||
|
||||
// ============================================================================
|
||||
// Types
|
||||
// ============================================================================
|
||||
|
||||
export interface DistrictStats {
|
||||
subDaoCount: number;
|
||||
activeAgents: number;
|
||||
nodeCount: number;
|
||||
memberCount: number;
|
||||
eventsThisWeek: number;
|
||||
gpuCapacity?: string;
|
||||
}
|
||||
|
||||
export interface DistrictMapElement {
|
||||
id: string;
|
||||
type: 'subdao' | 'room' | 'node' | 'agent' | 'portal';
|
||||
x: number;
|
||||
y: number;
|
||||
zone: string;
|
||||
label: string;
|
||||
icon: string;
|
||||
targetId: string;
|
||||
}
|
||||
|
||||
export interface DistrictMap {
|
||||
districtId: string;
|
||||
name: string;
|
||||
dimensions: { width: number; height: number };
|
||||
zones: string[];
|
||||
elements: DistrictMapElement[];
|
||||
background?: string;
|
||||
}
|
||||
|
||||
export interface DistrictDashboard {
|
||||
district: Microdao & { type: 'district' };
|
||||
primaryAgent: Agent;
|
||||
teamAgents: Agent[];
|
||||
stats: DistrictStats;
|
||||
rooms: Room[];
|
||||
subdaos: Microdao[];
|
||||
nodes: Node[];
|
||||
recentEvents: Array<{
|
||||
id: string;
|
||||
type: string;
|
||||
title: string;
|
||||
timestamp: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface District extends Microdao {
|
||||
type: 'district';
|
||||
leadAgentId: string;
|
||||
portalRoomId?: string;
|
||||
campusMapId?: string;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// API Functions
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Get all districts
|
||||
*/
|
||||
export async function getDistricts(): Promise<District[]> {
|
||||
const response = await apiClient.get<{ data: District[] }>(BASE_URL);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get district by ID
|
||||
*/
|
||||
export async function getDistrict(districtId: string): Promise<District> {
|
||||
const response = await apiClient.get<{ data: District }>(
|
||||
`${BASE_URL}/${districtId}`
|
||||
);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get district dashboard
|
||||
*/
|
||||
export async function getDistrictDashboard(
|
||||
districtId: string
|
||||
): Promise<DistrictDashboard> {
|
||||
const response = await apiClient.get<{ data: DistrictDashboard }>(
|
||||
`${BASE_URL}/${districtId}/dashboard`
|
||||
);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get district rooms
|
||||
*/
|
||||
export async function getDistrictRooms(districtId: string): Promise<Room[]> {
|
||||
const response = await apiClient.get<{ data: Room[] }>(
|
||||
`${BASE_URL}/${districtId}/rooms`
|
||||
);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get district sub-DAOs
|
||||
*/
|
||||
export async function getDistrictSubDaos(
|
||||
districtId: string
|
||||
): Promise<Microdao[]> {
|
||||
const response = await apiClient.get<{ data: Microdao[] }>(
|
||||
`${BASE_URL}/${districtId}/subdaos`
|
||||
);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get district campus map
|
||||
*/
|
||||
export async function getDistrictMap(districtId: string): Promise<DistrictMap> {
|
||||
const response = await apiClient.get<{ data: DistrictMap }>(
|
||||
`${BASE_URL}/${districtId}/map`
|
||||
);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get district agents
|
||||
*/
|
||||
export async function getDistrictAgents(districtId: string): Promise<Agent[]> {
|
||||
const response = await apiClient.get<{ data: Agent[] }>(
|
||||
`${BASE_URL}/${districtId}/agents`
|
||||
);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get district nodes
|
||||
*/
|
||||
export async function getDistrictNodes(districtId: string): Promise<Node[]> {
|
||||
const response = await apiClient.get<{ data: Node[] }>(
|
||||
`${BASE_URL}/${districtId}/nodes`
|
||||
);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get district stats
|
||||
*/
|
||||
export async function getDistrictStats(
|
||||
districtId: string
|
||||
): Promise<DistrictStats> {
|
||||
const response = await apiClient.get<{ data: DistrictStats }>(
|
||||
`${BASE_URL}/${districtId}/stats`
|
||||
);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add sub-DAO to district
|
||||
*/
|
||||
export async function addSubDao(
|
||||
districtId: string,
|
||||
microdaoId: string
|
||||
): Promise<void> {
|
||||
await apiClient.post(`${BASE_URL}/${districtId}/subdaos`, { microdaoId });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create district room
|
||||
*/
|
||||
export async function createDistrictRoom(
|
||||
districtId: string,
|
||||
room: Partial<Room>
|
||||
): Promise<Room> {
|
||||
const response = await apiClient.post<{ data: Room }>(
|
||||
`${BASE_URL}/${districtId}/rooms`,
|
||||
room
|
||||
);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// React Query Keys
|
||||
// ============================================================================
|
||||
|
||||
export const districtKeys = {
|
||||
all: ['districts'] as const,
|
||||
list: () => [...districtKeys.all, 'list'] as const,
|
||||
detail: (id: string) => [...districtKeys.all, 'detail', id] as const,
|
||||
dashboard: (id: string) => [...districtKeys.all, 'dashboard', id] as const,
|
||||
rooms: (id: string) => [...districtKeys.all, 'rooms', id] as const,
|
||||
subdaos: (id: string) => [...districtKeys.all, 'subdaos', id] as const,
|
||||
map: (id: string) => [...districtKeys.all, 'map', id] as const,
|
||||
agents: (id: string) => [...districtKeys.all, 'agents', id] as const,
|
||||
nodes: (id: string) => [...districtKeys.all, 'nodes', id] as const,
|
||||
stats: (id: string) => [...districtKeys.all, 'stats', id] as const,
|
||||
};
|
||||
|
||||
290
src/features/district/components/DistrictDashboard.tsx
Normal file
290
src/features/district/components/DistrictDashboard.tsx
Normal file
@@ -0,0 +1,290 @@
|
||||
/**
|
||||
* District Dashboard Component
|
||||
* Based on: docs/foundation/District_Interface_Architecture_v1.md
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useParams, Link } from 'react-router-dom';
|
||||
import { getDistrictDashboard, districtKeys } from '../../../api/districts';
|
||||
import { MicrodaoTypeBadge, NodeStatusBadge } from '../../ontology/components/OntologyBadge';
|
||||
|
||||
export function DistrictDashboard() {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
|
||||
const { data: dashboard, isLoading, error } = useQuery({
|
||||
queryKey: districtKeys.dashboard(id || ''),
|
||||
queryFn: () => getDistrictDashboard(id || ''),
|
||||
enabled: !!id,
|
||||
});
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-900 p-6">
|
||||
<div className="animate-pulse space-y-4">
|
||||
<div className="h-8 bg-gray-800 rounded w-1/3"></div>
|
||||
<div className="h-64 bg-gray-800 rounded"></div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (error || !dashboard) {
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-900 p-6 flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<h2 className="text-xl text-red-400 mb-2">District not found</h2>
|
||||
<Link to="/city" className="text-blue-400 hover:underline">
|
||||
← Back to City
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const { district, primaryAgent, teamAgents, stats, rooms, subdaos, nodes } = dashboard;
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-900 text-white">
|
||||
{/* Header */}
|
||||
<header className="bg-gray-800 border-b border-gray-700 px-6 py-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<Link to="/city" className="text-gray-400 hover:text-white">
|
||||
← City
|
||||
</Link>
|
||||
<h1 className="text-2xl font-bold">{district.name}</h1>
|
||||
<MicrodaoTypeBadge type="district" />
|
||||
</div>
|
||||
<button className="px-4 py-2 bg-gray-700 hover:bg-gray-600 rounded-lg text-sm">
|
||||
⚙️ Settings
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div className="p-6 space-y-6">
|
||||
{/* Top Row: Lead Agent + Stats */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
{/* Lead Agent Card */}
|
||||
<div className="bg-gray-800 border border-gray-700 rounded-xl p-6">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-16 h-16 bg-gradient-to-br from-purple-500 to-blue-500 rounded-full flex items-center justify-center text-2xl">
|
||||
🔋
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold">{primaryAgent?.name || 'Lead Agent'}</h3>
|
||||
<p className="text-gray-400 text-sm">District Lead</p>
|
||||
<span className="inline-flex items-center gap-1 px-2 py-0.5 bg-green-500/20 text-green-400 rounded-full text-xs mt-1">
|
||||
● Online
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<button className="mt-4 w-full py-2 bg-purple-600 hover:bg-purple-700 rounded-lg text-sm font-medium transition-colors">
|
||||
💬 Chat with {primaryAgent?.name || 'Lead'}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Stats Card */}
|
||||
<div className="lg:col-span-2 bg-gray-800 border border-gray-700 rounded-xl p-6">
|
||||
<h3 className="text-lg font-semibold mb-4">District Statistics</h3>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||
<StatItem label="Sub-DAOs" value={stats.subDaoCount} icon="🏢" />
|
||||
<StatItem label="Agents" value={stats.activeAgents} icon="🤖" />
|
||||
<StatItem label="Nodes" value={stats.nodeCount} icon="🖥️" />
|
||||
<StatItem label="Members" value={stats.memberCount} icon="👥" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Campus Map Preview */}
|
||||
<div className="bg-gray-800 border border-gray-700 rounded-xl p-6">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-lg font-semibold">🗺️ Campus Map</h3>
|
||||
<Link
|
||||
to={`/district/${id}/map`}
|
||||
className="text-blue-400 hover:text-blue-300 text-sm"
|
||||
>
|
||||
View Full Map →
|
||||
</Link>
|
||||
</div>
|
||||
<div className="bg-gray-700/50 rounded-lg p-8 text-center border-2 border-dashed border-gray-600">
|
||||
<div className="text-4xl mb-2">🗺️</div>
|
||||
<p className="text-gray-400">Campus Map Preview</p>
|
||||
<p className="text-gray-500 text-sm mt-1">Interactive map coming soon</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Rooms Row */}
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-lg font-semibold">💬 District Rooms</h3>
|
||||
<Link
|
||||
to={`/district/${id}/rooms`}
|
||||
className="text-blue-400 hover:text-blue-300 text-sm"
|
||||
>
|
||||
View All →
|
||||
</Link>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||
{rooms.slice(0, 4).map((room) => (
|
||||
<RoomCard key={room.id} room={room} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Sub-DAOs Row */}
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-lg font-semibold">🏢 Sub-DAOs</h3>
|
||||
<div className="flex items-center gap-3">
|
||||
<Link
|
||||
to={`/district/${id}/subdaos`}
|
||||
className="text-blue-400 hover:text-blue-300 text-sm"
|
||||
>
|
||||
View All →
|
||||
</Link>
|
||||
<button className="px-3 py-1 bg-green-600 hover:bg-green-700 rounded text-sm">
|
||||
+ Add
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
{subdaos.length > 0 ? (
|
||||
subdaos.slice(0, 3).map((dao) => (
|
||||
<SubDaoCard key={dao.id} dao={dao} />
|
||||
))
|
||||
) : (
|
||||
<div className="col-span-3 bg-gray-800 border border-dashed border-gray-600 rounded-xl p-8 text-center">
|
||||
<p className="text-gray-400">No sub-DAOs yet</p>
|
||||
<button className="mt-2 text-blue-400 hover:text-blue-300 text-sm">
|
||||
+ Add first Sub-DAO
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Team Agents */}
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-lg font-semibold">🤖 Team Agents</h3>
|
||||
<Link
|
||||
to={`/district/${id}/agents`}
|
||||
className="text-blue-400 hover:text-blue-300 text-sm"
|
||||
>
|
||||
View All →
|
||||
</Link>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||
{teamAgents.map((agent) => (
|
||||
<AgentCard key={agent.id} agent={agent} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Nodes */}
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-lg font-semibold">🖥️ District Nodes</h3>
|
||||
<Link
|
||||
to={`/district/${id}/nodes`}
|
||||
className="text-blue-400 hover:text-blue-300 text-sm"
|
||||
>
|
||||
View All →
|
||||
</Link>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
{nodes.slice(0, 3).map((node) => (
|
||||
<NodeCard key={node.id} node={node} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Helper Components
|
||||
// ============================================================================
|
||||
|
||||
function StatItem({ label, value, icon }: { label: string; value: number; icon: string }) {
|
||||
return (
|
||||
<div className="bg-gray-700/50 rounded-lg p-4 text-center">
|
||||
<div className="text-2xl mb-1">{icon}</div>
|
||||
<div className="text-2xl font-bold">{value}</div>
|
||||
<div className="text-gray-400 text-sm">{label}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function RoomCard({ room }: { room: any }) {
|
||||
const icons: Record<string, string> = {
|
||||
'district-room': '💬',
|
||||
'front-room': '🚪',
|
||||
'city-room': '🏛️',
|
||||
};
|
||||
|
||||
return (
|
||||
<Link
|
||||
to={`/room/${room.id}`}
|
||||
className="bg-gray-800 border border-gray-700 hover:border-gray-600 rounded-xl p-4 transition-colors"
|
||||
>
|
||||
<div className="text-2xl mb-2">{icons[room.type] || '💬'}</div>
|
||||
<h4 className="font-medium text-sm">{room.name}</h4>
|
||||
<p className="text-gray-500 text-xs mt-1">{room.visibility}</p>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
function SubDaoCard({ dao }: { dao: any }) {
|
||||
return (
|
||||
<Link
|
||||
to={`/microdao/${dao.id}`}
|
||||
className="bg-gray-800 border border-gray-700 hover:border-gray-600 rounded-xl p-4 transition-colors"
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 bg-gradient-to-br from-blue-500 to-cyan-500 rounded-lg flex items-center justify-center">
|
||||
🏢
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-medium">{dao.name}</h4>
|
||||
<p className="text-gray-500 text-xs">{dao.slug}</p>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
function AgentCard({ agent }: { agent: any }) {
|
||||
return (
|
||||
<div className="bg-gray-800 border border-gray-700 rounded-xl p-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 bg-gradient-to-br from-purple-500 to-pink-500 rounded-full flex items-center justify-center">
|
||||
🤖
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-medium text-sm">{agent.name}</h4>
|
||||
<p className="text-gray-500 text-xs">{agent.kind}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function NodeCard({ node }: { node: any }) {
|
||||
return (
|
||||
<div className="bg-gray-800 border border-gray-700 rounded-xl p-4">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<h4 className="font-medium text-sm">{node.name || node.nodeId}</h4>
|
||||
<span className="px-2 py-0.5 bg-green-500/20 text-green-400 rounded text-xs">
|
||||
{node.status || 'active'}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-gray-500 text-xs">{node.kind || 'datacenter'}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default DistrictDashboard;
|
||||
|
||||
Reference in New Issue
Block a user