Created
February 4, 2025 12:25
-
-
Save syafiqfaiz/366af256f62f48e0b9f69f0d2d9cd961 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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