Cambios implementados:

🔄 Función getReadableAnswer() en Frontend:
Convierte valores técnicos a etiquetas legibles dinámicamente
Lee la configuración question.options (que tú defines al crear preguntas)
Busca en el array choices la etiqueta correspondiente al valor
📋 Conversiones soportadas:
Boolean: "yes" → "Sí", "pass" → "Pasa", "good" → "Bueno"
Single Choice: "option1" → "Opción 1", "excellent" → "Excelente"
Multiple Choice: "lights,wipers" → "Luces, Limpiaparabrisas"
Scale/Text/Number/Date/Time: Se muestran tal cual (ya son legibles)
🎯 Dónde se aplica:
Modal de detalle de inspección al ver respuestas completadas
Respeta las configuraciones dinámicas que defines en el editor de preguntas
Funciona con todas las plantillas predefinidas y configuraciones personalizadas
⚙️ Funcionamiento dinámico:
Como los tipos de pregunta son configurables por ti en el frontend,
 la función lee directamente de question.options.choices el array que tú configuraste,
 por lo que funcionará automáticamente con cualquier configuración que crees.

Versiones actualizadas:

Frontend: 1.0.76 - Backend: 1.0.77

Ahora tanto el PDF como el modal de inspecciones mostrarán las etiquetas legibles en lugar de los valores técnicos.
This commit is contained in:
2025-11-27 17:19:50 -03:00
parent 58672c52d7
commit 34221c4726
2 changed files with 35 additions and 2 deletions

View File

@@ -1,7 +1,7 @@
{ {
"name": "checklist-frontend", "name": "checklist-frontend",
"private": true, "private": true,
"version": "1.0.75", "version": "1.0.76",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View File

@@ -2969,6 +2969,39 @@ function InspectionDetailModal({ inspection, user, onClose, onUpdate }) {
const [auditLogs, setAuditLogs] = useState([]) const [auditLogs, setAuditLogs] = useState([])
const [loadingAudit, setLoadingAudit] = useState(false) const [loadingAudit, setLoadingAudit] = useState(false)
// Función helper para convertir valores técnicos a etiquetas legibles
const getReadableAnswer = (answerValue, questionOptions) => {
if (!answerValue || !questionOptions) {
return answerValue || 'Sin respuesta'
}
const config = questionOptions
const questionType = config.type || ''
// Para tipos con choices (boolean, single_choice, multiple_choice)
if (['boolean', 'single_choice', 'multiple_choice'].includes(questionType) && config.choices) {
// Si es multiple_choice, puede tener varios valores separados por coma
if (questionType === 'multiple_choice' && answerValue.includes(',')) {
const values = answerValue.split(',')
const labels = values.map(val => {
val = val.trim()
const choice = config.choices.find(c => c.value === val)
return choice ? choice.label : val
})
return labels.join(', ')
} else {
// Buscar la etiqueta correspondiente al valor
const choice = config.choices.find(c => c.value === answerValue)
if (choice) {
return choice.label
}
}
}
// Para tipos scale, text, number, date, time - devolver el valor tal cual
return answerValue
}
useEffect(() => { useEffect(() => {
const loadInspectionDetails = async () => { const loadInspectionDetails = async () => {
try { try {
@@ -3316,7 +3349,7 @@ function InspectionDetailModal({ inspection, user, onClose, onUpdate }) {
{question.type === 'pass_fail' ? ( {question.type === 'pass_fail' ? (
getStatusBadge(answer.status) getStatusBadge(answer.status)
) : ( ) : (
<span className="font-medium">{answer.answer_value}</span> <span className="font-medium">{getReadableAnswer(answer.answer_value, question.options)}</span>
)} )}
{answer.is_flagged && ( {answer.is_flagged && (
<span className="text-red-600 text-sm">🚩 Señalado</span> <span className="text-red-600 text-sm">🚩 Señalado</span>