Frontend v1.0.68:

- Agregada funcionalidad de edición de checklists
- Nuevo modal para editar nombre, descripción, modo IA y scoring
- Botón "✏️ Editar" en cada checklist (solo admins)
- Mejora en la gestión de checklists en el panel de administración

Backend v1.0.68:
- Actualización de versión para sincronizar con frontend
- Endpoint PUT /api/checklists/{id} ya soportaba la funcionalidad
This commit is contained in:
2025-11-27 11:19:48 -03:00
parent efbf57e6bc
commit 0117ba34f8
5 changed files with 292 additions and 4 deletions

View File

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

View File

@@ -1735,6 +1735,7 @@ function ChecklistsTab({ checklists, user, onChecklistCreated, onStartInspection
const [showCreateModal, setShowCreateModal] = useState(false)
const [showQuestionsModal, setShowQuestionsModal] = useState(false)
const [showEditPermissionsModal, setShowEditPermissionsModal] = useState(false)
const [showEditChecklistModal, setShowEditChecklistModal] = useState(false)
const [showLogoModal, setShowLogoModal] = useState(false)
const [selectedChecklist, setSelectedChecklist] = useState(null)
const [creating, setCreating] = useState(false)
@@ -1752,6 +1753,12 @@ function ChecklistsTab({ checklists, user, onChecklistCreated, onStartInspection
scoring_enabled: true,
mechanic_ids: []
})
const [editChecklistData, setEditChecklistData] = useState({
name: '',
description: '',
ai_mode: 'off',
scoring_enabled: true
})
const [editPermissionsData, setEditPermissionsData] = useState({
mechanic_ids: []
})
@@ -1875,6 +1882,39 @@ function ChecklistsTab({ checklists, user, onChecklistCreated, onStartInspection
}
}
const handleEditChecklist = async (e) => {
e.preventDefault()
setUpdating(true)
try {
const token = localStorage.getItem('token')
const API_URL = import.meta.env.VITE_API_URL || ''
const response = await fetch(`${API_URL}/api/checklists/${selectedChecklist.id}`, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(editChecklistData),
})
if (response.ok) {
setShowEditChecklistModal(false)
setSelectedChecklist(null)
setEditChecklistData({ name: '', description: '', ai_mode: 'off', scoring_enabled: true })
onChecklistCreated() // Reload checklists
} else {
alert('Error al actualizar checklist')
}
} catch (error) {
console.error('Error:', error)
alert('Error al actualizar checklist')
} finally {
setUpdating(false)
}
}
const handleUploadLogo = async (e) => {
const file = e.target.files[0]
if (!file) return
@@ -2078,9 +2118,25 @@ function ChecklistsTab({ checklists, user, onChecklistCreated, onStartInspection
</div>
)}
</div>
<div className="flex gap-2">
<div className="flex gap-2 flex-wrap">
{user.role === 'admin' && (
<>
<button
onClick={() => {
setSelectedChecklist(checklist)
setEditChecklistData({
name: checklist.name,
description: checklist.description || '',
ai_mode: checklist.ai_mode || 'off',
scoring_enabled: checklist.scoring_enabled ?? true
})
setShowEditChecklistModal(true)
}}
className="px-3 py-2 bg-gradient-to-r from-indigo-500 to-purple-500 text-white rounded-lg hover:from-indigo-600 hover:to-purple-600 transition-all transform hover:scale-105 shadow-lg text-sm"
title="Editar checklist"
>
Editar
</button>
<button
onClick={() => {
setSelectedChecklist(checklist)
@@ -2381,6 +2437,106 @@ function ChecklistsTab({ checklists, user, onChecklistCreated, onStartInspection
</div>
)}
{/* Modal Editar Checklist */}
{showEditChecklistModal && selectedChecklist && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-lg max-w-2xl w-full max-h-[90vh] overflow-y-auto">
<div className="p-6">
<h2 className="text-2xl font-bold text-gray-900 mb-4"> Editar Checklist</h2>
<form onSubmit={handleEditChecklist} className="space-y-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Nombre del Checklist *
</label>
<input
type="text"
value={editChecklistData.name}
onChange={(e) => setEditChecklistData({ ...editChecklistData, name: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
placeholder="Ej: Inspección Pre-entrega"
required
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Descripción
</label>
<textarea
value={editChecklistData.description}
onChange={(e) => setEditChecklistData({ ...editChecklistData, description: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
rows="3"
placeholder="Descripción del checklist..."
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Modo IA
</label>
<select
value={editChecklistData.ai_mode}
onChange={(e) => setEditChecklistData({ ...editChecklistData, ai_mode: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
>
<option value="off"> Desactivado (Manual)</option>
<option value="assisted">💡 Asistido (Sugerencias)</option>
<option value="copilot">🤖 Copiloto (Auto-completar)</option>
</select>
<p className="mt-1 text-xs text-gray-500">
{editChecklistData.ai_mode === 'off' && '❌ El mecánico completa todo manualmente'}
{editChecklistData.ai_mode === 'assisted' && '💡 IA sugiere respuestas, el mecánico confirma'}
{editChecklistData.ai_mode === 'copilot' && '🤖 IA completa automáticamente, el mecánico revisa'}
</p>
</div>
<div className="flex items-center">
<input
type="checkbox"
checked={editChecklistData.scoring_enabled}
onChange={(e) => setEditChecklistData({ ...editChecklistData, scoring_enabled: e.target.checked })}
className="w-4 h-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500"
/>
<label className="ml-2 text-sm text-gray-700">
Habilitar sistema de puntuación
</label>
</div>
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
<p className="text-sm text-blue-800">
Los cambios se aplicarán inmediatamente. Las inspecciones existentes no se verán afectadas.
</p>
</div>
<div className="flex gap-3 pt-4">
<button
type="button"
onClick={() => {
setShowEditChecklistModal(false)
setSelectedChecklist(null)
setEditChecklistData({ name: '', description: '', ai_mode: 'off', scoring_enabled: true })
}}
className="flex-1 px-4 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition"
disabled={updating}
>
Cancelar
</button>
<button
type="submit"
className="flex-1 px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition disabled:opacity-50"
disabled={updating}
>
{updating ? 'Guardando...' : 'Guardar Cambios'}
</button>
</div>
</form>
</div>
</div>
</div>
)}
{/* Modal Editar Permisos */}
{showEditPermissionsModal && selectedChecklist && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">