Part 3: .vue file - SOLUTION

Step 1

~/path/to/projects » vue init webpack hostel-vue

? Project name hostel-vue
? Project description A Vue.js project
? Author Maxence POUTORD <maxence.poutord@gmail.com>
? Vue build standalone (Runtime + Compiler: recommended for most users)
? Install vue-router? No
? Use ESLint to lint your code? Yes
? Pick an ESLint preset Standard
? Setup unit tests with Karma + Mocha? No
? Setup e2e tests with Nightwatch? No

   vue-cli · Generated "hostel-vue".

   To get started:

     cd hostel-vue
     npm install
     npm run dev

   Documentation can be found at https://vuejs-templates.github.io/webpack

Then:

cd hostel-vue
npm install
npm run dev

Step 2

src/App.vue

<template>
  <div id="app">
    <HostelList/>
  </div>
</template>

<script>
import HostelList from './components/HostelList'

export default {
  name: 'app',
  components: {
    HostelList
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
  margin-top: 20px;
}

i.heart.icon {
  cursor: pointer;
}

i.heart.icon:hover {
  color: #E16D6D;
}
</style>

src/components/HostelList.vue

<template>
  <div class="ui container">
    <h1 class="ui center aligned header">HostelVue</h1>

    <form class="ui form">
      <div class="inline fields">
        <div class="one wide field">
          <i :class="onlyShowLiked ? 'red' : 'grey'" class="heart icon" @click="toogleLikeFilter" title="Only show liked hostels"></i>
        </div>
        <div class="fifteen wide field">
          <input type="text" placeholder="filter by name" v-model="userSearch">
        </div>
      </div>
    </form>
    <br>

    <div class="ui cards">
      <hostel-list-item
        v-for="(hostelShown, index) in hostelsShown" :key="index"
        v-if="hostelShown.isActive"
        :hostel="hostelShown"
        :like="likedHostels.indexOf(hostelShown) !== -1"
        v-on:like="likeHostel"
      ></hostel-list-item>
    </div>

  </div>
</template>

<script>
import HostelListItem from './HostelListItem'

export default {
  components: {
    HostelListItem
  },
  data () {
    return {
      userSearch: '',
      onlyShowLiked: false,
      likedHostels: [],
      hostels: [
        {
          name: 'Happy Hostel',
          location: 'Berlin',
          price: {
            amount: 12,
            currency: '€'
          },
          description: 'Laboriosam est doloremque et sunt iure. Tenetur fugiat non ut autem repellat qui qui. Tempore pariatur exercitationem tempora. Laborum ut qui sed enim recusandae voluptas voluptas rerum accusantium.',
          bonus: {
            hasFreeWifi: false,
            hasTv: false,
            hasFreeBreakfast: false,
            hasBar: true
          },
          rating: 88,
          availability: true,
          isActive: true
        }, {
          name: 'WunderLand',
          location: 'Dublin',
          price: {
            amount: 24,
            currency: '€'
          },
          description: 'Nulla vero eveniet autem perferendis. Esse est itaque esse assumenda odit enim. Perspiciatis non omnis fugit officia omnis quia distinctio consequatur voluptatem. Necessitatibus ipsa sunt autem ducimus facilis.',
          bonus: {
            hasFreeWifi: true,
            hasTv: true,
            hasFreeBreakfast: false,
            hasBar: true
          },
          rating: 95,
          availability: true,
          isActive: true
        }, {
          name: 'Unknown Hostel',
          location: 'Dublin',
          price: {
            amount: 24,
            currency: '€'
          },
          description: 'Repellat et aliquid sit ab nemo et qui veniam dignissimos. Ducimus explicabo ut. Error expedita commodi. Nihil in est voluptatem molestiae consequatur rerum ex.',
          bonus: {
            hasFreeWifi: true,
            hasTv: false,
            hasFreeBreakfast: false,
            hasBar: true
          },
          rating: 77,
          availability: true,
          isActive: false
        }, {
          name: 'Medium Hostel',
          location: 'Berlin',
          price: {
            amount: 5,
            currency: '€'
          },
          description: 'Aliquid id ad optio dignissimos modi.',
          bonus: {
            hasFreeWifi: false,
            hasTv: true,
            hasFreeBreakfast: false,
            hasBar: false
          },
          rating: 54,
          availability: true,
          isActive: true
        }
      ]
    }
  },
  computed: {
    hostelsShown () {
      const likeFilter = (hostel) => {
        if (this.onlyShowLiked) {
          return this.likedHostels.indexOf(hostel) !== -1
        }
        return true
      }

      return this.hostels
        .filter(likeFilter)
        .filter(hostel => hostel.name.toLowerCase().includes(this.userSearch))
    }
  },
  methods: {
    likeHostel (hostel) {
      if (this.likedHostels.indexOf(hostel) === -1) {
        this.likedHostels.push(hostel)
      } else {
        this.likedHostels.splice(this.likedHostels.indexOf(hostel), 1)
      }
    },
    toogleLikeFilter () {
      if (this.onlyShowLiked === false) {
        this.onlyShowLiked = true
      } else {
        this.onlyShowLiked = false
      }
    }
  }
}
</script>

src/components/HostelListItem.vue

<template>
  <div class="card">
    <div class="content">
      <div class="right floated meta">
        <i v-bind:class="{ red: like }" class="heart icon" @click="$emit('like', hostel)"></i>
      </div>
      <div class="header">{{ hostel.name }}</div>
      </div>
      <div class="content">
        <div class="meta">
          {{ hostel.location }}
          <i v-if="hostel.bonus.hasFreeWifi" class="wifi icon"></i>
          <i v-if="hostel.bonus.hasFreeBreakfast" class="coffee icon"></i>
          <i v-if="hostel.bonus.hasTv" class="desktop icon"></i>
          <i v-if="hostel.bonus.hasBar" class="bar icon"></i>
          <div class="right floated meta">
              {{ hostel.price.amount }}{{ hostel.price.currency }}/night
            </div>
        </div>
        <div class="description">
            {{ hostel.description }}
        </div>
      </div>
      <div v-if="hostel.availability" class="ui orange bottom attached button">
        Book now
      </div>
      <div v-else class="ui bottom attached disabled button">
        Too late!
      </div>
  </div>
</template>

<script>
export default {
  props: ['hostel', 'like']
}
</script>

results matching ""

    No results matching ""