|
|
@@ -1,243 +1,124 @@
|
|
|
-# app/pages/Events/index.coffee
|
|
|
-document.head.insertAdjacentHTML('beforeend','<style type="text/tailwindcss" page="Events">'+stylFns['app/pages/Events/index.styl']+'</style>')
|
|
|
+document.head.insertAdjacentHTML('beforeend','<style type="text/tailwindcss">'+stylFns['app/pages/Events/index.styl']+'</style>')
|
|
|
|
|
|
module.exports =
|
|
|
- name: 'Events'
|
|
|
- render: (new Function '_ctx', '_cache', renderFns['app/pages/Events/index.pug'])()
|
|
|
- data: ->
|
|
|
- allEvents: [
|
|
|
- {
|
|
|
- id: 1
|
|
|
- title: 'Концерт симфонического оркестра'
|
|
|
- date: '2025-10-15'
|
|
|
- time: '19:00'
|
|
|
- description: 'Произведения Чайковского и Рахманинова в исполнении Национального симфонического оркестра под руководством маэстро Фирдавса Абдурахмонова. Незабываемый вечер классической музыки в акустике мирового уровня.'
|
|
|
- image: 'https://avatars.mds.yandex.net/get-altay/9822373/2a0000019377c5d52c95d3175340aab4a35a/XXL_height'
|
|
|
- category: 'classical'
|
|
|
- price: 50
|
|
|
- venue: 'Большой зал'
|
|
|
- duration: '2 часа 30 минут'
|
|
|
- ageRestriction: '12+'
|
|
|
- availableTickets: 45
|
|
|
- }
|
|
|
- {
|
|
|
- id: 2
|
|
|
- title: 'Вечер таджикской народной музыки'
|
|
|
- date: '2025-10-20'
|
|
|
- time: '18:30'
|
|
|
- description: 'Выступление фольклорного ансамбля "Шашмаком" с программой традиционных мелодий и танцев. Погрузитесь в богатую культурную традицию Таджикистана.'
|
|
|
- image: 'https://avatars.mds.yandex.net/get-altay/9822373/2a0000019377c5d52c95d3175340aab4a35a/XXL_height'
|
|
|
- category: 'folk'
|
|
|
- price: 30
|
|
|
- venue: 'Малый зал'
|
|
|
- duration: '2 часа'
|
|
|
- ageRestriction: '6+'
|
|
|
- availableTickets: 28
|
|
|
- }
|
|
|
- {
|
|
|
- id: 3
|
|
|
- title: 'Джазовый фестиваль "Borbad Jazz"'
|
|
|
- date: '2025-10-25'
|
|
|
- time: '20:00'
|
|
|
- description: 'Международные джазовые коллективы из Европы и Азии в уникальной акустике зала. Три дня незабываемой музыки от лучших джазменов мира.'
|
|
|
- image: 'https://avatars.mds.yandex.net/get-altay/9822373/2a0000019377c5d52c95d3175340aab4a35a/XXL_height'
|
|
|
- category: 'jazz'
|
|
|
- price: 70
|
|
|
- venue: 'Большой зал'
|
|
|
- duration: '3 часа'
|
|
|
- ageRestriction: '16+'
|
|
|
- availableTickets: 15
|
|
|
- }
|
|
|
- {
|
|
|
- id: 4
|
|
|
- title: 'Концерт популярной музыки'
|
|
|
- date: '2025-10-28'
|
|
|
- time: '19:30'
|
|
|
- description: 'Лучшие поп-исполнители Таджикистана представят новые хиты и классические композиции. Энергичное шоу с современной хореографией.'
|
|
|
- image: 'https://avatars.mds.yandex.net/get-altay/9822373/2a0000019377c5d52c95d3175340aab4a35a/XXL_height'
|
|
|
- category: 'pop'
|
|
|
- price: 45
|
|
|
- venue: 'Большой зал'
|
|
|
- duration: '2 часа 15 минут'
|
|
|
- ageRestriction: '12+'
|
|
|
- availableTickets: 67
|
|
|
- }
|
|
|
- {
|
|
|
- id: 5
|
|
|
- title: 'Оперный гала-концерт'
|
|
|
- date: '2025-11-02'
|
|
|
- time: '18:00'
|
|
|
- description: 'Известные оперные певцы исполнят арии из мировых шедевров оперного искусства. Вечер великой музыки в исполнении мастеров.'
|
|
|
- image: 'https://avatars.mds.yandex.net/get-altay/9822373/2a0000019377c5d52c95d3175340aab4a35a/XXL_height'
|
|
|
- category: 'classical'
|
|
|
- price: 80
|
|
|
- venue: 'Большой зал'
|
|
|
- duration: '2 часа 45 минут'
|
|
|
- ageRestriction: '12+'
|
|
|
- availableTickets: 23
|
|
|
- }
|
|
|
- {
|
|
|
- id: 6
|
|
|
- title: 'Танцевальное шоу "Восточные ритмы"'
|
|
|
- date: '2025-11-05'
|
|
|
- time: '19:00'
|
|
|
- description: 'Традиционные и современные танцевальные коллективы представят красочное шоу. Яркие костюмы, зажигательная музыка и мастерство танцовщиков.'
|
|
|
- image: 'https://avatars.mds.yandex.net/get-altay/9822373/2a0000019377c5d52c95d3175340aab4a35a/XXL_height'
|
|
|
- category: 'dance'
|
|
|
- price: 35
|
|
|
- venue: 'Большой зал'
|
|
|
- duration: '2 часа 30 минут'
|
|
|
- ageRestriction: '6+'
|
|
|
- availableTickets: 89
|
|
|
- }
|
|
|
- {
|
|
|
- id: 7
|
|
|
- title: 'Камерная музыка: Струнный квартет'
|
|
|
- date: '2025-11-08'
|
|
|
- time: '17:00'
|
|
|
- description: 'Изысканная программа камерной музыки в исполнении ведущего струнного квартета страны. Интимная атмосфера и тонкое звучание.'
|
|
|
- image: 'https://avatars.mds.yandex.net/get-altay/9822373/2a0000019377c5d52c95d3175340aab4a35a/XXL_height'
|
|
|
- category: 'classical'
|
|
|
- price: 40
|
|
|
- venue: 'Камерный зал'
|
|
|
- duration: '1 час 45 минут'
|
|
|
- ageRestriction: '12+'
|
|
|
- availableTickets: 34
|
|
|
- }
|
|
|
- {
|
|
|
- id: 8
|
|
|
- title: 'Фестиваль современной музыки'
|
|
|
- date: '2025-11-12'
|
|
|
- time: '20:30'
|
|
|
- description: 'Экспериментальные проекты и инновационные музыкальные направления. Откройте для себя новые грани музыкального искусства.'
|
|
|
- image: 'https://avatars.mds.yandex.net/get-altay/9822373/2a0000019377c5d52c95d3175340aab4a35a/XXL_height'
|
|
|
- category: 'experimental'
|
|
|
- price: 55
|
|
|
- venue: 'Малый зал'
|
|
|
- duration: '3 часа'
|
|
|
- ageRestriction: '18+'
|
|
|
- availableTickets: 18
|
|
|
- }
|
|
|
- ]
|
|
|
- displayedEvents: []
|
|
|
- selectedEvent: null
|
|
|
- showEventModal: false
|
|
|
- loading: false
|
|
|
- currentPage: 1
|
|
|
- pageSize: 6
|
|
|
- eventFilters: [
|
|
|
- {
|
|
|
- key: 'category'
|
|
|
- label: 'Категория'
|
|
|
- type: 'select'
|
|
|
- options: [
|
|
|
- { value: 'all', label: 'Все категории' }
|
|
|
- { value: 'classical', label: 'Классическая музыка' }
|
|
|
- { value: 'folk', label: 'Фольклор' }
|
|
|
- { value: 'jazz', label: 'Джаз' }
|
|
|
- { value: 'pop', label: 'Поп-музыка' }
|
|
|
- { value: 'dance', label: 'Танцевальное шоу' }
|
|
|
- { value: 'experimental', label: 'Экспериментальная музыка' }
|
|
|
+ name: 'Events'
|
|
|
+ render: (new Function '_ctx', '_cache', renderFns['app/pages/Events/index.pug'])()
|
|
|
+ data: ->
|
|
|
+ allEvents: []
|
|
|
+ displayedEvents: []
|
|
|
+ loading: false
|
|
|
+ currentPage: 1
|
|
|
+ pageSize: 9
|
|
|
+ eventFilters: [
|
|
|
+ {
|
|
|
+ key: 'category'
|
|
|
+ label: 'Категория'
|
|
|
+ type: 'select'
|
|
|
+ options: [
|
|
|
+ { value: 'all', label: 'Все категории' }
|
|
|
+ { value: 'classical', label: 'Классическая музыка' }
|
|
|
+ { value: 'folk', label: 'Фольклор' }
|
|
|
+ { value: 'jazz', label: 'Джаз' }
|
|
|
+ { value: 'pop', label: 'Поп-музыка' }
|
|
|
+ { value: 'dance', label: 'Танцевальное шоу' }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ {
|
|
|
+ key: 'venue'
|
|
|
+ label: 'Зал'
|
|
|
+ type: 'select'
|
|
|
+ options: [
|
|
|
+ { value: 'all', label: 'Все залы' }
|
|
|
+ { value: 'Большой зал', label: 'Большой зал' }
|
|
|
+ { value: 'Малый зал', label: 'Малый зал' }
|
|
|
+ { value: 'Камерный зал', label: 'Камерный зал' }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ {
|
|
|
+ key: 'priceRange'
|
|
|
+ label: 'Цена'
|
|
|
+ type: 'range'
|
|
|
+ options: [
|
|
|
+ { value: 'all', label: 'Любая цена' }
|
|
|
+ { value: 'budget', label: 'До 50 сомони' }
|
|
|
+ { value: 'medium', label: '50-100 сомони' }
|
|
|
+ { value: 'premium', label: 'Выше 100 сомони' }
|
|
|
+ ]
|
|
|
+ }
|
|
|
]
|
|
|
- }
|
|
|
- {
|
|
|
- key: 'venue'
|
|
|
- label: 'Зал'
|
|
|
- type: 'select'
|
|
|
- options: [
|
|
|
- { value: 'all', label: 'Все залы' }
|
|
|
- { value: 'Большой зал', label: 'Большой зал' }
|
|
|
- { value: 'Малый зал', label: 'Малый зал' }
|
|
|
- { value: 'Камерный зал', label: 'Камерный зал' }
|
|
|
+ sortOptions: [
|
|
|
+ { value: 'date-asc', label: 'По дате (сначала ближайшие)' }
|
|
|
+ { value: 'date-desc', label: 'По дате (сначала дальние)' }
|
|
|
+ { value: 'price-asc', label: 'По цене (сначала дешевые)' }
|
|
|
+ { value: 'price-desc', label: 'По цене (сначала дорогие)' }
|
|
|
+ { value: 'name-asc', label: 'По названию (А-Я)' }
|
|
|
+ { value: 'name-desc', label: 'По названию (Я-А)' }
|
|
|
]
|
|
|
- }
|
|
|
- {
|
|
|
- key: 'priceRange'
|
|
|
- label: 'Цена, сомони'
|
|
|
- type: 'range'
|
|
|
- min: 0
|
|
|
- max: 100
|
|
|
- step: 5
|
|
|
- }
|
|
|
- ]
|
|
|
- sortOptions: [
|
|
|
- { value: 'date-asc', label: 'По дате (сначала ближайшие)' }
|
|
|
- { value: 'date-desc', label: 'По дате (сначала дальние)' }
|
|
|
- { value: 'price-asc', label: 'По цене (сначала дешевые)' }
|
|
|
- { value: 'price-desc', label: 'По цене (сначала дорогие)' }
|
|
|
- { value: 'name-asc', label: 'По названию (А-Я)' }
|
|
|
- { value: 'name-desc', label: 'По названию (Я-А)' }
|
|
|
- { value: 'popularity', label: 'По популярности' }
|
|
|
- ]
|
|
|
- categoryLabels:
|
|
|
- classical: 'Классика'
|
|
|
- folk: 'Фольклор'
|
|
|
- jazz: 'Джаз'
|
|
|
- pop: 'Поп'
|
|
|
- dance: 'Танцы'
|
|
|
- experimental: 'Эксперимент'
|
|
|
+ categoryLabels:
|
|
|
+ classical: 'Классика'
|
|
|
+ folk: 'Фольклор'
|
|
|
+ jazz: 'Джаз'
|
|
|
+ pop: 'Поп'
|
|
|
+ dance: 'Танцы'
|
|
|
|
|
|
- computed:
|
|
|
- hasMoreEvents: ->
|
|
|
- @currentPage * @pageSize < @allEvents.length
|
|
|
+ computed:
|
|
|
+ hasMoreEvents: ->
|
|
|
+ @currentPage * @pageSize < @allEvents.length
|
|
|
|
|
|
- mounted: ->
|
|
|
- @displayedEvents = @allEvents.slice(0, @pageSize)
|
|
|
+ mounted: ->
|
|
|
+ @loadEvents()
|
|
|
+ @displayedEvents = @allEvents.slice(0, @pageSize)
|
|
|
|
|
|
- methods:
|
|
|
- handleFilterChange: (filteredItems) ->
|
|
|
- @displayedEvents = filteredItems
|
|
|
- @currentPage = 1
|
|
|
+ methods:
|
|
|
+ loadEvents: ->
|
|
|
+ @loading = true
|
|
|
+ @allEvents = _.getEvents() || []
|
|
|
+
|
|
|
+ if @allEvents.length == 0
|
|
|
+ setTimeout =>
|
|
|
+ @loadEvents()
|
|
|
+ , 500
|
|
|
+ else
|
|
|
+ @loading = false
|
|
|
|
|
|
- # Стало (правильно)
|
|
|
- showEventDetails: (event) ->
|
|
|
- openModal('EventDetailModal', { event: event })
|
|
|
-
|
|
|
- handleTicketBooking: (event) ->
|
|
|
- debug.log "Обработка покупки билета на: "+event.title
|
|
|
- openModal('SuccessModal', {
|
|
|
- title: 'Билет забронирован!'
|
|
|
- content: "Вы успешно забронировали билет на \""+event.title+"\". Подробности отправлены на вашу почту."
|
|
|
- })
|
|
|
+ handleFilterChange: (filteredItems) ->
|
|
|
+ @displayedEvents = filteredItems
|
|
|
+ @currentPage = 1
|
|
|
|
|
|
- bookTicket: (event) ->
|
|
|
- # Открываем модальное окно покупки билетов
|
|
|
- @selectedEvent = event
|
|
|
- @showEventModal = true
|
|
|
- # Можно также сразу перейти к покупке
|
|
|
- debug.log 'Бронирование билета на:'+ event.title
|
|
|
+ openEventModal: (event) ->
|
|
|
+ _.openModal('EventDetailModal', { event: event })
|
|
|
|
|
|
+ loadMoreEvents: ->
|
|
|
+ @loading = true
|
|
|
+ setTimeout =>
|
|
|
+ @currentPage += 1
|
|
|
+ startIndex = 0
|
|
|
+ endIndex = @currentPage * @pageSize
|
|
|
+ @displayedEvents = @allEvents.slice(startIndex, endIndex)
|
|
|
+ @loading = false
|
|
|
+ , 1000
|
|
|
|
|
|
- loadMoreEvents: ->
|
|
|
- @loading = true
|
|
|
- # Имитация загрузки
|
|
|
- setTimeout =>
|
|
|
- @currentPage += 1
|
|
|
- startIndex = 0
|
|
|
- endIndex = @currentPage * @pageSize
|
|
|
- @displayedEvents = @allEvents.slice(startIndex, endIndex)
|
|
|
- @loading = false
|
|
|
- , 1000
|
|
|
+ resetFilters: ->
|
|
|
+ @displayedEvents = @allEvents.slice(0, @pageSize)
|
|
|
+ @currentPage = 1
|
|
|
|
|
|
- resetFilters: ->
|
|
|
- @displayedEvents = @allEvents.slice(0, @pageSize)
|
|
|
- @currentPage = 1
|
|
|
+ getCategoryLabel: (category) ->
|
|
|
+ @categoryLabels[category] || category
|
|
|
|
|
|
- getCategoryLabel: (category) ->
|
|
|
- @categoryLabels[category] || category
|
|
|
+ getCategoryBadgeClass: (category) ->
|
|
|
+ classes =
|
|
|
+ classical: 'bg-blue-500'
|
|
|
+ folk: 'bg-green-500'
|
|
|
+ jazz: 'bg-purple-500'
|
|
|
+ pop: 'bg-pink-500'
|
|
|
+ dance: 'bg-orange-500'
|
|
|
+
|
|
|
+ classes[category] || 'bg-gray-500'
|
|
|
|
|
|
- getCategoryBadgeClass: (category) ->
|
|
|
- classes =
|
|
|
- classical: 'bg-blue-500'
|
|
|
- folk: 'bg-green-500'
|
|
|
- jazz: 'bg-purple-500'
|
|
|
- pop: 'bg-pink-500'
|
|
|
- dance: 'bg-orange-500'
|
|
|
- experimental: 'bg-indigo-500'
|
|
|
-
|
|
|
- classes[category] || 'bg-gray-500'
|
|
|
-
|
|
|
- formatDate: (dateString) ->
|
|
|
- date = new Date(dateString)
|
|
|
- options = { day: 'numeric', month: 'short' }
|
|
|
- date.toLocaleDateString('ru-RU', options)
|
|
|
+ formatDate: (dateString) ->
|
|
|
+ try
|
|
|
+ date = new Date(dateString)
|
|
|
+ options = { day: 'numeric', month: 'short' }
|
|
|
+ date.toLocaleDateString('ru-RU', options)
|
|
|
+ catch
|
|
|
+ dateString
|