diff --git a/frontend/src/pages/Search.jsx b/frontend/src/pages/Search.jsx index 64e5129..68c4e26 100644 --- a/frontend/src/pages/Search.jsx +++ b/frontend/src/pages/Search.jsx @@ -51,224 +51,236 @@ export default function Search() { // Charger les sites au démarrage useEffect(() => { - } catch (error) { - console.error('Error loading sites:', error); - toast.error('Erreur lors du chargement des sites'); - } -}; + loadSites(); + }, []); -const handleSearch = async (e) => { - e.preventDefault(); - if (!query.trim() || !selectedSiteId) { - toast.error('Veuillez entrer une recherche et sélectionner un site'); - return; - } - - // Clear previous storage when starting new search - sessionStorage.removeItem(STORAGE_KEY); - - // Fermer l'EventSource précédent si existant - if (eventSourceRef.current) { - eventSourceRef.current.close(); - } - - setIsSearching(true); - setResults([]); - setProgress({ status: 'searching', total: 1, completed: 0 }); - - // Construire l'URL avec les paramètres - const params = new URLSearchParams({ - q: query.trim(), - sites: selectedSiteId, - max_results: 20, - }); - - // Créer l'EventSource pour SSE - const eventSource = new EventSource(`${API_URL}/search?${params}`); - eventSourceRef.current = eventSource; - - eventSource.addEventListener('progress', (event) => { + const loadSites = async () => { try { - const data = JSON.parse(event.data); - setProgress(data); - setResults(data.results || []); - - if (data.status === 'completed' || data.status === 'error') { - setIsSearching(false); - eventSource.close(); - - if (data.status === 'completed') { - toast.success(`${data.results?.length || 0} produits trouvés`); - } else if (data.message) { - toast.error(data.message); - } + const response = await axios.get(`${API_URL}/search-sites`); + const activeSites = response.data.filter(site => site.is_active); + setSites(activeSites); + // Sélectionner le premier site actif par défaut si aucun site n'est sélectionné + if (activeSites.length > 0 && !selectedSiteId) { + setSelectedSiteId(activeSites[0].id.toString()); } } catch (error) { - console.error('Error parsing SSE data:', error); + console.error('Error loading sites:', error); + toast.error('Erreur lors du chargement des sites'); } - }); - - eventSource.onerror = () => { - setIsSearching(false); - eventSource.close(); - toast.error('Erreur de connexion au serveur'); }; -}; -const handleAddToMonitoring = async (result) => { - try { - await axios.post(`${API_URL}/items`, { - url: result.url, - name: result.title, - target_price: null, - check_interval_minutes: 60, + const handleSearch = async (e) => { + e.preventDefault(); + if (!query.trim() || !selectedSiteId) { + toast.error('Veuillez entrer une recherche et sélectionner un site'); + return; + } + + // Clear previous storage when starting new search + sessionStorage.removeItem(STORAGE_KEY); + + // Fermer l'EventSource précédent si existant + if (eventSourceRef.current) { + eventSourceRef.current.close(); + } + + setIsSearching(true); + setResults([]); + setProgress({ status: 'searching', total: 1, completed: 0 }); + + // Construire l'URL avec les paramètres + const params = new URLSearchParams({ + q: query.trim(), + sites: selectedSiteId, + max_results: 20, }); - toast.success(`"${result.title}" ajouté au monitoring`); - } catch (error) { - console.error('Error adding item:', error); - toast.error("Erreur lors de l'ajout au monitoring"); - } -}; -const progressPercent = progress - ? Math.round((progress.completed / Math.max(progress.total, 1)) * 100) - : 0; + // Créer l'EventSource pour SSE + const eventSource = new EventSource(`${API_URL}/search?${params}`); + eventSourceRef.current = eventSource; -const selectedSite = sites.find(s => s.id.toString() === selectedSiteId); + eventSource.addEventListener('progress', (event) => { + try { + const data = JSON.parse(event.data); + setProgress(data); + setResults(data.results || []); -return ( -
- {/* Header */} -
-
-

Recherche de produits

-

- Recherchez des produits sur un site et ajoutez-les au monitoring -

+ if (data.status === 'completed' || data.status === 'error') { + setIsSearching(false); + eventSource.close(); + + if (data.status === 'completed') { + toast.success(`${data.results?.length || 0} produits trouvés`); + } else if (data.message) { + toast.error(data.message); + } + } + } catch (error) { + console.error('Error parsing SSE data:', error); + } + }); + + eventSource.onerror = () => { + setIsSearching(false); + eventSource.close(); + toast.error('Erreur de connexion au serveur'); + }; + }; + + const handleAddToMonitoring = async (result) => { + try { + await axios.post(`${API_URL}/items`, { + url: result.url, + name: result.title, + target_price: null, + check_interval_minutes: 60, + }); + toast.success(`"${result.title}" ajouté au monitoring`); + } catch (error) { + console.error('Error adding item:', error); + toast.error("Erreur lors de l'ajout au monitoring"); + } + }; + + const progressPercent = progress + ? Math.round((progress.completed / Math.max(progress.total, 1)) * 100) + : 0; + + const selectedSite = sites.find(s => s.id.toString() === selectedSiteId); + + return ( +
+ {/* Header */} +
+
+

Recherche de produits

+

+ Recherchez des produits sur un site et ajoutez-les au monitoring +

+
-
- {/* Search Form */} - - -
- {/* Site Selection */} -
-

Site de recherche :

- {sites.length === 0 ? ( -

- Aucun site configuré. Contactez l'administrateur pour activer des sites. -

- ) : ( - - )} -
- - {/* Search Input */} -
-
- - setQuery(e.target.value)} - className="pl-9" - disabled={isSearching} - /> -
- -
- - {/* Selected site info */} - {selectedSite && ( -

- Recherche sur {selectedSite.name} ({selectedSite.domain}) -

- )} -
-
-
- - {/* Progress Bar */} - {progress && isSearching && ( + {/* Search Form */} -
-
- {progress.message || 'Recherche en cours...'} - {progressPercent}% +
+ {/* Site Selection */} +
+

Site de recherche :

+ {sites.length === 0 ? ( +

+ Aucun site configuré. Contactez l'administrateur pour activer des sites. +

+ ) : ( + + )}
- + + {/* Search Input */} +
+
+ + setQuery(e.target.value)} + className="pl-9" + disabled={isSearching} + /> +
+ +
+ + {/* Selected site info */} + {selectedSite && ( +

+ Recherche sur {selectedSite.name} ({selectedSite.domain}) +

+ )} + + + + + {/* Progress Bar */} + {progress && isSearching && ( + + +
+
+ {progress.message || 'Recherche en cours...'} + {progressPercent}% +
+ +
+
+
+ )} + + {/* Results */} + {results.length > 0 && ( +
+
+

+ {results.length} produit{results.length > 1 ? 's' : ''} trouvé{results.length > 1 ? 's' : ''} +

+
+
+ {results.map((result, index) => ( + handleAddToMonitoring(result)} + /> + ))}
- - - )} - - {/* Results */} - {results.length > 0 && ( -
-
-

- {results.length} produit{results.length > 1 ? 's' : ''} trouvé{results.length > 1 ? 's' : ''} -

-
- {results.map((result, index) => ( - handleAddToMonitoring(result)} - /> - ))} -
-
- )} + )} - {/* Empty State */} - {!isSearching && results.length === 0 && progress?.status === 'completed' && ( - - - -

Aucun produit trouvé

-

- Essayez avec d'autres termes de recherche ou sélectionnez un autre site -

-
-
- )} -
-); + {/* Empty State */} + {!isSearching && results.length === 0 && progress?.status === 'completed' && ( + + + +

Aucun produit trouvé

+

+ Essayez avec d'autres termes de recherche ou sélectionnez un autre site +

+
+
+ )} +
+ ); }