akhaliq HF Staff commited on
Commit
f5b3bec
·
verified ·
1 Parent(s): 7cb9b0a

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +702 -19
index.html CHANGED
@@ -1,19 +1,702 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Modern To-Do App</title>
7
+ <!-- Importing Google Fonts -->
8
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
9
+ <!-- Importing FontAwesome for Icons -->
10
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
11
+
12
+ <style>
13
+ :root {
14
+ /* Color Palette */
15
+ --primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
16
+ --secondary-gradient: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
17
+ --bg-color: #f3f4f6;
18
+ --glass-bg: rgba(255, 255, 255, 0.85);
19
+ --glass-border: rgba(255, 255, 255, 0.5);
20
+ --text-main: #1f2937;
21
+ --text-secondary: #6b7280;
22
+ --accent-color: #764ba2;
23
+ --danger-color: #ef4444;
24
+ --success-color: #10b981;
25
+ --shadow-lg: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
26
+ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
27
+ }
28
+
29
+ * {
30
+ box-sizing: border-box;
31
+ margin: 0;
32
+ padding: 0;
33
+ font-family: 'Inter', sans-serif;
34
+ }
35
+
36
+ body {
37
+ background: var(--bg-color);
38
+ min-height: 100vh;
39
+ display: flex;
40
+ justify-content: center;
41
+ align-items: center;
42
+ padding: 20px;
43
+ background-image:
44
+ radial-gradient(circle at 10% 20%, rgba(118, 75, 162, 0.1) 0%, transparent 20%),
45
+ radial-gradient(circle at 90% 80%, rgba(102, 126, 234, 0.1) 0%, transparent 20%);
46
+ }
47
+
48
+ /* App Container */
49
+ .app-container {
50
+ width: 100%;
51
+ max-width: 500px;
52
+ background: var(--glass-bg);
53
+ backdrop-filter: blur(12px);
54
+ -webkit-backdrop-filter: blur(12px);
55
+ border: 1px solid var(--glass-border);
56
+ border-radius: 24px;
57
+ box-shadow: var(--shadow-lg);
58
+ overflow: hidden;
59
+ display: flex;
60
+ flex-direction: column;
61
+ position: relative;
62
+ transition: all 0.3s ease;
63
+ }
64
+
65
+ /* Header */
66
+ header {
67
+ padding: 30px 30px 20px 30px;
68
+ background: var(--primary-gradient);
69
+ color: white;
70
+ position: relative;
71
+ }
72
+
73
+ .header-top {
74
+ display: flex;
75
+ justify-content: space-between;
76
+ align-items: center;
77
+ margin-bottom: 10px;
78
+ }
79
+
80
+ h1 {
81
+ font-size: 1.8rem;
82
+ font-weight: 700;
83
+ letter-spacing: -0.5px;
84
+ }
85
+
86
+ .date-display {
87
+ font-size: 0.9rem;
88
+ opacity: 0.9;
89
+ font-weight: 500;
90
+ }
91
+
92
+ .credits {
93
+ font-size: 0.75rem;
94
+ opacity: 0.7;
95
+ text-align: right;
96
+ }
97
+
98
+ .credits a {
99
+ color: white;
100
+ text-decoration: none;
101
+ border-bottom: 1px dotted rgba(255,255,255,0.7);
102
+ }
103
+
104
+ /* Input Area */
105
+ .input-area {
106
+ padding: 25px 30px;
107
+ display: flex;
108
+ gap: 12px;
109
+ border-bottom: 1px solid rgba(0,0,0,0.05);
110
+ }
111
+
112
+ .input-wrapper {
113
+ position: relative;
114
+ flex-grow: 1;
115
+ }
116
+
117
+ #todo-input {
118
+ width: 100%;
119
+ padding: 14px 16px 14px 45px;
120
+ border: 2px solid transparent;
121
+ background: #f9fafb;
122
+ border-radius: 12px;
123
+ font-size: 1rem;
124
+ color: var(--text-main);
125
+ transition: all 0.2s ease;
126
+ outline: none;
127
+ }
128
+
129
+ #todo-input:focus {
130
+ background: white;
131
+ border-color: var(--accent-color);
132
+ box-shadow: 0 0 0 4px rgba(118, 75, 162, 0.1);
133
+ }
134
+
135
+ .input-icon {
136
+ position: absolute;
137
+ left: 16px;
138
+ top: 50%;
139
+ transform: translateY(-50%);
140
+ color: var(--text-secondary);
141
+ pointer-events: none;
142
+ }
143
+
144
+ #add-btn {
145
+ background: var(--primary-gradient);
146
+ color: white;
147
+ border: none;
148
+ width: 50px;
149
+ border-radius: 12px;
150
+ cursor: pointer;
151
+ font-size: 1.2rem;
152
+ transition: transform 0.2s, box-shadow 0.2s;
153
+ display: flex;
154
+ align-items: center;
155
+ justify-content: center;
156
+ }
157
+
158
+ #add-btn:hover {
159
+ transform: translateY(-2px);
160
+ box-shadow: 0 4px 12px rgba(118, 75, 162, 0.3);
161
+ }
162
+
163
+ #add-btn:active {
164
+ transform: scale(0.95);
165
+ }
166
+
167
+ /* Filters */
168
+ .filters {
169
+ display: flex;
170
+ padding: 15px 30px 0;
171
+ gap: 10px;
172
+ }
173
+
174
+ .filter-btn {
175
+ background: none;
176
+ border: none;
177
+ padding: 8px 16px;
178
+ font-size: 0.9rem;
179
+ font-weight: 600;
180
+ color: var(--text-secondary);
181
+ cursor: pointer;
182
+ border-radius: 20px;
183
+ transition: all 0.2s;
184
+ }
185
+
186
+ .filter-btn.active {
187
+ background: rgba(118, 75, 162, 0.1);
188
+ color: var(--accent-color);
189
+ }
190
+
191
+ .filter-btn:hover:not(.active) {
192
+ background: rgba(0,0,0,0.05);
193
+ }
194
+
195
+ /* Todo List */
196
+ .todo-list {
197
+ list-style: none;
198
+ padding: 20px 30px;
199
+ overflow-y: auto;
200
+ max-height: 400px;
201
+ min-height: 200px;
202
+ }
203
+
204
+ .todo-item {
205
+ background: white;
206
+ border-radius: 12px;
207
+ padding: 12px 16px;
208
+ margin-bottom: 10px;
209
+ display: flex;
210
+ align-items: center;
211
+ gap: 12px;
212
+ box-shadow: var(--shadow-sm);
213
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
214
+ border-left: 4px solid transparent;
215
+ cursor: grab;
216
+ position: relative;
217
+ animation: slideIn 0.3s ease forwards;
218
+ }
219
+
220
+ @keyframes slideIn {
221
+ from { opacity: 0; transform: translateY(10px); }
222
+ to { opacity: 1; transform: translateY(0); }
223
+ }
224
+
225
+ @keyframes slideOut {
226
+ to { opacity: 0; transform: translateX(20px); }
227
+ }
228
+
229
+ .todo-item:hover {
230
+ transform: translateY(-2px);
231
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
232
+ }
233
+
234
+ .todo-item.completed {
235
+ opacity: 0.7;
236
+ background: #f9fafb;
237
+ }
238
+
239
+ .todo-item.completed .todo-text {
240
+ text-decoration: line-through;
241
+ color: var(--text-secondary);
242
+ }
243
+
244
+ .todo-item.priority-high {
245
+ border-left-color: var(--danger-color);
246
+ }
247
+
248
+ .todo-item.priority-medium {
249
+ border-left-color: #f59e0b;
250
+ }
251
+
252
+ .todo-item.priority-low {
253
+ border-left-color: var(--success-color);
254
+ }
255
+
256
+ /* Custom Checkbox */
257
+ .custom-checkbox {
258
+ width: 22px;
259
+ height: 22px;
260
+ border: 2px solid #d1d5db;
261
+ border-radius: 6px;
262
+ display: flex;
263
+ align-items: center;
264
+ justify-content: center;
265
+ cursor: pointer;
266
+ transition: all 0.2s;
267
+ flex-shrink: 0;
268
+ }
269
+
270
+ .todo-item.completed .custom-checkbox {
271
+ background: var(--success-color);
272
+ border-color: var(--success-color);
273
+ }
274
+
275
+ .custom-checkbox i {
276
+ color: white;
277
+ font-size: 0.8rem;
278
+ opacity: 0;
279
+ transform: scale(0.5);
280
+ transition: all 0.2s;
281
+ }
282
+
283
+ .todo-item.completed .custom-checkbox i {
284
+ opacity: 1;
285
+ transform: scale(1);
286
+ }
287
+
288
+ .todo-text {
289
+ flex-grow: 1;
290
+ font-size: 1rem;
291
+ color: var(--text-main);
292
+ word-break: break-word;
293
+ }
294
+
295
+ .actions {
296
+ display: flex;
297
+ gap: 8px;
298
+ opacity: 0;
299
+ transition: opacity 0.2s;
300
+ }
301
+
302
+ .todo-item:hover .actions {
303
+ opacity: 1;
304
+ }
305
+
306
+ /* Mobile specific: always show actions or use a swipe pattern logic,
307
+ but for simplicity in this demo, we keep hover or ensure they are touchable */
308
+ @media (max-width: 600px) {
309
+ .actions { opacity: 1; }
310
+ }
311
+
312
+ .action-btn {
313
+ background: none;
314
+ border: none;
315
+ cursor: pointer;
316
+ width: 32px;
317
+ height: 32px;
318
+ border-radius: 6px;
319
+ color: var(--text-secondary);
320
+ transition: background 0.2s, color 0.2s;
321
+ display: flex;
322
+ align-items: center;
323
+ justify-content: center;
324
+ }
325
+
326
+ .action-btn:hover {
327
+ background: #f3f4f6;
328
+ color: var(--text-main);
329
+ }
330
+
331
+ .delete-btn:hover {
332
+ background: #fee2e2;
333
+ color: var(--danger-color);
334
+ }
335
+
336
+ /* Priority Selector inside Todo Item (Optional UI expansion) */
337
+ .priority-selector {
338
+ position: absolute;
339
+ right: 0;
340
+ top: 100%;
341
+ background: white;
342
+ border-radius: 8px;
343
+ box-shadow: var(--shadow-lg);
344
+ display: none;
345
+ flex-direction: column;
346
+ z-index: 10;
347
+ overflow: hidden;
348
+ border: 1px solid #e5e7eb;
349
+ }
350
+
351
+ .priority-selector.show {
352
+ display: flex;
353
+ }
354
+
355
+ .p-option {
356
+ padding: 8px 16px;
357
+ font-size: 0.85rem;
358
+ cursor: pointer;
359
+ transition: background 0.1s;
360
+ }
361
+ .p-option:hover { background: #f3f4f6; }
362
+
363
+ /* Empty State */
364
+ .empty-state {
365
+ text-align: center;
366
+ padding: 40px 20px;
367
+ color: var(--text-secondary);
368
+ display: none;
369
+ }
370
+
371
+ .empty-state i {
372
+ font-size: 3rem;
373
+ margin-bottom: 16px;
374
+ color: #d1d5db;
375
+ }
376
+
377
+ /* Footer Stats */
378
+ .footer-stats {
379
+ padding: 15px 30px;
380
+ border-top: 1px solid rgba(0,0,0,0.05);
381
+ display: flex;
382
+ justify-content: space-between;
383
+ align-items: center;
384
+ font-size: 0.85rem;
385
+ color: var(--text-secondary);
386
+ background: rgba(255,255,255,0.5);
387
+ }
388
+
389
+ .clear-btn {
390
+ background: none;
391
+ border: none;
392
+ color: var(--text-secondary);
393
+ cursor: pointer;
394
+ font-size: 0.85rem;
395
+ transition: color 0.2s;
396
+ }
397
+
398
+ .clear-btn:hover {
399
+ color: var(--danger-color);
400
+ text-decoration: underline;
401
+ }
402
+
403
+ /* Toast Notification */
404
+ .toast {
405
+ position: absolute;
406
+ bottom: 20px;
407
+ left: 50%;
408
+ transform: translateX(-50%) translateY(100px);
409
+ background: #1f2937;
410
+ color: white;
411
+ padding: 10px 20px;
412
+ border-radius: 30px;
413
+ font-size: 0.9rem;
414
+ opacity: 0;
415
+ transition: all 0.3s ease;
416
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
417
+ z-index: 100;
418
+ display: flex;
419
+ align-items: center;
420
+ gap: 8px;
421
+ }
422
+
423
+ .toast.show {
424
+ transform: translateX(-50%) translateY(0);
425
+ opacity: 1;
426
+ }
427
+
428
+ </style>
429
+ </head>
430
+ <body>
431
+
432
+ <div class="app-container">
433
+ <header>
434
+ <div class="header-top">
435
+ <div>
436
+ <h1>My Tasks</h1>
437
+ <div class="date-display" id="date-display">Loading date...</div>
438
+ </div>
439
+ <div class="credits">
440
+ Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">anycoder</a>
441
+ </div>
442
+ </div>
443
+ </header>
444
+
445
+ <div class="input-area">
446
+ <div class="input-wrapper">
447
+ <i class="fas fa-plus input-icon"></i>
448
+ <input type="text" id="todo-input" placeholder="Add a new task..." autocomplete="off">
449
+ </div>
450
+ <button id="add-btn"><i class="fas fa-arrow-up"></i></button>
451
+ </div>
452
+
453
+ <div class="filters">
454
+ <button class="filter-btn active" data-filter="all">All</button>
455
+ <button class="filter-btn" data-filter="active">Active</button>
456
+ <button class="filter-btn" data-filter="completed">Completed</button>
457
+ </div>
458
+
459
+ <ul class="todo-list" id="todo-list">
460
+ <!-- Todo items will be injected here -->
461
+ </ul>
462
+
463
+ <div class="empty-state" id="empty-state">
464
+ <i class="fas fa-clipboard-list"></i>
465
+ <p>No tasks found. Enjoy your day!</p>
466
+ </div>
467
+
468
+ <div class="footer-stats">
469
+ <span id="items-left">0 items left</span>
470
+ <button class="clear-btn" id="clear-completed">Clear Completed</button>
471
+ </div>
472
+
473
+ <div class="toast" id="toast">
474
+ <i class="fas fa-check-circle"></i>
475
+ <span id="toast-message">Action successful</span>
476
+ </div>
477
+ </div>
478
+
479
+ <script>
480
+ // --- State Management ---
481
+ let todos = JSON.parse(localStorage.getItem('myTodos')) || [];
482
+ let currentFilter = 'all';
483
+
484
+ // --- DOM Elements ---
485
+ const todoInput = document.getElementById('todo-input');
486
+ const addBtn = document.getElementById('add-btn');
487
+ const todoList = document.getElementById('todo-list');
488
+ const itemsLeft = document.getElementById('items-left');
489
+ const clearBtn = document.getElementById('clear-completed');
490
+ const filterBtns = document.querySelectorAll('.filter-btn');
491
+ const dateDisplay = document.getElementById('date-display');
492
+ const emptyState = document.getElementById('empty-state');
493
+ const toast = document.getElementById('toast');
494
+ const toastMsg = document.getElementById('toast-message');
495
+
496
+ // --- Initialization ---
497
+ document.addEventListener('DOMContentLoaded', () => {
498
+ renderTodos();
499
+ updateDate();
500
+ });
501
+
502
+ // --- Event Listeners ---
503
+ addBtn.addEventListener('click', addTodo);
504
+
505
+ todoInput.addEventListener('keypress', (e) => {
506
+ if (e.key === 'Enter') addTodo();
507
+ });
508
+
509
+ clearBtn.addEventListener('click', () => {
510
+ const completedCount = todos.filter(t => t.completed).length;
511
+ if (completedCount === 0) return;
512
+
513
+ todos = todos.filter(todo => !todo.completed);
514
+ saveAndRender();
515
+ showToast(`${completedCount} tasks cleared`);
516
+ });
517
+
518
+ filterBtns.forEach(btn => {
519
+ btn.addEventListener('click', () => {
520
+ document.querySelector('.filter-btn.active').classList.remove('active');
521
+ btn.classList.add('active');
522
+ currentFilter = btn.dataset.filter;
523
+ renderTodos();
524
+ });
525
+ });
526
+
527
+ // --- Core Functions ---
528
+
529
+ function addTodo() {
530
+ const text = todoInput.value.trim();
531
+ if (text === '') {
532
+ showToast('Please enter a task', true);
533
+ return;
534
+ }
535
+
536
+ const newTodo = {
537
+ id: Date.now(),
538
+ text: text,
539
+ completed: false,
540
+ priority: 'medium' // default priority
541
+ };
542
+
543
+ todos.unshift(newTodo); // Add to top
544
+ todoInput.value = '';
545
+ todoInput.focus();
546
+
547
+ saveAndRender();
548
+ showToast('Task added successfully');
549
+ }
550
+
551
+ function toggleTodo(id) {
552
+ todos = todos.map(todo => {
553
+ if (todo.id === id) {
554
+ return { ...todo, completed: !todo.completed };
555
+ }
556
+ return todo;
557
+ });
558
+ saveAndRender();
559
+ }
560
+
561
+ function deleteTodo(id) {
562
+ const item = document.querySelector(`li[data-id="${id}"]`);
563
+ if (item) {
564
+ item.style.animation = 'slideOut 0.3s ease forwards';
565
+ setTimeout(() => {
566
+ todos = todos.filter(todo => todo.id !== id);
567
+ saveAndRender();
568
+ showToast('Task deleted');
569
+ }, 300);
570
+ }
571
+ }
572
+
573
+ function cyclePriority(id) {
574
+ const priorities = ['low', 'medium', 'high'];
575
+ todos = todos.map(todo => {
576
+ if (todo.id === id) {
577
+ const currentIndex = priorities.indexOf(todo.priority);
578
+ const nextIndex = (currentIndex + 1) % priorities.length;
579
+ return { ...todo, priority: priorities[nextIndex] };
580
+ }
581
+ return todo;
582
+ });
583
+ saveAndRender();
584
+ }
585
+
586
+ function saveAndRender() {
587
+ localStorage.setItem('myTodos', JSON.stringify(todos));
588
+ renderTodos();
589
+ }
590
+
591
+ function renderTodos() {
592
+ todoList.innerHTML = '';
593
+
594
+ let filteredTodos = todos;
595
+ if (currentFilter === 'active') {
596
+ filteredTodos = todos.filter(t => !t.completed);
597
+ } else if (currentFilter === 'completed') {
598
+ filteredTodos = todos.filter(t => t.completed);
599
+ }
600
+
601
+ // Update items left count
602
+ const activeCount = todos.filter(t => !t.completed).length;
603
+ itemsLeft.textContent = `${activeCount} ${activeCount === 1 ? 'item' : 'items'} left`;
604
+
605
+ // Show/Hide empty state
606
+ if (filteredTodos.length === 0) {
607
+ emptyState.style.display = 'block';
608
+ if(currentFilter === 'completed') emptyState.querySelector('p').textContent = "No completed tasks yet.";
609
+ else if(currentFilter === 'active') emptyState.querySelector('p').textContent = "No active tasks. You're all caught up!";
610
+ else emptyState.querySelector('p').textContent = "No tasks found. Enjoy your day!";
611
+ } else {
612
+ emptyState.style.display = 'none';
613
+ }
614
+
615
+ filteredTodos.forEach(todo => {
616
+ const li = document.createElement('li');
617
+ li.className = `todo-item ${todo.completed ? 'completed' : ''} priority-${todo.priority}`;
618
+ li.dataset.id = todo.id;
619
+
620
+ // Priority Icon Color Logic
621
+ let priorityIcon = 'fa-circle';
622
+ let priorityColor = 'color: #f59e0b'; // default medium (orange)
623
+ if(todo.priority === 'high') priorityColor = 'color: #ef4444'; // red
624
+ if(todo.priority === 'low') priorityColor = 'color: #10b981'; // green
625
+
626
+ li.innerHTML = `
627
+ <div class="custom-checkbox" onclick="toggleTodo(${todo.id})">
628
+ <i class="fas fa-check"></i>
629
+ </div>
630
+ <span class="todo-text">${escapeHtml(todo.text)}</span>
631
+ <div class="actions">
632
+ <button class="action-btn" onclick="cyclePriority(${todo.id})" title="Change Priority">
633
+ <i class="fas fa-flag" style="${priorityColor}"></i>
634
+ </button>
635
+ <button class="action-btn delete-btn" onclick="deleteTodo(${todo.id})" title="Delete Task">
636
+ <i class="fas fa-trash"></i>
637
+ </button>
638
+ </div>
639
+ `;
640
+ todoList.appendChild(li);
641
+ });
642
+ }
643
+
644
+ // --- Helper Functions ---
645
+
646
+ function updateDate() {
647
+ const options = { weekday: 'long', month: 'long', day: 'numeric' };
648
+ const today = new Date();
649
+ dateDisplay.textContent = today.toLocaleDateString('en-US', options);
650
+ }
651
+
652
+ function showToast(message, isError = false) {
653
+ toastMsg.textContent = message;
654
+ const icon = toast.querySelector('i');
655
+
656
+ if (isError) {
657
+ icon.className = 'fas fa-exclamation-circle';
658
+ toast.style.background = '#ef4444';
659
+ } else {
660
+ icon.className = 'fas fa-check-circle';
661
+ toast.style.background = '#1f2937';
662
+ }
663
+
664
+ toast.classList.add('show');
665
+ setTimeout(() => {
666
+ toast.classList.remove('show');
667
+ }, 3000);
668
+ }
669
+
670
+ function escapeHtml(text) {
671
+ const div = document.createElement('div');
672
+ div.textContent = text;
673
+ return div.innerHTML;
674
+ }
675
+
676
+ // --- Drag and Drop Logic (Basic) ---
677
+ let dragStartIndex;
678
+
679
+ function dragStart() {
680
+ dragStartIndex = +this.closest('li').getAttribute('data-index');
681
+ }
682
+
683
+ function dragDrop() {
684
+ const dragEndIndex = +this.closest('li').getAttribute('data-index');
685
+ swapItems(dragStartIndex, dragEndIndex);
686
+ this.classList.remove('over');
687
+ }
688
+
689
+ function swapItems(fromIndex, toIndex) {
690
+ const itemOne = todos[fromIndex];
691
+ const itemTwo = todos[toIndex];
692
+ todos[fromIndex] = itemTwo;
693
+ todos[toIndex] = itemOne;
694
+ saveAndRender();
695
+ }
696
+
697
+ /* Note: Implementing full native HTML5 Drag and Drop for this list structure requires
698
+ more extensive event handling. For this version, we focus on the core CRUD functionality
699
+ and keeping the UI responsive. */
700
+ </script>
701
+ </body>
702
+ </html>