Files

12 KiB
Raw Permalink Blame History

pulse-web — Архитектура

Репозиторий: https://git.digital-home.site/daniil/pulse-web
URL: https://pulse.digital-home.site
Dev: http://192.168.31.60:5174
Storybook: http://192.168.31.60:6006

Общая архитектура

React SPA (Single Page Application):

src/
  api/         ← API-функции (axios, по доменам)
  store/       ← State management (Zustand)
  contexts/    ← React Context (тема)
  pages/       ← Страницы (маршруты)
  components/  ← Переиспользуемые компоненты
  main.jsx     ← Точка входа (BrowserRouter + ThemeContext)
  App.jsx      ← Роутер (Routes/Route)
  index.css    ← Глобальные стили (Tailwind)

Стек:

  • Framework: React 18
  • Bundler: Vite 5
  • Роутинг: React Router DOM 6
  • State: Zustand 4
  • HTTP: Axios (с interceptors для JWT refresh)
  • UI: Tailwind CSS 3
  • Анимации: Framer Motion 11
  • Иконки: Lucide React
  • Графики: Recharts 2
  • Утилиты дат: date-fns 3
  • Компонент-либа: Storybook 8
  • Тесты: Vitest + Testing Library

Структура папок

pulse-web/
├── src/
│   ├── api/
│   │   ├── client.js       # Axios instance + JWT interceptor
│   │   ├── auth.js         # (в store/auth.js)
│   │   ├── tasks.js        # tasksApi: list, today, create, complete...
│   │   ├── habits.js       # habitsApi: list, create, log, stats...
│   │   ├── finance.js      # financeApi: categories, transactions, summary
│   │   ├── savings.js      # savingsApi: categories, transactions, stats
│   │   └── profile.js      # profileApi: get, update
│   ├── store/
│   │   └── auth.js         # useAuthStore (Zustand): user, login, logout
│   ├── contexts/
│   │   └── ThemeContext.jsx # ThemeProvider: light/dark, localStorage
│   ├── pages/
│   │   ├── Home.jsx        # Главная страница (дашборд)
│   │   ├── Tracker.jsx     # Трекер (таб: привычки/задачи/статистика)
│   │   ├── Habits.jsx      # Страница привычек (встраивается в Tracker)
│   │   ├── Tasks.jsx       # Страница задач (встраивается в Tracker)
│   │   ├── Stats.jsx       # Статистика (встраивается в Tracker)
│   │   ├── Finance.jsx     # Финансы (таб: обзор/транзакции/аналитика/категории)
│   │   ├── Savings.jsx     # Накопления
│   │   ├── Settings.jsx    # Настройки пользователя
│   │   ├── Login.jsx       # Вход
│   │   ├── Register.jsx    # Регистрация
│   │   ├── ForgotPassword.jsx  # Сброс пароля
│   │   ├── ResetPassword.jsx   # Новый пароль (по токену из email)
│   │   └── VerifyEmail.jsx     # Подтверждение email
│   ├── components/
│   │   ├── Navigation.jsx      # Нижняя навигация (fixed bottom)
│   │   ├── CreateTaskModal.jsx
│   │   ├── EditTaskModal.jsx
│   │   ├── CreateHabitModal.jsx
│   │   ├── EditHabitModal.jsx
│   │   ├── LogHabitModal.jsx
│   │   └── finance/
│   │       ├── FinanceDashboard.jsx    # Обзор месяца
│   │       ├── TransactionList.jsx     # Список транзакций
│   │       ├── FinanceAnalytics.jsx    # Графики трендов
│   │       ├── CategoriesManager.jsx  # Управление категориями
│   │       └── AddTransactionModal.jsx
│   ├── App.jsx             # Routes + ProtectedRoute/PublicRoute
│   ├── main.jsx            # ReactDOM.render + Providers
│   └── index.css           # Tailwind + кастомные стили
├── public/
├── package.json
├── vite.config.js
├── tailwind.config.js
├── nginx.conf
└── Dockerfile

Страницы / Роуты

Путь Компонент Защита Описание
/login Login Public only Форма входа
/register Register Public only Форма регистрации
/forgot-password ForgotPassword Public only Запрос сброса пароля
/verify-email VerifyEmail Нет Подтверждение email по токену
/reset-password ResetPassword Нет Установка нового пароля
/ Home Protected Главная: дашборд
/tracker Tracker Protected Трекер привычек/задач/статистики
/habits /tracker Protected Редирект на трекер
/tasks /tracker Protected Редирект на трекер
/stats /tracker Protected Редирект на трекер
/savings Savings Protected Накопления
/settings Settings Protected Настройки аккаунта
* / Любой неизвестный → главная

Tracker (вкладки)

/tracker содержит 3 вкладки:

  1. ПривычкиHabits компонент
  2. ЗадачиTasks компонент
  3. СтатистикаStats компонент

Finance (вкладки)

/finance (доступна через роутер если добавить) содержит 4 вкладки:

  1. ОбзорFinanceDashboard
  2. ТранзакцииTransactionList
  3. АналитикаFinanceAnalytics
  4. КатегорииCategoriesManager

⚠️ Страница Finance рендерится, но нет роута в App.jsx. Доступ только если добавить <Route path="/finance">.

Основные компоненты

Компонент Файл Назначение
Navigation components/Navigation.jsx Нижняя навбар (Главная, Трекер, Накопления, Настройки). Показывает Finance только для user.id === 1 (owner)
ProtectedRoute App.jsx Редиректит на /login если не авторизован
PublicRoute App.jsx Редиректит на / если уже авторизован
FinanceDashboard finance/ Обзор месяца: баланс, доходы/расходы, по категориям, дневной график
TransactionList finance/ Список транзакций с фильтрацией
FinanceAnalytics finance/ Recharts: тренды по месяцам
CategoriesManager finance/ CRUD категорий
AddTransactionModal finance/ Модал добавления транзакции
CreateTaskModal components/ Создание задачи
EditTaskModal components/ Редактирование задачи
CreateHabitModal components/ Создание привычки
LogHabitModal components/ Отметка привычки

API вызовы

Axios Client (src/api/client.js)

const api = axios.create({ baseURL: VITE_API_URL })

// Request interceptor: добавляет Bearer токен из localStorage
api.interceptors.request  Authorization: Bearer <access_token>

// Response interceptor: при 401 делает refresh и повторяет запрос
api.interceptors.response  POST /auth/refresh  обновляет tokens в localStorage

API модули

// tasks.js
tasksApi.list(completed?)     GET /tasks
tasksApi.today()              GET /tasks/today
tasksApi.create(data)         POST /tasks
tasksApi.complete(id)         POST /tasks/{id}/complete
tasksApi.uncomplete(id)       POST /tasks/{id}/uncomplete
tasksApi.update(id, data)     PUT /tasks/{id}
tasksApi.delete(id)           DELETE /tasks/{id}

// habits.js
habitsApi.list()              GET /habits
habitsApi.create(data)        POST /habits
habitsApi.log(id, data)       POST /habits/{id}/log
habitsApi.stats()             GET /habits/stats
habitsApi.habitStats(id)      GET /habits/{id}/stats

// finance.js
financeApi.getCategories()            GET /finance/categories
financeApi.createCategory(data)       POST /finance/categories
financeApi.getTransactions(m, y)      GET /finance/transactions?month=&year=
financeApi.createTransaction(data)    POST /finance/transactions
financeApi.getSummary(m, y)           GET /finance/summary
financeApi.getAnalytics()             GET /finance/analytics

// savings.js
savingsApi.getCategories()            GET /savings/categories
savingsApi.createCategory(data)       POST /savings/categories
savingsApi.getTransactions()          GET /savings/transactions
savingsApi.getStats()                 GET /savings/stats

// profile.js
profileApi.get()              GET /profile
profileApi.update(data)       PUT /profile

State Management

Zustand — единственный store: src/store/auth.js

useAuthStore = {
  user: null | User,
  isLoading: boolean,
  isAuthenticated: boolean,

  initialize()  // Вызывается в App.jsx useEffect: GET /auth/me
  login(email, password)    // POST /auth/login, сохраняет tokens
  register(email, username, password)
  logout()      // Чистит localStorage + state
}

React Context:

  • ThemeContext (contexts/ThemeContext.jsx) — dark/light mode, сохраняется в localStorage

Нет Redux / React Query — данные загружаются локально в компонентах через useState + useEffect.

Основные зависимости

Пакет Версия Назначение
react 18.2 UI framework
react-router-dom 6.22 Роутинг
zustand 4.5 State management
axios 1.6 HTTP клиент
tailwindcss 3.4 CSS utility framework
framer-motion 11 Анимации
lucide-react 0.312 Иконки
recharts 2.12 Графики
date-fns 3.3 Утилиты дат
clsx 2.1 Условные классы
storybook 8.5 UI компонент-браузер (dev)
vitest 4 Тесты

Конфигурация

Env переменная Описание Default
VITE_API_URL URL backend API https://api.digital-home.site

Где искать что

Задача Файл
Новая страница src/pages/NewPage.jsx + роут в App.jsx + ссылка в Navigation.jsx
Новый компонент src/components/NewComponent.jsx
Новый API вызов src/api/<domain>.js (добавить метод)
Финансы: UI src/pages/Finance.jsx, src/components/finance/
Финансы: API src/api/finance.js
Привычки: UI src/pages/Habits.jsx, CreateHabitModal, LogHabitModal
Привычки: API src/api/habits.js
Задачи: UI src/pages/Tasks.jsx, CreateTaskModal, EditTaskModal
Задачи: API src/api/tasks.js
Авторизация src/store/auth.js, src/pages/Login.jsx
Глобальные стили src/index.css + tailwind.config.js
Темная тема src/contexts/ThemeContext.jsx
Нижняя навигация src/components/Navigation.jsx

Заметки

  • Finance страница не добавлена в роутер и навигацию для обычных пользователей — только для owner (id=1)
  • Legacy роуты /habits, /tasks, /stats → редиректят на /tracker
  • Токены хранятся в localStorage: access_token, refresh_token
  • Auto-refresh токена при 401 ответе (в axios interceptor)