feat(duplicates): add filter to show only groups where at least one song is in a playlist
This commit is contained in:
parent
f7f44f2c48
commit
f6ecd07d98
@ -1,5 +1,5 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import { Box, VStack, Heading, Text, HStack, Badge, Select, Spinner, Table, Thead, Tr, Th, Tbody, Td, IconButton, Tooltip } from '@chakra-ui/react';
|
import { Box, VStack, Heading, Text, HStack, Badge, Select, Spinner, Table, Thead, Tr, Th, Tbody, Td, IconButton, Tooltip, Switch } from '@chakra-ui/react';
|
||||||
import { FiCheck, FiTrash2 } from 'react-icons/fi';
|
import { FiCheck, FiTrash2 } from 'react-icons/fi';
|
||||||
import { api } from '../services/api';
|
import { api } from '../services/api';
|
||||||
|
|
||||||
@ -27,6 +27,7 @@ export const DuplicatesViewer: React.FC = () => {
|
|||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [minGroupSize, setMinGroupSize] = useState(2);
|
const [minGroupSize, setMinGroupSize] = useState(2);
|
||||||
const [processingGroupKey, setProcessingGroupKey] = useState<string | null>(null);
|
const [processingGroupKey, setProcessingGroupKey] = useState<string | null>(null);
|
||||||
|
const [onlyWithPlaylists, setOnlyWithPlaylists] = useState(false);
|
||||||
|
|
||||||
const loadDuplicates = async (minSize: number) => {
|
const loadDuplicates = async (minSize: number) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@ -45,6 +46,11 @@ export const DuplicatesViewer: React.FC = () => {
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [minGroupSize]);
|
}, [minGroupSize]);
|
||||||
|
|
||||||
|
const filteredGroups = useMemo(() => {
|
||||||
|
if (!onlyWithPlaylists) return groups;
|
||||||
|
return groups.filter(g => g.items.some(it => (it.playlists || []).length > 0));
|
||||||
|
}, [groups, onlyWithPlaylists]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VStack spacing={4} align="stretch">
|
<VStack spacing={4} align="stretch">
|
||||||
<HStack justify="space-between">
|
<HStack justify="space-between">
|
||||||
@ -64,16 +70,25 @@ export const DuplicatesViewer: React.FC = () => {
|
|||||||
<option value={3}>3+</option>
|
<option value={3}>3+</option>
|
||||||
<option value={4}>4+</option>
|
<option value={4}>4+</option>
|
||||||
</Select>
|
</Select>
|
||||||
|
<HStack pl={4} spacing={2}>
|
||||||
|
<Text color="gray.400" fontSize="sm">Only with playlists</Text>
|
||||||
|
<Switch
|
||||||
|
size="sm"
|
||||||
|
isChecked={onlyWithPlaylists}
|
||||||
|
onChange={(e) => setOnlyWithPlaylists(e.target.checked)}
|
||||||
|
colorScheme="blue"
|
||||||
|
/>
|
||||||
|
</HStack>
|
||||||
</HStack>
|
</HStack>
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<HStack><Spinner size="sm" /><Text color="gray.400">Scanning duplicates…</Text></HStack>
|
<HStack><Spinner size="sm" /><Text color="gray.400">Scanning duplicates…</Text></HStack>
|
||||||
) : groups.length === 0 ? (
|
) : filteredGroups.length === 0 ? (
|
||||||
<Text color="gray.500">No duplicate groups found.</Text>
|
<Text color="gray.500">No duplicate groups found.</Text>
|
||||||
) : (
|
) : (
|
||||||
<VStack spacing={4} align="stretch">
|
<VStack spacing={4} align="stretch">
|
||||||
{groups.map((group) => (
|
{filteredGroups.map((group) => (
|
||||||
<Box key={group.key} p={4} bg="gray.800" borderRadius="md" borderWidth="1px" borderColor="gray.700">
|
<Box key={group.key} p={4} bg="gray.800" borderRadius="md" borderWidth="1px" borderColor="gray.700">
|
||||||
<HStack justify="space-between" mb={2}>
|
<HStack justify="space-between" mb={2}>
|
||||||
<HStack>
|
<HStack>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user