import { Box, Button, Divider, Group, LoadingOverlay, Overlay, Stack, Switch, Text, Tooltip, } from '@mantine/core'; import { useDebouncedValue, useDisclosure } from '@mantine/hooks'; import { NoItemsFound, SettingsHeader } from 'components'; import { useCommonHooks, useQueryAPI } from 'hooks'; import { useEffect, useState } from 'react'; import { FaDice } from 'react-icons/fa'; import { FiChevronRight, FiEdit, FiMousePointer, FiStopCircle } from 'react-icons/fi'; import { useNavigate } from 'react-router-dom'; import { switchClasses, textClasses, toolTipClasses } from 'styles'; import type { Theme, ThemePlaylist } from 'types'; import { BackgroundModal } from '../Backgrounds'; import { ThemeCard } from './ThemeCard'; import { ThemeModal } from './ThemeModal'; export function Themes() { const backgroundsEndpoint = 'api/backgrounds'; const { data: allThemeData, isFetching: allThemeDataIsFetching } = useQueryAPI({ endpoint: 'api/themes', }); const [sortBy, setSortBy] = useState('Oldest'); const [searchValue, setSearchValue] = useState(''); const [debouncedSearch] = useDebouncedValue(searchValue, 500); const allThemes: Theme[] = allThemeData ?.filter((a: Theme) => a.name.toLowerCase().includes((debouncedSearch as string).toLowerCase()), ) .sort((a: Theme, b: Theme) => { switch (sortBy) { case 'A>Z': return a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase() ? 1 : -1; case 'Z>A': return a.name.toLocaleLowerCase() < b.name.toLocaleLowerCase() ? 1 : -1; case 'Newest': if (a.id && b.id) { return a.id < b.id ? 1 : -1; } return -1; case 'Oldest': if (a.id && b.id) { return a.id > b.id ? 1 : -1; } return -1; default: return 0; } }); const { data: backgroundData, isFetching: backgroundDataIsFetching } = useQueryAPI({ endpoint: backgroundsEndpoint, }); const { data: themePlaylistData } = useQueryAPI({ endpoint: 'api/themePlaylists', }); const themePlaylists: ThemePlaylist[] = themePlaylistData || []; const [themeModalOpened, { open: openThemeModal, close: closeThemeModal }] = useDisclosure(false); const [ backgroundModalOpened, { open: openBackgroundModal, close: closeBackgroundModal }, ] = useDisclosure(false); const backgroundList = backgroundData ? ['None', ...backgroundData.sort((a: string, b: string) => a.localeCompare(b))] : ['None']; const inUseBackgrounds: string[] = [ ...new Set( allThemes ?.filter((t) => { if (t.backgroundImage !== 'none') { return t.backgroundImage; } return undefined; }) .map((t) => t.backgroundImage), ), ] as string[]; const { currentTheme, currentUser, setCurrentTheme, theme, isMobile, currentThemePlaylist, setCurrentThemePlaylist, } = useCommonHooks(); const [selectedTheme, setSelectedTheme] = useState({ id: undefined, name: 'default', backgroundImage: 'none', backgroundColor: '#EEEEEE', searchColor: '#00000033', primaryColor: '#222222', accentColor: '#5c5c5c', borderColor: '#5c5c5c', randomEnabled: 1, textShadowsEnabled: 0, appShadowsEnabled: 0, themeFont: currentUser.defaultFont, }); const [isLoading, setIsLoading] = useState(false); const [isNew, setIsNew] = useState(false); const navigate = useNavigate(); const handleNewTheme = () => { setIsNew(true); openThemeModal(); }; useEffect(() => { if (debouncedSearch === searchValue) { setIsLoading(false); } }, [debouncedSearch]); return ( {themeModalOpened && ( )} {backgroundModalOpened && ( )} {allThemes?.length > 0 ? ( allThemes.map((cardTheme: Theme) => ( {cardTheme.name === currentTheme && ( )} t.name.toLowerCase() === currentThemePlaylist.toLowerCase(), ) ?.themeList.includes(`${cardTheme.id}`) || cardTheme.name === theme.name) ? 195 : 0, }} > )) ) : ( )} Current Settings: Active Playlist: {currentThemePlaylist === 'All' ? 'All' : currentThemePlaylist} ) : ( Shuffle Enabled ) } labelPosition='left' checked={currentTheme === 'random'} onChange={(e) => { setCurrentTheme(e.target.checked ? 'random' : theme.name); setCurrentThemePlaylist('All'); }} className={switchClasses.default} classNames={switchClasses} style={{ zIndex: 250, }} /> ); }