diff --git a/interaction-integrity-rules.md b/interaction-integrity-rules.md index 57669ac..6c68295 100644 --- a/interaction-integrity-rules.md +++ b/interaction-integrity-rules.md @@ -139,6 +139,52 @@ ignores: ['diagnostic-script.js', 'legacy-config.js'] // конкретные ф - Планирую создать новые файлы вместо редактирования существующих ``` +### 1.5 🎯 ПРАВИЛА АНАЛИЗА ИСХОДНЫХ ПРИМЕРОВ + +**КРИТИЧЕСКИ ВАЖНО**: При работе с существующими примерами кода или UI Kit компонентами: + +#### 🔍 **ОБЯЗАТЕЛЬНЫЙ ТРЕХУРОВНЕВЫЙ АНАЛИЗ:** + +1. **📋 СОДЕРЖАТЕЛЬНЫЙ АНАЛИЗ** (что делает код): + - Функциональность компонента + - Логика работы + - Данные и состояния + +2. **🏗️ АРХИТЕКТУРНЫЙ АНАЛИЗ** (как организован код): + - Структура компонентов и контейнеров + - Взаимосвязи между элементами + - Позиционирование и layout + - Иерархия DOM-элементов + +3. **🎨 СТИЛЕВОЙ АНАЛИЗ** (как выглядит код): + - CSS классы и стили + - Анимации и переходы + - Цвета и размеры + +#### ❌ **ТИПИЧНЫЕ ОШИБКИ АНАЛИЗА:** + +- **Поверхностный анализ**: Копирование только стилей без понимания архитектуры +- **Игнорирование контекста**: Непонимание места элемента в общей структуре +- **Буквальное копирование**: Применение решения без адаптации к текущей задаче + +#### ✅ **ПРАВИЛЬНЫЙ ПОДХОД:** + +``` +🔬 АЛГОРИТМ АНАЛИЗА ПРИМЕРА: +1. Прочитать ВЕСЬ код компонента-примера +2. Понять АРХИТЕКТУРУ: где элемент размещен относительно других +3. Понять ЛОГИКУ: почему именно так структурировано +4. Адаптировать к ТЕКУЩЕЙ ЗАДАЧЕ: применить принципы, а не просто скопировать +5. Проверить СООТВЕТСТВИЕ правилам проекта +``` + +#### 🚨 **СТОП-ВОПРОСЫ ПЕРЕД РЕАЛИЗАЦИЕЙ:** + +- "Понимаю ли я **архитектуру** этого решения?" +- "Где именно должен располагаться элемент в **общей структуре**?" +- "Какова **семантическая роль** этого элемента?" +- "Как это решение **адаптируется** к моей текущей задаче?" + --- ## 🔄 II. ПРОЦЕДУРНЫЙ УРОВЕНЬ: ПОСЛЕДОВАТЕЛЬНОСТИ ДЕЙСТВИЙ @@ -563,9 +609,69 @@ ignores: ['diagnostic-script.js', 'legacy-config.js'] // конкретные ф --- +## 📚 VIII. ИЗВЛЕЧЕННЫЕ УРОКИ И АНТИ-ПАТТЕРНЫ + +### 8.1 🚨 КРИТИЧЕСКИЕ ОШИБКИ В АНАЛИЗЕ UI КОМПОНЕНТОВ + +#### **CASE STUDY: Ошибка с плавающей кнопкой из UI Kit** + +**❌ ОШИБКА**: При добавлении кнопки "🌟 Вариант 1: Плавающая кнопка слева" из UI Kit: + +1. **Поверхностный анализ**: Скопировал только стили кнопки +2. **Игнорирование архитектуры**: Не заметил, что кнопка в **отдельном контейнере** +3. **Неправильное размещение**: Добавил как часть блока контента +4. **Непонимание термина**: "Плавающая" = независимая от контента, между элементами + +**✅ ПРАВИЛЬНОЕ РЕШЕНИЕ**: + +```tsx +// ❌ НЕПРАВИЛЬНО - кнопка внутри блока контента +
+ +
...
+
+ +// ✅ ПРАВИЛЬНО - кнопка в отдельном контейнере +
+ +
{/* Отдельный контейнер */} + +
+
...
+
+``` + +#### **📋 ОБЯЗАТЕЛЬНЫЙ ЧЕКЛИСТ ДЛЯ UI KIT КОМПОНЕНТОВ:** + +``` +🔍 ПЕРЕД РЕАЛИЗАЦИЕЙ: +□ Прочитал ВЕСЬ код компонента-примера +□ Понял архитектуру размещения в layout +□ Определил семантическую роль элемента +□ Понял взаимосвязи с соседними элементами +□ Адаптировал принципы к текущей задаче +□ Проверил соответствие правилам проекта +``` + +#### **⚡ АНТИ-ПАТТЕРНЫ:** + +- **"Быстрое копирование"** - копировать стили без понимания архитектуры +- **"Частичный анализ"** - читать только нужную часть кода +- **"Буквальное применение"** - использовать без адаптации к контексту +- **"Игнорирование контейнеров"** - не обращать внимание на DOM-структуру + +#### **✅ ПРАВИЛЬНЫЕ ПАТТЕРНЫ:** + +- **"Архитектурный анализ первым"** - понять структуру, потом стили +- **"Контекстная адаптация"** - применять принципы, а не код буквально +- **"Семантическое понимание"** - осознавать роль каждого элемента +- **"Итеративная проверка"** - сверяться с примером на каждом шаге + +--- + **Дата создания**: Декабрь 2024 **Последнее обновление**: Август 2025 -**Версия**: 3.0 - ПОЛНАЯ РЕСТРУКТУРИЗАЦИЯ +**Версия**: 3.1 - ДОПОЛНЕНЫ ПРАВИЛА АНАЛИЗА UI KIT **Статус**: АКТИВЕН - ОБЯЗАТЕЛЕН К ИСПОЛНЕНИЮ **Связанные файлы**: diff --git a/rules-complete.md b/rules-complete.md index e70a373..0a82e65 100644 --- a/rules-complete.md +++ b/rules-complete.md @@ -854,7 +854,8 @@ const handleSuppliesClick = () => { **БЛОК 1: ПОСТАВЩИКИ** _(адаптивная сетка)_ -- **Заголовок**: Минималистичный "🏢 Поставщики" без лишних элементов +- **Навигация**: Плавающая кнопка "Назад" между сайдбаром и контентом (см. детали в seller-ui-rules.md) +- **Заголовок**: БЕЗ заголовка - блок начинается сразу с функционального контента - **Поиск**: Компактное поле справа "Поиск поставщиков..." (w-64) - **Отображение**: Карточки поставщиков из раздела "Партнеры" в адаптивной сетке - **Выбор**: Клик выделяет карточку поставщика @@ -1780,6 +1781,8 @@ height: calc(100vh - headerHeight - tabsHeight - statsHeight - margins); **БЛОК 1: ПОСТАВЩИКИ** _(обязательный, 180px)_: +- **Навигация**: Плавающая кнопка "Назад" между сайдбаром и контентом (см. seller-ui-rules.md) +- **БЕЗ заголовка** - блок начинается сразу с поиска и карточек - Карточки поставщиков из раздела "Партнеры" - Горизонтальный скролл при превышении ширины - Выбор только одного поставщика одновременно diff --git a/seller-ui-rules.md b/seller-ui-rules.md index 05a8439..a0587f3 100644 --- a/seller-ui-rules.md +++ b/seller-ui-rules.md @@ -17,7 +17,7 @@ **СЕЛЛЕР (`SELLER`)** имеет доступ к следующим разделам: - **Мои поставки** (`/my-supplies`) - управление поставками -- **Маркет** (`/market`) - просмотр глобального каталога +- **Маркет** (`/market`) - просмотр глобального каталога - **Партнеры** (`/partners`) - управление контрагентами - **Мессенджер** (`/messenger`) - связь с партнерами - **Настройки** (`/settings`) - профиль и настройки @@ -56,11 +56,48 @@ switch (user?.organization?.type) { ### 2.2 Детальные правила горизонтального скролла поставщиков -**СТРУКТУРА И ОТОБРАЖЕНИЕ:** +**КНОПКА НАВИГАЦИИ "НАЗАД":** +**Архитектура размещения:** + +- **Расположение**: Между сайдбаром и основным контентом +- **Контейнер**: Отдельный `
` +- **НЕ является частью блока 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, включает заголовок + контейнер скролла +- **Блок поставщиков**: Общая высота 180px - **Направление**: Слева направо (LTR) - **Поведение**: Плавный скролл с автоскрытием полосы прокрутки @@ -382,6 +419,8 @@ height: calc(100vh - headerHeight - tabsHeight - statsHeight - margins); **БЛОК 1: ПОСТАВЩИКИ** _(обязательный, 180px)_: +- БЕЗ заголовка - сразу функциональный контент +- Кнопка навигации "Назад" - между сайдбаром и блоком (см. раздел 2.2) - Карточки поставщиков из раздела "Партнеры" - Горизонтальный скролл при превышении ширины - Выбор только одного поставщика одновременно @@ -448,6 +487,7 @@ height: calc(100vh - headerHeight - tabsHeight - statsHeight - margins); ### 3.1 React компоненты селлера **Основные компоненты:** + - `SellerHomePage` - главная страница селлера (4 типо-зависимых компонента) - `SellerEconomicsPage` - экономическая аналитика селлера @@ -497,4 +537,4 @@ query GetSellerCards { **Связанные файлы**: - [rules-complete.md](./rules-complete.md) - Общие бизнес-правила -- [visual-design-rules.md](./visual-design-rules.md) - Визуальные правила \ No newline at end of file +- [visual-design-rules.md](./visual-design-rules.md) - Визуальные правила diff --git a/src/components/ui/date-picker.tsx b/src/components/ui/date-picker.tsx index 84022d2..00973cc 100644 --- a/src/components/ui/date-picker.tsx +++ b/src/components/ui/date-picker.tsx @@ -19,7 +19,13 @@ interface DatePickerProps { disabled?: boolean } -export function DatePicker({ value, onChange, placeholder = 'Выберите дату', className, disabled }: DatePickerProps) { +export function DatePicker({ + value, + onChange, + placeholder: _placeholder = 'Выберите дату', + className, + disabled, +}: DatePickerProps) { const handleDateChange = (e: React.ChangeEvent) => { onChange?.(e.target.value) } @@ -32,7 +38,7 @@ export function DatePicker({ value, onChange, placeholder = 'Выберите д onChange={handleDateChange} disabled={disabled} className={cn( - 'flex h-9 w-full rounded-lg border border-white/10 bg-white/5 backdrop-blur px-3 py-1 text-sm text-white placeholder:text-white/50 focus:border-white/20 focus:outline-none focus:ring-1 focus:ring-white/20 disabled:cursor-not-allowed disabled:opacity-50', + 'flex h-9 w-full rounded-lg border border-white/10 bg-white/5 backdrop-blur px-3 py-1 text-sm text-white placeholder:text-white/50 hover:border-white/30 hover:bg-white/10 focus:border-purple-400/50 focus:outline-none focus:ring-2 focus:ring-purple-400/20 transition-all duration-200 disabled:cursor-not-allowed disabled:opacity-50', 'pr-8', // Place for calendar icon className, )} diff --git a/src/components/ui/glass-date-picker.tsx b/src/components/ui/glass-date-picker.tsx new file mode 100644 index 0000000..adc83ce --- /dev/null +++ b/src/components/ui/glass-date-picker.tsx @@ -0,0 +1,46 @@ +'use client' + +import { Calendar } from 'lucide-react' +import * as React from 'react' + +interface GlassDatePickerProps { + value?: string + onChange?: (date: string) => void + placeholder?: string + className?: string + disabled?: boolean +} + +export function GlassDatePicker({ + value, + onChange, + placeholder: _placeholder = 'дд.мм.гггг', + className = '', + disabled = false, +}: GlassDatePickerProps) { + const handleDateChange = (e: React.ChangeEvent) => { + onChange?.(e.target.value) + } + + return ( +
+ + +
+ ) +} diff --git a/src/components/ui/glass-select.tsx b/src/components/ui/glass-select.tsx new file mode 100644 index 0000000..8da7196 --- /dev/null +++ b/src/components/ui/glass-select.tsx @@ -0,0 +1,114 @@ +'use client' + +import React from 'react' + +interface GlassSelectOption { + value: string + label: string + disabled?: boolean +} + +interface GlassSelectProps { + value: string + onChange: (value: string) => void + placeholder?: string + options: GlassSelectOption[] + className?: string + size?: 'sm' | 'md' | 'lg' + disabled?: boolean +} + +export function GlassSelect({ + value, + onChange, + placeholder = 'Выберите вариант', + options, + className = '', + size = 'md', + disabled = false, +}: GlassSelectProps) { + const sizeClasses = { + sm: 'h-8 text-xs px-3', + md: 'h-9 text-sm px-3', + lg: 'h-11 text-base px-4', + } + + return ( + + ) +} + +// Дополнительный компонент для простого использования с children +interface GlassSelectSimpleProps { + value: string + onChange: (value: string) => void + placeholder?: string + children: React.ReactNode + className?: string + size?: 'sm' | 'md' | 'lg' + disabled?: boolean +} + +export function GlassSelectSimple({ + value, + onChange, + placeholder, + children, + className = '', + size = 'md', + disabled = false, +}: GlassSelectSimpleProps) { + const sizeClasses = { + sm: 'h-8 text-xs px-3', + md: 'h-9 text-sm px-3', + lg: 'h-11 text-base px-4', + } + + return ( + + ) +}