akhaliq HF Staff commited on
Commit
ec3b1f0
·
verified ·
1 Parent(s): d75e1e7

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +1098 -19
index.html CHANGED
@@ -1,19 +1,1098 @@
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
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>TaskFlow - Modern Todo App</title>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ * {
11
+ margin: 0;
12
+ padding: 0;
13
+ box-sizing: border-box;
14
+ }
15
+
16
+ :root {
17
+ --primary: #6366f1;
18
+ --primary-dark: #4f46e5;
19
+ --primary-light: #818cf8;
20
+ --secondary: #22d3ee;
21
+ --success: #10b981;
22
+ --warning: #f59e0b;
23
+ --danger: #ef4444;
24
+ --dark: #1e293b;
25
+ --light: #f1f5f9;
26
+ --white: #ffffff;
27
+ --gray: #64748b;
28
+ --gray-light: #e2e8f0;
29
+ --shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
30
+ --shadow-lg: 0 20px 40px rgba(0, 0, 0, 0.15);
31
+ --radius: 12px;
32
+ --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
33
+ }
34
+
35
+ body {
36
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
37
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
38
+ min-height: 100vh;
39
+ display: flex;
40
+ justify-content: center;
41
+ align-items: center;
42
+ padding: 20px;
43
+ position: relative;
44
+ overflow-x: hidden;
45
+ }
46
+
47
+ body::before {
48
+ content: '';
49
+ position: absolute;
50
+ top: 0;
51
+ left: 0;
52
+ right: 0;
53
+ bottom: 0;
54
+ background:
55
+ radial-gradient(circle at 20% 80%, rgba(99, 102, 241, 0.3) 0%, transparent 50%),
56
+ radial-gradient(circle at 80% 20%, rgba(34, 211, 238, 0.3) 0%, transparent 50%),
57
+ radial-gradient(circle at 40% 40%, rgba(168, 85, 247, 0.2) 0%, transparent 50%);
58
+ pointer-events: none;
59
+ }
60
+
61
+ .container {
62
+ width: 100%;
63
+ max-width: 900px;
64
+ background: rgba(255, 255, 255, 0.95);
65
+ backdrop-filter: blur(20px);
66
+ border-radius: 24px;
67
+ box-shadow: var(--shadow-lg);
68
+ overflow: hidden;
69
+ position: relative;
70
+ z-index: 1;
71
+ animation: slideUp 0.5s ease-out;
72
+ }
73
+
74
+ @keyframes slideUp {
75
+ from {
76
+ opacity: 0;
77
+ transform: translateY(30px);
78
+ }
79
+
80
+ to {
81
+ opacity: 1;
82
+ transform: translateY(0);
83
+ }
84
+ }
85
+
86
+ header {
87
+ background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
88
+ color: white;
89
+ padding: 30px;
90
+ position: relative;
91
+ overflow: hidden;
92
+ }
93
+
94
+ header::after {
95
+ content: '';
96
+ position: absolute;
97
+ top: -50%;
98
+ right: -10%;
99
+ width: 300px;
100
+ height: 300px;
101
+ background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, transparent 70%);
102
+ border-radius: 50%;
103
+ }
104
+
105
+ .header-content {
106
+ position: relative;
107
+ z-index: 1;
108
+ }
109
+
110
+ .header-top {
111
+ display: flex;
112
+ justify-content: space-between;
113
+ align-items: center;
114
+ margin-bottom: 20px;
115
+ }
116
+
117
+ h1 {
118
+ font-size: 2.5rem;
119
+ font-weight: 700;
120
+ display: flex;
121
+ align-items: center;
122
+ gap: 12px;
123
+ }
124
+
125
+ h1 i {
126
+ font-size: 2rem;
127
+ opacity: 0.9;
128
+ }
129
+
130
+ .brand-link {
131
+ color: white;
132
+ text-decoration: none;
133
+ font-size: 0.85rem;
134
+ opacity: 0.8;
135
+ transition: opacity 0.3s;
136
+ position: absolute;
137
+ bottom: 10px;
138
+ right: 30px;
139
+ }
140
+
141
+ .brand-link:hover {
142
+ opacity: 1;
143
+ }
144
+
145
+ .stats {
146
+ display: grid;
147
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
148
+ gap: 20px;
149
+ margin-top: 20px;
150
+ }
151
+
152
+ .stat-card {
153
+ background: rgba(255, 255, 255, 0.1);
154
+ backdrop-filter: blur(10px);
155
+ padding: 15px;
156
+ border-radius: var(--radius);
157
+ text-align: center;
158
+ transition: var(--transition);
159
+ }
160
+
161
+ .stat-card:hover {
162
+ background: rgba(255, 255, 255, 0.15);
163
+ transform: translateY(-2px);
164
+ }
165
+
166
+ .stat-number {
167
+ font-size: 2rem;
168
+ font-weight: 700;
169
+ margin-bottom: 5px;
170
+ }
171
+
172
+ .stat-label {
173
+ font-size: 0.85rem;
174
+ opacity: 0.9;
175
+ }
176
+
177
+ .progress-bar {
178
+ width: 100%;
179
+ height: 8px;
180
+ background: rgba(255, 255, 255, 0.2);
181
+ border-radius: 4px;
182
+ overflow: hidden;
183
+ margin-top: 10px;
184
+ }
185
+
186
+ .progress-fill {
187
+ height: 100%;
188
+ background: linear-gradient(90deg, var(--success), var(--secondary));
189
+ border-radius: 4px;
190
+ transition: width 0.5s ease;
191
+ }
192
+
193
+ .main-content {
194
+ padding: 30px;
195
+ }
196
+
197
+ .input-section {
198
+ background: var(--light);
199
+ padding: 25px;
200
+ border-radius: var(--radius);
201
+ margin-bottom: 30px;
202
+ }
203
+
204
+ .input-group {
205
+ display: flex;
206
+ gap: 15px;
207
+ margin-bottom: 15px;
208
+ flex-wrap: wrap;
209
+ }
210
+
211
+ .task-input {
212
+ flex: 1;
213
+ min-width: 200px;
214
+ padding: 12px 20px;
215
+ border: 2px solid transparent;
216
+ border-radius: var(--radius);
217
+ font-size: 1rem;
218
+ background: white;
219
+ transition: var(--transition);
220
+ }
221
+
222
+ .task-input:focus {
223
+ outline: none;
224
+ border-color: var(--primary);
225
+ box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
226
+ }
227
+
228
+ .input-meta {
229
+ display: flex;
230
+ gap: 15px;
231
+ flex-wrap: wrap;
232
+ }
233
+
234
+ .meta-input {
235
+ padding: 10px 15px;
236
+ border: 2px solid var(--gray-light);
237
+ border-radius: var(--radius);
238
+ background: white;
239
+ font-size: 0.9rem;
240
+ transition: var(--transition);
241
+ }
242
+
243
+ .meta-input:focus {
244
+ outline: none;
245
+ border-color: var(--primary);
246
+ }
247
+
248
+ .btn {
249
+ padding: 12px 24px;
250
+ border: none;
251
+ border-radius: var(--radius);
252
+ font-size: 1rem;
253
+ font-weight: 600;
254
+ cursor: pointer;
255
+ transition: var(--transition);
256
+ display: inline-flex;
257
+ align-items: center;
258
+ gap: 8px;
259
+ }
260
+
261
+ .btn-primary {
262
+ background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
263
+ color: white;
264
+ }
265
+
266
+ .btn-primary:hover {
267
+ transform: translateY(-2px);
268
+ box-shadow: 0 10px 20px rgba(99, 102, 241, 0.3);
269
+ }
270
+
271
+ .btn-secondary {
272
+ background: var(--gray-light);
273
+ color: var(--dark);
274
+ }
275
+
276
+ .btn-secondary:hover {
277
+ background: var(--gray);
278
+ color: white;
279
+ }
280
+
281
+ .controls {
282
+ display: flex;
283
+ justify-content: space-between;
284
+ align-items: center;
285
+ margin-bottom: 20px;
286
+ flex-wrap: wrap;
287
+ gap: 15px;
288
+ }
289
+
290
+ .filter-tabs {
291
+ display: flex;
292
+ gap: 10px;
293
+ background: var(--light);
294
+ padding: 5px;
295
+ border-radius: var(--radius);
296
+ }
297
+
298
+ .filter-tab {
299
+ padding: 8px 16px;
300
+ background: transparent;
301
+ border: none;
302
+ border-radius: 8px;
303
+ cursor: pointer;
304
+ font-weight: 500;
305
+ color: var(--gray);
306
+ transition: var(--transition);
307
+ }
308
+
309
+ .filter-tab.active {
310
+ background: white;
311
+ color: var(--primary);
312
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
313
+ }
314
+
315
+ .search-box {
316
+ position: relative;
317
+ min-width: 250px;
318
+ }
319
+
320
+ .search-input {
321
+ width: 100%;
322
+ padding: 10px 40px 10px 15px;
323
+ border: 2px solid var(--gray-light);
324
+ border-radius: var(--radius);
325
+ font-size: 0.9rem;
326
+ transition: var(--transition);
327
+ }
328
+
329
+ .search-input:focus {
330
+ outline: none;
331
+ border-color: var(--primary);
332
+ }
333
+
334
+ .search-icon {
335
+ position: absolute;
336
+ right: 15px;
337
+ top: 50%;
338
+ transform: translateY(-50%);
339
+ color: var(--gray);
340
+ }
341
+
342
+ .todo-list {
343
+ display: flex;
344
+ flex-direction: column;
345
+ gap: 12px;
346
+ max-height: 500px;
347
+ overflow-y: auto;
348
+ padding-right: 10px;
349
+ }
350
+
351
+ .todo-list::-webkit-scrollbar {
352
+ width: 8px;
353
+ }
354
+
355
+ .todo-list::-webkit-scrollbar-track {
356
+ background: var(--light);
357
+ border-radius: 4px;
358
+ }
359
+
360
+ .todo-list::-webkit-scrollbar-thumb {
361
+ background: var(--gray);
362
+ border-radius: 4px;
363
+ }
364
+
365
+ .todo-item {
366
+ background: white;
367
+ border: 2px solid var(--gray-light);
368
+ border-radius: var(--radius);
369
+ padding: 20px;
370
+ display: flex;
371
+ align-items: center;
372
+ gap: 15px;
373
+ transition: var(--transition);
374
+ cursor: move;
375
+ animation: fadeIn 0.3s ease;
376
+ }
377
+
378
+ @keyframes fadeIn {
379
+ from {
380
+ opacity: 0;
381
+ transform: translateX(-20px);
382
+ }
383
+
384
+ to {
385
+ opacity: 1;
386
+ transform: translateX(0);
387
+ }
388
+ }
389
+
390
+ .todo-item:hover {
391
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
392
+ transform: translateY(-2px);
393
+ }
394
+
395
+ .todo-item.dragging {
396
+ opacity: 0.5;
397
+ transform: rotate(2deg);
398
+ }
399
+
400
+ .todo-item.completed {
401
+ opacity: 0.7;
402
+ background: var(--light);
403
+ }
404
+
405
+ .todo-item.completed .todo-text {
406
+ text-decoration: line-through;
407
+ color: var(--gray);
408
+ }
409
+
410
+ .checkbox {
411
+ width: 24px;
412
+ height: 24px;
413
+ border: 2px solid var(--primary);
414
+ border-radius: 6px;
415
+ cursor: pointer;
416
+ display: flex;
417
+ align-items: center;
418
+ justify-content: center;
419
+ transition: var(--transition);
420
+ flex-shrink: 0;
421
+ }
422
+
423
+ .checkbox:hover {
424
+ background: var(--primary-light);
425
+ border-color: var(--primary-light);
426
+ }
427
+
428
+ .checkbox.checked {
429
+ background: var(--primary);
430
+ border-color: var(--primary);
431
+ }
432
+
433
+ .checkbox.checked::after {
434
+ content: '✓';
435
+ color: white;
436
+ font-weight: bold;
437
+ }
438
+
439
+ .todo-content {
440
+ flex: 1;
441
+ }
442
+
443
+ .todo-text {
444
+ font-size: 1rem;
445
+ color: var(--dark);
446
+ margin-bottom: 5px;
447
+ word-break: break-word;
448
+ }
449
+
450
+ .todo-meta {
451
+ display: flex;
452
+ gap: 10px;
453
+ flex-wrap: wrap;
454
+ margin-top: 8px;
455
+ }
456
+
457
+ .todo-badge {
458
+ padding: 3px 8px;
459
+ border-radius: 4px;
460
+ font-size: 0.75rem;
461
+ font-weight: 600;
462
+ }
463
+
464
+ .priority-high {
465
+ background: rgba(239, 68, 68, 0.1);
466
+ color: var(--danger);
467
+ }
468
+
469
+ .priority-medium {
470
+ background: rgba(245, 158, 11, 0.1);
471
+ color: var(--warning);
472
+ }
473
+
474
+ .priority-low {
475
+ background: rgba(16, 185, 129, 0.1);
476
+ color: var(--success);
477
+ }
478
+
479
+ .category-badge {
480
+ background: rgba(99, 102, 241, 0.1);
481
+ color: var(--primary);
482
+ }
483
+
484
+ .due-date {
485
+ background: rgba(100, 116, 139, 0.1);
486
+ color: var(--gray);
487
+ }
488
+
489
+ .todo-actions {
490
+ display: flex;
491
+ gap: 8px;
492
+ }
493
+
494
+ .action-btn {
495
+ width: 32px;
496
+ height: 32px;
497
+ border: none;
498
+ background: var(--light);
499
+ border-radius: 8px;
500
+ cursor: pointer;
501
+ display: flex;
502
+ align-items: center;
503
+ justify-content: center;
504
+ transition: var(--transition);
505
+ color: var(--gray);
506
+ }
507
+
508
+ .action-btn:hover {
509
+ background: var(--primary);
510
+ color: white;
511
+ transform: scale(1.1);
512
+ }
513
+
514
+ .action-btn.delete:hover {
515
+ background: var(--danger);
516
+ }
517
+
518
+ .empty-state {
519
+ text-align: center;
520
+ padding: 60px 20px;
521
+ color: var(--gray);
522
+ }
523
+
524
+ .empty-state i {
525
+ font-size: 4rem;
526
+ margin-bottom: 20px;
527
+ opacity: 0.3;
528
+ }
529
+
530
+ .empty-state h3 {
531
+ font-size: 1.5rem;
532
+ margin-bottom: 10px;
533
+ }
534
+
535
+ .clear-completed {
536
+ display: flex;
537
+ justify-content: space-between;
538
+ align-items: center;
539
+ margin-top: 20px;
540
+ padding-top: 20px;
541
+ border-top: 2px solid var(--gray-light);
542
+ }
543
+
544
+ .toast {
545
+ position: fixed;
546
+ bottom: 30px;
547
+ right: 30px;
548
+ background: var(--dark);
549
+ color: white;
550
+ padding: 15px 20px;
551
+ border-radius: var(--radius);
552
+ box-shadow: var(--shadow-lg);
553
+ display: flex;
554
+ align-items: center;
555
+ gap: 10px;
556
+ transform: translateX(400px);
557
+ transition: transform 0.3s ease;
558
+ z-index: 1000;
559
+ }
560
+
561
+ .toast.show {
562
+ transform: translateX(0);
563
+ }
564
+
565
+ @media (max-width: 768px) {
566
+ h1 {
567
+ font-size: 1.8rem;
568
+ }
569
+
570
+ .stats {
571
+ grid-template-columns: repeat(2, 1fr);
572
+ }
573
+
574
+ .controls {
575
+ flex-direction: column;
576
+ align-items: stretch;
577
+ }
578
+
579
+ .search-box {
580
+ width: 100%;
581
+ }
582
+
583
+ .filter-tabs {
584
+ justify-content: center;
585
+ }
586
+
587
+ .todo-item {
588
+ padding: 15px;
589
+ }
590
+
591
+ .input-meta {
592
+ flex-direction: column;
593
+ }
594
+
595
+ .meta-input {
596
+ width: 100%;
597
+ }
598
+ }
599
+
600
+ @media (max-width: 480px) {
601
+ .container {
602
+ border-radius: 0;
603
+ min-height: 100vh;
604
+ }
605
+
606
+ body {
607
+ padding: 0;
608
+ }
609
+
610
+ header {
611
+ padding: 20px;
612
+ }
613
+
614
+ .main-content {
615
+ padding: 20px;
616
+ }
617
+
618
+ h1 {
619
+ font-size: 1.5rem;
620
+ }
621
+ }
622
+ </style>
623
+ </head>
624
+
625
+ <body>
626
+ <div class="container">
627
+ <header>
628
+ <div class="header-content">
629
+ <div class="header-top">
630
+ <h1>
631
+ <i class="fas fa-tasks"></i>
632
+ TaskFlow
633
+ </h1>
634
+ </div>
635
+ <div class="stats">
636
+ <div class="stat-card">
637
+ <div class="stat-number" id="totalTasks">0</div>
638
+ <div class="stat-label">Total Tasks</div>
639
+ </div>
640
+ <div class="stat-card">
641
+ <div class="stat-number" id="completedTasks">0</div>
642
+ <div class="stat-label">Completed</div>
643
+ </div>
644
+ <div class="stat-card">
645
+ <div class="stat-number" id="activeTasks">0</div>
646
+ <div class="stat-label">Active</div>
647
+ </div>
648
+ <div class="stat-card">
649
+ <div class="stat-number" id="completionRate">0%</div>
650
+ <div class="stat-label">Completion</div>
651
+ <div class="progress-bar">
652
+ <div class="progress-fill" id="progressFill"></div>
653
+ </div>
654
+ </div>
655
+ </div>
656
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="brand-link">
657
+ Built with anycoder
658
+ </a>
659
+ </div>
660
+ </header>
661
+
662
+ <main class="main-content">
663
+ <section class="input-section">
664
+ <div class="input-group">
665
+ <input type="text"
666
+ class="task-input"
667
+ id="taskInput"
668
+ placeholder="What needs to be done today?..."
669
+ maxlength="200">
670
+ <button class="btn btn-primary" id="addTaskBtn">
671
+ <i class="fas fa-plus"></i>
672
+ Add Task
673
+ </button>
674
+ </div>
675
+ <div class="input-meta">
676
+ <select class="meta-input" id="prioritySelect">
677
+ <option value="low">Low Priority</option>
678
+ <option value="medium" selected>Medium Priority</option>
679
+ <option value="high">High Priority</option>
680
+ </select>
681
+ <select class="meta-input" id="categorySelect">
682
+ <option value="personal">Personal</option>
683
+ <option value="work">Work</option>
684
+ <option value="shopping">Shopping</option>
685
+ <option value="health">Health</option>
686
+ <option value="education">Education</option>
687
+ <option value="other">Other</option>
688
+ </select>
689
+ <input type="date"
690
+ class="meta-input"
691
+ id="dueDateInput">
692
+ </div>
693
+ </section>
694
+
695
+ <section class="controls">
696
+ <div class="filter-tabs">
697
+ <button class="filter-tab active" data-filter="all">
698
+ All Tasks
699
+ </button>
700
+ <button class="filter-tab" data-filter="active">
701
+ Active
702
+ </button>
703
+ <button class="filter-tab" data-filter="completed">
704
+ Completed
705
+ </button>
706
+ </div>
707
+ <div class="search-box">
708
+ <input type="text"
709
+ class="search-input"
710
+ id="searchInput"
711
+ placeholder="Search tasks...">
712
+ <i class="fas fa-search search-icon"></i>
713
+ </div>
714
+ </section>
715
+
716
+ <section class="todo-list" id="todoList">
717
+ <!-- Tasks will be dynamically added here -->
718
+ </section>
719
+
720
+ <div class="empty-state" id="emptyState" style="display: none;">
721
+ <i class="fas fa-clipboard-list"></i>
722
+ <h3>No tasks yet!</h3>
723
+ <p>Start by adding your first task above.</p>
724
+ </div>
725
+
726
+ <div class="clear-completed" id="clearSection" style="display: none;">
727
+ <span id="completedCount">0 completed tasks</span>
728
+ <button class="btn btn-secondary" id="clearCompletedBtn">
729
+ <i class="fas fa-trash"></i>
730
+ Clear Completed
731
+ </button>
732
+ </div>
733
+ </main>
734
+ </div>
735
+
736
+ <div class="toast" id="toast">
737
+ <i class="fas fa-check-circle"></i>
738
+ <span id="toastMessage">Task added successfully!</span>
739
+ </div>
740
+
741
+ <script>
742
+ class TodoApp {
743
+ constructor() {
744
+ this.todos = JSON.parse(localStorage.getItem('todos')) || [];
745
+ this.currentFilter = 'all';
746
+ this.searchTerm = '';
747
+ this.draggedItem = null;
748
+ this.init();
749
+ }
750
+
751
+ init() {
752
+ this.setupEventListeners();
753
+ this.render();
754
+ this.updateStats();
755
+ this.setMinDate();
756
+ }
757
+
758
+ setMinDate() {
759
+ const today = new Date().toISOString().split('T')[0];
760
+ document.getElementById('dueDateInput').setAttribute('min', today);
761
+ }
762
+
763
+ setupEventListeners() {
764
+ // Add task
765
+ document.getElementById('addTaskBtn').addEventListener('click', () => this.addTask());
766
+ document.getElementById('taskInput').addEventListener('keypress', (e) => {
767
+ if (e.key === 'Enter') this.addTask();
768
+ });
769
+
770
+ // Filter tabs
771
+ document.querySelectorAll('.filter-tab').forEach(tab => {
772
+ tab.addEventListener('click', (e) => {
773
+ document.querySelectorAll('.filter-tab').forEach(t => t.classList.remove('active'));
774
+ e.target.classList.add('active');
775
+ this.currentFilter = e.target.dataset.filter;
776
+ this.render();
777
+ });
778
+ });
779
+
780
+ // Search
781
+ document.getElementById('searchInput').addEventListener('input', (e) => {
782
+ this.searchTerm = e.target.value.toLowerCase();
783
+ this.render();
784
+ });
785
+
786
+ // Clear completed
787
+ document.getElementById('clearCompletedBtn').addEventListener('click', () => {
788
+ this.clearCompleted();
789
+ });
790
+ }
791
+
792
+ addTask() {
793
+ const input = document.getElementById('taskInput');
794
+ const text = input.value.trim();
795
+
796
+ if (!text) {
797
+ this.showToast('Please enter a task!', 'error');
798
+ return;
799
+ }
800
+
801
+ const todo = {
802
+ id: Date.now(),
803
+ text: text,
804
+ completed: false,
805
+ priority: document.getElementById('prioritySelect').value,
806
+ category: document.getElementById('categorySelect').value,
807
+ dueDate: document.getElementById('dueDateInput').value,
808
+ createdAt: new Date().toISOString()
809
+ };
810
+
811
+ this.todos.unshift(todo);
812
+ this.saveTodos();
813
+ this.render();
814
+ this.updateStats();
815
+
816
+ // Reset form
817
+ input.value = '';
818
+ document.getElementById('dueDateInput').value = '';
819
+ document.getElementById('prioritySelect').value = 'medium';
820
+ document.getElementById('categorySelect').value = 'personal';
821
+
822
+ this.showToast('Task added successfully!');
823
+ }
824
+
825
+ toggleTask(id) {
826
+ const todo = this.todos.find(t => t.id === id);
827
+ if (todo) {
828
+ todo.completed = !todo.completed;
829
+ this.saveTodos();
830
+ this.render();
831
+ this.updateStats();
832
+ this.showToast(todo.completed ? 'Task completed!' : 'Task marked as active');
833
+ }
834
+ }
835
+
836
+ deleteTask(id) {
837
+ this.todos = this.todos.filter(t => t.id !== id);
838
+ this.saveTodos();
839
+ this.render();
840
+ this.updateStats();
841
+ this.showToast('Task deleted!');
842
+ }
843
+
844
+ editTask(id) {
845
+ const todo = this.todos.find(t => t.id === id);
846
+ if (todo) {
847
+ const newText = prompt('Edit task:', todo.text);
848
+ if (newText && newText.trim()) {
849
+ todo.text = newText.trim();
850
+ this.saveTodos();
851
+ this.render();
852
+ this.showToast('Task updated!');
853
+ }
854
+ }
855
+ }
856
+
857
+ clearCompleted() {
858
+ const completedCount = this.todos.filter(t => t.completed).length;
859
+ if (completedCount === 0) {
860
+ this.showToast('No completed tasks to clear');
861
+ return;
862
+ }
863
+
864
+ if (confirm(`Clear ${completedCount} completed task(s)?`)) {
865
+ this.todos = this.todos.filter(t => !t.completed);
866
+ this.saveTodos();
867
+ this.render();
868
+ this.updateStats();
869
+ this.showToast(`Cleared ${completedCount} completed task(s)!`);
870
+ }
871
+ }
872
+
873
+ getFilteredTodos() {
874
+ let filtered = this.todos;
875
+
876
+ // Apply filter
877
+ if (this.currentFilter === 'active') {
878
+ filtered = filtered.filter(t => !t.completed);
879
+ } else if (this.currentFilter === 'completed') {
880
+ filtered = filtered.filter(t => t.completed);
881
+ }
882
+
883
+ // Apply search
884
+ if (this.searchTerm) {
885
+ filtered = filtered.filter(t =>
886
+ t.text.toLowerCase().includes(this.searchTerm) ||
887
+ t.category.toLowerCase().includes(this.searchTerm)
888
+ );
889
+ }
890
+
891
+ return filtered;
892
+ }
893
+
894
+ render() {
895
+ const todoList = document.getElementById('todoList');
896
+ const emptyState = document.getElementById('emptyState');
897
+ const clearSection = document.getElementById('clearSection');
898
+ const filteredTodos = this.getFilteredTodos();
899
+
900
+ if (this.todos.length === 0) {
901
+ todoList.style.display = 'none';
902
+ emptyState.style.display = 'block';
903
+ clearSection.style.display = 'none';
904
+ return;
905
+ }
906
+
907
+ todoList.style.display = 'flex';
908
+ emptyState.style.display = 'none';
909
+
910
+ if (this.todos.some(t => t.completed)) {
911
+ clearSection.style.display = 'flex';
912
+ const completedCount = this.todos.filter(t => t.completed).length;
913
+ document.getElementById('completedCount').textContent =
914
+ `${completedCount} completed task${completedCount !== 1 ? 's' : ''}`;
915
+ } else {
916
+ clearSection.style.display = 'none';
917
+ }
918
+
919
+ if (filteredTodos.length === 0) {
920
+ todoList.innerHTML = `
921
+ <div class="empty-state">
922
+ <i class="fas fa-search"></i>
923
+ <h3>No tasks found</h3>
924
+ <p>Try adjusting your search or filter</p>
925
+ </div>
926
+ `;
927
+ return;
928
+ }
929
+
930
+ todoList.innerHTML = filteredTodos.map(todo => this.createTodoHTML(todo)).join('');
931
+
932
+ // Add event listeners to new elements
933
+ this.attachTodoEventListeners();
934
+ this.setupDragAndDrop();
935
+ }
936
+
937
+ createTodoHTML(todo) {
938
+ const priorityClass = `priority-${todo.priority}`;
939
+ const dueDateText = todo.dueDate ? this.formatDate(todo.dueDate) : '';
940
+ const isOverdue = todo.dueDate && new Date(todo.dueDate) < new Date() && !todo.completed;
941
+
942
+ return `
943
+ <div class="todo-item ${todo.completed ? 'completed' : ''}"
944
+ data-id="${todo.id}"
945
+ draggable="true">
946
+ <div class="checkbox ${todo.completed ? 'checked' : ''}"
947
+ onclick="app.toggleTask(${todo.id})"></div>
948
+ <div class="todo-content">
949
+ <div class="todo-text">${this.escapeHtml(todo.text)}</div>
950
+ <div class="todo-meta">
951
+ <span class="todo-badge ${priorityClass}">
952
+ ${todo.priority.charAt(0).toUpperCase() + todo.priority.slice(1)}
953
+ </span>
954
+ <span class="todo-badge category-badge">
955
+ ${todo.category.charAt(0).toUpperCase() + todo.category.slice(1)}
956
+ </span>
957
+ ${dueDateText ? `
958
+ <span class="todo-badge due-date ${isOverdue ? 'priority-high' : ''}">
959
+ <i class="far fa-calendar"></i> ${dueDateText}
960
+ </span>
961
+ ` : ''}
962
+ </div>
963
+ </div>
964
+ <div class="todo-actions">
965
+ <button class="action-btn" onclick="app.editTask(${todo.id})">
966
+ <i class="fas fa-edit"></i>
967
+ </button>
968
+ <button class="action-btn delete" onclick="app.deleteTask(${todo.id})">
969
+ <i class="fas fa-trash"></i>
970
+ </button>
971
+ </div>
972
+ </div>
973
+ `;
974
+ }
975
+
976
+ formatDate(dateString) {
977
+ const date = new Date(dateString);
978
+ const today = new Date();
979
+ const tomorrow = new Date(today);
980
+ tomorrow.setDate(tomorrow.getDate() + 1);
981
+
982
+ if (date.toDateString() === today.toDateString()) {
983
+ return 'Today';
984
+ } else if (date.toDateString() === tomorrow.toDateString()) {
985
+ return 'Tomorrow';
986
+ } else {
987
+ return date.toLocaleDateString('en-US', {
988
+ month: 'short',
989
+ day: 'numeric'
990
+ });
991
+ }
992
+ }
993
+
994
+ attachTodoEventListeners() {
995
+ // Already handled by inline onclick handlers
996
+ }
997
+
998
+ setupDragAndDrop() {
999
+ const items = document.querySelectorAll('.todo-item');
1000
+
1001
+ items.forEach(item => {
1002
+ item.addEventListener('dragstart', (e) => {
1003
+ this.draggedItem = item;
1004
+ item.classList.add('dragging');
1005
+ });
1006
+
1007
+ item.addEventListener('dragend', (e) => {
1008
+ item.classList.remove('dragging');
1009
+ });
1010
+
1011
+ item.addEventListener('dragover', (e) => {
1012
+ e.preventDefault();
1013
+ const afterElement = this.getDragAfterElement(document.getElementById('todoList'), e.clientY);
1014
+ if (afterElement == null) {
1015
+ document.getElementById('todoList').appendChild(this.draggedItem);
1016
+ } else {
1017
+ document.getElementById('todoList').insertBefore(this.draggedItem, afterElement);
1018
+ }
1019
+ });
1020
+
1021
+ item.addEventListener('drop', (e) => {
1022
+ e.preventDefault();
1023
+ this.reorderTodos();
1024
+ });
1025
+ });
1026
+ }
1027
+
1028
+ getDragAfterElement(container, y) {
1029
+ const draggableElements = [...container.querySelectorAll('.todo-item:not(.dragging)')];
1030
+
1031
+ return draggableElements.reduce((closest, child) => {
1032
+ const box = child.getBoundingClientRect();
1033
+ const offset = y - box.top - box.height / 2;
1034
+
1035
+ if (offset < 0 && offset > closest.offset) {
1036
+ return { offset: offset, element: child };
1037
+ } else {
1038
+ return closest;
1039
+ }
1040
+ }, { offset: Number.NEGATIVE_INFINITY }).element;
1041
+ }
1042
+
1043
+ reorderTodos() {
1044
+ const items = document.querySelectorAll('.todo-item');
1045
+ const newOrder = [];
1046
+
1047
+ items.forEach(item => {
1048
+ const id = parseInt(item.dataset.id);
1049
+ const todo = this.todos.find(t => t.id === id);
1050
+ if (todo) newOrder.push(todo);
1051
+ });
1052
+
1053
+ this.todos = newOrder;
1054
+ this.saveTodos();
1055
+ }
1056
+
1057
+ updateStats() {
1058
+ const total = this.todos.length;
1059
+ const completed = this.todos.filter(t => t.completed).length;
1060
+ const active = total - completed;
1061
+ const rate = total > 0 ? Math.round((completed / total) * 100) : 0;
1062
+
1063
+ document.getElementById('totalTasks').textContent = total;
1064
+ document.getElementById('completedTasks').textContent = completed;
1065
+ document.getElementById('activeTasks').textContent = active;
1066
+ document.getElementById('completionRate').textContent = `${rate}%`;
1067
+ document.getElementById('progressFill').style.width = `${rate}%`;
1068
+ }
1069
+
1070
+ saveTodos() {
1071
+ localStorage.setItem('todos', JSON.stringify(this.todos));
1072
+ }
1073
+
1074
+ showToast(message, type = 'success') {
1075
+ const toast = document.getElementById('toast');
1076
+ const toastMessage = document.getElementById('toastMessage');
1077
+
1078
+ toastMessage.textContent = message;
1079
+ toast.classList.add('show');
1080
+
1081
+ setTimeout(() => {
1082
+ toast.classList.remove('show');
1083
+ }, 3000);
1084
+ }
1085
+
1086
+ escapeHtml(text) {
1087
+ const div = document.createElement('div');
1088
+ div.textContent = text;
1089
+ return div.innerHTML;
1090
+ }
1091
+ }
1092
+
1093
+ // Initialize the app
1094
+ const app = new TodoApp();
1095
+ </script>
1096
+ </body>
1097
+
1098
+ </html>