akhaliq HF Staff commited on
Commit
d0c7707
Β·
verified Β·
1 Parent(s): e401285

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +451 -614
index.html CHANGED
@@ -3,8 +3,7 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>TaskFlow - Modern Todo App</title>
7
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
8
  <style>
9
  * {
10
  margin: 0;
@@ -13,736 +12,585 @@
13
  }
14
 
15
  :root {
16
- --primary: #6366f1;
17
- --primary-dark: #4f46e5;
18
- --secondary: #8b5cf6;
19
- --success: #10b981;
20
- --warning: #f59e0b;
21
- --danger: #ef4444;
22
- --dark: #1f2937;
23
- --light: #f3f4f6;
24
- --white: #ffffff;
25
- --gray: #6b7280;
26
- --border: #e5e7eb;
27
- --shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
28
- --shadow-lg: 0 10px 25px -5px rgba(0, 0, 0, 0.1);
 
 
 
 
29
  --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
30
  }
31
 
32
- [data-theme="dark"] {
33
- --primary: #818cf8;
34
- --primary-dark: #6366f1;
35
- --secondary: #a78bfa;
36
- --dark: #f3f4f6;
37
- --light: #1f2937;
38
- --white: #111827;
39
- --gray: #9ca3af;
40
- --border: #374151;
41
- --shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.3);
42
- --shadow-lg: 0 10px 25px -5px rgba(0, 0, 0, 0.3);
 
43
  }
44
 
45
  body {
46
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
47
- background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
 
48
  min-height: 100vh;
49
- color: var(--dark);
50
- transition: var(--transition);
51
- }
52
-
53
- .container {
54
- max-width: 900px;
55
- margin: 0 auto;
56
- padding: 2rem;
57
  }
58
 
59
  header {
60
- text-align: center;
61
- margin-bottom: 2rem;
62
- animation: slideDown 0.5s ease-out;
 
 
 
 
 
 
63
  }
64
 
65
  .header-content {
 
 
66
  display: flex;
67
  justify-content: space-between;
68
  align-items: center;
69
- margin-bottom: 1rem;
70
  }
71
 
72
- h1 {
73
- color: var(--white);
74
- font-size: 2.5rem;
75
- font-weight: 700;
76
- text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
77
  display: flex;
78
  align-items: center;
79
- gap: 0.5rem;
 
 
 
80
  }
81
 
82
- .logo {
83
- width: 40px;
84
- height: 40px;
85
- background: var(--white);
86
- border-radius: 10px;
87
  display: flex;
88
  align-items: center;
89
  justify-content: center;
90
- color: var(--primary);
91
- font-size: 1.5rem;
92
  }
93
 
94
  .header-actions {
95
  display: flex;
96
- gap: 1rem;
97
  }
98
 
99
  .theme-toggle {
100
- background: var(--white);
101
- border: none;
 
102
  width: 40px;
103
  height: 40px;
104
- border-radius: 50%;
105
- cursor: pointer;
106
  display: flex;
107
  align-items: center;
108
  justify-content: center;
109
- font-size: 1.2rem;
110
- color: var(--primary);
111
  transition: var(--transition);
112
- box-shadow: var(--shadow);
113
  }
114
 
115
  .theme-toggle:hover {
116
- transform: scale(1.1);
117
- box-shadow: var(--shadow-lg);
118
- }
119
-
120
- .main-card {
121
- background: var(--white);
122
- border-radius: 20px;
123
- padding: 2rem;
124
- box-shadow: var(--shadow-lg);
125
- animation: fadeIn 0.6s ease-out;
126
- }
127
-
128
- .stats {
129
- display: grid;
130
- grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
131
- gap: 1rem;
132
- margin-bottom: 2rem;
133
- }
134
-
135
- .stat-card {
136
- background: var(--light);
137
- padding: 1rem;
138
- border-radius: 10px;
139
- text-align: center;
140
- transition: var(--transition);
141
  }
142
 
143
- .stat-card:hover {
144
- transform: translateY(-2px);
145
- box-shadow: var(--shadow);
146
- }
147
-
148
- .stat-number {
149
- font-size: 2rem;
150
- font-weight: 700;
151
- color: var(--primary);
152
  }
153
 
154
- .stat-label {
155
- color: var(--gray);
156
- font-size: 0.875rem;
157
- margin-top: 0.25rem;
 
 
158
  }
159
 
160
- .add-todo-section {
161
- margin-bottom: 2rem;
 
 
 
 
 
 
 
162
  }
163
 
164
- .add-todo-form {
165
- display: grid;
166
- gap: 1rem;
167
  }
168
 
169
- .input-group {
170
  display: flex;
171
- gap: 0.5rem;
172
- flex-wrap: wrap;
173
  }
174
 
175
- .input-field {
176
  flex: 1;
177
- min-width: 200px;
178
- padding: 0.75rem 1rem;
179
- border: 2px solid var(--border);
180
- border-radius: 10px;
181
- font-size: 1rem;
 
182
  transition: var(--transition);
183
- background: var(--light);
184
- color: var(--dark);
185
- }
186
-
187
- .input-field:focus {
188
  outline: none;
189
- border-color: var(--primary);
190
- background: var(--white);
191
- }
192
-
193
- .select-field {
194
- padding: 0.75rem 1rem;
195
- border: 2px solid var(--border);
196
- border-radius: 10px;
197
- font-size: 1rem;
198
- background: var(--light);
199
- color: var(--dark);
200
- cursor: pointer;
201
- transition: var(--transition);
202
  }
203
 
204
- .select-field:focus {
205
- outline: none;
206
- border-color: var(--primary);
 
207
  }
208
 
209
- .btn {
210
- padding: 0.75rem 1.5rem;
 
 
211
  border: none;
212
- border-radius: 10px;
213
- font-size: 1rem;
214
  font-weight: 600;
215
  cursor: pointer;
216
  transition: var(--transition);
217
- display: inline-flex;
218
  align-items: center;
219
- gap: 0.5rem;
220
- }
221
-
222
- .btn-primary {
223
- background: var(--primary);
224
- color: var(--white);
225
  }
226
 
227
- .btn-primary:hover {
228
- background: var(--primary-dark);
229
  transform: translateY(-2px);
230
- box-shadow: var(--shadow-lg);
231
- }
232
-
233
- .btn-secondary {
234
- background: var(--gray);
235
- color: var(--white);
236
- }
237
-
238
- .btn-danger {
239
- background: var(--danger);
240
- color: var(--white);
241
  }
242
 
243
- .btn-sm {
244
- padding: 0.5rem 1rem;
245
- font-size: 0.875rem;
246
  }
247
 
248
- .filter-section {
249
  display: flex;
250
- gap: 0.5rem;
251
- margin-bottom: 1.5rem;
252
- flex-wrap: wrap;
253
- }
254
-
255
- .filter-btn {
256
- padding: 0.5rem 1rem;
257
- border: 2px solid var(--border);
258
- background: var(--white);
259
- color: var(--gray);
260
- border-radius: 20px;
261
- cursor: pointer;
262
- transition: var(--transition);
263
- font-weight: 500;
264
  }
265
 
266
- .filter-btn:hover {
267
- border-color: var(--primary);
268
- color: var(--primary);
269
- }
270
-
271
- .filter-btn.active {
272
- background: var(--primary);
273
- color: var(--white);
274
- border-color: var(--primary);
275
- }
276
-
277
- .search-box {
278
- position: relative;
279
  flex: 1;
280
- max-width: 300px;
281
- }
282
-
283
- .search-input {
284
- width: 100%;
285
- padding: 0.5rem 1rem 0.5rem 2.5rem;
286
- border: 2px solid var(--border);
287
- border-radius: 20px;
288
- background: var(--light);
289
  transition: var(--transition);
290
  }
291
 
292
- .search-input:focus {
293
- outline: none;
294
- border-color: var(--primary);
295
- background: var(--white);
296
  }
297
 
298
- .search-icon {
299
- position: absolute;
300
- left: 0.75rem;
301
- top: 50%;
302
- transform: translateY(-50%);
303
- color: var(--gray);
304
  }
305
 
306
- .todos-container {
 
307
  max-height: 500px;
308
  overflow-y: auto;
309
- padding-right: 0.5rem;
310
  }
311
 
312
- .todos-container::-webkit-scrollbar {
313
- width: 8px;
314
  }
315
 
316
- .todos-container::-webkit-scrollbar-track {
317
- background: var(--light);
318
- border-radius: 10px;
319
  }
320
 
321
- .todos-container::-webkit-scrollbar-thumb {
322
- background: var(--gray);
323
- border-radius: 10px;
324
  }
325
 
326
  .todo-item {
327
- background: var(--light);
328
- border-radius: 10px;
329
- padding: 1rem;
330
- margin-bottom: 0.75rem;
331
  display: flex;
332
  align-items: center;
333
- gap: 1rem;
 
 
 
 
334
  transition: var(--transition);
335
- animation: slideIn 0.3s ease-out;
336
- }
337
-
338
- .todo-item:hover {
339
- transform: translateX(5px);
340
- box-shadow: var(--shadow);
341
  }
342
 
343
- .todo-item.completed {
344
- opacity: 0.6;
 
 
 
 
 
 
 
345
  }
346
 
347
- .todo-item.completed .todo-text {
348
- text-decoration: line-through;
349
- color: var(--gray);
 
350
  }
351
 
352
  .todo-checkbox {
353
  width: 24px;
354
  height: 24px;
355
- border: 2px solid var(--primary);
356
  border-radius: 50%;
357
  cursor: pointer;
358
- display: flex;
359
- align-items: center;
360
- justify-content: center;
361
  transition: var(--transition);
 
362
  flex-shrink: 0;
363
  }
364
 
365
  .todo-checkbox:hover {
366
- background: var(--primary);
367
- color: var(--white);
368
  }
369
 
370
  .todo-checkbox.checked {
371
- background: var(--primary);
372
- color: var(--white);
373
  }
374
 
375
- .todo-content {
376
- flex: 1;
377
- }
378
-
379
- .todo-header {
380
- display: flex;
381
- align-items: center;
382
- gap: 0.5rem;
383
- margin-bottom: 0.25rem;
384
  }
385
 
386
  .todo-text {
387
- font-size: 1rem;
388
- color: var(--dark);
389
  flex: 1;
 
 
 
 
 
 
 
390
  }
391
 
392
- .todo-category {
393
- padding: 0.25rem 0.5rem;
394
- border-radius: 5px;
395
- font-size: 0.75rem;
396
- font-weight: 600;
397
- text-transform: uppercase;
398
- }
399
-
400
- .category-work {
401
- background: var(--primary);
402
- color: var(--white);
403
- }
404
-
405
- .category-personal {
406
- background: var(--success);
407
- color: var(--white);
408
- }
409
-
410
- .category-shopping {
411
- background: var(--warning);
412
- color: var(--white);
413
- }
414
-
415
- .category-health {
416
- background: var(--danger);
417
- color: var(--white);
418
- }
419
-
420
- .priority-badge {
421
- padding: 0.25rem 0.5rem;
422
- border-radius: 5px;
423
- font-size: 0.75rem;
424
- font-weight: 600;
425
- }
426
-
427
- .priority-high {
428
- background: var(--danger);
429
- color: var(--white);
430
- }
431
-
432
- .priority-medium {
433
- background: var(--warning);
434
- color: var(--white);
435
  }
436
 
437
- .priority-low {
438
- background: var(--success);
439
- color: var(--white);
440
  }
441
 
442
- .todo-meta {
443
  display: flex;
444
- align-items: center;
445
- gap: 1rem;
446
- font-size: 0.875rem;
447
- color: var(--gray);
448
  }
449
 
450
- .todo-actions {
451
- display: flex;
452
- gap: 0.5rem;
453
  }
454
 
455
  .action-btn {
456
  width: 32px;
457
  height: 32px;
458
  border: none;
459
- background: var(--white);
460
- color: var(--gray);
461
- border-radius: 8px;
462
  cursor: pointer;
463
  display: flex;
464
  align-items: center;
465
  justify-content: center;
466
  transition: var(--transition);
 
467
  }
468
 
469
  .action-btn:hover {
470
- color: var(--primary);
 
471
  transform: scale(1.1);
472
  }
473
 
474
- .action-btn.delete:hover {
475
- color: var(--danger);
476
- }
477
-
478
  .empty-state {
479
  text-align: center;
480
- padding: 3rem;
481
- color: var(--gray);
482
  }
483
 
484
  .empty-icon {
485
- font-size: 4rem;
486
- margin-bottom: 1rem;
487
  opacity: 0.5;
488
  }
489
 
490
- .footer-actions {
 
 
 
 
 
 
 
 
 
 
 
 
491
  display: flex;
492
  justify-content: space-between;
493
  align-items: center;
494
- margin-top: 2rem;
495
- padding-top: 1rem;
496
- border-top: 2px solid var(--border);
497
  }
498
 
499
- .progress-bar {
500
- flex: 1;
501
- height: 8px;
502
- background: var(--light);
503
- border-radius: 10px;
504
- overflow: hidden;
505
- margin-right: 1rem;
506
  }
507
 
508
- .progress-fill {
509
- height: 100%;
510
- background: linear-gradient(90deg, var(--primary), var(--secondary));
511
- border-radius: 10px;
512
- transition: width 0.5s ease;
 
 
 
 
513
  }
514
 
515
- @keyframes slideDown {
516
- from {
517
- opacity: 0;
518
- transform: translateY(-20px);
519
- }
520
- to {
521
- opacity: 1;
522
- transform: translateY(0);
523
- }
524
  }
525
 
526
- @keyframes fadeIn {
527
- from {
528
- opacity: 0;
529
- }
530
- to {
531
- opacity: 1;
532
- }
533
  }
534
 
535
- @keyframes slideIn {
536
- from {
537
- opacity: 0;
538
- transform: translateX(-20px);
539
- }
540
- to {
541
- opacity: 1;
542
- transform: translateX(0);
543
- }
544
  }
545
 
546
- @media (max-width: 768px) {
547
- .container {
548
- padding: 1rem;
549
- }
550
 
551
- h1 {
552
- font-size: 2rem;
553
- }
 
 
 
554
 
555
- .main-card {
556
- padding: 1.5rem;
557
- }
 
558
 
559
- .stats {
560
- grid-template-columns: repeat(2, 1fr);
 
561
  }
562
 
563
- .filter-section {
564
  flex-direction: column;
565
  }
566
 
567
- .search-box {
568
- max-width: 100%;
 
569
  }
570
 
571
- .footer-actions {
572
- flex-direction: column;
573
- gap: 1rem;
574
  }
575
 
576
- .progress-bar {
577
- width: 100%;
578
- margin-right: 0;
579
  }
580
  }
581
  </style>
582
  </head>
583
  <body>
584
- <div class="container">
585
- <header>
586
- <div class="header-content">
587
- <h1>
588
- <div class="logo">
589
- <i class="fas fa-tasks"></i>
590
- </div>
591
- TaskFlow
592
- </h1>
593
- <div class="header-actions">
594
- <button class="theme-toggle" onclick="toggleTheme()">
595
- <i class="fas fa-moon" id="themeIcon"></i>
596
- </button>
597
- </div>
598
  </div>
599
- <p style="color: white; opacity: 0.9;">Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" style="color: white; text-decoration: underline;" target="_blank">anycoder</a></p>
600
- </header>
601
-
602
- <main class="main-card">
603
- <section class="stats">
604
- <div class="stat-card">
605
- <div class="stat-number" id="totalTasks">0</div>
606
- <div class="stat-label">Total Tasks</div>
607
- </div>
608
- <div class="stat-card">
609
- <div class="stat-number" id="completedTasks">0</div>
610
- <div class="stat-label">Completed</div>
611
- </div>
612
- <div class="stat-card">
613
- <div class="stat-number" id="pendingTasks">0</div>
614
- <div class="stat-label">Pending</div>
615
- </div>
616
- <div class="stat-card">
617
- <div class="stat-number" id="todayTasks">0</div>
618
- <div class="stat-label">Due Today</div>
 
 
 
 
619
  </div>
620
- </section>
621
-
622
- <section class="add-todo-section">
623
- <form class="add-todo-form" onsubmit="addTodo(event)">
624
- <div class="input-group">
625
- <input type="text" class="input-field" id="todoInput" placeholder="What needs to be done?" required>
626
- <select class="select-field" id="categorySelect">
627
- <option value="work">Work</option>
628
- <option value="personal">Personal</option>
629
- <option value="shopping">Shopping</option>
630
- <option value="health">Health</option>
631
- </select>
632
- <select class="select-field" id="prioritySelect">
633
- <option value="low">Low Priority</option>
634
- <option value="medium">Medium Priority</option>
635
- <option value="high">High Priority</option>
636
- </select>
637
- <input type="date" class="input-field" id="dueDateInput" style="max-width: 200px;">
638
- <button type="submit" class="btn btn-primary">
639
- <i class="fas fa-plus"></i>
640
- Add Task
641
- </button>
642
- </div>
643
- </form>
644
- </section>
645
-
646
- <section class="filter-section">
647
- <button class="filter-btn active" onclick="filterTodos('all')">All</button>
648
- <button class="filter-btn" onclick="filterTodos('active')">Active</button>
649
- <button class="filter-btn" onclick="filterTodos('completed')">Completed</button>
650
- <div class="search-box">
651
- <i class="fas fa-search search-icon"></i>
652
- <input type="text" class="search-input" placeholder="Search tasks..." oninput="searchTodos(this.value)">
653
  </div>
654
- </section>
655
 
656
- <section class="todos-container" id="todosContainer">
657
  <div class="empty-state">
658
- <div class="empty-icon">
659
- <i class="fas fa-clipboard-list"></i>
660
- </div>
661
- <p>No tasks yet. Add your first task above!</p>
662
  </div>
663
- </section>
664
 
665
- <footer class="footer-actions">
666
- <div style="display: flex; align-items: center; flex: 1;">
667
- <div class="progress-bar">
668
- <div class="progress-fill" id="progressBar" style="width: 0%"></div>
669
- </div>
670
- <span id="progressText" style="color: var(--gray); font-size: 0.875rem;">0% Complete</span>
671
  </div>
672
- <button class="btn btn-danger btn-sm" onclick="clearCompleted()">
673
- <i class="fas fa-trash"></i>
674
- Clear Completed
675
- </button>
676
- </footer>
677
- </main>
678
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
679
 
680
  <script>
681
- let todos = [];
682
  let currentFilter = 'all';
683
- let searchTerm = '';
684
 
685
- // Initialize app
686
- document.addEventListener('DOMContentLoaded', () => {
687
- loadTodos();
688
- renderTodos();
689
- updateStats();
690
-
691
- // Set today's date as default
692
- const today = new Date().toISOString().split('T')[0];
693
- document.getElementById('dueDateInput').value = today;
694
-
695
- // Check for saved theme
696
- const savedTheme = localStorage.getItem('theme') || 'light';
697
- if (savedTheme === 'dark') {
698
- document.documentElement.setAttribute('data-theme', 'dark');
699
- document.getElementById('themeIcon').className = 'fas fa-sun';
700
- }
701
- });
702
 
703
- function toggleTheme() {
704
- const currentTheme = document.documentElement.getAttribute('data-theme');
705
- const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
706
- document.documentElement.setAttribute('data-theme', newTheme);
707
- localStorage.setItem('theme', newTheme);
708
-
709
- const icon = document.getElementById('themeIcon');
710
- icon.className = newTheme === 'dark' ? 'fas fa-sun' : 'fas fa-moon';
711
  }
712
 
713
- function addTodo(event) {
714
- event.preventDefault();
715
-
716
  const input = document.getElementById('todoInput');
717
- const category = document.getElementById('categorySelect').value;
718
- const priority = document.getElementById('prioritySelect').value;
719
- const dueDate = document.getElementById('dueDateInput').value;
720
 
 
 
 
 
 
721
  const todo = {
722
- id: Date.now(),
723
- text: input.value.trim(),
724
- category: category,
725
- priority: priority,
726
- dueDate: dueDate,
727
  completed: false,
728
  createdAt: new Date().toISOString()
729
  };
730
-
731
  todos.unshift(todo);
732
  saveTodos();
733
  renderTodos();
734
- updateStats();
735
-
736
- // Reset form
737
  input.value = '';
738
- const today = new Date().toISOString().split('T')[0];
739
- document.getElementById('dueDateInput').value = today;
740
-
741
- // Show success animation
742
- input.style.borderColor = 'var(--success)';
743
- setTimeout(() => {
744
- input.style.borderColor = '';
745
- }, 1000);
746
  }
747
 
748
  function toggleTodo(id) {
@@ -751,7 +599,6 @@
751
  todo.completed = !todo.completed;
752
  saveTodos();
753
  renderTodos();
754
- updateStats();
755
  }
756
  }
757
 
@@ -759,149 +606,139 @@
759
  todos = todos.filter(t => t.id !== id);
760
  saveTodos();
761
  renderTodos();
762
- updateStats();
763
  }
764
 
765
- function editTodo(id) {
 
 
 
 
766
  const todo = todos.find(t => t.id === id);
767
  if (todo) {
768
- const newText = prompt('Edit task:', todo.text);
769
- if (newText && newText.trim()) {
770
- todo.text = newText.trim();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
771
  saveTodos();
772
- renderTodos();
773
  }
 
774
  }
 
775
  }
776
 
777
  function filterTodos(filter) {
778
  currentFilter = filter;
779
 
780
- // Update active button
781
- document.querySelectorAll('.filter-btn').forEach(btn => {
782
- btn.classList.remove('active');
783
  });
784
  event.target.classList.add('active');
785
 
786
  renderTodos();
787
  }
788
 
789
- function searchTodos(term) {
790
- searchTerm = term.toLowerCase();
 
791
  renderTodos();
792
  }
793
 
794
  function getFilteredTodos() {
795
- let filtered = todos;
796
-
797
- // Apply filter
798
- if (currentFilter === 'active') {
799
- filtered = filtered.filter(t => !t.completed);
800
- } else if (currentFilter === 'completed') {
801
- filtered = filtered.filter(t => t.completed);
802
- }
803
-
804
- // Apply search
805
- if (searchTerm) {
806
- filtered = filtered.filter(t =>
807
- t.text.toLowerCase().includes(searchTerm) ||
808
- t.category.toLowerCase().includes(searchTerm)
809
- );
810
  }
811
-
812
- return filtered;
813
  }
814
 
815
  function renderTodos() {
816
- const container = document.getElementById('todosContainer');
817
  const filteredTodos = getFilteredTodos();
818
 
819
  if (filteredTodos.length === 0) {
820
- container.innerHTML = `
821
  <div class="empty-state">
822
- <div class="empty-icon">
823
- <i class="fas fa-clipboard-list"></i>
824
- </div>
825
- <p>${searchTerm ? 'No tasks found matching your search.' : 'No tasks yet. Add your first task above!'}</p>
826
  </div>
827
  `;
828
  return;
829
  }
830
-
831
- container.innerHTML = filteredTodos.map(todo => {
832
- const isOverdue = todo.dueDate && new Date(todo.dueDate) < new Date() && !todo.completed;
833
- const dueDateFormatted = todo.dueDate ? new Date(todo.dueDate).toLocaleDateString() : '';
834
-
835
- return `
836
- <div class="todo-item ${todo.completed ? 'completed' : ''}" style="${isOverdue ? 'border-left: 4px solid var(--danger);' : ''}">
837
- <div class="todo-checkbox ${todo.completed ? 'checked' : ''}" onclick="toggleTodo(${todo.id})">
838
- ${todo.completed ? '<i class="fas fa-check"></i>' : ''}
839
- </div>
840
- <div class="todo-content">
841
- <div class="todo-header">
842
- <span class="todo-text">${todo.text}</span>
843
- <span class="todo-category category-${todo.category}">${todo.category}</span>
844
- <span class="priority-badge priority-${todo.priority}">${todo.priority}</span>
845
- </div>
846
- <div class="todo-meta">
847
- ${todo.dueDate ? `
848
- <span style="${isOverdue ? 'color: var(--danger);' : ''}">
849
- <i class="fas fa-calendar"></i> ${dueDateFormatted}
850
- ${isOverdue ? ' (Overdue)' : ''}
851
- </span>
852
- ` : ''}
853
- </div>
854
- </div>
855
- <div class="todo-actions">
856
- <button class="action-btn" onclick="editTodo(${todo.id})">
857
- <i class="fas fa-edit"></i>
858
- </button>
859
- <button class="action-btn delete" onclick="deleteTodo(${todo.id})">
860
- <i class="fas fa-trash"></i>
861
- </button>
862
- </div>
863
  </div>
864
- `;
865
- }).join('');
 
 
 
 
 
 
 
866
  }
867
 
868
  function updateStats() {
869
  const total = todos.length;
870
  const completed = todos.filter(t => t.completed).length;
871
- const pending = total - completed;
872
- const today = new Date().toISOString().split('T')[0];
873
- const dueToday = todos.filter(t => t.dueDate === today && !t.completed).length;
874
 
875
  document.getElementById('totalTasks').textContent = total;
876
  document.getElementById('completedTasks').textContent = completed;
877
- document.getElementById('pendingTasks').textContent = pending;
878
- document.getElementById('todayTasks').textContent = dueToday;
879
-
880
- // Update progress bar
881
- const progress = total > 0 ? Math.round((completed / total) * 100) : 0;
882
- document.getElementById('progressBar').style.width = `${progress}%`;
883
- document.getElementById('progressText').textContent = `${progress}% Complete`;
884
  }
885
 
886
- function clearCompleted() {
887
- if (confirm('Are you sure you want to clear all completed tasks?')) {
888
- todos = todos.filter(t => !t.completed);
889
- saveTodos();
890
- renderTodos();
891
- updateStats();
 
 
 
 
892
  }
893
  }
894
 
895
- function saveTodos() {
896
- localStorage.setItem('todos', JSON.stringify(todos));
897
- }
898
-
899
- function loadTodos() {
900
- const saved = localStorage.getItem('todos');
901
- if (saved) {
902
- todos = JSON.parse(saved);
903
- }
904
- }
905
  </script>
906
  </body>
907
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Todo - Apple Style</title>
 
7
  <style>
8
  * {
9
  margin: 0;
 
12
  }
13
 
14
  :root {
15
+ --primary-color: #007AFF;
16
+ --secondary-color: #5856D6;
17
+ --success-color: #34C759;
18
+ --danger-color: #FF3B30;
19
+ --warning-color: #FF9500;
20
+ --background: #F2F2F7;
21
+ --surface: #FFFFFF;
22
+ --text-primary: #1C1C1E;
23
+ --text-secondary: #8E8E93;
24
+ --text-tertiary: #C7C7CC;
25
+ --border-color: #D1D1D6;
26
+ --shadow-sm: 0 2px 10px rgba(0, 0, 0, 0.04);
27
+ --shadow-md: 0 4px 20px rgba(0, 0, 0, 0.08);
28
+ --shadow-lg: 0 10px 40px rgba(0, 0, 0, 0.12);
29
+ --radius-sm: 8px;
30
+ --radius-md: 12px;
31
+ --radius-lg: 16px;
32
  --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
33
  }
34
 
35
+ @media (prefers-color-scheme: dark) {
36
+ :root {
37
+ --background: #000000;
38
+ --surface: #1C1C1E;
39
+ --text-primary: #FFFFFF;
40
+ --text-secondary: #8E8E93;
41
+ --text-tertiary: #48484A;
42
+ --border-color: #38383A;
43
+ --shadow-sm: 0 2px 10px rgba(0, 0, 0, 0.3);
44
+ --shadow-md: 0 4px 20px rgba(0, 0, 0, 0.4);
45
+ --shadow-lg: 0 10px 40px rgba(0, 0, 0, 0.5);
46
+ }
47
  }
48
 
49
  body {
50
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
51
+ background: var(--background);
52
+ color: var(--text-primary);
53
  min-height: 100vh;
54
+ display: flex;
55
+ flex-direction: column;
56
+ line-height: 1.6;
57
+ -webkit-font-smoothing: antialiased;
58
+ -moz-osx-font-smoothing: grayscale;
 
 
 
59
  }
60
 
61
  header {
62
+ background: var(--surface);
63
+ backdrop-filter: blur(20px);
64
+ -webkit-backdrop-filter: blur(20px);
65
+ border-bottom: 1px solid var(--border-color);
66
+ padding: 20px;
67
+ position: sticky;
68
+ top: 0;
69
+ z-index: 100;
70
+ box-shadow: var(--shadow-sm);
71
  }
72
 
73
  .header-content {
74
+ max-width: 800px;
75
+ margin: 0 auto;
76
  display: flex;
77
  justify-content: space-between;
78
  align-items: center;
 
79
  }
80
 
81
+ .logo {
 
 
 
 
82
  display: flex;
83
  align-items: center;
84
+ gap: 12px;
85
+ font-size: 24px;
86
+ font-weight: 600;
87
+ color: var(--text-primary);
88
  }
89
 
90
+ .logo-icon {
91
+ width: 32px;
92
+ height: 32px;
93
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
94
+ border-radius: 8px;
95
  display: flex;
96
  align-items: center;
97
  justify-content: center;
98
+ color: white;
99
+ font-size: 20px;
100
  }
101
 
102
  .header-actions {
103
  display: flex;
104
+ gap: 8px;
105
  }
106
 
107
  .theme-toggle {
108
+ background: var(--background);
109
+ border: 1px solid var(--border-color);
110
+ border-radius: var(--radius-sm);
111
  width: 40px;
112
  height: 40px;
 
 
113
  display: flex;
114
  align-items: center;
115
  justify-content: center;
116
+ cursor: pointer;
 
117
  transition: var(--transition);
118
+ font-size: 18px;
119
  }
120
 
121
  .theme-toggle:hover {
122
+ background: var(--border-color);
123
+ transform: scale(1.05);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  }
125
 
126
+ main {
127
+ flex: 1;
128
+ padding: 40px 20px;
129
+ max-width: 800px;
130
+ width: 100%;
131
+ margin: 0 auto;
 
 
 
132
  }
133
 
134
+ .todo-container {
135
+ background: var(--surface);
136
+ border-radius: var(--radius-lg);
137
+ box-shadow: var(--shadow-md);
138
+ overflow: hidden;
139
+ animation: slideUp 0.5s ease-out;
140
  }
141
 
142
+ @keyframes slideUp {
143
+ from {
144
+ opacity: 0;
145
+ transform: translateY(20px);
146
+ }
147
+ to {
148
+ opacity: 1;
149
+ transform: translateY(0);
150
+ }
151
  }
152
 
153
+ .todo-header {
154
+ padding: 24px;
155
+ border-bottom: 1px solid var(--border-color);
156
  }
157
 
158
+ .todo-input-wrapper {
159
  display: flex;
160
+ gap: 12px;
161
+ margin-bottom: 20px;
162
  }
163
 
164
+ .todo-input {
165
  flex: 1;
166
+ padding: 14px 16px;
167
+ border: 2px solid var(--border-color);
168
+ border-radius: var(--radius-md);
169
+ font-size: 16px;
170
+ background: var(--background);
171
+ color: var(--text-primary);
172
  transition: var(--transition);
 
 
 
 
 
173
  outline: none;
 
 
 
 
 
 
 
 
 
 
 
 
 
174
  }
175
 
176
+ .todo-input:focus {
177
+ border-color: var(--primary-color);
178
+ background: var(--surface);
179
+ box-shadow: 0 0 0 4px rgba(0, 122, 255, 0.1);
180
  }
181
 
182
+ .add-btn {
183
+ padding: 14px 24px;
184
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
185
+ color: white;
186
  border: none;
187
+ border-radius: var(--radius-md);
188
+ font-size: 16px;
189
  font-weight: 600;
190
  cursor: pointer;
191
  transition: var(--transition);
192
+ display: flex;
193
  align-items: center;
194
+ gap: 8px;
195
+ box-shadow: var(--shadow-sm);
 
 
 
 
196
  }
197
 
198
+ .add-btn:hover {
 
199
  transform: translateY(-2px);
200
+ box-shadow: var(--shadow-md);
 
 
 
 
 
 
 
 
 
 
201
  }
202
 
203
+ .add-btn:active {
204
+ transform: translateY(0);
 
205
  }
206
 
207
+ .filter-tabs {
208
  display: flex;
209
+ gap: 8px;
210
+ padding: 4px;
211
+ background: var(--background);
212
+ border-radius: var(--radius-md);
 
 
 
 
 
 
 
 
 
 
213
  }
214
 
215
+ .filter-tab {
 
 
 
 
 
 
 
 
 
 
 
 
216
  flex: 1;
217
+ padding: 10px;
218
+ background: transparent;
219
+ border: none;
220
+ border-radius: var(--radius-sm);
221
+ font-size: 14px;
222
+ font-weight: 500;
223
+ color: var(--text-secondary);
224
+ cursor: pointer;
 
225
  transition: var(--transition);
226
  }
227
 
228
+ .filter-tab.active {
229
+ background: var(--surface);
230
+ color: var(--primary-color);
231
+ box-shadow: var(--shadow-sm);
232
  }
233
 
234
+ .filter-tab:hover:not(.active) {
235
+ color: var(--text-primary);
 
 
 
 
236
  }
237
 
238
+ .todo-list {
239
+ min-height: 300px;
240
  max-height: 500px;
241
  overflow-y: auto;
242
+ padding: 16px;
243
  }
244
 
245
+ .todo-list::-webkit-scrollbar {
246
+ width: 6px;
247
  }
248
 
249
+ .todo-list::-webkit-scrollbar-track {
250
+ background: var(--background);
 
251
  }
252
 
253
+ .todo-list::-webkit-scrollbar-thumb {
254
+ background: var(--border-color);
255
+ border-radius: 3px;
256
  }
257
 
258
  .todo-item {
 
 
 
 
259
  display: flex;
260
  align-items: center;
261
+ gap: 12px;
262
+ padding: 16px;
263
+ background: var(--background);
264
+ border-radius: var(--radius-md);
265
+ margin-bottom: 8px;
266
  transition: var(--transition);
267
+ animation: fadeIn 0.3s ease-out;
 
 
 
 
 
268
  }
269
 
270
+ @keyframes fadeIn {
271
+ from {
272
+ opacity: 0;
273
+ transform: translateX(-20px);
274
+ }
275
+ to {
276
+ opacity: 1;
277
+ transform: translateX(0);
278
+ }
279
  }
280
 
281
+ .todo-item:hover {
282
+ background: var(--surface);
283
+ box-shadow: var(--shadow-sm);
284
+ transform: translateX(4px);
285
  }
286
 
287
  .todo-checkbox {
288
  width: 24px;
289
  height: 24px;
290
+ border: 2px solid var(--border-color);
291
  border-radius: 50%;
292
  cursor: pointer;
 
 
 
293
  transition: var(--transition);
294
+ position: relative;
295
  flex-shrink: 0;
296
  }
297
 
298
  .todo-checkbox:hover {
299
+ border-color: var(--primary-color);
300
+ transform: scale(1.1);
301
  }
302
 
303
  .todo-checkbox.checked {
304
+ background: var(--success-color);
305
+ border-color: var(--success-color);
306
  }
307
 
308
+ .todo-checkbox.checked::after {
309
+ content: 'βœ“';
310
+ position: absolute;
311
+ top: 50%;
312
+ left: 50%;
313
+ transform: translate(-50%, -50%);
314
+ color: white;
315
+ font-size: 14px;
316
+ font-weight: bold;
317
  }
318
 
319
  .todo-text {
 
 
320
  flex: 1;
321
+ font-size: 16px;
322
+ color: var(--text-primary);
323
+ transition: var(--transition);
324
+ cursor: text;
325
+ padding: 4px;
326
+ border-radius: var(--radius-sm);
327
+ outline: none;
328
  }
329
 
330
+ .todo-text.completed {
331
+ text-decoration: line-through;
332
+ color: var(--text-tertiary);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
333
  }
334
 
335
+ .todo-text:focus {
336
+ background: var(--surface);
337
+ padding: 4px 8px;
338
  }
339
 
340
+ .todo-actions {
341
  display: flex;
342
+ gap: 8px;
343
+ opacity: 0;
344
+ transition: var(--transition);
 
345
  }
346
 
347
+ .todo-item:hover .todo-actions {
348
+ opacity: 1;
 
349
  }
350
 
351
  .action-btn {
352
  width: 32px;
353
  height: 32px;
354
  border: none;
355
+ background: var(--surface);
356
+ border-radius: var(--radius-sm);
 
357
  cursor: pointer;
358
  display: flex;
359
  align-items: center;
360
  justify-content: center;
361
  transition: var(--transition);
362
+ color: var(--text-secondary);
363
  }
364
 
365
  .action-btn:hover {
366
+ background: var(--danger-color);
367
+ color: white;
368
  transform: scale(1.1);
369
  }
370
 
 
 
 
 
371
  .empty-state {
372
  text-align: center;
373
+ padding: 60px 20px;
374
+ color: var(--text-secondary);
375
  }
376
 
377
  .empty-icon {
378
+ font-size: 64px;
379
+ margin-bottom: 16px;
380
  opacity: 0.5;
381
  }
382
 
383
+ .empty-text {
384
+ font-size: 18px;
385
+ margin-bottom: 8px;
386
+ }
387
+
388
+ .empty-subtext {
389
+ font-size: 14px;
390
+ color: var(--text-tertiary);
391
+ }
392
+
393
+ .todo-footer {
394
+ padding: 20px;
395
+ border-top: 1px solid var(--border-color);
396
  display: flex;
397
  justify-content: space-between;
398
  align-items: center;
399
+ font-size: 14px;
400
+ color: var(--text-secondary);
 
401
  }
402
 
403
+ .todo-count {
404
+ font-weight: 500;
 
 
 
 
 
405
  }
406
 
407
+ .clear-btn {
408
+ padding: 8px 16px;
409
+ background: transparent;
410
+ border: 1px solid var(--border-color);
411
+ border-radius: var(--radius-sm);
412
+ color: var(--text-secondary);
413
+ cursor: pointer;
414
+ transition: var(--transition);
415
+ font-size: 14px;
416
  }
417
 
418
+ .clear-btn:hover {
419
+ background: var(--danger-color);
420
+ border-color: var(--danger-color);
421
+ color: white;
422
+ transform: scale(1.05);
 
 
 
 
423
  }
424
 
425
+ .stats {
426
+ display: grid;
427
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
428
+ gap: 16px;
429
+ margin-top: 24px;
 
 
430
  }
431
 
432
+ .stat-card {
433
+ background: var(--surface);
434
+ padding: 20px;
435
+ border-radius: var(--radius-md);
436
+ text-align: center;
437
+ box-shadow: var(--shadow-sm);
438
+ transition: var(--transition);
 
 
439
  }
440
 
441
+ .stat-card:hover {
442
+ transform: translateY(-4px);
443
+ box-shadow: var(--shadow-md);
444
+ }
445
 
446
+ .stat-value {
447
+ font-size: 32px;
448
+ font-weight: 600;
449
+ color: var(--primary-color);
450
+ margin-bottom: 4px;
451
+ }
452
 
453
+ .stat-label {
454
+ font-size: 14px;
455
+ color: var(--text-secondary);
456
+ }
457
 
458
+ @media (max-width: 640px) {
459
+ main {
460
+ padding: 20px 16px;
461
  }
462
 
463
+ .todo-input-wrapper {
464
  flex-direction: column;
465
  }
466
 
467
+ .add-btn {
468
+ width: 100%;
469
+ justify-content: center;
470
  }
471
 
472
+ .filter-tabs {
473
+ flex-wrap: wrap;
 
474
  }
475
 
476
+ .stats {
477
+ grid-template-columns: 1fr;
 
478
  }
479
  }
480
  </style>
481
  </head>
482
  <body>
483
+ <header>
484
+ <div class="header-content">
485
+ <div class="logo">
486
+ <div class="logo-icon">βœ“</div>
487
+ <span>Todo</span>
 
 
 
 
 
 
 
 
 
488
  </div>
489
+ <div class="header-actions">
490
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="text-decoration: none; color: var(--text-secondary); font-size: 14px; margin-right: 12px;">
491
+ Built with anycoder
492
+ </a>
493
+ <button class="theme-toggle" onclick="toggleTheme()">πŸŒ™</button>
494
+ </div>
495
+ </div>
496
+ </header>
497
+
498
+ <main>
499
+ <div class="todo-container">
500
+ <div class="todo-header">
501
+ <div class="todo-input-wrapper">
502
+ <input
503
+ type="text"
504
+ class="todo-input"
505
+ id="todoInput"
506
+ placeholder="What needs to be done?"
507
+ onkeypress="handleInputKeypress(event)"
508
+ >
509
+ <button class="add-btn" onclick="addTodo()">
510
+ <span>+</span>
511
+ <span>Add</span>
512
+ </button>
513
  </div>
514
+ <div class="filter-tabs">
515
+ <button class="filter-tab active" onclick="filterTodos('all')">All</button>
516
+ <button class="filter-tab" onclick="filterTodos('active')">Active</button>
517
+ <button class="filter-tab" onclick="filterTodos('completed')">Completed</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
518
  </div>
519
+ </div>
520
 
521
+ <div class="todo-list" id="todoList">
522
  <div class="empty-state">
523
+ <div class="empty-icon">πŸ“</div>
524
+ <div class="empty-text">No tasks yet</div>
525
+ <div class="empty-subtext">Add your first task to get started</div>
 
526
  </div>
527
+ </div>
528
 
529
+ <div class="todo-footer">
530
+ <div class="todo-count">
531
+ <span id="activeCount">0</span> active tasks
 
 
 
532
  </div>
533
+ <button class="clear-btn" onclick="clearCompleted()">Clear Completed</button>
534
+ </div>
535
+ </div>
536
+
537
+ <div class="stats">
538
+ <div class="stat-card">
539
+ <div class="stat-value" id="totalTasks">0</div>
540
+ <div class="stat-label">Total Tasks</div>
541
+ </div>
542
+ <div class="stat-card">
543
+ <div class="stat-value" id="completedTasks">0</div>
544
+ <div class="stat-label">Completed</div>
545
+ </div>
546
+ <div class="stat-card">
547
+ <div class="stat-value" id="completionRate">0%</div>
548
+ <div class="stat-label">Completion Rate</div>
549
+ </div>
550
+ </div>
551
+ </main>
552
 
553
  <script>
554
+ let todos = JSON.parse(localStorage.getItem('todos')) || [];
555
  let currentFilter = 'all';
556
+ let editingId = null;
557
 
558
+ function generateId() {
559
+ return Date.now().toString(36) + Math.random().toString(36).substr(2);
560
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
561
 
562
+ function saveTodos() {
563
+ localStorage.setItem('todos', JSON.stringify(todos));
564
+ updateStats();
 
 
 
 
 
565
  }
566
 
567
+ function addTodo() {
 
 
568
  const input = document.getElementById('todoInput');
569
+ const text = input.value.trim();
 
 
570
 
571
+ if (text === '') {
572
+ input.focus();
573
+ return;
574
+ }
575
+
576
  const todo = {
577
+ id: generateId(),
578
+ text: text,
 
 
 
579
  completed: false,
580
  createdAt: new Date().toISOString()
581
  };
582
+
583
  todos.unshift(todo);
584
  saveTodos();
585
  renderTodos();
 
 
 
586
  input.value = '';
587
+ input.focus();
588
+ }
589
+
590
+ function handleInputKeypress(event) {
591
+ if (event.key === 'Enter') {
592
+ addTodo();
593
+ }
 
594
  }
595
 
596
  function toggleTodo(id) {
 
599
  todo.completed = !todo.completed;
600
  saveTodos();
601
  renderTodos();
 
602
  }
603
  }
604
 
 
606
  todos = todos.filter(t => t.id !== id);
607
  saveTodos();
608
  renderTodos();
 
609
  }
610
 
611
+ function startEdit(id) {
612
+ if (editingId && editingId !== id) {
613
+ finishEdit(editingId);
614
+ }
615
+ editingId = id;
616
  const todo = todos.find(t => t.id === id);
617
  if (todo) {
618
+ const textElement = document.querySelector(`[data-id="${id}"] .todo-text`);
619
+ textElement.contentEditable = true;
620
+ textElement.focus();
621
+
622
+ // Select all text
623
+ const range = document.createRange();
624
+ range.selectNodeContents(textElement);
625
+ const selection = window.getSelection();
626
+ selection.removeAllRanges();
627
+ selection.addRange(range);
628
+
629
+ textElement.addEventListener('blur', () => finishEdit(id));
630
+ textElement.addEventListener('keypress', (e) => {
631
+ if (e.key === 'Enter') {
632
+ e.preventDefault();
633
+ textElement.blur();
634
+ }
635
+ });
636
+ }
637
+ }
638
+
639
+ function finishEdit(id) {
640
+ const textElement = document.querySelector(`[data-id="${id}"] .todo-text`);
641
+ if (textElement) {
642
+ const newText = textElement.textContent.trim();
643
+ const todo = todos.find(t => t.id === id);
644
+ if (todo && newText !== '') {
645
+ todo.text = newText;
646
  saveTodos();
 
647
  }
648
+ textElement.contentEditable = false;
649
  }
650
+ editingId = null;
651
  }
652
 
653
  function filterTodos(filter) {
654
  currentFilter = filter;
655
 
656
+ // Update active tab
657
+ document.querySelectorAll('.filter-tab').forEach(tab => {
658
+ tab.classList.remove('active');
659
  });
660
  event.target.classList.add('active');
661
 
662
  renderTodos();
663
  }
664
 
665
+ function clearCompleted() {
666
+ todos = todos.filter(t => !t.completed);
667
+ saveTodos();
668
  renderTodos();
669
  }
670
 
671
  function getFilteredTodos() {
672
+ switch (currentFilter) {
673
+ case 'active':
674
+ return todos.filter(t => !t.completed);
675
+ case 'completed':
676
+ return todos.filter(t => t.completed);
677
+ default:
678
+ return todos;
 
 
 
 
 
 
 
 
679
  }
 
 
680
  }
681
 
682
  function renderTodos() {
683
+ const todoList = document.getElementById('todoList');
684
  const filteredTodos = getFilteredTodos();
685
 
686
  if (filteredTodos.length === 0) {
687
+ todoList.innerHTML = `
688
  <div class="empty-state">
689
+ <div class="empty-icon">${currentFilter === 'completed' ? 'πŸŽ‰' : 'πŸ“'}</div>
690
+ <div class="empty-text">${currentFilter === 'completed' ? 'All done!' : 'No tasks yet'}</div>
691
+ <div class="empty-subtext">${currentFilter === 'completed' ? 'Great job completing everything!' : 'Add your first task to get started'}</div>
 
692
  </div>
693
  `;
694
  return;
695
  }
696
+
697
+ todoList.innerHTML = filteredTodos.map(todo => `
698
+ <div class="todo-item" data-id="${todo.id}">
699
+ <div class="todo-checkbox ${todo.completed ? 'checked' : ''}" onclick="toggleTodo('${todo.id}')"></div>
700
+ <div class="todo-text ${todo.completed ? 'completed' : ''}" onclick="startEdit('${todo.id}')">${todo.text}</div>
701
+ <div class="todo-actions">
702
+ <button class="action-btn" onclick="deleteTodo('${todo.id}')">πŸ—‘οΈ</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
703
  </div>
704
+ </div>
705
+ `).join('');
706
+
707
+ updateActiveCount();
708
+ }
709
+
710
+ function updateActiveCount() {
711
+ const activeCount = todos.filter(t => !t.completed).length;
712
+ document.getElementById('activeCount').textContent = activeCount;
713
  }
714
 
715
  function updateStats() {
716
  const total = todos.length;
717
  const completed = todos.filter(t => t.completed).length;
718
+ const rate = total > 0 ? Math.round((completed / total) * 100) : 0;
 
 
719
 
720
  document.getElementById('totalTasks').textContent = total;
721
  document.getElementById('completedTasks').textContent = completed;
722
+ document.getElementById('completionRate').textContent = rate + '%';
 
 
 
 
 
 
723
  }
724
 
725
+ function toggleTheme() {
726
+ const body = document.body;
727
+ const themeToggle = document.querySelector('.theme-toggle');
728
+
729
+ if (body.style.filter === 'invert(1) hue-rotate(180deg)') {
730
+ body.style.filter = '';
731
+ themeToggle.textContent = 'πŸŒ™';
732
+ } else {
733
+ body.style.filter = 'invert(1) hue-rotate(180deg)';
734
+ themeToggle.textContent = 'β˜€οΈ';
735
  }
736
  }
737
 
738
+ // Initialize
739
+ renderTodos();
740
+ updateStats();
741
+ document.getElementById('todoInput').focus();
 
 
 
 
 
 
742
  </script>
743
  </body>
744
  </html>