feat(android): completar alta de Inventario de campo en castellano
This commit is contained in:
@@ -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) }
|
||||
|
||||
Reference in New Issue
Block a user