Files
sfera/seller-ui-rules.md
Veronika Smirnova c5cd75cdb9 docs: обновление правил UI Kit и блока поставщиков + новые glass компоненты
- Добавлены правила анализа UI Kit компонентов (interaction-integrity-rules.md)
- Обновлены правила блока 1: убран заголовок, добавлена кнопка навигации (rules-complete.md)
- Детальная спецификация плавающей кнопки "Назад" (seller-ui-rules.md)
- Новые компоненты: GlassDatePicker и GlassSelect для UI Kit
- Улучшены hover/focus эффекты в DatePicker

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-12 18:08:24 +03:00

24 KiB
Raw Blame History

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

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

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

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

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

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

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

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

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

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

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

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

📖 Бизнес-логика роутинга: См. 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 (поверх контента)

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

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-архитектура:

.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; /* Защита от сжатия */
}

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

.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 Размеры и позиционирование

<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: При вводе количества товар автоматически добавляется в корзину.

// ОБЯЗАТЕЛЬНАЯ РЕАЛИЗАЦИЯ:
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 Единая функция расчета стоимости

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

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           │
└─────────────────────────────────────────┘

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

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

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

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

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 Роутинг для селлера

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

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

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

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

4. 🛠️ GRAPHQL API

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

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

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

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