import axios from "axios"; import { useLocalSearchParams } from "expo-router"; import debounce from "lodash/debounce"; import { useCallback, useEffect, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { FlatList, View } from "react-native"; import { ActivityIndicator, Icon, Text } from "react-native-paper"; import env from "../../env"; import ErrorDisplay from "../error/error-display"; import JobListItem from "../jobs-list/job-list-item"; // Debounce delay (ms) – adjust as needed const GLOBAL_SEARCH_DEBOUNCE_MS = 400; /** * Hook returning a debounced search trigger. * It recreates the debounced function only when the underlying callback changes. * Placeholder: Replace the body of `performSearch` with real API / GraphQL logic. */ function useDebouncedGlobalSearch(onSearch, delay = GLOBAL_SEARCH_DEBOUNCE_MS) { const debouncedRef = useRef(() => {}); useEffect(() => { // Create debounced wrapper const debounced = debounce((query) => { onSearch(query); }, delay); debouncedRef.current = debounced; return () => debounced.cancel(); }, [onSearch, delay]); return useCallback((query) => { debouncedRef.current && debouncedRef.current(query); }, []); } export default function GlobalSearch() { const { globalSearch } = useLocalSearchParams(); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [results, setResults] = useState([]); const { t } = useTranslation(); // Placeholder: Replace with actual API call (e.g., Apollo client query, REST fetch, Redux saga dispatch) const performSearch = useCallback(async (query) => { // Defensive trimr const q = (query || "").trim(); if (!q) return; setLoading(true); setError(null); // TODO: Integrate real search endpoint console.log(`[GlobalSearch] (debounced placeholder) searching for: "${q}"`); try { const searchData = await axios.post(`${env.API_URL}/search`, { search: q, }); if (searchData.data) { const jobResults = searchData.data?.hits?.hits ?.filter((hit) => hit._index === "jobs") .map((hit) => hit._source); setResults(jobResults); } else { setError("No results available. Try again."); } } catch (error) { console.error("Search error:", error, error.response); setError(error.message); } setLoading(false); }, []); const debouncedSearch = useDebouncedGlobalSearch(performSearch); // Trigger debounced search when the route param changes useEffect(() => { if (typeof globalSearch === "string" && globalSearch.length > 0) { debouncedSearch(globalSearch); } }, [globalSearch, debouncedSearch]); if (globalSearch === undefined || globalSearch.trim() === "") { return ( {t("globalsearch.labels.entersearch")} ); } return ( {loading && } {error && } {results.length} results found item.id?.toString()} renderItem={(object) => } /> ); }