# Next.js Админ-Панель — Руководство ## Обзор Новая админ-панель на **Next.js 16** (App Router) + **TypeScript** + **shadcn/ui** + **Prisma** (SQLite) + **Recharts**. Полная замена EJS/SmartAdmin шаблонизатора. ## Стек | Слой | Технология | |---|---| | Фреймворк | Next.js 16 (App Router, Turbopack) | | Язык | TypeScript 5 | | Стилизация | Tailwind CSS 4 + shadcn/ui (New York) | | БД | Prisma ORM + SQLite | | Графики | Recharts | | Состояние | Zustand | | ИИ/LLM | z-ai-web-dev-sdk (chat, vision) | | Тема | next-themes (dark/light) | | Уведомления | Sonner (toast) | | Иконки | Lucide React | ## Авторизация - Пароль: значение `ADMIN_SECRET` из `.env` (по умолчанию `changeme`) - Если задан `SUPER_ADMIN_SECRET` (и ≠ `ADMIN_SECRET`) — вход с ним даёт роль `super_admin` - Если не задан — все админы = `super_admin` - Кука `admin_token` (httpOnly, sameSite=lax, 24ч, secure в production) - Rate-limit: 5 попыток / 15 мин с IP - HMAC-SHA256 подпись токена ## Экраны (15) ### Основные 1. **Dashboard** — 4 KPI-карточки, 8 графиков (recharts), лента активности, авто-обновление 2. **Catalog** — дерево локаций → категории → подкатегории → товары, CRUD, clone, экспорт 3. **Users** — таблица + детальная страница, batch ban/unban, заметки, поиск, статус-вкладки 4. **Wallets** — 4 вкладки (All/Owner/Transactions/Seeds), запись платежей, экспорт seed-фраз 5. **Purchases** — таблица с batch approve/cancel, фильтры по статусу/дате, модаль деталей 6. **Audit Log** — журнал действий, фильтры по действию/дате/поиску, копирование записей 7. **Categories** — CRUD с просмотром товаров, подсчёт подкатегорий и продуктов 8. **Locations** — CRUD (страна/город/район) 9. **Settings** — редактирование параметров, экспорт/импорт данных (super_admin) 10. **Locales** — inline-редактор EN/ES/DE переводов 11. **Danger Zone** — Seed / Clear с reauth (super_admin) ### ИИ-ассистент и Лиды 12. **AI Chatbot** (`#/chatbot`) — полная конфигурация ИИ-бота: - Включение/выключение бота - **Спящий режим** — при включении `/start` показывает ИИ-чат вместо каталога - Системный промпт и приветственное сообщение - Температура, max tokens, глубина истории - **База знаний** — словарный лексикон (товары, цены, FAQ) - Провайдер: OpenAI / DeepSeek / OpenRouter / Ollama / Custom - API endpoint и ключ (маскированный при отображении) 13. **Leads** (`#/leads`) — управление лидами и переписками: - Таблица лидов с поиском, фильтрами по статусу - AI-профиль клиента (intent, interests, sentiment, readiness) - Просмотр переписок в виде чат-пузырей - **Вход оператора** — переключение бота на ручной режим - Статусы: Новый / Контакт / Квалифицированный / Потерянный / Спам - Заметки и quick-статус ## Спящий режим магазина Когда спящий режим включён в настройках AI Chatbot: - Пользователь через `/start` получает ИИ-чат вместо каталога - Бот сообщает что магазин пополняется - Можно собрать контакты для уведомления при открытии - Все сессии сохраняются в таблице `chat_sessions` - Из переписок автоматически извлекаются лиды ## API маршруты (48+) ### Основные | Метод | Маршрут | Описание | |---|---|---| | POST | `/api/auth/login` | Вход, установка куки | | GET | `/api/auth/session` | Проверка сессии | | POST | `/api/auth/logout` | Выход | | GET | `/api/stats/dashboard` | Статистика дашборда | | GET/PUT | `/api/settings` | Настройки | | GET | `/api/settings/export` | Полный экспорт БД (JSON) | | POST | `/api/settings/import` | Импорт (в разработке) | ### Товары и каталог | Метод | Маршрут | Описание | |---|---|---| | GET | `/api/products/bulk` | Список товаров | | POST | `/api/products/add` | Создание товара | | GET/PUT/DELETE | `/api/products/[id]` | CRUD товара | | POST | `/api/products/[id]/clone` | Дублирование товара | | GET | `/api/catalog/tree` | Дерево каталога | | GET/POST | `/api/categories/bulk` | Список/создание категорий | | GET/PUT/DELETE | `/api/categories/[id]` | CRUD категории | | GET/POST | `/api/subcategories/bulk` | Список/создание подкатегорий | | GET/PUT/DELETE | `/api/subcategories/[id]` | CRUD подкатегории | | GET/POST | `/api/locations/bulk` | Список/создание локаций | | GET/PUT/DELETE | `/api/locations/[id]` | CRUD локации | ### Пользователи и кошельки | Метод | Маршрут | Описание | |---|---|---| | GET | `/api/users/bulk` | Список пользователей | | GET/PUT | `/api/users/[id]` | Профиль пользователя | | POST | `/api/users/[id]/adjust-balance` | Корректировка баланса | | POST | `/api/users/batch-status` | Batch ban/unban | | GET | `/api/wallets/bulk` | Список кошельков | | GET | `/api/wallets/overview` | Обзор кошельков | | GET | `/api/wallets/[userId]` | Кошельки пользователя | | POST | `/api/wallets/record-payment` | Запись платежа | | GET | `/api/wallets/seeds` | Seed-фразы (super_admin) | | GET | `/api/wallets/export-seeds` | Экспорт seed-фраз CSV | ### Покупки и транзакции | Метод | Маршрут | Описание | |---|---|---| | GET | `/api/purchases/bulk` | Список покупок | | GET/PUT | `/api/purchases/[id]` | Детали/статус покупки | | POST | `/api/purchases/batch-status` | Batch approve/cancel | | GET | `/api/transactions/bulk` | Список транзакций | ### Аудит и локали | Метод | Маршрут | Описание | |---|---|---| | GET | `/api/audit/bulk` | Журнал аудита | | GET | `/api/locales` | Локализации (EN/ES/DE) | | POST | `/api/seed/demo` | Генерация тестовых данных | | POST | `/api/seed/clear` | Очистка БД | ### ИИ-чатбот и лиды | Метод | Маршрут | Описание | |---|---|---| | GET/PUT | `/api/admin/chatbot` | Настройки ИИ-бота | | POST | `/api/chat` | Точка входа чата (для TG-бота) | | GET | `/api/leads/bulk` | Список лидов | | GET/PUT | `/api/leads/[id]` | Профиль лида | | GET | `/api/leads/[id]/sessions` | Чат-сессии лида | | POST | `/api/operator` | Подключение/отключение оператора | ## Модель данных (Prisma) Всего **15 моделей**: | Модель | Описание | |---|---| | `TgUser` | Пользователи Telegram | | `CryptoWallet` | Криптокошельки | | `Transaction` | Транзакции | | `Location` | Локации (страна/город/район) | | `Category` | Категории товаров | | `Subcategory` | Подкатегории | | `Product` | Товары | | `Purchase` | Покупки | | `CommissionPayment` | Комиссионные платежи | | `AuditLog` | Журнал аудита | | `UserState` | Состояния пользователей ( FSM ) | | `ChatSession` | Чат-сессии с ИИ-ботом | | `Lead` | Лиды (авто-экстракция из чата) | | `SiteSetting` | Ключ-значение настройки | ### ChatSession ```prisma model ChatSession { id Int @id @default(autoincrement()) sessionId String @unique telegramId String? leadId Int? messages String // JSON: [{role, content, timestamp}] customerProfile String? // AI-профиль клиента (JSON) isActive Boolean @default(true) operatorName String? // Подключённый оператор autoReplyDisabled Boolean @default(false) // Ручной режим operatorConnectedAt DateTime? device / ip / country createdAt / updatedAt } ``` ### Lead ```prisma model Lead { id Int @id @default(autoincrement()) telegramId String? @unique name / phone / email / telegram status String @default("new") aiLeadScore Float? // 0-1 скор от ИИ customFields String // JSON chatSessions ChatSession[] } ``` ## Архитектура ИИ-бота ### Конфигурация (SiteSetting) Все настройки бота хранятся в таблице `site_settings` как ключ-значение. Кэшируются 5 минут. | Ключ | Тип | По умолчанию | |---|---|---| | `chatbot_enabled` | bool | true | | `chatbot_sleep_mode` | bool | false | | `chatbot_sleep_message` | text | "Магазин пополняется..." | | `chatbot_system_prompt` | text | "Ты — AI-ассистент..." | | `chatbot_welcome_message` | text | "Здравствуйте!..." | | `chatbot_temperature` | float | 0.7 | | `chatbot_max_tokens` | int | 500 | | `chatbot_max_history` | int | 20 | | `chatbot_knowledge_base` | text | "" | | `chatbot_provider` | enum | openai | | `chatbot_api_endpoint` | url | https://api.openai.com/v1 | | `chatbot_api_key` | string | "" | ### Поток чата 1. TG-бот отправляет `POST /api/chat` с `{sessionId, message, telegramId}` 2. Сервер находит/создаёт ChatSession 3. Загружает конфигурацию бота (из кэша/БД) 4. Формирует системный промпт: `system_prompt + knowledge_base + customer_profile + catalog_context` 5. Если `sleep_mode` — добавляет информацию о режиме пополнения 6. Отправляет в LLM (через z-ai-web-dev-sdk) 7. Сохраняет сообщения в ChatSession 8. Извлекает данные лида (имя, телефон, email, telegram) из текста 9. Генерирует/обновляет AI-профиль клиента (intent, interests, sentiment, readiness) 10. Автоматически создаёт/обновляет запись Lead 11. Возвращает `{reply, sessionId, leadId?, profile?}` ### Профилирование клиента Из каждой переписки ИИ автоматически генерирует профиль: ```json { "intent": "покупка|информация|поддержка|пробный период", "interests": ["VPN-коды", "аналитика"], "sentiment": "positive|neutral|negative", "budgetHint": "бюджетный|высокий", "readiness": "exploring|considering|ready", "summary": "Цель: покупка. Интересуется VPN." } ``` ### Оператор - Оператор может подключиться к любой сессии (`POST /api/operator`) - При подключении: `autoReplyDisabled=true`, бот перестаёт отвечать - Оператор видит всю историю переписки - При отключении — бот снова отвечает ## Развертывание (Docker) ### Сравнение со старой версией | | Старая (Node.js бот) | Новая (Next.js админка) | |---|---|---| | Dockerfile | `FROM node:22`, `npm install`, `CMD node src/index.js` | Multi-stage build, standalone output, non-root user | | docker-compose | 1 сервис, BOT_TOKEN + ADMIN_IDS | 1 сервис, ADMIN_SECRET + CHATBOT_API_KEY | | БД | `./db/shop.db` (sqlite3 напрямую) | `./db/custom.db` (через Prisma ORM) | | Порт | Нет (только TG webhook) | 3000 (веб-интерфейс + API) | | RAM | ~64 MB | ~256–512 MB | ### Быстрый старт (docker compose) ```bash # 1. Клонировать ветку GIT_LFS_SKIP_SMUDGE=1 git clone -b feat/nextjs-admin https://git.softuniq.eu/Telegram-Market/telegram-shop.git CD telegram-shop # 2. Создать .env файл cat > .env << 'EOF' ADMIN_SECRET=your_admin_password SUPER_ADMIN_SECRET=your_super_admin_password CHATBOT_API_KEY=sk-your-openai-key # опционально, для ИИ-бота CHATBOT_API_ENDPOINT=https://api.openai.com/v1 # или другой провайдер EOF # 3. Создать папку для БД mkdir -p db # 4. Собрать и запустить COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker compose up -d --build # 5. Дождаться запуска (15-30 сек) docker compose logs -f ``` После запуска админка доступна на `http://:3000`. ### Ручной Docker (без compose) ```bash # Сборка docker build -t tg-shop-admin . # Запуск docker run -d \ --name tg_shop_admin \ --restart always \ -p 3000:3000 \ -v $(pwd)/db:/app/db \ -e ADMIN_SECRET=your_admin_password \ -e SUPER_ADMIN_SECRET=your_super_admin_password \ -e CHATBOT_API_KEY=sk-xxx \ -m 512m \ tg-shop-admin ``` ### Переменные окружения | Переменная | Обязательна | По умолчанию | Описание | |---|---|---|---| | `DATABASE_URL` | Нет | `file:/app/db/custom.db` | Путь к SQLite БД внутри контейнера | | `ADMIN_SECRET` | **Да** | `changeme` | Пароль для роли admin | | `SUPER_ADMIN_SECRET` | Нет | — | Пароль для роли super_admin | | `CHATBOT_API_KEY` | Нет | — | API-ключ для ИИ-бота (OpenAI/DeepSeek/etc) | | `CHATBOT_API_ENDPOINT` | Нет | `https://api.openai.com/v1` | Endpoint LLM-провайдера | ### Запуск без Docker (разработка) ```bash # Установить зависимости bun install # Инициализация БД bun run db:push # Создать .env echo 'DATABASE_URL=file:./db/custom.db' > .env echo 'ADMIN_SECRET=admin123' >> .env echo 'SUPER_ADMIN_SECRET=superadmin456' >> .env # Генерация тестовых данных (опционально) curl -X POST http://localhost:3000/api/seed/demo \ -H 'Cookie: admin_token=' # Dev-сервер bun run dev # http://localhost:3000 # Production bun run build # сборка standalone bun run start # запуск production ``` ### Первоначальная настройка после деплоя 1. Открыть `http://:3000` 2. Войти с паролем из `ADMIN_SECRET` 3. Перейти в **Settings** (`#/settings`) — настроить параметры магазина 4. Перейти в **AI Chatbot** (`#/chatbot`) — настроить ИИ-бота: - Ввести API-ключ и выбрать провайдера - Настроить системный промпт - Добавить базу знаний (словарный лексикон) 5. Перейти в **Danger Zone** → **Seed Demo Data** для заполнения тестовыми данными 6. Очистить тестовые данные через **Clear Database** перед продакшеном ### Обновление ```bash # docker compose git pull docker compose up -d --build # ручной git pull docker build -t tg-shop-admin . docker stop tg_shop_admin && docker rm tg_shop_admin # повторить docker run ... ``` **Важно:** БД хранится в volume `./db`, она сохраняется при пересборке. ### Требования к серверу | Ресурс | Минимум | Рекомендуется | |---|---|---| | CPU | 1 ядро | 2 ядра | | RAM | 256 MB | 512 MB | | Диск | 500 MB (образ) + БД | 1 GB | | Архитектура | x86_64, ARM64 | — | ### Reverse Proxy (Caddy / Nginx) **Caddy** (авто HTTPS): ``` admin.yourdomain.com { reverse_proxy localhost:3000 } ``` **Nginx**: ```nginx server { listen 443 ssl; server_name admin.yourdomain.com; # ... ssl certs ... location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } ``` ## Seed-данные POST `/api/seed/demo` создаёт данные: - 3 локации, 5 категорий, 11 подкатегорий - 10 пользователей (alice–jack) - 10 товаров, 25–30 покупок - 10 криптокошельков, 2 комиссионных платежа, 12 audit записей ## Общие компоненты - `Pagination` — числовая пагинация с многоточиями - `ErrorBoundary` — обработка ошибок рендеринга - `ExportButton` — экспорт CSV + JSON - `SortableHeader` — сортируемые заголовки таблиц - `useDebounce` — хук debounce (300ms) - `useMobile` — хук определения мобильного устройства - `useKeyboardShortcuts` — хук горячих клавиш (1–9) ## Навигация Хеш-роутинг (`window.location.hash`). Горячие клавиши: `1` Dashboard, `2` Catalog, `3` Users, `4` Wallets, `5` Purchases, `6` Audit, `7` Categories, `8` Locations, `9` Settings `Ctrl+K` — палитра команд ## Визуальные эффекты - **Matrix Rain** — CSS-анимация падающих символов на странице логина (низкая непрозрачность) - **Glass-card** — стеклянный эффект карточек (backdrop-blur) - **KPI shimmer** — мерцание при наведении на KPI-карточки - **Page-enter** — fade-in анимация страниц - **Gradient borders** — градиентные рамки хедера/футера - **Alternating rows** — чередующиеся строки таблиц - **Sticky table headers** — закреплённые заголовки таблиц