# ZeenSchedule

Компонент ZeenSchedule

# Примеры:

Размеры:

ZeenSchedule

zeen-schedule-header-margin-bottom

zeen-schedule-container-max-width

zeen-schedule-arrows-width

zeen-schedule-col-padding-bottom

zeen-schedule-time-text-size

По умолчанию наследуется от main-large-size

zeen-schedule-time-line-height

zeen-schedule-time-font-weight

zeen-schedule-time-width

zeen-schedule-hall-border-radius

zeen-schedule-col-line-size

zeen-schedule-row-height

zeen-schedule-hall-text-size

По умолчанию наследуется от main-small-text

zeen-schedule-hall-line-height

zeen-schedule-hall-font-weight

zeen-schedule-hall-padding-vertical

zeen-schedule-hall-padding-horizontal

zeen-schedule-hall-arrow-size

zeen-schedule-hall-arrow-margin-left

zeen-schedule-online-img-size

zeen-schedule-card-height

Цвета:

zeen-schedule-background

По умолчанию наследуется от main-light

zeen-schedule-col-border

По умолчанию наследуется от gray-1

zeen-schedule-time-color

По умолчанию наследуется от main-color

zeen-schedule-time-color-done

По умолчанию наследуется от gray-2

zeen-schedule-col-line

По умолчанию наследуется от gray-1

zeen-schedule-online-line

По умолчанию наследуется от main-danger-color

zeen-schedule-online-img

По умолчанию наследуется от main-light

zeen-schedule-hall

По умолчанию наследуется от gray-1

zeen-schedule-hall-active

По умолчанию наследуется от main-transparent

zeen-schedule-hall-hover

По умолчанию наследуется от main-transparent

zeen-schedule-hall-text

По умолчанию наследуется от input-main-value-color

zeen-schedule-hall-text-active

По умолчанию наследуется от main-color

zeen-schedule-hall-arrow-color

Программа дня

Зал финансовой аналитики и диджитал безопасности
Зал дизайна и продуктивности
Зал 3
  • 11:00
  • 11:05
  • 11:10
  • 11:15
  • 11:20
  • 11:25
  • 11:30
  • 11:35
  • 11:40
  • 11:45
  • 11:50
  • 11:55
  • 12:00
  • 12:10
  • 12:15
  • 12:20
  • 12:25
  • 12:30
11:00-11:20

Формула лучшего КЦ: взболтать, но не смешивать

11:20-11:30

Диджитал-привлечение в корпоративном бизнесе. Есть ли место подвигу?

11:40-12:00

Формула лучшего КЦ: взболтать, но не смешивать

11:00-11:20

Диджитал-привлечение в корпоративном бизнесе. Есть ли место подвигу?

11:25-11:45

Формула лучшего КЦ: взболтать, но не смешивать

12:00-12:30

Диджитал-привлечение в корпоративном бизнесе. Есть ли место подвигу?

11:00-11:05

Перерыв

11:05-11:20

Диджитал-привлечение в корпоративном бизнесе. Есть ли место подвигу?

11:20-11:25

Формула лучшего КЦ: взболтать, но не смешивать

# props

Название Тип Обязательный По умолчанию Описание
streams Array + - Массив стримов со спичами и спикерами
activeStreamId String - '' id активной страницы зала
speechModalProps Object - - Пропсы для модалки speechModal
speechCardProps Object - - Пропсы для модалки ZeenScheduleCard
marginBeforeOnline Number - 50 Отступ от края окна после скролла слайдером до онлайн спича
timeRowStep Number - 5 Максимальное кол-во делений у карточки спича
scrollLimit Number - 2 Ограничение скролла по стрелкам относительно видимой ширины окна , ширина/scrollLimit
slideToggleBtnText Object - open: 'Показать всё', close: 'Скрыть' текст кнопки toggle
offSlideToggle Boolean - false отключить toggle
toggleProps Object - 615 пропсы ZeenSlideToggle
hallOffset Number - 24 верхний отступ от границы колонки
showOnlineLine Boolean - false отвечает за показ онлайн-линии
visibleHallsCount Number - 2 количество видимых залов

# emits

Название Описание
cardClick Срабатывает при клике по карточке передает объект с hall и speech
cardButtonClick Срабатывает при клике по кнопке карточки передает объект с hall и speech
hallClick Срабатывает при клике по залу передает объект с hall
watchSpeech Срабатывает при клике по "Смотреть" передает объект с hall и speech
addToPersonalSchedule Срабатывает при клике по "Добавить в расписание" передает объект с hall и speech
removeFromPersonalSchedule Срабатывает при клике по "Удалить из расписания" передает объект с hall и speech

# slots

Название Описание
title title блока
day-tab таб для дней
arrow-prev иконка слайдера
arrow-next иконка слайдера
hall-img картинка для зала
hall-arrow стрелка для зала
hall-tooltip tooltip для зала
popover контент для tooltip
online-line-icon иконка онлайн линии
slide-toggle-btn кнопка для toggle

# Source Code - исходный код компонента

<template lang="pug">
  section.zeen-schedule
    ZeenSpeechModal(
      name='ZeenSchedule'
      :speech='modalSpeech'
      :hall='modalHall'
      v-bind='speechModalProps'
      v-on='modalEvents'
    )
      template(v-for='(slot, slotName) in modalSlots' v-slot:[slotName]='params')
        slot(:name='`${modalPrefix}${slotName}`' v-bind='params')

    ZeenContainer
      .zeen-schedule__top
        slot(name='title')
        slot(name='top-btn')
        slot(name='day-tab')
    ZeenSlideToggle(:open='isOpen || offSlideToggle' v-bind='toggleProps' :closedHeight='closedHeight' )
      .zeen-schedule__container
        .zeen-schedule__arrows
          ZeenActionIcon(
            theme='button'
            @click='prev'
            :disabled='prevDisabled'
          )
            slot(name='arrow-prev')
              svg(
                width='100%'
                height='100%'
                viewBox='0 0 12 12'
                xmlns='http://www.w3.org/2000/svg'
              )
                path(
                  fill-rule='evenodd' clip-rule='evenodd' d='M7.35667 1.10026C6.94389 \
                  0.73334 6.31182 0.77052 5.9449 1.1833L2.25259 5.33715C1.9158 5.71603 1.9158 \
                  6.28699 2.25259 6.66588L5.9449 10.8197C6.31182 11.2325 6.94389 11.2697 7.35667 \
                  10.9028C7.76945 10.5359 7.80664 9.90378 7.43972 9.491L4.33795 6.00151L7.43972 \
                  2.51203C7.80664 2.09925 7.76945 1.46718 7.35667 1.10026Z')

          ZeenActionIcon(
            theme='button'
            @click='next'
            :disabled='nextDisabled'
          )
            slot(name='arrow-next')
              svg.zeen-schedule__arrow(
                width='100%'
                height='100%'
                viewBox='0 0 12 12'
                xmlns='http://www.w3.org/2000/svg'
              )
                path(
                  fill-rule='evenodd' clip-rule='evenodd' d='M7.35667 1.10026C6.94389 \
                  0.73334 6.31182 0.77052 5.9449 1.1833L2.25259 5.33715C1.9158 5.71603 1.9158 \
                  6.28699 2.25259 6.66588L5.9449 10.8197C6.31182 11.2325 6.94389 11.2697 7.35667 \
                  10.9028C7.76945 10.5359 7.80664 9.90378 7.43972 9.491L4.33795 6.00151L7.43972 \
                  2.51203C7.80664 2.09925 7.76945 1.46718 7.35667 1.10026Z')
        .zeen-schedule__hall(
          v-for='(hall, i) in streams'
          :key='hall.id'
          :class='activeHall[i]'
          :style='hallLinkStyles[i]'
          @click='hallClick(hall)'
        ) 
          slot(name='hall-img' :hall="hall")
          | {{hall.name}}
          slot(v-if="!hall.description" name='hall-arrow')
            svg.zeen-schedule__hall-arrow(
              width='100%'
              height='100%'
              viewBox='0 0 16 17'
              xmlns='http://www.w3.org/2000/svg'
            )
              path(
                fill-rule='evenodd'
                clip-rule='evenodd'
                d='M4.87471 14.3187C5.28749 14.6856 5.91956 14.6484 6.28648 14.2356L11.2096 8.69718C11.5463 \
                8.31829 11.5463 7.74734 11.2096 7.36845L6.28648 1.82999C5.91956 1.41721 5.28749 1.38003 4.87471 \
                1.74695C4.46193 2.11386 4.42475 2.74594 4.79166 3.15872L9.1242 8.03282L4.79166 12.9069C4.42475 \
                13.3197 4.46193 13.9518 4.87471 14.3187Z')

          slot(v-else name='hall-tooltip' :hall="hall")
            VPopover(placement='top' trigger='hover' offset='5')
              svg.zeen-schedule__hall-tooltip-icon(
                width="100%"
                height="100%"
                viewBox="0 0 12 12"
                xmlns="http://www.w3.org/2000/svg"
              )
                path(
                  fill-rule="evenodd"
                  clip-rule="evenodd"
                  d="M12 6C12 9.31371 9.31371 12 6 12C2.68629 12 0 9.31371 0 6C0 2.68629 2.68629 0 6 0C9.31371 \
                  0 12 2.68629 12 6ZM6.85686 3.42746C6.85686 3.90084 6.47311 4.2846 5.99972 4.2846C5.52633 \
                  4.2846 5.14258 3.90084 5.14258 3.42746C5.14258 2.95407 5.52633 2.57031 5.99972 2.57031C6.47311 \
                  2.57031 6.85686 2.95407 6.85686 3.42746ZM5.99972 5.14062C5.52633 5.14062 5.14258 5.52438 5.14258 \
                  5.99777V8.5692C5.14258 9.04258 5.52633 9.42634 5.99972 9.42634C6.47311 9.42634 6.85686 9.04258 6.85686 \
                  8.5692V5.99777C6.85686 5.52438 6.47311 5.14062 5.99972 5.14062Z")

              .zeen-schedule__popover(slot="popover") {{ hall.description }}

        .zeen-schedule__main(ref='schWidth')
          .swiper-slider
            .swiper-container(ref='slider')
              .swiper-wrapper(:style='{transform: `translateX(${customTranslate}px)`}')
                .swiper-slide
                  .zeen-schedule__wrapper
                    .zeen-schedule__online-line(
                      :style='onlineLeftSpacing'
                      v-if='onlineLeftSpacing'
                    )
                      span.zeen-schedule__online-circle
                        span.zeen-schedule__online-img
                          slot(name='online-line-icon')
                            svg(width='100%' height='100%' viewBox='0 0 16 14' xmlns='http://www.w3.org/2000/svg')
                              path(
                                d='M3.45301 1.16705C3.38625 1.09893 3.30672 1.04464 \
                                3.21896 1.00726C3.13121 0.969895 3.03695 0.950182 \
                                2.94158 0.949253C2.8462 0.948324 2.75158 0.966198 2.66312 \
                                1.00185C2.57465 1.03751 2.49408 1.09024 2.42601 1.15705C1.65596 \
                                1.92263 1.04512 2.83311 0.628737 3.83596C0.212354 4.83881 \
                                -0.00133197 5.91419 6.24671e-06 7.00005C-0.00124271 8.12757 \
                                0.22926 9.24331 0.677209 10.278C1.12516 11.3128 1.78099 12.2444 \
                                2.60401 13.015C2.74253 13.1431 2.9255 13.2121 3.11408 \
                                13.2074C3.30266 13.2028 3.48199 13.1248 3.61401 12.99C3.93001 \
                                12.674 3.89101 12.171 3.58701 11.88C2.9265 11.2506 2.4009 10.4934 \
                                2.04212 9.65447C1.68335 8.81556 1.49891 7.91246 1.50001 \
                                7.00005C1.50001 5.15405 2.24101 3.48005 3.44301 2.26205C3.73301 \
                                1.96705 3.76301 1.47705 3.45301 1.16705Z'
                              )
                              path(
                                d='M5.214 2.92927C5.0823 2.79376 4.90225 2.71598 4.71331 \
                                2.71298C4.52437 2.70998 4.34194 2.78201 4.206 2.91327C3.66483 \
                                3.44734 3.2353 4.08373 2.94242 4.78538C2.64953 5.48704 \
                                2.49914 6.23994 2.5 7.00027C2.5 8.69227 3.23 10.2133 4.393 \
                                11.2643C4.53025 11.3855 4.70889 11.4493 4.89191 11.4424C5.07492 \
                                11.4356 5.24826 11.3585 5.376 11.2273C5.704 10.8993 5.643 \
                                10.3833 5.335 10.0933C4.91281 9.6964 4.57651 9.21715 4.34689 \
                                8.68515C4.11727 8.15315 3.99921 7.57971 4 7.00027C4 5.85027 \
                                4.457 4.80627 5.2 4.04027C5.486 3.74627 5.533 3.24727 5.214 \
                                2.92927Z'
                              )
                              path(
                                d='M10.7858 2.92927C10.9175 2.79376 11.0976 2.71598 \
                                11.2865 2.71298C11.4755 2.70998 11.6579 2.78201 11.7938 \
                                2.91327C12.335 3.44734 12.7645 4.08373 13.0574 4.78538C13.3503 \
                                5.48704 13.5007 6.23994 13.4998 7.00027C13.4998 8.69227 12.7698 \
                                10.2133 11.6068 11.2643C11.4696 11.3855 11.2909 11.4493 11.1079 \
                                11.4424C10.9249 11.4356 10.7516 11.3585 10.6238 11.2273C10.2958 \
                                10.8993 10.3568 10.3833 10.6648 10.0933C11.087 9.6964 11.4233 \
                                9.21715 11.6529 8.68515C11.8826 8.15315 12.0006 7.57971 11.9998 \
                                7.00027C11.9998 5.85027 11.5428 4.80627 10.7998 4.04027C10.5138 \
                                3.74627 10.4668 3.24727 10.7858 2.92927Z'
                              )
                              path(
                                d='M12.5471 1.16705C12.6138 1.09893 12.6933 1.04464 \
                                12.7811 1.00726C12.8689 0.969895 12.9631 0.950182 \
                                13.0585 0.949253C13.1539 0.948324 13.2485 0.966198 \
                                13.3369 1.00185C13.4254 1.03751 13.506 1.09024 13.5741 \
                                1.15705C14.3441 1.92263 14.9549 2.83311 15.3713 3.83596C15.7877 \
                                4.83881 16.0014 5.91419 16.0001 7.00005C16.0013 8.12757 \
                                15.7708 9.24331 15.3229 10.278C14.8749 11.3128 14.2191 12.2444 \
                                13.3961 13.015C13.2575 13.1431 13.0746 13.2121 12.886 \
                                13.2074C12.6974 13.2028 12.5181 13.1248 12.3861 12.99C12.0701 \
                                12.674 12.1091 12.171 12.4141 11.88C13.0744 11.2505 13.5998 \
                                10.4933 13.9584 9.65435C14.317 8.81544 14.5013 7.91238 14.5001 \
                                7.00005C14.5001 5.15405 13.7591 3.48005 12.5571 2.26205C12.2671 \
                                1.96705 12.2371 1.47705 12.5471 1.16705Z'
                              )
                              path(
                                d='M8 5.5C7.60218 5.5 7.22064 5.65804 6.93934 5.93934C6.65804 \
                                6.22064 6.5 6.60218 6.5 7C6.5 7.39782 6.65804 7.77936 6.93934 \
                                8.06066C7.22064 8.34196 7.60218 8.5 8 8.5C8.39782 8.5 8.77936 \
                                8.34196 9.06066 8.06066C9.34196 7.77936 9.5 7.39782 9.5 7C9.5 \
                                6.60218 9.34196 6.22064 9.06066 5.93934C8.77936 5.65804 8.39782 \
                                5.5 8 5.5Z'
                              )
                    ul.zeen-schedule__col(ref='timeRow')
                      li.zeen-schedule__time(
                        v-for='(time, idx) in timeArray'
                        :key='idx'
                        ref='timeCol'
                        :class='timeRowDone[idx]'
                      ) {{time}}
                        span.zeen-schedule__time-line(ref='colLine')
                          svg(width='100%' height='100%' viewBox='0 0 1 730' fill='none' xmlns='http://www.w3.org/2000/svg')
                            line(x1='0.5' y1='-2.12908e-08' x2='0.50005' y2='1113' stroke-dasharray='6 10')
                    .zeen-schedule__row(v-for='(hall, i) in streams' :key='i' ref='cardsRow')
                      ZeenScheduleCard.zeen-schedule__card(
                        v-for='(speech, i) in hall.speeches'
                        :key='i'
                        :speech='speech'
                        :width='colWidthAndTimeArray'
                        :coords='timeCoordsAndTime'
                        :hall='hall'
                        v-bind='speechCardProps'
                        @cardClick='cardClick'
                        @cardButtonClick='cardButtonClick'
                        ref='cards'
                      )
                        template(v-for='(slot, slotName) in speechSlots' v-slot:[slotName]='params')
                          slot(:name='`${speechPrefix}${slotName}`' v-bind='params')
                .swiper-slide
                  span.zeen-schedule__span-slider
    .zeen-schedule__hide-button(v-if='!offSlideToggle' @click='isOpen = !isOpen')
      slot(name='slide-toggle-btn' :isOpen='isOpen')
        ZeenButton {{ isOpen ? slideToggleBtnText.close : slideToggleBtnText.open }}
          template(#rightIcon)
            svg.zeen-schedule__hide-button-svg(
              :class="{'zeen-schedule__hide-button-svg_open': isOpen}"
              width="100%"
              height="100%"
              viewBox="0 0 16 16"
              xmlns="http://www.w3.org/2000/svg"
            )
              path(
                fill-rule="evenodd"
                clip-rule="evenodd"
                d="M14.2853 4.8735C14.6522 5.28628 14.615 5.91835 14.2022 6.28527L8.66377 \
                11.2083C8.28489 11.5451 7.71393 11.5451 7.33505 11.2083L1.79658 6.28527C1.3838 \
                5.91835 1.34662 5.28628 1.71354 4.8735C2.08046 4.46071 2.71253 4.42353 3.12531 \
                4.79045L7.99941 9.12298L12.8735 4.79045C13.2863 4.42353 13.9184 4.46071 14.2853 4.8735Z"
              )

</template>

<script>
import Swiper from 'swiper/bundle'
import {VPopover} from 'v-tooltip'
import ZeenScheduleCard from '../../components/ZeenScheduleCard/ZeenScheduleCard'
import ZeenContainer from '../../components/ZeenContainer/ZeenContainer'
import ZeenActionIcon from '../../components/ZeenActionIcon/ZeenActionIcon'
import ZeenSpeechModal from '../../components/ZeenSpeechModal/ZeenSpeechModal'
import ZeenSlideToggle from '../../components/ZeenSlideToggle/ZeenSlideToggle'
import ZeenButton from '../../components/ZeenButton/ZeenButton'
import {getMinutes, toStringTime, getCurrentTime} from '../../helpers/timeConverter'
import {createEventsFor, createSlotsFor} from '../../helpers/createBlockData'

export default {
  name: 'ZeenSchedule',
  components: {
    ZeenScheduleCard,
    ZeenContainer,
    ZeenActionIcon,
    ZeenSpeechModal,
    ZeenSlideToggle,
    ZeenButton,
    VPopover,
  },
  props: {
    streams: {
      type: Array,
      require: true,
    },
    activeStreamId: {
      type: String,
      default: '',
    },
    timeFormat: {
      type: String,
      default: 'HH:mm',
    },
    marginBeforeOnline: {
      type: Number,
      default: 50,
    },
    speechModalProps: Object,
    speechCardProps: Object,
    timeRowStep: {
      type: Number,
      default: 5,
    },
    scrollLimit: {
      type: Number,
      default: 2,
    },
    slideToggleBtnText: {
      type: Object,
      default: () => {
        return {
          open: 'Показать всё',
          close: 'Скрыть',
        }
      },
    },
    offSlideToggle: {
      type: Boolean,
      default: true,
    },
    hallOffset: {
      type: Number,
      default: 24,
    },
    toggleProps: {
      type: Object,
    },
    showOnlineLine: {
      type: Boolean,
      default: false,
    },
    visibleHallsCount: {
      type: Number,
      default: 2,
    },
  },
  data() {
    return {
      slider: null,
      customTranslate: 0,
      diffBetweenSliderAndSch: 0,
      nextDisabled: false,
      prevDisabled: false,
      modalSpeech: null,
      modalHall: null,
      timeCoordsAndTime: [],
      colWidthAndTimeArray: null,
      coordsToHall: [],
      date: null,
      intervalToCurrentTime: null,
      isOpen: false,
    }
  },
  async mounted() {
    await this.$nextTick()
    this.slider = new Swiper(this.$refs.slider, {
      slidesPerView: 'auto',
      grabCursor: true,
      freeMode: true,
      virtualTranslate: true,
      on: {
        setTranslate: () => {
          this.customScroll()
        },
        touchEnd: () => {
          this.prevOrNextDisabled()
        },
        resize: () => {
          this.getDiffBetweenSliderAndSch()
          this.coordsToHallFunc()
        },
      },
    })
    this.updateSlider()
    this.date = getCurrentTime(this.timeFormat)
    this.intervalToCurrentTime = setInterval(() => {
      this.date = getCurrentTime(this.timeFormat)
    }, 60 * 1000)
  },
  destroyed() {
    this.slider?.destroy(true, true)
    if (this.intervalToCurrentTime) clearInterval(this.intervalToCurrentTime)
  },
  methods: {
    // Получаем координаты времени в временной шкале и само время
    getTimeCoordsAndTime() {
      const colCoord = this.$refs.timeRow?.getBoundingClientRect().left
      const coords = this.$refs.colLine?.map((line) => line?.getBoundingClientRect().right - colCoord + 12)
      const coordsWithTime = coords?.map((coord, index) => {
        return {
          coord,
          time: this.timeArray[index],
        }
      })
      this.timeCoordsAndTime = coordsWithTime ?? []
    },
    // Достаем ширину колонки времени и весь массив временой шкалы
    getColWidthAndTimeArray() {
      this.colWidthAndTimeArray = {
        width: this.$refs?.timeCol?.[0]?.clientWidth,
        timeArray: this.timeArray,
      }
    },
    async updateSlider() {
      await this.$nextTick()
      this.slider.update()
      this.getDiffBetweenSliderAndSch()
      this.getTimeCoordsAndTime()
      this.getColWidthAndTimeArray()
      this.coordsToHallFunc()
      this.scrollToOnline()
    },
    // Кастом для слайдера кнопка next
    next() {
      this.slider.translate = this.slider.translate - this.getWidthToSlide()
      this.slider.translateTo(this.slider.translate, 250, false)
      this.prevOrNextDisabled()
    },
    // Кастом для слайдера кнопка prev
    prev() {
      this.slider.translate = this.slider.translate + this.getWidthToSlide()
      this.slider.translateTo(this.slider.translate, 250, false)
      this.prevOrNextDisabled()
    },
    // Ширина на которую будет произведен скролл
    getWidthToSlide() {
      return this.$refs.schWidth.clientWidth / this.scrollLimit
    },
    prevOrNextDisabled() {
      this.nextDisabled = this.slider.translate <= -this.diffBetweenSliderAndSch
      this.prevDisabled = this.slider.translate >= 0
    },
    // Разница между шириной слайдера и секции
    getDiffBetweenSliderAndSch() {
      if (!this.slider || !this.$refs.schWidth) return
      const sliderWidth = this.slider.width
      const schWidth = this.$refs.schWidth.clientWidth
      this.diffBetweenSliderAndSch = sliderWidth > schWidth ? sliderWidth - schWidth : 0
    },
    // Скролл до онлайн карточки
    async scrollToOnline() {
      await this.$nextTick()
      if (this.onlineCardId) {
        const firstOnlineCardPosition = this.$refs.cards?.find((card) => card.speech.id === this.onlineCardId)?.position
        this.slider.translateTo(-firstOnlineCardPosition + this.marginBeforeOnline, 250, false)
      }
    },
    // Кастомный скролл для слайдера
    customScroll() {
      if (!this.slider) return
      if (this.slider.translate <= -this.diffBetweenSliderAndSch) {
        this.slider.translate = -this.diffBetweenSliderAndSch
        this.customTranslate = -this.diffBetweenSliderAndSch
      } else {
        this.customTranslate = this.slider.translate
      }
    },
    cardClick(data) {
      this.$vfm.show('ZeenSchedule')
      this.modalSpeech = data.speech
      this.modalHall = data.hall
      this.$emit('cardClick', data)
    },
    cardButtonClick(data) {
      if (data.speech.status === 'hold') {
        this.$vfm.show('ZeenSchedule')
        this.modalSpeech = data.speech
        this.modalHall = data.hall
        this.$emit('cardButtonClickHold', data)
      } else {
        this.$emit('cardButtonClick', data)
      }
    },
    hallClick(data) {
      this.$emit('hallClick', data)
    },
    watchSpeech(data) {
      this.$emit('watchSpeech', data)
    },
    addToPersonalSchedule(data) {
      this.$emit('addToPersonalSchedule', data)
    },
    removeFromPersonalSchedule(data) {
      this.$emit('removeFromPersonalSchedule', data)
    },
    coordsToHallFunc() {
      const col = this.$refs.timeRow?.getBoundingClientRect().top
      const hall = this.$refs.cardsRow?.map((row) => {
        return row?.getBoundingClientRect().top - col + this.hallOffset
      })
      this.coordsToHall = hall ?? []
    },
  },
  computed: {
    // получаем координаты для линии показывающее текущее время
    onlineLineCoords() {
      const timeColWidthAndDiff = this.timeArray.map((time, i) => {
        if (i >= this.timeArray.length - 1) return null
        const diff = getMinutes(this.timeArray[i + 1]) - getMinutes(time)
        return {
          width: this.colWidthAndTimeArray?.width / diff,
          diff,
        }
      })
      let now = getMinutes(this.date) - this.beginTime
      let coord = this.colWidthAndTimeArray?.width * 0.25
      timeColWidthAndDiff.forEach((item) => {
        switch (true) {
          case now > item?.diff:
            coord += item?.diff * item?.width
            break
          case now > 0:
            coord += now * item?.width
            break
        }
        now -= item?.diff
      })
      return coord
    },
    // получаем массив для временной шкалы
    timeArray() {
      let speechesTime = this.speechesTime
      // Дополнительное время для временной шкалы
      this.speechesTimeBeginEnd.forEach((speech) => {
        // Разница между началом спича и окончанием
        let diff = speech.time_end - speech.time_begin
        // Временные отрезки которые будут добавлены между началом спича и окончанием
        const timeStep = 5
        const bigTimeStep = 10
        let count = 1
        const toMoreSteps = () => {
          diff -= timeStep
          ++count
          speechesTime.push(diff + speech.time_begin)
          if (diff >= bigTimeStep && count < this.timeRowStep) {
            toMoreSteps()
          }
        }
        switch (true) {
          case diff < bigTimeStep && diff > timeStep:
            speechesTime.push(bigTimeStep - diff + speech.time_begin)
            break
          case diff >= bigTimeStep:
            toMoreSteps()
        }
      })
      // Удаляем одинаковые временные отрезки и сортируем по возрастанию
      speechesTime = [...new Set(speechesTime)].sort((a, b) => a - b)
      // Преобразуем минуты в часовой формат
      speechesTime = speechesTime.map((step) => toStringTime(step * 60 * 1000, this.timeFormat))
      return speechesTime
    },
    // получаем всех спичей со всех стримов
    speeches() {
      const arrSpeeches = []
      this.streams.forEach((stream) => {
        stream.speeches?.forEach((speech) => arrSpeeches.push(speech))
      })
      return arrSpeeches
    },
    // получаем id первого по времение онлайн спича из всех стримов
    onlineCardId() {
      const arrOnlineCards = []
      this.speeches.forEach((speech) => {
        if (speech.status === 'online') {
          arrOnlineCards.push(speech)
        }
      })
      if (arrOnlineCards?.length) {
        const minTime = Math.min(...arrOnlineCards.map((card) => getMinutes(card.time_begin)))
        const firstOnlineCard = arrOnlineCards.find((card) => {
          if (getMinutes(card.time_begin) === minTime) {
            return card
          }
        })
        return firstOnlineCard?.id
      }
      return 0
    },
    // получаем времена спичей в формате начало спича и конец
    speechesTimeBeginEnd() {
      const speechesTimeBeginEnd = []
      this.speeches.forEach((speech) => {
        speechesTimeBeginEnd.push({
          time_begin: getMinutes(speech.time_begin),
          time_end: getMinutes(speech.time_end),
        })
      })
      return speechesTimeBeginEnd
    },
    // получаем все времена спичей
    speechesTime() {
      const speechTimeArr = []
      this.speeches.forEach((speech) => {
        speechTimeArr.push(getMinutes(speech.time_begin))
        speechTimeArr.push(getMinutes(speech.time_end))
      })
      return speechTimeArr
    },
    // получаем время начала первого спича
    beginTime() {
      return Math.min(...this.speechesTime)
    },
    // получаем время окончания последнего спича
    endTime() {
      return Math.max(...this.speechesTime)
    },
    // меняем класс у времени если текущее время больше
    timeRowDone() {
      const arrTimeDone = this.timeCoordsAndTime.map((item) => {
        return this.onlineLineCoords > item.coord ? 'zeen-schedule__time_done' : ''
      })
      return arrTimeDone ?? []
    },
    // меняем класс у активного зала
    activeHall() {
      return this.streams.map((stream) => {
        if (stream.id === this.activeStreamId) {
          return 'zeen-schedule__hall_active'
        }
        return undefined
      })
    },
    hallLinkStyles() {
      return this.streams.map((_, i) => {
        return {top: this.coordsToHall[i] + 'px'}
      })
    },
    // меняем поизицию у линии показывающее текущее время в соответсвии с полученными координатами
    onlineLeftSpacing() {
      return this.showOnlineLine ? (this.onlineLineCoords ? { left: `${this.onlineLineCoords}px` } : false) : false
    },
    speechPrefix() {
      return 'speech_'
    },
    speechEvents() {
      const {...allEvents} = createEventsFor(this, this.speechPrefix)

      delete allEvents.cardClick
      delete allEvents.cardButtonClick

      return allEvents
    },
    speechSlots() {
      return createSlotsFor(this, this.speechPrefix)
    },
    modalPrefix() {
      return 'modal_'
    },
    modalEvents() {
      const {...allEvents} = createEventsFor(this, this.modalPrefix)
      return allEvents
    },
    modalSlots() {
      return createSlotsFor(this, this.modalPrefix)
    },
    displayedStreams() {
      if (this.offSlideToggle) {
        return this.streams
      }
      return this.isOpen ? this.streams : this.streams.slice(0, this.visibleHallsCount)
    },
    closedHeight() {
      if (this.offSlideToggle) {
        return null
      }
      return (275 * this.visibleHallsCount) + 80
    }
    
  },
  watch: {
    onlineCardId() {
      setTimeout(() => {
        this.updateSlider()
      })
    },
    streams() {
      setTimeout(() => {
        this.updateSlider()
      })
    },
  },
}
</script>

<style lang="scss">
@import '../../styles/mixins.scss';

:root {
  /* Размеры */
  --zeen-schedule-header-margin-bottom: 32px;
  --zeen-schedule-container-max-width: 100%;
  --zeen-schedule-arrows-width: 80%;
  --zeen-schedule-col-padding-bottom: 36px;
  --zeen-schedule-time-text-size: var(--main-large-size);
  --zeen-schedule-time-line-height: 1.5;
  --zeen-schedule-time-font-weight: 400;
  --zeen-schedule-time-width: 112px;
  --zeen-schedule-col-line-size: 750px;
  --zeen-schedule-row-height: 274px;
  --zeen-schedule-hall-text-size: var(--main-small-text);
  --zeen-schedule-hall-line-height: 1.42;
  --zeen-schedule-hall-font-weight: 700;
  --zeen-schedule-hall-padding-vertical: 8px;
  --zeen-schedule-hall-padding-horizontal: 12px;
  --zeen-schedule-hall-arrow-size: 16px;
  --zeen-schedule-hall-arrow-margin-left: 8px;
  --zeen-schedule-hall-left: 50px;
  --zeen-schedule-online-img-size: 16px;
  --zeen-schedule-card-height: 170px;
  --zeen-schedule-online-line-top: 36px;
  --zeen-schedule-hall-border-radius: 8px;
  --zeen-schedule-hide-button-margin: 8px;
  --zeen-schedule-hide-button-size: 16px;

  @include phones {
    --zeen-schedule-col-padding-bottom: 28px;
    --zeen-schedule-row-height: 240px;
    --zeen-schedule-time-text-size: 14px;
    --zeen-schedule-time-line-height: 1.42;
    --zeen-schedule-hall-text-size: 10px;
    --zeen-schedule-hall-line-height: 1.6;
    --zeen-schedule-hall-padding-vertical: 5px;
    --zeen-schedule-hall-padding-horizontal: 32px;
    --zeen-schedule-online-img-size: 13px;
    --zeen-schedule-card-height: 150px;
    --zeen-schedule-online-line-top: 22px;
    --zeen-schedule-hall-left: 28px;
  }

  /* Цвета */
  --zeen-schedule-background: var(--main-light);
  --zeen-schedule-col-border: var(--gray-1);
  --zeen-schedule-time-color: var(--main-color);
  --zeen-schedule-time-color-done: var(--gray-2);
  --zeen-schedule-col-line: var(--gray-1);
  --zeen-schedule-online-line: var(--main-danger-color);
  --zeen-schedule-online-img: var(--main-light);
  --zeen-schedule-hall: var(--gray-1);
  --zeen-schedule-hall-active: var(--main-transparent);
  --zeen-schedule-hall-hover: var(--main-transparent);
  --zeen-schedule-hall-text: var(--input-main-value-color);
  --zeen-schedule-hall-text-active: var(--main-color);
  --zeen-schedule-hall-arrow-color: #302e33;
}
</style>

<style scoped lang="scss">
@import '../../styles/mixins.scss';

.zeen-schedule {
  background: var(--zeen-schedule-background);
  overflow: hidden;

  &__top {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: var(--zeen-schedule-header-margin-bottom);
  }

  &__container {
    position: relative;
    width: 100%;
    max-width: var(--zeen-schedule-container-max-width);
    margin-left: auto;
    margin-right: auto;
  }

  &__arrows {
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: var(--zeen-schedule-arrows-width);
    z-index: 10;

    @include phones {
      display: none;
    }
  }

  &__arrow {
    transform: rotateY(180deg);
  }

  &__main {
    box-sizing: border-box;
    display: flex;
  }

  &__wrapper {
    position: relative;
  }

  &__col {
    position: relative;
    display: flex;
    justify-content: flex-start;
    align-items: center;
    padding: 0;
    margin: 0;
    list-style-type: none;
    padding-bottom: var(--zeen-schedule-col-padding-bottom);
    border-bottom: 1px solid var(--zeen-schedule-col-border);
  }

  &__time {
    user-select: none;
    position: relative;
    font-size: var(--zeen-schedule-time-text-size);
    line-height: var(--zeen-schedule-time-line-height);
    font-weight: var(--zeen-schedule-time-font-weight);
    color: var(--zeen-schedule-time-color);
    width: var(--zeen-schedule-time-width);

    &:nth-child(2n) {
      color: transparent;
      &:before {
        content: '';
        position: absolute;
        width: 2px;
        height: 10px;
        background: var(--zeen-schedule-time-color);
        border-radius: 2px;
        top: 50%;
        transform: translateY(-50%);
        left: 25%;
        @include phones {
          left: 20%;
        }
      }
    }

    &_done {
      color: var(--zeen-schedule-time-color-done);

      &:nth-child(2n) {
        &:before {
          background: var(--zeen-schedule-time-color-done);
        }
      }
    }
  }

  &__time-line {
    position: absolute;
    top: calc(100% + var(--zeen-schedule-col-padding-bottom));
    left: 25%;
    height: var(--zeen-schedule-col-line-size);
    width: 1px;
    stroke: var(--zeen-schedule-col-line);
    @include phones {
      left: 20%;
    }
  }

  &__online-line {
    position: absolute;
    top: var(--zeen-schedule-online-line-top);
    height: 100%;
    background: var(--zeen-schedule-online-line);
    width: 2px;
  }

  &__online-circle {
    display: flex;
    justify-content: center;
    align-items: center;
    position: absolute;
    top: 9px;
    left: 50%;
    transform: translateX(-50%);
    width: 26px;
    height: 26px;
    background: var(--zeen-schedule-online-line);
    border-radius: 100%;
    @include phones {
      top: 5px;
      width: 20px;
      height: 20px;
    }
  }

  &__online-img {
    display: flex;
    justify-content: center;
    align-items: center;
    fill: var(--zeen-schedule-online-img);
    width: var(--zeen-schedule-online-img-size);
    height: auto;
  }

  &__row {
    position: relative;
    display: flex;
    justify-content: flex-start;
    align-items: flex-start;
    height: var(--zeen-schedule-row-height);
    border-bottom: 1px solid var(--zeen-schedule-col-border);
    &:last-child {
      border-bottom: none;
    }
  }

  &__hall {
    position: absolute;
    top: 0;
    left: var(--zeen-schedule-hall-left);
    display: flex;
    align-items: center;
    padding: var(--zeen-schedule-hall-padding-vertical) var(--zeen-schedule-hall-padding-horizontal);
    border-radius: var(--zeen-schedule-hall-border-radius);
    background: var(--zeen-schedule-hall);
    color: var(--zeen-schedule-hall-text);
    font-size: var(--zeen-schedule-hall-text-size);
    font-weight: var(--zeen-schedule-hall-font-weight);
    line-height: var(--zeen-schedule-hall-line-height);
    text-transform: uppercase;
    cursor: pointer;
    transition: 0.2s;
    z-index: 2;

    &:hover {
      background: var(--zeen-schedule-hall-hover);
    }

    &_active {
      color: var(--zeen-schedule-hall-text-active);
      background: var(--zeen-schedule-hall-active);
    }
  }

  &__hall-arrow {
    width: var(--zeen-schedule-hall-arrow-size);
    height: var(--zeen-schedule-hall-arrow-size);
    fill: var(--zeen-schedule-hall-arrow-color);
    margin-left: var(--zeen-schedule-hall-arrow-margin-left);
  }

  &__hall-tooltip-icon {
    display: block;
    width: var(--zeen-schedule-hall-arrow-size);
    height: var(--zeen-schedule-hall-arrow-size);
    fill: var(--zeen-schedule-hall-arrow-color);
    margin-left: var(--zeen-schedule-hall-arrow-margin-left);
  }

  &__card {
    position: absolute;
    left: 0;
    bottom: 20px;
    z-index: 1;
    --zeen-schedule-card-footer-margin-top: 0;
    height: var(--zeen-schedule-card-height);
  }

  &__hide-button {
    --button-border-radius: 16px;

    display: flex;
    justify-content: center;
    padding-top: 20px;
    width: 100%;
  }

  &__hide-button-svg {
    width: var(--zeen-schedule-hide-button-size);
    height: var(--zeen-schedule-hide-button-size);
    margin-left: var(--zeen-schedule-hide-button-margin);
    transition: 0.2s;

    &_open {
      transform: rotate(180deg);
    }
  }

  &__popover {
    position: relative;
    display: flex;
    align-items: center;
    padding: var(--zeen-schedule-hall-padding-vertical) var(--zeen-schedule-hall-padding-horizontal);
    border-radius: var(--zeen-schedule-hall-border-radius);
    background: var(--zeen-schedule-hall);
    color: var(--zeen-schedule-hall-text);
    font-size: var(--zeen-schedule-hall-text-size);
    font-weight: var(--zeen-schedule-hall-font-weight);
    line-height: var(--zeen-schedule-hall-line-height);
    z-index: 1000;
  }
}
</style>