diff --git a/src/pages/settings/components/Theming/ThemePlaylists/ThemePlaylists.tsx b/src/pages/settings/components/Theming/ThemePlaylists/ThemePlaylists.tsx index 223d3c4..43bdaf5 100644 --- a/src/pages/settings/components/Theming/ThemePlaylists/ThemePlaylists.tsx +++ b/src/pages/settings/components/Theming/ThemePlaylists/ThemePlaylists.tsx @@ -2,7 +2,7 @@ import { Box, Group, LoadingOverlay, SimpleGrid, Stack, Text } from '@mantine/co import { useDebouncedValue, useDisclosure } from '@mantine/hooks'; import { NoItemsFound, SettingsHeader } from 'components'; import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks'; -import { useEffect, useState } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import { FiChevronRight } from 'react-icons/fi'; import { textClasses } from 'styles'; import type { Theme, ThemePlaylist } from 'types'; @@ -21,13 +21,17 @@ export function ThemePlaylists() { }); const [searchValue, setSearchValue] = useState(''); const [debouncedSearch] = useDebouncedValue(searchValue, 500); - const themePlaylists: ThemePlaylist[] = - themePlaylistData?.filter( - (a: ThemePlaylist) => - a.name.toLowerCase().includes((debouncedSearch as string).toLowerCase()) || - a.name.includes('Time of Day'), - ) || []; - const defaultPlaylist = { + + const themePlaylists: ThemePlaylist[] = useMemo(() => { + return ( + themePlaylistData?.filter( + (a: ThemePlaylist) => + a.name.toLowerCase().includes((debouncedSearch as string).toLowerCase()) || + a.name.includes('Time of Day'), + ) || [] + ); + }, [themePlaylistData, debouncedSearch]); + const defaultPlaylist: ThemePlaylist = { id: undefined, default: 0, name: 'New Playlist', @@ -40,30 +44,94 @@ export function ThemePlaylists() { const { currentThemePlaylist, theme, isMobile } = useCommonHooks(); const [isLoading, setIsLoading] = useState(false); - const handleOpen = (playlist: ThemePlaylist) => { - setSelectedPlaylist(playlist); - open(); - }; + const handleOpen = useCallback( + (playlist: ThemePlaylist) => { + setSelectedPlaylist(playlist); + open(); + }, + [open], + ); - const handleClose = () => { + const handleClose = useCallback(() => { setSelectedPlaylist(defaultPlaylist); close(); - }; + }, [close]); - const handleSavePlaylist = () => { + const handleSavePlaylist = useCallback(() => { mutateAsync({ method: selectedPlaylist?.id === undefined ? 'POST' : 'PATCH', endpoint: themePlaylistsEndpoint, body: selectedPlaylist ?? {}, }); close(); - }; + }, [selectedPlaylist, mutateAsync, themePlaylistsEndpoint, close]); useEffect(() => { if (debouncedSearch === searchValue) { setIsLoading(false); } - }, [debouncedSearch]); + }, [debouncedSearch, searchValue]); + + const allThemesIds = useMemo( + () => allThemeData?.map((a: Theme) => a.id) ?? [], + [allThemeData], + ); + + const backgroundsThemes = useMemo( + () => + allThemeData?.filter( + (a: any) => !a.backgroundImage.toLowerCase().includes('none'), + ) ?? [], + [allThemeData], + ); + + const noBackgroundsThemes = useMemo( + () => + allThemeData?.filter((a: any) => + a.backgroundImage.toLowerCase().includes('none'), + ) ?? [], + [allThemeData], + ); + + const timeOfDayPlaylist = useMemo(() => { + const found = themePlaylists?.find((a: ThemePlaylist) => a.name === 'Time of Day'); + return { + id: found?.id, + name: 'Time of Day', + default: 1, + themeList: found?.themeList ?? '[]', + }; + }, [themePlaylists]); + + const allStack = useMemo( + () => ({ + id: undefined, + name: 'All', + default: 1, + themeList: `[${allThemesIds.join(',')}]`, + }), + [allThemesIds], + ); + + const backgroundsStack = useMemo( + () => ({ + id: undefined, + name: 'Backgrounds', + default: 1, + themeList: `[${backgroundsThemes.map((a: Theme) => a.id).join(',')}]`, + }), + [backgroundsThemes], + ); + + const noBackgroundsStack = useMemo( + () => ({ + id: undefined, + name: 'No Backgrounds', + default: 1, + themeList: `[${noBackgroundsThemes.map((a: Theme) => a.id).join(',')}]`, + }), + [noBackgroundsThemes], + ); return ( @@ -108,7 +176,7 @@ export function ThemePlaylists() { /> {allThemeData && ( <> - + Defaults - - - - {'All' === currentThemePlaylist && ( - - )} - - a.id) ?? ''}]`, - }} - handleOpen={handleOpen} - allThemes={allThemeData} - /> - - - - {'Backgrounds' === currentThemePlaylist && ( - - )} - - !a.backgroundImage.toLowerCase().includes('none')).map((a: Theme) => a.id) ?? ''}]`, - }} - handleOpen={handleOpen} - allThemes={allThemeData} - /> - - - - {'No Backgrounds' === currentThemePlaylist && ( - - )} - - a.backgroundImage.toLowerCase().includes('none')).map((a: Theme) => a.id) ?? ''}]`, - }} - handleOpen={handleOpen} - allThemes={allThemeData} - /> - - - - {'Time of Day' === currentThemePlaylist && ( - - )} - - a.name === 'Time of Day', - )?.id ?? undefined, - name: 'Time of Day', - default: 1, - themeList: - themePlaylists?.find( - (a: ThemePlaylist) => a.name === 'Time of Day', - )?.themeList ?? '[]', - }} - handleOpen={handleOpen} - allThemes={allThemeData} - /> - - - - - - User Made - - - - {themePlaylists.length > 1 ? ( - - {themePlaylists - .filter((playlist: ThemePlaylist) => playlist.default === 0) - .sort((a: ThemePlaylist, b: ThemePlaylist) => - a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase() ? 1 : -1, - ) - .map((cardPlaylist: ThemePlaylist) => { - return ( - - {cardPlaylist.name === currentThemePlaylist && ( - - )} - - - - - ); - })} - - ) : ( - - + + + {'All' === currentThemePlaylist && ( + + )} + + + - )} - + + {'Backgrounds' === currentThemePlaylist && ( + + )} + + + + + + {'No Backgrounds' === currentThemePlaylist && ( + + )} + + + + + + {'Time of Day' === currentThemePlaylist && ( + + )} + + + + + + + + + + User Made + + + + {themePlaylists.length > 1 ? ( + + {themePlaylists + .filter((playlist: ThemePlaylist) => playlist.default === 0) + .sort((a: ThemePlaylist, b: ThemePlaylist) => + a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase() ? 1 : -1, + ) + .map((cardPlaylist: ThemePlaylist) => { + return ( + + {cardPlaylist.name === currentThemePlaylist && ( + + )} + + + + + ); + })} + + ) : ( + + + + )} + + )}