Перейти к содержанию

Образы

Обзор функциональности

Обзор

Образы — комбинации вещей из гардероба, организованные по слотам (верх, низ, обувь, аксессуар). Пользователь собирает образ в конструкторе, система автоматически генерирует название через AI. Образы можно просматривать, шерить и удалять.

Страницы модуля

Страница Маршрут Назначение
OutfitsPage /outfits Список всех образов (свои / чужие / все)
OutfitBuilderPage /outfits/build Конструктор образа
ItemSelectPage /outfits/build/select Выбор вещи для конкретного слота
OutfitDetailPage /outfits/:outfitId Детальный просмотр образа

State diagram: конструктор образов

stateDiagram-v2
    [*] --> Init: Открытие /outfits/build
    Init --> SlotsLoaded: useLocalSlots() загружены
    SlotsLoaded --> Empty: initSlots(slots)

    Empty --> Filling: Выбор вещи для слота
    Filling --> Filling: Добавление вещи в другой слот
    Filling --> Empty: clearAll()

    Filling --> TitleSuggesting: suggestItems.length > 0
    TitleSuggesting --> TitleReady: API вернул название
    TitleReady --> Filling: Пользователь изменил название

    Filling --> Creating: handleCreate()
    Creating --> DuplicateCheck: findDuplicateOutfit()
    DuplicateCheck --> Created: Нет дупликата
    DuplicateCheck --> Filling: Дупликат найден (warning)
    Created --> [*]: navigate('/outfits')

    state Filling {
        [*] --> SlotView: Листает слоты
        SlotView --> ItemSelect: "Все →" (navigate to select page)
        ItemSelect --> SlotView: Выбрал вещь (navigate back)
    }

Диаграмма

Sequence diagram: создание образа

sequenceDiagram
    participant U as Пользователь
    participant Builder as OutfitBuilderPage
    participant Store as outfitBuilderStore
    participant API as outfitsApi
    participant IDB as IndexedDB

    U->>Builder: Открывает /outfits/build
    Builder->>Store: initSlots(slots)
    Store-->>Builder: slots[] (верх, низ, обувь)

    loop Для каждого слота
        U->>Builder: Выбирает вещь из горизонтального ряда
        Builder->>Store: setSlotItem(slotId, item)
    end

    Note over Builder, API: Автогенерация названия
    Builder->>API: POST /outfits/suggest-title { outfit_items }
    API-->>Builder: { title: "Городской casual" }
    Builder->>Store: setTitle(suggestion)

    U->>Builder: Нажимает "Создать образ"
    Builder->>IDB: findDuplicateOutfit(items)
    IDB-->>Builder: null (нет дубликата)
    Builder->>API: offlineOutfitsService.create({ title, outfit_items })
    API-->>Builder: Outfit created
    Builder->>Store: clearAll()
    Builder->>U: navigate('/outfits')

Диаграмма

Слоты

Слоты определяют позиции вещей в образе:

Слот Код Назначение
Верх top Футболки, рубашки, худи, куртки
Низ bottom Джинсы, брюки, юбки
Обувь shoes Кроссовки, туфли, ботинки

Слот "Платье" (dress) фильтруется из конструктора: slots.filter((sl) => sl.code !== 'dress').

Автогенерация названия

При изменении состава вещей (с debounce 500ms): 1. Отправляется POST /outfits/suggest-title с текущими outfit_items 2. API возвращает AI-сгенерированное название 3. Название применяется автоматически если пользователь не менял его вручную

Логика auto-apply:

const canAutoApply =
  currentTitle.length === 0 ||
  (lastAutoTitle.length > 0 && currentTitle === lastAutoTitle);

API-модуль

// outfitsApi (frontend/src/api/outfits.ts)
outfitsApi.list(params)              // GET /outfits
outfitsApi.get(id)                   // GET /outfits/:id
outfitsApi.create(data)              // POST /outfits
outfitsApi.suggestTitle(data)        // POST /outfits/suggest-title
outfitsApi.update(id, data)          // PATCH /outfits/:id
outfitsApi.delete(id)                // DELETE /outfits/:id
outfitsApi.save(id)                  // POST /outfits/:id/save
outfitsApi.unsave(id)                // DELETE /outfits/:id/save
outfitsApi.share(id, format)         // POST /outfits/:id/share
outfitsApi.similar(id, params)       // GET /outfits/:id/similar

Навигация