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 kotlinx.coroutines.launch
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -511,4 +512,5 @@ fun NotesApp() {
)
}
}
}
}

View File

@ -1,147 +1,148 @@
// File: presentation/dialogs/CategoryDialog.kt
package com.example.notesai.presentation.dialogs
// File: presentation/dialogs/CategoryDialog.kt
package com.example.notesai.presentation.dialogs
import androidx.compose.animation.*
import androidx.compose.animation.core.*
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.notesai.util.AppColors
import com.example.notesai.util.Constants
import androidx.compose.animation.*
import androidx.compose.animation.core.*
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.notesai.util.AppColors
import com.example.notesai.util.Constants
@Composable
fun CategoryDialog(
onDismiss: () -> Unit,
onSave: (String, Long, Long) -> Unit
) {
var name by remember { mutableStateOf("") }
var selectedGradient by remember { mutableStateOf(0) }
@Composable
fun CategoryDialog(
onDismiss: () -> Unit,
onSave: (String, Long, Long) -> Unit
) {
var name by remember { mutableStateOf("") }
var selectedGradient by remember { mutableStateOf(0) }
AlertDialog(
onDismissRequest = onDismiss,
containerColor = AppColors.Surface,
shape = RoundedCornerShape(20.dp),
title = {
Text(
"Buat Kategori Baru",
color = AppColors.OnBackground,
fontWeight = FontWeight.Bold,
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
AlertDialog(
onDismissRequest = onDismiss,
containerColor = AppColors.Surface,
shape = RoundedCornerShape(20.dp),
title = {
Text(
"Buat Kategori Baru",
color = AppColors.OnBackground,
fontWeight = FontWeight.Bold,
fontSize = 20.sp
)
// Gradient Selector
},
text = {
Column(
verticalArrangement = Arrangement.spacedBy(12.dp)
verticalArrangement = Arrangement.spacedBy(20.dp)
) {
Text(
"Pilih Warna:",
style = MaterialTheme.typography.bodyMedium,
color = AppColors.OnSurface,
fontWeight = FontWeight.SemiBold,
fontSize = 14.sp
// 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
)
Constants.CategoryColors.chunked(4).forEach { row ->
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
row.forEach { gradient ->
val globalIndex = Constants.CategoryColors.indexOf(gradient)
val isSelected = selectedGradient == globalIndex
// Gradient Selector
Column(
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
Text(
"Pilih Warna:",
style = MaterialTheme.typography.bodyMedium,
color = AppColors.OnSurface,
fontWeight = FontWeight.SemiBold,
fontSize = 14.sp
)
// Scale animation
val scale by animateFloatAsState(
targetValue = if (isSelected) 1.1f else 1f,
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessMedium
),
label = "scale"
)
Constants.CategoryColors.chunked(4).forEach { row ->
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
row.forEach { gradient ->
val globalIndex = Constants.CategoryColors.indexOf(gradient)
val isSelected = selectedGradient == globalIndex
Box(
modifier = Modifier
.weight(1f)
.aspectRatio(1f)
.clip(RoundedCornerShape(12.dp))
.background(
brush = Brush.linearGradient(
colors = listOf(
Color(gradient.first),
Color(gradient.second)
// Scale animation
val scale by animateFloatAsState(
targetValue = if (isSelected) 1.1f else 1f,
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessMedium
),
label = "scale"
)
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 },
contentAlignment = Alignment.Center
) {
// Check icon dengan animation
this@Row.AnimatedVisibility(
visible = isSelected,
enter = scaleIn() + fadeIn(),
exit = scaleOut() + fadeOut()
.clickable { selectedGradient = globalIndex },
contentAlignment = Alignment.Center
) {
Surface(
color = Color.White.copy(alpha = 0.9f),
shape = RoundedCornerShape(8.dp)
// Check icon dengan animation
this@Row.AnimatedVisibility(
visible = isSelected,
enter = scaleIn() + fadeIn(),
exit = scaleOut() + fadeOut()
) {
Icon(
Icons.Default.Check,
contentDescription = null,
tint = Color(gradient.first),
modifier = Modifier
.padding(6.dp)
.size(20.dp)
)
Surface(
color = Color.White.copy(alpha = 0.9f),
shape = RoundedCornerShape(8.dp)
) {
Icon(
Icons.Default.Check,
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 {
}