Laravel+Vuejs（vuex、vue-router）を使ってWeb出席簿を作ってみた

## きっかけ

長年地元の少年サッカークラブのコーチをしていまして、今はもう名前だけの在籍で全く関わってないのですが、スタッフ達との交流はそれなりにあるんですね。
で、今年の3月初旬、久しぶりにスタッフミーティングに顔を出したんですね。
そしたらスタッフの長から、とある悩みを打ち明けられたんですよ。


## 長の悩み

- 毎練習時に「紙」の名簿で選手の出欠をつけている
- 年度末に皆勤賞を発表するため、一人ひとりの出欠状況をその名簿で確認している
- 数え間違いもあるだろうし、何より圧倒的時間浪費・・・！
- だからなんとかもっと簡単にできんのか
- なんとかできない？
- なんとかしてくれ


## 所感

え、それスプレッドシートでやればいいんじゃね？


## スプレッドシートで作ってみたら

チェックボックスをずらずら〜っと365日×人数分並べてみたら激重。表示するまで数分かかるレベル。
1ヶ月単位でシート分けるのもめんどくさいし、う〜んどうしよう。
ええいせっかくだから勉強がてらLaravelとVueで作っちゃおう！


## いざ開発

会員登録はLaravelデフォの機能を使用。
カレンダーはVueで作らず、1日ずつdateをレコード追加する形にして、seederで2050年3月まで流し込む。

### 開発環境

Laravel Homesteadを使用。

| Homestead | PHP   | Laravel | Vue.js | Vue Router | Vuex  |
|:---------:|:-----:|:-------:|:------:|:----------:|:-----:|
| 8.1.0     | 7.3.3 | 5.8.8   | 2.5.17 | 3.0.2      | 3.1.0 |


### DB設計

<details><summary>長いので折りたたみ</summary><div>

#### usersテーブル

```php
public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('name')->unique();
        $table->string('email')->unique();
        $table->timestamp('email_verified_at')->nullable();
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    });
}

public function down()
{
    Schema::dropIfExists('users');
}
```

ユーザー名でログインしたいので、nameをuniqueにした。

#### categoriesテーブル

```php
public function up()
{
    Schema::create('categories', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->bigInteger('user_id')->unsigned();
        $table->string('name')->nullable(false);
        $table->integer('sort')->nullable();
        $table->timestamps();

        $table->foreign('user_id')->references('id')->on('users');
    });
}

public function down()
{
    Schema::table('categories', function (Blueprint $table) {
        $table->dropForeign(['user_id']);
    });
    Schema::dropIfExists('categories');
}
```

学年分けをしたいので、カテゴリテーブルを作る。
ソート用のカラムも用意。

#### membersテーブル

```php
public function up()
{
    Schema::create('members', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->bigInteger('user_id')->unsigned();
        $table->string('name')->nullable(false);
        $table->bigInteger('category_id')->unsigned();
        $table->integer('sort')->nullable();
        $table->timestamps();

        $table->foreign('user_id')->references('id')->on('users');
        $table->foreign('category_id')->references('id')->on('categories');
    });
}

public function down()
{
    Schema::table('members', function (Blueprint $table) {
        $table->dropForeign(['user_id']);
        $table->dropForeign(['category_id']);
    });
    Schema::dropIfExists('members');
}
```

#### calendarsテーブル

```php
public function up()
{
    Schema::create('calendars', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->dateTime('date');
    });
}

public function down()
{
    Schema::dropIfExists('calendars');
}
```

#### holidaysテーブル

```php
public function up()
{
    Schema::create('holidays', function (Blueprint $table) {
        $table->dateTime('date');
        $table->string('name');
    });
}

public function down()
{
    Schema::dropIfExists('holidays');
}
```

なんとなく作ったけどこのテーブルは使ってないです。

#### statusesテーブル

```php
public function up()
{
    Schema::create('statuses', function (Blueprint $table) {
        $table->bigInteger('member_id')->unsigned();
        $table->bigInteger('calendar_id')->unsigned();
        $table->boolean('status');
        $table->timestamps();

        $table->foreign('member_id')->references('id')->on('members');
        $table->foreign('calendar_id')->references('id')->on('calendars');
    });
}

public function down()
{
    Schema::table('statuses', function (Blueprint $table) {
        $table->dropForeign(['member_id']);
        $table->dropForeign(['calendar_id']);
    });
    Schema::dropIfExists('statuses');
}
```

当初の予定だとstatusで出欠状況判定しようと思ったけど、レコードの有無で判定すればよくね？てなった。
statusの値で「早退／遅刻」とかやることもできるんじゃないかなと。
</div></details>

### フロント

いたって単純で、下記の機能／ページがあるだけ。

- ユーザー登録
- カテゴリ登録／編集
- メンバー登録／編集
- 集計

簡単な説明は下記。

- カテゴリ登録は必須（カテゴリがないとメンバー登録できない）
- トップページで出欠をつける
- 集計は期間を指定。デフォは当月分を表示


## 成果物とおソースと使い方

https://att-book.yuking11.net/
https://github.com/yuking11/att-book.yuking11.net


## 感想

- Laravel楽しい！
- Vue楽しい！
- vuexようわからん・・・
- DB設計むずい・・・

なにぶん雑魚ーダーってやつなので、見る人が見たらとんでもねぇクソコードだと罵倒されることを覚悟しつつビクビクしてます。

そして作るだけ作って満足してまだスタッフの長に連絡してないというオチ。