| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- # обязательно подключение глобальных массивов
- globalThis.renderFns = require 'pug.json'
- globalThis.stylFns = require 'styl.json'
- # подключение мета информации (строго в данном фиде)
- document.head.insertAdjacentHTML 'beforeend','<meta charset="UTF-8">'
- document.head.insertAdjacentHTML 'beforeend','<meta name="viewport" content="width=device-width, initial-scale=1.0">'
- document.head.insertAdjacentHTML('beforeend','<title>Кохи Борбад - Концертный зал Душанбе</title>')
- # Настройка tailwind
- tailwind.config = require 'tailwind.config.js'
- # подключение основных стилей
- ## tailwind
- document.head.insertAdjacentHTML('beforeend','<style type="text/tailwindcss" page="main">'+stylFns['main.css']+'</style>')
- ## базовой стиль приложения
- document.head.insertAdjacentHTML('beforeend','<style type="text/tailwindcss" page="root">'+stylFns['app/temp.styl']+'</style>')
- # Создаем глобальную шину событий
- class AppEventBus
- constructor: ->
- @events = {}
-
- on: (event, callback) ->
- if !@events[event]
- @events[event] = []
- @events[event].push(callback)
-
- emit: (event, data) ->
- if @events[event]
- for callback in @events[event]
- try
- callback(data)
- catch error
- debug.log "Event bus error: " + error
-
- off: (event, callback) ->
- if @events[event]
- @events[event] = @events[event].filter (cb) -> cb != callback
- # Создаем глобально
- globalThis.EventBus = new AppEventBus()
- # CouchDB сервис
- class CouchDBService
- constructor: ->
- @baseUrl = 'http://localhost:5984'
- @dbName = 'kohi_borbad_events'
- @headers =
- 'Content-Type': 'application/json'
- 'Authorization': 'Basic ' + btoa('admin:password')
- getAllEvents: ->
- try
- response = await fetch("#{@baseUrl}/#{@dbName}/_all_docs?include_docs=true", {
- method: 'GET'
- headers: @headers
- })
-
- if response.ok
- data = await response.json()
- events = data.rows.map (row) -> row.doc
- return events.filter (event) -> !event._id.startsWith('_design/')
- else
- debug.log "Ошибка получения мероприятий: "+response.statusText
- return []
- catch error
- debug.log "Ошибка подключения к CouchDB: "+error
- return []
- getFeaturedEvents: ->
- events = await @getAllEvents()
- events
- .filter (event) -> event.isFeatured || false
- .slice(0, 6)
- getSliderEvents: ->
- events = await @getAllEvents()
- events
- .filter (event) -> event.inSlider || false
- .map (event) ->
- id: event._id
- image: event.image || '/images/default-event.jpg'
- title: event.title
- description: event.shortDescription || event.description
- cta: event.cta || 'Подробнее'
- category: event.category
- # Маршруты
- routes = [
- { path: '/', component: require 'app/pages/Home' }
- { path: '/events', component: require 'app/pages/Events' }
- { path: '/about', component: require 'app/pages/About' }
- { path: '/contacts', component: require 'app/pages/Contacts' }
- ]
- # Глобальное определение vuejs приложения
- app = Vue.createApp
- name: 'app'
- data: ()->
- return
- theme: 'light'
- appState:
- events: []
- featuredEvents: []
- sliderEvents: []
- loading: true
- error: null
- modalState:
- currentModal: null
- modalProps: {}
- couchDBService: new CouchDBService()
- beforeMount: ()->
- debug.log "start beforeMount"
- # определение контекста vuejs приложения как глобальной переменной _
- globalThis._ = @
- render: (new Function '_ctx', '_cache', renderFns['app/temp.pug'])()
- mounted: ->
- # Предзагрузка темы
- if localStorage.theme == 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)
- @theme = 'dark'
- document.documentElement.classList.add('dark')
- else
- @theme = 'light'
- document.documentElement.classList.remove('dark')
-
- # Загрузка данных из CouchDB
- await @loadEventsData()
-
- # Обработчик открытия модальных окон
- EventBus.on 'open-modal', (config) =>
- @modalState.currentModal = config.component
- @modalState.modalProps = config.props || {}
- methods:
- toggleTheme: ->
- @theme = if @theme == 'light' then 'dark' else 'light'
- localStorage.setItem 'theme', @theme
- document.documentElement.classList.toggle 'dark'
-
- loadEventsData: ->
- @appState.loading = true
- try
- [events, featuredEvents, sliderEvents] = await Promise.all([
- @couchDBService.getAllEvents()
- @couchDBService.getFeaturedEvents()
- @couchDBService.getSliderEvents()
- ])
-
- @appState.events = events
- @appState.featuredEvents = featuredEvents
- @appState.sliderEvents = sliderEvents
- @appState.error = null
-
- catch error
- debug.log "Ошибка загрузки данных: "+error
- @appState.error = 'Не удалось загрузить данные мероприятий'
- @loadTestData()
- finally
- @appState.loading = false
-
- loadTestData: ->
- # Тестовые данные на случай недоступности CouchDB
- @appState.events = [
- {
- _id: '1'
- title: 'Концерт симфонического оркестра'
- date: '2025-10-15'
- time: '19:00'
- description: 'Произведения Чайковского и Рахманинова в исполнении Национального симфонического оркестра'
- image: '/images/event-classical.jpg'
- category: 'classical'
- price: 50
- venue: 'Большой зал'
- duration: '2 часа 30 минут'
- ageRestriction: '12+'
- availableTickets: 45
- isFeatured: true
- inSlider: true
- shortDescription: 'Шедевры классической музыки'
- cta: 'Купить билеты'
- }
- {
- _id: '2'
- title: 'Вечер таджикской народной музыки'
- date: '2025-10-20'
- time: '18:30'
- description: 'Выступление фольклорного ансамбля "Шашмаком" с программой традиционных мелодий и танцев'
- image: '/images/event-folk.jpg'
- category: 'folk'
- price: 30
- venue: 'Малый зал'
- duration: '2 часа'
- ageRestriction: '6+'
- availableTickets: 28
- isFeatured: true
- inSlider: true
- shortDescription: 'Традиционные мелодии и танцы Таджикистана'
- cta: 'Узнать больше'
- }
- {
- _id: '3'
- title: 'Джазовый фестиваль "Borbad Jazz"'
- date: '2025-10-25'
- time: '20:00'
- description: 'Международные джазовые коллективы из Европы и Азии в уникальной акустике зала'
- image: '/images/event-jazz.jpg'
- category: 'jazz'
- price: 70
- venue: 'Большой зал'
- duration: '3 часа'
- ageRestriction: '16+'
- availableTickets: 15
- isFeatured: true
- inSlider: true
- shortDescription: 'Международные джазовые коллективы'
- cta: 'Смотреть расписание'
- }
- ]
- @appState.featuredEvents = @appState.events.filter((event) -> event.isFeatured).slice(0, 6)
- @appState.sliderEvents = @appState.events.filter((event) -> event.inSlider).map (event) ->
- id: event._id
- image: event.image
- title: event.title
- description: event.shortDescription
- cta: event.cta
- category: event.category
-
- getEvents: -> @appState.events
- getFeaturedEvents: -> @appState.featuredEvents
- getSliderEvents: -> @appState.sliderEvents
- isLoading: -> @appState.loading
- hasError: -> @appState.error
-
- closeModal: ->
- @modalState.currentModal = null
- @modalState.modalProps = {}
- components:
- 'themetoggle': require 'app/shared/ThemeToggle'
- 'multilevelmenu': require 'app/shared/MultiLevelMenu'
- 'imageslider': require 'app/shared/ImageSlider'
- 'modalwindow': require 'app/shared/ModalWindow'
- 'formvalidator': require 'app/shared/FormValidator'
- 'filtersort': require 'app/shared/FilterSort'
- 'eventdetailmodal': require 'app/shared/EventDetailModal'
- 'successmodal': require 'app/shared/SuccessModal'
- app.use(VueRouter.createRouter({
- routes: routes
- history: VueRouter.createWebHistory()
- scrollBehavior: (to, from, savedPosition) ->
- if savedPosition
- return savedPosition
- else
- return { x: 0, y: 0 }
- }))
- # Глобальные функции для работы с модальными окнами
- globalThis.openModal = (component, props = {}) ->
- EventBus.emit 'open-modal', { component, props }
- globalThis.closeModal = ->
- EventBus.emit 'close-modal'
- # подключаем в body ОБЯЗАТЕЛЬНО!!!
- app.mount('body')
- debug.log "Vue application initialized successfully"
|