Berikan fungsi pada fitur pencarian pada halaman file berbintang, arsip, dan sampah
This commit is contained in:
parent
2e3cb39244
commit
f0e4396da1
@ -1,12 +1,30 @@
|
||||
package com.example.notesai.presentation.screens.archive
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Archive
|
||||
import androidx.compose.material.icons.filled.Clear
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.OutlinedTextFieldDefaults
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.example.notesai.data.model.Note
|
||||
import com.example.notesai.data.model.Category
|
||||
@ -20,18 +38,90 @@ fun ArchiveScreen(
|
||||
onRestore: (Note) -> Unit,
|
||||
onDelete: (Note) -> Unit
|
||||
) {
|
||||
if (notes.isEmpty()) {
|
||||
var searchQuery by remember { mutableStateOf("") }
|
||||
|
||||
// Filter berdasarkan search query
|
||||
val filteredNotes = if (searchQuery.isBlank()) {
|
||||
notes
|
||||
} else {
|
||||
notes.filter { note ->
|
||||
note.title.contains(searchQuery, ignoreCase = true) ||
|
||||
note.content.contains(searchQuery, ignoreCase = true) ||
|
||||
note.description.contains(searchQuery, ignoreCase = true) ||
|
||||
categories.find { it.id == note.categoryId }?.name?.contains(searchQuery, ignoreCase = true) == true
|
||||
}
|
||||
}
|
||||
|
||||
Column(modifier = Modifier.fillMaxSize()) {
|
||||
// Search Bar
|
||||
OutlinedTextField(
|
||||
value = searchQuery,
|
||||
onValueChange = { searchQuery = it },
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
placeholder = {
|
||||
Text(
|
||||
"Cari catatan arsip...",
|
||||
color = Color(0xFF64748B)
|
||||
)
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
Icons.Default.Search,
|
||||
contentDescription = null,
|
||||
tint = Color(0xFF64748B)
|
||||
)
|
||||
},
|
||||
trailingIcon = {
|
||||
if (searchQuery.isNotEmpty()) {
|
||||
IconButton(onClick = { searchQuery = "" }) {
|
||||
Icon(
|
||||
Icons.Default.Clear,
|
||||
contentDescription = "Clear",
|
||||
tint = Color(0xFF64748B)
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
colors = OutlinedTextFieldDefaults.colors(
|
||||
focusedContainerColor = Color(0xFF1E293B),
|
||||
unfocusedContainerColor = Color(0xFF1E293B),
|
||||
focusedBorderColor = Color(0xFF6366F1),
|
||||
unfocusedBorderColor = Color(0xFF334155),
|
||||
focusedTextColor = Color.White,
|
||||
unfocusedTextColor = Color.White,
|
||||
cursorColor = Color(0xFF6366F1)
|
||||
),
|
||||
singleLine = true
|
||||
)
|
||||
|
||||
// Content
|
||||
if (filteredNotes.isEmpty()) {
|
||||
if (searchQuery.isNotEmpty()) {
|
||||
EmptyState(
|
||||
icon = Icons.Default.Search,
|
||||
message = "Tidak ada hasil",
|
||||
subtitle = "Coba kata kunci lain"
|
||||
)
|
||||
} else {
|
||||
EmptyState(
|
||||
icon = Icons.Default.Archive,
|
||||
message = "Arsip kosong",
|
||||
subtitle = "Catatan yang diarsipkan akan muncul di sini"
|
||||
)
|
||||
}
|
||||
} else {
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(16.dp),
|
||||
contentPadding = PaddingValues(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 100.dp
|
||||
),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
items(notes) { note ->
|
||||
items(filteredNotes) { note ->
|
||||
val category = categories.find { it.id == note.categoryId }
|
||||
ArchiveNoteCard(
|
||||
note = note,
|
||||
@ -43,3 +133,4 @@ fun ArchiveScreen(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,14 +3,32 @@ package com.example.notesai.presentation.screens.starred
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Clear
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material.icons.filled.Star
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.OutlinedTextFieldDefaults
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.example.notesai.presentation.components.EmptyState
|
||||
import com.example.notesai.presentation.screens.starred.components.StarredNoteCard
|
||||
@ -25,27 +43,93 @@ fun StarredNotesScreen(
|
||||
onNoteClick: (Note) -> Unit,
|
||||
onUnpin: (Note) -> Unit
|
||||
) {
|
||||
val starredNotes = notes.filter { it.isPinned && !it.isArchived && !it.isDeleted }
|
||||
var searchQuery by remember { mutableStateOf("") }
|
||||
|
||||
val starredNotes = notes
|
||||
.filter { it.isPinned && !it.isArchived && !it.isDeleted }
|
||||
.sortedByDescending { it.timestamp }
|
||||
|
||||
// Filter berdasarkan search query
|
||||
val filteredNotes = if (searchQuery.isBlank()) {
|
||||
starredNotes
|
||||
} else {
|
||||
starredNotes.filter { note ->
|
||||
note.title.contains(searchQuery, ignoreCase = true) ||
|
||||
note.content.contains(searchQuery, ignoreCase = true) ||
|
||||
note.description.contains(searchQuery, ignoreCase = true)
|
||||
}
|
||||
}
|
||||
|
||||
Column(modifier = Modifier.fillMaxSize()) {
|
||||
if (starredNotes.isEmpty()) {
|
||||
// Search Bar
|
||||
OutlinedTextField(
|
||||
value = searchQuery,
|
||||
onValueChange = { searchQuery = it },
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
placeholder = {
|
||||
Text(
|
||||
"Cari catatan berbintang...",
|
||||
color = Color(0xFF64748B)
|
||||
)
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
Icons.Default.Search,
|
||||
contentDescription = null,
|
||||
tint = Color(0xFF64748B)
|
||||
)
|
||||
},
|
||||
trailingIcon = {
|
||||
if (searchQuery.isNotEmpty()) {
|
||||
IconButton(onClick = { searchQuery = "" }) {
|
||||
Icon(
|
||||
Icons.Default.Clear,
|
||||
contentDescription = "Clear",
|
||||
tint = Color(0xFF64748B)
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
colors = OutlinedTextFieldDefaults.colors(
|
||||
focusedContainerColor = Color(0xFF1E293B),
|
||||
unfocusedContainerColor = Color(0xFF1E293B),
|
||||
focusedBorderColor = Color(0xFF6366F1),
|
||||
unfocusedBorderColor = Color(0xFF334155),
|
||||
focusedTextColor = Color.White,
|
||||
unfocusedTextColor = Color.White,
|
||||
cursorColor = Color(0xFF6366F1)
|
||||
),
|
||||
singleLine = true
|
||||
)
|
||||
|
||||
// Content
|
||||
if (filteredNotes.isEmpty()) {
|
||||
if (searchQuery.isNotEmpty()) {
|
||||
EmptyState(
|
||||
icon = Icons.Default.Search,
|
||||
message = "Tidak ada hasil",
|
||||
subtitle = "Coba kata kunci lain"
|
||||
)
|
||||
} else {
|
||||
EmptyState(
|
||||
icon = Icons.Default.Star,
|
||||
message = "Belum ada catatan berbintang",
|
||||
subtitle = "Catatan yang ditandai berbintang akan muncul di sini"
|
||||
)
|
||||
}
|
||||
} else {
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
top = 16.dp,
|
||||
bottom = 100.dp // Extra space untuk bottom bar
|
||||
bottom = 100.dp
|
||||
),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
items(starredNotes) { note ->
|
||||
items(filteredNotes) { note ->
|
||||
val category = categories.find { it.id == note.categoryId }
|
||||
StarredNoteCard(
|
||||
note = note,
|
||||
|
||||
@ -1,15 +1,30 @@
|
||||
// File: presentation/screens/trash/TrashScreen.kt
|
||||
package com.example.notesai.presentation.screens.trash
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Clear
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.OutlinedTextFieldDefaults
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
@ -28,33 +43,114 @@ fun TrashScreen(
|
||||
onRestoreCategory: (Category) -> Unit,
|
||||
onDeleteCategoryPermanent: (Category) -> Unit
|
||||
) {
|
||||
var searchQuery by remember { mutableStateOf("") }
|
||||
|
||||
// Filter kategori dan note yang dihapus
|
||||
val deletedCategories = categories.filter { it.isDeleted }
|
||||
val deletedNotes = notes.filter { it.isDeleted }
|
||||
|
||||
if (deletedCategories.isEmpty() && deletedNotes.isEmpty()) {
|
||||
// Filter berdasarkan search query
|
||||
val filteredCategories = if (searchQuery.isBlank()) {
|
||||
deletedCategories
|
||||
} else {
|
||||
deletedCategories.filter { category ->
|
||||
category.name.contains(searchQuery, ignoreCase = true)
|
||||
}
|
||||
}
|
||||
|
||||
val filteredNotes = if (searchQuery.isBlank()) {
|
||||
deletedNotes
|
||||
} else {
|
||||
deletedNotes.filter { note ->
|
||||
note.title.contains(searchQuery, ignoreCase = true) ||
|
||||
note.content.contains(searchQuery, ignoreCase = true) ||
|
||||
note.description.contains(searchQuery, ignoreCase = true) ||
|
||||
categories.find { it.id == note.categoryId }?.name?.contains(searchQuery, ignoreCase = true) == true
|
||||
}
|
||||
}
|
||||
|
||||
Column(modifier = Modifier.fillMaxSize()) {
|
||||
// Search Bar
|
||||
OutlinedTextField(
|
||||
value = searchQuery,
|
||||
onValueChange = { searchQuery = it },
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
placeholder = {
|
||||
Text(
|
||||
"Cari di sampah...",
|
||||
color = Color(0xFF64748B)
|
||||
)
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
Icons.Default.Search,
|
||||
contentDescription = null,
|
||||
tint = Color(0xFF64748B)
|
||||
)
|
||||
},
|
||||
trailingIcon = {
|
||||
if (searchQuery.isNotEmpty()) {
|
||||
IconButton(onClick = { searchQuery = "" }) {
|
||||
Icon(
|
||||
Icons.Default.Clear,
|
||||
contentDescription = "Clear",
|
||||
tint = Color(0xFF64748B)
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
colors = OutlinedTextFieldDefaults.colors(
|
||||
focusedContainerColor = Color(0xFF1E293B),
|
||||
unfocusedContainerColor = Color(0xFF1E293B),
|
||||
focusedBorderColor = Color(0xFF6366F1),
|
||||
unfocusedBorderColor = Color(0xFF334155),
|
||||
focusedTextColor = Color.White,
|
||||
unfocusedTextColor = Color.White,
|
||||
cursorColor = Color(0xFF6366F1)
|
||||
),
|
||||
singleLine = true
|
||||
)
|
||||
|
||||
// Content
|
||||
if (filteredCategories.isEmpty() && filteredNotes.isEmpty()) {
|
||||
if (searchQuery.isNotEmpty()) {
|
||||
EmptyState(
|
||||
icon = Icons.Default.Search,
|
||||
message = "Tidak ada hasil",
|
||||
subtitle = "Coba kata kunci lain"
|
||||
)
|
||||
} else {
|
||||
EmptyState(
|
||||
icon = Icons.Default.Delete,
|
||||
message = "Sampah kosong",
|
||||
subtitle = "Kategori dan catatan yang dihapus akan muncul di sini"
|
||||
)
|
||||
}
|
||||
} else {
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(16.dp),
|
||||
contentPadding = PaddingValues(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 100.dp
|
||||
),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
// Section: Kategori Terhapus
|
||||
if (deletedCategories.isNotEmpty()) {
|
||||
if (filteredCategories.isNotEmpty()) {
|
||||
item {
|
||||
Text(
|
||||
"Kategori Terhapus (${deletedCategories.size})",
|
||||
"Kategori Terhapus (${filteredCategories.size})",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = Color(0xFF94A3B8)
|
||||
color = Color(0xFF94A3B8),
|
||||
modifier = Modifier.padding(vertical = 8.dp)
|
||||
)
|
||||
}
|
||||
|
||||
items(deletedCategories) { category ->
|
||||
items(filteredCategories) { category ->
|
||||
val notesInCategory = notes.count {
|
||||
it.categoryId == category.id && it.isDeleted
|
||||
}
|
||||
@ -68,17 +164,18 @@ fun TrashScreen(
|
||||
}
|
||||
|
||||
// Section: Catatan Terhapus
|
||||
if (deletedNotes.isNotEmpty()) {
|
||||
if (filteredNotes.isNotEmpty()) {
|
||||
item {
|
||||
Text(
|
||||
"Catatan Terhapus (${deletedNotes.size})",
|
||||
"Catatan Terhapus (${filteredNotes.size})",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = Color(0xFF94A3B8)
|
||||
color = Color(0xFF94A3B8),
|
||||
modifier = Modifier.padding(vertical = 8.dp)
|
||||
)
|
||||
}
|
||||
|
||||
items(deletedNotes) { note ->
|
||||
items(filteredNotes) { note ->
|
||||
val category = categories.find { it.id == note.categoryId }
|
||||
TrashNoteCard(
|
||||
note = note,
|
||||
@ -91,3 +188,4 @@ fun TrashScreen(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user