import React from 'react'; import { useSortable } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; import { Avatar, Tag, Progress, Typography, Button, Tooltip, Space } from 'antd'; import { HolderOutlined, MessageOutlined, PaperClipOutlined, ClockCircleOutlined, } from '@ant-design/icons'; import { IProjectTask } from '@/types/project/projectTasksViewModel.types'; import { IGroupBy } from '@/features/tasks/tasks.slice'; import { useTranslation } from 'react-i18next'; const { Text } = Typography; interface TaskRowProps { task: IProjectTask; projectId: string; groupId: string; currentGrouping: IGroupBy; isSelected: boolean; isDragOverlay?: boolean; index?: number; onSelect?: (taskId: string, selected: boolean) => void; onToggleSubtasks?: (taskId: string) => void; } const KanbanTaskCard: React.FC = ({ task, projectId, groupId, currentGrouping, isSelected, isDragOverlay = false, index, onSelect, onToggleSubtasks, }) => { const { t } = useTranslation('task-list-table'); const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id: task.id!, data: { type: 'task', taskId: task.id, groupId, }, disabled: isDragOverlay, }); const style = { transform: CSS.Transform.toString(transform), transition, opacity: isDragging ? 0.5 : 1, }; // Format due date const formatDueDate = (dateString?: string) => { if (!dateString) return null; const date = new Date(dateString); const now = new Date(); const diffTime = date.getTime() - now.getTime(); const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); if (diffDays < 0) { return { text: `${Math.abs(diffDays)}d overdue`, color: 'error' }; } else if (diffDays === 0) { return { text: 'Due today', color: 'warning' }; } else if (diffDays <= 3) { return { text: `Due in ${diffDays}d`, color: 'warning' }; } else { return { text: `Due ${date.toLocaleDateString()}`, color: 'default' }; } }; const dueDate = formatDueDate(task.end_date); return (
)}
{/* Task Key and Status */}
{task.task_key && ( {task.task_key} )} {task.status_name && ( {task.status_name} )} {task.priority_name && ( {task.priority_name} )}
{/* Progress and Due Date */}
{typeof task.complete_ratio === 'number' && ( )} {dueDate && ( {dueDate.text} )}
{/* Assignees and Labels */}
{task.assignees && task.assignees.length > 0 && ( {task.assignees.map(assignee => ( {assignee.name?.charAt(0)?.toUpperCase()} ))} )} {task.labels && task.labels.length > 0 && (
{task.labels.slice(0, 2).map(label => ( {label.name} ))} {task.labels.length > 2 && ( +{task.labels.length - 2} )}
)}
{/* Indicators */}
{task.time_spent_string && ( {task.time_spent_string} )} {task.comments_count && task.comments_count > 1 && ( {task.comments_count} )} {task.attachments_count && task.attachments_count > 1 && ( {task.attachments_count} )}
{/* Subtasks */} {task.show_sub_tasks && task.sub_tasks && task.sub_tasks.length > 0 && (
{task.sub_tasks.map(subtask => ( ))}
)}
); }; export default KanbanTaskCard;