From 4ce2f3a4e96993b41018e00e447aee7a2d7c0cb4 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Sun, 12 Dec 2021 00:57:25 -0800 Subject: [PATCH] Clean up dual filter logic --- src/components/library/AdvancedFilters.tsx | 69 ++++++++++++++++------ src/components/library/AlbumList.tsx | 19 ++++-- src/hooks/useAdvancedFilter.ts | 25 +++++++- 3 files changed, 89 insertions(+), 24 deletions(-) diff --git a/src/components/library/AdvancedFilters.tsx b/src/components/library/AdvancedFilters.tsx index 7dae251..bba70b1 100644 --- a/src/components/library/AdvancedFilters.tsx +++ b/src/components/library/AdvancedFilters.tsx @@ -21,31 +21,64 @@ const AdvancedFilters = ({ filteredData, originalData, filter, setAdvancedFilter const dispatch = useAppDispatch(); const [availableGenres, setAvailableGenres] = useState([]); const [availableArtists, setAvailableArtists] = useState([]); - const [data, setData] = useState([]); + const [genreListData, setGenreListData] = useState([]); + const [artistListData, setArtistListData] = useState([]); const genreFilterPickerContainerRef = useRef(); const artistFilterPickerContainerRef = useRef(); + // Filter flow from TOP to BOTTOM (see useAdvancedFilter hook) + // 1. byStarredData + // 2. byGenreData + // 3. byArtistData + // 4. filteredData + useEffect(() => { - if ( - filter.properties.artist.type === 'or' && - filter.properties.artist.list.length > 0 && - filter.properties.genre.list.length > 0 - ) { - return setData(filteredData.byGenreData); + if (filter.properties.artist.type === 'and') { + return setArtistListData(filteredData.byArtistData); } - if (filter.properties.artist.type === 'or' && filter.properties.artist.list.length > 0) { - return setData(filteredData.byStarredData); + if (filter.properties.starred) { + return setArtistListData(filteredData.byGenreData); } - if (filter.properties.genre.list.length > 0) { - return setData(filteredData.filteredData); + if (filter.properties.artist.type === 'or') { + return setArtistListData(filteredData.byGenreData); } - return setData(originalData); + return setArtistListData(originalData); }, [ filter.properties.artist.list.length, filter.properties.artist.type, + filter.properties.starred, + filteredData.byArtistData, + filteredData.byGenreData, + originalData, + ]); + + useEffect(() => { + if (filter.properties.starred) { + if (filter.properties.genre.type === 'and') { + return setGenreListData(filteredData.filteredData); + } + return setGenreListData(filteredData.byArtistData); + } + + if (filter.properties.artist.list.length > 0) { + if (filter.properties.genre.type === 'and') { + return setGenreListData(filteredData.filteredData); + } + return setGenreListData(filteredData.byArtistBaseData); + } + + if (filter.properties.genre.list.length > 0) { + if (filter.properties.genre.type === 'and') { + return setGenreListData(filteredData.byGenreData); + } + } + + return setGenreListData(originalData); + }, [ + filter.properties.artist.list.length, filter.properties.genre.list.length, filter.properties.genre.type, filter.properties.starred, @@ -54,7 +87,7 @@ const AdvancedFilters = ({ filteredData, originalData, filter, setAdvancedFilter ]); useEffect(() => { - const allGenres = _.flatten(_.map(data, 'genre')); + const allGenres = _.flatten(_.map(genreListData, 'genre')); const counts = _.countBy(allGenres, 'title'); const uniqueGenres = _.orderBy(_.uniqBy(allGenres, 'title'), [ (entry: any) => { @@ -73,10 +106,10 @@ const AdvancedFilters = ({ filteredData, originalData, filter, setAdvancedFilter }; }) ); - }, [data, filter.properties.genre.type, filter.properties.starred, filteredData, originalData]); + }, [genreListData]); useEffect(() => { - const allArtists = _.flatten(_.map(data, 'artist')); + const allArtists = _.flatten(_.map(artistListData, 'artist')); const counts = _.countBy(allArtists, 'id'); const uniqueArtists = _.orderBy(_.uniqBy(allArtists, 'id'), [ (entry: any) => { @@ -95,7 +128,7 @@ const AdvancedFilters = ({ filteredData, originalData, filter, setAdvancedFilter }; }) ); - }, [data, filter.properties.artist.type, filter.properties.starred, filteredData, originalData]); + }, [artistListData]); return (
@@ -166,7 +199,7 @@ const AdvancedFilters = ({ filteredData, originalData, filter, setAdvancedFilter }} /> 0 ? 'primary' : ''} + appearance={filter.properties.genre.list.length > 0 ? 'primary' : 'subtle'} disabled={filter.properties.genre.list.length === 0} size="xs" icon={} @@ -227,7 +260,7 @@ const AdvancedFilters = ({ filteredData, originalData, filter, setAdvancedFilter }} /> 0 ? 'primary' : ''} + appearance={filter.properties.artist.list.length > 0 ? 'primary' : 'subtle'} disabled={filter.properties.artist.list.length === 0} size="xs" icon={} diff --git a/src/components/library/AlbumList.tsx b/src/components/library/AlbumList.tsx index 58d22cc..b2cc239 100644 --- a/src/components/library/AlbumList.tsx +++ b/src/components/library/AlbumList.tsx @@ -132,10 +132,13 @@ const AlbumList = () => { 'year', ]); - const { filteredData, byArtistData, byGenreData, byStarredData } = useAdvancedFilter( - albums, - album.advancedFilters - ); + const { + filteredData, + byArtistData, + byArtistBaseData, + byGenreData, + byStarredData, + } = useAdvancedFilter(albums, album.advancedFilters); useEffect(() => { setSortTypes(_.compact(_.concat(ALBUM_SORT_TYPES, genres))); @@ -260,7 +263,13 @@ const AlbumList = () => { speaker={ { const [byStarredData, setByStarredData] = useState([]); const [byGenreData, setByGenreData] = useState([]); const [byArtistData, setByArtistData] = useState([]); + const [byArtistBaseData, setByArtistBaseData] = useState([]); const [filterProps, setFilterProps] = useState(filters); @@ -64,16 +65,38 @@ const useAdvancedFilter = (data: any[], filters: AdvancedFilters) => { }) : filteredByGenres; + // Instead of filtering from the previous (genre), start from the starred filter + const filteredByArtistsBase = + filterProps.properties.artist.list.length > 0 + ? (filteredByStarred || []).filter((entry) => { + const entryArtistIds = _.map(entry.artist, 'id'); + + if (filterProps.properties.artist.type === 'or') { + return entryArtistIds.some((artistId) => artistId.match(artistRegex)); + } + + const matches = []; + for (let i = 0; i < filterProps.properties.artist.list.length; i += 1) { + if (entryArtistIds.includes(filterProps.properties.artist.list[i])) { + matches.push(entry); + } + } + + return matches.length === filterProps.properties.artist.list.length; + }) + : filteredByStarred; + setByStarredData(_.compact(_.uniqBy(filteredByStarred, 'uniqueId'))); setByGenreData(_.compact(_.uniqBy(filteredByGenres, 'uniqueId'))); setByArtistData(_.compact(_.uniqBy(filteredByArtists, 'uniqueId'))); + setByArtistBaseData(_.compact(_.uniqBy(filteredByArtistsBase, 'uniqueId'))); setFilteredData(_.compact(_.uniqBy(filteredByArtists, 'uniqueId'))); } else { setFilteredData(data); } }, [data, filterProps, filters]); - return { filteredData, byStarredData, byGenreData, byArtistData }; + return { filteredData, byStarredData, byGenreData, byArtistData, byArtistBaseData }; }; export default useAdvancedFilter;