import { useEffect, useCallback } from 'react' import './App.css' import { AppRouter } from './router' import { useAppDispatch, useAppSelector } from './store' import { loadFolderResults, setBootstrapped, setCurrentFolderHash, setPollingInterval, stopPolling, setCurrentFolderName } from './store/documentSlice' export default function App() { const dispatch = useAppDispatch() const { documents, bootstrapped, currentFolderHash, folderResults, hasPending, pollingInterval } = useAppSelector((state) => state.document) // Bootstrap au démarrage de l'application avec système de dossiers useEffect(() => { console.log('🔍 [APP] useEffect déclenché:', { documentsLength: documents.length, bootstrapped, currentFolderHash, folderResultsLength: folderResults.length, isDev: import.meta.env.DEV, }) // Récupérer le hash du dossier depuis l'URL const urlParams = new URLSearchParams(window.location.search) const urlFolderHash = urlParams.get('hash') console.log('🔍 [APP] Hash du dossier depuis URL:', urlFolderHash) const initializeFolder = async () => { try { let folderHash = urlFolderHash || currentFolderHash // Si un hash est passé dans l'URL, le prioriser et l'enregistrer if (urlFolderHash && urlFolderHash !== currentFolderHash) { dispatch(setCurrentFolderHash(urlFolderHash)) } // Si aucun hash n'est disponible, utiliser le dossier par défaut demandé if (!folderHash) { folderHash = '7d99a85daf66a0081a0e881630e6b39b' dispatch(setCurrentFolderHash(folderHash)) console.log('📌 [APP] Dossier par défaut appliqué:', folderHash) } // Charger les résultats du dossier console.log('📁 [APP] Chargement des résultats du dossier:', folderHash) await dispatch(loadFolderResults(folderHash)).unwrap() // Marquer le bootstrap comme terminé dispatch(setBootstrapped(true)) console.log('🎉 [APP] Bootstrap terminé avec le dossier:', folderHash) } catch (error) { console.error("❌ [APP] Erreur lors de l'initialisation du dossier:", error) } } // Ne pas refaire le bootstrap si déjà fait if (bootstrapped) { console.log('⏭️ [APP] Bootstrap déjà effectué, dossier:', currentFolderHash) return } initializeFolder() }, [dispatch, bootstrapped, currentFolderHash, folderResults.length, documents.length]) // Listener pour appliquer le fallback de nom de dossier côté store useEffect(() => { const handler = (e: Event) => { const name = (e as CustomEvent).detail if (typeof name === 'string' && name.length > 0) { dispatch(setCurrentFolderName(name)) } } window.addEventListener('4nk:setFolderName', handler as EventListener) return () => window.removeEventListener('4nk:setFolderName', handler as EventListener) }, [dispatch]) // Fonction pour démarrer le polling const startPolling = useCallback( (folderHash: string) => { console.log('🔄 [APP] Démarrage du polling pour le dossier:', folderHash) let pollCount = 0 const maxPolls = 30 // Maximum 30 tentatives (4 minutes à 8s d'intervalle) const interval = setInterval(() => { pollCount++ console.log(`🔄 [APP] Polling #${pollCount} - Vérification des résultats...`) if (pollCount >= maxPolls) { console.log('⏹️ [APP] Arrêt du polling - limite de tentatives atteinte') clearInterval(interval) dispatch(stopPolling()) return } dispatch(loadFolderResults(folderHash)) }, 12000) // Polling moins fréquent (12s) dispatch(setPollingInterval(interval)) }, [dispatch], ) // Fonction pour arrêter le polling const stopPollingCallback = useCallback(() => { console.log('⏹️ [APP] Arrêt du polling') dispatch(stopPolling()) }, [dispatch]) // Gestion du polling basé sur l'état hasPending useEffect(() => { // Ne démarrer le polling que si on n'a encore jamais chargé ce dossier // et seulement quand le backend indique des pending if (hasPending && currentFolderHash && !pollingInterval) { console.log('🔄 [APP] Démarrage du polling - fichiers en cours détectés') startPolling(currentFolderHash) } else if (!hasPending && pollingInterval) { console.log('⏹️ [APP] Arrêt du polling - tous les fichiers traités') stopPollingCallback() } }, [hasPending, currentFolderHash, pollingInterval, startPolling, stopPollingCallback]) // Nettoyage au démontage du composant useEffect(() => { return () => { if (pollingInterval) { clearInterval(pollingInterval) } } }, [pollingInterval]) return }