92e67d0769
- 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>
88 lines
2.6 KiB
TypeScript
88 lines
2.6 KiB
TypeScript
import { formatDistanceToNow, format, differenceInSeconds } from 'date-fns';
|
|
import { fr } from 'date-fns/locale';
|
|
|
|
/**
|
|
* Formate une date ISO en temps relatif lisible en français.
|
|
* Ex : "il y a 3 minutes", "dans 2 heures"
|
|
*
|
|
* @param dateString - Date au format ISO 8601
|
|
* @returns Chaîne relative en français, ou "date inconnue" si parsing impossible
|
|
*/
|
|
export const formatRelativeDate = (dateString: string): string => {
|
|
try {
|
|
return formatDistanceToNow(new Date(dateString), { addSuffix: true, locale: fr });
|
|
} catch {
|
|
return 'date inconnue';
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Formate une date ISO en format court DD/MM/YYYY HH:mm.
|
|
*
|
|
* @param dateString - Date au format ISO 8601
|
|
* @returns Chaîne formatée, ou "date inconnue" si parsing impossible
|
|
*/
|
|
export const formatShortDate = (dateString: string): string => {
|
|
try {
|
|
return format(new Date(dateString), 'dd/MM/yyyy HH:mm', { locale: fr });
|
|
} catch {
|
|
return 'date inconnue';
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Calcule et formate la durée entre deux dates.
|
|
* Si stoppedAt est absent, calcule jusqu'à maintenant (exécution en cours).
|
|
*
|
|
* @param startedAt - Date de début ISO 8601
|
|
* @param stoppedAt - Date de fin ISO 8601 (optionnelle)
|
|
* @returns Durée formatée ex : "2m 34s", "45s"
|
|
*/
|
|
export const formatDuration = (startedAt: string, stoppedAt?: string): string => {
|
|
try {
|
|
const start = new Date(startedAt);
|
|
const end = stoppedAt ? new Date(stoppedAt) : new Date();
|
|
const seconds = differenceInSeconds(end, start);
|
|
if (seconds < 60) return `${seconds}s`;
|
|
const minutes = Math.floor(seconds / 60);
|
|
const remainingSeconds = seconds % 60;
|
|
return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;
|
|
} catch {
|
|
return 'durée inconnue';
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Traduit le statut d'une exécution n8n en libellé français.
|
|
*
|
|
* @param status - Statut brut de l'API n8n
|
|
* @returns Libellé français correspondant
|
|
*/
|
|
export const formatStatus = (status: string): string => {
|
|
const statusMap: Record<string, string> = {
|
|
success: 'Succès',
|
|
error: 'Erreur',
|
|
waiting: 'En attente',
|
|
running: 'En cours',
|
|
canceled: 'Annulé',
|
|
};
|
|
return statusMap[status] ?? status;
|
|
};
|
|
|
|
/**
|
|
* Traduit le mode de déclenchement d'une exécution n8n.
|
|
*
|
|
* @param mode - Mode brut retourné par l'API
|
|
* @returns Libellé français correspondant
|
|
*/
|
|
export const formatMode = (mode: string): string => {
|
|
const modeMap: Record<string, string> = {
|
|
manual: 'Manuel',
|
|
trigger: 'Déclencheur',
|
|
webhook: 'Webhook',
|
|
internal: 'Interne',
|
|
retry: 'Réessai',
|
|
};
|
|
return modeMap[mode] ?? mode;
|
|
};
|