iProsto commited on
Commit
8104128
·
verified ·
1 Parent(s): c384632

Create a todo list site. Minimalistic, easy to use and user-friendly, cute. Opportunities: add a new task, remove any task, mark as done, mark as undone. Use localstorage for tasks. Sort undone tasks to the top of the list

Browse files
Files changed (4) hide show
  1. README.md +7 -4
  2. index.html +64 -19
  3. script.js +128 -0
  4. style.css +47 -18
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Cute Task Tracker
3
- emoji: 🐠
4
  colorFrom: blue
5
- colorTo: yellow
 
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
  ---
2
+ title: Cute Task Tracker 🌈
 
3
  colorFrom: blue
4
+ colorTo: green
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://huggingface.co/deepsite).
index.html CHANGED
@@ -1,19 +1,64 @@
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>Cute Task Tracker</title>
7
+ <link rel="stylesheet" href="style.css">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://unpkg.com/feather-icons"></script>
10
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
11
+ </head>
12
+ <body class="bg-pink-50 min-h-screen font-sans">
13
+ <div class="container mx-auto px-4 py-8 max-w-md">
14
+ <header class="text-center mb-10">
15
+ <h1 class="text-3xl font-bold text-pink-600 mb-2">Cute Task Tracker 🌈</h1>
16
+ <p class="text-pink-400">Your adorable companion for getting things done!</p>
17
+ </header>
18
+
19
+ <main>
20
+ <div class="bg-white rounded-2xl shadow-lg p-6 mb-6">
21
+ <form id="task-form" class="flex gap-2">
22
+ <input
23
+ type="text"
24
+ id="new-task"
25
+ placeholder="Add a new task..."
26
+ class="flex-grow px-4 py-3 rounded-xl border border-pink-200 focus:outline-none focus:ring-2 focus:ring-pink-300"
27
+ required
28
+ >
29
+ <button
30
+ type="submit"
31
+ class="bg-pink-500 hover:bg-pink-600 text-white px-5 py-3 rounded-xl transition duration-200 flex items-center"
32
+ >
33
+ <i data-feather="plus" class="w-5 h-5"></i>
34
+ </button>
35
+ </form>
36
+ </div>
37
+
38
+ <div class="bg-white rounded-2xl shadow-lg overflow-hidden">
39
+ <ul id="task-list" class="divide-y divide-pink-100">
40
+ <!-- Tasks will be added here dynamically -->
41
+ </ul>
42
+
43
+ <div id="empty-state" class="text-center py-12 hidden">
44
+ <div class="mb-4">
45
+ <i data-feather="check-circle" class="w-16 h-16 text-pink-300 mx-auto"></i>
46
+ </div>
47
+ <h3 class="text-xl font-semibold text-pink-500 mb-2">All caught up!</h3>
48
+ <p class="text-pink-400">You have no pending tasks. Great job! 🎉</p>
49
+ </div>
50
+ </div>
51
+ </main>
52
+
53
+ <footer class="mt-12 text-center text-pink-400 text-sm">
54
+ <p>Made with ❤️ | Your tasks are saved locally</p>
55
+ </footer>
56
+ </div>
57
+
58
+ <script src="script.js"></script>
59
+ <script>
60
+ feather.replace();
61
+ </script>
62
+ <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
63
+ </body>
64
+ </html>
script.js ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ document.addEventListener('DOMContentLoaded', () => {
2
+ const taskForm = document.getElementById('task-form');
3
+ const newTaskInput = document.getElementById('new-task');
4
+ const taskList = document.getElementById('task-list');
5
+ const emptyState = document.getElementById('empty-state');
6
+
7
+ let tasks = JSON.parse(localStorage.getItem('tasks')) || [];
8
+
9
+ // Render tasks on page load
10
+ renderTasks();
11
+
12
+ // Add new task
13
+ taskForm.addEventListener('submit', (e) => {
14
+ e.preventDefault();
15
+
16
+ const taskText = newTaskInput.value.trim();
17
+ if (taskText) {
18
+ addTask(taskText);
19
+ newTaskInput.value = '';
20
+ newTaskInput.focus();
21
+ }
22
+ });
23
+
24
+ // Add task function
25
+ function addTask(text) {
26
+ const newTask = {
27
+ id: Date.now(),
28
+ text: text,
29
+ completed: false
30
+ };
31
+
32
+ tasks.unshift(newTask); // Add to beginning of array
33
+ saveTasks();
34
+ renderTasks();
35
+ }
36
+
37
+ // Delete task
38
+ function deleteTask(id) {
39
+ tasks = tasks.filter(task => task.id !== id);
40
+ saveTasks();
41
+ renderTasks();
42
+ }
43
+
44
+ // Toggle task completion
45
+ function toggleTask(id) {
46
+ tasks = tasks.map(task => {
47
+ if (task.id === id) {
48
+ return {...task, completed: !task.completed};
49
+ }
50
+ return task;
51
+ });
52
+
53
+ // Sort tasks: incomplete first
54
+ tasks.sort((a, b) => {
55
+ if (a.completed && !b.completed) return 1;
56
+ if (!a.completed && b.completed) return -1;
57
+ return 0;
58
+ });
59
+
60
+ saveTasks();
61
+ renderTasks();
62
+ }
63
+
64
+ // Save tasks to localStorage
65
+ function saveTasks() {
66
+ localStorage.setItem('tasks', JSON.stringify(tasks));
67
+ }
68
+
69
+ // Render tasks to the DOM
70
+ function renderTasks() {
71
+ if (tasks.length === 0) {
72
+ taskList.innerHTML = '';
73
+ emptyState.classList.remove('hidden');
74
+ return;
75
+ }
76
+
77
+ emptyState.classList.add('hidden');
78
+
79
+ // Sort tasks: incomplete first
80
+ const sortedTasks = [...tasks].sort((a, b) => {
81
+ if (a.completed && !b.completed) return 1;
82
+ if (!a.completed && b.completed) return -1;
83
+ return 0;
84
+ });
85
+
86
+ taskList.innerHTML = sortedTasks.map(task => `
87
+ <li class="task-item ${task.completed ? 'completed' : ''} p-4 flex items-center justify-between transition-all duration-200 hover:bg-pink-50">
88
+ <div class="flex items-center space-x-3">
89
+ <button
90
+ class="check-button w-6 h-6 rounded-full border-2 border-pink-300 flex items-center justify-center ${task.completed ? 'checked bg-pink-400 border-pink-400' : ''}"
91
+ data-id="${task.id}"
92
+ aria-label="${task.completed ? 'Mark as incomplete' : 'Mark as complete'}"
93
+ >
94
+ ${task.completed ? '<i data-feather="check" class="w-4 h-4 text-white"></i>' : ''}
95
+ </button>
96
+ <span class="task-text ${task.completed ? 'text-pink-400' : 'text-gray-700'}">${task.text}</span>
97
+ </div>
98
+ <div class="task-actions flex space-x-2">
99
+ <button
100
+ class="delete-button text-pink-400 hover:text-pink-600 transition-colors"
101
+ data-id="${task.id}"
102
+ aria-label="Delete task"
103
+ >
104
+ <i data-feather="trash-2" class="w-5 h-5"></i>
105
+ </button>
106
+ </div>
107
+ </li>
108
+ `).join('');
109
+
110
+ // Add event listeners to new buttons
111
+ document.querySelectorAll('.check-button').forEach(button => {
112
+ button.addEventListener('click', (e) => {
113
+ const id = parseInt(e.currentTarget.getAttribute('data-id'));
114
+ toggleTask(id);
115
+ });
116
+ });
117
+
118
+ document.querySelectorAll('.delete-button').forEach(button => {
119
+ button.addEventListener('click', (e) => {
120
+ const id = parseInt(e.currentTarget.getAttribute('data-id'));
121
+ deleteTask(id);
122
+ });
123
+ });
124
+
125
+ // Re-initialize Feather icons
126
+ feather.replace();
127
+ }
128
+ });
style.css CHANGED
@@ -1,28 +1,57 @@
 
 
1
  body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  }
5
 
6
- h1 {
7
- font-size: 16px;
8
- margin-top: 0;
9
  }
10
 
11
- p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
16
  }
17
 
18
- .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
24
  }
25
 
26
- .card p:last-child {
27
- margin-bottom: 0;
 
 
28
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import url('https://fonts.googleapis.com/css2?family=Nunito:wght@300;400;600;700&display=swap');
2
+
3
  body {
4
+ font-family: 'Nunito', sans-serif;
5
+ background: linear-gradient(135deg, #fdf2f8 0%, #fce7f3 100%);
6
+ }
7
+
8
+ .task-item {
9
+ transition: all 0.3s ease;
10
+ }
11
+
12
+ .task-item.completed .task-text {
13
+ text-decoration: line-through;
14
+ color: #c084fc;
15
+ }
16
+
17
+ .task-actions {
18
+ opacity: 0;
19
+ transition: opacity 0.2s ease;
20
  }
21
 
22
+ .task-item:hover .task-actions {
23
+ opacity: 1;
 
24
  }
25
 
26
+ .check-button.checked {
27
+ background-color: #f0abfc;
28
+ border-color: #f0abfc;
 
 
29
  }
30
 
31
+ .empty-state-animation {
32
+ animation: float 3s ease-in-out infinite;
 
 
 
 
33
  }
34
 
35
+ @keyframes float {
36
+ 0% { transform: translateY(0px); }
37
+ 50% { transform: translateY(-10px); }
38
+ 100% { transform: translateY(0px); }
39
  }
40
+
41
+ /* Custom scrollbar */
42
+ ::-webkit-scrollbar {
43
+ width: 8px;
44
+ }
45
+
46
+ ::-webkit-scrollbar-track {
47
+ background: #fce7f3;
48
+ }
49
+
50
+ ::-webkit-scrollbar-thumb {
51
+ background: #f0abfc;
52
+ border-radius: 4px;
53
+ }
54
+
55
+ ::-webkit-scrollbar-thumb:hover {
56
+ background: #e879f9;
57
+ }