Vue.js＋Firebase+Stripeをさわさわしてみるーその５


その５
登録／ログインまわりの実装は完成したので、次はサービスのコア部分を作っていきます。今回は「観光スポット」のビューア―アプリケーションを作ってきましょう。

・Top画面には観光名所をいくつか並べます（今回は3つだけ）。
・気になる観光名所をタップすると、詳細情報が閲覧できます。
　そこに「お気に入りの」ボタンを設け、お気に入りに登録できます。
　また、コメントも投稿できるようにしておきます。
・詳細画面には「ホテル・宿」と「レストラン」のリンクを設けます。
　「ホテル」のリンクをタップすると、観光名所周辺のホテル一覧が表示されます。
　「レストラン」のリンクをタップすると、観光名所周辺のレストラン一覧が表示されます。

ユーザ投稿系の機能として、「お気に入り」ができるようにします。それでは早速手を動かしていきますよ！

##観光名所のデータをjsonファイルの形で準備する。
まずは観光名所のデータをfirebaseに登録しなければいけません。データはjson形式で以下のように手元にあるとしましょう。画像はフォト蔵さんからテキトーに拝借しています。
あざますm（_ _）m

```spot.json
[
    {
        "address": "北海道１－１－１",
        "created_at": "2018-02-02 18:31",
        "detail": "神威岬（かむいみさき）は、北海道積丹郡積丹町大字神岬町にある岬。積丹半島北西部から日本海に突き出している。ニセコ積丹小樽海岸国定公園に属している。",
        "id": "1",
        "image_url": "http://art41.photozou.jp/pub/983/3124983/photo/244310636_org.v1531461646.jpg",
        "latitude": "43.1905982",
        "longitude": "141.0071705",
        "name": "神威岬",
        "near_station": "札幌",
        "official_url": "https://www.abc,co.jp",
        "updated_at": "2018-07-26 03:32:19.391612"
    },
    {
        "address": "青森１－１－１",
        "created_at": "2018-02-02 18:31",
        "detail": "歴代の藩主が岩木山神社に寄進を行ったため、その社殿は荘厳なものとなり、「奥の日光」とも呼ばれた。",
        "id": "2",
        "image_url": "http://art5.photozou.jp/pub/872/2143872/photo/248349373_624.v1531998173.jpg",
        "latitude": "43.1905982",
        "longitude": "141.0071705",
        "name": "岩木山神社",
        "near_station": "釧路",
        "official_url": "https://www.abc,co.jp",
        "updated_at": "2018-07-26 03:32:19.729371"
    },
    {
        "address": "岩手１－１－１",
        "created_at": "2018-02-02 18:31",
        "detail": "中尊寺（ちゅうそんじ）は、岩手県西磐井郡平泉町にある天台宗東北大本山の寺院。奥州三十三観音番外札所。山号は関山（かんざん）、本尊は釈迦如来。寺伝では円仁の開山とされる。",
        "id": "3",
        "image_url": "http://art21.photozou.jp/pub/292/304292/photo/247842149_624.v1532080817.jpg",
        "latitude": "40.798685",
        "longitude": "140.7483241",
        "name": "中尊寺",
        "near_station": "青森",
        "official_url": "https://www.abc,co.jp",
        "updated_at": "2018-07-26 03:32:20.477305"
    }
]
```

このjsonファイルをfirebaseにアップロードしたいのですが、残念ながら今回利用しているfirestoreはjsonフィアルのアップロードができません（お金払えばできますが、jsonファイルアップロードするだけにお金払うのなんて負け組感半端ないわぁ・・・）

ですので、アップロードするためのスクリプトをちょちょいと作ってあげましょう。
firebaseのターミナルで叩いてもいいのですが、vueの勉強もかねてこのアプリケーションから登録してみます。まず、上記のjsonをspots.jsonファイルとして/assets/dataのフォルダの中に配置します。続いて以下のようにPlaceregist.vueファイルを作成しましょう。

```views/Placeregist.vue
<template>
  <div class="mymemo">
    <h2>Place</h2>
    <br />
        <button @click="placeregister">Register</button>
    <br /><br />
    <ul>
    <li v-for="place in placelist">
    {{place}}
    </li>
    </ul>
  </div>
</template>

<script>
import firebase from 'firebase'
import 'firebase/firestore'

export default {
  name: 'placeregist',
  data () {
    return {
      placelist: [],
    }
  },
  created: function(){
    const jsondata = require('../assets/data/spots.json')
    this.placelist = jsondata
  },
  methods: {
    placeregister: function () {
        for (var i = 0; i < 50; i++) {
            const insertdata = this.placelist[i]
            firebase.firestore().collection('place').add({
                name: insertdata.name,
                address: insertdata.address,
                detail: insertdata.detail,
                image_url: insertdata.image_url,
                official_url: insertdata.official_url,
                longitude: insertdata.longitude,
                latitude: insertdata.latitude,
                near_station: insertdata.near_station,                
            }).catch(function (error) {
                console.error('Error adding document: ', error);
            })
        }
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  margin: 0 10px;
}
a {
  color: #42b983;
}
input {
  margin: 10px 0;
  padding: 10px;
}
h2 {
    background:#1c4b7a;
    color:#fff;
}
</style>
```

ここで一度画面を確認しましょう。以下の図のようになっていればOKです。

![図2.png](https://qiita-image-store.s3.amazonaws.com/0/293340/39dad33b-18e1-8744-ca36-0aa43091fa01.png)



##firebaseにコレクション：placeを作成する

まだ、placelistを登録するためのコレクション(テーブルのようなもの)がありません。ので、この箱を用意してあげます。Firebaseを開き、新たにコレクションを作成しましょう。フィールドはテストとして一つだけ作成していただければOKです。

![図3.png](https://qiita-image-store.s3.amazonaws.com/0/293340/800f2208-2cd4-5629-e08e-aefa4c4296f0.png)


作成できたら、vueのアプリケーション画面に戻り、registerボタンをクリックしてみましょう。うまくいくとfirebaseのコレクションにデータが登録されます。下の図のようになっていればOKです。

![図4.png](https://qiita-image-store.s3.amazonaws.com/0/293340/bdbc9228-a50d-9d0c-7162-3062fdcf2cc6.png)


フィールドにテストとして登録したドキュメントデータは消去しておきましょう。


##トップ画面にplaceリストを表示する
では登録したplaceをトップ画面に表示してみましょう。新たにTop.vueファイルを作成します。

```views/Top.vue
<template>
  <div class="place">
    <h2>Place一覧</h2>
    <ul>
    <li v-for="place in placelist">{{place.data().name}}
    </li>
    </ul>
  </div>
</template>

<script>
import firebase from 'firebase'
import 'firebase/firestore'

export default {
  name: 'top',
  data () {
    return {
      placelist: []
    }
  },
  created: function(){
    firebase.firestore().collection('place').get().then((querySnapshot) => {
    querySnapshot.forEach((doc) => {
        this.placelist.push(doc)
        console.log(doc)
    })
  })
  },
  methods: {
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  margin: 0 10px;
}
a {
  color: #42b983;
}
input {
  margin: 10px 0;
  padding: 10px;
}
h2 {
    background:#1c4b7a;
    color:#fff;
}
</style>
```

ここでのポイントは```created```の個所。```this.placelist.push(doc)```とすることで、placelistの中に、firebaseのplaceコレクションのデータを配列の形で持たせます。push!push!

そして、この配列を```<template>```のv-forでさばいていきます。nameだけを一先ず表示させてみました。続いてrouteをとおしておきます。

```route.js
    {
      path: '/top',
      name: 'top',
      // route level code-splitting
      // this generates a separate chunk (about.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import(/* webpackChunkName: "about" */ './views/Top.vue')
    },
```

今回はここまで。次回はTop画面から詳細画面への遷移を作りこんでいきます。