Vue.js + Nuxt.js + Vuetify + PWA + Firebaseで家計簿アプリを作ってみた

なぜ作ろうと思ったか

Nuxt.jsの便利さ、手軽さを知って、一度アプリを作ってみたいと思っていた

もともとVue.jsに興味を持ち始めて、いろいろ勉強していました。あんまりVuexとか理解していない内にNuxt.jsに出会い、Vuex, Vue Routerがもともと組み込まれており、ディレクトリ構造に従って記述していけばアプリが開発できる手軽さに感動しました。

僕自身、Webアプリに興味を持ち始めて日が浅いので、今後のためにも何か成果物を作りたいと思ってました。Todoアプリとかチュートリアルで作るようなものを量産する毎日で、何か実践に役立つアプリを作ろうとアイデアを探してました。

結婚して約半年、奥さんから家計管理を楽にしたいと言われていた

そんな中、奥さんから家計管理について「なんか知りたい情報をパッと見れるようにしてくれない?」と相談されました。

結婚後、僕が使っていたメインの口座(給与振込される)を生活用口座にしたことで、我が家の家計管理が少し複雑になっていたようです。

  • 個人型確定拠出年金の引き落とし口座になっており、結婚前に拠出年金用資金としてまとまった金額を入金していた
  • 僕の会社は半年に一回、6ヶ月定期分の交通費が支給されるが、pitapaを使っているため交通費の引き落としは毎月となっていた

上記理由により、実質残っている残高が把握できない状態になっており、経理をしている奥さんはExcelでコツコツ複雑な計算をして家計簿をつけていました。

それならと、収入、支出を入力するだけで、知りたい情報を表示してくれるできるだけシンプル操作を意識したアプリを作ろうと決めました。

どんなアプリなのか

前述のアプリを作った経緯にもある通り、我が家のニーズだけに絞ってアプリを作成したため、我が家専用のアプリとなってます。

だったら、なぜこの記事を書くのかというと、私自身初めて使う技術ばかりで流行りのサーバーレス構成となっているので、使用技術、アプリ構成など同じように個人開発始めようとされてる方の参考になれば嬉しいと思ったからです。

アプリとしては単純な家計簿アプリで以下のような機能があります。

  • 支出、収入項目の入力
    • 日付、項目、金額を入力するだけです
  • カレンダーベースで表示月を選択
  • 各月ごとの収入合計、支出合計、損益、収入・支出項目一覧を表示
  • 各月ごとにメモの入力が可能
  • 口座残高の表示
  • 実質の口座残高の表示(確保しておくべき拠出年金と交通費を考慮した金額)

使用技術

  • Vue.js
  • Nuxt.js
  • Vuetify
  • PWA
  • Cloud Firestore
  • Firebase Authentication
  • Firebase Hosting

前述の経緯によりNuxt.jsで開発。UIフレームワークはNuxtと相性の良いVuetifyを採用しました。

今回はモバイル向けWebアプリなのでPWA対応としました。

サーバー環境はFirebase任せです。ホスティング、認証、データベースまとめて管理できるので実装はとても楽できました。

実装する上で手こずった箇所

金額入力時に自動で3桁ごとにカンマが付くようにした**

Oct-25-2018 20-33-28

入力した金額が分かりづらいと経理をやってる奥さんから要望があったので実装しました。

テキストフィールドで金額の入力時に自動的に3桁ごとにカンマを付けてくれる実装はあまり参考なのがなかったので苦労しましたが、以下のコードで実装できました。スマホで数字だけ入力しやすいようにtype="tel"としています。

あまり慣れていない身としてはこういう動きは完成したとき少し感動します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<template>
<v-text-field v-model="inputAmount" @blur="setBlur()" @keyup="setKeyup()" @keydown="setKeydown()" @keypress="setKeypress()" label="金額" prefix="¥" type="tel" required></v-text-field>
</template>

<script>
export default {
data () {
return {
isIME: false
}
},
methods: {
addFigure (value) {
let originValue = value
value = this.removeFigure(value)
value = parseInt(value, 10)
if (isNaN(value)) return originValue
return value.toString().replace(/(\d)(?=(\d{3})+$)/g, '$1,')
},
removeFigure (value) {
if (value.length === 0) return ''
let num = Number(value.toString().replace(/,/g, ''))
if (isNaN(num)) return value
return num
},
setKeydown () {
this.isIME = true
},
setKeypress () {
this.isIME = false
},
setKeyup () {
if (this.isIME === false) this.inputAmount = this.addFigure(this.inputAmount)
},
setBlur () {
this.inputAmount = this.addFigure(this.inputAmount)
}
}
}
</script>

Nuxt.jsでのFirebaseの連携

何せどちらも初めて使うので、どうやって連携させればいいか悩みました。

Nuxt.jsとfirestoreを組み合わせて簡単なサイトを作った話 | MOJIの本棚

上記のサイトを参考にFirestore, Authentication, Hostingを使うには以下の実装でできました。

firebaseのプロジェクト設定の読み込み

設定内容はFirebaseコンソール画面の「アプリにFirebaseを追加」から見れる内容です。

image-20181025210141842

上記から見れる設定内容を以下のように記載します。

今回はFirestore, Authenticationに必要な設定のみ記載しています。

1
2
3
4
5
6
7
// ./util/firebaseConfig.js
export default {
apiKey: '',
authDomain: '',
databaseURL: '',
projectId: ''
}

Nuxt.jsのプラグインファイルを作成

Nuxt.jsでfirebaseを扱うためにプラグインディレクトリにファイルを作成します。

ここでもFirestore, Authenticationに必要な設定のみ記載しているので、必要に応じて追加します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// ./plugins/firebase.js
import firebase from 'firebase'
import config from './../util/firebaseConfig'
import 'firebase/auth'
import 'firebase/firestore'

if (!firebase.apps.length) {
firebase.initializeApp(config)
}

const settings = { timestampsInSnapshots: true }

export const auth = firebase.auth()
export const DB = firebase.firestore()
DB.settings(settings)

export default firebase

使用したい箇所でimport

後はAuthentication, Firestoreを利用したvueファイル、jsファイルでimportするだけです。

1
import { auth, DB } from '~/plugins/firebase'

Hosting設定

Hostingへデプロイするためには、以下のfirebase cli用設定ファイルをプロジェクトディレクトリ内に作成します。

1
2
3
4
5
6
7
8
9
10
11
// ./firebase.json
{
"hosting": {
"public": "dist",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
}

上記設定ファイルを作成しておくことで、firebase cliでコマンド一発でデプロイできます。

具体的には、Nuxt.jsで静的ファイルを生成

1
$ npm run generate

Firebase Hostingへデプロイ

1
$ firebase deploy
共有

Hexoでブログカードリンクを有効にする

Wordpressやはてなブログなどでは内部リンク等を貼ったときにカード形式でリンクが表示されます。

こんなの
IMAGE

外部リンクも含めて、ただの文字列だけのリンクだとそっけないので、Hexoでもできないかと調べてみました。

すると、プラグインとして提供されていました。

hexo-tag-link-preview

導入方法

以下コマンドでインストールします。

1
% npm install hexo-tag-link-preview

CSS設定

デザインはCSSをいじることで好きなようにカスタムできます。

themes/icarus/source/css/style.stylを編集します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.link-preview
color: #1b1b2e
display: block
.link-area
display: flex
margin: 1em 0
padding: .5em
border: 1px solid #c2c2c2
.descriptions
margin: 0 .5em
overflow: hidden
img
max-width: 75px
.og-title
margin-bottom: .3em
line-height: 1.7em
.og-description
margin-top: .2em
font-size: .8em
line-height: 1.5em

表示してみる

1
{% linkPreview https://github.com/ppoffice/hexo-theme-icarus _blank nofollow %}

上記のように書くだけで

IMAGE

このように表示されます。

もうちょっとデザインよくしたいですね。

共有

Hexoでブログサイトのセットアップをする

Node.js, npmのアップデート

homebrewでnodeをインストールしている環境でのアップデート方法です。
久しぶりなので、homebrewでインストールしているモジュール全てをアップデートしておきました。

1
% brew upgrade

Node.jsのアップデートが完了したら、npmもアップデートします。

1
% npm update -g npm

Hexoのインストール

公式サイトの手順にしたがって、インストールします。

1
2
3
4
5
% npm install hexo-cli -g
% hexo init uryolog
% cd uryolog
% npm install
% hexo server

これでとりあえず起動します。簡単ですね!
http://localhost:4000

IMAGE

デフォルトテーマでもまぁまぁシンプルでかっこいい気がしますが、扱いやすそうさシンプルなテーマを探します。

テーマのインストール

さーっと見てるだけでも、Jekyllよりいい感じのテーマは多いですね。
とりあえず気に入ったのはこれです。
Hipaper

あとはこれなんかもカスタマイズしやすそうで、気に入りました。
Light

これもいいかも
Maupassant

これも。
Bubuzou

いろいろ悩みましたが、ある程度直近で更新されてて、Githubスターも多いIcarusを使用することにしました。

Icarus テーマのインストール

作成したルートディレクトリ上で下記コマンドを実行します。
テーマの導入方法もJekyllよりわかりやすく簡単な気がします。

1
% git clone https://github.com/ppoffice/hexo-theme-icarus.git themes/icarus

テーマの切り替え、サイト設定

_config.ymlファイルを修正して、テーマを切り替えますが、ついでにサイト全体の設定もしておきます。

1
theme: icarus

その他のサイト設定は下記リンクを参照に適宜設定してください。

これでテーマの適用ができました。
IMAGE

テーマの設定

テーマ独自の設定もやっておきます。
修正するのはthemes/light/_config.ymlですが、_config.yml.exampleとなっているのでリネームします。

各設定は以下を参照してください。

1
2
3
4
5
6
# Menus
menu:
Home: .
開発: categories/develop
車: categories/car
About: about

Insight Searchの有効

上記設定で出てきますが、Insight Searchを有効にするため、下記npmパッケージをインストールします。

1
% npm install -S hexo-generator-json-content

設定はデフォルトで有効になってるかと思います。

1
insight: true

以上で、Hexoのセットアップは完了です。

共有

MacbookPro2015にKickflipスタンドを買って付けてみた

買おうと思ったきっかけ

僕のメインPCはMacbook Pro 2015ですが、普通に机の上で使っていると首が痛くなってきます。やはりノートパソコンはディスプレイが下の方になるので姿勢が悪くなってしまいます。

かといって、ディスプレイを目の高さに合わせるようにすると今度はキーボードが打ちづらくなります。外部ディスプレイ、外部キーボード、マウスも場合によって使ってはいますが、なんだかしっくり来なくて悩んでました。

そんなときにネットサーフィンしているとたまたまKickflipというMacbook用のスタンドがあるのを見つけました。

IMG_20180819_115758

装着してみる

IMG_20180819_120436

取り付けはとても簡単で、後ろのこのように貼るだけです。
粘着シートで張り付いているだけで、中性洗剤で洗えば何度でも貼りなおせるようです。
僕はいまのところ剥がれそうな雰囲気もないので、十分な粘着力かなと思います。

とても使いやすくなりました

IMG_20180819_120806

スタンドを立ててみるとこんな感じ。
最初は思ったよりがっつり傾斜がつくように思いますが、キーボードの打ちやすさ、ディスプレイ位置が少し上がることによる首の疲労感の軽減はなかなかな効果です。

キーボードの打ち心地かなり変わるので、僕のメイン作業のプログラミングのコーディング作業もかなり捗るようになりました。

また、夏の時期は底部に空間ができることによる排熱効果も期待できそうです。

価格の割にいろいろと効果があるので、なかなかおすすめの商品です。

共有

ZenFone3(ZE520KL)を買ってからやったこと

Android7から6へダウングレード

bootloaderのアンロックをするために、Android7のままだとpermission deniedが発生したため、ひとまずAndroid6へダウングレードします。

Android8の場合、そのままでできるかは分かりませんが、ダウングレード手順は同様かと思います。

http://www.birumendesu.com/entry/Zenfone3-downgrade

用意するもの

ファームウェアの準備

ダウンロードしたファームウェアをMicroSDに入れておきます。
他のデータが入っていても大丈夫です。

【Z017D_WW_13.20.10.152】のrecovery.imgとboot.imgをダウンロードします。
https://www.axfc.net/u/3859468

ダウンロードしたrecovery.imgとboot.imgをPCの任意の場所に配置します。
僕はC:¥zenfone¥としました。

fastbootでzenfone3を起動

一度zenfoneの電源を落とし、ボリュームUPボタンを押しながら、電源ボタンを長押しします。
すると、fastbootモードで起動します。

この状態でPCと接続します。

zenfoneドライバを認識するかをデバイスマネージャーで確認
ドライバ入れたら認識するはず

コマンドを送信

  • コマンドプロンプトを起動
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
C:\Users\ryo>cd c:\zenfone

c:\zenfone>dir
Volume in drive C has no label.
Volume Serial Number is 8C60-960D

Directory of c:\zenfone

2018/06/16 16:41 <DIR> .
2018/06/16 16:41 <DIR> ..
2018/06/16 16:41 18,314,488 boot.img
2018/06/16 16:32 19,090,684 recovery.img
2 File(s) 37,405,172 bytes
2 Dir(s) 25,320,337,408 bytes free
c:\zenfone>
c:\zenfone>
c:\zenfone>adb devices
List of devices attached
* daemon not running. starting it now on port 5037 *
* daemon started successfully *


c:\zenfone>fastboot devices
GBAZCY01K446S5V fastboot

c:\zenfone>
c:\zenfone>fastboot flash recovery recovery.img
target reported max download size of 536870912 bytes
sending 'recovery' (18643 KB)...
OKAY [ 0.426s]
writing 'recovery'...
OKAY [ 0.365s]
finished. total time: 0.796s

c:\zenfone>
c:\zenfone>fastboot flash boot boot.img
target reported max download size of 536870912 bytes
sending 'boot' (17885 KB)...
OKAY [ 0.416s]
writing 'boot'...
OKAY [ 0.332s]
finished. total time: 0.753s

zenfoneを電源長押しでfastbootモードを終了する。

ファームウェアを書き込む

  • まずはリカバリーモードでzenfoneを起動します。
  • ボリュームDOWN + 電源ボタン長押しで、画面がついたら電源ボタンのみ離します。
  • 【Apply update from microSD card】を選択
  • microSDカードに入れたらファームウェア【UL-ASUS_Z017D_1-WW-13.20.10.152-user.zip】を選択
  • 10分くらいで書き込みは完了します。
  • 完了後、【wipe data/factory reset】を選択
  • 【wipe cache partition】を選択
  • 完了後、【reboot system now】を選択して、OSを起動

これでAndroid6.0へのダウングレードは完了です。

bootloaderのアンロック

fastbootモードで起動

fastbootで起動してPCに接続します。

Android6.0でbootloaderアンロックを試そうとしたところ、なぜかrawファイルを書き込んでもFAILEDが表示されます。
特にOTAの通知が来なくても問題ないかと判断し、ASUS公式の方法でのアンロックをすることにしました。

ASUS公式のbootloaderアンロック方法

apkをダウンロードして、ZenFone上からインストール、実行するだけです。
Android6.0用と7.0, 8.0用があるので注意してください。

Android8.0へアップデート

OTA経由でのアップグレードができないので、公式サイトからzipを落としてきて、端末のリカバリからアップデートします。
これでひとまず、Android8.0になりました。

TWRPの導入

共有

BMWコーディングを初期化する【E84】

エアバックのリコール対応のためディーラー入庫になったので、コーディングをとりあえず初期化して出してみようと思います。

納車してすぐにコーディングに手を出して、それから安定して放置していたので、現状整理を兼ねてどういう手順で初期化していけばいいか備忘録として残します。

あと、助手席側ドアノブのコンフォートアクセスも反応がしないようになっていたため、ついでにディーラーで見てもらいます。

中古車保証が効いてるうちでよかった。

現状のコーディング状況

  • デジタルスピード表示
  • デイライト有効化
  • デイライト輝度調整 ← 入れただけで多分効いてない
  • USサイドマーカー有効化
  • ロック連動ミラークローズ時間変更
  • シートベルト警告無効化
  • リバース時ミラー角度変更

変更している箇所は上記のとおりです。
定番コーディングだけで特にややこしいことはしていないのですが、
デイライトに関してCIC経由で有効化にしても20分くらいしたらもとに戻ってしまう現象がありました。

解決策がネットにありましたが、試しても解決せず。
最終的に以下手順で解決しました。

  • KOMBIでデイライト有効化無効化オプション表示のコーディングを実施
    • KOMBIでのオプションは表示されず
  • CICでデイライト有効化無効化オプション表示のコーディングを実施
    • 設定項目にデイライトが追加され、有効化
  • 20分位経つとiDrive上からデイライト項目が消えるのですが、デイライトは有効のまま
    • KOMBIのコーディング実施しなければ、デイライトも同時に無効化されてました。

KOMBI側で設定を保持するようになったため、解決したのだと思っていますが、初期化のときにどうなるか不安要素の1つです。

一応、以下の手順で初期化を実施予定です

  • CICでデイライト有効化、無効化オプションの表示
  • iDrive上からデイライト設定を無効化
  • 時間が経てばCICコーディングは初期化される
    • この状態でデイライトは無効化のままのはず
  • KOMBIコーディングを初期化
    • これでもとに戻るのではという想定

ひとまず試してみます。

共有

【SOL26】今更だけどXperiaZ3にAndroid6.0.1でrootを取得してみた。

MVNOに移行したので、SOL26にグローバルD6603のAndroid6.0.1のROMを焼いて、rootを取得してみる記録を残します。

docomo系のMVNOを使用するので、SIMロック解除は必須です。
僕はデータ通信専用SIMで通話はこの端末では使わないので、通話機能は無視してます。

KitKatなD6603でとりあえずrootを取得する

[Guide]{Root}{Recovery} How to Root and install Recovery on Locked BL for NOOBS

この辺を参照して、一旦ロリポップでrootを取得しましょう。

23.0.A.2.93のROMをflashtoolで焼きます。
データ等はすべてwipeで。

上記、手順でrootを取得し、リカバリーまで焼けたら次のステップです。

prerootedなAndroid6のROMを焼く

[D66XX]{5.0/5.1/6.0} Flashable stock LP/MM pre-rooted collection & XZ dualrecovery

次はこの辺を参照して、好きなバージョンのROMを落としましょう。

僕は「D6603_23.5.A.1.291_Customized_IT_RecRoot」を選択しました。

これを端末に持ってきて、リカバリーから焼くだけです。

共有

【MacOSX】Mac OSX のHDD容量を削減してみた

中古で格安で購入した、Mac mini Server (Mid 2011)ですが、最近SDDの容量が結構カツカツになってきていることに気づきました。

128GBのSDDに交換したのですが、Windowsと違ってデータの保存場所をあまり気にせずほいほい使ってるといつの間にか容量が。。。ってことになるような気がします。

そこでデータ整理もかねて、Mac miniのHDD容量削減を行ってみました。

参考にしたのは下記のNaverまとめ

初級/Macの容量がいっぱいになったときに見るまとめ

実際に行ってみました。

OnyXでメンテナンス

20150804202948

久しくやってなかったので、とりあえず自動処理をひと通りやっときました。

SSDにデータファイルがないかチェック

20150804203756

Disk Inventory X
こちらのソフトを使用して、ディスク容量を可視化し、いらないファイルを探します。

僕の場合は、Lightroomのバックアップファイルとか置きっぱなしだった動画ファイルとかですね。

itunes関連のファイルを整理

割りと容量食ってたのが、iPhone, iPadとかのバックアップファイル。
itunesの設定から「デバイス」の項目で削除しましょう!
あとはいらないAppファイルも消して、一旦終わり。

結果は

削除前

20150804213659

削除後

20150804213714

約35GB減らしたかな!

割りと置きっぱなしだった動画ファイルが結構大きかったっていう・・・

でも、何が容量食ってたのか把握できるいい機会でした!

共有

【MacOSX】Macでスクリーンショットの撮影と保存場所を変更してみた

ブログでMac関連の記事を書くとなると、スクリーンショットを載せたいと思うことが多々ありますが、
Mac乗り換えたてではどうやって撮ればいいのかわかりませんでした。
そもそもソフト入れないと撮れないと思ってた。。。

以下の方法で簡単にできました。

ブログに載せたいときなどに多用するであろう、指定したウィンドウのスクリーンショットを撮る方法

「command + shift + 4 」キーを押しながら、「space」キーを押す

そうすると、カーソルがカメラアイコンに変わりますので、撮影したいウィンドウ上でクリックします。

20150801114255

そしたらデスクトップに保存された!

整理が大変ではないか!
デスクトップにファイルを置くのはどうも好きじゃないのです。

ということでスクリーンショットのデフォルト保存場所を変更してみた

ターミナルから

1
defaults write com.apple.screencapture location "保存したいディレクトリ"

ちなみに、保存時の名前も変えたい場合は以下で指定できます。

1
defaults write com.apple.screencapture name sshot

上記を実行した場合、ファイル名は「sshot 2015-08-01 11.42.33.png」のようになります。

デフォルト保存場所をHDDに変更したので、撮りまくっても容量を気にしなくて済みそう!

共有

【さくらVPS】メールサーバ導入してみる(sendmail)

postfixで動かしてるメールサーバがあるのですが、
仕事で扱うサーバがsendmailなので、sendmailでも作ってみます。

CentOS6.5のさくらVPSはもともとpostfixがインストールされているので、sendmailをコンフィグツールと一緒に入れときます。

1
2
# yum install sendmail
# yum install sendmail-cf

設定ツールファイルの編集

1
# vi /etc/mail/sendmail.cf

このファイルの

1
DAEMON_OPTIONS(`Port=smtp,Addr=127.0.0.1, Name=MTA')dnl

の、127.0.0.1を消して

1
DAEMON_OPTIONS(`Port=smtp, Name=MTA')dnl

とします。

次に

1
LOCAL_DOMAIN(`localhost.localdomain')dnl

の、127.0.0.1を消して

1
LOCAL_DOMAIN(`str-project.tk')dnl

とします。

共有