Ahmed303's picture
Create a Todo List, with a todo list section, and a history section.
405b9a1 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FuchsiTodos</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/feather-icons"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
body {
font-family: 'Poppins', sans-serif;
}
.glow {
box-shadow: 0 0 15px rgba(217, 70, 239, 0.5);
}
.task-checkbox:checked + .task-label {
text-decoration: line-through;
color: #9ca3af;
}
.fade-in {
animation: fadeIn 0.3s ease-in;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
</style>
</head>
<body class="bg-gray-50 min-h-screen">
<div class="container mx-auto px-4 py-8 max-w-2xl">
<!-- Header -->
<header class="flex justify-between items-center mb-10">
<h1 class="text-3xl font-bold text-fuchsia-600">
<span class="inline-flex items-center">
<i data-feather="check-circle" class="mr-2"></i>
FuchsiTodos
</span>
</h1>
<div class="flex space-x-2">
<button id="todoTab" class="px-4 py-2 rounded-lg bg-fuchsia-600 text-white font-medium hover:bg-fuchsia-700 transition">Todo</button>
<button id="historyTab" class="px-4 py-2 rounded-lg bg-gray-200 text-gray-700 font-medium hover:bg-gray-300 transition">History</button>
</div>
</header>
<!-- Todo Section -->
<section id="todoSection" class="space-y-6">
<!-- Add Task -->
<div class="flex items-center space-x-2 mb-6">
<input type="text" id="newTaskInput" placeholder="Add a new task..." class="flex-1 px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-fuchsia-500 focus:border-transparent">
<button id="addTaskBtn" class="px-6 py-3 bg-fuchsia-600 text-white rounded-lg hover:bg-fuchsia-700 transition flex items-center">
<i data-feather="plus" class="mr-1"></i> Add
</button>
</div>
<!-- Task List -->
<div id="taskList" class="space-y-3">
<!-- Tasks will be added here dynamically -->
<div class="text-center py-10 text-gray-400" id="emptyState">
<i data-feather="inbox" class="w-12 h-12 mx-auto mb-3"></i>
<p>No tasks yet. Add one above!</p>
</div>
</div>
</section>
<!-- History Section (Hidden by default) -->
<section id="historySection" class="space-y-6 hidden">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-semibold text-gray-700">Completed Tasks</h2>
<button id="clearHistoryBtn" class="text-sm text-fuchsia-600 hover:text-fuchsia-800 flex items-center">
<i data-feather="trash-2" class="w-4 h-4 mr-1"></i> Clear All
</button>
</div>
<div id="historyList" class="space-y-3">
<!-- Completed tasks will be added here dynamically -->
<div class="text-center py-10 text-gray-400" id="emptyHistoryState">
<i data-feather="clock" class="w-12 h-12 mx-auto mb-3"></i>
<p>No completed tasks yet. Get to work!</p>
</div>
</div>
</section>
<!-- Stats -->
<div class="mt-10 p-4 bg-white rounded-xl shadow-sm">
<div class="flex justify-between items-center">
<div class="text-center">
<p class="text-sm text-gray-500">Tasks Today</p>
<p id="taskCount" class="text-2xl font-bold text-gray-800">0</p>
</div>
<div class="text-center">
<p class="text-sm text-gray-500">Completed</p>
<p id="completedCount" class="text-2xl font-bold text-fuchsia-600">0</p>
</div>
<div class="text-center">
<p class="text-sm text-gray-500">Pending</p>
<p id="pendingCount" class="text-2xl font-bold text-gray-800">0</p>
</div>
</div>
</div>
</div>
<script>
// Initialize Feather Icons
feather.replace();
// DOM Elements
const todoSection = document.getElementById('todoSection');
const historySection = document.getElementById('historySection');
const todoTab = document.getElementById('todoTab');
const historyTab = document.getElementById('historyTab');
const newTaskInput = document.getElementById('newTaskInput');
const addTaskBtn = document.getElementById('addTaskBtn');
const taskList = document.getElementById('taskList');
const historyList = document.getElementById('historyList');
const clearHistoryBtn = document.getElementById('clearHistoryBtn');
const emptyState = document.getElementById('emptyState');
const emptyHistoryState = document.getElementById('emptyHistoryState');
const taskCount = document.getElementById('taskCount');
const completedCount = document.getElementById('completedCount');
const pendingCount = document.getElementById('pendingCount');
// Tasks and History Arrays
let tasks = JSON.parse(localStorage.getItem('tasks')) || [];
let history = JSON.parse(localStorage.getItem('history')) || [];
// Tab Switching
todoTab.addEventListener('click', () => {
todoSection.classList.remove('hidden');
historySection.classList.add('hidden');
todoTab.classList.remove('bg-gray-200', 'text-gray-700');
todoTab.classList.add('bg-fuchsia-600', 'text-white');
historyTab.classList.remove('bg-fuchsia-600', 'text-white');
historyTab.classList.add('bg-gray-200', 'text-gray-700');
});
historyTab.addEventListener('click', () => {
todoSection.classList.add('hidden');
historySection.classList.remove('hidden');
todoTab.classList.add('bg-gray-200', 'text-gray-700');
todoTab.classList.remove('bg-fuchsia-600', 'text-white');
historyTab.classList.add('bg-fuchsia-600', 'text-white');
historyTab.classList.remove('bg-gray-200', 'text-gray-700');
renderHistory();
});
// Add New Task
function addTask() {
const taskText = newTaskInput.value.trim();
if (taskText) {
const newTask = {
id: Date.now(),
text: taskText,
completed: false,
timestamp: new Date().toISOString()
};
tasks.unshift(newTask);
saveTasks();
renderTasks();
newTaskInput.value = '';
updateStats();
}
}
addTaskBtn.addEventListener('click', addTask);
newTaskInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') addTask();
});
// Toggle Task Completion
function toggleTaskCompletion(taskId) {
const taskIndex = tasks.findIndex(task => task.id === taskId);
if (taskIndex !== -1) {
const task = tasks[taskIndex];
task.completed = !task.completed;
if (task.completed) {
// Move to history if completed
history.unshift({...task, completedAt: new Date().toISOString()});
tasks.splice(taskIndex, 1);
}
saveTasks();
saveHistory();
renderTasks();
updateStats();
}
}
// Delete Task
function deleteTask(taskId) {
tasks = tasks.filter(task => task.id !== taskId);
saveTasks();
renderTasks();
updateStats();
}
// Clear History
function clearHistory() {
history = [];
saveHistory();
renderHistory();
}
clearHistoryBtn.addEventListener('click', clearHistory);
// Render Tasks
function renderTasks() {
if (tasks.length === 0) {
emptyState.classList.remove('hidden');
taskList.innerHTML = '';
} else {
emptyState.classList.add('hidden');
taskList.innerHTML = '';
tasks.forEach(task => {
const taskElement = document.createElement('div');
taskElement.className = 'fade-in bg-white p-4 rounded-lg shadow-sm hover:shadow-md transition flex items-center justify-between';
taskElement.innerHTML = `
<div class="flex items-center space-x-3">
<input type="checkbox" id="task-${task.id}" class="task-checkbox h-5 w-5 text-fuchsia-600 rounded focus:ring-fuchsia-500" ${task.completed ? 'checked' : ''}>
<label for="task-${task.id}" class="task-label text-gray-800 ${task.completed ? 'line-through text-gray-400' : ''}">${task.text}</label>
</div>
<button data-id="${task.id}" class="delete-btn text-gray-400 hover:text-fuchsia-600 transition">
<i data-feather="trash-2" class="w-5 h-5"></i>
</button>
`;
taskList.appendChild(taskElement);
// Add event listeners
const checkbox = taskElement.querySelector(`#task-${task.id}`);
checkbox.addEventListener('change', () => toggleTaskCompletion(task.id));
const deleteBtn = taskElement.querySelector('.delete-btn');
deleteBtn.addEventListener('click', () => deleteTask(task.id));
});
}
feather.replace();
}
// Render History
function renderHistory() {
if (history.length === 0) {
emptyHistoryState.classList.remove('hidden');
historyList.innerHTML = '';
} else {
emptyHistoryState.classList.add('hidden');
historyList.innerHTML = '';
history.forEach(task => {
const historyElement = document.createElement('div');
historyElement.className = 'fade-in bg-white p-4 rounded-lg shadow-sm hover:shadow-md transition';
const completedDate = new Date(task.completedAt).toLocaleString();
historyElement.innerHTML = `
<div class="flex justify-between items-center">
<span class="text-gray-600 line-through">${task.text}</span>
<span class="text-xs text-gray-400">${completedDate}</span>
</div>
`;
historyList.appendChild(historyElement);
});
}
feather.replace();
}
// Update Stats
function updateStats() {
const totalTasks = tasks.length + history.length;
taskCount.textContent = totalTasks;
completedCount.textContent = history.length;
pendingCount.textContent = tasks.filter(t => !t.completed).length;
}
// Save to LocalStorage
function saveTasks() {
localStorage.setItem('tasks', JSON.stringify(tasks));
}
function saveHistory() {
localStorage.setItem('history', JSON.stringify(history));
}
// Initial Render
renderTasks();
updateStats();
</script>
</body>
</html>