Adjust album list header/filters
This commit is contained in:
parent
5ed06f79b3
commit
926d7f714e
3 changed files with 173 additions and 125 deletions
|
@ -136,7 +136,7 @@ export const AlbumListHeader = ({ gridRef }: AlbumListHeaderProps) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleFilterChange = useCallback(
|
const handleFilterChange = useCallback(
|
||||||
async (filters: any) => {
|
async (filters: AlbumListFilter) => {
|
||||||
gridRef.current?.scrollTo(0);
|
gridRef.current?.scrollTo(0);
|
||||||
gridRef.current?.resetLoadMoreItemsCache();
|
gridRef.current?.resetLoadMoreItemsCache();
|
||||||
|
|
||||||
|
@ -185,14 +185,11 @@ export const AlbumListHeader = ({ gridRef }: AlbumListHeaderProps) => {
|
||||||
[handleFilterChange, page.filter.musicFolderId, setFilter],
|
[handleFilterChange, page.filter.musicFolderId, setFilter],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSetOrder = useCallback(
|
const handleToggleSortOrder = useCallback(() => {
|
||||||
(e: MouseEvent<HTMLButtonElement>) => {
|
const newSortOrder = filters.sortOrder === SortOrder.ASC ? SortOrder.DESC : SortOrder.ASC;
|
||||||
if (!e.currentTarget?.value) return;
|
const updatedFilters = setFilter({ sortOrder: newSortOrder });
|
||||||
const updatedFilters = setFilter({ sortOrder: e.currentTarget.value as SortOrder });
|
|
||||||
handleFilterChange(updatedFilters);
|
handleFilterChange(updatedFilters);
|
||||||
},
|
}, [filters.sortOrder, handleFilterChange, setFilter]);
|
||||||
[handleFilterChange, setFilter],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleSetViewType = useCallback(
|
const handleSetViewType = useCallback(
|
||||||
(e: MouseEvent<HTMLButtonElement>) => {
|
(e: MouseEvent<HTMLButtonElement>) => {
|
||||||
|
@ -210,7 +207,9 @@ export const AlbumListHeader = ({ gridRef }: AlbumListHeaderProps) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSearch = debounce((e: ChangeEvent<HTMLInputElement>) => {
|
const handleSearch = debounce((e: ChangeEvent<HTMLInputElement>) => {
|
||||||
const updatedFilters = setFilter({ searchTerm: e.target.value });
|
const updatedFilters = setFilter({
|
||||||
|
searchTerm: e.target.value === '' ? undefined : e.target.value,
|
||||||
|
});
|
||||||
handleFilterChange(updatedFilters);
|
handleFilterChange(updatedFilters);
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
|
@ -222,7 +221,7 @@ export const AlbumListHeader = ({ gridRef }: AlbumListHeaderProps) => {
|
||||||
gap="md"
|
gap="md"
|
||||||
justify="center"
|
justify="center"
|
||||||
>
|
>
|
||||||
<DropdownMenu position="bottom">
|
<DropdownMenu position="bottom-start">
|
||||||
<DropdownMenu.Target>
|
<DropdownMenu.Target>
|
||||||
<Button
|
<Button
|
||||||
compact
|
compact
|
||||||
|
@ -240,6 +239,7 @@ export const AlbumListHeader = ({ gridRef }: AlbumListHeaderProps) => {
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenu.Target>
|
</DropdownMenu.Target>
|
||||||
<DropdownMenu.Dropdown>
|
<DropdownMenu.Dropdown>
|
||||||
|
<DropdownMenu.Label>Item size</DropdownMenu.Label>
|
||||||
<DropdownMenu.Item>
|
<DropdownMenu.Item>
|
||||||
<Slider
|
<Slider
|
||||||
defaultValue={page.grid.size || 0}
|
defaultValue={page.grid.size || 0}
|
||||||
|
@ -248,16 +248,17 @@ export const AlbumListHeader = ({ gridRef }: AlbumListHeaderProps) => {
|
||||||
/>
|
/>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
<DropdownMenu.Divider />
|
<DropdownMenu.Divider />
|
||||||
|
<DropdownMenu.Label>Display type</DropdownMenu.Label>
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
$isActive={page.display === CardDisplayType.CARD}
|
$isActive={page.display === ListDisplayType.CARD}
|
||||||
value={CardDisplayType.CARD}
|
value={ListDisplayType.CARD}
|
||||||
onClick={handleSetViewType}
|
onClick={handleSetViewType}
|
||||||
>
|
>
|
||||||
Card
|
Card
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
$isActive={page.display === CardDisplayType.POSTER}
|
$isActive={page.display === ListDisplayType.POSTER}
|
||||||
value={CardDisplayType.POSTER}
|
value={ListDisplayType.POSTER}
|
||||||
onClick={handleSetViewType}
|
onClick={handleSetViewType}
|
||||||
>
|
>
|
||||||
Poster
|
Poster
|
||||||
|
@ -272,7 +273,7 @@ export const AlbumListHeader = ({ gridRef }: AlbumListHeaderProps) => {
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
</DropdownMenu.Dropdown>
|
</DropdownMenu.Dropdown>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
<DropdownMenu position="bottom">
|
<DropdownMenu position="bottom-start">
|
||||||
<DropdownMenu.Target>
|
<DropdownMenu.Target>
|
||||||
<Button
|
<Button
|
||||||
compact
|
compact
|
||||||
|
@ -295,12 +296,12 @@ export const AlbumListHeader = ({ gridRef }: AlbumListHeaderProps) => {
|
||||||
))}
|
))}
|
||||||
</DropdownMenu.Dropdown>
|
</DropdownMenu.Dropdown>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
<DropdownMenu position="bottom">
|
|
||||||
<DropdownMenu.Target>
|
|
||||||
<Button
|
<Button
|
||||||
compact
|
compact
|
||||||
fw="normal"
|
fw="normal"
|
||||||
|
tooltip={!cq.isMd ? { label: sortOrderLabel } : undefined}
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
|
onClick={handleToggleSortOrder}
|
||||||
>
|
>
|
||||||
{cq.isMd ? (
|
{cq.isMd ? (
|
||||||
sortOrderLabel
|
sortOrderLabel
|
||||||
|
@ -314,26 +315,13 @@ export const AlbumListHeader = ({ gridRef }: AlbumListHeaderProps) => {
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenu.Target>
|
|
||||||
<DropdownMenu.Dropdown>
|
|
||||||
{ORDER.map((sort) => (
|
|
||||||
<DropdownMenu.Item
|
|
||||||
key={`sort-${sort.value}`}
|
|
||||||
$isActive={sort.value === filters.sortOrder}
|
|
||||||
value={sort.value}
|
|
||||||
onClick={handleSetOrder}
|
|
||||||
>
|
|
||||||
{sort.name}
|
|
||||||
</DropdownMenu.Item>
|
|
||||||
))}
|
|
||||||
</DropdownMenu.Dropdown>
|
|
||||||
</DropdownMenu>
|
|
||||||
{server?.type === ServerType.JELLYFIN && (
|
{server?.type === ServerType.JELLYFIN && (
|
||||||
<DropdownMenu position="bottom">
|
<DropdownMenu position="bottom-start">
|
||||||
<DropdownMenu.Target>
|
<DropdownMenu.Target>
|
||||||
<Button
|
<Button
|
||||||
compact
|
compact
|
||||||
fw="normal"
|
fw="normal"
|
||||||
|
tooltip={!cq.isMd ? { label: 'Folder' } : undefined}
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
>
|
>
|
||||||
{cq.isMd ? 'Folder' : <RiFolder2Line size={15} />}
|
{cq.isMd ? 'Folder' : <RiFolder2Line size={15} />}
|
||||||
|
@ -353,11 +341,15 @@ export const AlbumListHeader = ({ gridRef }: AlbumListHeaderProps) => {
|
||||||
</DropdownMenu.Dropdown>
|
</DropdownMenu.Dropdown>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
)}
|
)}
|
||||||
<Popover>
|
<Popover
|
||||||
|
closeOnClickOutside={false}
|
||||||
|
position="bottom-start"
|
||||||
|
>
|
||||||
<Popover.Target>
|
<Popover.Target>
|
||||||
<Button
|
<Button
|
||||||
compact
|
compact
|
||||||
fw="normal"
|
fw="normal"
|
||||||
|
tooltip={!cq.isMd ? { label: 'Filters' } : undefined}
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
>
|
>
|
||||||
{cq.isMd ? 'Filters' : <RiFilter3Line size={15} />}
|
{cq.isMd ? 'Filters' : <RiFilter3Line size={15} />}
|
||||||
|
@ -365,23 +357,17 @@ export const AlbumListHeader = ({ gridRef }: AlbumListHeaderProps) => {
|
||||||
</Popover.Target>
|
</Popover.Target>
|
||||||
<Popover.Dropdown>
|
<Popover.Dropdown>
|
||||||
{server?.type === ServerType.NAVIDROME ? (
|
{server?.type === ServerType.NAVIDROME ? (
|
||||||
<NavidromeAlbumFilters />
|
<NavidromeAlbumFilters handleFilterChange={handleFilterChange} />
|
||||||
) : (
|
) : (
|
||||||
<JellyfinAlbumFilters />
|
<JellyfinAlbumFilters handleFilterChange={handleFilterChange} />
|
||||||
)}
|
)}
|
||||||
</Popover.Dropdown>
|
</Popover.Dropdown>
|
||||||
</Popover>
|
</Popover>
|
||||||
</Flex>
|
<DropdownMenu position="bottom-start">
|
||||||
<Flex gap="md">
|
|
||||||
<SearchInput
|
|
||||||
defaultValue={page.filter.searchTerm}
|
|
||||||
openedWidth={cq.isLg ? 300 : cq.isMd ? 250 : cq.isSm ? 150 : 75}
|
|
||||||
onChange={handleSearch}
|
|
||||||
/>
|
|
||||||
<DropdownMenu>
|
|
||||||
<DropdownMenu.Target>
|
<DropdownMenu.Target>
|
||||||
<Button
|
<Button
|
||||||
px="sm"
|
compact
|
||||||
|
tooltip={{ label: 'More' }}
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
>
|
>
|
||||||
<RiMoreFill size={15} />
|
<RiMoreFill size={15} />
|
||||||
|
@ -395,6 +381,13 @@ export const AlbumListHeader = ({ gridRef }: AlbumListHeaderProps) => {
|
||||||
</DropdownMenu.Dropdown>
|
</DropdownMenu.Dropdown>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
<Flex gap="md">
|
||||||
|
<SearchInput
|
||||||
|
defaultValue={page.filter.searchTerm}
|
||||||
|
openedWidth={cq.isLg ? 300 : cq.isMd ? 250 : cq.isSm ? 150 : 75}
|
||||||
|
onChange={handleSearch}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
</HeaderItems>
|
</HeaderItems>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
import { ChangeEvent, useMemo } from 'react';
|
import { ChangeEvent, useMemo } from 'react';
|
||||||
import { Divider, Group, Stack } from '@mantine/core';
|
import { Divider, Group, Stack } from '@mantine/core';
|
||||||
import { MultiSelect, NumberInput, Switch, Text } from '/@/renderer/components';
|
import { MultiSelect, NumberInput, Switch, Text } from '/@/renderer/components';
|
||||||
import { useAlbumListStore, useSetAlbumFilters } from '/@/renderer/store';
|
import { AlbumListFilter, useAlbumListStore, useSetAlbumFilters } from '/@/renderer/store';
|
||||||
import debounce from 'lodash/debounce';
|
import debounce from 'lodash/debounce';
|
||||||
import { useGenreList } from '/@/renderer/features/genres';
|
import { useGenreList } from '/@/renderer/features/genres';
|
||||||
|
|
||||||
export const JellyfinAlbumFilters = () => {
|
interface JellyfinAlbumFiltersProps {
|
||||||
|
handleFilterChange: (filters: AlbumListFilter) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const JellyfinAlbumFilters = ({ handleFilterChange }: JellyfinAlbumFiltersProps) => {
|
||||||
const { filter } = useAlbumListStore();
|
const { filter } = useAlbumListStore();
|
||||||
const setFilters = useSetAlbumFilters();
|
const setFilters = useSetAlbumFilters();
|
||||||
|
|
||||||
|
@ -28,9 +32,10 @@ export const JellyfinAlbumFilters = () => {
|
||||||
{
|
{
|
||||||
label: 'Is favorited',
|
label: 'Is favorited',
|
||||||
onChange: (e: ChangeEvent<HTMLInputElement>) => {
|
onChange: (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
setFilters({
|
const updatedFilters = setFilters({
|
||||||
jfParams: { ...filter.jfParams, isFavorite: e.currentTarget.checked ? true : undefined },
|
jfParams: { ...filter.jfParams, isFavorite: e.currentTarget.checked ? true : undefined },
|
||||||
});
|
});
|
||||||
|
handleFilterChange(updatedFilters);
|
||||||
},
|
},
|
||||||
value: filter.jfParams?.isFavorite,
|
value: filter.jfParams?.isFavorite,
|
||||||
},
|
},
|
||||||
|
@ -38,36 +43,77 @@ export const JellyfinAlbumFilters = () => {
|
||||||
|
|
||||||
const handleMinYearFilter = debounce((e: number | undefined) => {
|
const handleMinYearFilter = debounce((e: number | undefined) => {
|
||||||
if (e && (e < 1700 || e > 2300)) return;
|
if (e && (e < 1700 || e > 2300)) return;
|
||||||
setFilters({
|
const updatedFilters = setFilters({
|
||||||
jfParams: {
|
jfParams: {
|
||||||
...filter.jfParams,
|
...filter.jfParams,
|
||||||
minYear: e,
|
minYear: e,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
handleFilterChange(updatedFilters);
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
const handleMaxYearFilter = debounce((e: number | undefined) => {
|
const handleMaxYearFilter = debounce((e: number | undefined) => {
|
||||||
if (e && (e < 1700 || e > 2300)) return;
|
if (e && (e < 1700 || e > 2300)) return;
|
||||||
setFilters({
|
const updatedFilters = setFilters({
|
||||||
jfParams: {
|
jfParams: {
|
||||||
...filter.jfParams,
|
...filter.jfParams,
|
||||||
maxYear: e,
|
maxYear: e,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
handleFilterChange(updatedFilters);
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
const handleGenresFilter = debounce((e: string[] | undefined) => {
|
const handleGenresFilter = debounce((e: string[] | undefined) => {
|
||||||
const genreFilterString = e?.join(',');
|
const genreFilterString = e?.join(',');
|
||||||
setFilters({
|
const updatedFilters = setFilters({
|
||||||
jfParams: {
|
jfParams: {
|
||||||
...filter.jfParams,
|
...filter.jfParams,
|
||||||
genreIds: genreFilterString,
|
genreIds: genreFilterString,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
handleFilterChange(updatedFilters);
|
||||||
}, 250);
|
}, 250);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack p="0.8rem">
|
<Stack p="0.8rem">
|
||||||
|
<Group position="apart">
|
||||||
|
<Text>Year range</Text>
|
||||||
|
<Group>
|
||||||
|
<NumberInput
|
||||||
|
required
|
||||||
|
hideControls={false}
|
||||||
|
max={2300}
|
||||||
|
min={1700}
|
||||||
|
value={filter.jfParams?.minYear}
|
||||||
|
width={80}
|
||||||
|
onChange={handleMinYearFilter}
|
||||||
|
/>
|
||||||
|
<NumberInput
|
||||||
|
hideControls={false}
|
||||||
|
max={2300}
|
||||||
|
min={1700}
|
||||||
|
value={filter.jfParams?.maxYear}
|
||||||
|
width={80}
|
||||||
|
onChange={handleMaxYearFilter}
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
<Divider my="0.5rem" />
|
||||||
|
<Group
|
||||||
|
position="apart"
|
||||||
|
spacing={20}
|
||||||
|
>
|
||||||
|
<Text>Genres</Text>
|
||||||
|
<MultiSelect
|
||||||
|
clearable
|
||||||
|
searchable
|
||||||
|
data={genreList}
|
||||||
|
defaultValue={selectedGenres}
|
||||||
|
width={250}
|
||||||
|
onChange={handleGenresFilter}
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
<Divider my="0.5rem" />
|
||||||
{toggleFilters.map((filter) => (
|
{toggleFilters.map((filter) => (
|
||||||
<Group
|
<Group
|
||||||
key={`nd-filter-${filter.label}`}
|
key={`nd-filter-${filter.label}`}
|
||||||
|
@ -81,49 +127,14 @@ export const JellyfinAlbumFilters = () => {
|
||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
))}
|
))}
|
||||||
<Divider my="0.5rem" />
|
{/* <Divider my="0.5rem" />
|
||||||
<Group position="apart">
|
|
||||||
<Text>Year range</Text>
|
|
||||||
<Group>
|
|
||||||
<NumberInput
|
|
||||||
required
|
|
||||||
max={2300}
|
|
||||||
min={1700}
|
|
||||||
size="sm"
|
|
||||||
value={filter.jfParams?.minYear}
|
|
||||||
width={60}
|
|
||||||
onChange={handleMinYearFilter}
|
|
||||||
/>
|
|
||||||
<NumberInput
|
|
||||||
max={2300}
|
|
||||||
min={1700}
|
|
||||||
size="sm"
|
|
||||||
value={filter.jfParams?.maxYear}
|
|
||||||
width={60}
|
|
||||||
onChange={handleMaxYearFilter}
|
|
||||||
/>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
<Divider my="0.5rem" />
|
|
||||||
<Stack>
|
|
||||||
<Text>Genres</Text>
|
|
||||||
<MultiSelect
|
|
||||||
clearable
|
|
||||||
searchable
|
|
||||||
data={genreList}
|
|
||||||
defaultValue={selectedGenres}
|
|
||||||
width={250}
|
|
||||||
onChange={handleGenresFilter}
|
|
||||||
/>
|
|
||||||
</Stack>
|
|
||||||
<Divider my="0.5rem" />
|
|
||||||
<Stack>
|
<Stack>
|
||||||
<Text>Tags</Text>
|
<Text>Tags</Text>
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
disabled
|
disabled
|
||||||
data={[]}
|
data={[]}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack> */}
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,66 +1,123 @@
|
||||||
import { ChangeEvent } from 'react';
|
import { ChangeEvent, useMemo } from 'react';
|
||||||
import { Divider, Group, Stack } from '@mantine/core';
|
import { Divider, Group, Stack } from '@mantine/core';
|
||||||
import { NumberInput, Switch, Text } from '/@/renderer/components';
|
import { NumberInput, Switch, Text, Select } from '/@/renderer/components';
|
||||||
import { useAlbumListStore, useSetAlbumFilters } from '/@/renderer/store';
|
import { AlbumListFilter, useAlbumListStore, useSetAlbumFilters } from '/@/renderer/store';
|
||||||
import debounce from 'lodash/debounce';
|
import debounce from 'lodash/debounce';
|
||||||
|
import { useGenreList } from '/@/renderer/features/genres';
|
||||||
|
|
||||||
export const NavidromeAlbumFilters = () => {
|
interface NavidromeAlbumFiltersProps {
|
||||||
|
handleFilterChange: (filters: AlbumListFilter) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const NavidromeAlbumFilters = ({ handleFilterChange }: NavidromeAlbumFiltersProps) => {
|
||||||
const { filter } = useAlbumListStore();
|
const { filter } = useAlbumListStore();
|
||||||
const setFilters = useSetAlbumFilters();
|
const setFilters = useSetAlbumFilters();
|
||||||
|
|
||||||
|
const genreListQuery = useGenreList(null);
|
||||||
|
|
||||||
|
const genreList = useMemo(() => {
|
||||||
|
if (!genreListQuery?.data) return [];
|
||||||
|
return genreListQuery.data.map((genre) => ({
|
||||||
|
label: genre.name,
|
||||||
|
value: genre.id,
|
||||||
|
}));
|
||||||
|
}, [genreListQuery.data]);
|
||||||
|
|
||||||
|
const handleGenresFilter = debounce((e: string | null) => {
|
||||||
|
const updatedFilters = setFilters({
|
||||||
|
ndParams: {
|
||||||
|
...filter.ndParams,
|
||||||
|
genre_id: e || undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
handleFilterChange(updatedFilters);
|
||||||
|
}, 250);
|
||||||
|
|
||||||
const toggleFilters = [
|
const toggleFilters = [
|
||||||
{
|
{
|
||||||
label: 'Is rated',
|
label: 'Is rated',
|
||||||
onChange: (e: ChangeEvent<HTMLInputElement>) => {
|
onChange: (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
setFilters({
|
const updatedFilters = setFilters({
|
||||||
ndParams: { ...filter.ndParams, has_rating: e.currentTarget.checked ? true : undefined },
|
ndParams: { ...filter.ndParams, has_rating: e.currentTarget.checked ? true : undefined },
|
||||||
});
|
});
|
||||||
|
handleFilterChange(updatedFilters);
|
||||||
},
|
},
|
||||||
value: filter.ndParams?.has_rating,
|
value: filter.ndParams?.has_rating,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Is favorited',
|
label: 'Is favorited',
|
||||||
onChange: (e: ChangeEvent<HTMLInputElement>) => {
|
onChange: (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
setFilters({
|
const updatedFilters = setFilters({
|
||||||
ndParams: { ...filter.ndParams, starred: e.currentTarget.checked ? true : undefined },
|
ndParams: { ...filter.ndParams, starred: e.currentTarget.checked ? true : undefined },
|
||||||
});
|
});
|
||||||
|
handleFilterChange(updatedFilters);
|
||||||
},
|
},
|
||||||
value: filter.ndParams?.starred,
|
value: filter.ndParams?.starred,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Is compilation',
|
label: 'Is compilation',
|
||||||
onChange: (e: ChangeEvent<HTMLInputElement>) => {
|
onChange: (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
setFilters({
|
const updatedFilters = setFilters({
|
||||||
ndParams: { ...filter.ndParams, compilation: e.currentTarget.checked ? true : undefined },
|
ndParams: { ...filter.ndParams, compilation: e.currentTarget.checked ? true : undefined },
|
||||||
});
|
});
|
||||||
|
handleFilterChange(updatedFilters);
|
||||||
},
|
},
|
||||||
value: filter.ndParams?.compilation,
|
value: filter.ndParams?.compilation,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Is recently played',
|
label: 'Is recently played',
|
||||||
onChange: (e: ChangeEvent<HTMLInputElement>) => {
|
onChange: (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
setFilters({
|
const updatedFilters = setFilters({
|
||||||
ndParams: {
|
ndParams: {
|
||||||
...filter.ndParams,
|
...filter.ndParams,
|
||||||
recently_played: e.currentTarget.checked ? true : undefined,
|
recently_played: e.currentTarget.checked ? true : undefined,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
handleFilterChange(updatedFilters);
|
||||||
},
|
},
|
||||||
value: filter.ndParams?.recently_played,
|
value: filter.ndParams?.recently_played,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const handleYearFilter = debounce((e: number | undefined) => {
|
const handleYearFilter = debounce((e: number | undefined) => {
|
||||||
setFilters({
|
const updatedFilters = setFilters({
|
||||||
ndParams: {
|
ndParams: {
|
||||||
...filter.ndParams,
|
...filter.ndParams,
|
||||||
year: e,
|
year: e,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
handleFilterChange(updatedFilters);
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack p="0.8rem">
|
<Stack p="0.8rem">
|
||||||
|
<Group position="apart">
|
||||||
|
<Text>Year</Text>
|
||||||
|
<NumberInput
|
||||||
|
hideControls={false}
|
||||||
|
max={5000}
|
||||||
|
min={0}
|
||||||
|
value={filter.ndParams?.year}
|
||||||
|
width={80}
|
||||||
|
onChange={handleYearFilter}
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
<Divider my="0.5rem" />
|
||||||
|
<Group
|
||||||
|
position="apart"
|
||||||
|
spacing={20}
|
||||||
|
>
|
||||||
|
<Text>Genre</Text>
|
||||||
|
<Select
|
||||||
|
clearable
|
||||||
|
searchable
|
||||||
|
data={genreList}
|
||||||
|
defaultValue={filter.ndParams?.genre_id}
|
||||||
|
width={150}
|
||||||
|
onChange={handleGenresFilter}
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
<Divider my="0.5rem" />
|
||||||
{toggleFilters.map((filter) => (
|
{toggleFilters.map((filter) => (
|
||||||
<Group
|
<Group
|
||||||
key={`nd-filter-${filter.label}`}
|
key={`nd-filter-${filter.label}`}
|
||||||
|
@ -69,23 +126,10 @@ export const NavidromeAlbumFilters = () => {
|
||||||
<Text>{filter.label}</Text>
|
<Text>{filter.label}</Text>
|
||||||
<Switch
|
<Switch
|
||||||
checked={filter?.value || false}
|
checked={filter?.value || false}
|
||||||
size="xs"
|
|
||||||
onChange={filter.onChange}
|
onChange={filter.onChange}
|
||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
))}
|
))}
|
||||||
<Divider my="0.5rem" />
|
|
||||||
<Group position="apart">
|
|
||||||
<Text>Year</Text>
|
|
||||||
<NumberInput
|
|
||||||
max={5000}
|
|
||||||
min={0}
|
|
||||||
size="xs"
|
|
||||||
value={filter.ndParams?.year}
|
|
||||||
width={50}
|
|
||||||
onChange={handleYearFilter}
|
|
||||||
/>
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
Reference in a new issue