feat: arrastrar con el mouse para reordenar actividades y tareas
Hook reutilizable useDragReorder (drag & drop nativo HTML5, sin libreria nueva) usado en dos lugares: ListView (opt-in via onReorder, deshabilitado mientras haya un ordenamiento por columna activo) para el listado de actividades de un proyecto, y el listado de tareas de una actividad. Orden persistido en sort_order (activities y tasks, migracion 012, posiciones siempre 1..N). Fix real encontrado durante las pruebas: sincronizar el estado interno del hook por la REFERENCIA del arreglo de entrada entraba en loop infinito de renders cuando el llamador pasa "algo || []" (un arreglo nuevo en cada render mientras los datos cargan). Corregido para sincronizar por el contenido (ids), no por referencia. Probado en dev con curl (persistencia del orden) y Playwright (arrastrar filas en el navegador, orden visible y guardado correctamente, sin errores de consola tras el fix). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,7 @@ import { Plus, Save, Trash2 } from 'lucide-react';
|
||||
import { useUi } from '../../context/ui-context.jsx';
|
||||
import { useAuth } from '../../context/auth-context.jsx';
|
||||
import { useAsync, useAction } from '../../hooks/useAsync.js';
|
||||
import { listActivitiesByProject, createActivity, getActivity, deleteActivity } from '../../services/activities.js';
|
||||
import { listActivitiesByProject, createActivity, getActivity, deleteActivity, reorderActivities } from '../../services/activities.js';
|
||||
import { listCatalog } from '../../services/catalogs.js';
|
||||
import { listUsers } from '../../services/users.js';
|
||||
import { ListView } from '../../components/ListView.jsx';
|
||||
@@ -57,6 +57,11 @@ export default function ProjectActivitiesTab({ projectId }) {
|
||||
if (selected) setSelected(await getActivity(selected.id));
|
||||
}
|
||||
|
||||
async function handleReorder(ids) {
|
||||
await reorderActivities(projectId, ids);
|
||||
await reload();
|
||||
}
|
||||
|
||||
function confirmDelete(row) {
|
||||
openDialog({
|
||||
tone: 'warning',
|
||||
@@ -107,6 +112,7 @@ export default function ProjectActivitiesTab({ projectId }) {
|
||||
getSearchHaystack={(a) => `${a.code} ${a.name} ${a.responsible_name || ''}`}
|
||||
getRowKey={(a) => a.id}
|
||||
onRowClick={openActivity}
|
||||
onReorder={currentUser?.roleCode !== 'viewer' ? handleReorder : undefined}
|
||||
rowActions={currentUser?.roleCode !== 'viewer' ? (a) => [
|
||||
{ label: t('common_delete'), icon: Trash2, danger: true, onClick: () => confirmDelete(a) },
|
||||
] : undefined}
|
||||
|
||||
Reference in New Issue
Block a user