Backend v1.0.73:
- Implementado sistema de reordenamiento de preguntas
- Nuevo endpoint PATCH /api/checklists/{id}/questions/reorder
- Schema QuestionReorder para validar datos de reorden
- Actualización en lote de campo 'order' en preguntas
- Auditoría automática de cambios de orden
- Validación de permisos y existencia de checklist
Frontend v1.0.71:
- Agregada funcionalidad de reordenamiento de preguntas
- Botones ▲ ▼ para mover preguntas arriba/abajo
- Función moveQuestion() para gestionar reordenamiento
- Interfaz visual mejorada con separadores
- Tooltips descriptivos en botones de orden
- Recarga automática tras reordenar
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "checklist-frontend",
|
||||
"private": true,
|
||||
"version": "1.0.70",
|
||||
"version": "1.0.71",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1167,6 +1167,51 @@ function QuestionsManagerModal({ checklist, onClose }) {
|
||||
}
|
||||
}
|
||||
|
||||
const moveQuestion = async (questionId, direction) => {
|
||||
const questionsList = Object.values(questionsBySection).flat()
|
||||
const currentIndex = questionsList.findIndex(q => q.id === questionId)
|
||||
|
||||
if (currentIndex === -1) return
|
||||
|
||||
const newIndex = direction === 'up' ? currentIndex - 1 : currentIndex + 1
|
||||
|
||||
if (newIndex < 0 || newIndex >= questionsList.length) return
|
||||
|
||||
// Crear nueva lista con el orden actualizado
|
||||
const newList = [...questionsList]
|
||||
const [movedQuestion] = newList.splice(currentIndex, 1)
|
||||
newList.splice(newIndex, 0, movedQuestion)
|
||||
|
||||
// Preparar datos para el backend
|
||||
const reorderData = newList.map((q, index) => ({
|
||||
question_id: q.id,
|
||||
new_order: index
|
||||
}))
|
||||
|
||||
try {
|
||||
const token = localStorage.getItem('token')
|
||||
const API_URL = import.meta.env.VITE_API_URL || ''
|
||||
|
||||
const response = await fetch(`${API_URL}/api/checklists/${checklist.id}/questions/reorder`, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(reorderData)
|
||||
})
|
||||
|
||||
if (response.ok) {
|
||||
loadQuestions()
|
||||
} else {
|
||||
alert('Error al reordenar pregunta')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error:', error)
|
||||
alert('Error al reordenar pregunta')
|
||||
}
|
||||
}
|
||||
|
||||
const questionsBySection = questions.reduce((acc, q) => {
|
||||
const section = q.section || 'Sin sección'
|
||||
if (!acc[section]) acc[section] = []
|
||||
@@ -1582,7 +1627,25 @@ function QuestionsManagerModal({ checklist, onClose }) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="ml-4 flex gap-2">
|
||||
<div className="ml-4 flex gap-2 items-center">
|
||||
{/* Botones de reordenamiento */}
|
||||
<div className="flex flex-col gap-1">
|
||||
<button
|
||||
onClick={() => moveQuestion(question.id, 'up')}
|
||||
className="text-gray-500 hover:text-indigo-600 text-xs px-2 py-1 hover:bg-indigo-50 rounded transition"
|
||||
title="Mover arriba"
|
||||
>
|
||||
▲
|
||||
</button>
|
||||
<button
|
||||
onClick={() => moveQuestion(question.id, 'down')}
|
||||
className="text-gray-500 hover:text-indigo-600 text-xs px-2 py-1 hover:bg-indigo-50 rounded transition"
|
||||
title="Mover abajo"
|
||||
>
|
||||
▼
|
||||
</button>
|
||||
</div>
|
||||
<div className="h-8 w-px bg-gray-300"></div>
|
||||
<button
|
||||
onClick={() => loadAuditHistory(question.id)}
|
||||
className="text-gray-600 hover:text-gray-700 text-sm"
|
||||
|
||||
Reference in New Issue
Block a user