diff --git a/android-app/app/src/main/java/com/korexlabs/dhinspeccion/ui/ModernVisitRoot.kt b/android-app/app/src/main/java/com/korexlabs/dhinspeccion/ui/ModernVisitRoot.kt index c624720..0fe77b3 100644 --- a/android-app/app/src/main/java/com/korexlabs/dhinspeccion/ui/ModernVisitRoot.kt +++ b/android-app/app/src/main/java/com/korexlabs/dhinspeccion/ui/ModernVisitRoot.kt @@ -262,7 +262,7 @@ private fun ModernChecklistCard(visit: VisitDetail) { val checklist = visit.checklist ElevatedCard(Modifier.fillMaxWidth()) { Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) { - Text("Antecedentes", fontWeight = FontWeight.Bold) + Text("Antecedentes y controles", fontWeight = FontWeight.Bold) Text( "${checklist.antecedents} antecedentes · ${checklist.upcomingControls} próximos controles", color = MaterialTheme.colorScheme.onSurfaceVariant, @@ -274,7 +274,7 @@ private fun ModernChecklistCard(visit: VisitDetail) { ) } if (checklist.stale) { - Text("El checklist requiere actualización.", color = MaterialTheme.colorScheme.error) + Text("La lista de control requiere actualización.", color = MaterialTheme.colorScheme.error) } } } @@ -296,6 +296,8 @@ private fun ModernFieldInventoryScreen(model: MainViewModel, onBack: () -> Unit) var parentLabel by rememberSaveable(visit.id) { mutableStateOf("") } var name by rememberSaveable(visit.id) { mutableStateOf("") } var commonName by rememberSaveable(visit.id) { mutableStateOf("") } + var description by rememberSaveable(visit.id) { mutableStateOf("") } + var discoveryNotes by rememberSaveable(visit.id) { mutableStateOf("") } var selectedTypeId by rememberSaveable(visit.id) { mutableStateOf(null) } var selectedFamilyId by rememberSaveable(visit.id) { mutableStateOf(null) } var familySearch by rememberSaveable(visit.id) { mutableStateOf("") } @@ -311,6 +313,8 @@ private fun ModernFieldInventoryScreen(model: MainViewModel, onBack: () -> Unit) fun resetForm() { name = "" commonName = "" + description = "" + discoveryNotes = "" selectedTypeId = null selectedFamilyId = null familySearch = "" @@ -427,7 +431,7 @@ private fun ModernFieldInventoryScreen(model: MainViewModel, onBack: () -> Unit) pendingPhotoGeo = geo takePicture.launch(uri) } - .onFailure { localError = it.message ?: "No se pudo obtener el GPS para la fotografía." } + .onFailure { localError = it.message ?: "No se pudo obtener la ubicación para la fotografía." } } } @@ -444,13 +448,15 @@ private fun ModernFieldInventoryScreen(model: MainViewModel, onBack: () -> Unit) familyId = selectedFamilyId, name = name, commonName = commonName, + description = description, + discoveryNotes = discoveryNotes, attributes = buildModernAttributes(type, attributeValues), latitude = geo.latitude, longitude = geo.longitude, accuracyM = geo.accuracyM, ) } - .onFailure { localError = it.message ?: "No se pudo capturar la ubicación GPS." } + .onFailure { localError = it.message ?: "No se pudo capturar la ubicación actual." } } } @@ -800,8 +806,8 @@ private fun ModernFieldInventoryScreen(model: MainViewModel, onBack: () -> Unit) OutlinedTextField( value = name, onValueChange = { name = it }, - label = { Text("Nombre o código visible *") }, - supportingText = { Text("Usá lo que figura en placa o identifica el elemento en campo.") }, + label = { Text("Nombre técnico / identificación *") }, + supportingText = { Text("Usá lo que figura en placa o identifica el elemento. El Código DH de campo se genera automáticamente.") }, modifier = Modifier.fillMaxWidth(), singleLine = true, ) @@ -812,6 +818,21 @@ private fun ModernFieldInventoryScreen(model: MainViewModel, onBack: () -> Unit) modifier = Modifier.fillMaxWidth(), singleLine = true, ) + OutlinedTextField( + value = description, + onValueChange = { description = it }, + label = { Text("Descripción (opcional)") }, + modifier = Modifier.fillMaxWidth(), + minLines = 2, + ) + OutlinedTextField( + value = discoveryNotes, + onValueChange = { discoveryNotes = it }, + label = { Text("Observaciones del alta (opcional)") }, + supportingText = { Text("Anotá datos útiles para la revisión posterior en oficina.") }, + modifier = Modifier.fillMaxWidth(), + minLines = 2, + ) selectedType?.attributes?.forEach { definition -> OutlinedTextField( @@ -830,12 +851,12 @@ private fun ModernFieldInventoryScreen(model: MainViewModel, onBack: () -> Unit) } HorizontalDivider() - ModernStepHeader(if (isSubinstallation) 3 else 2, "GPS + foto") + ModernStepHeader(if (isSubinstallation) 3 else 2, "Ubicación y foto") Surface(Modifier.fillMaxWidth(), shape = MaterialTheme.shapes.medium, color = MaterialTheme.colorScheme.secondaryContainer) { Row(Modifier.padding(14.dp), horizontalArrangement = Arrangement.spacedBy(10.dp), verticalAlignment = Alignment.CenterVertically) { Icon(Icons.Filled.CameraAlt, null, tint = MaterialTheme.colorScheme.secondary) Text( - "Al guardar capturamos el GPS y abrimos la cámara. La foto es obligatoria antes de registrar Hallazgos.", + "Al guardar capturamos la ubicación y abrimos la cámara. La foto es obligatoria antes de registrar Hallazgos.", style = MaterialTheme.typography.bodySmall, modifier = Modifier.weight(1f), ) @@ -927,7 +948,7 @@ private fun ModernInventoryCard(item: FieldInventoryItem, onInspect: () -> Unit, } item.commonName?.takeIf { it.isNotBlank() }?.let { Text(it, style = MaterialTheme.typography.bodySmall) } Text( - if (item.readyForFinding) "Listo para Hallazgos" else "Falta GPS / foto", + if (item.readyForFinding) "Listo para Hallazgos" else "Falta ubicación / foto", color = if (item.readyForFinding) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.error, style = MaterialTheme.typography.bodySmall, fontWeight = FontWeight.SemiBold, @@ -966,7 +987,7 @@ private fun ModernCaptureCard( IconButton(onClick = onClose) { Icon(Icons.Filled.Close, "Cerrar") } } Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) { - Text(if (gps) "✓ GPS" else "GPS pendiente", color = if (gps) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.error) + Text(if (gps) "✓ Ubicación" else "Ubicación pendiente", color = if (gps) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.error) Text("Fotos · $photos") } if (!ready) { @@ -1078,7 +1099,7 @@ private fun modernStatusLabel(status: String): String = when (status) { "IN_PROGRESS" -> "En curso" "CLOSED" -> "Cerrada" "CANCELLED" -> "Cancelada" - else -> status + else -> "Estado no reconocido" } private fun buildModernAttributes(type: FieldType, values: Map): Map = @@ -1112,7 +1133,7 @@ private suspend fun currentModernGeo(context: Context): ModernGeoSnapshot = susp client.getCurrentLocation(Priority.PRIORITY_HIGH_ACCURACY, source.token) .addOnSuccessListener { location -> if (!continuation.isActive) return@addOnSuccessListener - if (location == null) continuation.resumeWithException(IllegalStateException("No se pudo obtener una ubicación GPS actual.")) + if (location == null) continuation.resumeWithException(IllegalStateException("No se pudo obtener una ubicación actual.")) else continuation.resume(ModernGeoSnapshot(location.latitude, location.longitude, location.accuracy.toDouble())) } .addOnFailureListener { if (continuation.isActive) continuation.resumeWithException(it) }