iProsto commited on
Commit
a8e626b
·
verified ·
1 Parent(s): 6bccb39

Save tasks in the localstorage. Add to each task an id and use the id as a unique identificator of task

Browse files
Files changed (5) hide show
  1. README.md +8 -5
  2. components/header.js +44 -0
  3. index.html +45 -19
  4. script.js +148 -0
  5. style.css +14 -20
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Tasky Mctaskface
3
- emoji: 🏃
4
- colorFrom: red
5
- colorTo: green
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: Tasky McTaskface 🗒️
3
+ colorFrom: green
4
+ colorTo: red
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).
components/header.js ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomHeader extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ header {
7
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
8
+ color: white;
9
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
10
+ }
11
+
12
+ .header-content {
13
+ max-width: 1200px;
14
+ margin: 0 auto;
15
+ }
16
+
17
+ .logo {
18
+ font-weight: 700;
19
+ letter-spacing: 1px;
20
+ }
21
+
22
+ .task-count {
23
+ background-color: rgba(255, 255, 255, 0.2);
24
+ border-radius: 9999px;
25
+ padding: 2px 8px;
26
+ font-size: 0.8rem;
27
+ }
28
+ </style>
29
+ <header class="py-6">
30
+ <div class="header-content px-6">
31
+ <div class="flex items-center justify-between">
32
+ <div class="flex items-center space-x-2">
33
+ <i data-feather="check-circle" class="text-white"></i>
34
+ <h1 class="logo text-xl">Tasky McTaskface</h1>
35
+ </div>
36
+ <span class="task-count" id="taskCounter">0 tasks</span>
37
+ </div>
38
+ </div>
39
+ </header>
40
+ `;
41
+ }
42
+ }
43
+
44
+ customElements.define('custom-header', CustomHeader);
index.html CHANGED
@@ -1,19 +1,45 @@
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>Tasky McTaskface</title>
7
+ <link rel="stylesheet" href="style.css">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
10
+ <script src="https://unpkg.com/feather-icons"></script>
11
+ </head>
12
+ <body class="bg-gray-100 min-h-screen">
13
+ <custom-header></custom-header>
14
+
15
+ <main class="container mx-auto px-4 py-8">
16
+ <div class="max-w-2xl mx-auto bg-white rounded-lg shadow-md overflow-hidden">
17
+ <div class="p-6">
18
+ <h2 class="text-2xl font-bold text-gray-800 mb-6">My Tasks</h2>
19
+
20
+ <div class="flex mb-6">
21
+ <input type="text" id="taskInput" placeholder="Add a new task..."
22
+ class="flex-grow px-4 py-2 border border-gray-300 rounded-l-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
23
+ <button id="addTaskBtn" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-r-lg transition duration-200">
24
+ <i data-feather="plus"></i>
25
+ </button>
26
+ </div>
27
+
28
+ <div id="taskList" class="space-y-3">
29
+ <!-- Tasks will be dynamically inserted here -->
30
+ </div>
31
+ </div>
32
+ </div>
33
+ </main>
34
+
35
+ <script src="components/header.js"></script>
36
+ <script src="script.js"></script>
37
+ <script>
38
+ feather.replace();
39
+ document.addEventListener('DOMContentLoaded', () => {
40
+ loadTasks();
41
+ });
42
+ </script>
43
+ <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
44
+ </body>
45
+ </html>
script.js ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Task Manager Class
2
+ class TaskManager {
3
+ constructor() {
4
+ this.tasks = this.loadTasksFromStorage();
5
+ }
6
+
7
+ loadTasksFromStorage() {
8
+ const tasks = localStorage.getItem('tasks');
9
+ return tasks ? JSON.parse(tasks) : [];
10
+ }
11
+
12
+ saveTasksToStorage() {
13
+ localStorage.setItem('tasks', JSON.stringify(this.tasks));
14
+ }
15
+
16
+ addTask(text) {
17
+ const newTask = {
18
+ id: Date.now().toString(),
19
+ text,
20
+ completed: false,
21
+ createdAt: new Date().toISOString()
22
+ };
23
+ this.tasks.unshift(newTask);
24
+ this.saveTasksToStorage();
25
+ return newTask;
26
+ }
27
+
28
+ toggleTask(id) {
29
+ const task = this.tasks.find(t => t.id === id);
30
+ if (task) {
31
+ task.completed = !task.completed;
32
+ this.saveTasksToStorage();
33
+ }
34
+ }
35
+
36
+ deleteTask(id) {
37
+ this.tasks = this.tasks.filter(t => t.id !== id);
38
+ this.saveTasksToStorage();
39
+ }
40
+
41
+ getTasks() {
42
+ return [...this.tasks];
43
+ }
44
+ }
45
+
46
+ // UI Controller
47
+ class UIController {
48
+ constructor() {
49
+ this.taskManager = new TaskManager();
50
+ this.taskInput = document.getElementById('taskInput');
51
+ this.addTaskBtn = document.getElementById('addTaskBtn');
52
+ this.taskList = document.getElementById('taskList');
53
+
54
+ this.setupEventListeners();
55
+ }
56
+
57
+ setupEventListeners() {
58
+ this.addTaskBtn.addEventListener('click', () => this.handleAddTask());
59
+ this.taskInput.addEventListener('keypress', (e) => {
60
+ if (e.key === 'Enter') this.handleAddTask();
61
+ });
62
+ }
63
+
64
+ handleAddTask() {
65
+ const taskText = this.taskInput.value.trim();
66
+ if (taskText) {
67
+ const newTask = this.taskManager.addTask(taskText);
68
+ this.renderTask(newTask);
69
+ this.taskInput.value = '';
70
+ this.taskInput.focus();
71
+ }
72
+ }
73
+
74
+ renderTask(task) {
75
+ const taskElement = document.createElement('div');
76
+ taskElement.className = 'task-item task-enter bg-gray-50 p-4 rounded-lg flex items-center justify-between';
77
+ taskElement.dataset.id = task.id;
78
+
79
+ taskElement.innerHTML = `
80
+ <div class="flex items-center">
81
+ <button class="toggle-btn mr-3 text-gray-400 hover:text-green-500 transition" data-id="${task.id}">
82
+ <i data-feather="${task.completed ? 'check-circle' : 'circle'}" class="${task.completed ? 'text-green-500' : ''}"></i>
83
+ </button>
84
+ <span class="${task.completed ? 'task-complete text-gray-500' : 'text-gray-800'}">${task.text}</span>
85
+ </div>
86
+ <button class="delete-btn text-gray-400 hover:text-red-500 transition" data-id="${task.id}">
87
+ <i data-feather="trash-2"></i>
88
+ </button>
89
+ `;
90
+
91
+ this.taskList.prepend(taskElement);
92
+ feather.replace();
93
+
94
+ // Add event listeners to the new buttons
95
+ taskElement.querySelector('.toggle-btn').addEventListener('click', (e) => {
96
+ this.toggleTask(e.currentTarget.dataset.id);
97
+ });
98
+
99
+ taskElement.querySelector('.delete-btn').addEventListener('click', (e) => {
100
+ this.deleteTask(e.currentTarget.dataset.id);
101
+ });
102
+ }
103
+
104
+ toggleTask(id) {
105
+ this.taskManager.toggleTask(id);
106
+ const taskElement = document.querySelector(`[data-id="${id}"]`);
107
+ if (taskElement) {
108
+ const icon = taskElement.querySelector('.toggle-btn i');
109
+ const text = taskElement.querySelector('span');
110
+
111
+ if (this.taskManager.getTasks().find(t => t.id === id).completed) {
112
+ icon.setAttribute('data-feather', 'check-circle');
113
+ icon.classList.add('text-green-500');
114
+ text.classList.add('task-complete', 'text-gray-500');
115
+ text.classList.remove('text-gray-800');
116
+ } else {
117
+ icon.setAttribute('data-feather', 'circle');
118
+ icon.classList.remove('text-green-500');
119
+ text.classList.remove('task-complete', 'text-gray-500');
120
+ text.classList.add('text-gray-800');
121
+ }
122
+ feather.replace();
123
+ }
124
+ }
125
+
126
+ deleteTask(id) {
127
+ this.taskManager.deleteTask(id);
128
+ const taskElement = document.querySelector(`[data-id="${id}"]`);
129
+ if (taskElement) {
130
+ taskElement.classList.add('opacity-0', 'translate-x-10');
131
+ setTimeout(() => {
132
+ taskElement.remove();
133
+ }, 300);
134
+ }
135
+ }
136
+
137
+ loadTasks() {
138
+ this.taskList.innerHTML = '';
139
+ const tasks = this.taskManager.getTasks();
140
+ tasks.forEach(task => this.renderTask(task));
141
+ }
142
+ }
143
+
144
+ // Initialize the app
145
+ function loadTasks() {
146
+ const ui = new UIController();
147
+ ui.loadTasks();
148
+ }
style.css CHANGED
@@ -1,28 +1,22 @@
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
+ .task-item {
2
+ transition: all 0.2s ease;
 
3
  }
4
 
5
+ .task-item:hover {
6
+ transform: translateY(-2px);
 
7
  }
8
 
9
+ .task-complete {
10
+ text-decoration: line-through;
11
+ opacity: 0.7;
 
 
12
  }
13
 
14
+ /* Animation for task addition/removal */
15
+ @keyframes fadeIn {
16
+ from { opacity: 0; transform: translateY(10px); }
17
+ to { opacity: 1; transform: translateY(0); }
 
 
18
  }
19
 
20
+ .task-enter {
21
+ animation: fadeIn 0.3s ease forwards;
22
+ }