From 14bf2f2f24eddb0323571d2bd76ea580bc974ee0 Mon Sep 17 00:00:00 2001 From: dendi <202310715051@mhs.ubharajaya.ac.id> Date: Sat, 13 Dec 2025 02:01:34 +0700 Subject: [PATCH] * **Fitur search beranda** - Cari kategori berdasarkan nama * **Search filtering real-time** - Kategori otomatis filter saat mengetik * **Delete kategori dengan UI** - Tombol X di top-right corner setiap kategori * **Confirmation dialog untuk delete** - Prevent accidental deletion dengan warning message * **Search di kategori** - Cari catatan berdasarkan judul & isi (case-insensitive) * **Search empty state** - Tampilkan pesan "Tidak ada hasil" saat search kosong * **Gradle optimization** - Cleanup dependencies yang tidak diperlukan --- .idea/deploymentTargetSelector.xml | 8 ++ Readme.md | 21 +++- .../java/com/example/notesai/MainActivity.kt | 116 +++++++++++++++--- gradle/libs.versions.toml | 2 +- 4 files changed, 122 insertions(+), 25 deletions(-) diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml index b268ef3..c03b827 100644 --- a/.idea/deploymentTargetSelector.xml +++ b/.idea/deploymentTargetSelector.xml @@ -4,6 +4,14 @@ diff --git a/Readme.md b/Readme.md index 751ab2a..219a66e 100644 --- a/Readme.md +++ b/Readme.md @@ -1,5 +1,3 @@ - - # **AI Notes – Changelog** ## **Tim Pengembang** @@ -25,7 +23,6 @@ * Penambahan validasi input form kategori * Tampilan kategori Staggered Grid (2 kolom) * Category Card (ikon folder, nama, jumlah catatan, gradient) -* Long press untuk menghapus kategori * Empty state kategori * Implementasi LazyVerticalStaggeredGrid * Gradient preset 8 warna @@ -36,7 +33,6 @@ * Fitur pin untuk catatan penting * Full-screen editable note view dengan auto-save * Fitur arsip, hapus, dan pin di full-screen mode -* Long press untuk mengarsipkan catatan * Fitur search catatan (judul + isi) * Sorting catatan berdasarkan pin & timestamp * Implementasi custom TextField dan date formatter @@ -84,15 +80,27 @@ * Halaman untuk Catatan Berbintang dan Ikon Pesan Berbintang * Pemberitahuan Konfirmasi untuk Arsip dan Hapus Catatan +## **Sprint 2: Fitur Search & Delete Kategori (Hari Ini)** + +* **Fitur search beranda** - Cari kategori berdasarkan nama +* **Search filtering real-time** - Kategori otomatis filter saat mengetik +* **Delete kategori dengan UI** - Tombol X di top-right corner setiap kategori +* **Confirmation dialog untuk delete** - Prevent accidental deletion dengan warning message +* **Search di kategori** - Cari catatan berdasarkan judul & isi (case-insensitive) +* **Search empty state** - Tampilkan pesan "Tidak ada hasil" saat search kosong +* **Gradle optimization** - Cleanup dependencies yang tidak diperlukan + --- ## **Fitur Utama Aplikasi** * Sistem kategori dengan gradient +* Buat/edit/hapus kategori dengan confirmation dialog * Buat/edit/hapus catatan * Pin catatan penting * Full-screen editor -* Search catatan +* Search kategori di beranda +* Search catatan dalam kategori * Arsip & Sampah dengan restore/delete permanen * AI Chat powered by Gemini * AI membaca & menganalisis catatan pengguna @@ -112,4 +120,5 @@ * Dark theme toggle * Multi-language support ---- \ No newline at end of file +--- + diff --git a/app/src/main/java/com/example/notesai/MainActivity.kt b/app/src/main/java/com/example/notesai/MainActivity.kt index ff9770a..86a1023 100644 --- a/app/src/main/java/com/example/notesai/MainActivity.kt +++ b/app/src/main/java/com/example/notesai/MainActivity.kt @@ -324,8 +324,10 @@ fun NotesApp() { } }, onCategoryLongClick = { category -> + // Delete kategori dan semua catatan di dalamnya categories = categories.filter { it.id != category.id } notes = notes.filter { it.categoryId != category.id } + selectedCategory = null } ) "starred" -> StarredNotesScreen( @@ -828,6 +830,7 @@ fun MainScreen( ) { Column(modifier = Modifier.fillMaxSize()) { if (selectedCategory == null) { + // Beranda: Tampilkan kategori dengan search filtering if (categories.isEmpty()) { EmptyState( icon = Icons.Default.Create, @@ -835,20 +838,41 @@ fun MainScreen( subtitle = "Tekan tombol + untuk memulai" ) } else { - LazyVerticalStaggeredGrid( - columns = StaggeredGridCells.Fixed(2), - contentPadding = PaddingValues(16.dp), - horizontalArrangement = Arrangement.spacedBy(12.dp), - verticalItemSpacing = 12.dp, - modifier = Modifier.fillMaxSize() - ) { - items(categories) { category -> - CategoryCard( - category = category, - noteCount = notes.count { it.categoryId == category.id && !it.isDeleted && !it.isArchived }, - onClick = { onCategoryClick(category) }, - onLongClick = { onCategoryLongClick(category) } - ) + // Filter kategori berdasarkan searchQuery + val filteredCategories = if (searchQuery.isEmpty()) { + categories + } else { + categories.filter { + it.name.contains(searchQuery, ignoreCase = true) + } + } + + if (filteredCategories.isEmpty()) { + EmptyState( + icon = Icons.Default.Search, + message = "Kategori tidak ditemukan", + subtitle = "Coba kata kunci lain" + ) + } else { + LazyVerticalStaggeredGrid( + columns = StaggeredGridCells.Fixed(2), + contentPadding = PaddingValues(16.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalItemSpacing = 12.dp, + modifier = Modifier.fillMaxSize() + ) { + items(filteredCategories) { category -> + CategoryCard( + category = category, + noteCount = notes.count { it.categoryId == category.id && !it.isDeleted && !it.isArchived }, + onClick = { onCategoryClick(category) }, + onLongClick = { onCategoryLongClick(category) }, + onDelete = { + // Delete kategori dan semua catatan di dalamnya + onCategoryLongClick(category) + } + ) + } } } } @@ -898,8 +922,45 @@ fun CategoryCard( category: Category, noteCount: Int, onClick: () -> Unit, - onLongClick: () -> Unit + onLongClick: () -> Unit, + onDelete: () -> Unit = {} ) { + var showDeleteConfirm by remember { mutableStateOf(false) } + + // Delete confirmation dialog + if (showDeleteConfirm) { + AlertDialog( + onDismissRequest = { showDeleteConfirm = false }, + title = { Text("Hapus Kategori?") }, + text = { + Text("Kategori '$${category.name}' dan semua catatan di dalamnya akan dihapus. Tindakan ini tidak dapat dibatalkan.") + }, + confirmButton = { + Button( + onClick = { + onDelete() + showDeleteConfirm = false + }, + colors = ButtonDefaults.buttonColors( + containerColor = Color(0xFFEF4444) + ) + ) { + Text("Hapus", color = Color.White) + } + }, + dismissButton = { + Button( + onClick = { showDeleteConfirm = false }, + colors = ButtonDefaults.buttonColors( + containerColor = Color(0xFF64748B) + ) + ) { + Text("Batal", color = Color.White) + } + } + ) + } + Card( modifier = Modifier .fillMaxWidth() @@ -945,6 +1006,21 @@ fun CategoryCard( color = Color.White.copy(0.8f) ) } + + // Delete button di top-right corner + IconButton( + onClick = { showDeleteConfirm = true }, + modifier = Modifier + .align(Alignment.TopEnd) + .size(40.dp) + ) { + Icon( + Icons.Default.Close, + contentDescription = "Hapus kategori", + tint = Color.White.copy(0.7f), + modifier = Modifier.size(20.dp) + ) + } } } } @@ -972,7 +1048,11 @@ fun NoteCard( ), elevation = CardDefaults.cardElevation(defaultElevation = 4.dp) ) { - Column(modifier = Modifier.padding(16.dp)) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, @@ -1023,7 +1103,6 @@ fun NoteCard( Spacer(modifier = Modifier.height(12.dp)) - // Divider Divider( color = Color(0xFF334155), thickness = 1.dp @@ -2442,4 +2521,5 @@ fun EmptyState( ) } } -} \ No newline at end of file +} + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8169e4b..f222f63 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agp = "8.13.1" +agp = "8.13.2" kotlin = "2.0.21" coreKtx = "1.10.1" junit = "4.13.2"