feat(android): completar alta de Inventario de campo en castellano

This commit is contained in:
2026-09-11 11:30:22 -03:00
parent 752bd4d6db
commit 9ace5b8e46
@@ -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<String?>(null) }
var selectedFamilyId by rememberSaveable(visit.id) { mutableStateOf<String?>(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<String, String>): Map<String, Any?> =
@@ -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) }