Перейти к содержанию

App — Клиентская панель (Customer Panel)

Общее описание

Клиентская панель управления платформой AACSearch, реализованная на shadcn-admin-kit (ra-core + shadcn/ui). Позволяет тенантам управлять коллекциями Typesense, документами, биллингом, API-ключами и настройками через веб-интерфейс.

Расположение: /root/app/panel/ Домены: app.aacsearch.com, platform.aacsearch.com Платформа: Cloudflare Pages (проект: aacsearch-platform)


Технологический стек

Слой Технология Версия Назначение
Фреймворк React 19.2.0 UI-рендеринг
Admin-фреймворк ra-core 5.14.1 CRUD-ресурсы, data/auth провайдеры
UI-библиотека shadcn/ui (Radix) Headless-компоненты с Tailwind
Сборка Vite 7.3 Бандлинг, HMR
Стилизация Tailwind CSS 4.1 Utility-first CSS
Маршрутизация React Router 7.13 Клиентская навигация
Серверное состояние TanStack Query 5.90 Кеширование, синхронизация
Формы react-hook-form 7.71 Управление формами
Графики Recharts 2.15 Визуализация данных
Иконки Lucide React 0.563 SVG-иконки
Темы next-themes 0.4.6 Dark/Light mode
Тосты Sonner 2.0.7 Уведомления
Язык TypeScript ~5.9.3 Типизация

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

/root/app/panel/
├── src/
│   ├── main.tsx                 # Точка входа Vite
│   ├── App.tsx                  # Маршруты, ресурсы, layouts
│   ├── index.css                # Глобальные стили Tailwind
│   │
│   ├── components/
│   │   ├── admin/               # 85+ компонентов shadcn-admin-kit
│   │   │   ├── admin.tsx        # <Admin> обёртка
│   │   │   ├── app-sidebar.tsx  # Сайдбар с feature gates
│   │   │   ├── data-table.tsx   # Таблица данных
│   │   │   ├── user-menu.tsx    # Меню пользователя
│   │   │   └── ...
│   │   ├── ui/                  # 27 shadcn/ui примитивов
│   │   └── BillingStatusBanner.tsx
│   │
│   ├── pages/                   # 20 кастомных страниц
│   │   ├── Dashboard.tsx        # Онбординг + статистика
│   │   ├── SearchPlayground.tsx # UI поиска Typesense
│   │   ├── ConversationPlayground.tsx # RAG-чат
│   │   ├── BillingOverview.tsx  # Подписки, кошелёк, платежи
│   │   ├── PlanComparison.tsx   # Матрица фич по планам
│   │   ├── ApiKeys.tsx          # Scoped API-ключи
│   │   ├── ApiDocs.tsx          # Просмотр API-документации
│   │   ├── UsageAnalytics.tsx   # Графики использования
│   │   ├── BulkImport.tsx       # Массовый импорт CSV/JSON
│   │   ├── ReindexManagement.tsx # Задачи переиндексации
│   │   ├── Account.tsx          # Настройки аккаунта
│   │   └── Auth-страницы (Register, ForgotPassword, ResetPassword)
│   │
│   ├── resources/               # 14 CRUD-ресурсов ra-core
│   │   ├── collections.tsx      # Коллекции (List, Create, Edit, Show)
│   │   ├── documents.tsx        # Документы (per-collection)
│   │   ├── synonym-sets.tsx     # Синонимы
│   │   ├── curation-sets.tsx    # Курирование
│   │   ├── stopwords.tsx        # Стоп-слова
│   │   ├── presets.tsx          # Пресеты
│   │   ├── aliases.tsx          # Алиасы
│   │   ├── analytics.tsx        # Аналитика
│   │   ├── stemming.tsx         # Стемминг
│   │   ├── nl-search.tsx        # NL-поиск
│   │   ├── conversations.tsx    # Диалоги (RAG)
│   │   ├── data-sources.tsx     # Источники данных
│   │   ├── invoices.tsx         # Инвойсы (read-only)
│   │   └── subscriptions.tsx    # Подписки (read-only)
│   │
│   ├── providers/
│   │   ├── authProvider.ts      # Аутентификация (Zitadel V2 через API proxy)
│   │   ├── dataProvider.ts      # HTTP-клиент для ra-core
│   │   └── i18nProvider.ts      # Polyglot (en + ru)
│   │
│   ├── hooks/                   # Кастомные React-хуки
│   │   ├── useDashboardData.ts  # Данные дашборда (usage, plan, subscription)
│   │   ├── useCollectionChoices.ts
│   │   ├── useCollectionSchema.ts
│   │   ├── useChangePlan.ts
│   │   ├── useCreateWallet.ts
│   │   ├── useWalletTopup.ts
│   │   ├── useFeedPreview.ts
│   │   └── useReindexJobs.ts
│   │
│   ├── lib/
│   │   ├── api-client.ts        # Типизированные API-методы
│   │   ├── features.ts          # Определения планов, матрица фич
│   │   ├── constants.ts         # Константы
│   │   └── utils.ts             # Утилиты
│   │
│   ├── layout/
│   │   └── CustomSidebar.tsx    # Сайдбар с группами и feature gates
│   │
│   ├── locales/
│   │   ├── en.ts                # Английский
│   │   └── ru.ts                # Русский
│   │
│   └── types/
│       └── api.ts               # Типы API (billing, auth, documents)
├── dist/                        # Сборка Vite (→ CF Pages)
├── public/
│   └── _redirects               # SPA-редирект: /* → /index.html 200
├── vite.config.ts               # Vite + React + Tailwind
├── tsconfig.json                # TypeScript (alias: @/ → ./src/)
├── components.json              # shadcn конфиг + реестры
├── index.html                   # HTML точка входа
├── .env                         # VITE_API_URL=https://api.aacsearch.com
└── package.json

Аутентификация (authProvider.ts)

Панель аутентифицируется через Zitadel V2 Session API, проксированный через API-шлюз.

Поток

1. Пользователь → /login (встроенная форма)
2. POST /api/auth/v2/login (email + password)
     │ API-шлюз проксирует к Zitadel V2 Session API
     │ Возвращает: sessionId, sessionToken
3. Сохранение aac_session cookie
4. GET /api/auth/v2/session → проверка сессии
     │ Результат: userId, orgId (tenantId), displayName
5. GET /api/v1/billing/dashboard/usage → фичи плана
     │ Кеш 60 сек
6. authProvider.canAccess({resource}) → проверка feature gates

Методы authProvider

Метод Описание
login({email, password}) POST /api/auth/v2/login
logout() POST /api/auth/v2/logout
checkAuth() GET /api/auth/v2/session (кеш 30 сек)
checkError(error) 401 → logout, 402/403/429 → НЕ logout
getIdentity() Возвращает displayName, email из сессии
canAccess({resource}) Проверка фичей плана (RESOURCE_FEATURE_MAP)

Data Provider (dataProvider.ts)

Маппинг ra-core CRUD-операций на HTTP-эндпоинты API-шлюза.

Engine-ресурсы (Typesense через gateway, изоляция тенантов)

Ресурс Эндпоинт Описание
collections /api/v1/engine/collections Коллекции Typesense
documents /api/v1/engine/collections/{name}/documents Документы (per-collection)
synonym-sets /api/v1/engine/synonym_sets Наборы синонимов
curation-sets /api/v1/engine/curation_sets Правила курирования
stopwords /api/v1/engine/stopwords Стоп-слова
presets /api/v1/engine/presets Пресеты поиска
aliases /api/v1/engine/aliases Алиасы коллекций
analytics /api/v1/engine/analytics/rules Правила аналитики
stemming /api/v1/engine/stemming Стемминг
nl-search /api/v1/engine/nl_search_models NL-модели
conversations /api/v1/engine/conversations RAG-диалоги

Billing-ресурсы (Lago через API)

Ресурс Эндпоинт
subscriptions /api/v1/billing/subscriptions
invoices /api/v1/billing/invoices
wallets /api/v1/billing/wallets

Data Sources (D1-backed)

Ресурс Эндпоинт
data-sources /api/v1/data-sources

Feature Gating (features.ts)

Каждый ресурс привязан к фиче плана через RESOURCE_FEATURE_MAP. Если фича недоступна в плане тенанта, ресурс скрывается из сайдбара и возвращает 403.

Планы

План Цена Ключевые фичи
starter_v1 $29/мес bulk_import, export, faceting, scoped_api_keys
professional_v1 $99/мес + synonyms, curations, stemming, analytics, geo_search, multi_search, data_sources
enterprise_v1 Custom Все фичи
payg_v1 По использованию Все фичи

Feature → Resource маппинг

Ресурс Требуемая фича
synonym-sets synonyms
curation-sets curations
stopwords stopwords
presets presets
stemming stemming
nl-search nl_search
analytics analytics_advanced
conversations rag
data-sources data_sources

Кастомные страницы

Страница Описание
Dashboard Badge плана, статистика использования, чеклист онбординга
Search Playground Полнотекстовый поиск с фасетами и фильтрами
Conversation Playground RAG-чат интерфейс
Billing Overview Подписка, баланс кошелька, методы оплаты
Plan Comparison Интерактивная матрица фич по планам
API Keys Генерация scoped Typesense search keys
API Docs Встроенный просмотр API-документации
Usage Analytics Графики метрик (поиск, документы, API-вызовы)
Bulk Import Массовый импорт документов из CSV/JSON
Reindex Management Управление задачами переиндексации
Account Settings Профиль, пароль, email
Payments History Список инвойсов с повторной оплатой

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

Переменные окружения

VITE_API_URL=https://api.aacsearch.com

Vite (vite.config.ts)

  • Chunk size limit: 700 KB
  • Manual chunks: vendor-ra, vendor-icons, vendor-router, vendor-charts
  • Alias: @/./src/
  • Плагины: @vitejs/plugin-react, @tailwindcss/vite

shadcn (components.json)

  • Style: new-york
  • Icon library: lucide
  • CSS variables: enabled
  • Реестры: @shadcn-admin-kit (https://marmelab.com/shadcn-admin-kit/r/)

Интернационализация

  • Библиотека: ra-i18n-polyglot
  • Языки: английский (en), русский (ru)
  • Файлы: src/locales/en.ts, src/locales/ru.ts
  • Формат: ключи вида aac.dashboard.title, ra.action.save

Обработка ошибок

HTTP-код Поведение
401 Logout (сессия невалидна)
402 НЕ logout — показ "требуется оплата"
403 НЕ logout — показ "фича недоступна"
429 НЕ logout — показ "превышен лимит"
502/503 НЕ logout — сохранение stale кеша

Деплой

cd /root/app/panel
npm run build     # tsc -b && vite build → dist/
# Деплой dist/ на Cloudflare Pages
# Проект: aacsearch-platform
# Домены: app.aacsearch.com, platform.aacsearch.com

SPA Routing

Файл public/_redirects:

/* /index.html 200


Команды

Команда Описание
npm run dev Локальный сервер разработки (Vite)
npm run build TypeScript проверка + Production-сборка
npm run preview Предпросмотр собранного приложения
npm run lint ESLint проверка