diff --git a/src/pages/settings/components/Theming/ThemePlaylists/ThemePlaylists.tsx b/src/pages/settings/components/Theming/ThemePlaylists/ThemePlaylists.tsx index 223d3c4..8ccc0b4 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 { useEffect, useState, useMemo, useCallback } from 'react'; import { FiChevronRight } from 'react-icons/fi'; import { textClasses } from 'styles'; import type { Theme, ThemePlaylist } from 'types'; @@ -21,13 +21,15 @@ export function ThemePlaylists() { }); const [searchValue, setSearchValue] = useState(''); const [debouncedSearch] = useDebouncedValue(searchValue, 500); - const themePlaylists: ThemePlaylist[] = - themePlaylistData?.filter( + + const themePlaylists: ThemePlaylist[] = useMemo(() => { + return themePlaylistData?.filter( (a: ThemePlaylist) => - a.name.toLowerCase().includes((debouncedSearch as string).toLowerCase()) || - a.name.includes('Time of Day'), + a.name.toLowerCase().includes((debouncedSearch as string).toLowerCase()) || + a.name.includes('Time of Day'), ) || []; - const defaultPlaylist = { + }, [themePlaylistData, debouncedSearch]); + const defaultPlaylist: ThemePlaylist = { id: undefined, default: 0, name: 'New Playlist', @@ -40,30 +42,73 @@ export function ThemePlaylists() { const { currentThemePlaylist, theme, isMobile } = useCommonHooks(); const [isLoading, setIsLoading] = useState(false); - const handleOpen = (playlist: ThemePlaylist) => { + 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 ( @@ -135,117 +180,91 @@ export function ThemePlaylists() { )} 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 ?? '[]', - }} + cardPlaylist={allStack} handleOpen={handleOpen} allThemes={allThemeData} /> + + {'Backgrounds' === currentThemePlaylist && ( + + )} + + + + + + {'No Backgrounds' === currentThemePlaylist && ( + + )} + + + + + + {'Time of Day' === currentThemePlaylist && ( + + )} + + + + )} @@ -293,7 +312,7 @@ export function ThemePlaylists() { cardPlaylist={cardPlaylist} handleOpen={handleOpen} allThemes={allThemeData} - /> + /> );