# UX ПАТТЕРНЫ И ПОЛЬЗОВАТЕЛЬСКИЕ СЦЕНАРИИ SFERA

## 🎯 ФИЛОСОФИЯ UX

SFERA использует **user-centered design** подход с акцентом на **интуитивность**, **эффективность** и **accessibility**. Система построена для 4 типов пользователей с разными потребностями и workflow.

### Основные принципы UX:

- **Minimal Cognitive Load** - минимум усилий для выполнения задач
- **Progressive Disclosure** - поэтапное раскрытие функциональности
- **Contextual Actions** - действия в контексте текущей задачи
- **Visual Hierarchy** - четкая иерархия важности элементов
- **Feedback Systems** - мгновенная обратная связь на действия

## 👥 ТИПЫ ПОЛЬЗОВАТЕЛЕЙ И ИХ ПОТРЕБНОСТИ

### 1. FULFILLMENT (Фулфилмент-центр)

**Основные задачи:**

- Управление сотрудниками и расписанием
- Контроль расходных материалов
- Обработка входящих поставок
- Статистика производительности

**Ключевые UX потребности:**

- Быстрый доступ к табелю сотрудников
- Мгновенные уведомления о новых поставках
- Визуальный контроль остатков расходников
- Дашборд с ключевыми метриками

### 2. SELLER (Селлер/Продавец)

**Основные задачи:**

- Поиск и заказ товаров поставщиков
- Управление корзиной и избранным
- Создание рецептур с расходниками
- Отслеживание статусов заказов

**Ключевые UX потребности:**

- Быстрый поиск товаров по каталогу
- Интуитивная корзина с автосохранением
- Простое создание рецептур
- Четкий tracking заказов

### 3. WHOLESALE (Поставщик)

**Основные задачи:**

- Управление каталогом товаров
- Обработка входящих заказов
- Контроль остатков и резервов
- Коммуникация с покупателями

**Ключевые UX потребности:**

- Быстрое добавление и редактирование товаров
- Batch операции для больших каталогов
- Уведомления о новых заказах
- Простое управление остатками

### 4. LOGIST (Логистическая компания)

**Основные задачи:**

- Управление маршрутами доставки
- Подтверждение логистических заказов
- Контроль грузоперевозок
- Ценообразование по объему

**Ключевые UX потребности:**

- Карта маршрутов и адресов
- Быстрое подтверждение заказов
- Калькулятор стоимости доставки
- Tracking статусов доставок

## 🔄 ОСНОВНЫЕ ПОЛЬЗОВАТЕЛЬСКИЕ СЦЕНАРИИ

### 📋 СЦЕНАРИЙ 1: Создание заказа поставки (Селлер)

#### Шаг 1: Поиск товаров

```
Пользователь: Селлер
Цель: Найти нужные товары для заказа
```

**UX Flow:**

1. **Вход в каталог** → Главная → "Каталог товаров"
2. **Поиск товаров** → Строка поиска + фильтры
3. **Просмотр карточек** → Grid с товарами + основная информация
4. **Детали товара** → Клик → модальное окно с полной информацией

**UX Паттерны:**

- **Faceted Search** - фильтры по категориям, ценам, поставщикам
- **Infinite Scroll** - подгрузка товаров при прокрутке
- **Quick Preview** - hover для быстрого просмотра
- **Breadcrumbs** - навигация по категориям

**UI Компоненты:**

```typescript
<SearchBar placeholder="Поиск товаров..." />
<FilterSidebar categories={categories} priceRange={priceRange} />
<ProductGrid>
  {products.map(product => (
    <ProductCard
      key={product.id}
      product={product}
      onAddToCart={addToCart}
      onAddToFavorites={addToFavorites}
    />
  ))}
</ProductGrid>
```

#### Шаг 2: Добавление в корзину

```
Пользователь: Селлер
Цель: Собрать корзину товаров для заказа
```

**UX Flow:**

1. **Выбор количества** → Input с валидацией доступных остатков
2. **Добавление в корзину** → Кнопка "Добавить" + анимация
3. **Toast уведомление** → "Товар добавлен в корзину"
4. **Обновление счетчика** → Badge на иконке корзины

**UX Паттерны:**

- **Progressive Enhancement** - количество товара без перезагрузки
- **Micro-interactions** - анимация добавления в корзину
- **Real-time Validation** - проверка доступного количества
- **Persistent State** - корзина сохраняется между сессиями

#### Шаг 3: Оформление заказа

```
Пользователь: Селлер
Цель: Создать заказ поставки с рецептурой
```

**UX Flow:**

1. **Переход в корзину** → Кнопка "Корзина" в header
2. **Проверка товаров** → Список с возможностью редактирования
3. **Выбор поставщика** → Dropdown с фильтрацией
4. **Создание рецептуры** → Выбор услуг фулфилмента
5. **Подтверждение заказа** → Финальная проверка + отправка

**UX Паттерны:**

- **Multi-step Form** - пошаговое оформление заказа
- **Form Validation** - валидация каждого шага
- **Summary Review** - финальная проверка перед отправкой
- **Progress Indicator** - показ текущего шага

### 📦 СЦЕНАРИЙ 2: Обработка поставки (Фулфилмент)

#### Шаг 1: Получение уведомления

```
Пользователь: Фулфилмент-центр
Цель: Узнать о новой входящей поставке
```

**UX Flow:**

1. **Push уведомление** → "Новая поставка от ООО Поставщик"
2. **Badge на навигации** → Счетчик непрочитанных поставок
3. **Переход к поставкам** → Клик на уведомление/меню

**UX Паттерны:**

- **Real-time Notifications** - мгновенные уведомления
- **Attention Management** - badges для привлечения внимания
- **Context Switching** - быстрый переход к релевантной задаче

#### Шаг 2: Назначение ответственного

```
Пользователь: Фулфилмент-центр
Цель: Назначить сотрудника для обработки поставки
```

**UX Flow:**

1. **Просмотр деталей поставки** → Карточка с полной информацией
2. **Выбор сотрудника** → Dropdown с доступными сотрудниками
3. **Подтверждение назначения** → Кнопка "Назначить"
4. **Обновление статуса** → Автоматическое изменение статуса

**UX Паттерны:**

- **Smart Defaults** - предложение подходящих сотрудников
- **Contextual Information** - показ загрузки сотрудников
- **Immediate Feedback** - мгновенное подтверждение действия

### 💬 СЦЕНАРИЙ 3: Коммуникация между организациями

#### Шаг 1: Отправка сообщения

```
Пользователь: Любой тип организации
Цель: Связаться с контрагентом
```

**UX Flow:**

1. **Выбор получателя** → Список контрагентов
2. **Создание сообщения** → Текст + вложения
3. **Отправка** → Кнопка отправки + статус доставки

**UX Паттерны:**

- **Rich Communication** - текст, голос, файлы, изображения
- **Real-time Status** - статусы отправки и прочтения
- **Message Threading** - группировка сообщений по диалогам

## 🎨 UX ПАТТЕРНЫ ПО КАТЕГОРИЯМ

### 📊 1. DATA DISPLAY PATTERNS

#### Table with Actions

```typescript
// Таблица с действиями в каждой строке
<Table>
  <TableHeader>
    <TableRow>
      <TableHead>Товар</TableHead>
      <TableHead>Количество</TableHead>
      <TableHead>Действия</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    {items.map(item => (
      <TableRow key={item.id}>
        <TableCell>{item.name}</TableCell>
        <TableCell>{item.quantity}</TableCell>
        <TableCell>
          <DropdownMenu>
            <DropdownMenuTrigger>⋮</DropdownMenuTrigger>
            <DropdownMenuContent>
              <DropdownMenuItem>Редактировать</DropdownMenuItem>
              <DropdownMenuItem>Удалить</DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
        </TableCell>
      </TableRow>
    ))}
  </TableBody>
</Table>
```

#### Многоуровневые таблицы поставок (Раздел "Мои поставки")

```typescript
// Паттерн многоуровневой таблицы с раскрытием деталей
<MultiLevelSuppliesTable>
  {/* Уровень 1: Поставка */}
  <SupplyRow expanded={expandedSupplies[supply.id]}>
    <StatusBadge status={supply.status} />
    <SupplyNumber>#{supply.number}</SupplyNumber>
    <SupplyDate>{formatDate(supply.deliveryDate)}</SupplyDate>
    <SupplyAmount>{formatCurrency(supply.totalAmount)}</SupplyAmount>
    <ExpandButton onClick={() => toggleSupply(supply.id)}>
      {expanded ? <ChevronDown /> : <ChevronRight />}
    </ExpandButton>
  </SupplyRow>

  {/* Уровень 2: Маршруты (раскрывается) */}
  {expanded && supply.routes.map(route => (
    <RouteRow key={route.id} expanded={expandedRoutes[route.id]}>
      <RouteInfo>
        <MapPin /> {route.fromLocation} → {route.toLocation}
      </RouteInfo>
      <LogisticsPrice>{formatCurrency(route.price)}</LogisticsPrice>
      <ExpandButton onClick={() => toggleRoute(route.id)}>
        {expanded ? <ChevronDown /> : <ChevronRight />}
      </ExpandButton>
    </RouteRow>
  ))}

  {/* Уровень 3: Товары (раскрывается) */}
  {expandedRoutes[route.id] && route.items.map(item => (
    <ItemRow key={item.id}>
      <ProductInfo>
        <ProductName>{item.product.name}</ProductName>
        <ProductSKU>{item.product.article}</ProductSKU>
      </ProductInfo>
      <Quantities>
        <Badge variant="outline">План: {item.plannedQty}</Badge>
        <Badge variant="success">Факт: {item.actualQty}</Badge>
        {item.defectQty > 0 && (
          <Badge variant="destructive">Брак: {item.defectQty}</Badge>
        )}
      </Quantities>
      <ItemPrice>{formatCurrency(item.totalPrice)}</ItemPrice>
    </ItemRow>
  ))}
</MultiLevelSuppliesTable>
```

**UX особенности многоуровневых таблиц:**

1. **Прогрессивное раскрытие** - показываем детали только по запросу
2. **Визуальная иерархия** - отступы и цвета для разных уровней
3. **Сохранение контекста** - видны все родительские уровни
4. **Быстрая навигация** - клик по уровню раскрывает/скрывает детали
5. **Информативные индикаторы** - иконки и цвета для быстрого понимания

#### Card-based Layout

```typescript
// Карточки для визуального представления данных
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
  {orders.map(order => (
    <Card key={order.id} className="glass-card">
      <CardHeader>
        <CardTitle>Заказ #{order.id}</CardTitle>
        <CardAction>
          <Badge variant={getStatusVariant(order.status)}>
            {order.status}
          </Badge>
        </CardAction>
      </CardHeader>
      <CardContent>
        <p>{order.description}</p>
      </CardContent>
      <CardFooter>
        <Button variant="ghost" size="sm">Детали</Button>
      </CardFooter>
    </Card>
  ))}
</div>
```

#### Master-Detail Pattern

```typescript
// Список + детальная информация
<div className="flex h-full">
  <aside className="w-1/3 border-r">
    <OrdersList
      orders={orders}
      selectedId={selectedOrderId}
      onSelect={setSelectedOrderId}
    />
  </aside>
  <main className="flex-1 p-6">
    {selectedOrderId ? (
      <OrderDetails id={selectedOrderId} />
    ) : (
      <EmptyState>Выберите заказ для просмотра</EmptyState>
    )}
  </main>
</div>
```

### 🔄 2. NAVIGATION PATTERNS

#### Breadcrumb Navigation

```typescript
<Breadcrumb>
  <BreadcrumbItem>
    <BreadcrumbLink href="/catalog">Каталог</BreadcrumbLink>
  </BreadcrumbItem>
  <BreadcrumbSeparator />
  <BreadcrumbItem>
    <BreadcrumbLink href="/catalog/electronics">Электроника</BreadcrumbLink>
  </BreadcrumbItem>
  <BreadcrumbSeparator />
  <BreadcrumbItem>
    <BreadcrumbPage>Смартфоны</BreadcrumbPage>
  </BreadcrumbItem>
</Breadcrumb>
```

#### Tab Navigation

```typescript
<Tabs value={activeTab} onValueChange={setActiveTab}>
  <TabsList className="glass-tabs">
    <TabsTrigger value="supplies">Поставки</TabsTrigger>
    <TabsTrigger value="orders">Заказы</TabsTrigger>
    <TabsTrigger value="statistics">Статистика</TabsTrigger>
  </TabsList>
  <TabsContent value="supplies">
    <SuppliesContent />
  </TabsContent>
  <TabsContent value="orders">
    <OrdersContent />
  </TabsContent>
  <TabsContent value="statistics">
    <StatisticsContent />
  </TabsContent>
</Tabs>
```

#### Sidebar Navigation

```typescript
<div className="flex h-screen">
  <Sidebar className="glass-sidebar">
    <SidebarHeader>
      <Logo />
    </SidebarHeader>
    <SidebarContent>
      <SidebarGroup title="Основное">
        <SidebarMenuItem href="/dashboard" icon={Home}>
          Главная
        </SidebarMenuItem>
        <SidebarMenuItem href="/catalog" icon={Package}>
          Каталог
        </SidebarMenuItem>
      </SidebarGroup>
    </SidebarContent>
  </Sidebar>
  <main className="flex-1">
    <PageContent />
  </main>
</div>
```

### 📝 3. FORM PATTERNS

#### Multi-step Form

```typescript
const steps = [
  { id: 'basic', title: 'Основная информация' },
  { id: 'details', title: 'Детали товара' },
  { id: 'review', title: 'Проверка' }
]

<Card className="glass-card">
  <CardHeader>
    <ProgressIndicator steps={steps} currentStep={currentStep} />
  </CardHeader>
  <CardContent>
    {currentStep === 'basic' && <BasicInfoStep />}
    {currentStep === 'details' && <DetailsStep />}
    {currentStep === 'review' && <ReviewStep />}
  </CardContent>
  <CardFooter>
    <Button
      variant="outline"
      onClick={goToPreviousStep}
      disabled={currentStep === 'basic'}
    >
      Назад
    </Button>
    <Button onClick={goToNextStep}>
      {currentStep === 'review' ? 'Завершить' : 'Далее'}
    </Button>
  </CardFooter>
</Card>
```

#### Inline Editing

```typescript
const [editing, setEditing] = useState(false)
const [value, setValue] = useState(initialValue)

{editing ? (
  <div className="flex items-center gap-2">
    <Input
      value={value}
      onChange={(e) => setValue(e.target.value)}
      autoFocus
    />
    <Button size="sm" onClick={saveValue}>✓</Button>
    <Button size="sm" variant="ghost" onClick={cancelEdit}>✕</Button>
  </div>
) : (
  <div className="flex items-center gap-2">
    <span>{value}</span>
    <Button size="sm" variant="ghost" onClick={() => setEditing(true)}>
      ✏️
    </Button>
  </div>
)}
```

#### Smart Defaults

```typescript
// Автозаполнение на основе контекста
<Select
  value={selectedSupplier}
  onValueChange={setSelectedSupplier}
  defaultValue={suggestedSupplier} // На основе истории заказов
>
  <SelectTrigger>
    <SelectValue placeholder="Выберите поставщика" />
  </SelectTrigger>
  <SelectContent>
    {suppliers.map(supplier => (
      <SelectItem key={supplier.id} value={supplier.id}>
        {supplier.name}
        {supplier.id === suggestedSupplier && (
          <Badge variant="secondary" className="ml-2">
            Рекомендуется
          </Badge>
        )}
      </SelectItem>
    ))}
  </SelectContent>
</Select>
```

### ⚡ 4. FEEDBACK PATTERNS

#### Loading States

```typescript
// Скелетоны для лучшего UX
{loading ? (
  <div className="space-y-4">
    <Skeleton className="h-8 w-full" />
    <Skeleton className="h-32 w-full" />
    <div className="flex space-x-4">
      <Skeleton className="h-10 w-24" />
      <Skeleton className="h-10 w-24" />
    </div>
  </div>
) : (
  <ActualContent />
)}
```

#### Toast Notifications

```typescript
import { toast } from 'sonner'

// Различные типы уведомлений
const handleSuccess = () => {
  toast.success('Товар успешно добавлен', {
    description: 'Товар появится в каталоге через несколько минут',
    action: {
      label: 'Посмотреть',
      onClick: () => navigate('/catalog'),
    },
  })
}

const handleError = () => {
  toast.error('Ошибка при сохранении', {
    description: 'Проверьте подключение к интернету',
    action: {
      label: 'Повторить',
      onClick: retryAction,
    },
  })
}

const handleInfo = () => {
  toast.info('Обновление системы', {
    description: 'Система будет недоступна с 23:00 до 01:00',
  })
}
```

#### Progress Indicators

```typescript
// Для длительных операций
<div className="space-y-2">
  <div className="flex justify-between text-sm">
    <span>Загрузка товаров...</span>
    <span>{progress}%</span>
  </div>
  <Progress value={progress} className="w-full" />
  <div className="text-xs text-muted-foreground">
    {currentItem} из {totalItems} товаров
  </div>
</div>
```

### 🔍 5. SEARCH PATTERNS

#### Faceted Search

```typescript
<div className="flex gap-6">
  <aside className="w-64">
    <FilterSidebar>
      <FilterGroup title="Категория">
        {categories.map(category => (
          <Checkbox
            key={category.id}
            checked={selectedCategories.includes(category.id)}
            onCheckedChange={(checked) =>
              toggleCategory(category.id, checked)
            }
          >
            {category.name} ({category.count})
          </Checkbox>
        ))}
      </FilterGroup>

      <FilterGroup title="Цена">
        <Slider
          value={priceRange}
          onValueChange={setPriceRange}
          max={maxPrice}
          step={100}
          className="w-full"
        />
        <div className="flex justify-between text-sm">
          <span>{priceRange[0]} ₽</span>
          <span>{priceRange[1]} ₽</span>
        </div>
      </FilterGroup>
    </FilterSidebar>
  </aside>

  <main className="flex-1">
    <SearchHeader>
      <SearchInput
        value={searchTerm}
        onChange={setSearchTerm}
        placeholder="Поиск товаров..."
      />
      <SortSelect value={sortBy} onValueChange={setSortBy} />
    </SearchHeader>
    <SearchResults results={filteredResults} />
  </main>
</div>
```

#### Autocomplete Search

```typescript
<Popover open={isOpen} onOpenChange={setIsOpen}>
  <PopoverTrigger asChild>
    <Input
      value={searchTerm}
      onChange={(e) => {
        setSearchTerm(e.target.value)
        setIsOpen(e.target.value.length > 2)
      }}
      placeholder="Начните вводить название товара..."
    />
  </PopoverTrigger>
  <PopoverContent className="w-full p-0">
    <div className="max-h-60 overflow-y-auto">
      {suggestions.map(suggestion => (
        <div
          key={suggestion.id}
          className="px-3 py-2 hover:bg-accent cursor-pointer"
          onClick={() => selectSuggestion(suggestion)}
        >
          <div className="font-medium">{suggestion.name}</div>
          <div className="text-sm text-muted-foreground">
            {suggestion.category} • {suggestion.price} ₽
          </div>
        </div>
      ))}
    </div>
  </PopoverContent>
</Popover>
```

## 🎯 ACCESSIBILITY PATTERNS

### 1. Keyboard Navigation

```typescript
// Обработка клавиатуры для кастомных компонентов
const handleKeyDown = (e: KeyboardEvent) => {
  switch (e.key) {
    case 'Enter':
    case ' ':
      e.preventDefault()
      handleClick()
      break
    case 'Escape':
      handleClose()
      break
    case 'ArrowDown':
      focusNext()
      break
    case 'ArrowUp':
      focusPrevious()
      break
  }
}

<div
  role="button"
  tabIndex={0}
  onKeyDown={handleKeyDown}
  onClick={handleClick}
  aria-label="Добавить товар в корзину"
>
  Добавить в корзину
</div>
```

### 2. Screen Reader Support

```typescript
// Правильные ARIA атрибуты
<form role="form" aria-labelledby="form-title">
  <h2 id="form-title">Создание нового товара</h2>

  <Label htmlFor="product-name">Название товара *</Label>
  <Input
    id="product-name"
    required
    aria-describedby="name-error"
    aria-invalid={hasNameError}
  />
  {hasNameError && (
    <div id="name-error" role="alert" className="text-destructive">
      Название товара обязательно для заполнения
    </div>
  )}

  <Button type="submit" aria-describedby="submit-help">
    Создать товар
  </Button>
  <div id="submit-help" className="text-sm text-muted-foreground">
    Нажмите Enter или кликните для создания
  </div>
</form>
```

### 3. Focus Management

```typescript
// Управление фокусом в модальных окнах
const DialogContent = ({ children, ...props }) => {
  const focusRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    // Фокус на контент при открытии
    focusRef.current?.focus()

    // Возврат фокуса при закрытии
    return () => {
      document.getElementById('trigger-button')?.focus()
    }
  }, [])

  return (
    <div
      ref={focusRef}
      role="dialog"
      aria-modal="true"
      tabIndex={-1}
      {...props}
    >
      {children}
    </div>
  )
}
```

## 📱 RESPONSIVE PATTERNS

### Mobile-First Design

```typescript
// Компоненты адаптируются под размер экрана
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
  {/* Мобильный: 1 колонка, Планшет: 2 колонки, Десктоп: 3 колонки */}
</div>

// Навигация адаптируется
<nav className="hidden md:flex md:space-x-6">
  {/* Десктопное меню */}
</nav>
<Sheet> {/* Мобильное выдвижное меню */}
  <SheetTrigger className="md:hidden">
    <Menu />
  </SheetTrigger>
  <SheetContent>
    <MobileNavigation />
  </SheetContent>
</Sheet>
```

### Touch-Friendly Interfaces

```typescript
// Увеличенные области касания на мобильных
<Button
  size="lg" // На мобильных кнопки больше
  className="min-h-[44px] min-w-[44px]" // Минимум 44px для касания
>
  Действие
</Button>

// Swipe жесты для карточек
<div
  className="touch-pan-x" // Позволяет горизонтальную прокрутку
  onTouchStart={handleTouchStart}
  onTouchEnd={handleTouchEnd}
>
  <SwipeableCard />
</div>
```

## 🔄 ERROR HANDLING PATTERNS

### Form Validation

```typescript
const [errors, setErrors] = useState<Record<string, string>>({})

const validateForm = (data: FormData) => {
  const newErrors: Record<string, string> = {}

  if (!data.name) {
    newErrors.name = 'Название обязательно'
  }

  if (data.price <= 0) {
    newErrors.price = 'Цена должна быть больше 0'
  }

  setErrors(newErrors)
  return Object.keys(newErrors).length === 0
}

// В форме
<Input
  value={formData.name}
  onChange={(e) => setFormData({...formData, name: e.target.value})}
  aria-invalid={!!errors.name}
  className={errors.name ? 'border-destructive' : ''}
/>
{errors.name && (
  <div className="text-destructive text-sm mt-1">
    {errors.name}
  </div>
)}
```

### Network Error Handling

```typescript
const { data, error, isLoading, refetch } = useQuery(GET_PRODUCTS)

if (error) {
  return (
    <Card className="glass-card p-6 text-center">
      <AlertTriangle className="h-12 w-12 text-yellow-400 mx-auto mb-4" />
      <h3 className="text-lg font-semibold mb-2">
        Не удалось загрузить данные
      </h3>
      <p className="text-muted-foreground mb-4">
        Проверьте подключение к интернету и попробуйте снова
      </p>
      <Button onClick={() => refetch()}>
        Повторить попытку
      </Button>
    </Card>
  )
}
```

## 🚀 PERFORMANCE PATTERNS

### Lazy Loading

```typescript
// Ленивая загрузка тяжелых компонентов
const HeavyChart = lazy(() => import('./heavy-chart'))

<Suspense fallback={<ChartSkeleton />}>
  <HeavyChart data={chartData} />
</Suspense>
```

### Virtual Scrolling

```typescript
// Для больших списков
import { FixedSizeList as List } from 'react-window'

const ItemRenderer = ({ index, style }) => (
  <div style={style}>
    <ProductCard product={products[index]} />
  </div>
)

<List
  height={600}
  itemCount={products.length}
  itemSize={200}
  width="100%"
>
  {ItemRenderer}
</List>
```

---

_UX паттерны основаны на анализе пользовательских сценариев и UI компонентов системы SFERA_  
_Версия документа: 2025-08-21_  
_Основа: User-Centered Design + Accessibility + Mobile-First + Performance_
