diff --git a/app/src/main/java/com/yovinchen/bookkeeping/ui/components/DateTimePicker.kt b/app/src/main/java/com/yovinchen/bookkeeping/ui/components/DateTimePicker.kt index 55be6f3..d87cf8f 100644 --- a/app/src/main/java/com/yovinchen/bookkeeping/ui/components/DateTimePicker.kt +++ b/app/src/main/java/com/yovinchen/bookkeeping/ui/components/DateTimePicker.kt @@ -7,6 +7,7 @@ import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog import java.time.LocalDateTime import java.time.format.DateTimeFormatter @@ -19,6 +20,7 @@ fun DateTimePicker( ) { var showDatePicker by remember { mutableStateOf(false) } var showTimePicker by remember { mutableStateOf(false) } + var tempDateTime by remember { mutableStateOf(selectedDateTime) } val dateFormatter = remember { DateTimeFormatter.ofPattern("yyyy年MM月dd日") } val timeFormatter = remember { DateTimeFormatter.ofPattern("HH:mm") } @@ -55,96 +57,109 @@ fun DateTimePicker( // 日期选择器对话框 if (showDatePicker) { - val datePickerState = rememberDatePickerState( - initialSelectedDateMillis = selectedDateTime - .toLocalDate() - .atStartOfDay() - .toInstant(java.time.ZoneOffset.UTC) - .toEpochMilli() - ) - - DatePickerDialog( - onDismissRequest = { showDatePicker = false }, - confirmButton = { - TextButton( - onClick = { - datePickerState.selectedDateMillis?.let { millis -> - val newDate = java.time.Instant.ofEpochMilli(millis) - .atZone(java.time.ZoneOffset.UTC) - .toLocalDate() - val newDateTime = newDate.atTime( - selectedDateTime.hour, - selectedDateTime.minute - ) - onDateTimeSelected(newDateTime) - } - showDatePicker = false - } + Dialog(onDismissRequest = { showDatePicker = false }) { + Surface( + modifier = Modifier + .fillMaxWidth() + .wrapContentHeight(), + shape = MaterialTheme.shapes.extraLarge, + tonalElevation = 6.dp + ) { + Column( + modifier = Modifier.padding(16.dp) ) { - Text("确定") - } - }, - dismissButton = { - TextButton(onClick = { showDatePicker = false }) { - Text("取消") + val datePickerState = rememberDatePickerState( + initialSelectedDateMillis = selectedDateTime + .toLocalDate() + .atStartOfDay() + .toInstant(java.time.ZoneOffset.UTC) + .toEpochMilli() + ) + + DatePicker( + state = datePickerState, + showModeToggle = false + ) + + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 16.dp), + horizontalArrangement = Arrangement.End + ) { + TextButton(onClick = { showDatePicker = false }) { + Text("取消") + } + Spacer(modifier = Modifier.width(8.dp)) + Button( + onClick = { + datePickerState.selectedDateMillis?.let { millis -> + val newDate = java.time.Instant.ofEpochMilli(millis) + .atZone(java.time.ZoneOffset.UTC) + .toLocalDate() + val newDateTime = newDate.atTime( + selectedDateTime.hour, + selectedDateTime.minute + ) + onDateTimeSelected(newDateTime) + } + showDatePicker = false + } + ) { + Text("确定") + } + } } } - ) { - DatePicker( - state = datePickerState, - showModeToggle = false, - modifier = Modifier.padding(16.dp) - ) } } // 时间选择器对话框 if (showTimePicker) { - val timePickerState = rememberTimePickerState( - initialHour = selectedDateTime.hour, - initialMinute = selectedDateTime.minute - ) - - TimePickerDialog( - onDismissRequest = { showTimePicker = false }, - confirmButton = { - TextButton( - onClick = { - val newDateTime = selectedDateTime - .withHour(timePickerState.hour) - .withMinute(timePickerState.minute) - onDateTimeSelected(newDateTime) - showTimePicker = false - } + Dialog(onDismissRequest = { showTimePicker = false }) { + Surface( + modifier = Modifier + .fillMaxWidth() + .wrapContentHeight(), + shape = MaterialTheme.shapes.extraLarge, + tonalElevation = 6.dp + ) { + Column( + modifier = Modifier.padding(16.dp) ) { - Text("确定") - } - }, - dismissButton = { - TextButton(onClick = { showTimePicker = false }) { - Text("取消") + val timePickerState = rememberTimePickerState( + initialHour = selectedDateTime.hour, + initialMinute = selectedDateTime.minute + ) + + TimePicker( + state = timePickerState + ) + + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 16.dp), + horizontalArrangement = Arrangement.End + ) { + TextButton(onClick = { showTimePicker = false }) { + Text("取消") + } + Spacer(modifier = Modifier.width(8.dp)) + Button( + onClick = { + val newDateTime = selectedDateTime + .withHour(timePickerState.hour) + .withMinute(timePickerState.minute) + onDateTimeSelected(newDateTime) + showTimePicker = false + } + ) { + Text("确定") + } + } } } - ) { - TimePicker( - state = timePickerState, - modifier = Modifier.padding(16.dp) - ) } } } - -@Composable -private fun TimePickerDialog( - onDismissRequest: () -> Unit, - confirmButton: @Composable () -> Unit, - dismissButton: @Composable () -> Unit, - content: @Composable () -> Unit -) { - AlertDialog( - onDismissRequest = onDismissRequest, - confirmButton = confirmButton, - dismissButton = dismissButton, - text = { content() } - ) -} diff --git a/app/src/main/java/com/yovinchen/bookkeeping/ui/dialog/RecordEditDialog.kt b/app/src/main/java/com/yovinchen/bookkeeping/ui/dialog/RecordEditDialog.kt index 0094fd7..5a4676c 100644 --- a/app/src/main/java/com/yovinchen/bookkeeping/ui/dialog/RecordEditDialog.kt +++ b/app/src/main/java/com/yovinchen/bookkeeping/ui/dialog/RecordEditDialog.kt @@ -7,8 +7,13 @@ import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog import com.yovinchen.bookkeeping.model.BookkeepingRecord import com.yovinchen.bookkeeping.model.Category +import com.yovinchen.bookkeeping.ui.components.DateTimePicker +import java.time.Instant +import java.time.LocalDateTime +import java.time.ZoneId import java.util.Date @Composable @@ -21,17 +26,45 @@ fun RecordEditDialog( var amount by remember { mutableStateOf(record.amount.toString()) } var selectedCategory by remember { mutableStateOf(record.category) } var description by remember { mutableStateOf(record.description) } + var expanded by remember { mutableStateOf(false) } + var selectedDateTime by remember { + mutableStateOf( + LocalDateTime.ofInstant( + Instant.ofEpochMilli(record.date.time), + ZoneId.systemDefault() + ) + ) + } - AlertDialog( - onDismissRequest = onDismiss, - title = { Text("编辑记录") }, - text = { + Dialog(onDismissRequest = onDismiss) { + Card( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + elevation = CardDefaults.cardElevation(defaultElevation = 8.dp) + ) { Column( modifier = Modifier .fillMaxWidth() - .padding(16.dp), - verticalArrangement = Arrangement.spacedBy(8.dp) + .padding(16.dp) ) { + Text( + text = "编辑记录", + style = MaterialTheme.typography.titleLarge + ) + + Spacer(modifier = Modifier.height(16.dp)) + + // 日期时间选择 + DateTimePicker( + selectedDateTime = selectedDateTime, + onDateTimeSelected = { selectedDateTime = it }, + modifier = Modifier.fillMaxWidth() + ) + + Spacer(modifier = Modifier.height(16.dp)) + + // 金额输入 OutlinedTextField( value = amount, onValueChange = { amount = it }, @@ -39,6 +72,41 @@ fun RecordEditDialog( modifier = Modifier.fillMaxWidth() ) + Spacer(modifier = Modifier.height(8.dp)) + + // 类别选择 + ExposedDropdownMenuBox( + expanded = expanded, + onExpandedChange = { expanded = it } + ) { + OutlinedTextField( + value = selectedCategory, + onValueChange = {}, + readOnly = true, + label = { Text("类别") }, + modifier = Modifier + .fillMaxWidth() + .menuAnchor() + ) + ExposedDropdownMenu( + expanded = expanded, + onDismissRequest = { expanded = false } + ) { + categories.filter { it.type == record.type }.forEach { category -> + DropdownMenuItem( + text = { Text(category.name) }, + onClick = { + selectedCategory = category.name + expanded = false + } + ) + } + } + } + + Spacer(modifier = Modifier.height(8.dp)) + + // 描述输入 OutlinedTextField( value = description, onValueChange = { description = it }, @@ -46,52 +114,33 @@ fun RecordEditDialog( modifier = Modifier.fillMaxWidth() ) - ExposedDropdownMenuBox( - expanded = false, - onExpandedChange = {}, - ) { - OutlinedTextField( - value = selectedCategory, - onValueChange = {}, - readOnly = true, - label = { Text("类别") }, - modifier = Modifier.fillMaxWidth() - ) + Spacer(modifier = Modifier.height(16.dp)) - DropdownMenu( - expanded = false, - onDismissRequest = { }, - ) { - categories.filter { it.type == record.type }.forEach { category -> - DropdownMenuItem( - text = { Text(category.name) }, - onClick = { selectedCategory = category.name } + // 按钮 + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End + ) { + TextButton(onClick = onDismiss) { + Text("取消") + } + Spacer(modifier = Modifier.width(8.dp)) + Button( + onClick = { + val updatedRecord = record.copy( + amount = amount.toDoubleOrNull() ?: record.amount, + category = selectedCategory, + description = description, + date = Date.from(selectedDateTime.atZone(ZoneId.systemDefault()).toInstant()) ) + onConfirm(updatedRecord) + onDismiss() } + ) { + Text("确定") } } } - }, - confirmButton = { - TextButton( - onClick = { - val updatedRecord = record.copy( - amount = amount.toDoubleOrNull() ?: record.amount, - category = selectedCategory, - description = description, - date = Date() - ) - onConfirm(updatedRecord) - onDismiss() - } - ) { - Text("确认") - } - }, - dismissButton = { - TextButton(onClick = onDismiss) { - Text("取消") - } } - ) + } }