Download index.html from javed-78/ai_box: direct link, hf CLI and curl.
- Browser
- Download file 14.6 kB
-
https://huggingface.co/javed-78/ai_box/resolve/main/index.html
- Command line
-
hf download hf://javed-78/ai_box/index.html
-
curl -L -o index.html https://huggingface.co/javed-78/ai_box/resolve/main/index.html
14.6 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| <title>TaskMaster</title> | |
| <style> | |
| /* ββ Reset & Base ββ */ | |
| *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } | |
| :root { | |
| --bg: #0f1117; | |
| --surface: #181c27; | |
| --card: #1e2333; | |
| --border: #2a3045; | |
| --accent: #7c6af7; | |
| --accent2: #a78bfa; | |
| --text: #e2e8f0; | |
| --muted: #64748b; | |
| --high: #f87171; | |
| --medium: #fbbf24; | |
| --low: #34d399; | |
| --done-bg: #141820; | |
| --done-text: #3f4a5a; | |
| --radius: 12px; | |
| --font: 'Inter', system-ui, sans-serif; | |
| } | |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); | |
| body { | |
| font-family: var(--font); | |
| background: var(--bg); | |
| color: var(--text); | |
| min-height: 100vh; | |
| line-height: 1.6; | |
| } | |
| /* ββ Layout ββ */ | |
| .shell { | |
| max-width: 860px; | |
| margin: 0 auto; | |
| padding: 0 20px 60px; | |
| } | |
| /* ββ Header ββ */ | |
| header { | |
| padding: 40px 0 30px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| flex-wrap: wrap; | |
| gap: 16px; | |
| } | |
| .logo { | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| } | |
| .logo-icon { | |
| width: 40px; height: 40px; | |
| background: linear-gradient(135deg, var(--accent), #c084fc); | |
| border-radius: 10px; | |
| display: flex; align-items: center; justify-content: center; | |
| font-size: 20px; | |
| } | |
| .logo h1 { | |
| font-size: 1.5rem; | |
| font-weight: 700; | |
| letter-spacing: -0.03em; | |
| background: linear-gradient(to right, var(--accent2), #c084fc); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| } | |
| /* ββ Stats Bar ββ */ | |
| .stats { | |
| display: flex; | |
| gap: 12px; | |
| flex-wrap: wrap; | |
| margin-bottom: 28px; | |
| } | |
| .stat { | |
| background: var(--surface); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius); | |
| padding: 14px 20px; | |
| flex: 1; | |
| min-width: 100px; | |
| text-align: center; | |
| } | |
| .stat-num { | |
| font-size: 1.75rem; | |
| font-weight: 700; | |
| line-height: 1; | |
| margin-bottom: 4px; | |
| } | |
| .stat-label { | |
| font-size: 0.72rem; | |
| text-transform: uppercase; | |
| letter-spacing: 0.08em; | |
| color: var(--muted); | |
| } | |
| .stat-num.purple { color: var(--accent2); } | |
| .stat-num.green { color: var(--low); } | |
| .stat-num.red { color: var(--high); } | |
| /* ββ Add Task Form ββ */ | |
| .add-card { | |
| background: var(--surface); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius); | |
| padding: 22px; | |
| margin-bottom: 24px; | |
| } | |
| .add-card h2 { | |
| font-size: 0.85rem; | |
| text-transform: uppercase; | |
| letter-spacing: 0.08em; | |
| color: var(--muted); | |
| margin-bottom: 16px; | |
| } | |
| .form-row { | |
| display: flex; | |
| gap: 10px; | |
| flex-wrap: wrap; | |
| } | |
| input, select { | |
| background: var(--card); | |
| border: 1px solid var(--border); | |
| border-radius: 8px; | |
| color: var(--text); | |
| font-family: var(--font); | |
| font-size: 0.9rem; | |
| padding: 10px 14px; | |
| outline: none; | |
| transition: border-color 0.15s; | |
| } | |
| input:focus, select:focus { | |
| border-color: var(--accent); | |
| } | |
| input[type="text"] { flex: 1; min-width: 200px; } | |
| select { min-width: 120px; } | |
| input[type="date"] { min-width: 150px; color-scheme: dark; } | |
| .btn { | |
| border: none; | |
| border-radius: 8px; | |
| cursor: pointer; | |
| font-family: var(--font); | |
| font-size: 0.9rem; | |
| font-weight: 600; | |
| padding: 10px 22px; | |
| transition: opacity 0.15s, transform 0.1s; | |
| } | |
| .btn:active { transform: scale(0.97); } | |
| .btn-primary { | |
| background: linear-gradient(135deg, var(--accent), #a855f7); | |
| color: #fff; | |
| } | |
| .btn-primary:hover { opacity: 0.88; } | |
| /* ββ Filters ββ */ | |
| .filters { | |
| display: flex; | |
| gap: 8px; | |
| flex-wrap: wrap; | |
| margin-bottom: 16px; | |
| } | |
| .chip { | |
| border: 1px solid var(--border); | |
| border-radius: 20px; | |
| background: var(--surface); | |
| color: var(--muted); | |
| cursor: pointer; | |
| font-family: var(--font); | |
| font-size: 0.8rem; | |
| padding: 5px 14px; | |
| transition: all 0.15s; | |
| } | |
| .chip.active { | |
| background: var(--accent); | |
| border-color: var(--accent); | |
| color: #fff; | |
| } | |
| /* ββ Task List ββ */ | |
| #task-list { display: flex; flex-direction: column; gap: 10px; } | |
| .task-card { | |
| background: var(--card); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius); | |
| padding: 16px 18px; | |
| display: flex; | |
| align-items: flex-start; | |
| gap: 14px; | |
| transition: opacity 0.2s, border-color 0.2s; | |
| animation: slideIn 0.2s ease; | |
| } | |
| @keyframes slideIn { | |
| from { opacity: 0; transform: translateY(-6px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| .task-card.done-card { | |
| background: var(--done-bg); | |
| opacity: 0.6; | |
| } | |
| .task-card:hover { border-color: #3a4060; } | |
| /* Priority bar */ | |
| .task-card { border-left: 3px solid transparent; } | |
| .task-card[data-priority="high"] { border-left-color: var(--high); } | |
| .task-card[data-priority="medium"] { border-left-color: var(--medium); } | |
| .task-card[data-priority="low"] { border-left-color: var(--low); } | |
| /* Checkbox */ | |
| .check-btn { | |
| width: 22px; height: 22px; | |
| border: 2px solid var(--border); | |
| border-radius: 50%; | |
| background: transparent; | |
| cursor: pointer; | |
| flex-shrink: 0; | |
| margin-top: 2px; | |
| transition: all 0.15s; | |
| display: flex; align-items: center; justify-content: center; | |
| } | |
| .check-btn:hover { border-color: var(--low); } | |
| .check-btn.checked { | |
| background: var(--low); | |
| border-color: var(--low); | |
| } | |
| .check-btn.checked::after { content: 'β'; color: #0f1117; font-size: 13px; font-weight: 700; } | |
| /* Task body */ | |
| .task-body { flex: 1; min-width: 0; } | |
| .task-title { | |
| font-size: 0.95rem; | |
| font-weight: 500; | |
| color: var(--text); | |
| margin-bottom: 6px; | |
| word-break: break-word; | |
| } | |
| .task-card.done-card .task-title { | |
| text-decoration: line-through; | |
| color: var(--done-text); | |
| } | |
| .task-meta { | |
| display: flex; | |
| gap: 8px; | |
| flex-wrap: wrap; | |
| align-items: center; | |
| } | |
| .badge { | |
| border-radius: 4px; | |
| font-size: 0.7rem; | |
| font-weight: 600; | |
| padding: 2px 8px; | |
| text-transform: uppercase; | |
| letter-spacing: 0.05em; | |
| } | |
| .badge-high { background: rgba(248,113,113,0.15); color: var(--high); } | |
| .badge-medium { background: rgba(251,191,36,0.15); color: var(--medium); } | |
| .badge-low { background: rgba(52,211,153,0.15); color: var(--low); } | |
| .badge-cat { background: rgba(124,106,247,0.15); color: var(--accent2); } | |
| .badge-date { background: rgba(100,116,139,0.1); color: var(--muted); } | |
| /* Delete btn */ | |
| .del-btn { | |
| background: transparent; | |
| border: none; | |
| color: var(--muted); | |
| cursor: pointer; | |
| font-size: 18px; | |
| padding: 2px 6px; | |
| border-radius: 6px; | |
| transition: color 0.15s, background 0.15s; | |
| flex-shrink: 0; | |
| } | |
| .del-btn:hover { color: var(--high); background: rgba(248,113,113,0.1); } | |
| /* ββ Empty state ββ */ | |
| .empty { | |
| text-align: center; | |
| padding: 60px 20px; | |
| color: var(--muted); | |
| } | |
| .empty .icon { font-size: 3rem; margin-bottom: 12px; } | |
| .empty p { font-size: 0.9rem; } | |
| /* ββ Toast ββ */ | |
| #toast { | |
| position: fixed; | |
| bottom: 30px; right: 30px; | |
| background: #1e293b; | |
| border: 1px solid var(--border); | |
| border-radius: 10px; | |
| color: var(--text); | |
| font-size: 0.88rem; | |
| padding: 12px 20px; | |
| opacity: 0; | |
| transform: translateY(10px); | |
| transition: all 0.25s; | |
| z-index: 999; | |
| pointer-events: none; | |
| } | |
| #toast.show { opacity: 1; transform: translateY(0); } | |
| @media (max-width: 540px) { | |
| .form-row { flex-direction: column; } | |
| .form-row input, .form-row select, .form-row .btn { width: 100%; } | |
| .stats .stat-num { font-size: 1.4rem; } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="shell"> | |
| <!-- Header --> | |
| <header> | |
| <div class="logo"> | |
| <div class="logo-icon">β¦</div> | |
| <h1>TaskMaster</h1> | |
| </div> | |
| <span style="color:var(--muted);font-size:0.82rem;">Your personal task engine</span> | |
| </header> | |
| <!-- Stats --> | |
| <div class="stats" id="stats"> | |
| <div class="stat"><div class="stat-num purple" id="s-total">β</div><div class="stat-label">Total</div></div> | |
| <div class="stat"><div class="stat-num green" id="s-done">β</div><div class="stat-label">Done</div></div> | |
| <div class="stat"><div class="stat-num purple" id="s-pending">β</div><div class="stat-label">Pending</div></div> | |
| <div class="stat"><div class="stat-num red" id="s-high">β</div><div class="stat-label">Urgent</div></div> | |
| </div> | |
| <!-- Add Form --> | |
| <div class="add-card"> | |
| <h2>Add New Task</h2> | |
| <div class="form-row"> | |
| <input type="text" id="inp-title" placeholder="What needs to be done?" /> | |
| <select id="inp-priority"> | |
| <option value="high">π΄ High</option> | |
| <option value="medium" selected>π‘ Medium</option> | |
| <option value="low">π’ Low</option> | |
| </select> | |
| <select id="inp-category"> | |
| <option value="work">πΌ Work</option> | |
| <option value="personal">π Personal</option> | |
| <option value="learning">π Learning</option> | |
| <option value="general" selected>π General</option> | |
| </select> | |
| <input type="date" id="inp-due" /> | |
| <button class="btn btn-primary" onclick="addTask()">Add Task</button> | |
| </div> | |
| </div> | |
| <!-- Filters --> | |
| <div class="filters"> | |
| <button class="chip active" onclick="setFilter('all', this)">All</button> | |
| <button class="chip" onclick="setFilter('pending', this)">Pending</button> | |
| <button class="chip" onclick="setFilter('done', this)">Done</button> | |
| <button class="chip" onclick="setFilter('high', this)">π΄ High</button> | |
| <button class="chip" onclick="setFilter('work', this)">πΌ Work</button> | |
| <button class="chip" onclick="setFilter('personal', this)">π Personal</button> | |
| <button class="chip" onclick="setFilter('learning', this)">π Learning</button> | |
| </div> | |
| <!-- Task List --> | |
| <div id="task-list"> | |
| <div class="empty"><div class="icon">β³</div><p>Loading tasksβ¦</p></div> | |
| </div> | |
| </div> | |
| <!-- Toast --> | |
| <div id="toast"></div> | |
| <script> | |
| let currentFilter = 'all'; | |
| /* ββ API helpers ββ */ | |
| async function api(method, path, body) { | |
| const opts = { | |
| method, | |
| headers: { 'Content-Type': 'application/json' }, | |
| }; | |
| if (body) opts.body = JSON.stringify(body); | |
| const r = await fetch(path, opts); | |
| return r.json(); | |
| } | |
| /* ββ Load & render ββ */ | |
| async function loadTasks() { | |
| let url = '/api/tasks'; | |
| const params = []; | |
| if (currentFilter === 'pending') params.push('done=false'); | |
| if (currentFilter === 'done') params.push('done=true'); | |
| if (currentFilter === 'high') params.push('priority=high'); | |
| if (['work','personal','learning'].includes(currentFilter)) | |
| params.push(`category=${currentFilter}`); | |
| if (params.length) url += '?' + params.join('&'); | |
| const data = await api('GET', url); | |
| renderTasks(data.tasks); | |
| loadStats(); | |
| } | |
| function renderTasks(tasks) { | |
| const el = document.getElementById('task-list'); | |
| if (!tasks.length) { | |
| el.innerHTML = `<div class="empty"><div class="icon">π</div><p>No tasks here. Add one above!</p></div>`; | |
| return; | |
| } | |
| el.innerHTML = tasks.map(t => ` | |
| <div class="task-card ${t.done ? 'done-card' : ''}" data-priority="${t.priority}" id="tc-${t.id}"> | |
| <button class="check-btn ${t.done ? 'checked' : ''}" onclick="toggleDone('${t.id}', ${!t.done})" title="Toggle done"></button> | |
| <div class="task-body"> | |
| <div class="task-title">${escHtml(t.title)}</div> | |
| <div class="task-meta"> | |
| <span class="badge badge-${t.priority}">${t.priority}</span> | |
| <span class="badge badge-cat">${t.category}</span> | |
| ${t.due_date ? `<span class="badge badge-date">π ${t.due_date}</span>` : ''} | |
| <span style="color:var(--muted);font-size:0.72rem;">${t.created_at}</span> | |
| </div> | |
| </div> | |
| <button class="del-btn" onclick="deleteTask('${t.id}')" title="Delete">β</button> | |
| </div> | |
| `).join(''); | |
| } | |
| async function loadStats() { | |
| const s = await api('GET', '/api/stats'); | |
| document.getElementById('s-total').textContent = s.total; | |
| document.getElementById('s-done').textContent = s.done; | |
| document.getElementById('s-pending').textContent = s.pending; | |
| document.getElementById('s-high').textContent = s.high_priority; | |
| } | |
| /* ββ Actions ββ */ | |
| async function addTask() { | |
| const title = document.getElementById('inp-title').value.trim(); | |
| const priority = document.getElementById('inp-priority').value; | |
| const category = document.getElementById('inp-category').value; | |
| const due_date = document.getElementById('inp-due').value || null; | |
| if (!title) { toast('Please enter a task title.'); return; } | |
| await api('POST', '/api/tasks', { title, priority, category, due_date }); | |
| document.getElementById('inp-title').value = ''; | |
| document.getElementById('inp-due').value = ''; | |
| loadTasks(); | |
| toast('Task added β¦'); | |
| } | |
| async function toggleDone(id, done) { | |
| await api('PATCH', `/api/tasks/${id}`, { done }); | |
| loadTasks(); | |
| toast(done ? 'Task completed π' : 'Marked as pending'); | |
| } | |
| async function deleteTask(id) { | |
| const card = document.getElementById(`tc-${id}`); | |
| if (card) card.style.opacity = '0.3'; | |
| await api('DELETE', `/api/tasks/${id}`); | |
| loadTasks(); | |
| toast('Task removed'); | |
| } | |
| /* ββ Filters ββ */ | |
| function setFilter(filter, btn) { | |
| currentFilter = filter; | |
| document.querySelectorAll('.chip').forEach(c => c.classList.remove('active')); | |
| btn.classList.add('active'); | |
| loadTasks(); | |
| } | |
| /* ββ Enter key ββ */ | |
| document.getElementById('inp-title').addEventListener('keydown', e => { | |
| if (e.key === 'Enter') addTask(); | |
| }); | |
| /* ββ Toast ββ */ | |
| let toastTimer; | |
| function toast(msg) { | |
| const el = document.getElementById('toast'); | |
| el.textContent = msg; | |
| el.classList.add('show'); | |
| clearTimeout(toastTimer); | |
| toastTimer = setTimeout(() => el.classList.remove('show'), 2200); | |
| } | |
| /* ββ Utils ββ */ | |
| function escHtml(s) { | |
| return s.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"'); | |
| } | |
| /* ββ Init ββ */ | |
| loadTasks(); | |
| </script> | |
| </body> | |
| </html> | |