Skip to content

Instantly share code, notes, and snippets.

@syafiqfaiz
Created February 4, 2025 12:25
Show Gist options
  • Save syafiqfaiz/366af256f62f48e0b9f69f0d2d9cd961 to your computer and use it in GitHub Desktop.
Save syafiqfaiz/366af256f62f48e0b9f69f0d2d9cd961 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Todo App with Authentication</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
text-align: center;
margin: 0;
padding: 20px;
}
.container {
max-width: 400px;
margin: 0 auto;
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
h2 {
color: #333;
}
.todo-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
border-bottom: 1px solid #ddd;
}
.todo-item:last-child {
border-bottom: none;
}
.completed {
text-decoration: line-through;
color: gray;
}
.hidden {
display: none;
}
button {
padding: 8px 12px;
border: none;
border-radius: 5px;
cursor: pointer;
}
.btn-primary {
background-color: #28a745;
color: white;
}
.btn-danger {
background-color: #dc3545;
color: white;
}
.btn-secondary {
background-color: #007bff;
color: white;
}
input[type="text"] {
width: calc(100% - 20px);
padding: 8px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 5px;
}
</style>
</head>
<body>
<div class="container">
<h2>Todo List</h2>
<div id="auth-section">
<button class="btn-secondary" onclick="login()">Login</button>
<button class="btn-danger" onclick="logout()">Logout</button>
<p id="auth-status">Not logged in</p>
</div>
<div id="todo-form" class="hidden">
<input type="text" id="todo-input" placeholder="New todo" />
<button class="btn-primary" onclick="addTodo()">Add</button>
</div>
<ul id="todo-list"></ul>
</div>
<script>
let isAuthenticated = false;
document.addEventListener("DOMContentLoaded", loadTodos);
function login() {
isAuthenticated = true;
document.getElementById("auth-status").innerText = "Logged in";
document.getElementById("todo-form").classList.remove("hidden");
loadTodos();
}
function logout() {
isAuthenticated = false;
document.getElementById("auth-status").innerText = "Not logged in";
document.getElementById("todo-form").classList.add("hidden");
loadTodos();
}
function loadTodos() {
const todos = JSON.parse(localStorage.getItem("todos")) || [];
const list = document.getElementById("todo-list");
list.innerHTML = "";
todos.forEach((todo, index) => {
const li = document.createElement("li");
li.className = `todo-item ${todo.completed ? "completed" : ""}`;
li.innerHTML = `
<span onclick="toggleComplete(${index})">${todo.text}</span>
${
isAuthenticated
? `<button class="btn-secondary" onclick="editTodo(${index})">Edit</button>
<button class="btn-danger" onclick="deleteTodo(${index})">Delete</button>`
: ""
}
`;
list.appendChild(li);
});
}
function addTodo() {
if (!isAuthenticated)
return alert("You must be logged in to add a todo.");
const input = document.getElementById("todo-input");
if (!input.value.trim()) return;
const todos = JSON.parse(localStorage.getItem("todos")) || [];
todos.push({ text: input.value, completed: false });
localStorage.setItem("todos", JSON.stringify(todos));
input.value = "";
loadTodos();
}
function editTodo(index) {
if (!isAuthenticated) return;
const todos = JSON.parse(localStorage.getItem("todos"));
const newValue = prompt("Edit todo:", todos[index].text);
if (newValue) {
todos[index].text = newValue;
localStorage.setItem("todos", JSON.stringify(todos));
loadTodos();
}
}
function deleteTodo(index) {
if (!isAuthenticated) return;
const todos = JSON.parse(localStorage.getItem("todos"));
todos.splice(index, 1);
localStorage.setItem("todos", JSON.stringify(todos));
loadTodos();
}
function toggleComplete(index) {
const todos = JSON.parse(localStorage.getItem("todos"));
todos[index].completed = !todos[index].completed;
localStorage.setItem("todos", JSON.stringify(todos));
loadTodos();
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment