fix(client): add selection mode toggle for bulk delete UX
- Add 'Select' toggle button in filter area - Checkboxes only visible when selection mode is active - Hide individual trash buttons during selection mode - Exit selection mode when: deselecting all, deleting, or changing filters - Resolves visual conflict between checkbox and card title - Removes redundancy between checkbox and trash button The checkbox now appears on-demand via toggle, providing cleaner default UI.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
// Meetings list page
|
||||
|
||||
import { Calendar, Loader2 } from 'lucide-react';
|
||||
import { Calendar, Loader2, CheckSquare } from 'lucide-react';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { getAPI } from '@/api/interface';
|
||||
@@ -52,6 +52,7 @@ export default function MeetingsPage() {
|
||||
const [loadingMore, setLoadingMore] = useState(false);
|
||||
|
||||
// Bulk selection state
|
||||
const [isSelectionMode, setIsSelectionMode] = useState(false);
|
||||
const [selectedMeetingIds, setSelectedMeetingIds] = useState<Set<string>>(new Set());
|
||||
const [showBulkDeleteDialog, setShowBulkDeleteDialog] = useState(false);
|
||||
const { mutate: deleteMeetings, isLoading: isDeleting } = useDeleteMeetings();
|
||||
@@ -117,6 +118,7 @@ export default function MeetingsPage() {
|
||||
// Clear selections when filters change
|
||||
useEffect(() => {
|
||||
setSelectedMeetingIds(new Set());
|
||||
setIsSelectionMode(false);
|
||||
}, [searchQuery, stateFilter, projectScope, resolvedProjectId]);
|
||||
|
||||
const filteredMeetings = useMemo(
|
||||
@@ -149,6 +151,14 @@ export default function MeetingsPage() {
|
||||
|
||||
const handleDeselectAll = useCallback(() => {
|
||||
setSelectedMeetingIds(new Set());
|
||||
setIsSelectionMode(false);
|
||||
}, []);
|
||||
|
||||
const toggleSelectionMode = useCallback(() => {
|
||||
setIsSelectionMode((prev) => {
|
||||
if (prev) setSelectedMeetingIds(new Set());
|
||||
return !prev;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleBulkDelete = useCallback(() => {
|
||||
@@ -160,6 +170,7 @@ export default function MeetingsPage() {
|
||||
onSuccess: () => {
|
||||
setSelectedMeetingIds(new Set());
|
||||
setShowBulkDeleteDialog(false);
|
||||
setIsSelectionMode(false);
|
||||
fetchMeetings(0, false);
|
||||
},
|
||||
});
|
||||
@@ -232,6 +243,14 @@ export default function MeetingsPage() {
|
||||
{state}
|
||||
</Button>
|
||||
))}
|
||||
<Button
|
||||
variant={isSelectionMode ? 'default' : 'outline'}
|
||||
size="sm"
|
||||
onClick={toggleSelectionMode}
|
||||
>
|
||||
<CheckSquare className="h-4 w-4 mr-1" />
|
||||
Select
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -261,8 +280,8 @@ export default function MeetingsPage() {
|
||||
meeting={meeting}
|
||||
index={i}
|
||||
onDelete={handleDelete}
|
||||
showDeleteButton
|
||||
isSelectable={meeting.state !== 'recording'}
|
||||
showDeleteButton={!isSelectionMode}
|
||||
isSelectable={isSelectionMode && meeting.state !== 'recording'}
|
||||
isSelected={selectedMeetingIds.has(meeting.id)}
|
||||
onSelect={handleSelect}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user