Bab 10 dari 10
Proyek Akhir: Aplikasi Daftar Tugas
Pada proyek akhir, kita menggabungkan variabel, fungsi, array, object, DOM, event, dan penyimpanan browser menjadi aplikasi daftar tugas.
Fitur
- menambah tugas;
- menandai tugas selesai;
- menghapus tugas;
- memfilter semua, aktif, atau selesai;
- menyimpan data di
localStorage; - menampilkan jumlah tugas aktif.
Struktur HTML
Code
<main class="app">
<h1>Daftar Tugas</h1>
<form id="form-tugas">
<label for="input-tugas">Tugas baru</label>
<div>
<input id="input-tugas" autocomplete="off" required />
<button>Tambah</button>
</div>
</form>
<div id="filter">
<button data-filter="semua">Semua</button>
<button data-filter="aktif">Aktif</button>
<button data-filter="selesai">Selesai</button>
</div>
<p id="ringkasan"></p>
<ul id="daftar-tugas"></ul>
</main>
<script src="script.js"></script>
Model data dan penyimpanan
Code
const STORAGE_KEY = "basic-js-tasks";
let tasks = JSON.parse(localStorage.getItem(STORAGE_KEY) || "[]");
let filterAktif = "semua";
function simpan() {
localStorage.setItem(STORAGE_KEY, JSON.stringify(tasks));
}
Setiap tugas berbentuk:
Code
{
id: crypto.randomUUID(),
text: "Belajar JavaScript",
completed: false
}
Render tampilan
Code
const daftar = document.querySelector("#daftar-tugas");
const ringkasan = document.querySelector("#ringkasan");
function tugasTerfilter() {
if (filterAktif === "aktif") return tasks.filter(task => !task.completed);
if (filterAktif === "selesai") return tasks.filter(task => task.completed);
return tasks;
}
function render() {
daftar.replaceChildren();
for (const task of tugasTerfilter()) {
const item = document.createElement("li");
const label = document.createElement("span");
const toggle = document.createElement("button");
const hapus = document.createElement("button");
label.textContent = task.text;
toggle.textContent = task.completed ? "Batalkan" : "Selesai";
hapus.textContent = "Hapus";
toggle.dataset.action = "toggle";
hapus.dataset.action = "delete";
item.dataset.id = task.id;
item.append(label, toggle, hapus);
daftar.append(item);
}
const aktif = tasks.filter(task => !task.completed).length;
ringkasan.textContent = `${aktif} tugas aktif`;
}
Menambah tugas
Code
const form = document.querySelector("#form-tugas");
const input = document.querySelector("#input-tugas");
form.addEventListener("submit", event => {
event.preventDefault();
const text = input.value.trim();
if (!text) return;
tasks.push({
id: crypto.randomUUID(),
text,
completed: false,
});
simpan();
render();
form.reset();
input.focus();
});
Toggle dan hapus
Code
daftar.addEventListener("click", event => {
const action = event.target.dataset.action;
const item = event.target.closest("li");
if (!action || !item) return;
const index = tasks.findIndex(task => task.id === item.dataset.id);
if (index === -1) return;
if (action === "toggle") {
tasks[index] = { ...tasks[index], completed: !tasks[index].completed };
}
if (action === "delete") {
tasks.splice(index, 1);
}
simpan();
render();
});
Filter
Code
document.querySelector("#filter").addEventListener("click", event => {
const filter = event.target.dataset.filter;
if (!filter) return;
filterAktif = filter;
render();
});
render();
Pengembangan lanjutan
Setelah versi dasar bekerja, tambahkan:
- edit teks tugas;
- tombol hapus semua tugas selesai;
- validasi panjang maksimum;
- pengurutan berdasarkan waktu;
- styling responsif dan fokus keyboard yang terlihat.
Checklist kelulusan
- Semua fitur utama berjalan tanpa error Console.
- Data tetap ada setelah halaman dimuat ulang.
- Input kosong tidak membuat tugas baru.
- Nama variabel dan fungsi menjelaskan tugasnya.
- Tampilan dapat digunakan dengan keyboard.
Kamu kini sudah menggunakan fondasi JavaScript dalam satu aplikasi nyata. Langkah berikutnya adalah memperdalam module, error handling, testing, dan kemudian memilih framework jika kebutuhan proyek memang memerlukannya.