docs/specs/FRONTEND.md
2026-03-13 22:56:04 +01:00

15 KiB
Raw Blame History

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/                     # Статические ресурсы

Роуты и страницы

Публичные роуты:

  • /loginLoginPage — вход в систему

Защищённые роуты (AuthGuard):

  • /HomePage — список проектов
  • /projects/:idProjectPage — страница проекта с канбаном и чатом
  • /projects/newCreateProjectPage — создание нового проекта
  • /settingsSettingsLayout — настройки (nested routes)
    • /settingsSettingsPage — общие настройки
    • /settings/labelsLabelsPage — управление лейблами
    • /settings/agentsAgentsPage — управление агентами

Роутинг:

<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
Глобального стора нет — каждый компонент управляет своим состоянием

Паттерны управления состоянием:

Загрузка данных:

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 обновления:

useEffect(() => {
  const unsubscribe = wsClient.on("event.type", (data) => {
    setItems(prev => prev.map(item => 
      item.id === data.id ? data : item
    ));
  });
  return unsubscribe;
}, []);

Оптимистичные обновления:

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 клиент:

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 класс:

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)
}

Обработка событий:

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 компонент:

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 дизайн

Цветовая схема:

:root {
  --background: #ffffff;
  --foreground: #0f0f0f;
  --muted: #6b7280;
  --border: #e5e7eb;
  --primary: #3b82f6;
  --destructive: #ef4444;
}

Компоненты UI:

  • Модальные окна
  • Drag & drop интерфейсы
  • Kanban колонки
  • Формы с валидацией
  • Файл загрузчики
  • Chat интерфейс

Environment переменные

Файл: .env

VITE_API_URL=http://localhost:8100     # Базовый URL REST API
VITE_WS_URL=ws://localhost:8100        # Базовый URL WebSocket

Использование:

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/ на дату создания спецификации.