12 KiB
12 KiB
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 вкладки:
- Привычки —
Habitsкомпонент - Задачи —
Tasksкомпонент - Статистика —
Statsкомпонент
Finance (вкладки)
/finance (доступна через роутер если добавить) содержит 4 вкладки:
- Обзор —
FinanceDashboard - Транзакции —
TransactionList - Аналитика —
FinanceAnalytics - Категории —
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)