anycoder-9f1e7590 / index.html
akhaliq's picture
akhaliq HF Staff
Upload folder using huggingface_hub
5e4a88e verified
Raw
History Blame Contribute Delete
21.7 kB
<!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 Application</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Inter', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
}
.glass-effect {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
}
.task-item {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.task-item:hover {
transform: translateX(4px);
}
.task-item.completed .task-text {
text-decoration: line-through;
color: #9ca3af;
}
.checkbox-custom {
appearance: none;
width: 20px;
height: 20px;
border: 2px solid #d1d5db;
border-radius: 6px;
cursor: pointer;
position: relative;
transition: all 0.2s;
}
.checkbox-custom:checked {
background: #10b981;
border-color: #10b981;
}
.checkbox-custom:checked::after {
content: 'βœ“';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-size: 12px;
font-weight: bold;
}
.priority-high { border-left: 4px solid #ef4444; }
.priority-medium { border-left: 4px solid #f59e0b; }
.priority-low { border-left: 4px solid #10b981; }
.fade-in {
animation: fadeIn 0.3s ease-in;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
.slide-out {
animation: slideOut 0.3s ease-out forwards;
}
@keyframes slideOut {
to { opacity: 0; transform: translateX(100%); }
}
.progress-ring {
transform: rotate(-90deg);
}
.progress-ring-circle {
transition: stroke-dashoffset 0.35s;
transform-origin: 50% 50%;
}
/* Custom scrollbar */
::-webkit-scrollbar {
width: 6px;
}
::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 3px;
}
::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: #a1a1a1;
}
.category-btn.active {
background: #667eea;
color: white;
}
.filter-btn.active {
color: #667eea;
border-bottom: 2px solid #667eea;
}
</style>
</head>
<body class="p-4 md:p-8">
<div class="max-w-4xl mx-auto">
<!-- Header with Built with anycoder -->
<div class="text-center mb-6">
<a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank"
class="inline-flex items-center gap-2 px-4 py-2 bg-white/20 backdrop-blur-sm rounded-full text-white text-sm font-medium hover:bg-white/30 transition-all">
<span>Built with anycoder</span>
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"></path>
</svg>
</a>
</div>
<!-- Main Container -->
<div class="glass-effect rounded-3xl shadow-2xl overflow-hidden">
<!-- Header Section -->
<div class="bg-gradient-to-r from-indigo-600 to-purple-600 p-6 md:p-8 text-white">
<div class="flex items-center justify-between mb-4">
<div>
<h1 class="text-3xl md:text-4xl font-bold mb-1">TaskFlow</h1>
<p class="text-indigo-100 text-sm md:text-base" id="dateDisplay">Loading date...</p>
</div>
<div class="relative">
<svg class="w-16 h-16 md:w-20 md:h-20 progress-ring" viewBox="0 0 120 120">
<circle cx="60" cy="60" r="54" fill="none" stroke="rgba(255,255,255,0.2)" stroke-width="8"/>
<circle id="progressCircle" cx="60" cy="60" r="54" fill="none" stroke="white" stroke-width="8"
stroke-dasharray="339.292" stroke-dashoffset="339.292" stroke-linecap="round" class="progress-ring-circle"/>
</svg>
<div class="absolute inset-0 flex items-center justify-center">
<span id="progressPercent" class="text-lg md:text-xl font-bold">0%</span>
</div>
</div>
</div>
<!-- Stats -->
<div class="flex gap-6 text-sm">
<div>
<span class="text-indigo-200">Total</span>
<p class="text-2xl font-bold" id="totalTasks">0</p>
</div>
<div>
<span class="text-indigo-200">Completed</span>
<p class="text-2xl font-bold" id="completedTasks">0</p>
</div>
<div>
<span class="text-indigo-200">Pending</span>
<p class="text-2xl font-bold" id="pendingTasks">0</p>
</div>
</div>
</div>
<!-- Input Section -->
<div class="p-6 border-b border-gray-100">
<div class="flex flex-col md:flex-row gap-3">
<input type="text" id="taskInput" placeholder="What needs to be done?"
class="flex-1 px-4 py-3 rounded-xl border border-gray-200 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-all">
<select id="prioritySelect" class="px-4 py-3 rounded-xl border border-gray-200 focus:outline-none focus:ring-2 focus:ring-indigo-500 bg-white">
<option value="low">Low Priority</option>
<option value="medium" selected>Medium Priority</option>
<option value="high">High Priority</option>
</select>
<select id="categorySelect" class="px-4 py-3 rounded-xl border border-gray-200 focus:outline-none focus:ring-2 focus:ring-indigo-500 bg-white">
<option value="personal">Personal</option>
<option value="work">Work</option>
<option value="shopping">Shopping</option>
<option value="health">Health</option>
<option value="other">Other</option>
</select>
<button onclick="addTask()" class="px-6 py-3 bg-indigo-600 text-white rounded-xl font-medium hover:bg-indigo-700 transition-all flex items-center justify-center gap-2 shadow-lg hover:shadow-xl">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path>
</svg>
Add
</button>
</div>
</div>
<!-- Filters -->
<div class="px-6 py-4 border-b border-gray-100 flex flex-wrap gap-2 items-center justify-between">
<div class="flex gap-1 bg-gray-100 p-1 rounded-lg">
<button onclick="setFilter('all')" class="filter-btn active px-4 py-2 rounded-md text-sm font-medium transition-all" data-filter="all">All</button>
<button onclick="setFilter('active')" class="filter-btn px-4 py-2 rounded-md text-sm font-medium text-gray-600 transition-all" data-filter="active">Active</button>
<button onclick="setFilter('completed')" class="filter-btn px-4 py-2 rounded-md text-sm font-medium text-gray-600 transition-all" data-filter="completed">Completed</button>
</div>
<div class="flex gap-2">
<button onclick="clearCompleted()" class="px-4 py-2 text-sm text-red-600 hover:bg-red-50 rounded-lg transition-all">
Clear Completed
</button>
</div>
</div>
<!-- Category Filter -->
<div class="px-6 py-3 border-b border-gray-100 flex flex-wrap gap-2">
<button onclick="setCategory('all')" class="category-btn active px-3 py-1.5 rounded-full text-xs font-medium bg-gray-100 text-gray-600 transition-all" data-category="all">All</button>
<button onclick="setCategory('personal')" class="category-btn px-3 py-1.5 rounded-full text-xs font-medium bg-gray-100 text-gray-600 transition-all" data-category="personal">πŸ‘€ Personal</button>
<button onclick="setCategory('work')" class="category-btn px-3 py-1.5 rounded-full text-xs font-medium bg-gray-100 text-gray-600 transition-all" data-category="work">πŸ’Ό Work</button>
<button onclick="setCategory('shopping')" class="category-btn px-3 py-1.5 rounded-full text-xs font-medium bg-gray-100 text-gray-600 transition-all" data-category="shopping">πŸ›’ Shopping</button>
<button onclick="setCategory('health')" class="category-btn px-3 py-1.5 rounded-full text-xs font-medium bg-gray-100 text-gray-600 transition-all" data-category="health">❀️ Health</button>
<button onclick="setCategory('other')" class="category-btn px-3 py-1.5 rounded-full text-xs font-medium bg-gray-100 text-gray-600 transition-all" data-category="other">πŸ“Œ Other</button>
</div>
<!-- Task List -->
<div class="p-6 min-h-[300px] max-h-[500px] overflow-y-auto">
<ul id="taskList" class="space-y-3">
<!-- Tasks will be rendered here -->
</ul>
<!-- Empty State -->
<div id="emptyState" class="hidden flex-col items-center justify-center py-12 text-center">
<div class="w-24 h-24 bg-indigo-100 rounded-full flex items-center justify-center mb-4">
<svg class="w-12 h-12 text-indigo-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path>
</svg>
</div>
<h3 class="text-lg font-semibold text-gray-700 mb-1">No tasks found</h3>
<p class="text-gray-500 text-sm">Add a new task to get started!</p>
</div>
</div>
</div>
<!-- Footer -->
<p class="text-center text-white/80 text-sm mt-6">
Press <kbd class="px-2 py-1 bg-white/20 rounded text-xs">Enter</kbd> to add a task
</p>
</div>
<script>
// State
let tasks = JSON.parse(localStorage.getItem('tasks')) || [];
let currentFilter = 'all';
let currentCategory = 'all';
// Initialize
document.addEventListener('DOMContentLoaded', () => {
updateDate();
renderTasks();
updateStats();
// Enter key to add task
document.getElementById('taskInput').addEventListener('keypress', (e) => {
if (e.key === 'Enter') addTask();
});
});
// Update date display
function updateDate() {
const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
document.getElementById('dateDisplay').textContent = new Date().toLocaleDateString('en-US', options);
}
// Add task
function addTask() {
const input = document.getElementById('taskInput');
const priority = document.getElementById('prioritySelect').value;
const category = document.getElementById('categorySelect').value;
const text = input.value.trim();
if (!text) {
input.focus();
return;
}
const task = {
id: Date.now(),
text: text,
completed: false,
priority: priority,
category: category,
createdAt: new Date().toISOString()
};
tasks.unshift(task);
saveTasks();
renderTasks();
updateStats();
input.value = '';
input.focus();
}
// Toggle task completion
function toggleTask(id) {
const task = tasks.find(t => t.id === id);
if (task) {
task.completed = !task.completed;
saveTasks();
renderTasks();
updateStats();
}
}
// Delete task
function deleteTask(id) {
const taskElement = document.querySelector(`[data-task-id="${id}"]`);
if (taskElement) {
taskElement.classList.add('slide-out');
setTimeout(() => {
tasks = tasks.filter(t => t.id !== id);
saveTasks();
renderTasks();
updateStats();
}, 300);
}
}
// Edit task
function editTask(id) {
const task = tasks.find(t => t.id === id);
if (!task) return;
const newText = prompt('Edit task:', task.text);
if (newText !== null && newText.trim() !== '') {
task.text = newText.trim();
saveTasks();
renderTasks();
}
}
// Clear completed tasks
function clearCompleted() {
tasks = tasks.filter(t => !t.completed);
saveTasks();
renderTasks();
updateStats();
}
// Set filter
function setFilter(filter) {
currentFilter = filter;
document.querySelectorAll('.filter-btn').forEach(btn => {
btn.classList.remove('active');
if (btn.dataset.filter === filter) {
btn.classList.add('active');
}
});
renderTasks();
}
// Set category
function setCategory(category) {
currentCategory = category;
document.querySelectorAll('.category-btn').forEach(btn => {
btn.classList.remove('active');
if (btn.dataset.category === category) {
btn.classList.add('active');
}
});
renderTasks();
}
// Get priority color
function getPriorityColor(priority) {
const colors = {
high: 'text-red-600 bg-red-50',
medium: 'text-amber-600 bg-amber-50',
low: 'text-emerald-600 bg-emerald-50'
};
return colors[priority] || colors.low;
}
// Get category icon
function getCategoryIcon(category) {
const icons = {
personal: 'πŸ‘€',
work: 'πŸ’Ό',
shopping: 'πŸ›’',
health: '❀️',
other: 'πŸ“Œ'
};
return icons[category] || 'πŸ“Œ';
}
// Render tasks
function renderTasks() {
const list = document.getElementById('taskList');
const emptyState = document.getElementById('emptyState');
let filteredTasks = tasks;
// Apply status filter
if (currentFilter === 'active') {
filteredTasks = filteredTasks.filter(t => !t.completed);
} else if (currentFilter === 'completed') {
filteredTasks = filteredTasks.filter(t => t.completed);
}
// Apply category filter
if (currentCategory !== 'all') {
filteredTasks = filteredTasks.filter(t => t.category === currentCategory);
}
if (filteredTasks.length === 0) {
list.innerHTML = '';
emptyState.classList.remove('hidden');
emptyState.classList.add('flex');
return;
}
emptyState.classList.add('hidden');
emptyState.classList.remove('flex');
list.innerHTML = filteredTasks.map(task => `
<li data-task-id="${task.id}" class="task-item ${task.completed ? 'completed' : ''} priority-${task.priority} bg-white rounded-xl p-4 shadow-sm border border-gray-100 fade-in group">
<div class="flex items-center gap-3">
<input type="checkbox" class="checkbox-custom" ${task.completed ? 'checked' : ''}
onchange="toggleTask(${task.id})">
<div class="flex-1 min-w-0">
<p class="task-text text-gray-800 font-medium truncate">${escapeHtml(task.text)}</p>
<div class="flex items-center gap-2 mt-1">
<span class="text-xs px-2 py-0.5 rounded-full ${getPriorityColor(task.priority)} capitalize">
${task.priority}
</span>
<span class="text-xs text-gray-500">
${getCategoryIcon(task.category)} ${task.category}
</span>
</div>
</div>
<div class="flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
<button onclick="editTask(${task.id})" class="p-2 text-gray-400 hover:text-indigo-600 hover:bg-indigo-50 rounded-lg transition-all">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path>
</svg>
</button>
<button onclick="deleteTask(${task.id})" class="p-2 text-gray-400 hover:text-red-600 hover:bg-red-50 rounded-lg transition-all">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
</svg>
</button>
</div>
</div>
</li>
`).join('');
}
// Update statistics
function updateStats() {
const total = tasks.length;
const completed = tasks.filter(t => t.completed).length;
const pending = total - completed;
const percentage = total > 0 ? Math.round((completed / total) * 100) : 0;
document.getElementById('totalTasks').textContent = total;
document.getElementById('completedTasks').textContent = completed;
document.getElementById('pendingTasks').textContent = pending;
document.getElementById('progressPercent').textContent = `${percentage}%`;
// Update progress circle
const circle = document.getElementById('progressCircle');
const circumference = 2 * Math.PI * 54;
const offset = circumference - (percentage / 100) * circumference;
circle.style.strokeDashoffset = offset;
}
// Save to localStorage
function saveTasks() {
localStorage.setItem('tasks', JSON.stringify(tasks));
}
// Escape HTML
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
</script>
</body>
</html>