Files
n8n-mobile/src/hooks/useWorkflows.ts
T
billisdead 92e67d0769 feat: application n8n Pilot complète (Expo managed workflow)
- Stack : Expo Router, Axios, Zustand, React Native Paper (thème sombre), date-fns
- Sécurité : secrets dans Android Keystore via expo-secure-store, TLS obligatoire,
  headers X-N8N-API-KEY + X-App-Token injectés par intercepteur Axios
- API : client.ts centralisé + workflows.ts + executions.ts (TypeScript strict)
- Store : Zustand appStore avec chargement depuis secure store au démarrage
- Hooks : usePolling (générique), useWorkflows, useExecutions
- Composants : StatusBadge, WorkflowCard, ExecutionCard, SkeletonLoader
- Screens : Dashboard, Workflows, Executions, Logs (détail exécution), Settings
- Navigation Expo Router : 4 tabs + stack Logs + écran Setup initial
- Docs : INSTALL.md, UPDATE.md, BACKUP.md, HAPROXY.md, SECURITY.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 17:31:55 +02:00

115 lines
3.3 KiB
TypeScript

import { useState, useCallback } from 'react';
import { useAppStore } from '../store/appStore';
import {
fetchWorkflows,
activateWorkflow,
deactivateWorkflow,
runWorkflow,
Workflow,
} from '../api/workflows';
import { usePolling } from './usePolling';
/** Interface des valeurs et actions exposées par le hook */
interface UseWorkflowsResult {
workflows: Workflow[];
isLoading: boolean;
isRefreshing: boolean;
/**
* Recharge manuellement la liste des workflows.
* Utilisé pour le pull-to-refresh.
*/
refresh: () => Promise<void>;
/**
* Bascule le statut actif/inactif d'un workflow.
* Met à jour l'état local après confirmation serveur.
*
* @param workflow - Workflow à basculer
*/
toggleWorkflow: (workflow: Workflow) => Promise<void>;
/**
* Déclenche manuellement l'exécution d'un workflow.
*
* @param id - Identifiant du workflow à déclencher
*/
triggerWorkflow: (id: string) => Promise<void>;
}
/**
* Hook de gestion des workflows : chargement, polling automatique et actions.
* Délègue la gestion des erreurs à l'intercepteur Axios (errorHandler).
* Les screens ne font pas d'appels API directs — tout passe par ce hook.
*/
export const useWorkflows = (): UseWorkflowsResult => {
const { preferences, config } = useAppStore();
const [workflows, setWorkflows] = useState<Workflow[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [isRefreshing, setIsRefreshing] = useState(false);
/** Charge la liste des workflows depuis la couche API */
const loadWorkflows = useCallback(async (): Promise<void> => {
try {
const data = await fetchWorkflows();
setWorkflows(data);
} catch {
// Erreur déjà remontée via l'intercepteur Axios → toast affiché
} finally {
setIsLoading(false);
}
}, []);
/**
* Polling automatique déclenché uniquement si l'app est configurée.
* L'intervalle est lu depuis les préférences utilisateur (configurable dans Settings).
*/
usePolling({
callback: loadWorkflows,
interval: preferences.pollingInterval,
enabled: config.isConfigured,
immediate: true,
});
/** Pull-to-refresh : indicateur distinct du chargement initial */
const refresh = useCallback(async (): Promise<void> => {
setIsRefreshing(true);
try {
await loadWorkflows();
} finally {
setIsRefreshing(false);
}
}, [loadWorkflows]);
/**
* Bascule actif/inactif d'un workflow.
* Met à jour l'entrée correspondante dans l'état local après retour serveur.
*/
const toggleWorkflow = useCallback(async (workflow: Workflow): Promise<void> => {
try {
const updated = workflow.active
? await deactivateWorkflow(workflow.id)
: await activateWorkflow(workflow.id);
// Mise à jour ciblée sans recharger toute la liste
setWorkflows((prev) => prev.map((w) => (w.id === updated.id ? updated : w)));
} catch {
// Géré par l'intercepteur Axios
}
}, []);
const triggerWorkflow = useCallback(async (id: string): Promise<void> => {
try {
await runWorkflow(id);
} catch {
// Géré par l'intercepteur Axios
}
}, []);
return {
workflows,
isLoading,
isRefreshing,
refresh,
toggleWorkflow,
triggerWorkflow,
};
};