binhonglee/GlobeTrotte

View on GitHub
src/cockpit/views/vLanding.vue

Summary

Maintainability
Test Coverage
<template lang="pug">
.landing
  CHead(
    description="Welcome to GlobeTrotte - A travel itinerary crowdsourcing platform"
    type="homepage"
  )
  h1.title GlobeTrotte
  h3.subtitle Look for your next travel plan here!
  br
  form.tripSearchForm
    n-input.tripSearchQueryInput(
      placeholder="weekend"
      v-model:value="query"
      @keyup.enter.native="search"
    )
    n-select.tripSearchCityInput(
      v-model:value="selectedCities"
      :options="possibleCities"
      filterable
      multiple
      placeholder="City"
    )
    n-button(@click="search") Find
  .homePageTripCarousel
    CLoadingTripPreviewCard(
      v-if="trips.length === 0"
      v-for="count in 10"
      :key="count"
    )
    CTripPreviewCard(
      v-else
      v-for="trip in trips"
      :trip="trip"
    )
</template>

<script lang="ts">
import { defineComponent } from "vue";
import CTripPreviewCard from "@/components/CTripPreviewCard.vue";
import HTTPReq from "@/shared/HTTPReq";
import TripObj from "@/wings/TripObj";
import { Options, CityUtil } from "@/shared/CityUtil";
import Routing from "@/shared/Routing";
import Routes from "@/routes";
import City from "@/wings/City";
import { NButton, NInput, NSelect } from "naive-ui";
import CHead from "@/components/CHead.vue";
import CLoadingTripPreviewCard from "@/components/loading/CLoadingTripPreviewCard.vue";

interface Data {
  length: number;
  possibleCities: Array<Options>;
  query: string;
  selectedCities: City[];
  trips: TripObj[];
}

export default defineComponent({
  components: {
    NButton,
    NInput,
    NSelect,
    CTripPreviewCard,
    CHead,
    CLoadingTripPreviewCard,
  },
  data: (): Data => ({
    length: 0,
    possibleCities: [],
    query: "",
    selectedCities: [],
    trips: [],
  }),
  async beforeMount(): Promise<void> {
    this.$data.possibleCities = CityUtil.sortedCityOptions();
    this.$data.trips = [];
    const trips = await HTTPReq.genGET("v2/sample_trips");
    for (const trip of trips as Array<unknown>) {
      const newTrip = new TripObj(trip);
      if (newTrip.details.days.length > 0) {
        this.$data.trips.push(new TripObj(trip));
      }
    }
  },
  methods: {
    async search(): Promise<void> {
      if (
        !(
          this.$data.query.length > 0 ||
          this.$data.selectedCities.length > 0 ||
          this.$data.length !== 0
        )
      ) {
        await Routing.genRedirectTo(Routes.trip_Search);
      }
      await Routing.genRedirectTo(
        Routes.trip_Search,
        new Map<string, string>(
          Object.entries({
            length: this.$data.length.toString(),
            query: this.$data.query,
            cities: CityUtil.citiesToString(this.$data.selectedCities),
          }),
        ),
      );
    },
  },
});
</script>

<style scoped>
.tripSearchQueryInput {
  max-width: 300px;
}

.tripSearchForm {
  padding-bottom: 30px;
  text-align: center;
}

.tripSearchQueryInput {
  display: inline-block;
  text-align: left;
}

.tripSearchCityInput {
  margin: auto;
  padding: 10px 0;
  max-width: 300px;
}

.homePageTripCarousel {
  padding: 0 0 50px 0;
}
</style>