タスク管理.html

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>AIベースのタスク管理アプリ</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      background-color: #f4f4f9;
      margin: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      align-items: center;
    }
    h1 {
      color: #333;
    }
    .task-container {
      width: 90%;
      max-width: 1200px;
      padding: 20px;
    }
    .task-form {
      display: flex;
      flex-direction: column;
      margin-bottom: 20px;
    }
    .task-form input, .task-form textarea {
      margin-bottom: 10px;
      padding: 10px;
      font-size: 16px;
      border: 1px solid #ccc;
      border-radius: 5px;
    }
    .task-form button {
      padding: 10px;
      background-color: #28a745;
      color: #fff;
      border: none;
      border-radius: 5px;
      cursor: pointer;
    }
    .task-form button:hover {
      background-color: #218838;
    }
    .kanban-board {
      display: flex;
      justify-content: space-around;
    }
    .kanban-column {
      background-color: #f8f9fa;
      padding: 20px;
      width: 30%;
      border-radius: 10px;
      min-height: 300px;
    }
    .kanban-column h2 {
      text-align: center;
    }
    .task-list {
      margin-top: 10px;
    }
    .task-item {
      display: flex;
      justify-content: space-between;
      background-color: #e9ecef;
      margin-bottom: 10px;
      padding: 10px;
      border-radius: 5px;
    }
    .task-item.high {
      background-color: #ffcccc;
    }
    .task-item.medium {
      background-color: #fff3cd;
    }
    .task-item.low {
      background-color: #d4edda;
    }
    .task-item button {
      background-color: #dc3545;
      color: #fff;
      border: none;
      border-radius: 5px;
      cursor: pointer;
    }
    .task-item button:hover {
      background-color: #c82333;
    }
  </style>
</head>
<body>

  <h1>タスク管理</h1>
  <div class="task-container">
    <form class="task-form" id="taskForm">
      <input type="text" id="taskTitle" placeholder="タスクタイトル" required>
      <textarea id="taskDescription" placeholder="タスク詳細" rows="4"></textarea>
      <input type="date" id="taskDueDate" required>
      <button type="submit">タスクを追加</button>
    </form>

    <div class="kanban-board">
      <div class="kanban-column" id="notStarted">
        <h2>未着手</h2>
        <div class="task-list" id="notStartedList"></div>
      </div>
      <div class="kanban-column" id="inProgress">
        <h2>進行中</h2>
        <div class="task-list" id="inProgressList"></div>
      </div>
      <div class="kanban-column" id="completed">
        <h2>完了</h2>
        <div class="task-list" id="completedList"></div>
      </div>
    </div>
  </div>

  <script>
    let tasks = JSON.parse(localStorage.getItem('tasks')) || [];

    // 優先度予測(ルールベース)
    function predictPriority(taskDueDate) {
      const daysLeft = (new Date(taskDueDate) - new Date()) / (1000 * 60 * 60 * 24);
      if (daysLeft < 2) {
        return 'High';  // 緊急度が高い
      } else if (daysLeft < 7) {
        return 'Medium';  // 1週間以内
      } else {
        return 'Low';  // 余裕がある
      }
    }

    // タスクをローカルストレージに保存
    function saveTasks() {
      localStorage.setItem('tasks', JSON.stringify(tasks));
    }

    // タスク表示
    function loadTasks() {
      const notStartedList = document.getElementById('notStartedList');
      const inProgressList = document.getElementById('inProgressList');
      const completedList = document.getElementById('completedList');

      notStartedList.innerHTML = '';
      inProgressList.innerHTML = '';
      completedList.innerHTML = '';

      tasks.forEach(task => {
        const taskItem = document.createElement('div');
        taskItem.classList.add('task-item', task.priority.toLowerCase());
        taskItem.setAttribute('draggable', true);
        taskItem.innerHTML = `
          <div>
            <strong>${task.title}</strong>
            <p>${task.description}</p>
            <small>期限: ${new Date(task.dueDate).toLocaleDateString()}</small>
            <p>優先度: ${task.priority}</p>
          </div>
          <button onclick="deleteTask('${task.id}')">削除</button>
        `;

        taskItem.addEventListener('dragstart', (e) => {
          e.dataTransfer.setData('text/plain', task.id);
        });

        if (task.status === 'notStarted') {
          notStartedList.appendChild(taskItem);
        } else if (task.status === 'inProgress') {
          inProgressList.appendChild(taskItem);
        } else if (task.status === 'completed') {
          completedList.appendChild(taskItem);
        }
      });
    }

    // タスク追加
    document.getElementById('taskForm').addEventListener('submit', (e) => {
      e.preventDefault();
      const title = document.getElementById('taskTitle').value;
      const description = document.getElementById('taskDescription').value;
      const dueDate = document.getElementById('taskDueDate').value;

      const priority = predictPriority(dueDate);

      const newTask = {
        id: Date.now().toString(),
        title,
        description,
        dueDate,
        priority,
        status: 'notStarted'  // 初期状態は未着手
      };

      tasks.push(newTask);
      saveTasks();
      document.getElementById('taskForm').reset();
      loadTasks();
    });

    // タスク削除
    function deleteTask(taskId) {
      tasks = tasks.filter(task => task.id !== taskId);
      saveTasks();
      loadTasks();
    }

    // ドラッグ&ドロップの設定
    document.querySelectorAll('.kanban-column').forEach(column => {
      column.addEventListener('dragover', (e) => {
        e.preventDefault();
      });

      column.addEventListener('drop', (e) => {
        const taskId = e.dataTransfer.getData('text/plain');
        const newStatus = column.id;

        const task = tasks.find(task => task.id === taskId);
        task.status = newStatus;
        saveTasks();
        loadTasks();
      });
    });

    // ページ読み込み時にタスクを表示
    loadTasks();
  </script>

</body>
</html>

投稿者: chosuke

趣味はゲームやアニメや漫画などです

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です