feat(catalog): add search

This commit is contained in:
Tom (plebeius.eth)
2025-03-06 16:27:09 +01:00
parent cf183393a4
commit a8f7de7d85
41 changed files with 213 additions and 60 deletions
+22 -6
View File
@@ -246,7 +246,7 @@ export const MobileBoardButtons = () => {
const accountComment = useAccountComment({ commentIndex: params?.accountCommentIndex as any });
const subplebbitAddress = params?.subplebbitAddress || accountComment?.subplebbitAddress;
const { filteredCount } = useCatalogFiltersStore();
const { filteredCount, searchText } = useCatalogFiltersStore();
return (
<div className={`${styles.mobileBoardButtons} ${!isInCatalogView ? styles.addMargin : ''}`}>
@@ -269,11 +269,19 @@ export const MobileBoardButtons = () => {
)}
{!(isInAllView || isInSubscriptionsView) && <SubscribeButton address={subplebbitAddress} />}
<RefreshButton />
{isInCatalogView && filteredCount > 0 && (
{isInCatalogView && searchText ? (
<span className={styles.filteredThreadsCount}>
{' '}
{t('filtered_threads')}: <strong>{filteredCount}</strong>
{t('search_results_for')}: <strong>{searchText}</strong>
</span>
) : (
isInCatalogView &&
filteredCount > 0 && (
<span className={styles.filteredThreadsCount}>
{' '}
{t('filtered_threads')}: <strong>{filteredCount}</strong>
</span>
)
)}
{isInCatalogView && (
<>
@@ -331,7 +339,7 @@ export const DesktopBoardButtons = () => {
const isInPostView = isPostPageView(location.pathname, params);
const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams());
const { filteredCount } = useCatalogFiltersStore();
const { filteredCount, searchText } = useCatalogFiltersStore();
return (
<>
@@ -364,11 +372,19 @@ export const DesktopBoardButtons = () => {
</>
)}
[<RefreshButton />]
{isInCatalogView && filteredCount > 0 && (
{isInCatalogView && searchText ? (
<span className={styles.filteredThreadsCount}>
{' '}
{t('filtered_threads')}: <strong>{filteredCount}</strong>
{t('search_results_for')}: <strong>{searchText}</strong>
</span>
) : (
isInCatalogView &&
filteredCount > 0 && (
<span className={styles.filteredThreadsCount}>
{' '}
{t('filtered_threads')}: <strong>{filteredCount}</strong>
</span>
)
)}
<span className={styles.rightSideButtons}>
{isInCatalogView && (
@@ -1,11 +1,43 @@
import { useEffect, useState } from 'react';
import { useEffect, useState, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import styles from './catalog-search.module.css';
import useIsMobile from '../../hooks/use-is-mobile';
import useCatalogFiltersStore from '../../stores/use-catalog-filters-store';
import _ from 'lodash';
const CatalogSearch = () => {
const { t } = useTranslation();
const [openSearch, setOpenSearch] = useState(false);
const [inputValue, setInputValue] = useState('');
const { setSearchFilter, clearSearchFilter } = useCatalogFiltersStore();
// Create a debounced version of setSearchFilter
// eslint-disable-next-line react-hooks/exhaustive-deps
const debouncedSetSearchFilter = useCallback(
_.debounce((text: string) => {
if (text.trim()) {
setSearchFilter(text);
} else {
clearSearchFilter();
}
}, 300),
[setSearchFilter, clearSearchFilter],
);
const handleToggleSearch = useCallback(() => {
setOpenSearch((prev) => !prev);
if (openSearch) {
setInputValue('');
clearSearchFilter();
}
}, [openSearch, clearSearchFilter]);
const handleCloseSearch = useCallback(() => {
setOpenSearch(false);
setInputValue('');
clearSearchFilter();
}, [clearSearchFilter]);
useEffect(() => {
if (openSearch) {
@@ -14,26 +46,42 @@ const CatalogSearch = () => {
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === 'Escape') {
setOpenSearch(false);
handleCloseSearch();
}
};
window.addEventListener('keydown', handleKeyDown);
return () => {
window.removeEventListener('keydown', handleKeyDown);
};
}
}, [openSearch]);
}, [openSearch, handleCloseSearch]);
useEffect(() => {
debouncedSetSearchFilter(inputValue);
return () => {
debouncedSetSearchFilter.cancel();
};
}, [inputValue, debouncedSetSearchFilter]);
const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(e.target.value);
};
const isMobile = useIsMobile();
return (
<>
{!isMobile && '['}
<span className={`${styles.filtersButton} button`} onClick={() => setOpenSearch(!openSearch)}>
<span className={`${styles.filtersButton} button`} onClick={handleToggleSearch}>
{t('search')}
</span>
{!isMobile && ']'}
{openSearch && (
<div className={styles.searchContainer}>
<input type='text' />
<span className={styles.closeSearch} onClick={() => setOpenSearch(false)}>
<input type='text' value={inputValue} onChange={handleSearchChange} />
<span className={styles.closeSearch} onClick={handleCloseSearch}>
</span>
</div>