%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home/forge/takeaseat.eco-n-tech.co.uk/pages/therapists/
Upload File :
Create Path :
Current File : //home/forge/takeaseat.eco-n-tech.co.uk/pages/therapists/index.vue

<template>
  <div class="page-wrapper">
    <PageHeader classObject="bg-green z-30">
      <img class="relative z-20 mb-8"
        src="~assets/images/logo-white-small.svg" alt="Takeaseat" />
      <h1 class="relative z-20 text-5xl lg:text-7xl font-bold">Find a therapist</h1>
      <div ref="scrollTo" class="page-header-bottom grid grid-cols-1 md:grid-cols-2 gap-x-4">
        <div class="flex items-center justify-center md:justify-start">
          <SearchForm
            v-model="selected_filters.search_query"
            placeholder="Search Therapists" />
        </div>
        <div class="flex items-center justify-center md:justify-end mt-6 md:mt-0">
          <button @click="toggleFilters"
            class="flex items-center uppercase text-sm font-medium focus:outline-none"
            type="button">
            <span v-if="is_filters_showing == false">Show Filters</span>
            <span v-else>Hide Filters</span>
            <span class="block w-4 h-4 ml-3 icon-filters bg-contain bg-center bg-no-repeat"></span>
          </button>
        </div>
      </div>
    </PageHeader>
    <div :class="is_filters_showing ? 'grid grid-cols-1 lg:grid-cols-8 lg:gap-10' : ''"
      class="px-6 lg:px-0">
      <div v-if="is_filters_showing"
        class="lg:col-span-2">
        <div @click="toggleFilters"
          v-if="is_filters_showing"
          class="block fixed top-0 left-0 w-full h-full z-40 bg-black bg-opacity-20 lg:hidden"></div>
        <div :class="isFiltersActive ? 'pb-28' : 'pb-20'"
          class="fixed z-50 bottom-0 right-0 w-10/12 h-screen p-4 overflow-y-auto bg-white lg:static lg:h-auto lg:w-auto lg:p-0 lg:z-1">
          <span class="mb-8 block text-xl font-bold">Filter</span>
          <button v-if="isFiltersActive"
            class="block -mt-3 mb-6 uppercase transition text-blue-light hover:text-black focus:outline-none"
            @click="resetFilters">Reset Filters</button>
          <Widget title="Location">
            <div class="grid grid-cols-1 sm:grid-cols-6 gap-x-4">
              <div class="sm:col-span-4">
                <ValidationProvider name="postcode" :rules="{ regex: /^(([gG][iI][rR] {0,}0[aA]{2})|((([a-pr-uwyzA-PR-UWYZ][a-hk-yA-HK-Y]?[0-9][0-9]?)|(([a-pr-uwyzA-PR-UWYZ][0-9][a-hjkstuwA-HJKSTUW])|([a-pr-uwyzA-PR-UWYZ][a-hk-yA-HK-Y][0-9][abehmnprv-yABEHMNPRV-Y]))) {0,}[0-9][abd-hjlnp-uw-zABD-HJLNP-UW-Z]{2}))$/ }" v-slot="{ errors }">
                  <t-input-group label="Postcode">
                    <t-input
                      @keyup="filterOnKeyUp"
                      v-model="selected_filters.postcode"
                      placeholder="Enter your postcode" />
                      <span class="field-invalid" v-if="errors[0]">{{ errors[0] }}</span>
                  </t-input-group>
                </ValidationProvider>
              </div>
              <div class="sm:col-span-2">
                <ValidationProvider name="postcode" rules="required" v-slot="{ errors }">
                  <t-input-group label="Distance">
                    <t-select
                      @change="filter"
                      v-model="selected_filters.distance"
                      :options="[
                        { id: 5, text: '5 miles' },
                        { id: 10, text: '10 miles' },
                        { id: 20, text: '20 miles' },
                        { id: 30, text: '30 miles' },
                        { id: 40, text: '40 miles' },
                        { id: 50, text: '50 miles' },
                      ]" />
                      <span class="field-invalid" v-if="errors[0]">{{ errors[0] }}</span>
                  </t-input-group>
                </ValidationProvider>
              </div>
            </div>
          </Widget>
          <Widget title="Session Types">
            <t-checkbox-group
              @change="filter"
              :classes="{
                groupWrapper: 'flex flex-col justify-center px-0.5',
                label: 'block pl-2.5',
                input: 'rounded w-5 h-5 text-black transition duration-100 ease-in-out border-gray-300 shadow-sm focus:border-black focus:ring-2 focus:ring-black focus:outline-none focus:ring-opacity-50 focus:ring-offset-0  disabled:opacity-50 disabled:cursor-not-allowed',
                inputWrapper: 'inline-flex',
                wrapper: 'flex items-center my-1',
              }"
              v-model="selected_filters.session_types"
              name="session_types"
              valueAttribute="id"
              textAttribute="name"
              :options="filters.session_types"></t-checkbox-group>
          </Widget>
          <Widget title="Specialisms">
            <t-checkbox-group
              @change="filter"
              :classes="{
                groupWrapper: 'flex flex-col justify-center px-0.5',
                label: 'block pl-2.5',
                input: 'rounded w-5 h-5 text-black transition duration-100 ease-in-out border-gray-300 shadow-sm focus:border-black focus:ring-2 focus:ring-black focus:outline-none focus:ring-opacity-50 focus:ring-offset-0  disabled:opacity-50 disabled:cursor-not-allowed',
                inputWrapper: 'inline-flex',
                wrapper: 'flex items-center my-1',
              }"
              v-model="selected_filters.specialisms"
              name="specialisms"
              valueAttribute="id"
              textAttribute="name"
              :options="filters.specialisms"></t-checkbox-group>
          </Widget>
          <Widget title="Languages">
            <t-checkbox-group
              @change="filter"
              :classes="{
                groupWrapper: 'flex flex-col justify-center px-0.5',
                label: 'block pl-2.5',
                input: 'rounded w-5 h-5 text-black transition duration-100 ease-in-out border-gray-300 shadow-sm focus:border-black focus:ring-2 focus:ring-black focus:outline-none focus:ring-opacity-50 focus:ring-offset-0  disabled:opacity-50 disabled:cursor-not-allowed',
                inputWrapper: 'inline-flex',
                wrapper: 'flex items-center my-1',
              }"
              v-model="selected_filters.languages"
              name="languages"
              valueAttribute="id"
              textAttribute="name"
              :options="filters.languages"></t-checkbox-group>
          </Widget>
          <Widget title="Tags">
            <t-checkbox-group
              @change="filter"
              :classes="{
                groupWrapper: 'flex flex-col justify-center px-0.5',
                label: 'block pl-2.5',
                input: 'rounded w-5 h-5 text-black transition duration-100 ease-in-out border-gray-300 shadow-sm focus:border-black focus:ring-2 focus:ring-black focus:outline-none focus:ring-opacity-50 focus:ring-offset-0  disabled:opacity-50 disabled:cursor-not-allowed',
                inputWrapper: 'inline-flex',
                wrapper: 'flex items-center my-1',
              }"
              v-model="selected_filters.tags"
              name="tags"
              valueAttribute="id"
              textAttribute="name"
              :options="filters.tags"></t-checkbox-group>
          </Widget>
          <div class="block lg:hidden text-center fixed bottom-0 right-0 w-10/12 p-3 border-t border-black border-opacity-20 bg-white">
            <button v-if="isFiltersActive"
              class="inline-block mb-3 uppercase transition text-blue-light hover:text-black focus:outline-none"
              @click="resetFilters">Reset Filters</button>
            <button 
              @click="viewResults"
              class="btn btn-primary btn-small w-full">View Results</button>
          </div>
        </div>
      </div>
      <div v-if="meta.total > 0"
        :class="is_filters_showing ? 'lg:col-span-6' : ''">
        <div :class="is_filters_showing ? 'grid-cols-1 md:grid-cols-2' : ' grid-cols-1 md:grid-cols-2 lg:grid-cols-3'"
          class="grid gap-x-8 gap-y-12">
          <Therapist
            v-for="(therapist, key) in therapists"
            v-bind:key="key"
            :therapist="therapist" />
        </div>
        <div
          v-if="meta.total > meta.current_page"
          class="mt-8 sm:flex sm:items-center sm:justify-center sm:px-6 lg:px-0">
          <button v-if="current_page !== 1"
            @click="previousPage"
            class="btn btn-primary rounded-full shadow-md my-2 sm:my-0 sm:mx-3">Previous Page</button>
          <button v-if="current_page < meta.last_page"
            @click="nextPage"
            class="btn btn-primary rounded-full shadow-md my-2 sm:my-0 sm:mx-3">Next Page</button>
        </div>
      </div>
      <div v-else
        :class="is_filters_showing ? 'lg:col-span-6' : ''"
        class="text-center py-10 md:py-20 px-6 md:px-8 bg-gray">
        <p class="text-2xl md:text-4xl font-bold m-0">No therapists found</p>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  head () {
    return {
      titleTemplate: 'Therapists | %s',
    }
  },

  data() {
    return {
      timer: null,
      is_filters_showing: false,
      is_sortby_showing: false,
      current_page: 1,
      selected_filters: {
        search_query: null,
        postcode: null,
        distance: 30,
        session_types: [],
        specialisms: [],
        tags: [],
        languages: []
      }
    }
  },

  computed: {
    therapists() {
      return this.$store.state.therapists.list
    },
    filters() {
      return this.$store.state.therapists.filters
    },
    meta() {
      return this.$store.state.therapists.meta
    },
    isFiltersActive() {
      return this.selected_filters.session_types.length || 
        this.selected_filters.specialisms.length || 
        this.selected_filters.tags.length || 
        this.selected_filters.languages.length || 
        this.selected_filters.postcode != null;
    }
  },

  async asyncData ({ store, query, params }) {
    await store.dispatch('therapists/filters')
    await store.dispatch('therapists/get', query)
  },

  mounted() {
    const query = this.$route.query;
    this.current_page = Number(query.page) || 1;

    for (const [key, value] of Object.entries(query)) {
      if(Array.isArray(this.selected_filters[key])) {
        if(Array.isArray(query[key])) {
          this.selected_filters[key] = value.map(function (x) {
            return parseInt(x, 10);
          });
        } else {
          this.selected_filters[key] = [parseInt(value, 10)];
        }
      } else {
        this.selected_filters[key] = value;
      }
    }

    if(Object.keys(query).length !== 0 && window.innerWidth >= 1024) {
      this.is_filters_showing = true;
    }
  },

  methods: {
    async filter() {
      this.current_page = 1;
      this.$router.push({
        path: '/therapists',
        query: this.selected_filters
      })
      await this.$store.dispatch('therapists/get', this.selected_filters)
    },

    filterOnKeyUp() {
      if (this.timer) {
        clearTimeout(this.timer);
        this.timer = null;
      }

      this.timer = setTimeout(() => {
        this.filter();
      }, 500);
    },

    async sortBy() {
      this.$router.push({
        path: '/therapists',
        query: this.selected_filters
      })
      await this.$store.dispatch('therapists/get', this.selected_filters)
    },

    async previousPage() {
      this.scrollToTop();
      this.current_page = this.current_page - 1;
      this.$router.push({
        query: {
          specialisms: this.filter.specialisms,
          session_types: this.selected_filters.session_types,
          tags: this.selected_filters.tags,
          page: this.current_page
        }}
      );

      await this.$store.dispatch('therapists/get', {
        specialisms: this.filter.specialisms,
        session_types: this.selected_filters.session_types,
        tags: this.selected_filters.tags,
        page: this.current_page
      })
    },

    async nextPage() {
      this.scrollToTop();
      this.current_page = this.current_page + 1;
      this.$router.push({
        query: {
          specialisms: this.filter.specialisms,
          session_types: this.selected_filters.session_types,
          tags: this.selected_filters.tags,
          page: this.current_page
        }}
      );

      await this.$store.dispatch('therapists/get', {
        specialisms: this.filter.specialisms,
        session_types: this.selected_filters.session_types,
        tags: this.selected_filters.tags,
        page: this.current_page
      })
    },

    toggleFilters() {
      if(this.is_filters_showing == false) {
        this.is_filters_showing = true;
      } else {
        this.is_filters_showing = false;
      }
    },

    viewResults() {
      this.scrollToTop();
      this.is_filters_showing = false;
    },

    async resetFilters() {
      this.selected_filters = {
        postcode: null,
        distance: 30,
        session_types: [],
        specialisms: [],
        tags: [],
        languages: []
      }

      await this.$store.dispatch('therapists/get')
    },

    scrollToTop() {
      if (this.$refs.scrollTo) {
        this.$SmoothScroll(this.$refs.scrollTo, 500);
      }
    }
  },

  watch: {
    'selected_filters.search_query': function () {
      this.filter()
    }
  },
}
</script>

Zerion Mini Shell 1.0