Skip to content

Commit

Permalink
feat: enhance search component with loading state and localized messa…
Browse files Browse the repository at this point in the history
…ges for better user experience
  • Loading branch information
omdxp committed Dec 24, 2024
1 parent 7e05fb9 commit ec6df46
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 15 deletions.
8 changes: 8 additions & 0 deletions web/src/components/locale/dictionary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -446,4 +446,12 @@ Besides the open tasks on [/Contribute](/Contribute) page, you can also contribu
en: "Projects",
ar: "مشاريع",
},
"search-type-to-search": {
en: "Type to search...",
ar: "اكتب للبحث...",
},
"search-no-results-found": {
en: "No results found",
ar: "لم يتم العثور على نتائج",
},
} as const;
59 changes: 46 additions & 13 deletions web/src/components/search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function Search(): JSX.Element {
const { localize } = useLocale();
const [query, setQuery] = useState("");

const results = useSearch(query);
const { results, isFetching } = useSearch(query);

const hideModal = useCallback(() => {
(document.getElementById("search-modal") as HTMLDialogElement).hidePopover();
Expand Down Expand Up @@ -61,6 +61,30 @@ export function Search(): JSX.Element {
>;
}, [results?.searchResults.results]);

const searchTextOutput = useMemo(() => {
if (isFetching) {
return "";
}
if (query === "") {
return localize("search-type-to-search");
}
if (
projectsList.length === 0 &&
contributorsList.length === 0 &&
contributionsList.length === 0
) {
return localize("search-no-results-found");
}
return "";
}, [
isFetching,
query,
projectsList.length,
contributorsList.length,
contributionsList.length,
localize,
]);

return (
<dialog id="search-modal" className="modal">
<div className="modal-box w-11/12 max-w-5xl h-[80vh] flex flex-col">
Expand All @@ -71,20 +95,29 @@ export function Search(): JSX.Element {
placeholder={localize("navbar-section-search")}
onChange={onSearchInputChange}
/>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
className="h-4 w-4 opacity-70"
>
<path
fillRule="evenodd"
d="M9.965 11.026a5 5 0 1 1 1.06-1.06l2.755 2.754a.75.75 0 1 1-1.06 1.06l-2.755-2.754ZM10.5 7a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0Z"
clipRule="evenodd"
/>
</svg>
{isFetching ? (
<span className="loading loading-dots loading-lg"></span>
) : (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
className="h-4 w-4 opacity-70"
>
<path
fillRule="evenodd"
d="M9.965 11.026a5 5 0 1 1 1.06-1.06l2.755 2.754a.75.75 0 1 1-1.06 1.06l-2.755-2.754ZM10.5 7a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0Z"
clipRule="evenodd"
/>
</svg>
)}
</label>
<div className="overflow-y-auto flex-grow">
{searchTextOutput && (
<div className="flex justify-center items-center h-full">
<p>{searchTextOutput}</p>
</div>
)}
{contributionsList?.length > 0 && (
<div className="mt-4">
<h3 className="text-lg font-bold">
Expand Down
10 changes: 8 additions & 2 deletions web/src/utils/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { SearchResponse } from "@dzcode.io/api/dist/search/types";

export const useSearch = (query: string, limit: number = 5) => {
const [results, setResults] = useState<SearchResponse>();
const [isFetching, setIsFetching] = useState(false);
const queryRef = useRef("");
const timeoutRef = useRef<NodeJS.Timeout | null>(null);

const search = useCallback(async () => {
setIsFetching(true);
const searchResults = await fetchV2("api:Search", {
query: [
["query", queryRef.current],
Expand All @@ -16,22 +18,26 @@ export const useSearch = (query: string, limit: number = 5) => {
});

setResults(searchResults);
setIsFetching(false);
}, [limit]);

useEffect(() => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}

setIsFetching(true);
timeoutRef.current = setTimeout(() => {
queryRef.current = query;
if (queryRef.current.length) search();
else
else {
setResults({
searchResults: {
results: [],
},
});
setIsFetching(false);
}
}, 300);

return () => {
Expand All @@ -41,5 +47,5 @@ export const useSearch = (query: string, limit: number = 5) => {
};
}, [query, search]);

return results;
return { results, isFetching };
};

0 comments on commit ec6df46

Please sign in to comment.