
- Добавлены правила анализа 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>
24 KiB
ПРАВИЛА 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
, при hoverborder-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 Структура корзины
ОБЯЗАТЕЛЬНЫЕ ЭЛЕМЕНТЫ:
- Заголовок: "Корзина (X шт)" с иконкой корзины
- Список товаров:
- Название товара (БЕЗ суффикса "(с рецептурой)")
- Цена за единицу × количество
- Кнопка удаления (X справа)
- Мета-информация: Дата поставки, фулфилмент-центр, логистика
- Итого: Общая сумма с выделением зелёным цветом
- Кнопка действия: "Создать поставку" с градиентом
ЗАПРЕЩЕНО: Отображать текст "(с рецептурой)" в названиях товаров в корзине
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 Синхронизация данных между блоками
ПРАВИЛО СИНХРОНИЗАЦИИ: Данные в корзине должны отражать выборы из всех блоков формы:
- Дата поставки: Из Блока 3 (дата пикер)
- Фулфилмент-центр: Название выбранного FF (реальные данные!)
- Логистическая компания: Только партнеры типа
'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 Связанные файлы:
- rules-complete.md - Общие бизнес-правила
- visual-design-rules.md - Визуальные правила