diff --git a/Projects/Pulse/Architecture.md b/Projects/Pulse/Architecture.md new file mode 100644 index 0000000..340dae4 --- /dev/null +++ b/Projects/Pulse/Architecture.md @@ -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*