This commit is contained in:
202310715297 RAIHAN ARIQ MUZAKKI 2025-12-18 11:38:33 +07:00
parent da93991ef3
commit 520da1f66a
3 changed files with 173 additions and 175 deletions

View File

@ -47,6 +47,7 @@ import com.example.notesai.util.AppColors
import com.example.notesai.util.Constants import com.example.notesai.util.Constants
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -511,4 +512,5 @@ fun NotesApp() {
) )
} }
} }
} }

View File

@ -1,147 +1,148 @@
// File: presentation/dialogs/CategoryDialog.kt // File: presentation/dialogs/CategoryDialog.kt
package com.example.notesai.presentation.dialogs package com.example.notesai.presentation.dialogs
import androidx.compose.animation.* import androidx.compose.animation.*
import androidx.compose.animation.core.* import androidx.compose.animation.core.*
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check import androidx.compose.material.icons.filled.Check
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.example.notesai.util.AppColors import com.example.notesai.util.AppColors
import com.example.notesai.util.Constants import com.example.notesai.util.Constants
@Composable @Composable
fun CategoryDialog( fun CategoryDialog(
onDismiss: () -> Unit, onDismiss: () -> Unit,
onSave: (String, Long, Long) -> Unit onSave: (String, Long, Long) -> Unit
) { ) {
var name by remember { mutableStateOf("") } var name by remember { mutableStateOf("") }
var selectedGradient by remember { mutableStateOf(0) } var selectedGradient by remember { mutableStateOf(0) }
AlertDialog( AlertDialog(
onDismissRequest = onDismiss, onDismissRequest = onDismiss,
containerColor = AppColors.Surface, containerColor = AppColors.Surface,
shape = RoundedCornerShape(20.dp), shape = RoundedCornerShape(20.dp),
title = { title = {
Text( Text(
"Buat Kategori Baru", "Buat Kategori Baru",
color = AppColors.OnBackground, color = AppColors.OnBackground,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
fontSize = 20.sp fontSize = 20.sp
)
},
text = {
Column(
verticalArrangement = Arrangement.spacedBy(20.dp)
) {
// Input Nama
OutlinedTextField(
value = name,
onValueChange = { name = it },
label = {
Text(
"Nama Kategori",
color = AppColors.OnSurfaceVariant
)
},
placeholder = {
Text(
"Contoh: Pekerjaan, Personal",
color = AppColors.OnSurfaceTertiary,
fontSize = 14.sp
)
},
modifier = Modifier.fillMaxWidth(),
colors = OutlinedTextFieldDefaults.colors(
focusedTextColor = AppColors.OnBackground,
unfocusedTextColor = AppColors.OnSurface,
focusedContainerColor = AppColors.SurfaceVariant,
unfocusedContainerColor = AppColors.SurfaceVariant,
cursorColor = AppColors.Primary,
focusedBorderColor = AppColors.Primary,
unfocusedBorderColor = Color.Transparent
),
shape = RoundedCornerShape(12.dp),
singleLine = true
) )
},
// Gradient Selector text = {
Column( Column(
verticalArrangement = Arrangement.spacedBy(12.dp) verticalArrangement = Arrangement.spacedBy(20.dp)
) { ) {
Text( // Input Nama
"Pilih Warna:", OutlinedTextField(
style = MaterialTheme.typography.bodyMedium, value = name,
color = AppColors.OnSurface, onValueChange = { name = it },
fontWeight = FontWeight.SemiBold, label = {
fontSize = 14.sp Text(
"Nama Kategori",
color = AppColors.OnSurfaceVariant
)
},
placeholder = {
Text(
"Contoh: Pekerjaan, Personal",
color = AppColors.OnSurfaceTertiary,
fontSize = 14.sp
)
},
modifier = Modifier.fillMaxWidth(),
colors = OutlinedTextFieldDefaults.colors(
focusedTextColor = AppColors.OnBackground,
unfocusedTextColor = AppColors.OnSurface,
focusedContainerColor = AppColors.SurfaceVariant,
unfocusedContainerColor = AppColors.SurfaceVariant,
cursorColor = AppColors.Primary,
focusedBorderColor = AppColors.Primary,
unfocusedBorderColor = Color.Transparent
),
shape = RoundedCornerShape(12.dp),
singleLine = true
) )
Constants.CategoryColors.chunked(4).forEach { row -> // Gradient Selector
Row( Column(
modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(12.dp)
horizontalArrangement = Arrangement.spacedBy(8.dp) ) {
) { Text(
row.forEach { gradient -> "Pilih Warna:",
val globalIndex = Constants.CategoryColors.indexOf(gradient) style = MaterialTheme.typography.bodyMedium,
val isSelected = selectedGradient == globalIndex color = AppColors.OnSurface,
fontWeight = FontWeight.SemiBold,
fontSize = 14.sp
)
// Scale animation Constants.CategoryColors.chunked(4).forEach { row ->
val scale by animateFloatAsState( Row(
targetValue = if (isSelected) 1.1f else 1f, modifier = Modifier.fillMaxWidth(),
animationSpec = spring( horizontalArrangement = Arrangement.spacedBy(8.dp)
dampingRatio = Spring.DampingRatioMediumBouncy, ) {
stiffness = Spring.StiffnessMedium row.forEach { gradient ->
), val globalIndex = Constants.CategoryColors.indexOf(gradient)
label = "scale" val isSelected = selectedGradient == globalIndex
)
Box( // Scale animation
modifier = Modifier val scale by animateFloatAsState(
.weight(1f) targetValue = if (isSelected) 1.1f else 1f,
.aspectRatio(1f) animationSpec = spring(
.clip(RoundedCornerShape(12.dp)) dampingRatio = Spring.DampingRatioMediumBouncy,
.background( stiffness = Spring.StiffnessMedium
brush = Brush.linearGradient( ),
colors = listOf( label = "scale"
Color(gradient.first), )
Color(gradient.second)
Box(
modifier = Modifier
.weight(1f)
.aspectRatio(1f)
.clip(RoundedCornerShape(12.dp))
.background(
brush = Brush.linearGradient(
colors = listOf(
Color(gradient.first),
Color(gradient.second)
)
) )
) )
) .clickable { selectedGradient = globalIndex },
.clickable { selectedGradient = globalIndex }, contentAlignment = Alignment.Center
contentAlignment = Alignment.Center
) {
// Check icon dengan animation
this@Row.AnimatedVisibility(
visible = isSelected,
enter = scaleIn() + fadeIn(),
exit = scaleOut() + fadeOut()
) { ) {
Surface( // Check icon dengan animation
color = Color.White.copy(alpha = 0.9f), this@Row.AnimatedVisibility(
shape = RoundedCornerShape(8.dp) visible = isSelected,
enter = scaleIn() + fadeIn(),
exit = scaleOut() + fadeOut()
) { ) {
Icon( Surface(
Icons.Default.Check, color = Color.White.copy(alpha = 0.9f),
contentDescription = null, shape = RoundedCornerShape(8.dp)
tint = Color(gradient.first), ) {
modifier = Modifier Icon(
.padding(6.dp) Icons.Default.Check,
.size(20.dp) contentDescription = null,
) tint = Color(gradient.first),
modifier = Modifier
.padding(6.dp)
.size(20.dp)
)
}
} }
} }
} }
@ -149,44 +150,43 @@ fun CategoryDialog(
} }
} }
} }
},
confirmButton = {
Button(
onClick = {
if (name.isNotBlank()) {
val gradient = Constants.CategoryColors[selectedGradient]
onSave(name, gradient.first, gradient.second)
}
},
enabled = name.isNotBlank(),
colors = ButtonDefaults.buttonColors(
containerColor = AppColors.Primary,
disabledContainerColor = AppColors.Primary.copy(alpha = 0.5f)
),
shape = RoundedCornerShape(12.dp),
modifier = Modifier.height(48.dp)
) {
Text(
"Simpan",
color = Color.White,
fontWeight = FontWeight.Bold,
fontSize = 15.sp
)
}
},
dismissButton = {
TextButton(
onClick = onDismiss,
shape = RoundedCornerShape(12.dp),
modifier = Modifier.height(48.dp)
) {
Text(
"Batal",
color = AppColors.OnSurfaceVariant,
fontSize = 15.sp
)
}
} }
}, )
confirmButton = { }
Button(
onClick = {
if (name.isNotBlank()) {
val gradient = Constants.CategoryColors[selectedGradient]
onSave(name, gradient.first, gradient.second)
}
},
enabled = name.isNotBlank(),
colors = ButtonDefaults.buttonColors(
containerColor = AppColors.Primary,
disabledContainerColor = AppColors.Primary.copy(alpha = 0.5f)
),
shape = RoundedCornerShape(12.dp),
modifier = Modifier.height(48.dp)
) {
Text(
"Simpan",
color = Color.White,
fontWeight = FontWeight.Bold,
fontSize = 15.sp
)
}
},
dismissButton = {
TextButton(
onClick = onDismiss,
shape = RoundedCornerShape(12.dp),
modifier = Modifier.height(48.dp)
) {
Text(
"Batal",
color = AppColors.OnSurfaceVariant,
fontSize = 15.sp
)
}
}
)
}

View File

@ -1,4 +0,0 @@
package com.example.notesai.util
class COba {
}