From 25b56092d5a7570218119fa241456e09b37bcb13 Mon Sep 17 00:00:00 2001 From: Yanis Date: Fri, 1 May 2026 00:37:12 +0200 Subject: [PATCH] feat(search): centralized search modal with categories + map plant distance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Une seule SearchScreen modale gère la recherche depuis Home, MyPlants, Guides et Map. La SearchBar partagée passe en mode trigger sur ces pages, ouvrant la modal au tap. Animation par contexte (native-stack) : - Home/MyPlants/Guides → 'fade_from_bottom' (fade + léger glissement) - Map → 'fade' pur (la barre est déjà en haut, pas de mouvement vertical) via param de route { fromMap: true } SearchScreen — mode global : - 3 catégories : Maladies (red), Guides pratiques (blue), Mes plantes (green) - Filter chips scrollable horizontal : Tout / Maladies / Guides / Plantes avec count par catégorie - Sections en accordion (chevron) avec count par section - Tag coloré sur chaque résultat indiquant la catégorie - Plantes scannées incluses (recherche par customName / cépage) - Tap résultat : DiseaseDetail / GuideDetail / Map+focusScanId / ScanDetail SearchScreen — mode Map (fromMap=true) : - Liste plate des plantes localisées uniquement - Distance haversine depuis position courante (formatDistance helper) - Tri par distance croissante - Tap → navigate Main/Map avec focusScanId MapScreen : - useEffect sur route.params?.focusScanId : animation 2 étapes (zoom large 450ms → zoom serré 500ms) + ouverture du preview - Caméra décalée vers le sud (lat - delta * 0.18) pour que le marker soit visible AU-DESSUS du bottom sheet, pas masqué dessous - Reset du param après usage via setParams Recents : - Hook useRecentSearches (AsyncStorage @vineye:recent_searches) - Max 10, déduplication insensible à la casse - Affichés quand pas de query, avec clear all + remove individuel SearchBar partagée : - Refactorisée 100% Tailwind (sauf 2-3 props RN-spécifiques sur TextInput) - Nouvelle prop onTriggerPress : devient un Pressable avec Text placeholder qui navigate vers Search au lieu d'être un input local Wirings : - SearchSection (Home + Guides) : trigger - MyPlantsScreen : trigger (suppression de l'inline filtering, plus utilisé) - FloatingSearch (Map) : trigger avec fromMap: true - RootNavigator : Stack.Screen Search avec options dynamique selon param i18n FR + EN : - search.{placeholder, placeholderMap, recentTitle, clearAll, noRecent, resultsTitle, noResults, nearbyPlantsTitle, noPlants} - search.filter.{all, diseases, guides, plants} - search.section.{diseases, guides, plants} - search.tag.{disease, guide, plant} Co-Authored-By: Claude Opus 4.7 (1M context) --- VinEye/src/components/home/SearchSection.tsx | 23 +- VinEye/src/components/map/FloatingSearch.tsx | 13 +- VinEye/src/components/shared/SearchBar.tsx | 131 ++-- VinEye/src/hooks/useRecentSearches.ts | 63 ++ VinEye/src/i18n/en.json | 27 + VinEye/src/i18n/fr.json | 27 + VinEye/src/navigation/RootNavigator.tsx | 10 + VinEye/src/navigation/linking.ts | 1 + VinEye/src/screens/MapScreen.tsx | 66 +- VinEye/src/screens/MyPlantsScreen.tsx | 37 +- VinEye/src/screens/SearchScreen.tsx | 648 +++++++++++++++++++ VinEye/src/types/navigation.ts | 3 +- VinEye/src/utils/distance.ts | 34 + 13 files changed, 961 insertions(+), 122 deletions(-) create mode 100644 VinEye/src/hooks/useRecentSearches.ts create mode 100644 VinEye/src/screens/SearchScreen.tsx create mode 100644 VinEye/src/utils/distance.ts diff --git a/VinEye/src/components/home/SearchSection.tsx b/VinEye/src/components/home/SearchSection.tsx index 1980403..681da21 100644 --- a/VinEye/src/components/home/SearchSection.tsx +++ b/VinEye/src/components/home/SearchSection.tsx @@ -1,22 +1,23 @@ -import { View, StyleSheet } from "react-native"; +import { View } from "react-native"; +import { useNavigation } from "@react-navigation/native"; +import type { NativeStackNavigationProp } from "@react-navigation/native-stack"; import { useTranslation } from "react-i18next"; import SearchBar from "@/components/shared/SearchBar"; +import type { RootStackParamList } from "@/types/navigation"; + +type Nav = NativeStackNavigationProp; export default function SearchSection() { const { t } = useTranslation(); + const navigation = useNavigation