anycoder-2e309c83 / index.html
akhaliq's picture
akhaliq HF Staff
Upload folder using huggingface_hub
e0ac103 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TaskFlow - Modern Todo App</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--primary: #667eea;
--primary-dark: #5a67d8;
--secondary: #48bb78;
--danger: #f56565;
--warning: #ed8936;
--info: #4299e1;
--dark: #2d3748;
--light: #f7fafc;
--gray: #718096;
--border: #e2e8f0;
--shadow: rgba(0, 0, 0, 0.1);
--radius: 12px;
--transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
color: var(--dark);
transition: var(--transition);
}
body.dark-mode {
--light: #1a202c;
--dark: #f7fafc;
--border: #2d3748;
--shadow: rgba(0, 0, 0, 0.3);
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
header {
background: white;
border-radius: var(--radius);
padding: 25px;
margin-bottom: 30px;
box-shadow: 0 10px 30px var(--shadow);
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 20px;
animation: slideDown 0.5s ease;
}
.dark-mode header {
background: #2d3748;
color: var(--dark);
}
.logo {
display: flex;
align-items: center;
gap: 15px;
font-size: 28px;
font-weight: bold;
color: var(--primary);
}
.logo i {
font-size: 32px;
animation: pulse 2s infinite;
}
.header-actions {
display: flex;
gap: 15px;
align-items: center;
}
.theme-toggle {
background: var(--primary);
color: white;
border: none;
padding: 10px 15px;
border-radius: 50px;
cursor: pointer;
transition: var(--transition);
font-size: 18px;
}
.theme-toggle:hover {
transform: scale(1.1);
background: var(--primary-dark);
}
.main-content {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 30px;
animation: fadeIn 0.6s ease;
}
.sidebar {
background: white;
border-radius: var(--radius);
padding: 25px;
box-shadow: 0 10px 30px var(--shadow);
height: fit-content;
position: sticky;
top: 20px;
}
.dark-mode .sidebar {
background: #2d3748;
color: var(--dark);
}
.stats {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 15px;
margin-bottom: 30px;
}
.stat-card {
background: linear-gradient(135deg, var(--primary), var(--primary-dark));
color: white;
padding: 20px;
border-radius: var(--radius);
text-align: center;
transition: var(--transition);
}
.stat-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 20px var(--shadow);
}
.stat-number {
font-size: 32px;
font-weight: bold;
display: block;
}
.stat-label {
font-size: 14px;
opacity: 0.9;
margin-top: 5px;
}
.filters {
margin-bottom: 25px;
}
.filter-title {
font-size: 18px;
font-weight: 600;
margin-bottom: 15px;
color: var(--dark);
}
.dark-mode .filter-title {
color: var(--dark);
}
.filter-btn {
width: 100%;
padding: 12px;
margin-bottom: 10px;
background: var(--light);
border: 2px solid var(--border);
border-radius: 8px;
cursor: pointer;
transition: var(--transition);
display: flex;
align-items: center;
gap: 10px;
font-size: 15px;
}
.dark-mode .filter-btn {
background: #4a5568;
color: var(--dark);
}
.filter-btn:hover {
background: var(--primary);
color: white;
transform: translateX(5px);
}
.filter-btn.active {
background: var(--primary);
color: white;
}
.filter-count {
margin-left: auto;
background: rgba(255, 255, 255, 0.3);
padding: 2px 8px;
border-radius: 12px;
font-size: 12px;
}
.content-area {
background: white;
border-radius: var(--radius);
padding: 25px;
box-shadow: 0 10px 30px var(--shadow);
}
.dark-mode .content-area {
background: #2d3748;
color: var(--dark);
}
.add-task-section {
margin-bottom: 30px;
}
.add-task-form {
display: flex;
gap: 10px;
margin-bottom: 15px;
}
.task-input {
flex: 1;
padding: 15px;
border: 2px solid var(--border);
border-radius: var(--radius);
font-size: 16px;
transition: var(--transition);
}
.dark-mode .task-input {
background: #4a5568;
color: var(--dark);
border-color: #4a5568;
}
.task-input:focus {
outline: none;
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
.task-options {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.option-select {
padding: 10px;
border: 2px solid var(--border);
border-radius: 8px;
background: white;
cursor: pointer;
transition: var(--transition);
}
.dark-mode .option-select {
background: #4a5568;
color: var(--dark);
}
.option-select:focus {
outline: none;
border-color: var(--primary);
}
.add-btn {
padding: 15px 30px;
background: linear-gradient(135deg, var(--primary), var(--primary-dark));
color: white;
border: none;
border-radius: var(--radius);
cursor: pointer;
font-size: 16px;
font-weight: 600;
transition: var(--transition);
display: flex;
align-items: center;
gap: 10px;
}
.add-btn:hover {
transform: translateY(-2px);
box-shadow: 0 10px 20px var(--shadow);
}
.search-section {
margin-bottom: 25px;
}
.search-box {
position: relative;
}
.search-input {
width: 100%;
padding: 15px 15px 15px 45px;
border: 2px solid var(--border);
border-radius: var(--radius);
font-size: 16px;
transition: var(--transition);
}
.dark-mode .search-input {
background: #4a5568;
color: var(--dark);
border-color: #4a5568;
}
.search-icon {
position: absolute;
left: 15px;
top: 50%;
transform: translateY(-50%);
color: var(--gray);
}
.tasks-list {
max-height: 600px;
overflow-y: auto;
padding-right: 10px;
}
.tasks-list::-webkit-scrollbar {
width: 8px;
}
.tasks-list::-webkit-scrollbar-track {
background: var(--light);
border-radius: 10px;
}
.tasks-list::-webkit-scrollbar-thumb {
background: var(--primary);
border-radius: 10px;
}
.task-item {
background: var(--light);
border: 2px solid var(--border);
border-radius: var(--radius);
padding: 20px;
margin-bottom: 15px;
display: flex;
align-items: center;
gap: 15px;
transition: var(--transition);
animation: slideIn 0.3s ease;
}
.dark-mode .task-item {
background: #4a5568;
border-color: #4a5568;
}
.task-item:hover {
transform: translateX(5px);
box-shadow: 0 5px 15px var(--shadow);
}
.task-item.completed {
opacity: 0.7;
}
.task-item.completed .task-text {
text-decoration: line-through;
color: var(--gray);
}
.task-checkbox {
width: 24px;
height: 24px;
cursor: pointer;
accent-color: var(--primary);
}
.task-content {
flex: 1;
}
.task-text {
font-size: 16px;
margin-bottom: 8px;
color: var(--dark);
}
.dark-mode .task-text {
color: var(--dark);
}
.task-meta {
display: flex;
gap: 15px;
flex-wrap: wrap;
}
.task-meta-item {
display: flex;
align-items: center;
gap: 5px;
font-size: 14px;
color: var(--gray);
}
.priority-badge {
padding: 4px 10px;
border-radius: 20px;
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
}
.priority-high {
background: var(--danger);
color: white;
}
.priority-medium {
background: var(--warning);
color: white;
}
.priority-low {
background: var(--secondary);
color: white;
}
.task-actions {
display: flex;
gap: 10px;
}
.task-btn {
padding: 8px 12px;
background: transparent;
border: none;
cursor: pointer;
color: var(--gray);
transition: var(--transition);
font-size: 18px;
}
.task-btn:hover {
color: var(--primary);
transform: scale(1.2);
}
.task-btn.delete:hover {
color: var(--danger);
}
.empty-state {
text-align: center;
padding: 60px 20px;
color: var(--gray);
}
.empty-state i {
font-size: 64px;
margin-bottom: 20px;
opacity: 0.5;
}
.toast {
position: fixed;
bottom: 30px;
right: 30px;
background: var(--dark);
color: white;
padding: 15px 25px;
border-radius: var(--radius);
box-shadow: 0 10px 30px var(--shadow);
display: flex;
align-items: center;
gap: 10px;
animation: slideUp 0.3s ease;
z-index: 1000;
}
.toast.success {
background: var(--secondary);
}
.toast.error {
background: var(--danger);
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateX(-20px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes pulse {
0%,
100% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
}
@media (max-width: 768px) {
.main-content {
grid-template-columns: 1fr;
}
.sidebar {
position: static;
}
.stats {
grid-template-columns: repeat(4, 1fr);
}
.stat-card {
padding: 15px;
}
.stat-number {
font-size: 24px;
}
.add-task-form {
flex-direction: column;
}
.task-options {
flex-direction: column;
}
.option-select {
width: 100%;
}
}
@media (max-width: 480px) {
.container {
padding: 10px;
}
header {
padding: 20px;
}
.logo {
font-size: 24px;
}
.stats {
grid-template-columns: 1fr 1fr;
}
.task-item {
flex-direction: column;
align-items: flex-start;
}
.task-actions {
width: 100%;
justify-content: flex-end;
}
}
.credits {
position: fixed;
bottom: 10px;
left: 10px;
font-size: 12px;
color: rgba(255, 255, 255, 0.7);
z-index: 100;
}
.credits a {
color: white;
text-decoration: none;
font-weight: bold;
}
.credits a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div class="container">
<header>
<div class="logo">
<i class="fas fa-check-circle"></i>
<span>TaskFlow</span>
</div>
<div class="header-actions">
<button class="theme-toggle" onclick="toggleTheme()">
<i class="fas fa-moon"></i>
</button>
</div>
</header>
<main class="main-content">
<aside class="sidebar">
<div class="stats">
<div class="stat-card">
<span class="stat-number" id="totalTasks">0</span>
<span class="stat-label">Total Tasks</span>
</div>
<div class="stat-card">
<span class="stat-number" id="completedTasks">0</span>
<span class="stat-label">Completed</span>
</div>
<div class="stat-card">
<span class="stat-number" id="pendingTasks">0</span>
<span class="stat-label">Pending</span>
</div>
<div class="stat-card">
<span class="stat-number" id="completionRate">0%</span>
<span class="stat-label">Progress</span>
</div>
</div>
<div class="filters">
<h3 class="filter-title">Categories</h3>
<button class="filter-btn active" onclick="filterTasks('all')">
<i class="fas fa-list"></i>
All Tasks
<span class="filter-count" id="allCount">0</span>
</button>
<button class="filter-btn" onclick="filterTasks('work')">
<i class="fas fa-briefcase"></i>
Work
<span class="filter-count" id="workCount">0</span>
</button>
<button class="filter-btn" onclick="filterTasks('personal')">
<i class="fas fa-user"></i>
Personal
<span class="filter-count" id="personalCount">0</span>
</button>
<button class="filter-btn" onclick="filterTasks('shopping')">
<i class="fas fa-shopping-cart"></i>
Shopping
<span class="filter-count" id="shoppingCount">0</span>
</button>
<button class="filter-btn" onclick="filterTasks('health')">
<i class="fas fa-heartbeat"></i>
Health
<span class="filter-count" id="healthCount">0</span>
</button>
</div>
</aside>
<section class="content-area">
<div class="add-task-section">
<form class="add-task-form" onsubmit="addTask(event)">
<input
type="text"
class="task-input"
id="taskInput"
placeholder="What needs to be done?"
required
>
<button type="submit" class="add-btn">
<i class="fas fa-plus"></i>
Add Task
</button>
</form>
<div class="task-options">
<select class="option-select" id="categorySelect">
<option value="work">Work</option>
<option value="personal">Personal</option>
<option value="shopping">Shopping</option>
<option value="health">Health</option>
</select>
<select class="option-select" id="prioritySelect">
<option value="low">Low Priority</option>
<option value="medium">Medium Priority</option>
<option value="high">High Priority</option>
</select>
<input
type="date"
class="option-select"
id="dueDateSelect"
>
</div>
</div>
<div class="search-section">
<div class="search-box">
<i class="fas fa-search search-icon"></i>
<input
type="text"
class="search-input"
id="searchInput"
placeholder="Search tasks..."
oninput="searchTasks()"
>
</div>
</div>
<div class="tasks-list" id="tasksList">
<div class="empty-state">
<i class="fas fa-clipboard-list"></i>
<h3>No tasks yet</h3>
<p>Start by adding your first task above!</p>
</div>
</div>
</section>
</main>
</div>
<div class="credits">
Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">anycoder</a>
</div>
<script>
let tasks = JSON.parse(localStorage.getItem('tasks')) || [];
let currentFilter = 'all';
let editingTaskId = null;
// Initialize the app
function init() {
renderTasks();
updateStats();
setMinDate();
// Check for saved theme preference
if (localStorage.getItem('darkMode') === 'true') {
document.body.classList.add('dark-mode');
updateThemeIcon();
}
}
// Set minimum date for due date input
function setMinDate() {
const today = new Date().toISOString().split('T')[0];
document.getElementById('dueDateSelect').setAttribute('min', today);
}
// Add or update task
function addTask(event) {
event.preventDefault();
const taskInput = document.getElementById('taskInput');
const categorySelect = document.getElementById('categorySelect');
const prioritySelect = document.getElementById('prioritySelect');
const dueDateSelect = document.getElementById('dueDateSelect');
const taskText = taskInput.value.trim();
if (!taskText) return;
if (editingTaskId) {
// Update existing task
const taskIndex = tasks.findIndex(t => t.id === editingTaskId);
if (taskIndex !== -1) {
tasks[taskIndex].text = taskText;
tasks[taskIndex].category = categorySelect.value;
tasks[taskIndex].priority = prioritySelect.value;
tasks[taskIndex].dueDate = dueDateSelect.value;
tasks[taskIndex].updatedAt = new Date().toISOString();
}
editingTaskId = null;
showToast('Task updated successfully!', 'success');
} else {
// Add new task
const newTask = {
id: Date.now(),
text: taskText,
category: categorySelect.value,
priority: prioritySelect.value,
dueDate: dueDateSelect.value,
completed: false,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
};
tasks.unshift(newTask);
showToast('Task added successfully!', 'success');
}
// Save to localStorage
localStorage.setItem('tasks', JSON.stringify(tasks));
// Reset form
taskInput.value = '';
categorySelect.value = 'work';
prioritySelect.value = 'low';
dueDateSelect.value = '';
// Update UI
renderTasks();
updateStats();
}
// Render tasks based on current filter
function renderTasks() {
const tasksList = document.getElementById('tasksList');
let filteredTasks = tasks;
// Apply category filter
if (currentFilter !== 'all') {
filteredTasks = tasks.filter(task => task.category === currentFilter);
}
// Apply search filter
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
if (searchTerm) {
filteredTasks = filteredTasks.filter(task =>
task.text.toLowerCase().includes(searchTerm)
);
}
if (filteredTasks.length === 0) {
tasksList.innerHTML = `
<div class="empty-state">
<i class="fas fa-clipboard-list"></i>
<h3>No tasks found</h3>
<p>Try adjusting your filters or add a new task!</p>
</div>
`;
return;
}
tasksList.innerHTML = filteredTasks.map(task => `
<div class="task-item ${task.completed ? 'completed' : ''}" data-id="${task.id}">
<input
type="checkbox"
class="task-checkbox"
${task.completed ? 'checked' : ''}
onchange="toggleTask(${task.id})"
>
<div class="task-content">
<div class="task-text">${task.text}</div>
<div class="task-meta">
<span class="task-meta-item">
<i class="fas fa-tag"></i>
${task.category}
</span>
<span class="priority-badge priority-${task.priority}">
${task.priority}
</span>
${task.dueDate ? `
<span class="task-meta-item">
<i class="fas fa-calendar"></i>
${formatDate(task.dueDate)}
</span>
` : ''}
</div>
</div>
<div class="task-actions">
<button class="task-btn edit" onclick="editTask(${task.id})">
<i class="fas fa-edit"></i>
</button>
<button class="task-btn delete" onclick="deleteTask(${task.id})">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
`).join('');
}
// Toggle task completion
function toggleTask(id) {
const task = tasks.find(t => t.id === id);
if (task) {
task.completed = !task.completed;
task.updatedAt = new Date().toISOString();
localStorage.setItem('tasks', JSON.stringify(tasks));
renderTasks();
updateStats();
showToast(task.completed ? 'Task completed!' : 'Task marked as pending', 'success');
}
}
// Edit task
function editTask(id) {
const task = tasks.find(t => t.id === id);
if (task) {
document.getElementById('taskInput').value = task.text;
document.getElementById('categorySelect').value = task.category;
document.getElementById('prioritySelect').value = task.priority;
document.getElementById('dueDateSelect').value = task.dueDate || '';
editingTaskId = id;
document.getElementById('taskInput').focus();
// Scroll to add task form
document.querySelector('.add-task-section').scrollIntoView({ behavior: 'smooth' });
}
}
// Delete task
function deleteTask(id) {
if (confirm('Are you sure you want to delete this task?')) {
tasks = tasks.filter(t => t.id !== id);
localStorage.setItem('tasks', JSON.stringify(tasks));
renderTasks();
updateStats();
showToast('Task deleted successfully', 'success');
}
}
// Filter tasks by category
function filterTasks(category) {
currentFilter = category;
// Update active filter button
document.querySelectorAll('.filter-btn').forEach(btn => {
btn.classList.remove('active');
});
event.target.classList.add('active');
renderTasks();
}
// Search tasks
function searchTasks() {
renderTasks();
}
// Update statistics
function updateStats() {
const totalTasks = tasks.length;
const completedTasks = tasks.filter(t => t.completed).length;
const pendingTasks = totalTasks - completedTasks;
const completionRate = totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0;
document.getElementById('totalTasks').textContent = totalTasks;
document.getElementById('completedTasks').textContent = completedTasks;
document.getElementById('pendingTasks').textContent = pendingTasks;
document.getElementById('completionRate').textContent = completionRate + '%';
// Update category counts
const categories = ['all', 'work', 'personal', 'shopping', 'health'];
categories.forEach(cat => {
const count = cat === 'all' ? totalTasks : tasks.filter(t => t.category === cat).length;
const countElement = document.getElementById(cat + 'Count');
if (countElement) {
countElement.textContent = count;
}
});
}
// Format date
function formatDate(dateString) {
const date = new Date(dateString);
const today = new Date();
const tomorrow = new Date(today);
tomorrow.setDate(tomorrow.getDate() + 1);
if (date.toDateString() === today.toDateString()) {
return 'Today';
} else if (date.toDateString() === tomorrow.toDateString()) {
return 'Tomorrow';
} else {
return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
}
}
// Toggle dark mode
function toggleTheme() {
document.body.classList.toggle('dark-mode');
const isDarkMode = document.body.classList.contains('dark-mode');
localStorage.setItem('darkMode', isDarkMode);
updateThemeIcon();
}
// Update theme icon
function updateThemeIcon() {
const themeIcon = document.querySelector('.theme-toggle i');
if (document.body.classList.contains('dark-mode')) {
themeIcon.classList.remove('fa-moon');
themeIcon.classList.add('fa-sun');
} else {
themeIcon.classList.remove('fa-sun');
themeIcon.classList.add('fa-moon');
}
}
// Show toast notification
function showToast(message, type = 'success') {
const toast = document.createElement('div');
toast.className = `toast ${type}`;
toast.innerHTML = `
<i class="fas fa-${type === 'success' ? 'check-circle' : 'exclamation-circle'}"></i>
<span>${message}</span>
`;
document.body.appendChild(toast);
setTimeout(() => {
toast.style.animation = 'slideUp 0.3s ease reverse';
setTimeout(() => {
document.body.removeChild(toast);
}, 300);
}, 3000);
}
// Initialize app on load
document.addEventListener('DOMContentLoaded', init);
</script>
</body>
</html>