import React, { useMemo, useCallback } from 'react'; import { useDroppable } from '@dnd-kit/core'; // @ts-ignore: Heroicons module types import { ChevronDownIcon, ChevronRightIcon } from '@heroicons/react/24/outline'; import { Checkbox } from 'antd'; import { getContrastColor } from '@/utils/colorUtils'; import { useAppSelector } from '@/hooks/useAppSelector'; import { useAppDispatch } from '@/hooks/useAppDispatch'; import { selectSelectedTaskIds, selectTask, deselectTask } from '@/features/task-management/selection.slice'; import { selectGroups } from '@/features/task-management/task-management.slice'; interface TaskGroupHeaderProps { group: { id: string; name: string; count: number; color?: string; // Color for the group indicator }; isCollapsed: boolean; onToggle: () => void; } const TaskGroupHeader: React.FC = ({ group, isCollapsed, onToggle }) => { const dispatch = useAppDispatch(); const selectedTaskIds = useAppSelector(selectSelectedTaskIds); const groups = useAppSelector(selectGroups); const headerBackgroundColor = group.color || '#F0F0F0'; // Default light gray if no color const headerTextColor = getContrastColor(headerBackgroundColor); // Get tasks in this group const currentGroup = useMemo(() => { return groups.find(g => g.id === group.id); }, [groups, group.id]); const tasksInGroup = useMemo(() => { return currentGroup?.taskIds || []; }, [currentGroup]); // Calculate selection state for this group const { isAllSelected, isPartiallySelected } = useMemo(() => { if (tasksInGroup.length === 0) { return { isAllSelected: false, isPartiallySelected: false }; } const selectedTasksInGroup = tasksInGroup.filter(taskId => selectedTaskIds.includes(taskId)); const allSelected = selectedTasksInGroup.length === tasksInGroup.length; const partiallySelected = selectedTasksInGroup.length > 0 && selectedTasksInGroup.length < tasksInGroup.length; return { isAllSelected: allSelected, isPartiallySelected: partiallySelected }; }, [tasksInGroup, selectedTaskIds]); // Handle select all checkbox change const handleSelectAllChange = useCallback((e: any) => { e.stopPropagation(); if (isAllSelected) { // Deselect all tasks in this group tasksInGroup.forEach(taskId => { dispatch(deselectTask(taskId)); }); } else { // Select all tasks in this group tasksInGroup.forEach(taskId => { dispatch(selectTask(taskId)); }); } }, [dispatch, isAllSelected, tasksInGroup]); // Make the group header droppable const { isOver, setNodeRef } = useDroppable({ id: group.id, data: { type: 'group', group, }, }); return (
{/* Drag Handle Space - ultra minimal width */}
{/* Chevron button */}
{/* Select All Checkbox Space - ultra minimal width */}
e.stopPropagation()} style={{ color: headerTextColor, }} />
{/* Group indicator and name - no gap at all */}
{/* Group name and count */}
{group.name} ({group.count})
); }; export default TaskGroupHeader;