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, KeyboardAvoidingView, Platform } 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();
const performSearch = useCallback(async (query) => {
// Defensive trimr
const q = (query || "").trim();
if (!q) return;
setLoading(true);
setError(null);
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, { id: "footer-spacer", height: 128 }]);
} 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 && }
{!loading && (
{results.length} results found
)}
item.id?.toString()}
renderItem={(object) => }
/>
);
}