feat(duplicates): add filter to show only groups where at least one song is in a playlist

This commit is contained in:
Geert Rademakes 2025-08-08 09:09:31 +02:00
parent f7f44f2c48
commit f6ecd07d98

View File

@ -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>