Add Pulse architecture documentation
This commit is contained in:
324
Projects/Pulse/Architecture.md
Normal file
324
Projects/Pulse/Architecture.md
Normal file
@@ -0,0 +1,324 @@
|
||||
# Pulse — Архитектура проекта
|
||||
|
||||
## Обзор
|
||||
|
||||
**Pulse** — персональное productivity-приложение для управления задачами, привычками и напоминаниями с интеграцией Telegram-бота.
|
||||
|
||||
## Технологический стек
|
||||
|
||||
### Backend (pulse-api)
|
||||
- **Язык:** Go 1.22
|
||||
- **Web-фреймворк:** chi/v5
|
||||
- **База данных:** PostgreSQL 16
|
||||
- **ORM:** sqlx (raw SQL + struct mapping)
|
||||
- **Аутентификация:** JWT (access 15 мин / refresh 365 дней)
|
||||
- **Email:** Resend API
|
||||
- **Telegram:** go-telegram-bot-api/v5
|
||||
- **Scheduler:** robfig/cron/v3
|
||||
- **Контейнеризация:** Docker + Docker Compose
|
||||
|
||||
### Frontend (pulse-web)
|
||||
- **Фреймворк:** React 18
|
||||
- **Сборщик:** Vite 5
|
||||
- **Стили:** TailwindCSS
|
||||
- **Состояние:** Zustand (auth), TanStack Query (data fetching)
|
||||
- **Анимации:** Framer Motion
|
||||
- **Иконки:** Lucide React
|
||||
- **Контейнеризация:** nginx:alpine
|
||||
|
||||
### Инфраструктура
|
||||
- **Хостинг:** VM Ubuntu (192.168.31.60)
|
||||
- **Reverse proxy:** Nginx Proxy Manager
|
||||
- **SSL:** Let's Encrypt (auto-renew)
|
||||
- **Git:** Gitea (git.digital-home.site)
|
||||
- **Домены:**
|
||||
- API: api.digital-home.site
|
||||
- Web: pulse.digital-home.site
|
||||
|
||||
## Структура Backend
|
||||
|
||||
```
|
||||
homelab-api/
|
||||
├── cmd/api/
|
||||
│ └── main.go # Точка входа, инициализация
|
||||
├── internal/
|
||||
│ ├── bot/
|
||||
│ │ ├── bot.go # Telegram bot, long polling
|
||||
│ │ └── handlers.go # Обработчики команд и callback
|
||||
│ ├── config/
|
||||
│ │ └── config.go # Загрузка переменных окружения
|
||||
│ ├── handler/
|
||||
│ │ ├── auth.go # Регистрация, логин, JWT
|
||||
│ │ ├── habits.go # CRUD привычек
|
||||
│ │ ├── health.go # Health check
|
||||
│ │ ├── profile.go # Профиль пользователя
|
||||
│ │ └── tasks.go # CRUD задач
|
||||
│ ├── middleware/
|
||||
│ │ └── auth.go # JWT middleware
|
||||
│ ├── model/
|
||||
│ │ ├── habit.go # Модель привычки
|
||||
│ │ ├── task.go # Модель задачи
|
||||
│ │ └── user.go # Модель пользователя
|
||||
│ ├── repository/
|
||||
│ │ ├── db.go # Подключение к PostgreSQL
|
||||
│ │ ├── habit.go # SQL-запросы для привычек
|
||||
│ │ ├── task.go # SQL-запросы для задач
|
||||
│ │ └── user.go # SQL-запросы для пользователей
|
||||
│ ├── scheduler/
|
||||
│ │ └── scheduler.go # Cron jobs для уведомлений
|
||||
│ └── service/
|
||||
│ ├── auth.go # Бизнес-логика авторизации
|
||||
│ ├── email.go # Отправка email через Resend
|
||||
│ ├── habit.go # Бизнес-логика привычек
|
||||
│ └── task.go # Бизнес-логика задач
|
||||
├── Dockerfile
|
||||
├── docker-compose.yml
|
||||
├── go.mod
|
||||
└── go.sum
|
||||
```
|
||||
|
||||
## Структура Frontend
|
||||
|
||||
```
|
||||
pulse-web/
|
||||
├── public/
|
||||
│ └── favicon.svg # Иконка молния ⚡
|
||||
├── src/
|
||||
│ ├── api/
|
||||
│ │ ├── client.js # Axios instance + interceptors
|
||||
│ │ ├── habits.js # API привычек
|
||||
│ │ ├── profile.js # API профиля
|
||||
│ │ └── tasks.js # API задач
|
||||
│ ├── components/
|
||||
│ │ ├── CreateHabitModal.jsx
|
||||
│ │ ├── CreateTaskModal.jsx
|
||||
│ │ ├── EditHabitModal.jsx
|
||||
│ │ ├── EditTaskModal.jsx
|
||||
│ │ └── Navigation.jsx # Нижняя навигация
|
||||
│ ├── pages/
|
||||
│ │ ├── ForgotPassword.jsx
|
||||
│ │ ├── Habits.jsx # Управление привычками
|
||||
│ │ ├── Home.jsx # Главная (сегодня)
|
||||
│ │ ├── Login.jsx
|
||||
│ │ ├── Register.jsx
|
||||
│ │ ├── ResetPassword.jsx
|
||||
│ │ ├── Settings.jsx # Настройки профиля
|
||||
│ │ ├── Stats.jsx # Статистика
|
||||
│ │ ├── Tasks.jsx # Управление задачами
|
||||
│ │ └── VerifyEmail.jsx
|
||||
│ ├── store/
|
||||
│ │ └── auth.js # Zustand store для авторизации
|
||||
│ ├── App.jsx # Роутинг
|
||||
│ ├── index.css # Глобальные стили
|
||||
│ └── main.jsx # Entry point
|
||||
├── Dockerfile
|
||||
├── docker-compose.yml
|
||||
├── index.html
|
||||
├── nginx.conf
|
||||
├── package.json
|
||||
├── tailwind.config.js
|
||||
└── vite.config.js
|
||||
```
|
||||
|
||||
## База данных
|
||||
|
||||
### Таблицы
|
||||
|
||||
```sql
|
||||
-- Пользователи
|
||||
users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
email VARCHAR(255) UNIQUE NOT NULL,
|
||||
username VARCHAR(100) NOT NULL,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
email_verified BOOLEAN DEFAULT FALSE,
|
||||
telegram_chat_id BIGINT,
|
||||
notifications_enabled BOOLEAN DEFAULT TRUE,
|
||||
timezone VARCHAR(50) DEFAULT 'Europe/Moscow',
|
||||
morning_reminder_time TIME DEFAULT '09:00',
|
||||
evening_reminder_time TIME DEFAULT '21:00',
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
)
|
||||
|
||||
-- Задачи
|
||||
tasks (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id INTEGER REFERENCES users(id),
|
||||
title VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
icon VARCHAR(10) DEFAULT '📋',
|
||||
color VARCHAR(7) DEFAULT '#6B7280',
|
||||
due_date DATE,
|
||||
priority INTEGER DEFAULT 0, -- 0=none, 1=low, 2=medium, 3=high
|
||||
reminder_time TIME,
|
||||
completed_at TIMESTAMP,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
)
|
||||
|
||||
-- Привычки
|
||||
habits (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id INTEGER REFERENCES users(id),
|
||||
name VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
icon VARCHAR(10) DEFAULT '✨',
|
||||
color VARCHAR(7) DEFAULT '#10B981',
|
||||
frequency VARCHAR(20) DEFAULT 'daily', -- daily, weekly, custom
|
||||
target_days INTEGER[], -- [1,3,5] для пн,ср,пт
|
||||
target_count INTEGER DEFAULT 1,
|
||||
reminder_time TIME,
|
||||
archived BOOLEAN DEFAULT FALSE,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
)
|
||||
|
||||
-- Логи привычек
|
||||
habit_logs (
|
||||
id SERIAL PRIMARY KEY,
|
||||
habit_id INTEGER REFERENCES habits(id),
|
||||
user_id INTEGER REFERENCES users(id),
|
||||
date DATE NOT NULL,
|
||||
count INTEGER DEFAULT 1,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
)
|
||||
|
||||
-- Email токены
|
||||
email_tokens (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id INTEGER REFERENCES users(id),
|
||||
token VARCHAR(255) NOT NULL,
|
||||
type VARCHAR(50) NOT NULL, -- verification, password_reset
|
||||
expires_at TIMESTAMP NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
)
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Авторизация
|
||||
| Method | Endpoint | Описание |
|
||||
|--------|----------|----------|
|
||||
| POST | /auth/register | Регистрация |
|
||||
| POST | /auth/login | Вход |
|
||||
| POST | /auth/refresh | Обновить токены |
|
||||
| POST | /auth/verify-email | Подтвердить email |
|
||||
| POST | /auth/forgot-password | Запросить сброс пароля |
|
||||
| POST | /auth/reset-password | Сбросить пароль |
|
||||
|
||||
### Профиль (требует JWT)
|
||||
| Method | Endpoint | Описание |
|
||||
|--------|----------|----------|
|
||||
| GET | /profile | Получить профиль |
|
||||
| PUT | /profile | Обновить профиль |
|
||||
|
||||
### Задачи (требует JWT)
|
||||
| Method | Endpoint | Описание |
|
||||
|--------|----------|----------|
|
||||
| GET | /tasks | Список задач |
|
||||
| GET | /tasks/today | Задачи на сегодня |
|
||||
| POST | /tasks | Создать задачу |
|
||||
| GET | /tasks/{id} | Получить задачу |
|
||||
| PUT | /tasks/{id} | Обновить задачу |
|
||||
| DELETE | /tasks/{id} | Удалить задачу |
|
||||
| POST | /tasks/{id}/complete | Отметить выполненной |
|
||||
| POST | /tasks/{id}/uncomplete | Снять отметку |
|
||||
|
||||
### Привычки (требует JWT)
|
||||
| Method | Endpoint | Описание |
|
||||
|--------|----------|----------|
|
||||
| GET | /habits | Список привычек |
|
||||
| POST | /habits | Создать привычку |
|
||||
| GET | /habits/{id} | Получить привычку |
|
||||
| PUT | /habits/{id} | Обновить привычку |
|
||||
| DELETE | /habits/{id} | Удалить (архивировать) |
|
||||
| POST | /habits/{id}/log | Отметить выполнение |
|
||||
| GET | /habits/{id}/logs | История выполнений |
|
||||
| DELETE | /habits/{id}/logs/{logId} | Удалить запись |
|
||||
| GET | /habits/stats | Общая статистика |
|
||||
| GET | /habits/{id}/stats | Статистика привычки |
|
||||
|
||||
## Telegram Bot
|
||||
|
||||
### Команды
|
||||
| Команда | Описание |
|
||||
|---------|----------|
|
||||
| /start | Показать Chat ID |
|
||||
| /tasks | Задачи на сегодня |
|
||||
| /habits | Привычки на сегодня |
|
||||
| /help | Справка |
|
||||
|
||||
### Inline кнопки
|
||||
- ✅ Выполнено — отмечает задачу/привычку
|
||||
- 🗑 Удалить — удаляет задачу
|
||||
- ⏰ +30 мин — откладывает напоминание
|
||||
|
||||
### Уведомления
|
||||
1. **Утреннее** (настраивается): задачи и привычки на сегодня
|
||||
2. **Вечернее** (настраивается): итоги дня
|
||||
3. **Индивидуальные**: по reminder_time каждой задачи/привычки
|
||||
|
||||
## Docker Compose
|
||||
|
||||
### Backend (homelab-api)
|
||||
```yaml
|
||||
services:
|
||||
db:
|
||||
image: postgres:16-alpine
|
||||
environment:
|
||||
POSTGRES_USER: homelab
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||
POSTGRES_DB: homelab
|
||||
volumes:
|
||||
- db_data:/var/lib/postgresql/data
|
||||
networks:
|
||||
- backend
|
||||
|
||||
api:
|
||||
build: .
|
||||
environment:
|
||||
- DATABASE_URL=postgres://homelab:${DB_PASSWORD}@db:5432/homelab?sslmode=disable
|
||||
- JWT_SECRET=${JWT_SECRET}
|
||||
- RESEND_API_KEY=${RESEND_API_KEY}
|
||||
- TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN}
|
||||
depends_on:
|
||||
- db
|
||||
networks:
|
||||
- backend
|
||||
- services_proxy
|
||||
```
|
||||
|
||||
### Frontend (pulse-web)
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
build: .
|
||||
networks:
|
||||
- services_proxy
|
||||
```
|
||||
|
||||
## Дизайн
|
||||
|
||||
### Цвета
|
||||
- **Primary (Deep Teal):** #115E59
|
||||
- **Accent (Burnished Amber):** #F59E0B
|
||||
- **Surface:** #F8FAFC
|
||||
- **Text:** #1E293B
|
||||
|
||||
### Шрифты
|
||||
- **Body:** Inter (Google Fonts)
|
||||
|
||||
### UI-компоненты
|
||||
- Карточки с тенями и закруглениями (rounded-2xl)
|
||||
- Backdrop blur для header
|
||||
- Framer Motion анимации
|
||||
- Inline кнопки в Telegram
|
||||
|
||||
## Репозитории
|
||||
|
||||
- **Backend:** https://git.digital-home.site/daniil/pulse-api
|
||||
- **Frontend:** https://git.digital-home.site/daniil/pulse-web
|
||||
|
||||
---
|
||||
*Создано: 2026-02-06*
|
||||
Reference in New Issue
Block a user