diff --git a/src/stores/use-catalog-filters-store.ts b/src/stores/use-catalog-filters-store.ts index 73d55952..9ddccde8 100644 --- a/src/stores/use-catalog-filters-store.ts +++ b/src/stores/use-catalog-filters-store.ts @@ -1,6 +1,11 @@ import { create } from 'zustand'; import { persist } from 'zustand/middleware'; +interface FilterItem { + text: string; + enabled: boolean; +} + interface CatalogFiltersStore { showAdultBoards: boolean; setShowAdultBoards: (value: boolean) => void; @@ -10,11 +15,14 @@ interface CatalogFiltersStore { setShowTextOnlyThreads: (value: boolean) => void; filterText: string; setFilterText: (value: string) => void; + filterItems: FilterItem[]; + setFilterItems: (items: FilterItem[]) => void; // New method to set all filter items at once + saveAndApplyFilters: (items: FilterItem[]) => void; // Updated to accept items } const useCatalogFiltersStore = create( persist( - (set) => ({ + (set, get) => ({ showTextOnlyThreads: false, setShowTextOnlyThreads: (value: boolean) => set({ showTextOnlyThreads: value }), showAdultBoards: false, @@ -23,6 +31,13 @@ const useCatalogFiltersStore = create( setShowGoreBoards: (value: boolean) => set({ showGoreBoards: value }), filterText: '', setFilterText: (value: string) => set({ filterText: value }), + filterItems: [], + setFilterItems: (items: FilterItem[]) => set({ filterItems: items }), + saveAndApplyFilters: (items: FilterItem[]) => { + set({ filterItems: items }); + console.log('Filters saved and applied:', items); + // Example: refreshCatalog(); + }, }), { name: 'catalog-filters-storage', diff --git a/src/views/catalog/catalog-filters/catalog-filters.module.css b/src/views/catalog/catalog-filters/catalog-filters.module.css index 1067526a..fd2f7abf 100644 --- a/src/views/catalog/catalog-filters/catalog-filters.module.css +++ b/src/views/catalog/catalog-filters/catalog-filters.module.css @@ -111,7 +111,7 @@ border-spacing: 1px; margin-left: auto; margin-right: auto; - padding-top: 10px; + padding: 10px 2px 2px 2px; } .filtersTable th { diff --git a/src/views/catalog/catalog-filters/catalog-filters.tsx b/src/views/catalog/catalog-filters/catalog-filters.tsx index aab17e39..1c378c37 100644 --- a/src/views/catalog/catalog-filters/catalog-filters.tsx +++ b/src/views/catalog/catalog-filters/catalog-filters.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useState, useCallback, useEffect } from 'react'; import { useLocation, useParams } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { isAllView, isCatalogView } from '../../../lib/utils/view-utils'; @@ -7,8 +7,37 @@ import styles from './catalog-filters.module.css'; const FiltersTable = () => { const { t } = useTranslation(); - const { filterText, setFilterText } = useCatalogFiltersStore(); - const [localFilterText, setLocalFilterText] = useState(filterText); + const { filterItems, saveAndApplyFilters } = useCatalogFiltersStore(); + const [localFilterItems, setLocalFilterItems] = useState([]); + + useEffect(() => { + setLocalFilterItems(filterItems); + }, [filterItems]); + + const handleAddFilter = useCallback(() => { + setLocalFilterItems([...localFilterItems, { text: '', enabled: true }]); + }, [localFilterItems]); + + const handleSave = useCallback(() => { + saveAndApplyFilters(localFilterItems); + }, [saveAndApplyFilters, localFilterItems]); + + const updateLocalFilterItem = useCallback((index: number, item: any) => { + setLocalFilterItems((items) => items.map((f, i) => (i === index ? item : f))); + }, []); + + const removeLocalFilterItem = useCallback((index: number) => { + setLocalFilterItems((items) => items.filter((_, i) => i !== index)); + }, []); + + const moveLocalFilterItemUp = useCallback((index: number) => { + if (index === 0) return; + setLocalFilterItems((items) => { + const newItems = [...items]; + [newItems[index - 1], newItems[index]] = [newItems[index], newItems[index - 1]]; + return newItems; + }); + }, []); return ( @@ -21,26 +50,41 @@ const FiltersTable = () => { - - - - - - + {localFilterItems.map((item, index) => ( + + + + + + + ))} - @@ -89,8 +133,8 @@ const FiltersModal = ({ closeModal }: { closeModal: () => void }) => { )} - + ); diff --git a/src/views/catalog/catalog.tsx b/src/views/catalog/catalog.tsx index eefe7ab8..ee7bc0fc 100644 --- a/src/views/catalog/catalog.tsx +++ b/src/views/catalog/catalog.tsx @@ -27,13 +27,17 @@ const threadsWithImagesFilter = (comment: Comment) => { return hasThumbnail; }; -const textFilter = (comment: Comment, filterText: string) => { - if (!filterText) return true; - const filterWords = filterText.toLowerCase().split(/\s+/); - const titleWords = comment?.title?.toLowerCase().split(/\s+/) || []; - const contentWords = comment?.content?.toLowerCase().split(/\s+/) || []; +const textFilter = (comment: Comment, filterItems: any[]) => { + if (!filterItems) return true; + if (filterItems.length === 0) return true; + const titleLower = comment?.title?.toLowerCase() || ''; + const contentLower = comment?.content?.toLowerCase() || ''; - return !filterWords.every((filterWord) => titleWords.includes(filterWord) || contentWords.includes(filterWord)); + return filterItems.every((item) => { + if (!item.enabled) return true; + const pattern = item.text.toLowerCase(); + return !(titleLower.includes(pattern) || contentLower.includes(pattern)); + }); }; const Catalog = () => { @@ -43,7 +47,7 @@ const Catalog = () => { const isInAllView = isAllView(location.pathname, useParams()); const defaultSubplebbits = useDefaultSubplebbits(); - const { showAdultBoards, showGoreBoards, showTextOnlyThreads, filterText } = useCatalogFiltersStore(); + const { showAdultBoards, showGoreBoards, showTextOnlyThreads, filterItems } = useCatalogFiltersStore(); const account = useAccount(); const subscriptions = account?.subscriptions; @@ -92,10 +96,10 @@ const Catalog = () => { if (!showTextOnlyThreads && !threadsWithImagesFilter(comment)) { return false; } - return textFilter(comment, filterText); + return textFilter(comment, filterItems); }, }), - [subplebbitAddresses, sortType, isInAllView, isInSubscriptionsView, postsPerPage, showTextOnlyThreads, filterText], + [subplebbitAddresses, sortType, isInAllView, isInSubscriptionsView, postsPerPage, showTextOnlyThreads, filterItems], ); if (isInAllView || isInSubscriptionsView) {
- - - - - setLocalFilterText(e.target.value)} value={localFilterText} /> - - × -
+ moveLocalFilterItemUp(index)}> + ↑ + + + updateLocalFilterItem(index, { ...item, enabled: e.target.checked })} + /> + + updateLocalFilterItem(index, { ...item, text: e.target.value })} /> + + removeLocalFilterItem(index)}> + × + +
- - + + +