# ПРАВИЛА UI/UX КАБИНЕТА СЕЛЛЕРА (SELLER)

> ⚠️ **ВАЖНО**: Это файл с UI/UX деталями кабинета селлера.
> Общие бизнес-правила находятся в **[rules-complete.md](./rules-complete.md)**

## Когда использовать этот файл:

- Работа с компонентами `/supplies`, `/my-supplies`
- UI/UX специфика кабинета селлера
- Интерфейсы создания поставок
- Визуальные правила компонентов селлера

## 1. 🛍️ СТРУКТУРА КАБИНЕТА СЕЛЛЕРА

### 1.1 Основные разделы

**СЕЛЛЕР (`SELLER`)** имеет доступ к следующим разделам:

- **Мои поставки** (`/my-supplies`) - управление поставками
- **Маркет** (`/market`) - просмотр глобального каталога
- **Партнеры** (`/partners`) - управление контрагентами
- **Мессенджер** (`/messenger`) - связь с партнерами
- **Настройки** (`/settings`) - профиль и настройки
- **Экономика** (`/economics`) - финансовая аналитика

### 1.2 Навигация и роутинг

#### При входе в систему:

```typescript
switch (user?.organization?.type) {
  case 'SELLER':
    router.push('/my-supplies') // Направляем на страницу поставок
    break
}
```

#### Специальная логика роутинга:

> 📖 **Бизнес-логика роутинга**: См. [rules-complete.md#4-система-ролей-и-доступов](./rules-complete.md#4--система-ролей-и-доступов)

## 2. 🎨 UI/UX КОМПОНЕНТЫ

### 2.1 Dashboard компоненты

#### Основные компоненты кабинета:

- `SellerHomePage` - главный компонент селлера
- `SellerEconomicsPage` - экономическая аналитика
- `MySuppliesDashboard` - управление поставками

#### Wrapper-компоненты:

- `HomePageWrapper` - маршрутизация по типам организаций
- `EconomicsPageWrapper` - адаптивная экономика по кабинетам

### 2.2 Детальные правила горизонтального скролла поставщиков

**КНОПКА НАВИГАЦИИ "НАЗАД":**

**Архитектура размещения:**

- **Расположение**: Между сайдбаром и основным контентом
- **Контейнер**: Отдельный `<div className="relative">`
- **НЕ является частью блока 1** - независимый навигационный элемент
- **Позиционирование**: `absolute left-0 top-6`
- **z-index**: 10 (поверх контента)

**Визуальный дизайн:**

```tsx
className =
  'absolute left-0 top-6 z-10 w-8 h-8 bg-white/10 backdrop-blur-xl border border-white/20 hover:border-white/40 rounded-full flex items-center justify-center transition-all duration-300 hover:scale-110 hover:bg-white/20 group'
```

**Параметры кнопки:**

- **Размер**: 32×32px (`w-8 h-8`)
- **Форма**: Круглая (`rounded-full`)
- **Фон**: `bg-white/10` с эффектом размытия `backdrop-blur-xl`
- **Граница**: `border border-white/20`, при hover `border-white/40`
- **Иконка**: `ArrowLeft` 16×16px (`h-4 w-4`), цвет `text-white/70`
- **Hover эффекты**:
  - Масштабирование `scale-110`
  - Изменение фона `bg-white/20`
  - Иконка становится белой и увеличивается до `h-5 w-5`
- **Анимация**: `transition-all duration-300`

**Функциональность:**

- **onClick**: Переход на `/supplies?tab=goods&subTab=suppliers`
- **aria-label**: "Вернуться к поставщикам"
- **Семантика**: Кнопка возврата к списку поставок

**СТРУКТУРА И ОТОБРАЖЕНИЕ БЛОКА 1:**

- **БЕЗ ЗАГОЛОВКА** - блок начинается сразу с поиска и контента
- **Источник данных**: Партнеры типа `WHOLESALE` из раздела "Партнеры"
- **Контейнер**: Фиксированная высота 176px (h-44) с горизонтальным скроллом
- **Блок поставщиков**: Общая высота 180px
- **Направление**: Слева направо (LTR)
- **Поведение**: Плавный скролл с автоскрытием полосы прокрутки

**РАЗМЕРЫ И АДАПТИВНОСТЬ:**

- **Десктоп**: Карточка 216×92px, отступы 12px между карточками, 16px от краев
- **Планшет**: Карточка 200×92px, отступы 12px между карточками
- **Мобильный**: Карточка 184×92px, отступы 12px между карточками
- **Высота блока**: 180px фиксированная для всего блока поставщиков

**ВЗАИМОДЕЙСТВИЕ:**

- **Навигация**: Колесо мыши (Shift+скролл), стрелки клавиатуры, свайп на тач
- **Выбор**: Клик по карточке → активная рамка + загрузка товаров в блок 2
- **Состояния**: Default, Hover (box-shadow), Active (цветная рамка), Loading (скелетон)

**ГРАНИЧНЫЕ СЛУЧАИ:**

- **1-4 карточки**: Выравнивание по левому краю, скролл неактивен
- **5+ карточек**: Полный горизонтальный скролл
- **Нет партнеров**: Заглушка с ссылкой на раздел "Партнеры"

**ТЕХНИЧЕСКАЯ РЕАЛИЗАЦИЯ:**

**Критическая Flex-архитектура:**

```css
.parent-container {
  display: flex;
  gap: 16px;
  min-height: 0;
}

.left-block {
  flex: 1;
  min-width: 0; /* КРИТИЧЕСКИ ВАЖНО для overflow */
  display: flex;
  flex-direction: column;
}

.suppliers-container {
  height: 180px; /* Общая высота блока */
  flex-shrink: 0;
  min-width: 0; /* Предотвращает растяжение */
}

.right-block {
  width: 384px; /* w-96 */
  flex-shrink: 0; /* Защита от сжатия */
}
```

**Контейнер скролла:**

```css
.suppliers-block {
  display: flex;
  overflow-x: auto;
  scroll-behavior: smooth;
  gap: 12px;
  padding: 0 16px 8px 16px; /* px-4 pb-2 */
  height: 176px; /* h-44 */
  scrollbar-width: thin;
  scrollbar-color: #64748b33 transparent;
}

.suppliers-block:hover {
  scrollbar-color: #cbd5e0 #64748b22;
}

.supplier-card {
  flex-shrink: 0;
  width: 216px; /* Десктоп */
  height: 92px; /* Фиксированная высота */
  padding: 8px; /* p-2 */
  transition: all 0.2s ease;
}
```

**СОДЕРЖАНИЕ КАРТОЧКИ ПОСТАВЩИКА:**

**Структура (3 строки в 92px высоты):**

- **Строка 1**: Название + рейтинг (справа, если есть)
- **Строка 2**: ИНН (формат "ИНН: 1234567890")
- **Строка 3**: Бейдж рынка (отдельная строка)

**Элементы:**

- **Аватар**: Размер xs, слева с gap-2
- **Текст**: text-xs для компактности
- **Отступы**: mb-1 между строками 1-2, mb-0.5 между строками 2-3
- **Padding карточки**: 8px (p-2)

**ЦВЕТОВАЯ СХЕМА РЫНКОВ:**

- **"Садовод"** (sadovod): Зеленый `bg-green-500/20 text-green-300 border-green-500/30`
- **"ТЯК Москва"** (tyak-moscow): Синий `bg-blue-500/20 text-blue-300 border-blue-500/30`
- **Другие/не указан**: Серый `bg-gray-500/20 text-gray-300 border-gray-500/30`

**ДОСТУПНОСТЬ:**

- `role="tablist"` для контейнера
- `role="tab"` для карточек
- `aria-selected="true/false"` для выбранной карточки
- `tabindex="0"` для активной, `-1` для неактивных

### 2.3 Правила блока "Карточки товаров" (Блок 2)

**НАЗНАЧЕНИЕ И ЛОГИКА:**

- **Источник данных**: Товары выбранного поставщика из Блока 1
- **Триггер отображения**: Клик на карточку поставщика → загрузка карточек товаров
- **Взаимодействие**: Клик на карточку товара → добавление в Блок 3 "Товары поставщика"
- **Поведение**: Горизонтальный скролл при множестве товаров

**АРХИТЕКТУРА И РАЗМЕРЫ:**

- **Внешний контейнер**: bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl flex-shrink-0
- **Внутренний контейнер скролла**: flex gap-3 overflow-x-auto p-4
- **Стилизация скролла**: scrollbarWidth: 'thin' для тонкой полосы прокрутки
- **Отступы**: padding: 16px (p-4) внутри, gap: 12px (gap-3) между карточками
- **Адаптивная высота**: по содержимому карточек (БЕЗ фиксированной высоты)
- **Визуальное единство**: стеклянный эффект как у других блоков системы
- **БЕЗ заголовков/иконок**: только чистые карточки товаров в контейнере

**РАЗМЕРЫ КАРТОЧЕК ТОВАРОВ:**

- **Компактная карточка**: 80×112px (w-20 h-28), соотношение 5:7
- **Адаптивность**: фиксированный размер для всех устройств

**СОДЕРЖАНИЕ КАРТОЧКИ ТОВАРА:**

- **ТОЛЬКО изображение товара**: 80×112px, object-cover
- **Минималистичный дизайн**: БЕЗ текста, названий, цен, иконок
- **Состояния**: Default, Selected, Active (БЕЗ Hover-эффектов)
- **Рамка**: border-white/10, при выборе border-white/30
- **Фон**: bg-white/5 полупрозрачный

**ДЕЙСТВИЕ:**
Клик на карточку → добавление товара в Блок 3 (детальный каталог)

### 2.4 ПРАВИЛА КОРЗИНЫ - ЕДИНЫЙ СТАНДАРТ

**КРИТИЧЕСКИ ВАЖНО**: Все корзины в системе должны следовать единому стандарту дизайна и функциональности.

#### **2.4.1 Размеры и позиционирование**

```tsx
<div className="w-72 flex-shrink-0">
  <div className="bg-white/10 backdrop-blur border-white/20 p-3 sticky top-0 rounded-2xl">
```

**ОБЯЗАТЕЛЬНЫЕ ПАРАМЕТРЫ**:

- **Ширина**: `w-72` (288px) - фиксированная ширина для всех корзин
- **Флекс**: `flex-shrink-0` - корзина не сжимается
- **Позиция**: `sticky top-0` - прилипает к верху при прокрутке
- **Стиль**: Glass morphism эффект с `backdrop-blur` и `bg-white/10`

#### **2.4.2 Автодобавление товаров**

**ПРАВИЛО AUTO-ADD**: При вводе количества товар автоматически добавляется в корзину.

```tsx
// ОБЯЗАТЕЛЬНАЯ РЕАЛИЗАЦИЯ:
const handleQuantityChange = (e: React.ChangeEvent<HTMLInputElement>) => {
  const inputValue = e.target.value
  const newQuantity = inputValue === '' ? 0 : Math.max(0, parseInt(inputValue) || 0)

  if (newQuantity > 0) {
    // Автоматически добавляем товар в корзину
    updateProductQuantity(product.id, newQuantity)
  } else {
    // Удаляем товар из корзины при количестве 0
    removeFromCart(product.id)
  }
}
```

**ДЕФОЛТНОЕ ЗНАЧЕНИЕ**: Пустой инпут (`value={''}`) вместо `value={0}`

#### **2.4.3 Структура корзины**

**ОБЯЗАТЕЛЬНЫЕ ЭЛЕМЕНТЫ**:

1. **Заголовок**: "Корзина (X шт)" с иконкой корзины
2. **Список товаров**:
   - Название товара (БЕЗ суффикса "(с рецептурой)")
   - Цена за единицу × количество
   - Кнопка удаления (X справа)
3. **Мета-информация**: Дата поставки, фулфилмент-центр, логистика
4. **Итого**: Общая сумма с выделением зелёным цветом
5. **Кнопка действия**: "Создать поставку" с градиентом

**ЗАПРЕЩЕНО**: Отображать текст "(с рецептурой)" в названиях товаров в корзине

#### **2.4.4 Единая функция расчета стоимости**

**КРИТИЧЕСКИ ВАЖНО**: Использовать единую функцию расчета для избежания расхождений:

```tsx
const getProductTotalWithRecipe = (productId: string, quantity: number) => {
  const product = products.find((p) => p.id === productId)
  if (!product) return 0

  // Базовая цена товара
  let total = (product.pricePerUnit || 0) * quantity

  // Добавляем услуги
  if (product.services && product.services.length > 0) {
    const servicesTotal = product.services.reduce((sum, service) => {
      return sum + (service.pricePerUnit || 0) * quantity
    }, 0)
    total += servicesTotal
  }

  // Добавляем FF расходники (используем .price, НЕ .pricePerUnit!)
  if (product.ffConsumables && product.ffConsumables.length > 0) {
    const ffConsumablesTotal = product.ffConsumables.reduce((sum, consumable) => {
      return sum + (consumable.price || 0) * quantity // ВАЖНО: .price!
    }, 0)
    total += ffConsumablesTotal
  }

  // Добавляем расходники продавца
  if (product.sellerConsumables && product.sellerConsumables.length > 0) {
    const sellerConsumablesTotal = product.sellerConsumables.reduce((sum, consumable) => {
      return sum + (consumable.pricePerUnit || 0) * quantity
    }, 0)
    total += sellerConsumablesTotal
  }

  return total
}
```

#### **2.4.5 Синхронизация данных между блоками**

**ПРАВИЛО СИНХРОНИЗАЦИИ**: Данные в корзине должны отражать выборы из всех блоков формы:

1. **Дата поставки**: Из Блока 3 (дата пикер)
2. **Фулфилмент-центр**: Название выбранного FF (реальные данные!)
3. **Логистическая компания**: Только партнеры типа `'LOGIST'`

**ПОРЯДОК ОТОБРАЖЕНИЯ В КОРЗИНЕ**:

```
Дата поставки: 08.08.2025
Фулфилмент-центр: ФУЛФИЛМЕНТ РУ
Логистическая компания: [Выпадающий список]
```

#### **2.4.6 Критические требования**

🚨 **БЕЗОПАСНОСТЬ ТИПОВ**:

- Всегда проверять на `null/undefined`: `selectedSupplier?.id || ''`
- Использовать optional chaining для всех вложенных объектов

🚨 **ПРОИЗВОДИТЕЛЬНОСТЬ**:

- Мемоизация расчетов: `useMemo` для дорогих вычислений
- Debounce для инпутов количества

🚨 **UX КОНСИСТЕНТНОСТЬ**:

- Единые стили для всех корзин в системе
- Одинаковое поведение auto-add во всех формах
- Синхронная валидация данных

### 2.5 Трёхблочная архитектура страницы "Мои поставки"

**ПРИНЦИП**: Страница состоит из трёх визуально разделённых блоков

```
┌─────────────────────────────────────────┐
│  1. БЛОК ТАБОВ (навигация)             │
│     - Фиксированная высота             │
│     - Glass-эффект                     │
│     - Иерархическая структура          │
├─────────────────────────────────────────┤
│  2. БЛОК СТАТИСТИКИ (метрики)          │
│     - Контекстные данные               │
│     - 4 карточки в ряд (desktop)       │
│     - Динамическое обновление          │
├─────────────────────────────────────────┤
│  3. ОСНОВНОЙ БЛОК (контент)            │
│     - Сохраняет весь функционал        │
│     - Таблицы, фильтры, действия       │
│     - Высота до низа sidebar           │
└─────────────────────────────────────────┘
```

**ПРАВИЛО**: Статистика меняется в зависимости от выбранных табов

**Для путей "Фулфилмент → Товар → Карточки/Поставщики":**

- Всего поставок
- Активных поставок
- Сумма активных поставок
- В пути

**ФОРМУЛА РАСЧЕТА ВЫСОТЫ**:

```css
height: calc(100vh - headerHeight - tabsHeight - statsHeight - margins);
```

**ПРАВИЛО ВЫРАВНИВАНИЯ**:

- Нижняя граница основного блока должна быть на одном уровне с нижней границей sidebar
- При изменении размера окна высота пересчитывается
- Внутренний скролл: `overflow-y-auto`

### 2.6 Четырёхблочная архитектура создания поставки расходников

#### **Структура страницы**:

**БЛОК 1: ПОСТАВЩИКИ** _(обязательный, 180px)_:

- БЕЗ заголовка - сразу функциональный контент
- Кнопка навигации "Назад" - между сайдбаром и блоком (см. раздел 2.2)
- Карточки поставщиков из раздела "Партнеры"
- Горизонтальный скролл при превышении ширины
- Выбор только одного поставщика одновременно

**БЛОК 2: КАРТОЧКИ ТОВАРОВ** _(адаптивная высота - НОВЫЙ БЛОК)_:

- ТОЛЬКО минималистичные карточки товаров 80×112px
- ТОЛЬКО изображение товара, БЕЗ текста/названий/цен
- Горизонтальный скролл при множестве товаров
- Клик добавляет товар в блок 3

**БЛОК 3: ТОВАРЫ ПОСТАВЩИКА** _(flex-1, детальный каталог)_:

- Детальные карточки выбранных товаров
- Управление количеством и параметрами поставки

**БЛОК 4: КОРЗИНА И НАСТРОЙКИ** _(правая панель, 384px)_:

- Корзина поставки с выбранными товарами
- Настройки поставки (фулфилмент-центр, дата, логистика)
- Сортировка: цена, название, категория
- Фильтры: категория, ценовой диапазон
- Карточка с полем ввода количества и кнопками +/-

**БЛОК 3: КОРЗИНА** _(правая часть)_:

- **РАСПОЛОЖЕНИЕ**: Правая часть экрана
- **СОДЕРЖАНИЕ**:
  - Счетчик видов расходников
  - Детализация по каждому расходнику (название, количество, цена, сумма)
  - Общая сумма всех расходников
- **УПРАВЛЕНИЕ**:
  - Изменение количества (с валидацией остатков)
  - Удаление позиций
- **ОБЯЗАТЕЛЬНЫЕ ПОЛЯ**:
  - Выбор фулфилмент-центра (из партнеров)
  - Дата поставки (не прошедшая, по умолчанию - текущая)

### 2.7 Многоуровневая таблица поставок

#### **ПЕРВЫЙ УРОВЕНЬ** _(основной список)_:

- **СОРТИРОВКА**: Номер поставки от большего к меньшему
- **ОБЯЗАТЕЛЬНЫЕ КОЛОНКИ**:
  - Порядковый номер поставки
  - Количество видов расходников
  - Стоимость всей поставки
  - Количество категорий
  - Статус поставки

#### **ВТОРОЙ УРОВЕНЬ** _(детализация по клику)_:

- **АКТИВАЦИЯ**: По клику на строку первого уровня
- **СОДЕРЖАНИЕ**:
  - Название расходника
  - Количество
  - Цена
  - Категория
  - Поставщик
- **ОГРАНИЧЕНИЯ**: Только просмотр, редактирование запрещено

## 3. 🛠️ ГРАФИЧЕСКИЙ ИНТЕРФЕЙС И КОМПОНЕНТЫ

### 3.1 React компоненты селлера

**Основные компоненты:**

- `SellerHomePage` - главная страница селлера (4 типо-зависимых компонента)
- `SellerEconomicsPage` - экономическая аналитика селлера

### 3.2 Роутинг для селлера

```typescript
switch (user?.organization?.type) {
  case 'SELLER':
    router.push('/supplies')
    break
}
```

### 3.3 Структура разделов кабинета

**🛍️ СЕЛЛЕР (`SELLER`):**

- Мои поставки (`/supplies`) - управление заказами товаров
- WB Интеграция (`/wb-integration`) - связь с Wildberries

## 4. 🛠️ GRAPHQL API

### 4.1 Основные запросы (Queries)

#### Получение карточек селлера:

```graphql
query GetSellerCards {
  myMarketplaceCards {
    id
    title
    marketplace
    article
    linkedProductId # null если свободна
    linkedProduct {
      # для отображения занятости
      id
      name
    }
  }
}
```

---

**Последнее обновление**: Август 2025
**Связанные файлы**:

- [rules-complete.md](./rules-complete.md) - Общие бизнес-правила
- [visual-design-rules.md](./visual-design-rules.md) - Визуальные правила
