TailwindCSS Todoリスト

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Todo List with Tailwind CSS</title>
    <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
</head>
<body class="bg-gray-100 h-screen flex justify-center items-center">
    <div class="max-w-md w-full">
        <h1 class="text-center text-2xl font-bold mb-4">Todo List</h1>
        <div class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4">
            <div class="mb-4">
                <input type="text" placeholder="Add new task..." class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="taskInput">
            </div>
            <div class="flex items-center justify-between">
                <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline" id="addTaskBtn">
                    Add Task
                </button>
                <div>
                    <button class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline filter-btn" data-filter="all">
                        All
                    </button>
                    <button class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline filter-btn" data-filter="active">
                        Active
                    </button>
                    <button class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline filter-btn" data-filter="completed">
                        Completed
                    </button>
                </div>
            </div>
        </div>
        <ul id="taskList" class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4">
            <!-- Tasks will be dynamically added here -->
        </ul>
        <div class="flex justify-between">
            <p id="taskCounter" class="text-gray-600"></p>
            <button class="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline" id="clearCompletedBtn">
                Clear Completed
            </button>
        </div>
    </div>

    <script>
        let tasks = [];

        function renderTasks(filter) {
            const taskList = document.getElementById("taskList");
            taskList.innerHTML = "";

            tasks.forEach((task, index) => {
                if (filter === "all" || (filter === "active" && !task.completed) || (filter === "completed" && task.completed)) {
                    const listItem = document.createElement("li");
                    listItem.className = "flex justify-between items-center border-b py-2";
                    listItem.innerHTML = `
                        <span class="text-gray-700 ${task.completed ? 'line-through' : ''}">${task.text}</span>
                        <div>
                            <button class="text-green-500 hover:text-green-700 focus:outline-none" onclick="toggleTaskStatus(${index})">
                                ${task.completed ? `
                                    <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
                                        <path fill-rule="evenodd" d="M0 11l2-2 5 5L18 3l2 2L7 18z" clip-rule="evenodd" />
                                    </svg>
                                ` : `
                                    <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                        <path d="M19 9l-9 9-5-5"></path>
                                    </svg>
                                `}
                            </button>
                            <button class="text-blue-500 hover:text-blue-700 focus:outline-none" onclick="editTask(${index})">
                                <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
                                    <path fill-rule="evenodd" d="M3 17a2 2 0 01-2-2V6a2 2 0 012-2h5a2 2 0 011 3.732V15h5a2 2 0 012 2v2a2 2 0 01-2 2H3zm12-7V5a1 1 0 00-1-1H7a1 1 0 00-1 1v5h9zm-4 3h2v2h-2v-2z" clip-rule="evenodd"></path>
                                </svg>
                            </button>
                            <button class="text-red-500 hover:text-red-700 focus:outline-none" onclick="deleteTask(${index})">
                                <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
                                    <path fill-rule="evenodd" d="M5.293 6.293a1 1 0 011.414 1.414L11 11.414l4.293-4.293a1 1 0 111.414 1.414L12.414 12l4.293 4.293a1 1 0 01-1.414 1.414L11 13.414l-4.293 4.293a1 1 0 01-1.414-1.414L9.586 12 5.293 7.707a1 1 0 010-1.414z" clip-rule="evenodd" />
                                </svg>
                            </button>
                        </div>
                    `;
                    taskList.appendChild(listItem);
                }
            });

            updateTaskCounter();
        }

        function addTask(text) {
            tasks.push({ text: text, completed: false });
            renderTasks();
        }

        function deleteTask(index) {
            tasks.splice(index, 1);
            renderTasks();
        }

        function editTask(index) {
            const newText = prompt("Edit Task", tasks[index].text);
            if (newText !== null) {
                tasks[index].text = newText.trim();
                renderTasks();
            }
        }

        function toggleTaskStatus(index) {
            tasks[index].completed = !tasks[index].completed;
            renderTasks();
        }

        function clearCompletedTasks() {
            tasks = tasks.filter(task => !task.completed);
            renderTasks();
        }

        function updateTaskCounter() {
            const taskCounter = document.getElementById("taskCounter");
            const activeTasks = tasks.filter(task => !task.completed).length;
            const taskWord = activeTasks === 1 ? "task" : "tasks";
            taskCounter.textContent = `${activeTasks} ${taskWord} left`;
        }

        document.getElementById("addTaskBtn").addEventListener("click", function() {
            const taskInput = document.getElementById("taskInput");
            const taskText = taskInput.value.trim();

            if (taskText !== "") {
                addTask(taskText);
                taskInput.value = "";
            }
        });

        document.getElementById("clearCompletedBtn").addEventListener("click", function() {
            clearCompletedTasks();
        });

        document.querySelectorAll(".filter-btn").forEach(btn => {
            btn.addEventListener("click", function() {
                const filter = this.getAttribute("data-filter");
                renderTasks(filter);
            });
        });

        // Initial render
        renderTasks();
    </script>
</body>
</html>

投稿者: chosuke

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

コメントを残す

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