|
@@ -0,0 +1,412 @@
|
|
|
|
|
+# Компонент EventDetailModal - Полная документация
|
|
|
|
|
+
|
|
|
|
|
+## Назначение компонента
|
|
|
|
|
+
|
|
|
|
|
+`EventDetailModal` - модальное окно для детального просмотра информации о мероприятиях. Компонент предоставляет полную информацию о событии, включая описание, даты, место проведения, цены, доступные билеты и галерею изображений. Поддерживает мультиязычность и адаптивный дизайн.
|
|
|
|
|
+
|
|
|
|
|
+## git репозитарий
|
|
|
|
|
+https://gogs.osvoj.ru/s5l.ru/borbad.s5l.ru/src/master/vue/app/shared/EventDetailModal/
|
|
|
|
|
+
|
|
|
|
|
+## Импорт и регистрация
|
|
|
|
|
+
|
|
|
|
|
+```coffee
|
|
|
|
|
+# В основном файле приложения (app/temp.coffee)
|
|
|
|
|
+components:
|
|
|
|
|
+ 'event-detail-modal': require 'app/shared/EventDetailModal'
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Базовое использование
|
|
|
|
|
+
|
|
|
|
|
+### Открытие модального окна
|
|
|
|
|
+```coffee
|
|
|
|
|
+# Через глобальную шину событий
|
|
|
|
|
+EventBus.emit('open_event_modal', eventData)
|
|
|
|
|
+
|
|
|
|
|
+# Через метод родительского компонента
|
|
|
|
|
+_.openModal(require('app/shared/EventDetailModal'), { event: eventData })
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Props
|
|
|
|
|
+
|
|
|
|
|
+### `event` (обязательный)
|
|
|
|
|
+- **Тип:** `Object`
|
|
|
|
|
+- **Описание:** Объект события с полной информацией
|
|
|
|
|
+- **Структура:**
|
|
|
|
|
+ ```coffee
|
|
|
|
|
+ {
|
|
|
|
|
+ _id: String
|
|
|
|
|
+ type: "event"
|
|
|
|
|
+ title: Array[String] # мультиязычный массив
|
|
|
|
|
+ content: Array[String]
|
|
|
|
|
+ excerpt: Array[String]
|
|
|
|
|
+ image: Array[String]
|
|
|
|
|
+ gallery: Array[Array[String]]
|
|
|
|
|
+ event_data: {
|
|
|
|
|
+ event_date: ISOString
|
|
|
|
|
+ end_date: ISOString
|
|
|
|
|
+ location: Array[String]
|
|
|
|
|
+ price: Array[Number]
|
|
|
|
|
+ currency: String
|
|
|
|
|
+ available_tickets: Number
|
|
|
|
|
+ total_tickets: Number
|
|
|
|
|
+ status: String
|
|
|
|
|
+ registration_required: Boolean
|
|
|
|
|
+ age_restriction: Array[String]
|
|
|
|
|
+ organizer: Array[String]
|
|
|
|
|
+ performers: Array[Array[String]]
|
|
|
|
|
+ duration: Number
|
|
|
|
|
+ }
|
|
|
|
|
+ # ... другие поля
|
|
|
|
|
+ }
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+### `show` (опциональный)
|
|
|
|
|
+- **Тип:** `Boolean`
|
|
|
|
|
+- **По умолчанию:** `false`
|
|
|
|
|
+- **Описание:** Управление видимостью модального окна
|
|
|
|
|
+
|
|
|
|
|
+## События (Events)
|
|
|
|
|
+
|
|
|
|
|
+### `@close`
|
|
|
|
|
+- **Описание:** Событие закрытия модального окна
|
|
|
|
|
+- **Payload:** `null`
|
|
|
|
|
+- **Использование:**
|
|
|
|
|
+ ```pug
|
|
|
|
|
+ event-detail-modal(:event="eventData" @close="handleModalClose")
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+### `@register`
|
|
|
|
|
+- **Описание:** Событие регистрации на мероприятие
|
|
|
|
|
+- **Payload:** `{ event: Object, tickets: Number }`
|
|
|
|
|
+- **Использование:**
|
|
|
|
|
+ ```pug
|
|
|
|
|
+ event-detail-modal(:event="eventData" @register="handleEventRegistration")
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+## Слоты (Slots)
|
|
|
|
|
+
|
|
|
|
|
+### `[header]` (опциональный)
|
|
|
|
|
+- **Описание:** Кастомный заголовок модального окна
|
|
|
|
|
+- **Пример:**
|
|
|
|
|
+ ```pug
|
|
|
|
|
+ event-detail-modal(:event="eventData")
|
|
|
|
|
+ template([header])
|
|
|
|
|
+ div(class="custom-header")
|
|
|
|
|
+ h2 Специальное мероприятие
|
|
|
|
|
+ badge(type="premium")
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+### `[footer]` (опциональный)
|
|
|
|
|
+- **Описание:** Кастомный футер модального окна
|
|
|
|
|
+- **Пример:**
|
|
|
|
|
+ ```pug
|
|
|
|
|
+ event-detail-modal(:event="eventData")
|
|
|
|
|
+ template([footer])
|
|
|
|
|
+ div(class="flex justify-between items-center")
|
|
|
|
|
+ span Дополнительная информация
|
|
|
|
|
+ button(@click="showExtraInfo") Подробнее
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+## Методы компонента
|
|
|
|
|
+
|
|
|
|
|
+### `open()`
|
|
|
|
|
+- **Описание:** Программное открытие модального окна
|
|
|
|
|
+- **Использование:**
|
|
|
|
|
+ ```coffee
|
|
|
|
|
+ modalRef = _.$refs.eventModal
|
|
|
|
|
+ modalRef.open()
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+### `close()`
|
|
|
|
|
+- **Описание:** Программное закрытие модального окна
|
|
|
|
|
+- **Использование:**
|
|
|
|
|
+ ```coffee
|
|
|
|
|
+ modalRef = _.$refs.eventModal
|
|
|
|
|
+ modalRef.close()
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+### `registerForEvent(tickets)`
|
|
|
|
|
+- **Описание:** Программная регистрация на мероприятие
|
|
|
|
|
+- **Параметры:** `tickets` - количество билетов
|
|
|
|
|
+- **Использование:**
|
|
|
|
|
+ ```coffee
|
|
|
|
|
+ modalRef = _.$refs.eventModal
|
|
|
|
|
+ modalRef.registerForEvent(2)
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+## Полные примеры использования
|
|
|
|
|
+
|
|
|
|
|
+### 1. Базовое использование в компоненте
|
|
|
|
|
+```pug
|
|
|
|
|
+//- Родительский компонент
|
|
|
|
|
+div
|
|
|
|
|
+ button(
|
|
|
|
|
+ @click="openEventModal(event)"
|
|
|
|
|
+ class="btn btn-primary"
|
|
|
|
|
+ ) Подробнее о мероприятии
|
|
|
|
|
+
|
|
|
|
|
+ event-detail-modal(
|
|
|
|
|
+ v-if="selectedEvent"
|
|
|
|
|
+ :event="selectedEvent"
|
|
|
|
|
+ :show="showModal"
|
|
|
|
|
+ @close="closeEventModal"
|
|
|
|
|
+ @register="handleRegistration"
|
|
|
|
|
+ )
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+```coffee
|
|
|
|
|
+# Логика родительского компонента
|
|
|
|
|
+methods:
|
|
|
|
|
+ openEventModal: (event) ->
|
|
|
|
|
+ @selectedEvent = event
|
|
|
|
|
+ @showModal = true
|
|
|
|
|
+
|
|
|
|
|
+ closeEventModal: ->
|
|
|
|
|
+ @showModal = false
|
|
|
|
|
+ @selectedEvent = null
|
|
|
|
|
+
|
|
|
|
|
+ handleRegistration: (data) ->
|
|
|
|
|
+ debug.log "Регистрация на мероприятие: "+data.event.title
|
|
|
|
|
+ debug.log "Билетов: "+data.tickets
|
|
|
|
|
+ # Логика регистрации...
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 2. Использование с глобальной шиной событий
|
|
|
|
|
+```coffee
|
|
|
|
|
+# В любом месте приложения
|
|
|
|
|
+EventBus.emit('open_event_modal', {
|
|
|
|
|
+ _id: "event_123"
|
|
|
|
|
+ title: ["Концерт симфонической музыки", "Symphonic Concert"]
|
|
|
|
|
+ content: ["Описание мероприятия...", "Event description..."]
|
|
|
|
|
+ event_data: {
|
|
|
|
|
+ event_date: "2024-03-20T19:00:00.000Z"
|
|
|
|
|
+ location: ["Большой зал", "Main Hall"]
|
|
|
|
|
+ price: [500, 500]
|
|
|
|
|
+ currency: "TJS"
|
|
|
|
|
+ available_tickets: 45
|
|
|
|
|
+ status: "upcoming"
|
|
|
|
|
+ }
|
|
|
|
|
+ # ... другие поля
|
|
|
|
|
+})
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 3. Программное управление
|
|
|
|
|
+```pug
|
|
|
|
|
+div
|
|
|
|
|
+ event-detail-modal(
|
|
|
|
|
+ ref="eventModal"
|
|
|
|
|
+ :event="currentEvent"
|
|
|
|
|
+ @close="onModalClose"
|
|
|
|
|
+ @register="onEventRegister"
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ button(@click="openModalProgrammatically") Открыть программно
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+```coffee
|
|
|
|
|
+methods:
|
|
|
|
|
+ openModalProgrammatically: ->
|
|
|
|
|
+ @currentEvent = this.getEventData()
|
|
|
|
|
+ this.$nextTick(() =>
|
|
|
|
|
+ @$refs.eventModal.open()
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ onModalClose: ->
|
|
|
|
|
+ debug.log "Модальное окно закрыто"
|
|
|
|
|
+
|
|
|
|
|
+ onEventRegister: (data) ->
|
|
|
|
|
+ # Обработка регистрации
|
|
|
|
|
+ this.registerUserForEvent(data.event, data.tickets)
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 4. Использование с кастомными слотами
|
|
|
|
|
+```pug
|
|
|
|
|
+event-detail-modal(:event="eventData" :show="isModalOpen")
|
|
|
|
|
+ template([header])
|
|
|
|
|
+ div(class="bg-gradient-to-r from-blue-600 to-purple-600 text-white p-6")
|
|
|
|
|
+ h1(class="text-2xl font-bold") {{ eventData.title }}
|
|
|
|
|
+ div(class="flex items-center space-x-2 mt-2")
|
|
|
|
|
+ icon(name="star" class="w-5 h-5")
|
|
|
|
|
+ span Премиум мероприятие
|
|
|
|
|
+
|
|
|
|
|
+ template([footer])
|
|
|
|
|
+ div(class="bg-gray-50 p-4 border-t")
|
|
|
|
|
+ div(class="flex justify-between items-center")
|
|
|
|
|
+ span(class="text-sm text-gray-600") Нужна помощь?
|
|
|
|
|
+ app-link(
|
|
|
|
|
+ to="/contacts"
|
|
|
|
|
+ class="text-blue-600 hover:text-blue-800 text-sm"
|
|
|
|
|
+ ) Связаться с нами
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 5. Интеграция с системой бронирования
|
|
|
|
|
+```pug
|
|
|
|
|
+event-detail-modal(
|
|
|
|
|
+ :event="event"
|
|
|
|
|
+ @register="handleBooking"
|
|
|
|
|
+ ref="bookingModal"
|
|
|
|
|
+)
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+```coffee
|
|
|
|
|
+methods:
|
|
|
|
|
+ handleBooking: (bookingData) ->
|
|
|
|
|
+ # Интеграция с системой бронирования
|
|
|
|
|
+ try
|
|
|
|
|
+ result = await this.$api.events.register(
|
|
|
|
|
+ eventId: bookingData.event._id
|
|
|
|
|
+ tickets: bookingData.tickets
|
|
|
|
|
+ userInfo: this.userData
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ if result.success
|
|
|
|
|
+ this.showSuccessMessage("Регистрация успешна!")
|
|
|
|
|
+ this.$refs.bookingModal.close()
|
|
|
|
|
+ else
|
|
|
|
|
+ this.showErrorMessage(result.message)
|
|
|
|
|
+
|
|
|
|
|
+ catch error
|
|
|
|
|
+ debug.log "Ошибка бронирования: "+error
|
|
|
|
|
+ this.showErrorMessage("Ошибка при регистрации")
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Особенности работы
|
|
|
|
|
+
|
|
|
|
|
+### Мультиязычность
|
|
|
|
|
+Компонент автоматически обрабатывает мультиязычные массивы:
|
|
|
|
|
+- `title`, `content`, `excerpt` - текстовые поля
|
|
|
|
|
+- `location`, `organizer`, `performers` - информация о месте и участниках
|
|
|
|
|
+- `age_restriction` - возрастные ограничения
|
|
|
|
|
+
|
|
|
|
|
+### Адаптивный дизайн
|
|
|
|
|
+- Mobile-first подход
|
|
|
|
|
+- Оптимизация для различных размеров экранов
|
|
|
|
|
+- Горизонтальная прокрутка галереи на мобильных устройствах
|
|
|
|
|
+
|
|
|
|
|
+### Галерея изображений
|
|
|
|
|
+- Поддержка multiple изображений
|
|
|
|
|
+- Lightbox-просмотр при клике
|
|
|
|
|
+- Оптимизированная загрузка изображений
|
|
|
|
|
+
|
|
|
|
|
+### Система бронирования
|
|
|
|
|
+- Валидация количества билетов
|
|
|
|
|
+- Проверка доступности
|
|
|
|
|
+- Визуальная обратная связь
|
|
|
|
|
+
|
|
|
|
|
+## Стили и кастомизация
|
|
|
|
|
+
|
|
|
|
|
+### CSS-переменные для кастомизации
|
|
|
|
|
+```styl
|
|
|
|
|
+.event-modal
|
|
|
|
|
+ --modal-bg: theme('colors.white')
|
|
|
|
|
+ --modal-border: theme('colors.gray.200')
|
|
|
|
|
+ --primary-color: theme('colors.blue.600')
|
|
|
|
|
+ --success-color: theme('colors.green.600')
|
|
|
|
|
+ --error-color: theme('colors.red.600')
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Кастомные темы
|
|
|
|
|
+```pug
|
|
|
|
|
+event-detail-modal.event-modal--custom-theme(:event="eventData")
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+```styl
|
|
|
|
|
+.event-modal--custom-theme
|
|
|
|
|
+ --modal-bg: #1a202c
|
|
|
|
|
+ --modal-border: #2d3748
|
|
|
|
|
+ --primary-color: #9f7aea
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Интеграция с аналитикой
|
|
|
|
|
+
|
|
|
|
|
+### Отслеживание событий
|
|
|
|
|
+```coffee
|
|
|
|
|
+# В родительском компоненте
|
|
|
|
|
+methods:
|
|
|
|
|
+ handleModalOpen: (event) ->
|
|
|
|
|
+ analytics.track('event_modal_opened', {
|
|
|
|
|
+ event_id: event._id
|
|
|
|
|
+ event_title: event.title
|
|
|
|
|
+ category: event.category
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ handleRegistration: (data) ->
|
|
|
|
|
+ analytics.track('event_registration_started', {
|
|
|
|
|
+ event_id: data.event._id
|
|
|
|
|
+ ticket_count: data.tickets
|
|
|
|
|
+ })
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Best Practices
|
|
|
|
|
+
|
|
|
|
|
+### 1. Загрузка данных
|
|
|
|
|
+```coffee
|
|
|
|
|
+# Правильно - предзагрузка данных
|
|
|
|
|
+openEventModal: (eventId) ->
|
|
|
|
|
+ try
|
|
|
|
|
+ eventData = await AppDB.getDocumentById(eventId)
|
|
|
|
|
+ @selectedEvent = eventData
|
|
|
|
|
+ @showModal = true
|
|
|
|
|
+ catch error
|
|
|
|
|
+ debug.log "Ошибка загрузки мероприятия: "+error
|
|
|
|
|
+
|
|
|
|
|
+# Неправильно - открытие до загрузки данных
|
|
|
|
|
+openEventModal: (eventId) ->
|
|
|
|
|
+ @showModal = true # Модальное окно откроется пустым
|
|
|
|
|
+ # затем загрузка данных...
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 2. Обработка ошибок
|
|
|
|
|
+```coffee
|
|
|
|
|
+methods:
|
|
|
|
|
+ handleRegistration: (data) ->
|
|
|
|
|
+ try
|
|
|
|
|
+ await this.processRegistration(data)
|
|
|
|
|
+ this.showSuccessMessage("Успешная регистрация!")
|
|
|
|
|
+ catch error
|
|
|
|
|
+ debug.log "Ошибка регистрации: "+error
|
|
|
|
|
+ this.showErrorMessage("Ошибка при регистрации")
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 3. Доступность
|
|
|
|
|
+```pug
|
|
|
|
|
+//- Правильно - с семантической разметкой
|
|
|
|
|
+event-detail-modal(
|
|
|
|
|
+ :event="eventData"
|
|
|
|
|
+ aria-labelledby="event-modal-title"
|
|
|
|
|
+ aria-describedby="event-modal-description"
|
|
|
|
|
+)
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 4. Производительность
|
|
|
|
|
+```pug
|
|
|
|
|
+//- Lazy loading модального окна
|
|
|
|
|
+event-detail-modal(
|
|
|
|
|
+ v-if="showModal"
|
|
|
|
|
+ :event="eventData"
|
|
|
|
|
+ @close="showModal = false"
|
|
|
|
|
+)
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Отладка и разработка
|
|
|
|
|
+
|
|
|
|
|
+### Логирование событий
|
|
|
|
|
+```coffee
|
|
|
|
|
+# В родительском компоненте
|
|
|
|
|
+mounted: ->
|
|
|
|
|
+ EventBus.on 'open_event_modal', (eventData) ->
|
|
|
|
|
+ debug.log "Открытие модального окна мероприятия: "+eventData._id
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Валидация props
|
|
|
|
|
+```coffee
|
|
|
|
|
+# В дочерних компонентах при использовании
|
|
|
|
|
+props:
|
|
|
|
|
+ eventData:
|
|
|
|
|
+ type: Object
|
|
|
|
|
+ required: true
|
|
|
|
|
+ validator: (value) ->
|
|
|
|
|
+ return value && value._id && value.event_data
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+Компонент EventDetailModal предоставляет полнофункциональное решение для отображения детальной информации о мероприятиях с поддержкой мультиязычности, адаптивным дизайном и интеграцией с системой бронирования.
|