Compare commits
2 Commits
b264f87b14
...
05b7a2a71b
| Author | SHA1 | Date | |
|---|---|---|---|
| 05b7a2a71b | |||
| 7a67943800 |
@ -199,13 +199,9 @@ fun NotesApp() {
|
||||
"trash" -> "Sampah"
|
||||
else -> "AI Notes"
|
||||
},
|
||||
showBackButton = (selectedCategory != null && currentScreen == "main") || currentScreen == "starred",
|
||||
showBackButton = (selectedCategory != null && currentScreen == "main"),
|
||||
onBackClick = {
|
||||
if (currentScreen == "starred") {
|
||||
currentScreen = "main"
|
||||
} else {
|
||||
selectedCategory = null
|
||||
}
|
||||
selectedCategory = null
|
||||
},
|
||||
onMenuClick = { drawerState = !drawerState },
|
||||
onSearchClick = { showSearch = !showSearch },
|
||||
@ -354,6 +350,16 @@ fun NotesApp() {
|
||||
it
|
||||
}
|
||||
}
|
||||
},
|
||||
onNoteEdit = { note ->
|
||||
editingNote = note
|
||||
showNoteDialog = true
|
||||
},
|
||||
onNoteDelete = { note ->
|
||||
notes = notes.map {
|
||||
if (it.id == note.id) it.copy(isDeleted = true)
|
||||
else it
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@ -392,8 +398,6 @@ fun NotesApp() {
|
||||
fullScreenNote = note
|
||||
showFullScreenNote = true
|
||||
},
|
||||
onMenuClick = { drawerState = true },
|
||||
onBack = { currentScreen = "main" },
|
||||
onUnpin = { note ->
|
||||
notes = notes.map {
|
||||
if (it.id == note.id) it.copy(isPinned = false)
|
||||
|
||||
@ -4,6 +4,7 @@ import androidx.compose.animation.*
|
||||
import androidx.compose.animation.core.*
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
@ -14,6 +15,7 @@ import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
@ -34,113 +36,141 @@ fun ModernTopBar(
|
||||
onSearchQueryChange: (String) -> Unit,
|
||||
showSearch: Boolean
|
||||
) {
|
||||
// Smooth transition for search bar
|
||||
AnimatedContent(
|
||||
targetState = showSearch,
|
||||
transitionSpec = {
|
||||
fadeIn(animationSpec = tween(Constants.ANIMATION_DURATION_MEDIUM)) togetherWith
|
||||
fadeOut(animationSpec = tween(Constants.ANIMATION_DURATION_MEDIUM))
|
||||
},
|
||||
label = "topbar"
|
||||
) { isSearching ->
|
||||
if (isSearching) {
|
||||
// Search Mode - Minimalist
|
||||
Surface(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.shadow(Constants.Elevation.Small.dp),
|
||||
color = AppColors.Surface
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = Constants.Spacing.Medium.dp, vertical = Constants.Spacing.Small.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
// Search TextField
|
||||
TextField(
|
||||
value = searchQuery,
|
||||
onValueChange = onSearchQueryChange,
|
||||
placeholder = {
|
||||
Text(
|
||||
"Cari catatan atau kategori...",
|
||||
color = AppColors.OnSurfaceVariant,
|
||||
fontSize = 15.sp
|
||||
)
|
||||
},
|
||||
colors = TextFieldDefaults.colors(
|
||||
focusedContainerColor = AppColors.SurfaceVariant,
|
||||
unfocusedContainerColor = AppColors.SurfaceVariant,
|
||||
focusedTextColor = AppColors.OnBackground,
|
||||
unfocusedTextColor = AppColors.OnSurface,
|
||||
cursorColor = AppColors.Primary,
|
||||
focusedIndicatorColor = Color.Transparent,
|
||||
unfocusedIndicatorColor = Color.Transparent
|
||||
),
|
||||
// Floating Top Bar with same style as Bottom Bar
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||
) {
|
||||
Surface(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.shadow(
|
||||
elevation = Constants.Elevation.Large.dp,
|
||||
shape = RoundedCornerShape(Constants.Radius.ExtraLarge.dp)
|
||||
),
|
||||
color = AppColors.SurfaceElevated,
|
||||
shape = RoundedCornerShape(Constants.Radius.ExtraLarge.dp)
|
||||
) {
|
||||
// Smooth transition for search bar
|
||||
AnimatedContent(
|
||||
targetState = showSearch,
|
||||
transitionSpec = {
|
||||
fadeIn(animationSpec = tween(Constants.ANIMATION_DURATION_MEDIUM)) togetherWith
|
||||
fadeOut(animationSpec = tween(Constants.ANIMATION_DURATION_MEDIUM))
|
||||
},
|
||||
label = "topbar"
|
||||
) { isSearching ->
|
||||
if (isSearching) {
|
||||
// Search Mode
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.heightIn(min = 48.dp),
|
||||
shape = RoundedCornerShape(Constants.Radius.Medium.dp),
|
||||
singleLine = true,
|
||||
textStyle = LocalTextStyle.current.copy(fontSize = 15.sp)
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.width(Constants.Spacing.Small.dp))
|
||||
|
||||
// Close Search Button
|
||||
IconButton(
|
||||
onClick = {
|
||||
onSearchQueryChange("")
|
||||
onSearchClick()
|
||||
}
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 12.dp, vertical = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Close,
|
||||
contentDescription = "Close Search",
|
||||
tint = AppColors.OnSurfaceVariant
|
||||
// Search TextField
|
||||
OutlinedTextField(
|
||||
value = searchQuery,
|
||||
onValueChange = onSearchQueryChange,
|
||||
placeholder = {
|
||||
Text(
|
||||
"Cari...",
|
||||
color = AppColors.OnSurfaceVariant,
|
||||
fontSize = 15.sp
|
||||
)
|
||||
},
|
||||
colors = OutlinedTextFieldDefaults.colors(
|
||||
focusedContainerColor = AppColors.SurfaceVariant,
|
||||
unfocusedContainerColor = AppColors.SurfaceVariant,
|
||||
focusedTextColor = AppColors.OnBackground,
|
||||
unfocusedTextColor = AppColors.OnSurface,
|
||||
cursorColor = AppColors.Primary,
|
||||
focusedBorderColor = AppColors.Primary,
|
||||
unfocusedBorderColor = Color.Transparent
|
||||
),
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.heightIn(min = 48.dp),
|
||||
shape = RoundedCornerShape(Constants.Radius.Large.dp),
|
||||
singleLine = true,
|
||||
textStyle = LocalTextStyle.current.copy(fontSize = 15.sp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Normal Mode - Minimalist
|
||||
Surface(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.shadow(Constants.Elevation.Small.dp),
|
||||
color = AppColors.Surface
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = Constants.Spacing.Small.dp, vertical = Constants.Spacing.Small.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
// Back/Menu Button
|
||||
IconButton(onClick = if (showBackButton) onBackClick else onMenuClick) {
|
||||
Icon(
|
||||
if (showBackButton) Icons.AutoMirrored.Filled.ArrowBack else Icons.Default.Menu,
|
||||
contentDescription = if (showBackButton) "Back" else "Menu",
|
||||
tint = AppColors.OnSurface
|
||||
)
|
||||
}
|
||||
|
||||
// Title
|
||||
Text(
|
||||
title,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 20.sp,
|
||||
color = AppColors.OnBackground,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
// Close Search Button
|
||||
IconButton(
|
||||
onClick = {
|
||||
onSearchQueryChange("")
|
||||
onSearchClick()
|
||||
},
|
||||
modifier = Modifier
|
||||
.size(40.dp)
|
||||
.clip(CircleShape)
|
||||
.background(AppColors.SurfaceVariant)
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Close,
|
||||
contentDescription = "Close Search",
|
||||
tint = AppColors.OnSurfaceVariant,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Normal Mode
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 12.dp, vertical = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
// Back/Menu Button
|
||||
IconButton(
|
||||
onClick = if (showBackButton) onBackClick else onMenuClick,
|
||||
modifier = Modifier
|
||||
.size(40.dp)
|
||||
.clip(CircleShape)
|
||||
.background(
|
||||
if (showBackButton) AppColors.SurfaceVariant
|
||||
else AppColors.Primary.copy(alpha = 0.1f)
|
||||
)
|
||||
) {
|
||||
Icon(
|
||||
if (showBackButton) Icons.AutoMirrored.Filled.ArrowBack else Icons.Default.Menu,
|
||||
contentDescription = if (showBackButton) "Back" else "Menu",
|
||||
tint = if (showBackButton) AppColors.OnSurface else AppColors.Primary,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
}
|
||||
|
||||
// Search Button
|
||||
IconButton(onClick = onSearchClick) {
|
||||
Icon(
|
||||
Icons.Default.Search,
|
||||
contentDescription = "Search",
|
||||
tint = AppColors.OnSurfaceVariant
|
||||
// Title
|
||||
Text(
|
||||
title,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 18.sp,
|
||||
color = AppColors.OnBackground,
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(horizontal = 12.dp)
|
||||
)
|
||||
|
||||
// Search Button
|
||||
IconButton(
|
||||
onClick = onSearchClick,
|
||||
modifier = Modifier
|
||||
.size(40.dp)
|
||||
.clip(CircleShape)
|
||||
.background(AppColors.SurfaceVariant)
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Search,
|
||||
contentDescription = "Search",
|
||||
tint = AppColors.OnSurfaceVariant,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalClipboardManager
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
@ -22,6 +23,7 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.example.notesai.config.APIKey
|
||||
import com.example.notesai.data.local.DataStoreManager
|
||||
import com.example.notesai.data.model.*
|
||||
import com.example.notesai.util.Constants
|
||||
@ -35,7 +37,6 @@ import com.example.notesai.presentation.screens.ai.components.ChatHistoryDrawer
|
||||
import com.example.notesai.presentation.screens.ai.components.CompactStatItem
|
||||
import com.example.notesai.presentation.screens.ai.components.SuggestionChip
|
||||
import com.example.notesai.util.AppColors
|
||||
import com.example.notesai.config.APIKey
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
|
||||
@ -27,7 +27,9 @@ fun MainScreen(
|
||||
onNoteClick: (Note) -> Unit,
|
||||
onPinToggle: (Note) -> Unit,
|
||||
onCategoryDelete: (Category) -> Unit,
|
||||
onCategoryEdit: (Category, String, Long, Long) -> Unit
|
||||
onCategoryEdit: (Category, String, Long, Long) -> Unit,
|
||||
onNoteEdit: (Note) -> Unit = {},
|
||||
onNoteDelete: (Note) -> Unit = {}
|
||||
) {
|
||||
Column(modifier = Modifier.fillMaxSize()) {
|
||||
if (selectedCategory == null) {
|
||||
@ -120,7 +122,9 @@ fun MainScreen(
|
||||
NoteCard(
|
||||
note = note,
|
||||
onClick = { onNoteClick(note) },
|
||||
onPinClick = { onPinToggle(note) }
|
||||
onPinClick = { onPinToggle(note) },
|
||||
onEdit = { onNoteEdit(note) },
|
||||
onDelete = { onNoteDelete(note) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,11 +3,12 @@ package com.example.notesai.presentation.screens.main.components
|
||||
|
||||
import androidx.compose.animation.core.*
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Star
|
||||
import androidx.compose.material.icons.filled.*
|
||||
import androidx.compose.material.icons.outlined.StarBorder
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
@ -30,9 +31,13 @@ import java.util.*
|
||||
fun NoteCard(
|
||||
note: Note,
|
||||
onClick: () -> Unit,
|
||||
onPinClick: () -> Unit
|
||||
onPinClick: () -> Unit,
|
||||
onEdit: () -> Unit = {},
|
||||
onDelete: () -> Unit = {}
|
||||
) {
|
||||
val dateFormat = SimpleDateFormat("dd MMM, HH:mm", Locale("id", "ID"))
|
||||
var showMenu by remember { mutableStateOf(false) }
|
||||
var showDeleteConfirm by remember { mutableStateOf(false) }
|
||||
|
||||
// Scale animation on press
|
||||
var isPressed by remember { mutableStateOf(false) }
|
||||
@ -45,31 +50,78 @@ fun NoteCard(
|
||||
label = "scale"
|
||||
)
|
||||
|
||||
// Delete Confirmation Dialog
|
||||
if (showDeleteConfirm) {
|
||||
AlertDialog(
|
||||
onDismissRequest = { showDeleteConfirm = false },
|
||||
icon = {
|
||||
Icon(
|
||||
Icons.Default.DeleteForever,
|
||||
contentDescription = null,
|
||||
tint = AppColors.Error
|
||||
)
|
||||
},
|
||||
title = {
|
||||
Text(
|
||||
"Pindahkan ke Sampah?",
|
||||
color = AppColors.OnBackground,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
},
|
||||
text = {
|
||||
Text(
|
||||
"Catatan '${note.title}' akan dipindahkan ke sampah.",
|
||||
color = AppColors.OnSurfaceVariant
|
||||
)
|
||||
},
|
||||
confirmButton = {
|
||||
Button(
|
||||
onClick = {
|
||||
onDelete()
|
||||
showDeleteConfirm = false
|
||||
},
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = AppColors.Error
|
||||
)
|
||||
) {
|
||||
Text("Hapus", color = Color.White)
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = { showDeleteConfirm = false }) {
|
||||
Text("Batal", color = AppColors.OnSurfaceVariant)
|
||||
}
|
||||
},
|
||||
containerColor = AppColors.Surface,
|
||||
shape = RoundedCornerShape(Constants.Radius.Large.dp)
|
||||
)
|
||||
}
|
||||
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.scale(scale)
|
||||
.combinedClickable(onClick = onClick),
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
shape = RoundedCornerShape(Constants.Radius.Large.dp),
|
||||
colors = CardDefaults.cardColors(
|
||||
containerColor = AppColors.SurfaceVariant
|
||||
),
|
||||
elevation = CardDefaults.cardElevation(
|
||||
defaultElevation = 2.dp
|
||||
defaultElevation = Constants.Elevation.Small.dp
|
||||
)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp)
|
||||
.padding(Constants.Spacing.Large.dp)
|
||||
) {
|
||||
// Header: Title + Pin
|
||||
// Header: Title + Actions (Vertical)
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.Top
|
||||
) {
|
||||
// Title
|
||||
// Title - takes most space
|
||||
Text(
|
||||
note.title,
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
@ -81,17 +133,94 @@ fun NoteCard(
|
||||
fontSize = 18.sp
|
||||
)
|
||||
|
||||
// Pin Button
|
||||
IconButton(
|
||||
onClick = onPinClick,
|
||||
modifier = Modifier.size(32.dp)
|
||||
// Vertical Actions Stack
|
||||
Column(
|
||||
horizontalAlignment = Alignment.End,
|
||||
verticalArrangement = Arrangement.spacedBy(0.dp)
|
||||
) {
|
||||
Icon(
|
||||
if (note.isPinned) Icons.Filled.Star else Icons.Outlined.StarBorder,
|
||||
contentDescription = "Pin",
|
||||
tint = if (note.isPinned) AppColors.Warning else AppColors.OnSurfaceVariant,
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
// Menu Button
|
||||
Box {
|
||||
IconButton(
|
||||
onClick = { showMenu = true },
|
||||
modifier = Modifier.size(28.dp)
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.MoreVert,
|
||||
contentDescription = "Menu",
|
||||
tint = AppColors.OnSurfaceVariant,
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
}
|
||||
|
||||
DropdownMenu(
|
||||
expanded = showMenu,
|
||||
onDismissRequest = { showMenu = false },
|
||||
modifier = Modifier.background(AppColors.SurfaceElevated)
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(Constants.Spacing.Small.dp)
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Edit,
|
||||
contentDescription = null,
|
||||
tint = AppColors.Primary,
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
Text(
|
||||
"Edit Catatan",
|
||||
color = AppColors.OnSurface,
|
||||
fontSize = 14.sp
|
||||
)
|
||||
}
|
||||
},
|
||||
onClick = {
|
||||
showMenu = false
|
||||
onEdit()
|
||||
}
|
||||
)
|
||||
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(Constants.Spacing.Small.dp)
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Delete,
|
||||
contentDescription = null,
|
||||
tint = AppColors.Error,
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
Text(
|
||||
"Pindah ke Sampah",
|
||||
color = AppColors.OnSurface,
|
||||
fontSize = 14.sp
|
||||
)
|
||||
}
|
||||
},
|
||||
onClick = {
|
||||
showMenu = false
|
||||
showDeleteConfirm = true
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Pin Button
|
||||
IconButton(
|
||||
onClick = onPinClick,
|
||||
modifier = Modifier.size(28.dp)
|
||||
) {
|
||||
Icon(
|
||||
if (note.isPinned) Icons.Filled.Star else Icons.Outlined.StarBorder,
|
||||
contentDescription = "Pin",
|
||||
tint = if (note.isPinned) AppColors.Warning else AppColors.OnSurfaceVariant,
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,13 +1,16 @@
|
||||
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.fillMaxSize
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Star
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.example.notesai.presentation.components.EmptyState
|
||||
import com.example.notesai.presentation.screens.starred.components.StarredNoteCard
|
||||
@ -20,31 +23,37 @@ fun StarredNotesScreen(
|
||||
notes: List<Note>,
|
||||
categories: List<Category>,
|
||||
onNoteClick: (Note) -> Unit,
|
||||
onMenuClick: () -> Unit,
|
||||
onBack: () -> Unit,
|
||||
onUnpin: (Note) -> Unit
|
||||
) {
|
||||
val starredNotes = notes.filter { it.isPinned && !it.isArchived && !it.isDeleted }
|
||||
.sortedByDescending { it.timestamp }
|
||||
|
||||
if (starredNotes.isEmpty()) {
|
||||
EmptyState(
|
||||
icon = Icons.Default.Star,
|
||||
message = "Belum ada catatan berbintang",
|
||||
subtitle = "Catatan yang ditandai berbintang akan muncul di sini"
|
||||
)
|
||||
} else {
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
items(starredNotes) { note ->
|
||||
val category = categories.find { it.id == note.categoryId }
|
||||
StarredNoteCard(
|
||||
note = note,
|
||||
categoryName = category?.name ?: "Unknown",
|
||||
onClick = { onNoteClick(note) },
|
||||
onUnpin = { onUnpin(note) }
|
||||
)
|
||||
Column(modifier = Modifier.fillMaxSize()) {
|
||||
if (starredNotes.isEmpty()) {
|
||||
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
|
||||
),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
items(starredNotes) { note ->
|
||||
val category = categories.find { it.id == note.categoryId }
|
||||
StarredNoteCard(
|
||||
note = note,
|
||||
categoryName = category?.name ?: "Unknown",
|
||||
onClick = { onNoteClick(note) },
|
||||
onUnpin = { onUnpin(note) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user