Rails+Vue.jsでSPA/PWAな家計簿アプリ作った

# はじめに

嫁と「家計簿つけなきゃねー」という話になり、勉強していたRails+Vue.jsな環境で早速作ってみた。

![accountsbook.gif](https://qiita-image-store.s3.amazonaws.com/0/191521/669fd3f4-43e2-6981-2536-c88a3ff5724c.gif)

こんな感じで、SPAっぽく動作する。ついでに、PWA化もしてあるのでスマホでもPCでもよしなに動いてくれる。

ソースコードはこちら

[AccountsBook](https://github.com/S-H-GAMELINKS/AccountsBook)

# やったこと
## SPAなひな型を作る

基本的には以下の記事を参考にコンポーネントの作成やデータの送信などを行った。
なので、特別困ることもなるスムーズにできた。

[Vue.jsとRailsでTODOアプリのチュートリアルみたいなものを作ってみた](https://qiita.com/naoki85/items/51a8b0f2cbf949d08b11)

デザイン関係に関しては、愛用させていただいている[Umi](https://github.com/ysakasin/Um)を使用した。

API周りの認証とかまだ作ってないので、後々のことも考えて以下の記事を参考に実装する予定。

[【Rails】RailsでAPIの簡単なトークン認証を実装する](https://qiita.com/Yarimizu14/items/c81a8cf1859f954b953e)

## 日付を選択できるようにする

家計簿なので支出の日付などを入力できるようにする必要があったので、以下のように実装した。

```html
    <div class="input-group">
        <div class="input-group-append">
            <span class="input-group-text">日付</span>
        </div>
        <date-picker v-model="date" :config="options"></date-picker>
    </div>
```

```javascript
import datePicker from 'vue-bootstrap-datetimepicker';

export default {
    data: function() {
        return {
            date: null,
            options: {
                format: 'YYYY/MM/DD',
                useCurrent: false,
            },
        }
    },
    methods: {
        //メソッドなど
    },
    components: {
        datePicker,
    }
}
```

[vue-bootstrap-datetimepicker](https://github.com/ankurk91/vue-bootstrap-datetimepicker)という便利なものがあったのでそれを使って実装。

コンポーネントを呼び出して、日付として受け取る変数を`v-model`などに渡すだけの簡単なお仕事。

# 収入と支出の合計値を表示する。

こんな感じで処理を実装した。

```javascript

sumAccounts: function() {
    axios.get('api/accounts').then((response) => {
        for(var i = 0; i < response.data.length; i++){
            if(response.data[i].income === true){
                this.incomes += response.data[i].money;
            } else {
                this.payments += response.data[i].money;
            }
        }
    }, (error) => {
        console.log(error);
    });
},
```

APIから返ってきたJSONを`for`で回して支出の合計:`payments`と収入の合計：`incomes`に追加していくだけ。収入かどうかは`income`に`true`がわたっているかどうかで判断してる。

## 月毎の支出や収入の合計を算出する

簡単な家計簿サンプルであれば、これでOKなんだけども。今回作るのは、実際に使うためのものなのでもう一工夫。
月毎に収支を算出できるようにしたかったので、以下のように頑張ってみた。

```html
    <div class="input-group">
        <div class="input-group-append">
            <span class="input-group-text">絞り込み日付</span>
        </div>
        <vue-monthly-picker v-model="query"></vue-monthly-picker>
        <button type="button" class="btn btn-primary" v-on:click="sumAccounts">絞り込み</button>
    </div>
```

```javascript
import moment from 'moment';
import VueMonthlyPicker from 'vue-monthly-picker'

export default {
    data: function() {
        return {
            incomes: 0,
            payments: 0,
            query: moment(new Date()).format('YYYY/MM')
        }
    },
    created: function () {
        this.getAccountsBook();
        this.getCategories();
    },
    mounted: function() {
        this.sumAccounts();
    },
    methods: {
        sumAccounts: function() {
            axios.get('api/accounts').then((response) => {
                const date = new Date(this.query);
                this.payments = 0;
                this.incomes = 0;
                console.log(moment(date).format('YYYY/MM'));
                for(var i = 0; i < response.data.length; i++){
                    if(moment(response.data[i].date).format('YYYY/MM') === moment(date).format('YYYY/MM')) {
                        if(response.data[i].income === true){
                            this.incomes += response.data[i].money;
                        } else {
                            this.payments += response.data[i].money;
                        }
                    }
                }
                console.log(this.payments);
                this.$forceUpdate();
            }, (error) => {
                console.log(error);
            });
        },
    },
    components: {
        VueMonthlyPicker
    }
}
```

月の指定には[vue-monthly-picker](https://github.com/ittus/vue-monthly-picker)を使用している。これものすごく便利なので他な人も使うべき。

で、指定した月のデータを`query`に渡して、それを[moment.js](https://momentjs.com/)に渡して比較できるように成型している。

あとは、`payments`と`incomes`にそれぞれ足していくだけ。

# おわりに

とりあえず、動くものにはなったので嫁と使いながらよろしくないところを修正していこうかと思う。

# 参考記事

[Vue.jsとRailsでTODOアプリのチュートリアルみたいなものを作ってみた](https://qiita.com/naoki85/items/51a8b0f2cbf949d08b11)