Update index.html
Browse files- index.html +324 -19
index.html
CHANGED
@@ -1,19 +1,324 @@
|
|
1 |
-
<!
|
2 |
-
<html>
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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>My To-Do List</title>
|
7 |
+
<style>
|
8 |
+
body {
|
9 |
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
10 |
+
background-color: #f4f4f9;
|
11 |
+
color: #333;
|
12 |
+
display: flex;
|
13 |
+
justify-content: center;
|
14 |
+
align-items: center;
|
15 |
+
min-height: 100vh; /* Changed to min-height for longer lists */
|
16 |
+
margin: 0;
|
17 |
+
padding: 20px 0; /* Add some padding for scrollable content */
|
18 |
+
}
|
19 |
+
#app-container {
|
20 |
+
background: #fff;
|
21 |
+
padding: 25px 40px;
|
22 |
+
border-radius: 10px;
|
23 |
+
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
24 |
+
width: 100%;
|
25 |
+
max-width: 500px; /* Increased max-width slightly for more buttons */
|
26 |
+
box-sizing: border-box;
|
27 |
+
}
|
28 |
+
h1 {
|
29 |
+
color: #444;
|
30 |
+
text-align: center;
|
31 |
+
margin-top: 0;
|
32 |
+
margin-bottom: 20px;
|
33 |
+
font-weight: 600;
|
34 |
+
}
|
35 |
+
#task-input-container {
|
36 |
+
display: flex;
|
37 |
+
gap: 10px;
|
38 |
+
margin-bottom: 20px;
|
39 |
+
}
|
40 |
+
#task-input {
|
41 |
+
flex-grow: 1;
|
42 |
+
padding: 12px;
|
43 |
+
border: 1px solid #ddd;
|
44 |
+
border-radius: 5px;
|
45 |
+
font-size: 16px;
|
46 |
+
}
|
47 |
+
#add-task-btn {
|
48 |
+
padding: 12px 20px;
|
49 |
+
background-color: #007bff;
|
50 |
+
color: white;
|
51 |
+
border: none;
|
52 |
+
border-radius: 5px;
|
53 |
+
cursor: pointer;
|
54 |
+
font-size: 16px;
|
55 |
+
font-weight: 500;
|
56 |
+
transition: background-color 0.3s;
|
57 |
+
}
|
58 |
+
#add-task-btn:hover {
|
59 |
+
background-color: #0056b3;
|
60 |
+
}
|
61 |
+
#task-list {
|
62 |
+
list-style: none;
|
63 |
+
padding: 0;
|
64 |
+
margin: 0;
|
65 |
+
}
|
66 |
+
.task-item {
|
67 |
+
display: flex;
|
68 |
+
align-items: center;
|
69 |
+
justify-content: space-between;
|
70 |
+
padding: 12px 0; /* Adjusted padding, horizontal padding now on children */
|
71 |
+
border-bottom: 1px solid #eee;
|
72 |
+
font-size: 16px;
|
73 |
+
}
|
74 |
+
.task-item:last-child {
|
75 |
+
border-bottom: none;
|
76 |
+
}
|
77 |
+
.task-text-content { /* New class for the text part */
|
78 |
+
cursor: pointer;
|
79 |
+
flex-grow: 1;
|
80 |
+
padding-right: 10px; /* Space before action buttons */
|
81 |
+
overflow-wrap: break-word; /* Prevent long text from breaking layout */
|
82 |
+
word-break: break-word;
|
83 |
+
}
|
84 |
+
.task-item.completed .task-text-content { /* Updated selector */
|
85 |
+
text-decoration: line-through;
|
86 |
+
color: #aaa;
|
87 |
+
}
|
88 |
+
.task-actions {
|
89 |
+
display: flex;
|
90 |
+
align-items: center;
|
91 |
+
flex-shrink: 0; /* Prevent actions container from shrinking */
|
92 |
+
}
|
93 |
+
.emoji-toggle {
|
94 |
+
background: transparent;
|
95 |
+
border: 1px solid transparent; /* Keep layout consistent */
|
96 |
+
border-radius: 4px;
|
97 |
+
padding: 4px 6px;
|
98 |
+
cursor: pointer;
|
99 |
+
margin-left: 5px;
|
100 |
+
font-size: 18px; /* Slightly larger for emojis */
|
101 |
+
opacity: 0.4; /* Dimmed when inactive */
|
102 |
+
transition: opacity 0.2s, border-color 0.2s;
|
103 |
+
line-height: 1; /* Ensure consistent height */
|
104 |
+
}
|
105 |
+
.emoji-toggle:hover {
|
106 |
+
opacity: 0.7;
|
107 |
+
}
|
108 |
+
.emoji-toggle.active {
|
109 |
+
opacity: 1;
|
110 |
+
border: 1px solid #007bff;
|
111 |
+
}
|
112 |
+
.delete-btn {
|
113 |
+
background: #dc3545;
|
114 |
+
color: white;
|
115 |
+
border: none;
|
116 |
+
border-radius: 50%;
|
117 |
+
width: 28px;
|
118 |
+
height: 28px;
|
119 |
+
cursor: pointer;
|
120 |
+
font-size: 16px;
|
121 |
+
line-height: 28px;
|
122 |
+
text-align: center;
|
123 |
+
transition: background-color 0.3s;
|
124 |
+
margin-left: 8px; /* Space from emoji toggles */
|
125 |
+
flex-shrink: 0;
|
126 |
+
}
|
127 |
+
.delete-btn:hover {
|
128 |
+
background: #c82333;
|
129 |
+
}
|
130 |
+
</style>
|
131 |
+
</head>
|
132 |
+
<body>
|
133 |
+
|
134 |
+
<div id="app-container">
|
135 |
+
<h1>To-Do List β
</h1>
|
136 |
+
<div id="task-input-container">
|
137 |
+
<input type="text" id="task-input" placeholder="Add a new task...">
|
138 |
+
<button id="add-task-btn">Add</button>
|
139 |
+
</div>
|
140 |
+
<ul id="task-list"></ul>
|
141 |
+
</div>
|
142 |
+
|
143 |
+
<script>
|
144 |
+
document.addEventListener('DOMContentLoaded', () => {
|
145 |
+
const taskInput = document.getElementById('task-input');
|
146 |
+
const addTaskBtn = document.getElementById('add-task-btn');
|
147 |
+
const taskList = document.getElementById('task-list');
|
148 |
+
|
149 |
+
const initialRawTasks = [
|
150 |
+
{ text: "Chaucer ai", completed: true },
|
151 |
+
{ text: "PyBench CFWD on VAI multinode", completed: false },
|
152 |
+
{ text: "Managed Method call", completed: true },
|
153 |
+
{ text: "Add ER Poc Chaucer AI", completed: true },
|
154 |
+
{ text: "Add ER Poc TR", completed: false },
|
155 |
+
{ text: "Add ER Aueso", completed: false },
|
156 |
+
{ text: "Runway Help", completed: false },
|
157 |
+
{ text: "Inference wkshp", completed: false },
|
158 |
+
{ text: "TPU dock", completed: false },
|
159 |
+
{ text: "Meridian", completed: false },
|
160 |
+
{ text: "Nay Gnad for checkin", completed: false },
|
161 |
+
{ text: "KaiPopApp", completed: false }
|
162 |
+
];
|
163 |
+
|
164 |
+
// Helper function to ensure task objects have all necessary properties
|
165 |
+
const ensureTaskProperties = (task) => {
|
166 |
+
return {
|
167 |
+
text: task.text,
|
168 |
+
completed: !!task.completed,
|
169 |
+
isCode: !!task.isCode,
|
170 |
+
isAdmin: !!task.isAdmin,
|
171 |
+
isClient: !!task.isClient,
|
172 |
+
};
|
173 |
+
};
|
174 |
+
|
175 |
+
// Load tasks from local storage or use initial tasks if storage is empty
|
176 |
+
let tasks = [];
|
177 |
+
const storedTasks = localStorage.getItem('tasks');
|
178 |
+
if (storedTasks) {
|
179 |
+
tasks = JSON.parse(storedTasks).map(ensureTaskProperties);
|
180 |
+
} else {
|
181 |
+
tasks = initialRawTasks.map(ensureTaskProperties);
|
182 |
+
}
|
183 |
+
if (tasks.length === 0 && initialRawTasks.length > 0 && !storedTasks) { // Ensure initial tasks are used if local storage was empty
|
184 |
+
tasks = initialRawTasks.map(ensureTaskProperties);
|
185 |
+
}
|
186 |
+
|
187 |
+
|
188 |
+
// Function to save tasks to local storage
|
189 |
+
const saveTasks = () => {
|
190 |
+
localStorage.setItem('tasks', JSON.stringify(tasks));
|
191 |
+
};
|
192 |
+
|
193 |
+
// Function to render tasks to the DOM
|
194 |
+
const renderTasks = () => {
|
195 |
+
// Sort tasks: Client first, then Code, then by completion status
|
196 |
+
tasks.sort((a, b) => {
|
197 |
+
// Client tasks come first
|
198 |
+
if (a.isClient && !b.isClient) return -1;
|
199 |
+
if (!a.isClient && b.isClient) return 1;
|
200 |
+
|
201 |
+
// If both are Client or both are not Client, then Code tasks
|
202 |
+
if (a.isCode && !b.isCode) return -1;
|
203 |
+
if (!a.isCode && b.isCode) return 1;
|
204 |
+
|
205 |
+
// If same client and code status, then uncompleted tasks first
|
206 |
+
if (!a.completed && b.completed) return -1;
|
207 |
+
if (a.completed && !b.completed) return 1;
|
208 |
+
|
209 |
+
return 0; // Maintain relative order for items with same priority
|
210 |
+
});
|
211 |
+
|
212 |
+
taskList.innerHTML = ''; // Clear existing list
|
213 |
+
tasks.forEach((task, index) => {
|
214 |
+
const li = document.createElement('li');
|
215 |
+
li.className = 'task-item';
|
216 |
+
if (task.completed) {
|
217 |
+
li.classList.add('completed');
|
218 |
+
}
|
219 |
+
|
220 |
+
// Task text content (emojis + text)
|
221 |
+
const taskTextContentEl = document.createElement('span');
|
222 |
+
taskTextContentEl.className = 'task-text-content';
|
223 |
+
let emojisPrefix = '';
|
224 |
+
if (task.isClient) emojisPrefix += 'π€ ';
|
225 |
+
if (task.isCode) emojisPrefix += 'π» ';
|
226 |
+
if (task.isAdmin) emojisPrefix += 'βοΈ ';
|
227 |
+
taskTextContentEl.textContent = emojisPrefix + task.text;
|
228 |
+
taskTextContentEl.addEventListener('click', () => toggleTaskCompletion(index));
|
229 |
+
|
230 |
+
// Actions container (toggles + delete)
|
231 |
+
const actionsContainer = document.createElement('div');
|
232 |
+
actionsContainer.className = 'task-actions';
|
233 |
+
|
234 |
+
// Emoji Toggles
|
235 |
+
const categories = [
|
236 |
+
{ type: 'client', emoji: 'π€', prop: 'isClient', title: 'Client Task' },
|
237 |
+
{ type: 'code', emoji: 'π»', prop: 'isCode', title: 'Code Task' },
|
238 |
+
{ type: 'admin', emoji: 'βοΈ', prop: 'isAdmin', title: 'Admin Task' }
|
239 |
+
];
|
240 |
+
|
241 |
+
categories.forEach(cat => {
|
242 |
+
const toggleBtn = document.createElement('button');
|
243 |
+
toggleBtn.className = 'emoji-toggle';
|
244 |
+
toggleBtn.textContent = cat.emoji;
|
245 |
+
toggleBtn.title = `Toggle ${cat.title}`;
|
246 |
+
toggleBtn.dataset.type = cat.type;
|
247 |
+
if (task[cat.prop]) {
|
248 |
+
toggleBtn.classList.add('active');
|
249 |
+
}
|
250 |
+
toggleBtn.addEventListener('click', (e) => {
|
251 |
+
e.stopPropagation(); // Prevent task completion toggle
|
252 |
+
toggleEmojiCategory(index, cat.prop);
|
253 |
+
});
|
254 |
+
actionsContainer.appendChild(toggleBtn);
|
255 |
+
});
|
256 |
+
|
257 |
+
// Delete button
|
258 |
+
const deleteBtn = document.createElement('button');
|
259 |
+
deleteBtn.textContent = 'Γ';
|
260 |
+
deleteBtn.className = 'delete-btn';
|
261 |
+
deleteBtn.title = "Delete Task";
|
262 |
+
deleteBtn.addEventListener('click', (e) => {
|
263 |
+
e.stopPropagation(); // Prevent task completion toggle
|
264 |
+
deleteTask(index);
|
265 |
+
});
|
266 |
+
|
267 |
+
actionsContainer.appendChild(deleteBtn);
|
268 |
+
|
269 |
+
li.appendChild(taskTextContentEl);
|
270 |
+
li.appendChild(actionsContainer);
|
271 |
+
taskList.appendChild(li);
|
272 |
+
});
|
273 |
+
};
|
274 |
+
|
275 |
+
// Function to add a new task
|
276 |
+
const addTask = () => {
|
277 |
+
const taskText = taskInput.value.trim();
|
278 |
+
if (taskText !== '') {
|
279 |
+
// Add new task with default false for emoji categories
|
280 |
+
tasks.unshift(ensureTaskProperties({ text: taskText, completed: false }));
|
281 |
+
taskInput.value = '';
|
282 |
+
saveTasks();
|
283 |
+
renderTasks();
|
284 |
+
}
|
285 |
+
};
|
286 |
+
|
287 |
+
// Function to delete a task
|
288 |
+
const deleteTask = (index) => {
|
289 |
+
tasks.splice(index, 1);
|
290 |
+
saveTasks();
|
291 |
+
renderTasks();
|
292 |
+
};
|
293 |
+
|
294 |
+
// Function to toggle a task's completion status
|
295 |
+
const toggleTaskCompletion = (index) => {
|
296 |
+
tasks[index].completed = !tasks[index].completed;
|
297 |
+
saveTasks();
|
298 |
+
renderTasks(); // Re-render to apply style and potentially re-sort if completion affects order
|
299 |
+
};
|
300 |
+
|
301 |
+
// Function to toggle an emoji category for a task
|
302 |
+
const toggleEmojiCategory = (index, categoryProp) => {
|
303 |
+
tasks[index][categoryProp] = !tasks[index][categoryProp];
|
304 |
+
saveTasks();
|
305 |
+
renderTasks(); // Re-render to update emojis, sort, and toggle style
|
306 |
+
};
|
307 |
+
|
308 |
+
// Event listener for the "Add" button
|
309 |
+
addTaskBtn.addEventListener('click', addTask);
|
310 |
+
|
311 |
+
// Event listener for the Enter key in the input field
|
312 |
+
taskInput.addEventListener('keypress', (e) => {
|
313 |
+
if (e.key === 'Enter') {
|
314 |
+
addTask();
|
315 |
+
}
|
316 |
+
});
|
317 |
+
|
318 |
+
// Initial render of tasks on page load
|
319 |
+
renderTasks();
|
320 |
+
});
|
321 |
+
</script>
|
322 |
+
|
323 |
+
</body>
|
324 |
+
</html>
|