docs/specs/FRONTEND.md

452 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Team Board — Frontend спецификация
## Общие сведения
**Технологии:**
- React 19.2.0
- TypeScript (~5.9.3)
- Vite 7.3.1 (bundler + dev server)
- React Router DOM 7.13.1 (роутинг)
- Tailwind CSS 4.2.1 (стили)
**Файл конфигурации:** `package.json`
**Архитектура:** SPA (Single Page Application)
---
## Структура проекта
```
src/
├── App.tsx # Главный компонент с роутингом
├── pages/ # Страницы приложения
│ ├── HomePage.tsx # Главная страница (список проектов)
│ ├── LoginPage.tsx # Страница входа
│ ├── ProjectPage.tsx # Страница проекта (канбан + чат)
│ ├── CreateProjectPage.tsx # Создание проекта
│ └── settings/ # Настройки
│ ├── SettingsLayout.tsx # Layout для настроек
│ ├── SettingsPage.tsx # Общие настройки
│ ├── LabelsPage.tsx # Управление лейблами
│ └── AgentsPage.tsx # Управление агентами
├── components/ # Переиспользуемые компоненты
│ ├── AuthGuard.tsx # Защита роутов авторизацией
│ ├── Sidebar.tsx # Боковая панель навигации
│ ├── KanbanBoard.tsx # Канбан доска задач
│ ├── TaskModal.tsx # Модальное окно задачи
│ ├── CreateTaskModal.tsx # Создание задачи
│ ├── CreateProjectModal.tsx # Создание проекта
│ ├── CreateAgentModal.tsx # Создание агента
│ ├── AgentModal.tsx # Просмотр/редактирование агента
│ ├── ProjectSettings.tsx # Настройки проекта
│ ├── ProjectFiles.tsx # Файлы проекта
│ └── ChatPanel.tsx # Панель чата
├── lib/ # Библиотеки и утилиты
│ ├── api.ts # REST API клиент
│ ├── ws.ts # WebSocket клиент
│ └── auth-client.ts # Авторизация
└── assets/ # Статические ресурсы
```
---
## Роуты и страницы
### Публичные роуты:
- `/login`**LoginPage** — вход в систему
### Защищённые роуты (AuthGuard):
- `/`**HomePage** — список проектов
- `/projects/:id`**ProjectPage** — страница проекта с канбаном и чатом
- `/projects/new`**CreateProjectPage** — создание нового проекта
- `/settings`**SettingsLayout** — настройки (nested routes)
- `/settings`**SettingsPage** — общие настройки
- `/settings/labels`**LabelsPage** — управление лейблами
- `/settings/agents`**AgentsPage** — управление агентами
### Роутинг:
```tsx
<BrowserRouter>
<Routes>
<Route path="/login" element={<LoginPage />} />
<Route path="/" element={<AuthGuard><HomePage /></AuthGuard>} />
<Route path="/projects/:id" element={<AuthGuard><ProjectPage /></AuthGuard>} />
<Route path="/projects/new" element={<AuthGuard><CreateProjectPage /></AuthGuard>} />
<Route path="/settings" element={<AuthGuard><SettingsLayout /></AuthGuard>}>
<Route index element={<SettingsPage />} />
<Route path="labels" element={<LabelsPage />} />
<Route path="agents" element={<AgentsPage />} />
</Route>
</Routes>
</BrowserRouter>
```
---
## Основные компоненты
### AuthGuard
**Файл:** `components/AuthGuard.tsx`
**Назначение:** проверяет авторизацию, перенаправляет на /login если токена нет
### KanbanBoard
**Файл:** `components/KanbanBoard.tsx`
**Назначение:** канбан доска с drag & drop задач между колонками
**Колонки:**
- Backlog (#737373)
- TODO (#3b82f6)
- In Progress (#f59e0b)
- Review (#a855f7)
- Done (#22c55e)
**Функции:**
- Drag & drop задач между статусами
- Фильтрация по исполнителю/лейблам
- Real-time обновления через WebSocket
- Создание задач в определённой колонке
### TaskModal
**Файл:** `components/TaskModal.tsx`
**Назначение:** полное отображение и редактирование задачи
**Секции:**
- Заголовок и описание
- Метаданные (статус, приоритет, лейблы, исполнитель)
- Steps (чеклист этапов)
- Комментарии и обсуждения
- Файловые вложения
### ChatPanel
**Файл:** `components/ChatPanel.tsx`
**Назначение:** панель чата проекта с real-time сообщениями
**Функции:**
- Отправка сообщений
- Упоминания участников (@username)
- Загрузка файлов
- Real-time обновления через WebSocket
### Sidebar
**Файл:** `components/Sidebar.tsx`
**Назначение:** боковая панель навигации
**Элементы:**
- Список проектов
- Общий чат (Lobby)
- Настройки
- Онлайн участники
---
## State Management
**Подход:** Локальный state с React hooks
**Глобального стора нет** — каждый компонент управляет своим состоянием
### Паттерны управления состоянием:
#### Загрузка данных:
```tsx
const [data, setData] = useState<T[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function load() {
try {
const result = await apiCall();
setData(result);
} finally {
setLoading(false);
}
}
load();
}, [dependency]);
```
#### Real-time обновления:
```tsx
useEffect(() => {
const unsubscribe = wsClient.on("event.type", (data) => {
setItems(prev => prev.map(item =>
item.id === data.id ? data : item
));
});
return unsubscribe;
}, []);
```
#### Оптимистичные обновления:
```tsx
const handleUpdate = async (id: string, changes: Partial<T>) => {
// Оптимистично обновляем UI
setItems(prev => prev.map(item =>
item.id === id ? {...item, ...changes} : item
));
try {
await updateItem(id, changes);
} catch {
// Откат в случае ошибки
loadItems();
}
};
```
---
## API интеграция
**Файл:** `lib/api.ts`
**Базовый URL:** определяется через `VITE_API_URL` environment variable
### HTTP клиент:
```typescript
async function request<T>(path: string, options: RequestInit = {}): Promise<T> {
const token = getToken();
const headers = {
"Content-Type": "application/json",
...(token && { "Authorization": `Bearer ${token}` })
};
const res = await fetch(`${API_BASE}${path}`, { ...options, headers });
if (!res.ok) {
if (res.status === 401) {
localStorage.removeItem("tb_token");
window.location.href = "/login";
}
throw new Error(await res.json().error);
}
return res.json();
}
```
### API методы по категориям:
#### Auth:
- `login(login, password)` — вход в систему
#### Projects:
- `getProjects()` — список проектов
- `getProject(id)` — получить проект
- `createProject(data)` — создать проект
- `updateProject(id, data)` — обновить проект
- `deleteProject(id)` — удалить проект
#### Tasks:
- `getTasks(projectId)` — задачи проекта
- `getTask(id)` — получить задачу
- `createTask(projectId, data)` — создать задачу
- `updateTask(id, data)` — обновить задачу
- `deleteTask(id)` — удалить задачу
- `takeTask(id)` — взять задачу (для агентов)
- `rejectTask(id, reason)` — отклонить задачу
- `assignTask(id, assigneeId)` — назначить задачу
- `watchTask(id)` / `unwatchTask(id)` — подписки на задачу
#### Steps:
- `getTaskSteps(taskId)` — этапы задачи
- `createTaskStep(taskId, data)` — создать этап
- `updateTaskStep(taskId, stepId, data)` — обновить этап
- `deleteTaskStep(taskId, stepId)` — удалить этап
#### Messages:
- `getMessages(params)` — сообщения чата/задачи
- `createMessage(data)` — отправить сообщение
#### Members:
- `getMembers()` — список участников
- `getMember(id)` — получить участника
- `createMember(data)` — создать участника/агента
- `updateMember(id, data)` — обновить участника
- `regenerateMemberToken(id)` — новый токен агента
- `revokeMemberToken(id)` — отозвать токен
#### Labels:
- `getLabels()` — глобальные лейблы
- `createLabel(data)` — создать лейбл
- `updateLabel(id, data)` — обновить лейбл
- `deleteLabel(id)` — удалить лейбл
#### Files:
- `uploadFile(file)` — загрузить временный файл
- `downloadAttachment(id)` — скачать вложение
- `getProjectFiles(projectId)` — файлы проекта
- `uploadProjectFile(projectId, file, description)` — загрузить файл проекта
- `deleteProjectFile(projectId, fileId)` — удалить файл проекта
---
## WebSocket интеграция
**Файл:** `lib/ws.ts`
**URL:** определяется через `VITE_WS_URL` environment variable
### WSClient класс:
```typescript
class WSClient {
connect() // подключение с токеном из localStorage
disconnect() // отключение
on(type, handler) // подписка на события
send(data) // отправка сообщения
// Convenience методы:
subscribeProject(projectId)
unsubscribeProject(projectId)
sendChat(chatId, content, mentions)
sendTaskComment(taskId, content, mentions)
heartbeat(status)
}
```
### Обработка событий:
```typescript
useEffect(() => {
const unsubscribe = wsClient.on("message.new", (message) => {
setMessages(prev => [...prev, message]);
});
return unsubscribe;
}, []);
```
### Поддерживаемые события:
- `auth.ok` — успешная авторизация
- `auth.error` — ошибка авторизации
- `message.new` — новое сообщение
- `task.created` — задача создана
- `task.updated` — задача обновлена
- `task.assigned` — задача назначена
- `task.deleted` — задача удалена
- `agent.status` — изменение статуса участника
- `agent.stream.*` — streaming от агентов
### Auto-reconnect:
- При разрыве соединения автоматический переподключение через 3 секунды
- Heartbeat каждые 30 секунд для поддержания соединения
- Очередь сообщений до подключения и авторизации
---
## Авторизация
**Файл:** `lib/auth-client.ts`
### Токены:
- Хранение: `localStorage.getItem("tb_token")`
- Формат: JWT токен
- Автоматическое добавление в заголовки API запросов
- Автоматический redirect на /login при 401 ошибке
### AuthGuard компонент:
```tsx
function AuthGuard({ children }: { children: React.ReactNode }) {
const token = localStorage.getItem("tb_token");
if (!token) return <Navigate to="/login" />;
return <>{children}</>;
}
```
---
## Стили и UI
### Tailwind CSS 4.2.1:
- Utility-first подход
- CSS переменные для темизации
- Responsive дизайн
### Цветовая схема:
```css
:root {
--background: #ffffff;
--foreground: #0f0f0f;
--muted: #6b7280;
--border: #e5e7eb;
--primary: #3b82f6;
--destructive: #ef4444;
}
```
### Компоненты UI:
- Модальные окна
- Drag & drop интерфейсы
- Kanban колонки
- Формы с валидацией
- Файл загрузчики
- Chat интерфейс
---
## Environment переменные
**Файл:** `.env`
```bash
VITE_API_URL=http://localhost:8100 # Базовый URL REST API
VITE_WS_URL=ws://localhost:8100 # Базовый URL WebSocket
```
**Использование:**
```typescript
const API_BASE = import.meta.env.VITE_API_URL!;
const WS_BASE = import.meta.env.VITE_WS_URL!;
```
---
## Типизация
### TypeScript конфигурация:
- Строгий режим
- Path mapping (`@/` → `src/`)
- DOM типы
### API типы:
Все типы синхронизированы с backend Pydantic схемами:
- `Member`, `AgentConfig`, `MemberBrief`
- `Project`, `ProjectMember`
- `Task`, `Step`, `SubtaskBrief`
- `Message`, `Attachment`
- `Label`
---
## Производительность
### Оптимизации:
- Lazy loading компонентов
- Мемоизация через React.memo для тяжёлых компонентов
- Дебаунсинг поисковых запросов
- Пагинация сообщений чата
- Оптимистичные обновления UI
### Bundle размер:
- Tree shaking неиспользуемого кода
- Code splitting по роутам
- Минификация в production
---
## Особенности архитектуры
### Real-time синхронизация:
- WebSocket для мгновенных обновлений
- Оптимистичные обновления с откатом при ошибках
- Автоматическая подписка на события проекта
### Drag & Drop:
- Нативный HTML5 drag & drop API
- Визуальная обратная связь при перетаскивании
- Оптимистичное обновление с откатом
### Файловая система:
- Поддержка загрузки файлов через drag & drop
- Preview для изображений
- Скачивание файлов через API
### Offline-first:
- Кэширование в localStorage (токен авторизации)
- Graceful degradation при отсутствии сети
- Очередь WebSocket сообщений
Этот документ описывает фронтенд на основе исходного кода в `/root/projects/team-board/web-client-vite/src/` на дату создания спецификации.