Gogs před 3 týdny
rodič
revize
4213984f4f
2 změnil soubory, kde provedl 567 přidání a 1 odebrání
  1. 1 1
      README.md
  2. 566 0
      vue/app/shared/ModalWindow/README.md

+ 1 - 1
README.md

@@ -1,5 +1,5 @@
 # Текущая задача
-Опиши компонент для возможности использования в разработке: https://gogs.osvoj.ru/s5l.ru/borbad.s5l.ru/src/master/vue/app/shared/ModalWindow
+Опиши компонент для возможности использования в разработке: https://gogs.osvoj.ru/s5l.ru/borbad.s5l.ru/src/master/vue/app/shared/SuccessModal
 сделай полное описание вех методов использования и взаимодействия. (в описание не дублируй листинги из репозитария)
 
 # файл с правилами

+ 566 - 0
vue/app/shared/ModalWindow/README.md

@@ -0,0 +1,566 @@
+# Компонент ModalWindow - Полная документация
+
+## Назначение компонента
+
+`ModalWindow` - универсальный компонент для создания модальных окон (диалоговых окон) в приложении. Предоставляет функциональность для отображения контента поверх основного интерфейса с затемнением фона, анимациями и управлением через глобальную шину событий.
+
+## Архитектура компонента
+
+### Структура файлов
+```
+app/shared/ModalWindow/
+├── index.coffee    # Логика компонента
+├── index.pug       # Шаблон
+└── index.styl      # Стили
+```
+
+## Импорт и регистрация
+
+```coffee
+# В основном файле приложения (app/temp.coffee)
+components:
+    'modal-window': require 'app/shared/ModalWindow'
+```
+
+## Базовое использование
+
+### 1. Простое модальное окно
+```pug
+modal-window(
+    :is-visible="showModal"
+    @close="showModal = false"
+)
+    template([body])
+        h2(class="text-xl font-bold mb-4") Заголовок
+        p Содержимое модального окна
+```
+
+### 2. С кнопками действий
+```pug
+modal-window(
+    :is-visible="showModal"
+    @close="showModal = false"
+    @confirm="handleConfirm"
+)
+    template([body])
+        h2(class="text-xl font-bold mb-4") Подтверждение
+        p Вы уверены, что хотите выполнить это действие?
+    
+    template([footer])
+        button(@click="$emit('close')" class="btn-secondary") Отмена
+        button(@click="$emit('confirm')" class="btn-primary") Подтвердить
+```
+
+## Полный список props
+
+### `isVisible` (обязательный)
+- **Тип:** `Boolean`
+- **Описание:** Управляет видимостью модального окна
+- **Пример:**
+  ```pug
+  modal-window(:is-visible="isModalOpen")
+  ```
+
+### `title` (опциональный)
+- **Тип:** `String`
+- **По умолчанию:** `''`
+- **Описание:** Заголовок модального окна
+- **Пример:**
+  ```pug
+  modal-window(:is-visible="showModal" title="Заголовок окна")
+  ```
+
+### `size` (опциональный)
+- **Тип:** `String`
+- **По умолчанию:** `'md'`
+- **Допустимые значения:** `'sm'`, `'md'`, `'lg'`, `'xl'`, `'full'`
+- **Описание:** Размер модального окна
+- **Пример:**
+  ```pug
+  modal-window(:is-visible="showModal" size="lg")
+  ```
+
+### `closeOnBackdrop` (опциональный)
+- **Тип:** `Boolean`
+- **По умолчанию:** `true`
+- **Описание:** Закрывать ли окно при клике на подложку
+- **Пример:**
+  ```pug
+  modal-window(:is-visible="showModal" :close-on-backdrop="false")
+  ```
+
+### `closeOnEscape` (опциональный)
+- **Тип:** `Boolean`
+- **По умолчанию:** `true`
+- **Описание:** Закрывать ли окно при нажатии Escape
+- **Пример:**
+  ```pug
+  modal-window(:is-visible="showModal" :close-on-escape="false")
+  ```
+
+### `showCloseButton` (опциональный)
+- **Тип:** `Boolean`
+- **По умолчанию:** `true`
+- **Описание:** Показывать ли кнопку закрытия
+- **Пример:**
+  ```pug
+  modal-window(:is-visible="showModal" :show-close-button="false")
+  ```
+
+### `overlayClass` (опциональный)
+- **Тип:** `String`
+- **По умолчанию:** `''`
+- **Описание:** Дополнительные классы для подложки
+- **Пример:**
+  ```pug
+  modal-window(:is-visible="showModal" overlay-class="bg-opacity-80")
+  ```
+
+### `contentClass` (опциональный)
+- **Тип:** `String`
+- **По умолчанию:** `''`
+- **Описание:** Дополнительные классы для контента
+- **Пример:**
+  ```pug
+  modal-window(:is-visible="showModal" content-class="custom-modal-style")
+  ```
+
+## События (Events)
+
+### `@close`
+- **Описание:** Событие закрытия модального окна
+- **Payload:** `null`
+- **Пример:**
+  ```pug
+  modal-window(:is-visible="showModal" @close="handleModalClose")
+  ```
+
+### `@confirm` (опциональный)
+- **Описание:** Событие подтверждения действия
+- **Payload:** `null`
+- **Пример:**
+  ```pug
+  modal-window(:is-visible="showModal" @confirm="handleConfirm")
+  ```
+
+### `@opened`
+- **Описание:** Событие полного открытия модального окна (после анимации)
+- **Payload:** `null`
+- **Пример:**
+  ```pug
+  modal-window(:is-visible="showModal" @opened="handleModalOpened")
+  ```
+
+### `@closed`
+- **Описание:** Событие полного закрытия модального окна (после анимации)
+- **Payload:** `null`
+- **Пример:**
+  ```pug
+  modal-window(:is-visible="showModal" @closed="handleModalClosed")
+  ```
+
+## Слоты (Slots)
+
+### `[body]` (основной слот)
+- **Описание:** Основное содержимое модального окна
+- **Пример:**
+  ```pug
+  modal-window(:is-visible="showModal")
+      template([body])
+          h2 Заголовок
+          p Основной контент
+          form
+              input(type="text" placeholder="Введите данные")
+              button(type="submit") Отправить
+  ```
+
+### `[header]` (опциональный)
+- **Описание:** Заголовочная область модального окна
+- **Пример:**
+  ```pug
+  modal-window(:is-visible="showModal")
+      template([header])
+          div(class="flex items-center justify-between")
+              h2(class="text-xl font-bold") Пользовательский заголовок
+              custom-close-button(@click="$emit('close')")
+  
+      template([body])
+          p Содержимое модального окна
+  ```
+
+### `[footer]` (опциональный)
+- **Описание:** Нижняя область модального окна (обычно для кнопок)
+- **Пример:**
+  ```pug
+  modal-window(:is-visible="showModal")
+      template([body])
+          p Вы уверены, что хотите удалить этот элемент?
+  
+      template([footer])
+          div(class="flex justify-end space-x-3")
+              button(@click="$emit('close')" class="btn-secondary") Отмена
+              button(@click="$emit('confirm')" class="btn-danger") Удалить
+  ```
+
+## Размеры модальных окон
+
+### Доступные размеры
+```pug
+//- Маленькое (sm)
+modal-window(:is-visible="showModal" size="sm")
+
+//- Среднее (md) - по умолчанию
+modal-window(:is-visible="showModal" size="md")
+
+//- Большое (lg)
+modal-window(:is-visible="showModal" size="lg")
+
+//- Очень большое (xl)
+modal-window(:is-visible="showModal" size="xl")
+
+//- На весь экран (full)
+modal-window(:is-visible="showModal" size="full")
+```
+
+## Стили и CSS классы
+
+### Базовые классы
+- `.modal-overlay` - класс подложки
+- `.modal-container` - класс контейнера
+- `.modal-content` - класс контента
+
+### Модификаторы размера
+- `.modal--sm` - маленький размер
+- `.modal--md` - средний размер (по умолчанию)
+- `.modal--lg` - большой размер
+- `.modal--xl` - очень большой размер
+- `.modal--full` - на весь экран
+
+### Состояния анимации
+- `.modal-enter-active` - анимация появления
+- `.modal-leave-active` - анимация исчезновения
+
+## Примеры использования в различных сценариях
+
+### 1. Простая информационная модалка
+```pug
+modal-window(
+    :is-visible="showInfoModal"
+    @close="showInfoModal = false"
+    title="Информация"
+)
+    template([body])
+        p(class="mb-4") Это информационное модальное окно с простым текстом.
+        p Вы можете закрыть его, нажав на крестик или кликнув вне окна.
+```
+
+### 2. Модалка подтверждения действия
+```pug
+modal-window(
+    :is-visible="showConfirmModal"
+    @close="showConfirmModal = false"
+    @confirm="handleDeleteConfirm"
+    title="Подтверждение удаления"
+    size="sm"
+)
+    template([body])
+        p Вы уверены, что хотите удалить "{{ itemName }}"? Это действие нельзя отменить.
+
+    template([footer])
+        div(class="flex justify-end space-x-3")
+            button(
+                @click="$emit('close')"
+                class="px-4 py-2 text-gray-600 hover:text-gray-800 transition-colors"
+            ) Отмена
+            button(
+                @click="$emit('confirm')"
+                class="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700 transition-colors"
+            ) Удалить
+```
+
+### 3. Форма в модальном окне
+```pug
+modal-window(
+    :is-visible="showFormModal"
+    @close="closeFormModal"
+    title="Добавить мероприятие"
+    size="lg"
+    :close-on-backdrop="false"
+)
+    template([body])
+        form(@submit.prevent="submitEventForm")
+            div(class="space-y-4")
+                div
+                    label(for="title" class="block text-sm font-medium text-gray-700") Название
+                    input(
+                        id="title"
+                        v-model="form.title"
+                        type="text"
+                        class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500"
+                        required
+                    )
+                
+                div
+                    label(for="description" class="block text-sm font-medium text-gray-700") Описание
+                    textarea(
+                        id="description"
+                        v-model="form.description"
+                        rows="4"
+                        class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500"
+                    )
+    
+    template([footer])
+        div(class="flex justify-end space-x-3")
+            button(
+                type="button"
+                @click="$emit('close')"
+                class="px-4 py-2 text-gray-600 hover:text-gray-800 transition-colors"
+            ) Отмена
+            button(
+                type="submit"
+                class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors"
+            ) Сохранить
+```
+
+### 4. Модалка с кастомным заголовком
+```pug
+modal-window(
+    :is-visible="showCustomModal"
+    @close="showCustomModal = false"
+    :show-close-button="false"
+)
+    template([header])
+        div(class="bg-gradient-to-r from-blue-500 to-purple-600 text-white p-6")
+            div(class="flex items-center justify-between")
+                div
+                    h2(class="text-2xl font-bold") Премиум функции
+                    p(class="text-blue-100") Доступно только для премиум пользователей
+                button(
+                    @click="$emit('close')"
+                    class="text-white hover:text-blue-200 transition-colors"
+                )
+                    icon(name="close" class="w-6 h-6")
+    
+    template([body])
+        div(class="p-6")
+            ul(class="space-y-3")
+                li(class="flex items-center")
+                    icon(name="check" class="w-5 h-5 text-green-500 mr-3")
+                    span Расширенная аналитика
+                li(class="flex items-center")
+                    icon(name="check" class="w-5 h-5 text-green-500 mr-3")
+                    span Приоритетная поддержка
+                li(class="flex items-center")
+                    icon(name="check" class="w-5 h-5 text-green-500 mr-3")
+                    span Кастомные домены
+    
+    template([footer])
+        div(class="bg-gray-50 px-6 py-4 flex justify-between items-center")
+            span(class="text-gray-600") Всего 999 TJS/месяц
+            button(
+                @click="subscribePremium"
+                class="px-6 py-2 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-lg hover:from-blue-600 hover:to-purple-700 transition-colors"
+            ) Подписаться
+```
+
+### 5. Модалка с загрузкой контента
+```pug
+modal-window(
+    :is-visible="showLoadingModal"
+    @close="cancelLoading"
+    title="Загрузка"
+    :close-on-escape="false"
+    :close-on-backdrop="false"
+    :show-close-button="false"
+)
+    template([body])
+        div(class="text-center py-8")
+            div(class="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4")
+            p Загрузка данных, пожалуйста подождите...
+```
+
+### 6. Модалка с вкладками
+```pug
+modal-window(
+    :is-visible="showTabsModal"
+    @close="showTabsModal = false"
+    title="Настройки"
+    size="lg"
+)
+    template([body])
+        div
+            div(class="border-b border-gray-200")
+                nav(class="-mb-px flex space-x-8")
+                    button(
+                        v-for="tab in tabs"
+                        :key="tab.id"
+                        @click="currentTab = tab.id"
+                        :class="{
+                            'border-blue-500 text-blue-600': currentTab === tab.id,
+                            'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300': currentTab !== tab.id
+                        }"
+                        class="whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
+                    ) {{ tab.name }}
+            
+            div(class="py-4")
+                div(v-if="currentTab === 'general'")
+                    h3(class="text-lg font-medium mb-4") Основные настройки
+                    //- Контент вкладки
+                
+                div(v-else-if="currentTab === 'security'")
+                    h3(class="text-lg font-medium mb-4") Безопасность
+                    //- Контент вкладки
+```
+
+## Управление через глобальную шину событий
+
+### Открытие модального окна
+```coffee
+# В любом компоненте
+EventBus.emit('open_modal', {
+    component: require('app/components/CustomModal'),
+    props: {
+        title: 'Кастомное окно',
+        data: someData
+    }
+})
+```
+
+### Закрытие модального окна
+```coffee
+# Закрытие текущего модального окна
+EventBus.emit('close_modal')
+
+# Закрытие всех модальных окон
+EventBus.emit('close_all_modals')
+```
+
+## Интеграция с глобальным состоянием
+
+### Использование с appState
+```coffee
+# В основном приложении
+appState:
+    modalState:
+        isVisible: false
+        component: null
+        props: {}
+
+# Открытие модалки
+openModal: (component, props = {}) ->
+    @appState.modalState.component = component
+    @appState.modalState.props = props
+    @appState.modalState.isVisible = true
+
+# В шаблоне
+modal-window(
+    :is-visible="appState.modalState.isVisible"
+    @close="closeModal"
+    v-if="appState.modalState.component"
+)
+    component(
+        :is="appState.modalState.component"
+        v-bind="appState.modalState.props"
+        @close="closeModal"
+    )
+```
+
+## Анимации и переходы
+
+### Кастомные анимации
+```styl
+// В стилях компонента
+.modal-custom-enter-active
+    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1)
+    
+    .modal-container
+        transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1)
+        transform: scale(0.95) translateY(-10px)
+        opacity: 0
+
+.modal-custom-enter-to
+    .modal-container
+        transform: scale(1) translateY(0)
+        opacity: 1
+```
+
+## Best Practices
+
+### 1. Управление состоянием
+```coffee
+# Правильно - реактивное управление
+data: ->
+    return
+        showModal: false
+
+methods:
+    openModal: ->
+        @showModal = true
+    
+    closeModal: ->
+        @showModal = false
+```
+
+### 2. Обработка подтверждений
+```coffee
+methods:
+    handleConfirm: ->
+        try
+            await this.performAction()
+            this.showModal = false
+            this.showSuccessMessage()
+        catch error
+            this.showErrorMessage(error)
+```
+
+### 3. Доступность
+```pug
+//- Добавляйте aria-атрибуты для доступности
+modal-window(
+    :is-visible="showModal"
+    @close="closeModal"
+    role="dialog"
+    aria-labelledby="modal-title"
+)
+    template([header])
+        h2(id="modal-title") Заголовок модалки
+```
+
+### 4. Управление фокусом
+```coffee
+# Автоматически фокусироваться на первом интерактивном элементе
+mounted: ->
+    this.$nextTick(() ->
+        const firstInput = this.$el.querySelector('input, button, textarea')
+        if firstInput
+            firstInput.focus()
+    )
+```
+
+## Отладка и разработка
+
+### Логирование событий
+```coffee
+# Отслеживание событий модального окна
+EventBus.on('modal_opened', (data) ->
+    debug.log "Модальное окно открыто: "+data.component?.name
+)
+
+EventBus.on('modal_closed', (data) ->
+    debug.log "Модальное окно закрыто"
+)
+```
+
+### Проверка доступности
+```coffee
+# Проверка управления фокусом
+checkFocusManagement: ->
+    if this.isVisible
+        const activeElement = document.activeElement
+        const modalContent = this.$el.querySelector('.modal-content')
+        
+        if modalContent and !modalContent.contains(activeElement)
+            debug.log "Фокус вне модального окна!"
+```
+
+Компонент ModalWindow предоставляет мощный и гибкий инструмент для создания модальных окон с поддержкой анимаций, управления через события, кастомизацией и соблюдением лучших практик доступности.