PR
スポンサーリンク

Vue.jsでTodoアプリを作成する(期限の設定)

前回のVue.jsでTodoアプリを作るで基本的なTodoの追加、完了、削除はできるようになったので、今回は期限の設定と以下の画像のように期限が過ぎていたら赤色に表示するようにしていきたいと思います。

実際にコードを見ていきましょう。前回からコードの変更や追加された箇所に関しては文字色を赤くしているので、参考になれば幸いです。

C:/npm_sample\/src/App.vue

<template>
  <div id="app">
    <h1>ToDo List</h1>
    <input type="text" v-model="newTodo" @keyup.enter="addTodo">
    <input type="date" v-model="newTodoDueDate">
    <button @click="addTodo">Add</button>

    <ul>
      <li v-for="(todo, index) in todos" :key="index" 
        :class="{ 'completed': todo.completed, 'pastDue': isPastDue(todo.dueDate) }">
        {{ todo.text }} - 期限: {{  todo.dueDate  }}
        <button @click="toggleCompleted(index)">{{ todo.buttonText }}</button>
        <button @click="deleteTodo(index)" class="deleteButton">削除</button>
      </li>
    </ul>
  </div>
</template>


<script>
export default {
  data() {
    return {
      newTodo: '',
      newTodoDueDate: '',
      todos: [],
    }
  },
  methods: {
    addTodo() {
      if (this.newTodo.trim() && this.newTodoDueDate) {
        // 新しいToDo項目を追加するとき、buttonTextプロパティを含めます
        this.todos.push({ 
          text: this.newTodo,
          completed: false,
          buttonText: '完了',
          dueDate: this.newTodoDueDate // 期限日を追加
        });
        this.newTodo = ''; // フィールドをリセット
        this.newTodoDueDate = ''; // 期限日フィールドをリセット
      }
    },
    toggleCompleted(index) {
      // 特定のToDo項目のcompleted状態とbuttonTextを更新
      this.todos[index].completed = !this.todos[index].completed;
      this.todos[index].buttonText = this.todos[index].completed ? '戻す' : '完了';
    },
    deleteTodo(index) {
      if (window.confirm("本当に削除しますか?")) {
        this.todos.splice(index, 1);
      }
    },
    isPastDue(dueDate) {
      const today = new Date();
      today.setHours(0, 0, 0, 0); // 時間をリセットして今日の日付のみにする
      const due = new Date(dueDate);
      return due < today; //期限が今日より前であればtrueを返す
    }
  }
}
</script>


<style>
#app {
  max-width: 600px;
  margin: 0 auto;
  font-family: 'Helvetica Neue', Arial, sans-serif;
}

input[type="text"] {
  padding: 10px;
  border: 2px solid #ccc;
  border-radius: 4px;
  width: 70%;
  margin-right: 5px;
}

input[type="date"] {
  padding: 10px;
  border: 2px solid #ccc;
  border-radius: 4px;
  font-family: 'Helvetica Neue', Arial, sans-serif;
  font-size: 16px;
  cursor: pointer;
  background-color: white;
  margin-right: 5px;
}

/* フォーカス時のスタイル */
input[type="date"]:focus {
  outline: none;
  border-color: #4CAF50;
}

button {
  background-color: #4CAF50; /* 緑色のボタン */
  border: none; /* 枠線なし */
  color: white; /* テキスト色 */
  padding: 10px 15px; /* パディング */
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  transition-duration: 0.4s; /* ホバー効果のためのトランジション */
  cursor: pointer; /* マウスカーソルを指に */
  border-radius: 4px; /* 角を丸く */
}

button:hover {
  background-color: #45a049; /* ホバー時に少し暗く */
}

.deleteButton {
  background-color: rgb(243, 24, 24); /* 緑色のボタン */
  border: none; /* 枠線なし */
  color: white; /* テキスト色 */
  padding: 10px 15px; /* パディング */
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  transition-duration: 0.4s; /* ホバー効果のためのトランジション */
  cursor: pointer; /* マウスカーソルを指に */
  border-radius: 4px; /* 角を丸く */
}

.deleteButton:hover {
  background-color: #931a1a; /* ホバー時に少し暗く */
}

.completed {
  text-decoration: line-through;
}

ul {
  list-style-type: none; /* リストのスタイルをなしに */
  padding: 0;
}

li {
  margin: 8px 0;
}

.pastDue {
  color: red;
}
</style>

コメント

タイトルとURLをコピーしました