chore: estructura inicial del MVP
Backend (Express + MariaDB) y frontend (React + Vite, identidad Fluent/Windows) con el nucleo funcional: seguridad, organizacion, proyectos, actividades, subtareas, dependencias, dashboard, calendario, gantt, comentarios, adjuntos, notificaciones in-app y catalogos. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useUi } from '../context/ui-context.jsx';
|
||||
|
||||
// Abstrae el patron repetido loading/try-catch/error para llamadas a la API.
|
||||
export function useAsync(fn, deps = []) {
|
||||
const [data, setData] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
const reload = useCallback(async () => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const result = await fn();
|
||||
setData(result);
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, deps);
|
||||
|
||||
useEffect(() => { reload(); }, [reload]);
|
||||
|
||||
return { data, loading, error, reload, setData };
|
||||
}
|
||||
|
||||
// Ejecuta una accion mostrando error via ContentDialog si falla.
|
||||
export function useAction() {
|
||||
const { openDialog, t } = useUi();
|
||||
return useCallback(async (fn) => {
|
||||
try {
|
||||
return await fn();
|
||||
} catch (err) {
|
||||
openDialog({ tone: 'error', title: t('common_error'), message: err.message });
|
||||
throw err;
|
||||
}
|
||||
}, [openDialog, t]);
|
||||
}
|
||||
Reference in New Issue
Block a user