Обновление системной документации и UI Kit админ панели

- Обновлен CLAUDE.md с добавлением принципов качества кода
- Расширен interaction-integrity-rules.md новыми правилами взаимодействия
- Дополнен rules-complete.md техническими требованиями
- Добавлен демо-компонент вариантов кнопки "Назад" в UI Kit
- Обновлены компоненты админ панели и страницы создания расходников
- Уточнены visual-design-rules.md для компонента BackButton
- Исправлены ESLint ошибки и предупреждения

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Veronika Smirnova
2025-08-12 10:21:12 +03:00
parent 5a51ec32f6
commit c586ddc868
9 changed files with 735 additions and 118 deletions

View File

@ -99,6 +99,30 @@ npm run dev
> ⚠️ **ВАЖНО**: Всегда выполнять эти команды перед завершением задачи! > ⚠️ **ВАЖНО**: Всегда выполнять эти команды перед завершением задачи!
## 🔄 КОМАНДЫ ОТКАТА
### Откат через комментарии:
**Основная команда:**
```
"откати [описание] через комментарии"
```
**Примеры:**
- `"откати центрирование поиска через комментарии"`
- `"откати изменения кнопки через комментарии"`
- `"откати новую логику через комментарии"`
**Дополнительные команды:**
- `"очисти комментарии"` - удалить закомментированные варианты
- `"переключи на вариант 2"` - активировать закомментированный код
- `"покажи варианты"` - показать доступные варианты
> 📖 **Подробнее**: см. раздел 6.4 в `interaction-integrity-rules.md`
## 💾 РАБОТА С КОНТЕКСТОМ ## 💾 РАБОТА С КОНТЕКСТОМ
### Файлы для сохранения контекста: ### Файлы для сохранения контекста:

263
back-button-variants.html Normal file
View File

@ -0,0 +1,263 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Варианты кнопки "Назад"</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
body {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
}
.glass {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(16px);
border: 1px solid rgba(255, 255, 255, 0.2);
}
.sidebar-mock {
width: 240px;
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.block-mock {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(16px);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 16px;
height: 180px;
}
</style>
</head>
<body class="p-8 text-white">
<h1 class="text-3xl font-bold mb-8 text-center">Варианты размещения кнопки "Назад"</h1>
<!-- ВАРИАНТ 1: ПЛАВАЮЩАЯ КНОПКА СЛЕВА -->
<div class="mb-12">
<h2 class="text-xl font-semibold mb-4">🌟 Вариант 1: Плавающая кнопка слева</h2>
<div class="flex gap-4 h-48">
<!-- Sidebar Mock -->
<div class="sidebar-mock rounded-2xl p-4 flex flex-col">
<div class="flex items-center gap-3 mb-6">
<div class="w-8 h-8 bg-purple-500 rounded-full"></div>
<span class="text-sm">Rennel</span>
</div>
<div class="space-y-2">
<div class="text-sm opacity-60">Главная</div>
<div class="text-sm opacity-60">Маркет</div>
<div class="text-sm opacity-60">Мессенджер</div>
</div>
</div>
<!-- Floating Back Button -->
<div class="relative">
<button class="absolute left-0 top-6 z-10 w-8 h-8 glass rounded-full flex items-center justify-center transition-all duration-300 hover:scale-110 hover:bg-white/20 group">
<svg class="h-4 w-4 text-white/70 group-hover:text-white group-hover:h-5 group-hover:w-5 transition-all" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
</svg>
</button>
</div>
<!-- Block 1 Mock -->
<div class="flex-1 block-mock p-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<svg class="h-5 w-5 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"></path>
</svg>
<h2 class="text-lg font-semibold">Поставщики</h2>
</div>
<div class="w-64 glass rounded-full px-3 py-1.5 text-sm">
<span class="text-white/60">Поиск поставщиков...</span>
</div>
</div>
</div>
</div>
</div>
<!-- ВАРИАНТ 2: ПОЛОСА НАВИГАЦИИ СВЕРХУ -->
<div class="mb-12">
<h2 class="text-xl font-semibold mb-4">📍 Вариант 2: Полоса навигации сверху</h2>
<div class="flex gap-4">
<!-- Sidebar Mock -->
<div class="sidebar-mock rounded-2xl p-4 flex flex-col h-48">
<div class="flex items-center gap-3 mb-6">
<div class="w-8 h-8 bg-purple-500 rounded-full"></div>
<span class="text-sm">Rennel</span>
</div>
<div class="space-y-2">
<div class="text-sm opacity-60">Главная</div>
<div class="text-sm opacity-60">Маркет</div>
<div class="text-sm opacity-60">Мессенджер</div>
</div>
</div>
<!-- Content Area -->
<div class="flex-1">
<!-- Navigation Bar -->
<div class="flex items-center justify-start mb-4">
<button class="w-6 h-6 hover:w-8 hover:h-8 bg-gradient-to-r from-purple-500/20 to-blue-500/20 hover:from-purple-500/40 hover:to-blue-500/40 rounded-full flex items-center justify-center transition-all duration-300 backdrop-blur-sm border border-white/10 hover:border-white/30 group">
<svg class="h-3 w-3 group-hover:h-4 group-hover:w-4 text-white/60 group-hover:text-white transition-all" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
</svg>
</button>
</div>
<!-- Block 1 Mock -->
<div class="block-mock p-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<svg class="h-5 w-5 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"></path>
</svg>
<h2 class="text-lg font-semibold">Поставщики</h2>
</div>
<div class="w-64 glass rounded-full px-3 py-1.5 text-sm">
<span class="text-white/60">Поиск поставщиков...</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- ВАРИАНТ 3: КНОПКА В РАЗРЫВЕ -->
<div class="mb-12">
<h2 class="text-xl font-semibold mb-4">🎯 Вариант 3: Кнопка в разрыве</h2>
<div class="flex gap-4 h-48 relative">
<!-- Sidebar Mock -->
<div class="sidebar-mock rounded-2xl p-4 flex flex-col">
<div class="flex items-center gap-3 mb-6">
<div class="w-8 h-8 bg-purple-500 rounded-full"></div>
<span class="text-sm">Rennel</span>
</div>
<div class="space-y-2">
<div class="text-sm opacity-60">Главная</div>
<div class="text-sm opacity-60">Маркет</div>
<div class="text-sm opacity-60">Мессенджер</div>
</div>
</div>
<!-- Button in Gap -->
<div class="w-0 flex items-center justify-center relative">
<button class="absolute w-10 h-10 glass rounded-xl hover:bg-white/15 flex items-center justify-center transition-all duration-500 hover:scale-125 hover:rotate-12 hover:border-purple-400/50 group backdrop-blur-md">
<svg class="h-4 w-4 text-white/50 group-hover:text-purple-300 transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
</svg>
</button>
</div>
<!-- Block 1 Mock -->
<div class="flex-1 block-mock p-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<svg class="h-5 w-5 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"></path>
</svg>
<h2 class="text-lg font-semibold">Поставщики</h2>
</div>
<div class="w-64 glass rounded-full px-3 py-1.5 text-sm">
<span class="text-white/60">Поиск поставщиков...</span>
</div>
</div>
</div>
</div>
</div>
<!-- ВАРИАНТ 4: BREADCRUMB СТИЛЬ -->
<div class="mb-12">
<h2 class="text-xl font-semibold mb-4">🍞 Вариант 4: Breadcrumb стиль</h2>
<div class="flex gap-4">
<!-- Sidebar Mock -->
<div class="sidebar-mock rounded-2xl p-4 flex flex-col h-48">
<div class="flex items-center gap-3 mb-6">
<div class="w-8 h-8 bg-purple-500 rounded-full"></div>
<span class="text-sm">Rennel</span>
</div>
<div class="space-y-2">
<div class="text-sm opacity-60">Главная</div>
<div class="text-sm opacity-60">Маркет</div>
<div class="text-sm opacity-60">Мессенджер</div>
</div>
</div>
<!-- Content Area -->
<div class="flex-1">
<!-- Breadcrumb -->
<div class="flex items-center gap-2 mb-2 pl-2">
<button class="p-1 hover:p-2 bg-white/0 hover:bg-white/10 rounded-lg transition-all duration-300 group">
<svg class="h-3 w-3 group-hover:h-4 group-hover:w-4 text-white/40 group-hover:text-white transition-all" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
</svg>
</button>
<span class="text-white/20 text-sm"></span>
<span class="text-white/60 text-sm">Поставщики</span>
</div>
<!-- Block 1 Mock -->
<div class="block-mock p-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<svg class="h-5 w-5 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"></path>
</svg>
<h2 class="text-lg font-semibold">Поставщики</h2>
</div>
<div class="w-64 glass rounded-full px-3 py-1.5 text-sm">
<span class="text-white/60">Поиск поставщиков...</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- ВАРИАНТ 5: ВЕРТИКАЛЬНАЯ ПАНЕЛЬ -->
<div class="mb-12">
<h2 class="text-xl font-semibold mb-4">🔥 Вариант 5: Вертикальная панель</h2>
<div class="flex gap-4 h-48">
<!-- Sidebar Mock -->
<div class="sidebar-mock rounded-2xl p-4 flex flex-col">
<div class="flex items-center gap-3 mb-6">
<div class="w-8 h-8 bg-purple-500 rounded-full"></div>
<span class="text-sm">Rennel</span>
</div>
<div class="space-y-2">
<div class="text-sm opacity-60">Главная</div>
<div class="text-sm opacity-60">Маркет</div>
<div class="text-sm opacity-60">Мессенджер</div>
</div>
</div>
<!-- Vertical Panel -->
<div class="w-8 flex flex-col items-center py-4">
<button class="w-6 h-6 hover:w-7 hover:h-7 bg-gradient-to-b from-purple-500/10 to-transparent hover:from-purple-500/30 hover:to-purple-400/10 rounded-full flex items-center justify-center transition-all duration-300 hover:shadow-lg hover:shadow-purple-500/20 group">
<svg class="h-3 w-3 group-hover:h-4 group-hover:w-4 text-white/50 group-hover:text-purple-300 transition-all duration-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
</svg>
</button>
</div>
<!-- Block 1 Mock -->
<div class="flex-1 block-mock p-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<svg class="h-5 w-5 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"></path>
</svg>
<h2 class="text-lg font-semibold">Поставщики</h2>
</div>
<div class="w-64 glass rounded-full px-3 py-1.5 text-sm">
<span class="text-white/60">Поиск поставщиков...</span>
</div>
</div>
</div>
</div>
</div>
<div class="text-center text-white/60 mt-8">
<p>Наведите курсор на кнопки для просмотра hover эффектов</p>
</div>
</body>
</html>

View File

@ -470,6 +470,83 @@ ignores: ['diagnostic-script.js', 'legacy-config.js'] // конкретные ф
**ПРИ НЕОПРЕДЕЛЕННОСТИ:** СТОП → Вопрос пользователю → Ждать ответа **ПРИ НЕОПРЕДЕЛЕННОСТИ:** СТОП → Вопрос пользователю → Ждать ответа
**ПРИ ОШИБКЕ В ПЛАНЕ:** СТОП → Сообщить проблему → Не выполнять до исправления **ПРИ ОШИБКЕ В ПЛАНЕ:** СТОП → Сообщить проблему → Не выполнять до исправления
### 6.4 🔄 КОМАНДЫ ОТКАТА ЧЕРЕЗ КОММЕНТАРИИ
#### **ОСНОВНАЯ КОМАНДА:**
```
"откати [описание] через комментарии"
```
**Примеры использования:**
- `"откати центрирование поиска через комментарии"`
- `"откати изменения кнопки через комментарии"`
- `"откати новую логику через комментарии"`
#### **АЛГОРИТМ ВЫПОЛНЕНИЯ:**
**ЭТАП 1: ВОССТАНОВЛЕНИЕ ИСХОДНОГО КОДА**
1. Найти измененный код в текущих файлах
2. Извлечь исходный код из git истории (`git show HEAD:путь/к/файлу`)
3. Восстановить исходную функциональность
**ЭТАП 2: СОЗДАНИЕ СИСТЕМЫ ПЕРЕКЛЮЧЕНИЯ** 4. Оставить **Вариант 1** (исходный) - активным 5. Добавить **Вариант 2** (измененный) в комментариях 6. Добавить четкие описания для каждого варианта
**ПРИМЕР СТРУКТУРЫ КОДА:**
```jsx
// Вариант 1: Исходный (активный)
<div className="flex items-center justify-between">
{/* исходный код */}
</div>
// Вариант 2: Измененный (для быстрого переключения)
/*
<div className="flex justify-center">
{/* измененный код */}
</div>
*/
```
#### **ДОПОЛНИТЕЛЬНЫЕ КОМАНДЫ:**
**ОЧИСТКА КОММЕНТАРИЕВ:**
- `"очисти комментарии"` - удалить все закомментированные варианты
- `"удали вариант 2"` - удалить конкретный закомментированный вариант
**ПЕРЕКЛЮЧЕНИЕ ВАРИАНТОВ:**
- `"переключи на вариант 2"` - активировать закомментированный код
- `"активируй измененный вариант"` - то же самое
**ИНФОРМАЦИОННЫЕ КОМАНДЫ:**
- `"покажи варианты"` - показать все доступные варианты в комментариях
- `"какие есть варианты кода?"` - перечислить доступные варианты
#### **ПРЕИМУЩЕСТВА МЕТОДА:**
**Мгновенный откат** - просто переставить комментарии
**Видимость всех вариантов** - код содержит историю изменений
**Быстрые эксперименты** - легко переключаться между решениями
**Не усложняет архитектуру** - не требует feature flags или конфигов
#### **ОГРАНИЧЕНИЯ:**
⚠️ **Временное решение** - не для production кода
⚠️ **Увеличивает объем кода** - нужно очищать перед финальным коммитом
⚠️ **Только для небольших изменений** - не подходит для кардинальных переработок
#### **ПРАВИЛА ПРИМЕНЕНИЯ:**
- ✅ Использовать для UI экспериментов и небольших логических изменений
- ✅ Всегда добавлять четкие комментарии с описанием вариантов
- ✅ Очищать комментарии перед финальным коммитом
-Не использовать для изменений архитектуры или критической логики
--- ---
## 🚀 ЗАКЛЮЧЕНИЕ ## 🚀 ЗАКЛЮЧЕНИЕ

View File

@ -1,7 +1,3 @@
>
> ❌ **ЗАПРЕЩЕНО РЕДАКТИРОВАТЬ БЕЗ ЯВНОГО РАЗРЕШЕНИЯ ПОЛЬЗОВАТЕЛЯ!** > ❌ **ЗАПРЕЩЕНО РЕДАКТИРОВАТЬ БЕЗ ЯВНОГО РАЗРЕШЕНИЯ ПОЛЬЗОВАТЕЛЯ!**
> >
> 📅 **Дата создания резерва**: 2025-08-08 > 📅 **Дата создания резерва**: 2025-08-08
@ -852,6 +848,8 @@ const handleSuppliesClick = () => {
#### **📄 Структура страницы создания поставки:** #### **📄 Структура страницы создания поставки:**
**ВАЖНО**: Страница НЕ имеет основного заголовка и описания. Сразу начинается с блоков контента.
**ОБНОВЛЕННАЯ СТРУКТУРА СИСТЕМЫ (4 БЛОКА):** **ОБНОВЛЕННАЯ СТРУКТУРА СИСТЕМЫ (4 БЛОКА):**
**БЛОК 1: ПОСТАВЩИКИ** _(адаптивная сетка)_ **БЛОК 1: ПОСТАВЩИКИ** _(адаптивная сетка)_
@ -1981,6 +1979,7 @@ height: calc(100vh - headerHeight - tabsHeight - statsHeight - margins);
### 11.4 Правила фулфилмента ### 11.4 Правила фулфилмента
**ОБЯЗАТЕЛЬНО**: **ОБЯЗАТЕЛЬНО**:
- Установка цен на расходники перед доступностью селлерам - Установка цен на расходники перед доступностью селлерам
- Контроль качества товаров при приемке - Контроль качества товаров при приемке
- Своевременная обработка возвратов - Своевременная обработка возвратов
@ -1988,6 +1987,7 @@ height: calc(100vh - headerHeight - tabsHeight - statsHeight - margins);
- Управление персоналом и рабочим временем - Управление персоналом и рабочим временем
**ЗАПРЕЩЕНО**: **ЗАПРЕЩЕНО**:
- Отгружать товары без подтверждения наличия - Отгружать товары без подтверждения наличия
- Создавать расходники минуя систему поставок - Создавать расходники минуя систему поставок
- Изменять цены закупки после поступления товара - Изменять цены закупки после поступления товара
@ -2246,11 +2246,13 @@ const wholesalePartners = await prisma.counterparty.findMany({
**НАЗНАЧЕНИЕ**: Бизнес-партнерство с автоматическим добавлением в контрагенты **НАЗНАЧЕНИЕ**: Бизнес-партнерство с автоматическим добавлением в контрагенты
**ФОРМАТ URL**: `?partner=REFERRAL_CODE` **ФОРМАТ URL**: `?partner=REFERRAL_CODE`
``` ```
http://localhost:3000/register?partner=SF2X9K4M7P http://localhost:3000/register?partner=SF2X9K4M7P
``` ```
**ЧТО ПРОИСХОДИТ**: **ЧТО ПРОИСХОДИТ**:
1. ✅ Начисляется 100 сфер (⚡) реферальная награда 1. ✅ Начисляется 100 сфер (⚡) реферальная награда
2. ✅ **Автоматически создается партнерство**: взаимное добавление в контрагенты 2. ✅ **Автоматически создается партнерство**: взаимное добавление в контрагенты
3. ✅ Устанавливается реферальная связь (`referredById`) 3. ✅ Устанавливается реферальная связь (`referredById`)
@ -2264,11 +2266,13 @@ http://localhost:3000/register?partner=SF2X9K4M7P
**НАЗНАЧЕНИЕ**: Маркетинговое привлечение с наградой, БЕЗ автоматического партнерства **НАЗНАЧЕНИЕ**: Маркетинговое привлечение с наградой, БЕЗ автоматического партнерства
**ФОРМАТ URL**: `?ref=REFERRAL_CODE` **ФОРМАТ URL**: `?ref=REFERRAL_CODE`
``` ```
http://localhost:3000/register?ref=SF2X9K4M7P http://localhost:3000/register?ref=SF2X9K4M7P
``` ```
**ЧТО ПРОИСХОДИТ**: **ЧТО ПРОИСХОДИТ**:
1. ✅ Начисляется 100 сфер (⚡) реферальная награда 1. ✅ Начисляется 100 сфер (⚡) реферальная награда
2. ✅ Устанавливается реферальная связь (`referredById`) 2. ✅ Устанавливается реферальная связь (`referredById`)
3. ❌ **НЕ создается партнерство**: организации НЕ добавляются в контрагенты 3. ❌ **НЕ создается партнерство**: организации НЕ добавляются в контрагенты
@ -2303,11 +2307,13 @@ if (referralCode) {
**В разделе "Партнеры"**: **В разделе "Партнеры"**:
**Вкладка "Мои партнеры"**: **Вкладка "Мои партнеры"**:
- Партнерская ссылка: `?partner=CODE` (автоматическое партнерство) - Партнерская ссылка: `?partner=CODE` (автоматическое партнерство)
- Заголовок: "Пригласить партнера" - Заголовок: "Пригласить партнера"
- Описание: "Для прямого делового сотрудничества" - Описание: "Для прямого делового сотрудничества"
**Вкладка "Рефералы"**: **Вкладка "Рефералы"**:
- Реферальная ссылка: `?ref=CODE` (только маркетинг) - Реферальная ссылка: `?ref=CODE` (только маркетинг)
- Заголовок: "Реферальная ссылка" - Заголовок: "Реферальная ссылка"
- Описание: "Для маркетинговых кампаний" - Описание: "Для маркетинговых кампаний"
@ -2315,14 +2321,17 @@ if (referralCode) {
#### **13.6.5 Правила именования** #### **13.6.5 Правила именования**
**В коде ВСЕГДА использовать**: **В коде ВСЕГДА использовать**:
- `partnerCode` / `partner=` → бизнес-партнерство - `partnerCode` / `partner=` → бизнес-партнерство
- `referralCode` / `ref=` → маркетинговое привлечение - `referralCode` / `ref=` → маркетинговое привлечение
**В комментариях и документации**: **В комментариях и документации**:
- "Партнерская ссылка" → автоматическое партнерство - "Партнерская ссылка" → автоматическое партнерство
- "Реферальная ссылка" → только маркетинг - "Реферальная ссылка" → только маркетинг
**ЗАПРЕЩЕНО**: **ЗАПРЕЩЕНО**:
- ❌ Называть партнерские ссылки "реферальными" - ❌ Называть партнерские ссылки "реферальными"
- ❌ Называть реферальные ссылки "партнерскими" - ❌ Называть реферальные ссылки "партнерскими"
- ❌ Использовать термины взаимозаменяемо - ❌ Использовать термины взаимозаменяемо
@ -2331,6 +2340,7 @@ if (referralCode) {
#### **13.6.6 Примеры использования** #### **13.6.6 Примеры использования**
**Сценарий 1 - Деловое партнерство**: **Сценарий 1 - Деловое партнерство**:
``` ```
Фулфилмент-центр хочет пригласить логистическую компанию Фулфилмент-центр хочет пригласить логистическую компанию
→ Использует партнерскую ссылку ?partner=CODE → Использует партнерскую ссылку ?partner=CODE
@ -2339,6 +2349,7 @@ if (referralCode) {
``` ```
**Сценарий 2 - Маркетинговая кампания**: **Сценарий 2 - Маркетинговая кампания**:
``` ```
Организация запускает рекламу в соцсетях Организация запускает рекламу в соцсетях
→ Использует реферальную ссылку ?ref=CODE → Использует реферальную ссылку ?ref=CODE

View File

@ -43,9 +43,9 @@ const AdminDashboard = React.memo(() => {
}, [activeSection]) }, [activeSection])
return ( return (
<div className="min-h-screen bg-gradient-smooth flex"> <div className="h-screen bg-gradient-smooth flex overflow-hidden">
<AdminSidebar activeSection={activeSection} onSectionChange={handleSectionChange} /> <AdminSidebar activeSection={activeSection} onSectionChange={handleSectionChange} />
<main className="flex-1 ml-64">{renderContent}</main> <main className="flex-1 ml-64 overflow-y-auto">{renderContent}</main>
</div> </div>
) )
}) })

View File

@ -5,6 +5,7 @@ import React from 'react'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { AnimationsDemo } from './ui-kit/animations-demo' import { AnimationsDemo } from './ui-kit/animations-demo'
import { BackButtonVariantsDemo } from './ui-kit/back-button-variants-demo'
import { BusinessDemo } from './ui-kit/business-demo' import { BusinessDemo } from './ui-kit/business-demo'
import { BusinessProcessesDemo } from './ui-kit/business-processes-demo' import { BusinessProcessesDemo } from './ui-kit/business-processes-demo'
import { ButtonsDemo } from './ui-kit/buttons-demo' import { ButtonsDemo } from './ui-kit/buttons-demo'
@ -84,6 +85,12 @@ const UIKitSection = React.memo(() => {
> >
Навигация Навигация
</TabsTrigger> </TabsTrigger>
<TabsTrigger
value="back-button-variants"
className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2"
>
Кнопки Назад
</TabsTrigger>
<TabsTrigger <TabsTrigger
value="specialized" value="specialized"
className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2" className="data-[state=active]:bg-white/20 data-[state=active]:text-white text-white/70 text-xs px-3 py-2"
@ -243,6 +250,9 @@ const UIKitSection = React.memo(() => {
<TabsContent value="supplies-navigation" className="space-y-6"> <TabsContent value="supplies-navigation" className="space-y-6">
<SuppliesNavigationDemo /> <SuppliesNavigationDemo />
</TabsContent> </TabsContent>
<TabsContent value="back-button-variants" className="space-y-6">
<BackButtonVariantsDemo />
</TabsContent>
<TabsContent value="business-processes" className="space-y-6"> <TabsContent value="business-processes" className="space-y-6">
<BusinessProcessesDemo /> <BusinessProcessesDemo />

View File

@ -0,0 +1,234 @@
'use client'
import { ArrowLeft, Building2 } from 'lucide-react'
import React from 'react'
export function BackButtonVariantsDemo() {
return (
<div className="space-y-12 p-6">
<div>
<h2 className="text-2xl font-bold text-white mb-2">Варианты кнопки &quot;Назад&quot;</h2>
<p className="text-white/60 mb-8">
Интерактивные варианты размещения кнопки навигации между сайдбаром и контентом
</p>
</div>
{/* ВАРИАНТ 1: ПЛАВАЮЩАЯ КНОПКА СЛЕВА */}
<div className="space-y-4">
<h3 className="text-lg font-semibold text-white">🌟 Вариант 1: Плавающая кнопка слева</h3>
<div className="bg-white/5 rounded-lg p-6 border border-white/10">
<div className="flex gap-4 h-48">
{/* Sidebar Mock */}
<div className="w-60 bg-white/5 backdrop-blur-xl border border-white/10 rounded-2xl p-4 flex flex-col">
<div className="flex items-center gap-3 mb-6">
<div className="w-8 h-8 bg-purple-500 rounded-full"></div>
<span className="text-sm text-white">Rennel</span>
</div>
<div className="space-y-2">
<div className="text-sm text-white/60">Главная</div>
<div className="text-sm text-white/60">Маркет</div>
<div className="text-sm text-white/60">Мессенджер</div>
</div>
</div>
{/* Floating Back Button */}
<div className="relative">
<button 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">
<ArrowLeft className="h-4 w-4 text-white/70 group-hover:text-white group-hover:h-5 group-hover:w-5 transition-all" />
</button>
</div>
{/* Block 1 Mock */}
<div className="flex-1 bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl p-4">
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<Building2 className="h-5 w-5 text-blue-400" />
<h2 className="text-lg font-semibold text-white">Поставщики</h2>
</div>
<div className="w-64 bg-white/10 border border-white/20 rounded-full px-3 py-1.5 text-sm">
<span className="text-white/60">Поиск поставщиков...</span>
</div>
</div>
</div>
</div>
</div>
</div>
{/* ВАРИАНТ 2: ПОЛОСА НАВИГАЦИИ СВЕРХУ */}
<div className="space-y-4">
<h3 className="text-lg font-semibold text-white">📍 Вариант 2: Полоса навигации сверху</h3>
<div className="bg-white/5 rounded-lg p-6 border border-white/10">
<div className="flex gap-4">
{/* Sidebar Mock */}
<div className="w-60 bg-white/5 backdrop-blur-xl border border-white/10 rounded-2xl p-4 flex flex-col h-48">
<div className="flex items-center gap-3 mb-6">
<div className="w-8 h-8 bg-purple-500 rounded-full"></div>
<span className="text-sm text-white">Rennel</span>
</div>
<div className="space-y-2">
<div className="text-sm text-white/60">Главная</div>
<div className="text-sm text-white/60">Маркет</div>
<div className="text-sm text-white/60">Мессенджер</div>
</div>
</div>
{/* Content Area */}
<div className="flex-1">
{/* Navigation Bar */}
<div className="flex items-center justify-start mb-4">
<button className="w-6 h-6 hover:w-8 hover:h-8 bg-gradient-to-r from-purple-500/20 to-blue-500/20 hover:from-purple-500/40 hover:to-blue-500/40 rounded-full flex items-center justify-center transition-all duration-300 backdrop-blur-sm border border-white/10 hover:border-white/30 group">
<ArrowLeft className="h-3 w-3 group-hover:h-4 group-hover:w-4 text-white/60 group-hover:text-white transition-all" />
</button>
</div>
{/* Block 1 Mock */}
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl p-4 h-[180px]">
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<Building2 className="h-5 w-5 text-blue-400" />
<h2 className="text-lg font-semibold text-white">Поставщики</h2>
</div>
<div className="w-64 bg-white/10 border border-white/20 rounded-full px-3 py-1.5 text-sm">
<span className="text-white/60">Поиск поставщиков...</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{/* ВАРИАНТ 3: КНОПКА В РАЗРЫВЕ */}
<div className="space-y-4">
<h3 className="text-lg font-semibold text-white">🎯 Вариант 3: Кнопка в разрыве</h3>
<div className="bg-white/5 rounded-lg p-6 border border-white/10">
<div className="flex gap-4 h-48 relative">
{/* Sidebar Mock */}
<div className="w-60 bg-white/5 backdrop-blur-xl border border-white/10 rounded-2xl p-4 flex flex-col">
<div className="flex items-center gap-3 mb-6">
<div className="w-8 h-8 bg-purple-500 rounded-full"></div>
<span className="text-sm text-white">Rennel</span>
</div>
<div className="space-y-2">
<div className="text-sm text-white/60">Главная</div>
<div className="text-sm text-white/60">Маркет</div>
<div className="text-sm text-white/60">Мессенджер</div>
</div>
</div>
{/* Button in Gap */}
<div className="w-0 flex items-center justify-center relative">
<button className="absolute w-10 h-10 bg-white/5 hover:bg-white/15 rounded-xl border border-white/10 hover:border-purple-400/50 flex items-center justify-center transition-all duration-500 hover:scale-125 hover:rotate-12 group backdrop-blur-md">
<ArrowLeft className="h-4 w-4 text-white/50 group-hover:text-purple-300 transition-colors" />
</button>
</div>
{/* Block 1 Mock */}
<div className="flex-1 bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl p-4">
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<Building2 className="h-5 w-5 text-blue-400" />
<h2 className="text-lg font-semibold text-white">Поставщики</h2>
</div>
<div className="w-64 bg-white/10 border border-white/20 rounded-full px-3 py-1.5 text-sm">
<span className="text-white/60">Поиск поставщиков...</span>
</div>
</div>
</div>
</div>
</div>
</div>
{/* ВАРИАНТ 4: BREADCRUMB СТИЛЬ */}
<div className="space-y-4">
<h3 className="text-lg font-semibold text-white">🍞 Вариант 4: Breadcrumb стиль</h3>
<div className="bg-white/5 rounded-lg p-6 border border-white/10">
<div className="flex gap-4">
{/* Sidebar Mock */}
<div className="w-60 bg-white/5 backdrop-blur-xl border border-white/10 rounded-2xl p-4 flex flex-col h-48">
<div className="flex items-center gap-3 mb-6">
<div className="w-8 h-8 bg-purple-500 rounded-full"></div>
<span className="text-sm text-white">Rennel</span>
</div>
<div className="space-y-2">
<div className="text-sm text-white/60">Главная</div>
<div className="text-sm text-white/60">Маркет</div>
<div className="text-sm text-white/60">Мессенджер</div>
</div>
</div>
{/* Content Area */}
<div className="flex-1">
{/* Breadcrumb */}
<div className="flex items-center gap-2 mb-2 pl-2">
<button className="p-1 hover:p-2 bg-white/0 hover:bg-white/10 rounded-lg transition-all duration-300 group">
<ArrowLeft className="h-3 w-3 group-hover:h-4 group-hover:w-4 text-white/40 group-hover:text-white transition-all" />
</button>
<span className="text-white/20 text-sm"></span>
<span className="text-white/60 text-sm">Поставщики</span>
</div>
{/* Block 1 Mock */}
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl p-4 h-[180px]">
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<Building2 className="h-5 w-5 text-blue-400" />
<h2 className="text-lg font-semibold text-white">Поставщики</h2>
</div>
<div className="w-64 bg-white/10 border border-white/20 rounded-full px-3 py-1.5 text-sm">
<span className="text-white/60">Поиск поставщиков...</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{/* ВАРИАНТ 5: ВЕРТИКАЛЬНАЯ ПАНЕЛЬ */}
<div className="space-y-4">
<h3 className="text-lg font-semibold text-white">🔥 Вариант 5: Вертикальная панель</h3>
<div className="bg-white/5 rounded-lg p-6 border border-white/10">
<div className="flex gap-4 h-48">
{/* Sidebar Mock */}
<div className="w-60 bg-white/5 backdrop-blur-xl border border-white/10 rounded-2xl p-4 flex flex-col">
<div className="flex items-center gap-3 mb-6">
<div className="w-8 h-8 bg-purple-500 rounded-full"></div>
<span className="text-sm text-white">Rennel</span>
</div>
<div className="space-y-2">
<div className="text-sm text-white/60">Главная</div>
<div className="text-sm text-white/60">Маркет</div>
<div className="text-sm text-white/60">Мессенджер</div>
</div>
</div>
{/* Vertical Panel */}
<div className="w-8 flex flex-col items-center py-4">
<button className="w-6 h-6 hover:w-7 hover:h-7 bg-gradient-to-b from-purple-500/10 to-transparent hover:from-purple-500/30 hover:to-purple-400/10 rounded-full flex items-center justify-center transition-all duration-300 hover:shadow-lg hover:shadow-purple-500/20 group">
<ArrowLeft className="h-3 w-3 group-hover:h-4 group-hover:w-4 text-white/50 group-hover:text-purple-300 transition-all duration-300" />
</button>
</div>
{/* Block 1 Mock */}
<div className="flex-1 bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl p-4">
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<Building2 className="h-5 w-5 text-blue-400" />
<h2 className="text-lg font-semibold text-white">Поставщики</h2>
</div>
<div className="w-64 bg-white/10 border border-white/20 rounded-full px-3 py-1.5 text-sm">
<span className="text-white/60">Поиск поставщиков...</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="text-center text-white/60 mt-8 p-4 bg-white/5 rounded-lg border border-white/10">
<p>Наведите курсор на кнопки для просмотра hover эффектов</p>
</div>
</div>
)
}

View File

@ -1,16 +1,7 @@
'use client' 'use client'
import { useQuery, useMutation } from '@apollo/client' import { useQuery, useMutation } from '@apollo/client'
import { import { ArrowLeft, Building2, Search, Package, Plus, Minus, ShoppingCart, Wrench } from 'lucide-react'
ArrowLeft,
Building2,
Search,
Package,
Plus,
Minus,
ShoppingCart,
Wrench,
} from 'lucide-react'
import Image from 'next/image' import Image from 'next/image'
import { useRouter } from 'next/navigation' import { useRouter } from 'next/navigation'
import React, { useState } from 'react' import React, { useState } from 'react'
@ -131,7 +122,6 @@ export function CreateConsumablesSupplyPage() {
}).format(amount) }).format(amount)
} }
const updateConsumableQuantity = (productId: string, quantity: number) => { const updateConsumableQuantity = (productId: string, quantity: number) => {
const product = supplierProducts.find((p: ConsumableProduct) => p.id === productId) const product = supplierProducts.find((p: ConsumableProduct) => p.id === productId)
if (!product || !selectedSupplier) return if (!product || !selectedSupplier) return
@ -358,12 +348,8 @@ export function CreateConsumablesSupplyPage() {
<Sidebar /> <Sidebar />
<main className={`flex-1 ${getSidebarMargin()} overflow-auto transition-all duration-300 p-4`}> <main className={`flex-1 ${getSidebarMargin()} overflow-auto transition-all duration-300 p-4`}>
<div className="min-h-full w-full flex flex-col gap-4"> <div className="min-h-full w-full flex flex-col gap-4">
{/* Заголовок */} {/* Кнопка назад без заголовка */}
<div className="flex items-center justify-between flex-shrink-0"> <div className="flex items-center justify-end flex-shrink-0">
<div>
<h1 className="text-xl font-bold text-white mb-1">Создание поставки расходников</h1>
<p className="text-white/60 text-sm">Выберите поставщика и добавьте расходники в заказ</p>
</div>
<Button <Button
variant="ghost" variant="ghost"
size="sm" size="sm"
@ -429,10 +415,13 @@ export function CreateConsumablesSupplyPage() {
{filteredSuppliers.slice(0, 7).map((supplier: ConsumableSupplier, index) => ( {filteredSuppliers.slice(0, 7).map((supplier: ConsumableSupplier, index) => (
<Card <Card
key={supplier.id} key={supplier.id}
className={`relative cursor-pointer transition-all duration-300 border flex-shrink-0 rounded-xl overflow-hidden group ${ className={`relative cursor-pointer transition-all duration-300 border
flex-shrink-0 rounded-xl overflow-hidden group ${
selectedSupplier?.id === supplier.id selectedSupplier?.id === supplier.id
? 'bg-gradient-to-br from-orange-500/30 via-orange-400/20 to-orange-500/30 border-orange-400/60 shadow-lg shadow-orange-500/25' ? 'bg-gradient-to-br from-orange-500/30 via-orange-400/20 to-orange-500/30 ' +
: 'bg-gradient-to-br from-white/10 via-white/5 to-white/10 border-white/20 hover:from-white/20 hover:via-white/10 hover:to-white/20 hover:border-white/40' 'border-orange-400/60 shadow-lg shadow-orange-500/25'
: 'bg-gradient-to-br from-white/10 via-white/5 to-white/10 border-white/20 ' +
'hover:from-white/20 hover:via-white/10 hover:to-white/20 hover:border-white/40'
}`} }`}
style={{ style={{
width: 'calc((100% - 48px) / 7)', // 48px = 6 gaps * 8px each width: 'calc((100% - 48px) / 7)', // 48px = 6 gaps * 8px each
@ -545,10 +534,14 @@ export function CreateConsumablesSupplyPage() {
return ( return (
<Card <Card
key={product.id} key={product.id}
className={`relative bg-gradient-to-br from-white/10 via-white/5 to-white/10 backdrop-blur border border-white/20 p-3 rounded-xl overflow-hidden group hover:shadow-xl transition-all duration-300 ${ className={`relative bg-gradient-to-br from-white/10 via-white/5
to-white/10 backdrop-blur border border-white/20 p-3 rounded-xl
overflow-hidden group hover:shadow-xl transition-all duration-300 ${
selectedQuantity > 0 selectedQuantity > 0
? 'ring-2 ring-green-400/50 bg-gradient-to-br from-green-500/20 via-green-400/10 to-green-500/20' ? 'ring-2 ring-green-400/50 bg-gradient-to-br from-green-500/20 ' +
: 'hover:from-white/20 hover:via-white/10 hover:to-white/20 hover:border-white/40' 'via-green-400/10 to-green-500/20'
: 'hover:from-white/20 hover:via-white/10 hover:to-white/20 ' +
'hover:border-white/40'
}`} }`}
style={{ style={{
animationDelay: `${index * 50}ms`, animationDelay: `${index * 50}ms`,

View File

@ -241,20 +241,26 @@ flex flex-wrap gap-4
**КРИТИЧЕСКИ ВАЖНО**: Все вкладки раздела "Партнеры" должны иметь единую структуру: **КРИТИЧЕСКИ ВАЖНО**: Все вкладки раздела "Партнеры" должны иметь единую структуру:
#### Обязательные принципы: #### Обязательные принципы:
- **Блоки статистики**: `grid grid-cols-4 gap-3` с отдельными `glass-card` - **Блоки статистики**: `grid grid-cols-4 gap-3` с отдельными `glass-card`
- **ЗАПРЕЩЕНО**: Дополнительные обертки `glass-card` в TabsContent - **ЗАПРЕЩЕНО**: Дополнительные обертки `glass-card` в TabsContent
- **Цвета ссылок**: желтая схема (`bg-yellow-500/20`) - **Цвета ссылок**: желтая схема (`bg-yellow-500/20`)
- **Табличный формат**: вместо карточного grid-layout - **Табличный формат**: вместо карточного grid-layout
#### Структура блоков статистики: #### Структура блоков статистики:
```tsx ```tsx
{/* ПРАВИЛЬНО */} {
<div className="grid grid-cols-4 gap-3"> /* ПРАВИЛЬНО */
}
;<div className="grid grid-cols-4 gap-3">
<Card className="glass-card p-3">...</Card> <Card className="glass-card p-3">...</Card>
</div> </div>
{/* ЗАПРЕЩЕНО */} {
<Card className="glass-card"> /* ЗАПРЕЩЕНО */
}
;<Card className="glass-card">
<div className="grid...">...</div> <div className="grid...">...</div>
</Card> </Card>
``` ```
@ -556,9 +562,7 @@ text-white/50 /* Приглушенный текст */
<main className={`flex-1 ${getSidebarMargin()} overflow-hidden transition-all duration-300`}> <main className={`flex-1 ${getSidebarMargin()} overflow-hidden transition-all duration-300`}>
<div className="h-full flex flex-col"> <div className="h-full flex flex-col">
{/* Блоки занимают всю доступную область */} {/* Блоки занимают всю доступную область */}
<div className="flex-1 flex gap-2 min-h-0"> <div className="flex-1 flex gap-2 min-h-0">{/* Блоки без внешних отступов */}</div>
{/* Блоки без внешних отступов */}
</div>
</div> </div>
</main> </main>
</div> </div>
@ -669,11 +673,7 @@ text-white/50 /* Приглушенный текст */
### 13.2 Интерактивная кнопка ### 13.2 Интерактивная кнопка
```tsx ```tsx
<Button <Button variant="glass" className="hover:scale-105 transition-transform" onClick={handleClick}>
variant="glass"
className="hover:scale-105 transition-transform"
onClick={handleClick}
>
<Icon className="h-4 w-4 mr-2" /> <Icon className="h-4 w-4 mr-2" />
Действие Действие
</Button> </Button>
@ -684,10 +684,7 @@ text-white/50 /* Приглушенный текст */
```tsx ```tsx
<div className="space-y-2"> <div className="space-y-2">
<Label className="text-white/90">Поле ввода</Label> <Label className="text-white/90">Поле ввода</Label>
<Input <Input className="glass-input text-white placeholder:text-white/50" placeholder="Введите значение..." />
className="glass-input text-white placeholder:text-white/50"
placeholder="Введите значение..."
/>
{error && <p className="text-red-300 text-xs">{error}</p>} {error && <p className="text-red-300 text-xs">{error}</p>}
</div> </div>
``` ```
@ -697,7 +694,7 @@ text-white/50 /* Приглушенный текст */
```tsx ```tsx
// ✅ ПРАВИЛЬНАЯ структура страницы с сайдбаром // ✅ ПРАВИЛЬНАЯ структура страницы с сайдбаром
function PageWithSidebar() { function PageWithSidebar() {
const { getSidebarMargin } = useSidebar(); const { getSidebarMargin } = useSidebar()
return ( return (
<div className="h-screen flex overflow-hidden"> <div className="h-screen flex overflow-hidden">
@ -725,7 +722,7 @@ function PageWithSidebar() {
</div> </div>
</main> </main>
</div> </div>
); )
} }
``` ```
@ -875,25 +872,25 @@ const productCreationSteps = [
{ id: 'planning', label: 'Планирование работы', status: 'active' }, { id: 'planning', label: 'Планирование работы', status: 'active' },
{ id: 'processing', label: 'Обработка товара', status: 'pending' }, { id: 'processing', label: 'Обработка товара', status: 'pending' },
{ id: 'quality', label: 'Контроль качества', status: 'pending' }, { id: 'quality', label: 'Контроль качества', status: 'pending' },
{ id: 'completion', label: 'Завершение', status: 'pending' } { id: 'completion', label: 'Завершение', status: 'pending' },
]; ]
// Визуальный компонент // Визуальный компонент
<div className="flex items-center justify-between mb-6"> ;<div className="flex items-center justify-between mb-6">
{productCreationSteps.map((step, index) => ( {productCreationSteps.map((step, index) => (
<div key={step.id} className="flex items-center"> <div key={step.id} className="flex items-center">
<div className={` <div
className={`
flex items-center justify-center w-10 h-10 rounded-full border-2 text-sm font-semibold flex items-center justify-center w-10 h-10 rounded-full border-2 text-sm font-semibold
${step.status === 'completed' ? 'bg-green-500 border-green-500 text-white' : ''} ${step.status === 'completed' ? 'bg-green-500 border-green-500 text-white' : ''}
${step.status === 'active' ? 'bg-blue-500 border-blue-500 text-white animate-pulse' : ''} ${step.status === 'active' ? 'bg-blue-500 border-blue-500 text-white animate-pulse' : ''}
${step.status === 'pending' ? 'bg-white/10 border-white/30 text-white/50' : ''} ${step.status === 'pending' ? 'bg-white/10 border-white/30 text-white/50' : ''}
`}> `}
>
{step.status === 'completed' ? '✓' : index + 1} {step.status === 'completed' ? '✓' : index + 1}
</div> </div>
<span className="ml-2 text-sm text-white/70">{step.label}</span> <span className="ml-2 text-sm text-white/70">{step.label}</span>
{index < productCreationSteps.length - 1 && ( {index < productCreationSteps.length - 1 && <div className="w-12 h-0.5 bg-white/20 mx-4"></div>}
<div className="w-12 h-0.5 bg-white/20 mx-4"></div>
)}
</div> </div>
))} ))}
</div> </div>
@ -907,25 +904,25 @@ const productCreationSteps = [
/* WHOLESALE - поставщики */ /* WHOLESALE - поставщики */
.partner-wholesale { .partner-wholesale {
@apply bg-emerald-500/20 border-emerald-400; @apply bg-emerald-500/20 border-emerald-400;
--icon: "🏭"; /* factory */ --icon: '🏭'; /* factory */
} }
/* SELLER - селлеры */ /* SELLER - селлеры */
.partner-seller { .partner-seller {
@apply bg-blue-500/20 border-blue-400; @apply bg-blue-500/20 border-blue-400;
--icon: "🛍️"; /* shopping */ --icon: '🛍️'; /* shopping */
} }
/* FULFILLMENT - фулфилмент центры */ /* FULFILLMENT - фулфилмент центры */
.partner-fulfillment { .partner-fulfillment {
@apply bg-purple-500/20 border-purple-400; @apply bg-purple-500/20 border-purple-400;
--icon: "📦"; /* package */ --icon: '📦'; /* package */
} }
/* LOGIST - логистические компании */ /* LOGIST - логистические компании */
.partner-logist { .partner-logist {
@apply bg-orange-500/20 border-orange-400; @apply bg-orange-500/20 border-orange-400;
--icon: "🚚"; /* truck */ --icon: '🚚'; /* truck */
} }
``` ```
@ -974,38 +971,42 @@ export function SuppliesPage() {
#### 14.5.2 Контекстная статистика по табам #### 14.5.2 Контекстная статистика по табам
**Для пути "Фулфилмент → Товар → Карточки/Поставщики":** **Для пути "Фулфилмент → Товар → Карточки/Поставщики":**
```tsx ```tsx
const suppliesStats = [ const suppliesStats = [
{ label: "Всего поставок", value: "24", color: "text-blue-400" }, { label: 'Всего поставок', value: '24', color: 'text-blue-400' },
{ label: "Активных поставок", value: "8", color: "text-green-400" }, { label: 'Активных поставок', value: '8', color: 'text-green-400' },
{ label: "Сумма активных поставок", value: "₽142,350", color: "text-yellow-400" }, { label: 'Сумма активных поставок', value: '₽142,350', color: 'text-yellow-400' },
{ label: "В пути", value: "3", color: "text-purple-400" } { label: 'В пути', value: '3', color: 'text-purple-400' },
]; ]
``` ```
**Для пути "Фулфилмент → Расходники селлера":** **Для пути "Фулфилмент → Расходники селлера":**
```tsx ```tsx
const consumablesStats = [ const consumablesStats = [
{ label: "Всего поставок", value: "12", color: "text-blue-400" }, { label: 'Всего поставок', value: '12', color: 'text-blue-400' },
{ label: "Активных поставок", value: "4", color: "text-green-400" }, { label: 'Активных поставок', value: '4', color: 'text-green-400' },
{ label: "Видов расходников", value: "18", color: "text-orange-400" }, { label: 'Видов расходников', value: '18', color: 'text-orange-400' },
{ label: "Критические остатки", value: "2", color: "text-red-400" } { label: 'Критические остатки', value: '2', color: 'text-red-400' },
]; ]
``` ```
**Для путей "Маркетплейсы → Wildberries/Ozon":** **Для путей "Маркетплейсы → Wildberries/Ozon":**
```tsx ```tsx
const marketplaceStats = [ const marketplaceStats = [
{ label: "Поставок на маркетплейс", value: "15", color: "text-blue-400" }, { label: 'Поставок на маркетплейс', value: '15', color: 'text-blue-400' },
{ label: "Товаров отправлено", value: "347", color: "text-green-400" }, { label: 'Товаров отправлено', value: '347', color: 'text-green-400' },
{ label: "Возвраты за неделю", value: "12", color: "text-yellow-400" }, { label: 'Возвраты за неделю', value: '12', color: 'text-yellow-400' },
{ label: "Эффективность поставок", value: "94%", color: "text-emerald-400" } { label: 'Эффективность поставок', value: '94%', color: 'text-emerald-400' },
]; ]
``` ```
#### 14.5.3 Система создания поставок #### 14.5.3 Система создания поставок
**Выбор типа поставки:** **Выбор типа поставки:**
```tsx ```tsx
const supplyTypes = [ const supplyTypes = [
{ {
@ -1013,23 +1014,25 @@ const supplyTypes = [
title: 'Карточки товаров', title: 'Карточки товаров',
description: 'Импорт через WB API с автосозданием поставки', description: 'Импорт через WB API с автосозданием поставки',
icon: '📱', icon: '📱',
color: 'bg-blue-500/20 border-blue-400' color: 'bg-blue-500/20 border-blue-400',
}, },
{ {
id: 'goods-suppliers', id: 'goods-suppliers',
title: 'Поставщики товаров', title: 'Поставщики товаров',
description: 'Прямой заказ с указанием рецептуры', description: 'Прямой заказ с указанием рецептуры',
icon: '🏭', icon: '🏭',
color: 'bg-emerald-500/20 border-emerald-400' color: 'bg-emerald-500/20 border-emerald-400',
}, },
{ {
id: 'consumables', id: 'consumables',
title: 'Расходники селлера', title: 'Расходники селлера',
description: 'Материалы для производства', description: 'Материалы для производства',
icon: '🔧', icon: '🔧',
color: 'bg-purple-500/20 border-purple-400' color: 'bg-purple-500/20 border-purple-400',
} // ВАЖНО: На странице /supplies/create-consumables НЕ отображается заголовок и описание
]; pageHeader: false,
},
]
``` ```
#### 14.5.4 Интерфейс рецептуры продукта #### 14.5.4 Интерфейс рецептуры продукта
@ -1068,30 +1071,31 @@ const supplyTypes = [
#### 14.5.5 WB интеграция - визуальные индикаторы #### 14.5.5 WB интеграция - визуальные индикаторы
**Статусы синхронизации с WB API:** **Статусы синхронизации с WB API:**
```css ```css
/* Успешная синхронизация */ /* Успешная синхронизация */
.wb-sync-success { .wb-sync-success {
@apply bg-green-500/20 border-green-400 text-green-100; @apply bg-green-500/20 border-green-400 text-green-100;
--status-icon: "✅"; --status-icon: '✅';
} }
/* Ошибка синхронизации */ /* Ошибка синхронизации */
.wb-sync-error { .wb-sync-error {
@apply bg-red-500/20 border-red-400 text-red-100; @apply bg-red-500/20 border-red-400 text-red-100;
--status-icon: "❌"; --status-icon: '❌';
} }
/* В процессе синхронизации */ /* В процессе синхронизации */
.wb-sync-loading { .wb-sync-loading {
@apply bg-yellow-500/20 border-yellow-400 text-yellow-100; @apply bg-yellow-500/20 border-yellow-400 text-yellow-100;
--status-icon: "⏳"; --status-icon: '⏳';
animation: pulse 2s infinite; animation: pulse 2s infinite;
} }
/* Не настроена */ /* Не настроена */
.wb-sync-none { .wb-sync-none {
@apply bg-gray-500/20 border-gray-400 text-gray-100; @apply bg-gray-500/20 border-gray-400 text-gray-100;
--status-icon: "⚠️"; --status-icon: '⚠️';
} }
``` ```
@ -1102,6 +1106,7 @@ const supplyTypes = [
**📅 ДАТА**: 2025, полная синхронизация с техническими требованиями **📅 ДАТА**: 2025, полная синхронизация с техническими требованиями
### 🆕 ДОБАВЛЕНИЯ v1.2: ### 🆕 ДОБАВЛЕНИЯ v1.2:
- ✅ Детальные правила для кабинета селлера (раздел 14.5) - ✅ Детальные правила для кабинета селлера (раздел 14.5)
- ✅ Трёхблочная архитектура страницы "Мои поставки" - ✅ Трёхблочная архитектура страницы "Мои поставки"
- ✅ Контекстная статистика по типам поставок - ✅ Контекстная статистика по типам поставок