Vue.jsでTodoistを模してTodoアプリを作ってみた②

# はじめに
[Vue.jsでTodoistを模してTodoアプリを作ってみた①](https://qiita.com/Tekere/items/7a7e38f1bf97226ce304)の続きです。

今回は３種類のページと、Mixin、ヘルパーとして切り出したファイルを紹介していきます。

## Mixinとhelper

### Mixin.js
Inbox Today Fewdays で共通する部分をまとめています。

```js
export default {
  data() {
    return {
      createFormShow: false
    };
  },
  methods: {
    // タスク作成エディタのオープン・クローズ
    toggleCreateForm() {
      this.createFormShow = !this.createFormShow;
    },
    // タスク完了メソッド
    doneTask(task) {
      this.$store.dispatch('tasksModule/doneTask', task);
    }
  }
};

```

### helper.js
さまざまな場所で使われる関数をヘルパーとして作成しました。

```js
// YMDに変換
export const formatDate = function(dt) {
  var y = dt.getFullYear();
  var m = ('00' + (dt.getMonth() + 1)).slice(-2);
  var d = ('00' + dt.getDate()).slice(-2);
  return y + '-' + m + '-' + d;
};
// YMDから日付を取得
export const getDateFromYMD = function(ymd) {
  const result = new Date(ymd);
  return result.getDate();
};

//   // 日付から特定の条件で色分けするためのメソッド
export const addClassDateColor = function(dueDate) {
  const resultObj = {
    today: false,
    tomorrow: false,
    expired: false
  };
  if (dueDate == '今日') {
    resultObj.today = true;
  } else if (dueDate == '明日') {
    resultObj.tomorrow = true;
  } else if (dueDate.match(/期限切れ/)) {
    resultObj.expired = true;
  }
  return resultObj;
};
```

## Views

### Inbox.vue
全てのタスクを表示するコンポーネントです。

```vuejs
<template>
  <div class="home">
    <div class="header">
      <div class="header-content">
        <h1>インボックス</h1>
      </div>
    </div>
    <div class="list-editor">
      <task-list :tasks="tasks"></task-list>
    </div>
    <create-editor
      :createFormShow="createFormShow"
      @click-toggle="toggleCreateForm"
    ></create-editor>
  </div>
</template>

<script>
import TaskList from '../components/TaskList';
import CreateEditor from '../components/CreateEditor';
import Mixin from '../mixin';

export default {
  name: 'Inbox',
  mixins: [Mixin],
  components: { TaskList, CreateEditor },

  computed: {
    // sortされたタスク一覧が渡ってきます
    tasks() {
      return this.$store.getters['tasksModule/tasks'];
    }
  }
};
</script>
```


### Today.vue

```vue
<template>
  <div class="home">
    <div class="header">
      <div class="header-content">
        <h1>今日</h1>
      </div>
    </div>
    <div class="list-editor">
      <task-list :tasks="todayTasks"></task-list>
    </div>
    <create-editor
      :createFormShow="createFormShow"
      @click-toggle="toggleCreateForm"
    ></create-editor>
  </div>
</template>

<script>
import TaskList from '../components/TaskList';
import CreateEditor from '../components/CreateEditor';
import Mixin from '../mixin';
const today = new Date();
export default {
  name: 'Today',
  mixins: [Mixin],
  components: { TaskList, CreateEditor },

  computed: {
    todayTasks() {
      const tasks = this.$store.getters['tasksModule/tasks'];
      // 今日のタスクのみにする
      return tasks.filter(el => {
        // gettersから取得したタイムスタンプ型の期日
        const taskDueDate = new Date(el.data.dueDate.seconds * 1000);
        // お互いの日付を比較して本日のみfilterにかけます
        return ( taskDueDate.getDate() == today.getDate());
      });
    }
  },
  methods: {}
};
```

### FewDays.vue

```vue
<template>
  <div class="few-days">
    <div class="header">
      <div class="header-content">
        <h1>近日予定</h1>
      </div>
      <div class="nav-bar">
        <a href="" @click.prevent="prevWeek">prev</a>
        <a href="" @click.prevent="nextWeek">next</a>
      </div>
      <ul uk-tab>
        <li
          v-for="(day, index) in selectedWeek"
          :key="index"
          :class="{ 'uk-active': day.isToday, disabled: day.isPast }"
        >
          <a href="#" @click="selectDate(day.date)"
            ><span>{{ day.day }} </span> {{ getDateFromYMD(day.date) }}</a
          >
        </li>
      </ul>
    </div>
    <div class="list-editor">
      <task-list :tasks="tasksOfSelectedDate"></task-list>
    </div>
    <create-editor
      :createFormShow="createFormShow"
      :selectedDate="selectedDate"
      @click-toggle="toggleCreateForm"
    ></create-editor>
  </div>
</template>
<script>
import TaskList from '../components/TaskList.vue';
import CreateEditor from '../components/CreateEditor';
import Mixin from '../mixin';
import { formatDate, getDateFromYMD } from '../helper';

const DAY = ['日', '月', '火', '水', '木', '金', '土'];
const WEEK_NUM = 7;
const today = new Date();
const todayDate = formatDate(today);
const thisSunday = formatDate(
  new Date(today.setDate(today.getDate() - today.getDay()))
);

export default {
  name: 'Fewdays',
  mixins: [Mixin],

  components: { TaskList, CreateEditor },
  data() {
    return {
      selectedDate: todayDate,
      displaySunday: ''
    };
  },
  computed: {
    // 選択された日のタスクを取得
    tasksOfSelectedDate() {
      const tasks = this.$store.getters['tasksModule/tasks'];
      const that = this;
      const result = tasks.filter(el => {
        const taskDueDate = new Date(el.data.dueDate.seconds * 1000);
        return formatDate(taskDueDate) == that.selectedDate;
      });
      console.log(result);
      return result;
    },
    selectedWeek() {
      // １週間を作成

      let i = 0;
      // 配列で週を生成
      const selectedWeek = DAY.reduce((acc, el) => {
        const date = new Date(this.displaySunday);
        date.setDate(date.getDate() + i);

        const displayDateObj = {
          date: formatDate(date),
          day: el,
          isToday: false,
          isPast: false
        };

        if (displayDateObj.date == todayDate) {
          displayDateObj.isToday = true;
        } else if (date < new Date(todayDate)) {
          displayDateObj.isPast = true;
        }
        acc.push(displayDateObj);
        i++;
        return acc;
      }, []);
      return selectedWeek;
    }
  },
  methods: {
    selectDate(val) {
      this.selectedDate = val;
    },
    getDateFromYMD,
    // 表示する週を前に移動するメソッド
    prevWeek() {
      const currentDisplaySunday = new Date(this.displaySunday);
      currentDisplaySunday.setDate(currentDisplaySunday.getDate() - WEEK_NUM);
      this.displaySunday = formatDate(new Date(currentDisplaySunday));
    },
    // 表示する週を次に移動するメソッド
    nextWeek() {
      const currentDisplaySunday = new Date(this.displaySunday);
      currentDisplaySunday.setDate(currentDisplaySunday.getDate() + WEEK_NUM);
      this.displaySunday = formatDate(new Date(currentDisplaySunday));
    }
  },
  created() {
    this.selectedDate = todayDate;
    this.displaySunday = thisSunday;
  }
};
</script>
```

# おわりに
もう少しコードをきれいにできそうな部分が多々ありそうですね。
ちょこちょこ編集していきたいです。。

あとmoment使うべきでした！！