Skip to content
Snippets Groups Projects
HomeNextEvents.vue 3.27 KiB
Newer Older
Emmanuel Salomon's avatar
Emmanuel Salomon committed
<template>
  <section id="agenda" class="container py-12">
    <div class="border-b-2 container flex items-end mb-3 pb-2">
      <JuneCalendar class="w-12 mr-3 fill-current dark:text-gray-100" />
Emmanuel Salomon's avatar
Emmanuel Salomon committed
      <a
        :href="`${$config.forum_url}/calendar`"
        target="_blank"
        class="
          group
          bg-clip-text bg-gradient-to-r
          font-extrabold
          from-purple-800
          hover:underline
          text-4xl text-transparent
          to-blue-600
          uppercase
        "
        rel="noopener noreferrer"
Emmanuel Salomon's avatar
Emmanuel Salomon committed
      >
        Agenda
        <fa
          icon="external-link-alt"
          class="w-3 ml-1.5 text-gray-500 opacity-0 group-hover:opacity-75"
        />
Emmanuel Salomon's avatar
Emmanuel Salomon committed
      </a>
    </div>
    <aside v-if="!loading" class="lg:flex">
      <div
        v-for="(column, num) in columns"
        :key="num"
        class="flex-1"
        :class="num === 1 && 'lg:ml-4'"
      >
        <a
          v-for="(event, index) in column"
          :key="index"
          :href="`${$config.forum_url}/t/${event.slug}/${event.id}`"
          class="
            block
            hover:bg-hover-light
            dark-hover:text-gray-800
            p-2
            mt-1
            rounded-lg
            transition-colors
          "
          rel="noopener noreferrer"
        >
          <div class="event-date text-sm text-gray-500">
            {{ prettyDate(event.event.start) }}
            <div v-for="(tag, i) in event.tag" :key="i">{{ tag }}</div>
          </div>
          <div>{{ event.title }}</div>
        </a>
      </div>
    </aside>

    <div v-else class="h-80 flex items-center">
      <span class="loading-state h-12 w-12 scale-150 transform mx-auto" />
    </div>
  </section>
Emmanuel Salomon's avatar
Emmanuel Salomon committed
</template>

<script>
import JuneCalendar from '~/static/img/june-calendar.svg?inline'
Emmanuel Salomon's avatar
Emmanuel Salomon committed
import { fetchNextEvents } from '~/libs/api-forum'

export default {
  name: 'HomeNextEvents',
  components: {
    JuneCalendar,
  },
Emmanuel Salomon's avatar
Emmanuel Salomon committed
  data() {
    return {
      events: [],
      loading: false,
      cols: 2,
  computed: {
    columns() {
      const columns = []
      const mid = Math.ceil(this.events.length / this.cols)
      for (let col = 0; col < this.cols; col++) {
        columns.push(this.events.slice(col * mid, col * mid + mid))
      }
      return columns
    },
  },
Emmanuel Salomon's avatar
Emmanuel Salomon committed
  async mounted() {
    this.loading = true
    this.events = await fetchNextEvents(`?start=${this.formatDateForParams()}`)
Emmanuel Salomon's avatar
Emmanuel Salomon committed
    this.loading = false
  },

  methods: {
    formatDateForParams(date = new Date()) {
      const offset = date.getTimezoneOffset()
      date = new Date(date.getTime() - offset * 60 * 1000)
      return date.toISOString().split('T')[0]
    },
    prettyDate(date) {
      const formatter = new Intl.DateTimeFormat(
        this.$i18n.locale,
        this.$i18n.dateTimeFormats[this.$i18n.locale].full
      )
      return formatter
        .formatToParts(Date.parse(date))
        .map(({ type, value }) => {
          switch (type) {
            case 'literal':
              return value === ', ' ? ' à ' : value === ':' ? 'h' : value
            default:
              return value
          }
        })
        .reduce((string, part) => string + part)
    },
  },
Emmanuel Salomon's avatar
Emmanuel Salomon committed
}
</script>

<style lang="postcss" scoped>
.event-date:first-letter {
  text-transform: uppercase;
}
</style>