From 411b4923877f10ebd3d0572df1a0eeddf5d2abb9 Mon Sep 17 00:00:00 2001 From: Sofiia-Khrystyna <sonia030605@gmail.com> Date: Wed, 15 Jan 2025 15:32:12 +0100 Subject: [PATCH 01/10] Styling of the add appointment screen --- .../java/at/ac/fhstp/pawwatch/Navigation.kt | 2 +- .../fhstp/pawwatch/ui/AddAppointmentScreen.kt | 59 +++++++++++++------ ...tailScreen.kt => AllAppointmentsScreen.kt} | 0 .../at/ac/fhstp/pawwatch/ui/theme/Color.kt | 1 + .../at/ac/fhstp/pawwatch/ui/theme/Theme.kt | 2 +- .../at/ac/fhstp/pawwatch/ui/theme/Type.kt | 2 +- 6 files changed, 46 insertions(+), 20 deletions(-) rename app/src/main/java/at/ac/fhstp/pawwatch/ui/{AppointmentDetailScreen.kt => AllAppointmentsScreen.kt} (100%) diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/Navigation.kt b/app/src/main/java/at/ac/fhstp/pawwatch/Navigation.kt index 584bf57..055f735 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/Navigation.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/Navigation.kt @@ -52,7 +52,7 @@ fun BottomNavigationBar(navController: NavController) { selected = currentRoute == Screens.AddAppointment.route, onClick = { navController.navigate(Screens.AddAppointment.route) }, icon = { Icon(Icons.Filled.Add, contentDescription = "Add Appointment") }, - label = { Text("Add Appointment") } + label = { Text("Add") } ) NavigationBarItem( selected = currentRoute == Screens.Overview.route, diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt index 729b76d..d0f6642 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt @@ -23,7 +23,7 @@ fun AddAppointmentScreen( navController: NavController ) { // Collect the appointments as a state - val appointments by viewModel.appointments.collectAsState() + //val appointments by viewModel.appointments.collectAsState() // Store the selected appointment date var selectedAppointmentDate by remember { mutableStateOf<Long?>(null) } @@ -37,9 +37,10 @@ fun AddAppointmentScreen( Column( modifier = Modifier - .fillMaxWidth() + .fillMaxSize() .padding(35.dp), - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center ) { Spacer(modifier = Modifier.height(10.dp)) @@ -48,12 +49,13 @@ fun AddAppointmentScreen( style = MaterialTheme.typography.headlineMedium ) - Spacer(modifier = Modifier.height(25.dp)) + Spacer(modifier = Modifier.height(45.dp)) Text( text = "Pet Name:", modifier = Modifier.align(Alignment.Start) ) + Spacer(modifier = Modifier.height(5.dp)) OutlinedTextField( value = petName.value, @@ -62,14 +64,21 @@ fun AddAppointmentScreen( colors = TextFieldDefaults.outlinedTextFieldColors( containerColor = MaterialTheme.colorScheme.secondary ), - textStyle = MaterialTheme.typography.bodyMedium + textStyle = MaterialTheme.typography.bodyMedium, + placeholder = { + Text( + text = "Enter your pet name, e.g. Cupcake", + style = MaterialTheme.typography.bodyMedium + ) + } ) - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.height(20.dp)) Text( text = "Appointment Category:", modifier = Modifier.align(Alignment.Start) ) + Spacer(modifier = Modifier.height(5.dp)) OutlinedTextField( value = category.value, @@ -78,14 +87,21 @@ fun AddAppointmentScreen( colors = TextFieldDefaults.outlinedTextFieldColors( containerColor = MaterialTheme.colorScheme.secondary ), - textStyle = MaterialTheme.typography.bodyMedium + textStyle = MaterialTheme.typography.bodyMedium, + placeholder = { + Text( + text = "Select a category, e.g. Grooming", + style = MaterialTheme.typography.bodyMedium + ) + } ) - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.height(20.dp)) Text( - text = "Description:", + text = "Description (Optional):", modifier = Modifier.align(Alignment.Start) ) + Spacer(modifier = Modifier.height(5.dp)) OutlinedTextField( value = description.value, @@ -94,9 +110,15 @@ fun AddAppointmentScreen( colors = TextFieldDefaults.outlinedTextFieldColors( containerColor = MaterialTheme.colorScheme.secondary ), - textStyle = MaterialTheme.typography.bodyMedium + textStyle = MaterialTheme.typography.bodyMedium, + placeholder = { + Text( + text = "Enter a description, e.g. address, phone number", + style = MaterialTheme.typography.bodyMedium + ) + } ) - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.height(20.dp)) if (showDatePicker) { @@ -111,10 +133,12 @@ fun AddAppointmentScreen( OutlinedButton( onClick = { showDatePicker = true }, + modifier = Modifier.fillMaxWidth(), colors = ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary, + containerColor = MaterialTheme.colorScheme.tertiary, contentColor = MaterialTheme.colorScheme.onPrimary - ) + ), + elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 4.dp) ) { Text( text = "Select Appointment Date", @@ -127,17 +151,17 @@ fun AddAppointmentScreen( selectedAppointmentDate?.let { val dateString = DateFormat.getDateInstance().format(Date(it)) Text( - text = "Selected Appointment Date: $dateString", + text = "Selected Date: $dateString", modifier = Modifier.padding(2.dp), style = MaterialTheme.typography.labelMedium ) } - Spacer(modifier = Modifier.height(22.dp)) + Spacer(modifier = Modifier.height(40.dp)) // Button to submit new appointment OutlinedButton( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier.width(200.dp), colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary), onClick = { if (petName.value.isNotBlank() && selectedAppointmentDate != null) { @@ -155,7 +179,8 @@ fun AddAppointmentScreen( category.value ) } - } + }, + elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp) ) { Text( text = "Add Appointment", diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentDetailScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AllAppointmentsScreen.kt similarity index 100% rename from app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentDetailScreen.kt rename to app/src/main/java/at/ac/fhstp/pawwatch/ui/AllAppointmentsScreen.kt diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Color.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Color.kt index 45ca9f5..13f9b18 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Color.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Color.kt @@ -4,6 +4,7 @@ import androidx.compose.ui.graphics.Color val bg = Color(0xFFFDE9C3) val buttonBg = Color(0xFFFFBA66) +val lightButtonBg = Color(0xFFFFCE93) val text = Color(0xFF000000) val fieldBg = Color(0xFFFFF4DE) val deleteButtonBg = Color(0xFFbf4342) \ No newline at end of file diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Theme.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Theme.kt index cc6be4e..c6c272e 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Theme.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Theme.kt @@ -3,13 +3,13 @@ package at.ac.fhstp.pawwatch.ui.theme import androidx.compose.material3.MaterialTheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable -import androidx.compose.ui.graphics.Color private val AppColorScheme = lightColorScheme( background = bg, primary = buttonBg, onPrimary = text, secondary = fieldBg, + tertiary = lightButtonBg, error = deleteButtonBg ) diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Type.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Type.kt index b6a201e..0b00793 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Type.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Type.kt @@ -44,7 +44,7 @@ val Typography = Typography( labelMedium = TextStyle( fontFamily = FontFamily.Default, fontWeight = FontWeight.Bold, - fontSize = 15.sp, + fontSize = 17.sp, lineHeight = 24.sp, letterSpacing = 0.5.sp ) -- GitLab From 1388e635f9a5b17acc4ec990ac8ada22c95c552f Mon Sep 17 00:00:00 2001 From: Sofiia-Khrystyna <sonia030605@gmail.com> Date: Wed, 15 Jan 2025 15:39:55 +0100 Subject: [PATCH 02/10] test test --- .../main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt index d0f6642..e05a906 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt @@ -219,7 +219,6 @@ fun CustomDatePickerDialog( } this.date = calendar.timeInMillis - setOnDateChangeListener { _, year, month, dayOfMonth -> calendar.set(year, month, dayOfMonth) onDateSelected(calendar.timeInMillis) -- GitLab From b74ef836b7ddc79367500139aabd30b73fb4785c Mon Sep 17 00:00:00 2001 From: Sofiia-Khrystyna <sonia030605@gmail.com> Date: Wed, 15 Jan 2025 19:57:48 +0100 Subject: [PATCH 03/10] :zap:added time picker, but the time is shown in the wrong way with PM or AM --- .../java/at/ac/fhstp/pawwatch/MainActivity.kt | 4 +- .../pawwatch/data/AppointmentRepository.kt | 2 + .../fhstp/pawwatch/data/db/AppointmentDao.kt | 4 +- .../pawwatch/data/db/AppointmentDatabase.kt | 3 +- .../pawwatch/data/db/AppointmentEntity.kt | 1 + .../fhstp/pawwatch/ui/AddAppointmentScreen.kt | 180 +++++++++++++++--- .../pawwatch/ui/AppointmentEditScreen.kt | 3 +- .../fhstp/pawwatch/ui/AppointmentViewModel.kt | 8 +- 8 files changed, 169 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/MainActivity.kt b/app/src/main/java/at/ac/fhstp/pawwatch/MainActivity.kt index 01ee352..7337ab0 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/MainActivity.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/MainActivity.kt @@ -62,9 +62,9 @@ class MainActivity : ComponentActivity() { ) navController.navigate(route) }, - onAddAppointmentClick = { petName, description, date, category -> + onAddAppointmentClick = { petName, description, date, time, category -> // Add a new appointment via the ViewModel - viewModel.addAppointment(petName, description, date, category) + viewModel.addAppointment(petName, description, date, time, category) // Navigate back to the overview screen navController.popBackStack() }, diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/data/AppointmentRepository.kt b/app/src/main/java/at/ac/fhstp/pawwatch/data/AppointmentRepository.kt index f550e33..ebe0045 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/data/AppointmentRepository.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/data/AppointmentRepository.kt @@ -22,6 +22,7 @@ class AppointmentRepository(private val taskDao: AppointmentDao) { petName: String, description: String, appointmentDate: Long, + appointmentTime: Long, category: String ) { taskDao.updateAppointment( @@ -29,6 +30,7 @@ class AppointmentRepository(private val taskDao: AppointmentDao) { petName, description, appointmentDate, + appointmentTime, category ) } diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentDao.kt b/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentDao.kt index d9e0309..c1a24a9 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentDao.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentDao.kt @@ -3,6 +3,7 @@ package at.ac.fhstp.pawwatch.data.db import androidx.room.Dao import androidx.room.Insert import androidx.room.Query +import java.sql.Time @Dao interface AppointmentDao { @@ -16,12 +17,13 @@ interface AppointmentDao { @Query("DELETE FROM appointment_table WHERE id = :appointmentId") suspend fun deleteAppointmentById(appointmentId: Long) - @Query("UPDATE appointment_table SET petName = :petName, description = :description, appointmentDate = :appointmentDate, category = :category WHERE id = :appointmentId") + @Query("UPDATE appointment_table SET petName = :petName, description = :description, appointmentDate = :appointmentDate, appointmentTime = :appointmentTime, category = :category WHERE id = :appointmentId") suspend fun updateAppointment( appointmentId: Long, petName: String, description: String, appointmentDate: Long, + appointmentTime: Long, category: String ) diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentDatabase.kt b/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentDatabase.kt index 169f89e..37a8456 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentDatabase.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentDatabase.kt @@ -5,7 +5,7 @@ import androidx.room.Database import androidx.room.Room import androidx.room.RoomDatabase -@Database(entities = [AppointmentEntity::class], version = 2) +@Database(entities = [AppointmentEntity::class], version = 3) abstract class AppointmentDatabase : RoomDatabase() { abstract fun appointmentDao() : AppointmentDao @@ -24,6 +24,5 @@ abstract class AppointmentDatabase : RoomDatabase() { return tempInstance } } - } } \ No newline at end of file diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentEntity.kt b/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentEntity.kt index 586a57a..f03f720 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentEntity.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentEntity.kt @@ -10,5 +10,6 @@ data class AppointmentEntity( val petName: String, val description: String, val appointmentDate: Long, + val appointmentTime: Long, val category: String ) \ No newline at end of file diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt index e05a906..c3fed99 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt @@ -1,6 +1,7 @@ package at.ac.fhstp.pawwatch.ui import android.widget.CalendarView +import android.widget.NumberPicker import androidx.compose.foundation.layout.* import androidx.compose.material3.* import androidx.compose.runtime.* @@ -19,7 +20,7 @@ import java.util.* fun AddAppointmentScreen( viewModel: AppointmentViewModel, onAppointmentClick: (AppointmentEntity) -> Unit, - onAddAppointmentClick: (String, String, Long, String) -> Unit, + onAddAppointmentClick: (String, String, Long, Long, String) -> Unit, navController: NavController ) { // Collect the appointments as a state @@ -27,6 +28,7 @@ fun AddAppointmentScreen( // Store the selected appointment date var selectedAppointmentDate by remember { mutableStateOf<Long?>(null) } + var selectedAppointmentTime by remember { mutableStateOf<Long?>(null) } // DatePicker Dialog state var showDatePicker by remember { mutableStateOf(false) } @@ -124,6 +126,7 @@ fun AddAppointmentScreen( if (showDatePicker) { CustomDatePickerDialog( selectedDate = selectedAppointmentDate, // Pass the previously selected date + onDismiss = { showDatePicker = false }, onDateSelected = { date -> selectedAppointmentDate = date // Update the selected date @@ -149,9 +152,9 @@ fun AddAppointmentScreen( // for displaying the selected appointment date below the button Spacer(modifier = Modifier.height(8.dp)) selectedAppointmentDate?.let { - val dateString = DateFormat.getDateInstance().format(Date(it)) + val dateTimeString = DateFormat.getDateTimeInstance().format(Date(it)) Text( - text = "Selected Date: $dateString", + text = "Selected Date and Time: $dateTimeString", modifier = Modifier.padding(2.dp), style = MaterialTheme.typography.labelMedium ) @@ -176,6 +179,7 @@ fun AddAppointmentScreen( petName.value, description.value, selectedAppointmentDate!!, + selectedAppointmentTime!!, category.value ) } @@ -189,6 +193,59 @@ fun AddAppointmentScreen( } } } +// +//@Composable +//fun CustomDatePickerDialog( +// onDismiss: () -> Unit, +// selectedDate: Long?, // Pass the currently selected date +// onDateSelected: (Long) -> Unit +//) { +// val calendar = Calendar.getInstance(Locale.getDefault()).apply { +// firstDayOfWeek = Calendar.MONDAY +// } +// +// Dialog(onDismissRequest = onDismiss) { +// Surface( +// shape = MaterialTheme.shapes.medium, +// tonalElevation = 8.dp +// ) { +// Column( +// modifier = Modifier.padding(16.dp) +// ) { +// AndroidView( +// factory = { context -> +// CalendarView(context).apply { +// this.firstDayOfWeek = Calendar.MONDAY +// +// // Set the calendar to the selected date or today's date +// if (selectedDate != null) { +// calendar.timeInMillis = selectedDate +// } +// this.date = calendar.timeInMillis +// +// setOnDateChangeListener { _, year, month, dayOfMonth -> +// calendar.set(year, month, dayOfMonth) +// onDateSelected(calendar.timeInMillis) +// onDismiss() // Close the dialog after selecting a date +// } +// } +// }, +// modifier = Modifier.wrapContentHeight() +// ) +// +// Spacer(modifier = Modifier.height(16.dp)) +// +// Button( +// onClick = onDismiss, +// modifier = Modifier.align(Alignment.End) +// ) { +// Text("Cancel") +// } +// } +// } +// } +//} + @Composable fun CustomDatePickerDialog( @@ -200,6 +257,11 @@ fun CustomDatePickerDialog( firstDayOfWeek = Calendar.MONDAY } + // Time selection state + var showTimePicker by remember { mutableStateOf(false) } + var selectedHour by remember { mutableIntStateOf(12) } // Default hour + var selectedMinute by remember { mutableIntStateOf(0) } // Default minute + Dialog(onDismissRequest = onDismiss) { Surface( shape = MaterialTheme.shapes.medium, @@ -208,34 +270,100 @@ fun CustomDatePickerDialog( Column( modifier = Modifier.padding(16.dp) ) { - AndroidView( - factory = { context -> - CalendarView(context).apply { - this.firstDayOfWeek = Calendar.MONDAY - - // Set the calendar to the selected date or today's date - if (selectedDate != null) { - calendar.timeInMillis = selectedDate + if (!showTimePicker) { + // Calendar View + AndroidView( + factory = { context -> + CalendarView(context).apply { + this.firstDayOfWeek = Calendar.MONDAY + + // Set the calendar to the selected date or today's date + if (selectedDate != null) { + calendar.timeInMillis = selectedDate + } + this.date = calendar.timeInMillis + + setOnDateChangeListener { _, year, month, dayOfMonth -> + calendar.set(year, month, dayOfMonth) + showTimePicker = true // Show time picker after date selection + } } - this.date = calendar.timeInMillis + }, + modifier = Modifier.wrapContentHeight() + ) + + Spacer(modifier = Modifier.height(16.dp)) + + Button( + onClick = onDismiss, + modifier = Modifier.align(Alignment.End) + ) { + Text("Cancel") + } + } else { + // Time Picker + Text("Select Time", style = MaterialTheme.typography.bodyLarge) + Spacer(modifier = Modifier.height(16.dp)) + + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceEvenly, + modifier = Modifier.fillMaxWidth() + ) { + // Hour Picker + AndroidView( + factory = { context -> + NumberPicker(context).apply { + minValue = 0 + maxValue = 23 + value = selectedHour + setOnValueChangedListener { _, _, newValue -> + selectedHour = newValue + } + } + }, + modifier = Modifier.wrapContentHeight() + ) - setOnDateChangeListener { _, year, month, dayOfMonth -> - calendar.set(year, month, dayOfMonth) + // Minute Picker + AndroidView( + factory = { context -> + NumberPicker(context).apply { + minValue = 0 + maxValue = 59 + value = selectedMinute + setOnValueChangedListener { _, _, newValue -> + selectedMinute = newValue + } + } + }, + modifier = Modifier.wrapContentHeight() + ) + } + + Spacer(modifier = Modifier.height(16.dp)) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Button(onClick = { showTimePicker = false }) { + Text("Back") + } + Button( + onClick = { + calendar.set(Calendar.HOUR_OF_DAY, selectedHour) + calendar.set(Calendar.MINUTE, selectedMinute) + calendar.set(Calendar.SECOND, 0) + + // Pass the selected date and time onDateSelected(calendar.timeInMillis) - onDismiss() // Close the dialog after selecting a date + onDismiss() } + ) { + Text("OK") } - }, - modifier = Modifier.wrapContentHeight() - ) - - Spacer(modifier = Modifier.height(16.dp)) - - Button( - onClick = onDismiss, - modifier = Modifier.align(Alignment.End) - ) { - Text("Cancel") + } } } } diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentEditScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentEditScreen.kt index bda19e3..3cafe06 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentEditScreen.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentEditScreen.kt @@ -24,6 +24,7 @@ fun AppointmentEditScreen( var petName by remember { mutableStateOf(appointment?.petName ?: "") } var description by remember { mutableStateOf(appointment?.description ?: "") } var appointmentDate by remember { mutableLongStateOf(appointment?.appointmentDate ?: System.currentTimeMillis()) } + var appointmentTime by remember { mutableLongStateOf(appointment?.appointmentTime ?: System.currentTimeMillis()) } var category by remember { mutableStateOf(appointment?.category ?: "") } var showDatePicker by remember { mutableStateOf(false) } @@ -142,7 +143,7 @@ fun AppointmentEditScreen( OutlinedButton( onClick = { if (petName.isNotBlank() && description.isNotBlank()) { - viewModel.editAppointment(appointmentId!!.toLong(), petName, description, appointmentDate, category) + viewModel.editAppointment(appointmentId!!.toLong(), petName, description, appointmentDate, appointmentTime, category) navController.navigateUp() } }, diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentViewModel.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentViewModel.kt index 74c1192..463d901 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentViewModel.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentViewModel.kt @@ -33,8 +33,8 @@ class AppointmentViewModel(private val appointmentRepository: AppointmentReposit } // Add a new appointment - fun addAppointment(petName: String, description: String, appointmentDate: Long, category: String) { - val appointment = AppointmentEntity(petName = petName, description = description, appointmentDate = appointmentDate, category = category) + fun addAppointment(petName: String, description: String, appointmentDate: Long, appointmentTime: Long, category: String) { + val appointment = AppointmentEntity(petName = petName, description = description, appointmentDate = appointmentDate, appointmentTime = appointmentTime, category = category) viewModelScope.launch { appointmentRepository.insertAppointment(appointment) loadAppointments() // Reload appointments from the repository to update the list @@ -58,9 +58,9 @@ class AppointmentViewModel(private val appointmentRepository: AppointmentReposit } } - fun editAppointment(appointmentId: Long, petName: String, description: String, appointmentDate: Long, category: String) { + fun editAppointment(appointmentId: Long, petName: String, description: String, appointmentDate: Long, appointmentTime: Long, category: String) { viewModelScope.launch { - appointmentRepository.updateAppointment(appointmentId, petName, description, appointmentDate, category) + appointmentRepository.updateAppointment(appointmentId, petName, description, appointmentDate, appointmentTime, category) loadAppointments() // Refresh the appointment list } } -- GitLab From 907082eb7db320840b556e990c4edc624d6e62f1 Mon Sep 17 00:00:00 2001 From: Sofiia-Khrystyna <sonia030605@gmail.com> Date: Fri, 17 Jan 2025 10:40:55 +0100 Subject: [PATCH 04/10] :zap:added time picker, but the time is shown with offset of 1 hour --- app/build.gradle.kts | 1 + .../java/at/ac/fhstp/pawwatch/Navigation.kt | 11 +- .../fhstp/pawwatch/ui/AddAppointmentScreen.kt | 117 ++++++------------ ...tsScreen.kt => AppointmentDetailScreen.kt} | 11 +- .../pawwatch/ui/AppointmentEditScreen.kt | 93 +++++++++++--- .../at/ac/fhstp/pawwatch/ui/theme/Type.kt | 8 ++ gradle/libs.versions.toml | 4 + 7 files changed, 145 insertions(+), 100 deletions(-) rename app/src/main/java/at/ac/fhstp/pawwatch/ui/{AllAppointmentsScreen.kt => AppointmentDetailScreen.kt} (89%) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index dba15af..438742f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -73,4 +73,5 @@ dependencies { androidTestImplementation(libs.androidx.ui.test.junit4) debugImplementation(libs.androidx.ui.tooling) debugImplementation(libs.androidx.ui.test.manifest) + implementation(libs.jetbrains.kotlinx.datetime) } \ No newline at end of file diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/Navigation.kt b/app/src/main/java/at/ac/fhstp/pawwatch/Navigation.kt index 055f735..a4397d2 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/Navigation.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/Navigation.kt @@ -28,6 +28,8 @@ import at.ac.fhstp.pawwatch.data.db.AppointmentEntity import at.ac.fhstp.pawwatch.ui.AppointmentViewModel import java.sql.Date import java.text.DateFormat +import java.text.SimpleDateFormat +import java.util.Locale sealed class Screens(val route: String) { @@ -112,8 +114,15 @@ fun AppointmentCard(appointment: AppointmentEntity, onClick: () -> Unit) { ) Spacer(modifier = Modifier.height(14.dp)) + val date = Date(appointment.appointmentDate) + val time = Date(appointment.appointmentTime) + + // Use SimpleDateFormat for 24-hour time format (HH:mm) + val timeFormat = SimpleDateFormat("HH:mm", Locale.getDefault()) + + // Combine Date and Time into one line Text( - "Date: ${DateFormat.getDateInstance().format(Date(appointment.appointmentDate))}", + "${DateFormat.getDateInstance().format(date)} at ${timeFormat.format(time)}", style = MaterialTheme.typography.bodyMedium ) } diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt index c3fed99..0577000 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt @@ -1,6 +1,8 @@ package at.ac.fhstp.pawwatch.ui +import android.util.Log import android.widget.CalendarView +import android.widget.DatePicker import android.widget.NumberPicker import androidx.compose.foundation.layout.* import androidx.compose.material3.* @@ -12,7 +14,8 @@ import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.window.Dialog import androidx.navigation.NavController import at.ac.fhstp.pawwatch.data.db.AppointmentEntity -import java.text.DateFormat +import kotlinx.datetime.Instant +import java.text.SimpleDateFormat import java.util.* @OptIn(ExperimentalMaterial3Api::class) @@ -125,12 +128,20 @@ fun AddAppointmentScreen( if (showDatePicker) { CustomDatePickerDialog( - selectedDate = selectedAppointmentDate, // Pass the previously selected date + selectedDateTime = selectedAppointmentDate, // Pass the previously selected date onDismiss = { showDatePicker = false }, - onDateSelected = { date -> - selectedAppointmentDate = date // Update the selected date + onDateTimeSelected = { dateTime -> + Log.w("xaver", dateTime.toString()) + selectedAppointmentDate = dateTime + selectedAppointmentTime = Calendar.getInstance().apply { + timeInMillis = dateTime + }.get(Calendar.HOUR_OF_DAY) * 3600000L + // Convert hours to ms + Calendar.getInstance().apply { + timeInMillis = dateTime + }.get(Calendar.MINUTE) * 60000L // Convert minutes to ms } + ) } @@ -152,11 +163,11 @@ fun AddAppointmentScreen( // for displaying the selected appointment date below the button Spacer(modifier = Modifier.height(8.dp)) selectedAppointmentDate?.let { - val dateTimeString = DateFormat.getDateTimeInstance().format(Date(it)) + val dateTimeString = SimpleDateFormat("MMM dd, yyyy HH:mm", Locale.getDefault()).format(Date(it)) Text( text = "Selected Date and Time: $dateTimeString", modifier = Modifier.padding(2.dp), - style = MaterialTheme.typography.labelMedium + style = MaterialTheme.typography.labelSmall ) } @@ -167,14 +178,10 @@ fun AddAppointmentScreen( modifier = Modifier.width(200.dp), colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary), onClick = { - if (petName.value.isNotBlank() && selectedAppointmentDate != null) { - if (description.value.isBlank()) { - description.value = "No Description" - } - if (category.value.isBlank()) { - category.value = "General" - } - // Calls the onAddAppointmentClick with selected date + if (petName.value.isNotBlank() && selectedAppointmentDate != null && selectedAppointmentTime != null) { + if (description.value.isBlank()) { description.value = "No Description" } + if (category.value.isBlank()) { category.value = "General" } + // Calls the onAddAppointmentClick with selected date and time onAddAppointmentClick( petName.value, description.value, @@ -183,6 +190,7 @@ fun AddAppointmentScreen( category.value ) } + }, elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp) ) { @@ -193,65 +201,12 @@ fun AddAppointmentScreen( } } } -// -//@Composable -//fun CustomDatePickerDialog( -// onDismiss: () -> Unit, -// selectedDate: Long?, // Pass the currently selected date -// onDateSelected: (Long) -> Unit -//) { -// val calendar = Calendar.getInstance(Locale.getDefault()).apply { -// firstDayOfWeek = Calendar.MONDAY -// } -// -// Dialog(onDismissRequest = onDismiss) { -// Surface( -// shape = MaterialTheme.shapes.medium, -// tonalElevation = 8.dp -// ) { -// Column( -// modifier = Modifier.padding(16.dp) -// ) { -// AndroidView( -// factory = { context -> -// CalendarView(context).apply { -// this.firstDayOfWeek = Calendar.MONDAY -// -// // Set the calendar to the selected date or today's date -// if (selectedDate != null) { -// calendar.timeInMillis = selectedDate -// } -// this.date = calendar.timeInMillis -// -// setOnDateChangeListener { _, year, month, dayOfMonth -> -// calendar.set(year, month, dayOfMonth) -// onDateSelected(calendar.timeInMillis) -// onDismiss() // Close the dialog after selecting a date -// } -// } -// }, -// modifier = Modifier.wrapContentHeight() -// ) -// -// Spacer(modifier = Modifier.height(16.dp)) -// -// Button( -// onClick = onDismiss, -// modifier = Modifier.align(Alignment.End) -// ) { -// Text("Cancel") -// } -// } -// } -// } -//} - @Composable fun CustomDatePickerDialog( onDismiss: () -> Unit, - selectedDate: Long?, // Pass the currently selected date - onDateSelected: (Long) -> Unit + selectedDateTime: Long?, // Pass the currently selected date + onDateTimeSelected: (Long) -> Unit ) { val calendar = Calendar.getInstance(Locale.getDefault()).apply { firstDayOfWeek = Calendar.MONDAY @@ -278,8 +233,8 @@ fun CustomDatePickerDialog( this.firstDayOfWeek = Calendar.MONDAY // Set the calendar to the selected date or today's date - if (selectedDate != null) { - calendar.timeInMillis = selectedDate + if (selectedDateTime != null) { + calendar.timeInMillis = selectedDateTime } this.date = calendar.timeInMillis @@ -316,9 +271,11 @@ fun CustomDatePickerDialog( NumberPicker(context).apply { minValue = 0 maxValue = 23 - value = selectedHour + //value = selectedHour + value = calendar.get(Calendar.HOUR_OF_DAY) setOnValueChangedListener { _, _, newValue -> - selectedHour = newValue + //selectedHour = newValue + calendar.set(Calendar.HOUR_OF_DAY, newValue) } } }, @@ -331,9 +288,11 @@ fun CustomDatePickerDialog( NumberPicker(context).apply { minValue = 0 maxValue = 59 - value = selectedMinute + //value = selectedMinute + value = calendar.get(Calendar.MINUTE) setOnValueChangedListener { _, _, newValue -> - selectedMinute = newValue + //selectedMinute = newValue + calendar.set(Calendar.MINUTE, newValue) } } }, @@ -352,12 +311,12 @@ fun CustomDatePickerDialog( } Button( onClick = { - calendar.set(Calendar.HOUR_OF_DAY, selectedHour) - calendar.set(Calendar.MINUTE, selectedMinute) - calendar.set(Calendar.SECOND, 0) +// calendar.set(Calendar.HOUR_OF_DAY, selectedHour) +// calendar.set(Calendar.MINUTE, selectedMinute) + //calendar.set(Calendar.SECOND, 0) // Pass the selected date and time - onDateSelected(calendar.timeInMillis) + onDateTimeSelected(calendar.timeInMillis) onDismiss() } ) { diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AllAppointmentsScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentDetailScreen.kt similarity index 89% rename from app/src/main/java/at/ac/fhstp/pawwatch/ui/AllAppointmentsScreen.kt rename to app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentDetailScreen.kt index f4f0c2f..41ebe17 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AllAppointmentsScreen.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentDetailScreen.kt @@ -12,7 +12,9 @@ import androidx.navigation.NavController import at.ac.fhstp.pawwatch.Screens import at.ac.fhstp.pawwatch.ui.theme.text import java.text.DateFormat +import java.text.SimpleDateFormat import java.util.Date +import java.util.Locale @Composable fun AppointmentDetailScreen( @@ -64,8 +66,15 @@ fun AppointmentDetailScreen( ) Spacer(modifier = Modifier.height(10.dp)) + // Format date and time (using SimpleDateFormat for time in 24-hour format) + val date = Date(it.appointmentDate) + val time = Date(it.appointmentTime) + + val timeFormat = SimpleDateFormat("HH:mm", Locale.getDefault()) + + // Display Date and Time Text( - DateFormat.getDateInstance().format(Date(it.appointmentDate)), + "${DateFormat.getDateInstance().format(date)} at ${timeFormat.format(time)}", style = MaterialTheme.typography.bodyMedium, modifier = Modifier.padding(2.dp) ) diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentEditScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentEditScreen.kt index 3cafe06..67e1eb2 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentEditScreen.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentEditScreen.kt @@ -12,6 +12,9 @@ import androidx.navigation.NavController import at.ac.fhstp.pawwatch.ui.theme.text import java.sql.Date import java.text.DateFormat +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Locale @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -23,11 +26,12 @@ fun AppointmentEditScreen( val appointment = appointmentId?.let { id -> viewModel.getAppointmentById(id.toLong()) } var petName by remember { mutableStateOf(appointment?.petName ?: "") } var description by remember { mutableStateOf(appointment?.description ?: "") } - var appointmentDate by remember { mutableLongStateOf(appointment?.appointmentDate ?: System.currentTimeMillis()) } - var appointmentTime by remember { mutableLongStateOf(appointment?.appointmentTime ?: System.currentTimeMillis()) } + var selectedAppointmentDate by remember { mutableLongStateOf(appointment?.appointmentDate ?: System.currentTimeMillis()) } + var selectedAppointmentTime by remember { mutableLongStateOf(appointment?.appointmentTime ?: System.currentTimeMillis()) } var category by remember { mutableStateOf(appointment?.category ?: "") } var showDatePicker by remember { mutableStateOf(false) } + var showTimePicker by remember { mutableStateOf(false) } Column( modifier = Modifier @@ -110,48 +114,99 @@ fun AppointmentEditScreen( if (showDatePicker) { CustomDatePickerDialog( - selectedDate = appointmentDate, + selectedDateTime = selectedAppointmentDate, // Pass the previously selected date + onDismiss = { showDatePicker = false }, - onDateSelected = { date -> - appointmentDate = date // Update appointmentDate - showDatePicker = false + onDateTimeSelected = { dateTime -> + selectedAppointmentDate = dateTime + selectedAppointmentTime = Calendar.getInstance().apply { + timeInMillis = dateTime + }.get(Calendar.HOUR_OF_DAY) * 3600000L + // Convert hours to ms + Calendar.getInstance().apply { + timeInMillis = dateTime + }.get(Calendar.MINUTE) * 60000L // Convert minutes to ms } + ) } - val formattedDate = DateFormat.getDateInstance().format(Date(appointmentDate)) - Text( - "Selected Appointment Date: $formattedDate", - modifier = Modifier.padding(2.dp), - style = MaterialTheme.typography.labelMedium - ) + // Display formatted date and time +// val formattedDate = DateFormat.getDateInstance().format(Date(selectedAppointmentDate)) +// val timeFormat = SimpleDateFormat("HH:mm", Locale.getDefault()) +// val formattedTime = timeFormat.format(Date(selectedAppointmentTime)) +// +// Text( +// "Selected Date and Time: $formattedDate at $formattedTime", +// modifier = Modifier.padding(2.dp), +// style = MaterialTheme.typography.labelMedium +// ) Spacer(modifier = Modifier.height(8.dp)) OutlinedButton( onClick = { showDatePicker = true }, - colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary), + modifier = Modifier.fillMaxWidth(), + colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.tertiary, + contentColor = MaterialTheme.colorScheme.onPrimary + ), + elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 4.dp) ) { Text( - "Change Appointment Date", + text = "Change Date or Time", style = MaterialTheme.typography.labelMedium ) } + Spacer(modifier = Modifier.height(8.dp)) + selectedAppointmentDate.let { + val dateTimeString = SimpleDateFormat("MMM dd, yyyy HH:mm", Locale.getDefault()).format(Date(it)) + Text( + text = "Selected Date and Time: $dateTimeString", + modifier = Modifier.padding(2.dp), + style = MaterialTheme.typography.labelSmall + ) + } + Spacer(modifier = Modifier.height(16.dp)) +// OutlinedButton( +// onClick = { +// if (petName.isNotBlank() && description.isNotBlank()) { +// viewModel.editAppointment(appointmentId!!.toLong(), petName, description, selectedAppointmentDate, selectedAppointmentTime, category) +// navController.navigateUp() +// } +// }, +// modifier = Modifier.fillMaxWidth(), +// colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary), +// ) { +// Text( +// "Save Changes", +// style = MaterialTheme.typography.labelMedium +// ) +// } + OutlinedButton( + modifier = Modifier.width(200.dp), + colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary), onClick = { - if (petName.isNotBlank() && description.isNotBlank()) { - viewModel.editAppointment(appointmentId!!.toLong(), petName, description, appointmentDate, appointmentTime, category) + if (petName.isNotBlank()) { + viewModel.editAppointment( + appointmentId!!.toLong(), + petName, + description, + selectedAppointmentDate, + selectedAppointmentTime, + category + ) navController.navigateUp() } + }, - modifier = Modifier.fillMaxWidth(), - colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary), + elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp) ) { Text( - "Save Changes", + text = "Save Changes", style = MaterialTheme.typography.labelMedium ) } diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Type.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Type.kt index 0b00793..f6d5aae 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Type.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Type.kt @@ -47,5 +47,13 @@ val Typography = Typography( fontSize = 17.sp, lineHeight = 24.sp, letterSpacing = 0.5.sp + ), + + labelSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Bold, + fontSize = 15.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp ) ) \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4684332..6140e43 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,6 +5,8 @@ coreKtx = "1.13.1" junit = "4.13.2" junitVersion = "1.2.1" espressoCore = "3.6.1" +kotlinxDatetime = "0.6.1" +kotlinxDatetimeVersion = "0.6.1" lifecycleRuntimeKtx = "2.8.6" activityCompose = "1.9.2" composeBom = "2024.04.01" @@ -17,6 +19,7 @@ navigationCompose = "2.8.3" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "roomCompiler" } +jetbrains-kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinxDatetimeVersion" } junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } @@ -33,6 +36,7 @@ androidx-material3 = { group = "androidx.compose.material3", name = "material3" androidx-room-common = { group = "androidx.room", name = "room-common", version.ref = "roomCommon" } androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "roomKtx" } androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" } +kotlinx-datetime = { module = "kotlinx.datetime:kotlinx-datetime", version.ref = "kotlinxDatetime" } materialdatetimepicker = { module = "com.wdullaer:materialdatetimepicker", version.ref = "materialdatetimepicker" } [plugins] -- GitLab From 8be8ae7a2de8c550593ab5f6793dc9528b8bb2a1 Mon Sep 17 00:00:00 2001 From: Sofiia-Khrystyna <sonia030605@gmail.com> Date: Fri, 17 Jan 2025 11:54:44 +0100 Subject: [PATCH 05/10] :tada:time picker,works everywhere now --- .../java/at/ac/fhstp/pawwatch/MainActivity.kt | 4 +- .../java/at/ac/fhstp/pawwatch/Navigation.kt | 9 ++-- .../pawwatch/data/AppointmentRepository.kt | 2 - .../fhstp/pawwatch/data/db/AppointmentDao.kt | 5 +-- .../pawwatch/data/db/AppointmentDatabase.kt | 2 +- .../pawwatch/data/db/AppointmentEntity.kt | 3 +- .../fhstp/pawwatch/ui/AddAppointmentScreen.kt | 43 +++++-------------- .../pawwatch/ui/AppointmentDetailScreen.kt | 13 +++--- .../pawwatch/ui/AppointmentEditScreen.kt | 39 +++-------------- .../fhstp/pawwatch/ui/AppointmentViewModel.kt | 8 ++-- 10 files changed, 36 insertions(+), 92 deletions(-) diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/MainActivity.kt b/app/src/main/java/at/ac/fhstp/pawwatch/MainActivity.kt index 7337ab0..f2c9db2 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/MainActivity.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/MainActivity.kt @@ -62,9 +62,9 @@ class MainActivity : ComponentActivity() { ) navController.navigate(route) }, - onAddAppointmentClick = { petName, description, date, time, category -> + onAddAppointmentClick = { petName, description, dateTime, category -> // Add a new appointment via the ViewModel - viewModel.addAppointment(petName, description, date, time, category) + viewModel.addAppointment(petName, description, dateTime, category) // Navigate back to the overview screen navController.popBackStack() }, diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/Navigation.kt b/app/src/main/java/at/ac/fhstp/pawwatch/Navigation.kt index a4397d2..86c0ae3 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/Navigation.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/Navigation.kt @@ -27,7 +27,6 @@ import androidx.navigation.compose.currentBackStackEntryAsState import at.ac.fhstp.pawwatch.data.db.AppointmentEntity import at.ac.fhstp.pawwatch.ui.AppointmentViewModel import java.sql.Date -import java.text.DateFormat import java.text.SimpleDateFormat import java.util.Locale @@ -114,15 +113,13 @@ fun AppointmentCard(appointment: AppointmentEntity, onClick: () -> Unit) { ) Spacer(modifier = Modifier.height(14.dp)) - val date = Date(appointment.appointmentDate) - val time = Date(appointment.appointmentTime) + val date = Date(appointment.appointmentDateTime) // Use SimpleDateFormat for 24-hour time format (HH:mm) - val timeFormat = SimpleDateFormat("HH:mm", Locale.getDefault()) + val dateFormat = SimpleDateFormat("MMM dd, yyyy 'at' HH:mm", Locale.getDefault()) - // Combine Date and Time into one line Text( - "${DateFormat.getDateInstance().format(date)} at ${timeFormat.format(time)}", + dateFormat.format(date), style = MaterialTheme.typography.bodyMedium ) } diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/data/AppointmentRepository.kt b/app/src/main/java/at/ac/fhstp/pawwatch/data/AppointmentRepository.kt index ebe0045..f550e33 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/data/AppointmentRepository.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/data/AppointmentRepository.kt @@ -22,7 +22,6 @@ class AppointmentRepository(private val taskDao: AppointmentDao) { petName: String, description: String, appointmentDate: Long, - appointmentTime: Long, category: String ) { taskDao.updateAppointment( @@ -30,7 +29,6 @@ class AppointmentRepository(private val taskDao: AppointmentDao) { petName, description, appointmentDate, - appointmentTime, category ) } diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentDao.kt b/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentDao.kt index c1a24a9..ec987da 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentDao.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentDao.kt @@ -17,13 +17,12 @@ interface AppointmentDao { @Query("DELETE FROM appointment_table WHERE id = :appointmentId") suspend fun deleteAppointmentById(appointmentId: Long) - @Query("UPDATE appointment_table SET petName = :petName, description = :description, appointmentDate = :appointmentDate, appointmentTime = :appointmentTime, category = :category WHERE id = :appointmentId") + @Query("UPDATE appointment_table SET petName = :petName, description = :description, appointmentDateTime = :appointmentDateTime, category = :category WHERE id = :appointmentId") suspend fun updateAppointment( appointmentId: Long, petName: String, description: String, - appointmentDate: Long, - appointmentTime: Long, + appointmentDateTime: Long, category: String ) diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentDatabase.kt b/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentDatabase.kt index 37a8456..5c6406a 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentDatabase.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentDatabase.kt @@ -5,7 +5,7 @@ import androidx.room.Database import androidx.room.Room import androidx.room.RoomDatabase -@Database(entities = [AppointmentEntity::class], version = 3) +@Database(entities = [AppointmentEntity::class], version = 4) abstract class AppointmentDatabase : RoomDatabase() { abstract fun appointmentDao() : AppointmentDao diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentEntity.kt b/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentEntity.kt index f03f720..6cdc0c1 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentEntity.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/data/db/AppointmentEntity.kt @@ -9,7 +9,6 @@ data class AppointmentEntity( val id: Int = 0, val petName: String, val description: String, - val appointmentDate: Long, - val appointmentTime: Long, + val appointmentDateTime: Long, val category: String ) \ No newline at end of file diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt index 0577000..82eae84 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt @@ -1,8 +1,6 @@ package at.ac.fhstp.pawwatch.ui -import android.util.Log import android.widget.CalendarView -import android.widget.DatePicker import android.widget.NumberPicker import androidx.compose.foundation.layout.* import androidx.compose.material3.* @@ -14,7 +12,6 @@ import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.window.Dialog import androidx.navigation.NavController import at.ac.fhstp.pawwatch.data.db.AppointmentEntity -import kotlinx.datetime.Instant import java.text.SimpleDateFormat import java.util.* @@ -23,15 +20,12 @@ import java.util.* fun AddAppointmentScreen( viewModel: AppointmentViewModel, onAppointmentClick: (AppointmentEntity) -> Unit, - onAddAppointmentClick: (String, String, Long, Long, String) -> Unit, + onAddAppointmentClick: (String, String, Long, String) -> Unit, navController: NavController ) { - // Collect the appointments as a state - //val appointments by viewModel.appointments.collectAsState() // Store the selected appointment date - var selectedAppointmentDate by remember { mutableStateOf<Long?>(null) } - var selectedAppointmentTime by remember { mutableStateOf<Long?>(null) } + var selectedAppointmentDateTime by remember { mutableStateOf<Long?>(null) } // DatePicker Dialog state var showDatePicker by remember { mutableStateOf(false) } @@ -127,19 +121,11 @@ fun AddAppointmentScreen( if (showDatePicker) { - CustomDatePickerDialog( - selectedDateTime = selectedAppointmentDate, // Pass the previously selected date - + CustomDateTimePickerDialog( + selectedDateTime = selectedAppointmentDateTime, // Pass the previously selected date onDismiss = { showDatePicker = false }, onDateTimeSelected = { dateTime -> - Log.w("xaver", dateTime.toString()) - selectedAppointmentDate = dateTime - selectedAppointmentTime = Calendar.getInstance().apply { - timeInMillis = dateTime - }.get(Calendar.HOUR_OF_DAY) * 3600000L + // Convert hours to ms - Calendar.getInstance().apply { - timeInMillis = dateTime - }.get(Calendar.MINUTE) * 60000L // Convert minutes to ms + selectedAppointmentDateTime = dateTime } ) @@ -155,15 +141,15 @@ fun AddAppointmentScreen( elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 4.dp) ) { Text( - text = "Select Appointment Date", + text = "Select Appointment Date and Time", style = MaterialTheme.typography.labelMedium ) } // for displaying the selected appointment date below the button Spacer(modifier = Modifier.height(8.dp)) - selectedAppointmentDate?.let { - val dateTimeString = SimpleDateFormat("MMM dd, yyyy HH:mm", Locale.getDefault()).format(Date(it)) + selectedAppointmentDateTime?.let { + val dateTimeString = SimpleDateFormat("MMM dd, yyyy 'at' HH:mm", Locale.getDefault()).format(Date(it)) Text( text = "Selected Date and Time: $dateTimeString", modifier = Modifier.padding(2.dp), @@ -178,15 +164,14 @@ fun AddAppointmentScreen( modifier = Modifier.width(200.dp), colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary), onClick = { - if (petName.value.isNotBlank() && selectedAppointmentDate != null && selectedAppointmentTime != null) { + if (petName.value.isNotBlank() && selectedAppointmentDateTime != null) { if (description.value.isBlank()) { description.value = "No Description" } if (category.value.isBlank()) { category.value = "General" } // Calls the onAddAppointmentClick with selected date and time onAddAppointmentClick( petName.value, description.value, - selectedAppointmentDate!!, - selectedAppointmentTime!!, + selectedAppointmentDateTime!!, category.value ) } @@ -203,7 +188,7 @@ fun AddAppointmentScreen( } @Composable -fun CustomDatePickerDialog( +fun CustomDateTimePickerDialog( onDismiss: () -> Unit, selectedDateTime: Long?, // Pass the currently selected date onDateTimeSelected: (Long) -> Unit @@ -214,8 +199,6 @@ fun CustomDatePickerDialog( // Time selection state var showTimePicker by remember { mutableStateOf(false) } - var selectedHour by remember { mutableIntStateOf(12) } // Default hour - var selectedMinute by remember { mutableIntStateOf(0) } // Default minute Dialog(onDismissRequest = onDismiss) { Surface( @@ -311,10 +294,6 @@ fun CustomDatePickerDialog( } Button( onClick = { -// calendar.set(Calendar.HOUR_OF_DAY, selectedHour) -// calendar.set(Calendar.MINUTE, selectedMinute) - //calendar.set(Calendar.SECOND, 0) - // Pass the selected date and time onDateTimeSelected(calendar.timeInMillis) onDismiss() diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentDetailScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentDetailScreen.kt index 41ebe17..b190a32 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentDetailScreen.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentDetailScreen.kt @@ -66,17 +66,14 @@ fun AppointmentDetailScreen( ) Spacer(modifier = Modifier.height(10.dp)) - // Format date and time (using SimpleDateFormat for time in 24-hour format) - val date = Date(it.appointmentDate) - val time = Date(it.appointmentTime) + val date = Date(appointment.appointmentDateTime) - val timeFormat = SimpleDateFormat("HH:mm", Locale.getDefault()) + // Use SimpleDateFormat for 24-hour time format (HH:mm) + val dateFormat = SimpleDateFormat("MMM dd, yyyy 'at' HH:mm", Locale.getDefault()) - // Display Date and Time Text( - "${DateFormat.getDateInstance().format(date)} at ${timeFormat.format(time)}", - style = MaterialTheme.typography.bodyMedium, - modifier = Modifier.padding(2.dp) + dateFormat.format(date), + style = MaterialTheme.typography.bodyMedium ) Spacer(modifier = Modifier.height(20.dp)) diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentEditScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentEditScreen.kt index 67e1eb2..0f89e76 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentEditScreen.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentEditScreen.kt @@ -26,8 +26,7 @@ fun AppointmentEditScreen( val appointment = appointmentId?.let { id -> viewModel.getAppointmentById(id.toLong()) } var petName by remember { mutableStateOf(appointment?.petName ?: "") } var description by remember { mutableStateOf(appointment?.description ?: "") } - var selectedAppointmentDate by remember { mutableLongStateOf(appointment?.appointmentDate ?: System.currentTimeMillis()) } - var selectedAppointmentTime by remember { mutableLongStateOf(appointment?.appointmentTime ?: System.currentTimeMillis()) } + var selectedAppointmentDateTime by remember { mutableLongStateOf(appointment?.appointmentDateTime ?: System.currentTimeMillis()) } var category by remember { mutableStateOf(appointment?.category ?: "") } var showDatePicker by remember { mutableStateOf(false) } @@ -113,20 +112,13 @@ fun AppointmentEditScreen( Spacer(modifier = Modifier.height(16.dp)) if (showDatePicker) { - CustomDatePickerDialog( - selectedDateTime = selectedAppointmentDate, // Pass the previously selected date + CustomDateTimePickerDialog( + selectedDateTime = selectedAppointmentDateTime, // Pass the previously selected date onDismiss = { showDatePicker = false }, onDateTimeSelected = { dateTime -> - selectedAppointmentDate = dateTime - selectedAppointmentTime = Calendar.getInstance().apply { - timeInMillis = dateTime - }.get(Calendar.HOUR_OF_DAY) * 3600000L + // Convert hours to ms - Calendar.getInstance().apply { - timeInMillis = dateTime - }.get(Calendar.MINUTE) * 60000L // Convert minutes to ms + selectedAppointmentDateTime = dateTime } - ) } @@ -159,8 +151,8 @@ fun AppointmentEditScreen( } Spacer(modifier = Modifier.height(8.dp)) - selectedAppointmentDate.let { - val dateTimeString = SimpleDateFormat("MMM dd, yyyy HH:mm", Locale.getDefault()).format(Date(it)) + selectedAppointmentDateTime.let { + val dateTimeString = SimpleDateFormat("MMM dd, yyyy 'at' HH:mm", Locale.getDefault()).format(Date(it)) Text( text = "Selected Date and Time: $dateTimeString", modifier = Modifier.padding(2.dp), @@ -170,22 +162,6 @@ fun AppointmentEditScreen( Spacer(modifier = Modifier.height(16.dp)) -// OutlinedButton( -// onClick = { -// if (petName.isNotBlank() && description.isNotBlank()) { -// viewModel.editAppointment(appointmentId!!.toLong(), petName, description, selectedAppointmentDate, selectedAppointmentTime, category) -// navController.navigateUp() -// } -// }, -// modifier = Modifier.fillMaxWidth(), -// colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary), -// ) { -// Text( -// "Save Changes", -// style = MaterialTheme.typography.labelMedium -// ) -// } - OutlinedButton( modifier = Modifier.width(200.dp), colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary), @@ -195,8 +171,7 @@ fun AppointmentEditScreen( appointmentId!!.toLong(), petName, description, - selectedAppointmentDate, - selectedAppointmentTime, + selectedAppointmentDateTime, category ) navController.navigateUp() diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentViewModel.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentViewModel.kt index 463d901..6839d11 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentViewModel.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentViewModel.kt @@ -33,8 +33,8 @@ class AppointmentViewModel(private val appointmentRepository: AppointmentReposit } // Add a new appointment - fun addAppointment(petName: String, description: String, appointmentDate: Long, appointmentTime: Long, category: String) { - val appointment = AppointmentEntity(petName = petName, description = description, appointmentDate = appointmentDate, appointmentTime = appointmentTime, category = category) + fun addAppointment(petName: String, description: String, appointmentDateTime: Long, category: String) { + val appointment = AppointmentEntity(petName = petName, description = description, appointmentDateTime = appointmentDateTime, category = category) viewModelScope.launch { appointmentRepository.insertAppointment(appointment) loadAppointments() // Reload appointments from the repository to update the list @@ -58,9 +58,9 @@ class AppointmentViewModel(private val appointmentRepository: AppointmentReposit } } - fun editAppointment(appointmentId: Long, petName: String, description: String, appointmentDate: Long, appointmentTime: Long, category: String) { + fun editAppointment(appointmentId: Long, petName: String, description: String, appointmentDateTime: Long, category: String) { viewModelScope.launch { - appointmentRepository.updateAppointment(appointmentId, petName, description, appointmentDate, appointmentTime, category) + appointmentRepository.updateAppointment(appointmentId, petName, description, appointmentDateTime, category) loadAppointments() // Refresh the appointment list } } -- GitLab From 0d485112b3d10d744a6a93cad2783bb788eb6d6f Mon Sep 17 00:00:00 2001 From: Sofiia-Khrystyna <sonia030605@gmail.com> Date: Fri, 17 Jan 2025 13:54:30 +0100 Subject: [PATCH 06/10] :card_file_box:overview related code is moved to separate file from Navigation --- .idea/vcs.xml | 6 ++ .../java/at/ac/fhstp/pawwatch/MainActivity.kt | 1 + .../java/at/ac/fhstp/pawwatch/Navigation.kt | 86 +------------------ .../at/ac/fhstp/pawwatch/ui/OverviewScreen.kt | 81 +++++++++++++++++ 4 files changed, 89 insertions(+), 85 deletions(-) create mode 100644 .idea/vcs.xml create mode 100644 app/src/main/java/at/ac/fhstp/pawwatch/ui/OverviewScreen.kt diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="VcsDirectoryMappings"> + <mapping directory="$PROJECT_DIR$" vcs="Git" /> + </component> +</project> \ No newline at end of file diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/MainActivity.kt b/app/src/main/java/at/ac/fhstp/pawwatch/MainActivity.kt index f2c9db2..639ed6e 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/MainActivity.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/MainActivity.kt @@ -20,6 +20,7 @@ import at.ac.fhstp.pawwatch.ui.AppointmentDetailScreen import at.ac.fhstp.pawwatch.ui.AppointmentEditScreen import at.ac.fhstp.pawwatch.ui.AppointmentViewModelFactory import at.ac.fhstp.pawwatch.ui.AddAppointmentScreen +import at.ac.fhstp.pawwatch.ui.OverviewScreen import at.ac.fhstp.pawwatch.ui.theme.PawWatchTheme class MainActivity : ComponentActivity() { diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/Navigation.kt b/app/src/main/java/at/ac/fhstp/pawwatch/Navigation.kt index 86c0ae3..d03c9e0 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/Navigation.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/Navigation.kt @@ -1,34 +1,12 @@ package at.ac.fhstp.pawwatch -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -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.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.List import androidx.compose.material.icons.filled.Add -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.NavigationBar -import androidx.compose.material3.NavigationBarItem -import androidx.compose.material3.OutlinedCard -import androidx.compose.material3.Text +import androidx.compose.material3.* import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp import androidx.navigation.NavController import androidx.navigation.compose.currentBackStackEntryAsState -import at.ac.fhstp.pawwatch.data.db.AppointmentEntity -import at.ac.fhstp.pawwatch.ui.AppointmentViewModel -import java.sql.Date -import java.text.SimpleDateFormat -import java.util.Locale sealed class Screens(val route: String) { @@ -62,66 +40,4 @@ fun BottomNavigationBar(navController: NavController) { label = { Text("Appointments") } ) } -} - -@Composable -fun OverviewScreen(viewModel: AppointmentViewModel, navController: NavController) { - val appointments by viewModel.appointments.collectAsState() - - LazyColumn( - modifier = Modifier.fillMaxWidth().padding(16.dp) - ) { - items(appointments) { appointment -> - AppointmentCard(appointment = appointment) { - navController.navigate(Screens.AppointmentDetails(appointmentId = appointment.id.toString()).createRoute( - appointment.id.toString() - )) - } - Spacer(modifier = Modifier.height(14.dp)) - } - } -} - -@Composable -fun AppointmentCard(appointment: AppointmentEntity, onClick: () -> Unit) { - OutlinedCard( - modifier = Modifier - .fillMaxWidth() - .padding(start = 16.dp, top = 8.dp, end = 16.dp, bottom = 0.dp), - onClick = onClick, - colors = CardDefaults.outlinedCardColors( - containerColor = MaterialTheme.colorScheme.secondary, - contentColor = MaterialTheme.colorScheme.onPrimary - ) - ) { - Column(modifier = Modifier.padding(16.dp)) { - Text( - appointment.petName, - style = MaterialTheme.typography.bodyLarge - ) - Spacer(modifier = Modifier.height(3.dp)) - - Text( - appointment.category, - style = MaterialTheme.typography.bodyMedium - ) - Spacer(modifier = Modifier.height(10.dp)) - - Text( - appointment.description, - style = MaterialTheme.typography.bodyMedium - ) - Spacer(modifier = Modifier.height(14.dp)) - - val date = Date(appointment.appointmentDateTime) - - // Use SimpleDateFormat for 24-hour time format (HH:mm) - val dateFormat = SimpleDateFormat("MMM dd, yyyy 'at' HH:mm", Locale.getDefault()) - - Text( - dateFormat.format(date), - style = MaterialTheme.typography.bodyMedium - ) - } - } } \ No newline at end of file diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/OverviewScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/OverviewScreen.kt new file mode 100644 index 0000000..2c38030 --- /dev/null +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/OverviewScreen.kt @@ -0,0 +1,81 @@ +package at.ac.fhstp.pawwatch.ui + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedCard +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.navigation.NavController +import at.ac.fhstp.pawwatch.Screens +import at.ac.fhstp.pawwatch.data.db.AppointmentEntity +import java.sql.Date +import java.text.SimpleDateFormat +import java.util.Locale + +@Composable +fun OverviewScreen(viewModel: AppointmentViewModel, navController: NavController) { + val appointments by viewModel.appointments.collectAsState() + + LazyColumn( + modifier = Modifier.fillMaxWidth().padding(16.dp) + ) { + items(appointments) { appointment -> + AppointmentCard(appointment = appointment) { + navController.navigate( + Screens.AppointmentDetails(appointmentId = appointment.id.toString()).createRoute( + appointment.id.toString() + )) + } + Spacer(modifier = Modifier.height(14.dp)) + } + } +} + +@Composable +fun AppointmentCard(appointment: AppointmentEntity, onClick: () -> Unit) { + OutlinedCard( + modifier = Modifier + .fillMaxWidth() + .padding(start = 16.dp, top = 8.dp, end = 16.dp, bottom = 0.dp), + onClick = onClick, + colors = CardDefaults.outlinedCardColors( + containerColor = MaterialTheme.colorScheme.secondary, + contentColor = MaterialTheme.colorScheme.onPrimary + ) + ) { + Column(modifier = Modifier.padding(16.dp)) { + Text( + appointment.petName, + style = MaterialTheme.typography.bodyLarge + ) + Spacer(modifier = Modifier.height(3.dp)) + + Text( + appointment.category, + style = MaterialTheme.typography.bodyMedium + ) + Spacer(modifier = Modifier.height(10.dp)) + + Text( + appointment.description, + style = MaterialTheme.typography.bodyMedium + ) + Spacer(modifier = Modifier.height(14.dp)) + + val date = Date(appointment.appointmentDateTime) + val dateFormat = SimpleDateFormat("MMM dd, yyyy 'at' HH:mm", Locale.getDefault()) + + Text( + dateFormat.format(date), + style = MaterialTheme.typography.bodyMedium + ) + } + } +} \ No newline at end of file -- GitLab From b1f1de2a892b0949f775cf2cd1faae938d9b9708 Mon Sep 17 00:00:00 2001 From: Sofiia-Khrystyna <sonia030605@gmail.com> Date: Fri, 17 Jan 2025 22:10:51 +0100 Subject: [PATCH 07/10] :art: added shadowing for buttons + pop-up on the Add page as an error handler --- .../fhstp/pawwatch/ui/AddAppointmentScreen.kt | 23 ++++++-- .../pawwatch/ui/AppointmentDetailScreen.kt | 22 +++++--- .../pawwatch/ui/AppointmentEditScreen.kt | 20 ++----- .../at/ac/fhstp/pawwatch/ui/OverviewScreen.kt | 53 ++++++++++++++----- .../at/ac/fhstp/pawwatch/ui/theme/Color.kt | 3 +- .../at/ac/fhstp/pawwatch/ui/theme/Theme.kt | 1 + 6 files changed, 84 insertions(+), 38 deletions(-) diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt index 82eae84..9feac2c 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt @@ -7,6 +7,7 @@ import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.window.Dialog @@ -26,6 +27,7 @@ fun AddAppointmentScreen( // Store the selected appointment date var selectedAppointmentDateTime by remember { mutableStateOf<Long?>(null) } + var errorAddAppointment by remember { mutableStateOf(false) } // DatePicker Dialog state var showDatePicker by remember { mutableStateOf(false) } @@ -131,6 +133,21 @@ fun AddAppointmentScreen( ) } + if (errorAddAppointment) { + AlertDialog( + onDismissRequest = { errorAddAppointment = false }, + title = { Text("Could not add an appointment") }, + text = { Text("Please fill in all required fields and select a date and time") }, + confirmButton = { + Button( + onClick = { errorAddAppointment = false } + ) { + Text("OK") + } + } + ) + } + OutlinedButton( onClick = { showDatePicker = true }, modifier = Modifier.fillMaxWidth(), @@ -164,9 +181,9 @@ fun AddAppointmentScreen( modifier = Modifier.width(200.dp), colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary), onClick = { - if (petName.value.isNotBlank() && selectedAppointmentDateTime != null) { + if (petName.value.isNotBlank() && category.value.isNotBlank() && selectedAppointmentDateTime != null) { if (description.value.isBlank()) { description.value = "No Description" } - if (category.value.isBlank()) { category.value = "General" } + //if (category.value.isBlank()) { category.value = "General" } // Calls the onAddAppointmentClick with selected date and time onAddAppointmentClick( petName.value, @@ -175,7 +192,7 @@ fun AddAppointmentScreen( category.value ) } - + else errorAddAppointment = true }, elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp) ) { diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentDetailScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentDetailScreen.kt index b190a32..330311a 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentDetailScreen.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentDetailScreen.kt @@ -36,7 +36,8 @@ fun AppointmentDetailScreen( navController.navigateUp() }, modifier = Modifier.align(Alignment.Start), - colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.background) + colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.background), + elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp) ) { Icon( imageVector = Icons.AutoMirrored.Filled.ArrowBack, @@ -46,7 +47,8 @@ fun AppointmentDetailScreen( Spacer(modifier = Modifier.width(6.dp)) Text( text = "Back", - color = text // same colour variable as for the icon + color = text, // same colour variable as for the icon + style = MaterialTheme.typography.labelMedium ) } @@ -94,9 +96,13 @@ fun AppointmentDetailScreen( // Navigate using the sealed class route navController.navigate(Screens.EditAppointment(it.id.toString()).createRoute(it.id.toString())) }, - modifier = Modifier.width(150.dp) + modifier = Modifier.width(150.dp), + elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp) ) { - Text("Edit") + Text( + text = "Edit", + style = MaterialTheme.typography.labelMedium + ) } Spacer(modifier = Modifier.width(40.dp)) @@ -108,9 +114,13 @@ fun AppointmentDetailScreen( viewModel.deleteAppointment(it.id.toLong()) // Call delete logic navController.navigateUp() }, - modifier = Modifier.width(150.dp) + modifier = Modifier.width(150.dp), + elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp) ) { - Text("Delete") + Text( + text = "Delete", + style = MaterialTheme.typography.labelMedium + ) } } } diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentEditScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentEditScreen.kt index 0f89e76..8e1067c 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentEditScreen.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentEditScreen.kt @@ -30,7 +30,6 @@ fun AppointmentEditScreen( var category by remember { mutableStateOf(appointment?.category ?: "") } var showDatePicker by remember { mutableStateOf(false) } - var showTimePicker by remember { mutableStateOf(false) } Column( modifier = Modifier @@ -44,7 +43,8 @@ fun AppointmentEditScreen( navController.navigateUp() }, modifier = Modifier.align(Alignment.Start), - colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.background) + colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.background), + elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp) ) { Icon( imageVector = Icons.AutoMirrored.Filled.ArrowBack, @@ -54,7 +54,8 @@ fun AppointmentEditScreen( Spacer(modifier = Modifier.width(6.dp)) Text( text = "Back", - color = text // same colour variable as for the icon + color = text, // same colour variable as for the icon + style = MaterialTheme.typography.labelMedium ) } @@ -122,17 +123,6 @@ fun AppointmentEditScreen( ) } - // Display formatted date and time -// val formattedDate = DateFormat.getDateInstance().format(Date(selectedAppointmentDate)) -// val timeFormat = SimpleDateFormat("HH:mm", Locale.getDefault()) -// val formattedTime = timeFormat.format(Date(selectedAppointmentTime)) -// -// Text( -// "Selected Date and Time: $formattedDate at $formattedTime", -// modifier = Modifier.padding(2.dp), -// style = MaterialTheme.typography.labelMedium -// ) - Spacer(modifier = Modifier.height(8.dp)) OutlinedButton( @@ -142,7 +132,7 @@ fun AppointmentEditScreen( containerColor = MaterialTheme.colorScheme.tertiary, contentColor = MaterialTheme.colorScheme.onPrimary ), - elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 4.dp) + elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp) ) { Text( text = "Change Date or Time", diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/OverviewScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/OverviewScreen.kt index 2c38030..ca20d21 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/OverviewScreen.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/OverviewScreen.kt @@ -3,6 +3,7 @@ package at.ac.fhstp.pawwatch.ui import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items +import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.CardDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedCard @@ -10,6 +11,7 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.navigation.NavController @@ -20,35 +22,60 @@ import java.text.SimpleDateFormat import java.util.Locale @Composable -fun OverviewScreen(viewModel: AppointmentViewModel, navController: NavController) { +fun OverviewScreen( + viewModel: AppointmentViewModel, + navController: NavController +) { val appointments by viewModel.appointments.collectAsState() - LazyColumn( - modifier = Modifier.fillMaxWidth().padding(16.dp) + Column( + modifier = Modifier + .fillMaxSize() + .padding(35.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center ) { - items(appointments) { appointment -> - AppointmentCard(appointment = appointment) { - navController.navigate( - Screens.AppointmentDetails(appointmentId = appointment.id.toString()).createRoute( - appointment.id.toString() - )) + Spacer(modifier = Modifier.height(10.dp)) + + Text( + text = "Your Appointments", + style = MaterialTheme.typography.headlineMedium + ) + + Spacer(modifier = Modifier.height(20.dp)) + + LazyColumn( + modifier = Modifier.fillMaxWidth() + ) { + items(appointments) { appointment -> + AppointmentCard(appointment = appointment) { + navController.navigate( + Screens.AppointmentDetails(appointmentId = appointment.id.toString()).createRoute( + appointment.id.toString() + )) + } + Spacer(modifier = Modifier.height(14.dp)) } - Spacer(modifier = Modifier.height(14.dp)) } } + } @Composable -fun AppointmentCard(appointment: AppointmentEntity, onClick: () -> Unit) { +fun AppointmentCard( + appointment: AppointmentEntity, + onClick: () -> Unit +) { OutlinedCard( modifier = Modifier .fillMaxWidth() - .padding(start = 16.dp, top = 8.dp, end = 16.dp, bottom = 0.dp), + .padding(top = 8.dp), onClick = onClick, colors = CardDefaults.outlinedCardColors( containerColor = MaterialTheme.colorScheme.secondary, contentColor = MaterialTheme.colorScheme.onPrimary - ) + ), + elevation = CardDefaults.elevatedCardElevation(defaultElevation = 3.dp) ) { Column(modifier = Modifier.padding(16.dp)) { Text( diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Color.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Color.kt index 13f9b18..22987b9 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Color.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Color.kt @@ -5,6 +5,7 @@ import androidx.compose.ui.graphics.Color val bg = Color(0xFFFDE9C3) val buttonBg = Color(0xFFFFBA66) val lightButtonBg = Color(0xFFFFCE93) +val appointmentBg = Color(0xFFF8F8F8) val text = Color(0xFF000000) val fieldBg = Color(0xFFFFF4DE) -val deleteButtonBg = Color(0xFFbf4342) \ No newline at end of file +val deleteButtonBg = Color(0xFFE04F47) \ No newline at end of file diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Theme.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Theme.kt index c6c272e..8792eb1 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Theme.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Theme.kt @@ -10,6 +10,7 @@ private val AppColorScheme = lightColorScheme( onPrimary = text, secondary = fieldBg, tertiary = lightButtonBg, + tertiaryContainer = appointmentBg, error = deleteButtonBg ) -- GitLab From 913ac414c6c774369a471ace50b3c61c1d59a848 Mon Sep 17 00:00:00 2001 From: Sofiia-Khrystyna <sonia030605@gmail.com> Date: Sat, 18 Jan 2025 00:20:37 +0100 Subject: [PATCH 08/10] :memo: the description is now shorten on the overview page + the height of the description field is set with scroll --- .../java/at/ac/fhstp/pawwatch/MainActivity.kt | 12 +- .../{AddAppointmentScreen.kt => AddScreen.kt} | 17 +- .../pawwatch/ui/AppointmentEditScreen.kt | 179 --------------- ...intmentDetailScreen.kt => DetailScreen.kt} | 19 +- .../at/ac/fhstp/pawwatch/ui/EditScreen.kt | 206 ++++++++++++++++++ .../at/ac/fhstp/pawwatch/ui/OverviewScreen.kt | 11 +- 6 files changed, 245 insertions(+), 199 deletions(-) rename app/src/main/java/at/ac/fhstp/pawwatch/ui/{AddAppointmentScreen.kt => AddScreen.kt} (95%) delete mode 100644 app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentEditScreen.kt rename app/src/main/java/at/ac/fhstp/pawwatch/ui/{AppointmentDetailScreen.kt => DetailScreen.kt} (89%) create mode 100644 app/src/main/java/at/ac/fhstp/pawwatch/ui/EditScreen.kt diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/MainActivity.kt b/app/src/main/java/at/ac/fhstp/pawwatch/MainActivity.kt index 639ed6e..2ae6fa2 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/MainActivity.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/MainActivity.kt @@ -16,10 +16,10 @@ import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import at.ac.fhstp.pawwatch.data.AppointmentRepository import at.ac.fhstp.pawwatch.data.db.AppointmentDatabase -import at.ac.fhstp.pawwatch.ui.AppointmentDetailScreen -import at.ac.fhstp.pawwatch.ui.AppointmentEditScreen +import at.ac.fhstp.pawwatch.ui.DetailScreen +import at.ac.fhstp.pawwatch.ui.EditScreen import at.ac.fhstp.pawwatch.ui.AppointmentViewModelFactory -import at.ac.fhstp.pawwatch.ui.AddAppointmentScreen +import at.ac.fhstp.pawwatch.ui.AddScreen import at.ac.fhstp.pawwatch.ui.OverviewScreen import at.ac.fhstp.pawwatch.ui.theme.PawWatchTheme @@ -54,7 +54,7 @@ class MainActivity : ComponentActivity() { OverviewScreen(viewModel, navController) } composable(Screens.AddAppointment.route) { - AddAppointmentScreen( + AddScreen( viewModel = viewModel, onAppointmentClick = { appointment -> // Navigate to the appointment details screen @@ -74,7 +74,7 @@ class MainActivity : ComponentActivity() { } composable(Screens.AppointmentDetails("appointmentId").route) { backStackEntry -> val appointmentId = backStackEntry.arguments?.getString("appointmentId") - AppointmentDetailScreen( + DetailScreen( appointmentId = appointmentId, viewModel = viewModel, navController = navController @@ -83,7 +83,7 @@ class MainActivity : ComponentActivity() { composable(Screens.EditAppointment("{appointmentId}").route) { backStackEntry -> val appointmentId = backStackEntry.arguments?.getString("appointmentId") - AppointmentEditScreen( + EditScreen( appointmentId = appointmentId, viewModel = viewModel, navController = navController diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddScreen.kt similarity index 95% rename from app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt rename to app/src/main/java/at/ac/fhstp/pawwatch/ui/AddScreen.kt index 9feac2c..e461123 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddAppointmentScreen.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AddScreen.kt @@ -3,11 +3,12 @@ package at.ac.fhstp.pawwatch.ui import android.widget.CalendarView import android.widget.NumberPicker import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.window.Dialog @@ -18,7 +19,7 @@ import java.util.* @OptIn(ExperimentalMaterial3Api::class) @Composable -fun AddAppointmentScreen( +fun AddScreen( viewModel: AppointmentViewModel, onAppointmentClick: (AppointmentEntity) -> Unit, onAddAppointmentClick: (String, String, Long, String) -> Unit, @@ -107,7 +108,16 @@ fun AddAppointmentScreen( OutlinedTextField( value = description.value, onValueChange = { description.value = it }, - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .fillMaxWidth() + .heightIn(max = 100.dp) // Restrict the height + .let { modifier -> + if (description.value.length > 200) { + modifier.verticalScroll(rememberScrollState()) // Enable scroll if content exceeds 200 characters + } else { + modifier + } + }, colors = TextFieldDefaults.outlinedTextFieldColors( containerColor = MaterialTheme.colorScheme.secondary ), @@ -119,6 +129,7 @@ fun AddAppointmentScreen( ) } ) + Spacer(modifier = Modifier.height(20.dp)) diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentEditScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentEditScreen.kt deleted file mode 100644 index 8e1067c..0000000 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentEditScreen.kt +++ /dev/null @@ -1,179 +0,0 @@ -package at.ac.fhstp.pawwatch.ui - -import androidx.compose.foundation.layout.* -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowBack -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import androidx.navigation.NavController -import at.ac.fhstp.pawwatch.ui.theme.text -import java.sql.Date -import java.text.DateFormat -import java.text.SimpleDateFormat -import java.util.Calendar -import java.util.Locale - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun AppointmentEditScreen( - appointmentId: String?, - viewModel: AppointmentViewModel, - navController: NavController -) { - val appointment = appointmentId?.let { id -> viewModel.getAppointmentById(id.toLong()) } - var petName by remember { mutableStateOf(appointment?.petName ?: "") } - var description by remember { mutableStateOf(appointment?.description ?: "") } - var selectedAppointmentDateTime by remember { mutableLongStateOf(appointment?.appointmentDateTime ?: System.currentTimeMillis()) } - var category by remember { mutableStateOf(appointment?.category ?: "") } - - var showDatePicker by remember { mutableStateOf(false) } - - Column( - modifier = Modifier - .fillMaxWidth() - .padding(35.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - // Back Button - OutlinedButton( - onClick = { - navController.navigateUp() - }, - modifier = Modifier.align(Alignment.Start), - colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.background), - elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp) - ) { - Icon( - imageVector = Icons.AutoMirrored.Filled.ArrowBack, - contentDescription = "Back", - tint = text // "text" is the variable which contains black colour in Color.kt - ) - Spacer(modifier = Modifier.width(6.dp)) - Text( - text = "Back", - color = text, // same colour variable as for the icon - style = MaterialTheme.typography.labelMedium - ) - } - - Spacer(modifier = Modifier.height(40.dp)) - - Text( - text = "Pet Name:", - modifier = Modifier.align(Alignment.Start) - ) - - OutlinedTextField( - value = petName, - onValueChange = { petName = it }, - modifier = Modifier.fillMaxWidth(), - colors = TextFieldDefaults.outlinedTextFieldColors( - containerColor = MaterialTheme.colorScheme.secondary - ), - textStyle = MaterialTheme.typography.bodyMedium - ) - - Spacer(modifier = Modifier.height(16.dp)) - - Text( - text = "Appointment Category:", - modifier = Modifier.align(Alignment.Start) - ) - - OutlinedTextField( - value = category, - onValueChange = { category = it }, - modifier = Modifier.fillMaxWidth(), - colors = TextFieldDefaults.outlinedTextFieldColors( - containerColor = MaterialTheme.colorScheme.secondary - ), - textStyle = MaterialTheme.typography.bodyMedium - ) - - Spacer(modifier = Modifier.height(16.dp)) - - Text( - text = "Description:", - modifier = Modifier.align(Alignment.Start) - ) - - OutlinedTextField( - value = description, - onValueChange = { description = it }, - modifier = Modifier.fillMaxWidth(), - colors = TextFieldDefaults.outlinedTextFieldColors( - containerColor = MaterialTheme.colorScheme.secondary - ), - textStyle = MaterialTheme.typography.bodyMedium - ) - - Spacer(modifier = Modifier.height(16.dp)) - - if (showDatePicker) { - CustomDateTimePickerDialog( - selectedDateTime = selectedAppointmentDateTime, // Pass the previously selected date - - onDismiss = { showDatePicker = false }, - onDateTimeSelected = { dateTime -> - selectedAppointmentDateTime = dateTime - } - ) - } - - Spacer(modifier = Modifier.height(8.dp)) - - OutlinedButton( - onClick = { showDatePicker = true }, - modifier = Modifier.fillMaxWidth(), - colors = ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.tertiary, - contentColor = MaterialTheme.colorScheme.onPrimary - ), - elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp) - ) { - Text( - text = "Change Date or Time", - style = MaterialTheme.typography.labelMedium - ) - } - - Spacer(modifier = Modifier.height(8.dp)) - selectedAppointmentDateTime.let { - val dateTimeString = SimpleDateFormat("MMM dd, yyyy 'at' HH:mm", Locale.getDefault()).format(Date(it)) - Text( - text = "Selected Date and Time: $dateTimeString", - modifier = Modifier.padding(2.dp), - style = MaterialTheme.typography.labelSmall - ) - } - - Spacer(modifier = Modifier.height(16.dp)) - - OutlinedButton( - modifier = Modifier.width(200.dp), - colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary), - onClick = { - if (petName.isNotBlank()) { - viewModel.editAppointment( - appointmentId!!.toLong(), - petName, - description, - selectedAppointmentDateTime, - category - ) - navController.navigateUp() - } - - }, - elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp) - ) { - Text( - text = "Save Changes", - style = MaterialTheme.typography.labelMedium - ) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentDetailScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/DetailScreen.kt similarity index 89% rename from app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentDetailScreen.kt rename to app/src/main/java/at/ac/fhstp/pawwatch/ui/DetailScreen.kt index 330311a..38940db 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/AppointmentDetailScreen.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/DetailScreen.kt @@ -11,13 +11,12 @@ import androidx.compose.ui.unit.dp import androidx.navigation.NavController import at.ac.fhstp.pawwatch.Screens import at.ac.fhstp.pawwatch.ui.theme.text -import java.text.DateFormat import java.text.SimpleDateFormat import java.util.Date import java.util.Locale @Composable -fun AppointmentDetailScreen( +fun DetailScreen( appointmentId: String?, viewModel: AppointmentViewModel, navController: NavController @@ -26,9 +25,10 @@ fun AppointmentDetailScreen( Column( modifier = Modifier - .fillMaxWidth() + .fillMaxSize() .padding(35.dp), - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center ) { // Back Button OutlinedButton( @@ -58,15 +58,16 @@ fun AppointmentDetailScreen( Text( it.petName, style = MaterialTheme.typography.headlineMedium, - modifier = Modifier.padding(2.dp) + //modifier = Modifier.padding(2.dp) ) + Spacer(modifier = Modifier.height(9.dp)) Text( it.category, style = MaterialTheme.typography.bodyLarge, - modifier = Modifier.padding(2.dp) + //modifier = Modifier.padding(2.dp) ) - Spacer(modifier = Modifier.height(10.dp)) + Spacer(modifier = Modifier.height(20.dp)) val date = Date(appointment.appointmentDateTime) @@ -75,7 +76,7 @@ fun AppointmentDetailScreen( Text( dateFormat.format(date), - style = MaterialTheme.typography.bodyMedium + style = MaterialTheme.typography.labelSmall ) Spacer(modifier = Modifier.height(20.dp)) @@ -86,7 +87,7 @@ fun AppointmentDetailScreen( modifier = Modifier.padding(2.dp) ) - Spacer(modifier = Modifier.height(30.dp)) + Spacer(modifier = Modifier.height(50.dp)) Row { // Edit Button diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/EditScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/EditScreen.kt new file mode 100644 index 0000000..0e91f39 --- /dev/null +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/EditScreen.kt @@ -0,0 +1,206 @@ +package at.ac.fhstp.pawwatch.ui + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.navigation.NavController +import at.ac.fhstp.pawwatch.ui.theme.text +import java.sql.Date +import java.text.SimpleDateFormat +import java.util.Locale + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun EditScreen( + appointmentId: String?, + viewModel: AppointmentViewModel, + navController: NavController +) { + val appointment = appointmentId?.let { id -> viewModel.getAppointmentById(id.toLong()) } + var petName by remember { mutableStateOf(appointment?.petName ?: "") } + var description by remember { mutableStateOf(appointment?.description ?: "") } + var selectedAppointmentDateTime by remember { mutableLongStateOf(appointment?.appointmentDateTime ?: System.currentTimeMillis()) } + var category by remember { mutableStateOf(appointment?.category ?: "") } + + var showDatePicker by remember { mutableStateOf(false) } + + Box( + modifier = Modifier + .fillMaxSize() + .padding(35.dp) // Padding for spacing within the screen + ) { + // Back Button at Top-Start + OutlinedButton( + onClick = { + navController.navigateUp() + }, + modifier = Modifier + .align(Alignment.TopStart), // Aligns the button at the top-left corner + //.padding(8.dp), // Add padding around the button + colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.background), + elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp), + ) { + Icon( + imageVector = Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = "Back", + tint = text + ) + Spacer(modifier = Modifier.width(6.dp)) + Text( + text = "Back", + color = text, + style = MaterialTheme.typography.labelMedium + ) + } + + // Rest of the content + Column( + modifier = Modifier + .fillMaxSize() + .padding(top = 45.dp), // Leave space for the back button + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Text( + text = "Edit Appointment", + style = MaterialTheme.typography.headlineMedium + ) + + Spacer(modifier = Modifier.height(25.dp)) + + Text( + text = "Pet Name:", + modifier = Modifier.align(Alignment.Start) + ) + Spacer(modifier = Modifier.height(5.dp)) + + OutlinedTextField( + value = petName, + onValueChange = { petName = it }, + modifier = Modifier.fillMaxWidth(), + colors = TextFieldDefaults.outlinedTextFieldColors( + containerColor = MaterialTheme.colorScheme.secondary + ), + textStyle = MaterialTheme.typography.bodyMedium + ) + + Spacer(modifier = Modifier.height(20.dp)) + + Text( + text = "Appointment Category:", + modifier = Modifier.align(Alignment.Start) + ) + Spacer(modifier = Modifier.height(5.dp)) + + OutlinedTextField( + value = category, + onValueChange = { category = it }, + modifier = Modifier.fillMaxWidth(), + colors = TextFieldDefaults.outlinedTextFieldColors( + containerColor = MaterialTheme.colorScheme.secondary + ), + textStyle = MaterialTheme.typography.bodyMedium + ) + + Spacer(modifier = Modifier.height(20.dp)) + + Text( + text = "Description (Optional):", + modifier = Modifier.align(Alignment.Start) + ) + Spacer(modifier = Modifier.height(5.dp)) + + OutlinedTextField( + value = description, + onValueChange = { description = it }, + modifier = Modifier + .fillMaxWidth() + .heightIn(max = 100.dp) // Restrict the height + .let { modifier -> + if (description.length > 200) { + modifier.verticalScroll(rememberScrollState()) // Enable scroll if content exceeds 200 characters + } else { + modifier + } + }, + colors = TextFieldDefaults.outlinedTextFieldColors( + containerColor = MaterialTheme.colorScheme.secondary + ), + textStyle = MaterialTheme.typography.bodyMedium + ) + + + Spacer(modifier = Modifier.height(20.dp)) + + if (showDatePicker) { + CustomDateTimePickerDialog( + selectedDateTime = selectedAppointmentDateTime, + onDismiss = { showDatePicker = false }, + onDateTimeSelected = { dateTime -> + selectedAppointmentDateTime = dateTime + } + ) + } + + Spacer(modifier = Modifier.height(8.dp)) + + OutlinedButton( + onClick = { showDatePicker = true }, + modifier = Modifier.fillMaxWidth(), + colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.tertiary, + contentColor = MaterialTheme.colorScheme.onPrimary + ), + elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp) + ) { + Text( + text = "Change Date or Time", + style = MaterialTheme.typography.labelMedium + ) + } + + Spacer(modifier = Modifier.height(8.dp)) + selectedAppointmentDateTime.let { + val dateTimeString = + SimpleDateFormat("MMM dd, yyyy 'at' HH:mm", Locale.getDefault()).format(Date(it)) + Text( + text = "Selected Date and Time: $dateTimeString", + modifier = Modifier.padding(2.dp), + style = MaterialTheme.typography.labelSmall + ) + } + + Spacer(modifier = Modifier.height(35.dp)) + + OutlinedButton( + modifier = Modifier.width(200.dp), + colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary), + onClick = { + if (petName.isNotBlank()) { + viewModel.editAppointment( + appointmentId!!.toLong(), + petName, + description, + selectedAppointmentDateTime, + category + ) + navController.navigateUp() + } + }, + elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp) + ) { + Text( + text = "Save Changes", + style = MaterialTheme.typography.labelMedium + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/OverviewScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/OverviewScreen.kt index ca20d21..012224e 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/OverviewScreen.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/OverviewScreen.kt @@ -42,7 +42,7 @@ fun OverviewScreen( style = MaterialTheme.typography.headlineMedium ) - Spacer(modifier = Modifier.height(20.dp)) + Spacer(modifier = Modifier.height(30.dp)) LazyColumn( modifier = Modifier.fillMaxWidth() @@ -90,12 +90,19 @@ fun AppointmentCard( ) Spacer(modifier = Modifier.height(10.dp)) + val shortenDescription = if (appointment.description.length > 70) { + "${appointment.description.take(70)}..." + } else { + appointment.description + } + Text( - appointment.description, + shortenDescription, style = MaterialTheme.typography.bodyMedium ) Spacer(modifier = Modifier.height(14.dp)) + val date = Date(appointment.appointmentDateTime) val dateFormat = SimpleDateFormat("MMM dd, yyyy 'at' HH:mm", Locale.getDefault()) -- GitLab From 18bb5ebee858fb35cfd2c867968e102ce2b95a76 Mon Sep 17 00:00:00 2001 From: Sofiia-Khrystyna <sonia030605@gmail.com> Date: Sat, 18 Jan 2025 01:42:52 +0100 Subject: [PATCH 09/10] :art: added filter buttons + colouring of the missed appointments and the ones that are tmrw are done --- .../at/ac/fhstp/pawwatch/ui/OverviewScreen.kt | 112 +++++++++++++++++- .../at/ac/fhstp/pawwatch/ui/theme/Color.kt | 3 +- .../at/ac/fhstp/pawwatch/ui/theme/Theme.kt | 1 + 3 files changed, 109 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/OverviewScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/OverviewScreen.kt index 012224e..2c96abf 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/OverviewScreen.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/OverviewScreen.kt @@ -6,11 +6,15 @@ import androidx.compose.foundation.lazy.items import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.CardDefaults import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedCard import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp @@ -19,6 +23,7 @@ import at.ac.fhstp.pawwatch.Screens import at.ac.fhstp.pawwatch.data.db.AppointmentEntity import java.sql.Date import java.text.SimpleDateFormat +import java.util.Calendar import java.util.Locale @Composable @@ -27,13 +32,26 @@ fun OverviewScreen( navController: NavController ) { val appointments by viewModel.appointments.collectAsState() + // State to store the filter type + var filterType by remember { mutableStateOf(FilterType.ALL) } + + // Filter appointments based on the selected filter type + val filteredAppointments = when (filterType) { + FilterType.PAST -> appointments.filter { it.appointmentDateTime < System.currentTimeMillis() } + FilterType.UPCOMING -> appointments.filter { it.appointmentDateTime >= System.currentTimeMillis() } + else -> appointments // ALL + } + + // Sort appointments by date + val sortedAppointments = filteredAppointments.sortedBy { it.appointmentDateTime } + Column( modifier = Modifier .fillMaxSize() .padding(35.dp), horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center + //verticalArrangement = Arrangement.Center ) { Spacer(modifier = Modifier.height(10.dp)) @@ -44,10 +62,25 @@ fun OverviewScreen( Spacer(modifier = Modifier.height(30.dp)) + // Filter buttons + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceEvenly, + verticalAlignment = Alignment.CenterVertically, + ) { + FilterButton("All", FilterType.ALL, filterType) { filterType = it } + FilterButton("Past", FilterType.PAST, filterType) { filterType = it } + FilterButton("Upcoming", FilterType.UPCOMING, filterType) { filterType = it } + } + + Spacer(modifier = Modifier.height(20.dp)) + + // Display sorted and filtered appointments LazyColumn( modifier = Modifier.fillMaxWidth() ) { - items(appointments) { appointment -> + items(sortedAppointments) { appointment -> AppointmentCard(appointment = appointment) { navController.navigate( Screens.AppointmentDetails(appointmentId = appointment.id.toString()).createRoute( @@ -66,6 +99,22 @@ fun AppointmentCard( appointment: AppointmentEntity, onClick: () -> Unit ) { + val date = Date(appointment.appointmentDateTime) + val dateFormat = SimpleDateFormat("MMM dd, yyyy 'at' HH:mm", Locale.getDefault()) + + // Get today's date and the appointment date + val calendar = Calendar.getInstance() + val today = calendar.apply { set(Calendar.HOUR_OF_DAY, 0); set(Calendar.MINUTE, 0); set(Calendar.SECOND, 0) } + val tomorrow = calendar.apply { add(Calendar.DATE, 1) } + val appointmentCalendar = Calendar.getInstance().apply { time = date } + + // Check if the appointment is tomorrow + val isTomorrow = appointmentCalendar.get(Calendar.YEAR) == tomorrow.get(Calendar.YEAR) && + appointmentCalendar.get(Calendar.DAY_OF_YEAR) == tomorrow.get(Calendar.DAY_OF_YEAR) + + // Check if the appointment is missed + val isMissed = appointment.appointmentDateTime < System.currentTimeMillis() + OutlinedCard( modifier = Modifier .fillMaxWidth() @@ -102,14 +151,65 @@ fun AppointmentCard( ) Spacer(modifier = Modifier.height(14.dp)) - - val date = Date(appointment.appointmentDateTime) - val dateFormat = SimpleDateFormat("MMM dd, yyyy 'at' HH:mm", Locale.getDefault()) + // Appointment date with conditional coloring + val dateColor = when { + isMissed -> MaterialTheme.colorScheme.error // Red for missed appointments + isTomorrow -> MaterialTheme.colorScheme.onSecondary // Orange for tomorrow + else -> MaterialTheme.colorScheme.onPrimary // Default color + } Text( dateFormat.format(date), - style = MaterialTheme.typography.bodyMedium + style = MaterialTheme.typography.labelSmall, + color = dateColor ) + + // Missed label + if (isMissed) { + Text( + text = "Missed", + style = MaterialTheme.typography.labelSmall, + modifier = Modifier.padding(top = 4.dp), + color = MaterialTheme.colorScheme.error + ) + } + + if (isTomorrow) { + Text( + text = "Tomorrow", + style = MaterialTheme.typography.labelSmall, + modifier = Modifier.padding(top = 4.dp), + color = MaterialTheme.colorScheme.onSecondary + ) + } } } +} + +@Composable +fun FilterButton( + text: String, + filterType: FilterType, + currentFilterType: FilterType, + onClick: (FilterType) -> Unit +) { + OutlinedButton( + onClick = { onClick(filterType) }, + colors = ButtonDefaults.buttonColors( + containerColor = if (filterType == currentFilterType) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.secondary + ), + modifier = Modifier + .padding(horizontal = 5.dp) // Add some horizontal padding to make buttons smaller + .height(40.dp), // Set a fixed height to control the button size + elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 4.dp) + ) { + Text( + text = text, + style = MaterialTheme.typography.bodyMedium + ) + } +} + +enum class FilterType { + ALL, PAST, UPCOMING } \ No newline at end of file diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Color.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Color.kt index 22987b9..954cfcc 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Color.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Color.kt @@ -8,4 +8,5 @@ val lightButtonBg = Color(0xFFFFCE93) val appointmentBg = Color(0xFFF8F8F8) val text = Color(0xFF000000) val fieldBg = Color(0xFFFFF4DE) -val deleteButtonBg = Color(0xFFE04F47) \ No newline at end of file +val deleteButtonBg = Color(0xFFE04F47) +val dateLabel = Color(0xFFFF9800) \ No newline at end of file diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Theme.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Theme.kt index 8792eb1..17bcd78 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Theme.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/theme/Theme.kt @@ -9,6 +9,7 @@ private val AppColorScheme = lightColorScheme( primary = buttonBg, onPrimary = text, secondary = fieldBg, + onSecondary = dateLabel, tertiary = lightButtonBg, tertiaryContainer = appointmentBg, error = deleteButtonBg -- GitLab From 012d069507e5de2b142862406783a3e1a92e91fb Mon Sep 17 00:00:00 2001 From: Sofiia-Khrystyna <sonia030605@gmail.com> Date: Sat, 18 Jan 2025 01:49:41 +0100 Subject: [PATCH 10/10] :art: back button on details screen is now aligned at the top properly --- .../at/ac/fhstp/pawwatch/ui/DetailScreen.kt | 148 ++++++++++-------- 1 file changed, 80 insertions(+), 68 deletions(-) diff --git a/app/src/main/java/at/ac/fhstp/pawwatch/ui/DetailScreen.kt b/app/src/main/java/at/ac/fhstp/pawwatch/ui/DetailScreen.kt index 38940db..dcb6987 100644 --- a/app/src/main/java/at/ac/fhstp/pawwatch/ui/DetailScreen.kt +++ b/app/src/main/java/at/ac/fhstp/pawwatch/ui/DetailScreen.kt @@ -23,105 +23,117 @@ fun DetailScreen( ) { val appointment = appointmentId?.let { id -> viewModel.getAppointmentById(id.toLong()) } - Column( + Box( modifier = Modifier .fillMaxSize() - .padding(35.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center + .padding(35.dp) // Padding for spacing within the screen ) { - // Back Button + // Back Button at Top-Start OutlinedButton( onClick = { navController.navigateUp() }, - modifier = Modifier.align(Alignment.Start), + modifier = Modifier + .align(Alignment.TopStart), // Aligns the button at the top-left corner + //.padding(8.dp), // Add padding around the button colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.background), - elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp) + elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp), ) { Icon( imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back", - tint = text // "text" is the variable which contains black colour in Color.kt + tint = text ) Spacer(modifier = Modifier.width(6.dp)) Text( text = "Back", - color = text, // same colour variable as for the icon + color = text, style = MaterialTheme.typography.labelMedium ) } - Spacer(modifier = Modifier.height(60.dp)) + //Spacer(modifier = Modifier.height(60.dp)) - appointment?.let { - Text( - it.petName, - style = MaterialTheme.typography.headlineMedium, - //modifier = Modifier.padding(2.dp) - ) - Spacer(modifier = Modifier.height(9.dp)) + // Rest of the content + Column( + modifier = Modifier + .fillMaxSize() + .padding(top = 45.dp), // Leave space for the back button + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + appointment?.let { + Text( + it.petName, + style = MaterialTheme.typography.headlineMedium, + //modifier = Modifier.padding(2.dp) + ) + Spacer(modifier = Modifier.height(9.dp)) - Text( - it.category, - style = MaterialTheme.typography.bodyLarge, - //modifier = Modifier.padding(2.dp) - ) - Spacer(modifier = Modifier.height(20.dp)) + Text( + it.category, + style = MaterialTheme.typography.bodyLarge, + //modifier = Modifier.padding(2.dp) + ) + Spacer(modifier = Modifier.height(20.dp)) - val date = Date(appointment.appointmentDateTime) + val date = Date(appointment.appointmentDateTime) - // Use SimpleDateFormat for 24-hour time format (HH:mm) - val dateFormat = SimpleDateFormat("MMM dd, yyyy 'at' HH:mm", Locale.getDefault()) + // Use SimpleDateFormat for 24-hour time format (HH:mm) + val dateFormat = SimpleDateFormat("MMM dd, yyyy 'at' HH:mm", Locale.getDefault()) - Text( - dateFormat.format(date), - style = MaterialTheme.typography.labelSmall - ) + Text( + dateFormat.format(date), + style = MaterialTheme.typography.labelSmall + ) - Spacer(modifier = Modifier.height(20.dp)) + Spacer(modifier = Modifier.height(20.dp)) - Text( - it.description, - style = MaterialTheme.typography.bodyMedium, - modifier = Modifier.padding(2.dp) - ) + Text( + it.description, + style = MaterialTheme.typography.bodyMedium, + modifier = Modifier.padding(2.dp) + ) - Spacer(modifier = Modifier.height(50.dp)) + Spacer(modifier = Modifier.height(50.dp)) - Row { - // Edit Button - OutlinedButton( - colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary), - onClick = { - // Navigate using the sealed class route - navController.navigate(Screens.EditAppointment(it.id.toString()).createRoute(it.id.toString())) - }, - modifier = Modifier.width(150.dp), - elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp) - ) { - Text( - text = "Edit", - style = MaterialTheme.typography.labelMedium - ) - } + Row { + // Edit Button + OutlinedButton( + colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary), + onClick = { + // Navigate using the sealed class route + navController.navigate( + Screens.EditAppointment(it.id.toString()) + .createRoute(it.id.toString()) + ) + }, + modifier = Modifier.width(150.dp), + elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp) + ) { + Text( + text = "Edit", + style = MaterialTheme.typography.labelMedium + ) + } - Spacer(modifier = Modifier.width(40.dp)) + Spacer(modifier = Modifier.width(40.dp)) - // Delete Button - OutlinedButton( - colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.error), - onClick = { - viewModel.deleteAppointment(it.id.toLong()) // Call delete logic - navController.navigateUp() - }, - modifier = Modifier.width(150.dp), - elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp) - ) { - Text( - text = "Delete", - style = MaterialTheme.typography.labelMedium - ) + // Delete Button + OutlinedButton( + colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.error), + onClick = { + viewModel.deleteAppointment(it.id.toLong()) // Call delete logic + navController.navigateUp() + }, + modifier = Modifier.width(150.dp), + elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 3.dp) + ) { + Text( + text = "Delete", + style = MaterialTheme.typography.labelMedium + ) + } } } } -- GitLab