Anonymous
Сохранение списка строк в Firestore
Сообщение
Anonymous » 06 фев 2025, 17:39
Я работаю над тем, чтобы сэкономить время, которое выбирается пользователями. Выбранные времена должны быть спасены в Firestore. В моих журналах log.d («Firestoresave», «Saving Place: $ placeinfo») показывает, что Times также создает область доступного времени в Firestore, но массив выглядит пустым. Также другие входы от пользователя, показанные без проблем. < /P>
Мой класс данных < /p>
Код: Выделить всё
data class PlaceData(
val name: String = "",
val capacity: Int = 0,
val id: String = "",
val placeImageUrl: String = "",
val availableTimes: List = emptyList() // Firestore can handle this
):Serializable
< /code>
Репозитория реализация < /p>
override suspend fun addPlace(placeData: PlaceData): Flow = flow {
emit(RootResult.Loading)
try {
val currentUser = firebaseAuth.currentUser
val userId = currentUser?.uid
if (userId != null) {
val placeId = firestore.collection("users").document(userId).collection("places")
.document().id
// Create a map of the data to save
val placeInfo = mapOf(
"name" to placeData.name,
"capacity" to placeData.capacity,
"id" to placeId,
"placeImageUrl" to placeData.placeImageUrl,
"availableTimes" to placeData.availableTimes // Ensure this is a List
)
Log.d("FirestoreSave", "Saving place: $placeInfo")
// Save the data to Firestore
firestore.collection("users").document(userId).collection("places")
.document(placeId).set(placeInfo, SetOptions.merge())
.addOnSuccessListener {
Log.d("FirestoreSave", "Place saved successfully!")
}
.addOnFailureListener { e ->
Log.e("FirestoreSave", "Failed to save place: ", e)
}
emit(RootResult.Success(true))
} else {
emit(RootResult.Error("User ID is null"))
}
} catch (e: Exception) {
emit(RootResult.Error(e.message ?: "Something went wrong"))
}
}.flowOn(Dispatchers.IO)
< /code>
my ui < /p>
@Composable
fun AddPlaceDialog(
onDismiss: () -> Unit,
onSave: (PlaceData) -> Unit,
onImagePick: () -> Unit,
selectedImageUri: Uri?,
context: Context
) {
var expanded by remember { mutableStateOf(false) }
var customPlaceName by remember { mutableStateOf("") }
val availableTimes = remember { mutableStateListOf() }
val timePickerDialog = remember { mutableStateOf(false) }
AlertDialog(
containerColor = Color.Black,
onDismissRequest = onDismiss,
title = {
Text(
text = "Add Place",
style = TextStyle(color = Color.White, fontSize = 25.sp)
)
},
text = {
Column(modifier = Modifier.fillMaxWidth().padding(16.dp)) {
// Image Picker
Box(
modifier = Modifier.fillMaxWidth()
.height(128.dp)
.clip(RoundedCornerShape(8.dp))
.background(Color.White)
.clickable { onImagePick() }
.align(Alignment.CenterHorizontally)
.border(1.dp, Color.Black, RoundedCornerShape(8.dp))
) {
selectedImageUri?.let { uri ->
Image(
painter = rememberAsyncImagePainter(uri),
contentDescription = "Selected Image",
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop,
)
} ?: run {
Icon(
imageVector = Icons.Filled.Add,
contentDescription = "Select Image",
modifier = Modifier.align(Alignment.Center).size(50.dp),
tint = Color.Red
)
}
}
Spacer(modifier = Modifier.height(16.dp))
// Place Name Input
TextField(
colors = TextFieldDefaults.colors(
unfocusedContainerColor = Color.White,
focusedContainerColor = Color.White,
focusedTextColor = Color.Black,
focusedIndicatorColor = Color.Black,
unfocusedIndicatorColor = Color.Black,
unfocusedLabelColor = Color.Black,
focusedLabelColor = Color.Black,
cursorColor = Color.Black,
unfocusedTextColor = Color.Black
),
value = customPlaceName,
onValueChange = { customPlaceName = it },
label = { Text("Enter Place Name", fontSize = 13.sp, color = Color.Black) },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(16.dp))
// Add Time Button
Button(
onClick = { timePickerDialog.value = true },
colors = ButtonDefaults.buttonColors(containerColor = Color.White),
modifier = Modifier.fillMaxWidth()
) {
Icon(imageVector = Icons.Filled.Add, contentDescription = "Add Time", tint = Color.Black)
Spacer(modifier = Modifier.width(8.dp))
Text("Add Available Time", color = Color.Black)
}
Spacer(modifier = Modifier.height(16.dp))
// Display Selected Times
availableTimes.forEachIndexed { index, time ->
Row(
modifier = Modifier.fillMaxWidth()
.padding(vertical = 4.dp)
.background(Color.Gray.copy(alpha = 0.2f), RoundedCornerShape(8.dp))
.padding(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(text = time, color = Color.White, modifier = Modifier.weight(1f))
IconButton(onClick = { availableTimes.removeAt(index) }) {
Icon(imageVector = Icons.Filled.Delete, contentDescription = "Remove", tint = Color.Red)
}
}
}
}
},
confirmButton = {
AuthButtonComponent(
value = "Save",
onClick = {
// if (selectedImageUri == null) {
// Toast.makeText(context, "Please choose an image.", Toast.LENGTH_SHORT).show()
// return@AuthButtonComponent
// }
// if (customPlaceName.isBlank()) {
// Toast.makeText(context, "Please enter a place name.", Toast.LENGTH_SHORT).show()
// return@AuthButtonComponent
// }
// if (availableTimes.isEmpty()) {
// Toast.makeText(context, "Please add at least one available time.", Toast.LENGTH_SHORT).show()
// return@AuthButtonComponent
// }
val placeData = PlaceData(
name = customPlaceName,
placeImageUrl = selectedImageUri.toString(),
availableTimes = availableTimes.toList()
)
Log.d("PlaceData", "Saving PlaceData: $placeData")
onSave(placeData)
onDismiss()
},
modifier = Modifier.width(70.dp),
fillMaxWidth = false,
heightIn = 40.dp,
firstColor = Color.Black,
secondColor = Color.Black
)
},
dismissButton = {
AuthButtonComponent(
value = "Cancel",
onClick = { onDismiss() },
modifier = Modifier.width(80.dp),
fillMaxWidth = false,
heightIn = 40.dp,
firstColor = Color.Black,
secondColor = Color.Black
)
}
)
// Time Picker Dialog
if (timePickerDialog.value) {
val timePicker = TimePickerDialog(
context,
{ _, hour, minute ->
val selectedTime = String.format("%02d:%02d", hour, minute)
val times = availableTimes.add(selectedTime)
val list = times.toString()
timePickerDialog.value = false
Log.d("AvailableTimes", availableTimes.toString())
},
24, 0, true
)
timePicker.show()
}
}
Я не понимаю, почему он не работает, пожалуйста, помогите мне
Подробнее здесь:
https://stackoverflow.com/questions/794 ... -firestore
1738852789
Anonymous
Я работаю над тем, чтобы сэкономить время, которое выбирается пользователями. Выбранные времена должны быть спасены в Firestore. В моих журналах log.d («Firestoresave», «Saving Place: $ placeinfo») показывает, что Times также создает область доступного времени в Firestore, но массив выглядит пустым. Также другие входы от пользователя, показанные без проблем. < /P> Мой класс данных < /p> [code]data class PlaceData( val name: String = "", val capacity: Int = 0, val id: String = "", val placeImageUrl: String = "", val availableTimes: List = emptyList() // Firestore can handle this ):Serializable < /code> Репозитория реализация < /p> override suspend fun addPlace(placeData: PlaceData): Flow = flow { emit(RootResult.Loading) try { val currentUser = firebaseAuth.currentUser val userId = currentUser?.uid if (userId != null) { val placeId = firestore.collection("users").document(userId).collection("places") .document().id // Create a map of the data to save val placeInfo = mapOf( "name" to placeData.name, "capacity" to placeData.capacity, "id" to placeId, "placeImageUrl" to placeData.placeImageUrl, "availableTimes" to placeData.availableTimes // Ensure this is a List ) Log.d("FirestoreSave", "Saving place: $placeInfo") // Save the data to Firestore firestore.collection("users").document(userId).collection("places") .document(placeId).set(placeInfo, SetOptions.merge()) .addOnSuccessListener { Log.d("FirestoreSave", "Place saved successfully!") } .addOnFailureListener { e -> Log.e("FirestoreSave", "Failed to save place: ", e) } emit(RootResult.Success(true)) } else { emit(RootResult.Error("User ID is null")) } } catch (e: Exception) { emit(RootResult.Error(e.message ?: "Something went wrong")) } }.flowOn(Dispatchers.IO) < /code> my ui < /p> @Composable fun AddPlaceDialog( onDismiss: () -> Unit, onSave: (PlaceData) -> Unit, onImagePick: () -> Unit, selectedImageUri: Uri?, context: Context ) { var expanded by remember { mutableStateOf(false) } var customPlaceName by remember { mutableStateOf("") } val availableTimes = remember { mutableStateListOf() } val timePickerDialog = remember { mutableStateOf(false) } AlertDialog( containerColor = Color.Black, onDismissRequest = onDismiss, title = { Text( text = "Add Place", style = TextStyle(color = Color.White, fontSize = 25.sp) ) }, text = { Column(modifier = Modifier.fillMaxWidth().padding(16.dp)) { // Image Picker Box( modifier = Modifier.fillMaxWidth() .height(128.dp) .clip(RoundedCornerShape(8.dp)) .background(Color.White) .clickable { onImagePick() } .align(Alignment.CenterHorizontally) .border(1.dp, Color.Black, RoundedCornerShape(8.dp)) ) { selectedImageUri?.let { uri -> Image( painter = rememberAsyncImagePainter(uri), contentDescription = "Selected Image", modifier = Modifier.fillMaxSize(), contentScale = ContentScale.Crop, ) } ?: run { Icon( imageVector = Icons.Filled.Add, contentDescription = "Select Image", modifier = Modifier.align(Alignment.Center).size(50.dp), tint = Color.Red ) } } Spacer(modifier = Modifier.height(16.dp)) // Place Name Input TextField( colors = TextFieldDefaults.colors( unfocusedContainerColor = Color.White, focusedContainerColor = Color.White, focusedTextColor = Color.Black, focusedIndicatorColor = Color.Black, unfocusedIndicatorColor = Color.Black, unfocusedLabelColor = Color.Black, focusedLabelColor = Color.Black, cursorColor = Color.Black, unfocusedTextColor = Color.Black ), value = customPlaceName, onValueChange = { customPlaceName = it }, label = { Text("Enter Place Name", fontSize = 13.sp, color = Color.Black) }, modifier = Modifier.fillMaxWidth() ) Spacer(modifier = Modifier.height(16.dp)) // Add Time Button Button( onClick = { timePickerDialog.value = true }, colors = ButtonDefaults.buttonColors(containerColor = Color.White), modifier = Modifier.fillMaxWidth() ) { Icon(imageVector = Icons.Filled.Add, contentDescription = "Add Time", tint = Color.Black) Spacer(modifier = Modifier.width(8.dp)) Text("Add Available Time", color = Color.Black) } Spacer(modifier = Modifier.height(16.dp)) // Display Selected Times availableTimes.forEachIndexed { index, time -> Row( modifier = Modifier.fillMaxWidth() .padding(vertical = 4.dp) .background(Color.Gray.copy(alpha = 0.2f), RoundedCornerShape(8.dp)) .padding(8.dp), verticalAlignment = Alignment.CenterVertically ) { Text(text = time, color = Color.White, modifier = Modifier.weight(1f)) IconButton(onClick = { availableTimes.removeAt(index) }) { Icon(imageVector = Icons.Filled.Delete, contentDescription = "Remove", tint = Color.Red) } } } } }, confirmButton = { AuthButtonComponent( value = "Save", onClick = { // if (selectedImageUri == null) { // Toast.makeText(context, "Please choose an image.", Toast.LENGTH_SHORT).show() // return@AuthButtonComponent // } // if (customPlaceName.isBlank()) { // Toast.makeText(context, "Please enter a place name.", Toast.LENGTH_SHORT).show() // return@AuthButtonComponent // } // if (availableTimes.isEmpty()) { // Toast.makeText(context, "Please add at least one available time.", Toast.LENGTH_SHORT).show() // return@AuthButtonComponent // } val placeData = PlaceData( name = customPlaceName, placeImageUrl = selectedImageUri.toString(), availableTimes = availableTimes.toList() ) Log.d("PlaceData", "Saving PlaceData: $placeData") onSave(placeData) onDismiss() }, modifier = Modifier.width(70.dp), fillMaxWidth = false, heightIn = 40.dp, firstColor = Color.Black, secondColor = Color.Black ) }, dismissButton = { AuthButtonComponent( value = "Cancel", onClick = { onDismiss() }, modifier = Modifier.width(80.dp), fillMaxWidth = false, heightIn = 40.dp, firstColor = Color.Black, secondColor = Color.Black ) } ) // Time Picker Dialog if (timePickerDialog.value) { val timePicker = TimePickerDialog( context, { _, hour, minute -> val selectedTime = String.format("%02d:%02d", hour, minute) val times = availableTimes.add(selectedTime) val list = times.toString() timePickerDialog.value = false Log.d("AvailableTimes", availableTimes.toString()) }, 24, 0, true ) timePicker.show() } } [/code] Я не понимаю, почему он не работает, пожалуйста, помогите мне Подробнее здесь: [url]https://stackoverflow.com/questions/79418340/saving-string-list-to-firestore[/url]