import React, { useEffect, useRef, useState } from 'react'; import { Button, Dropdown, Input, InputRef, MenuProps, Typography } from '@/shared/antd-imports'; import { DeleteOutlined, EditOutlined, LoadingOutlined, MoreOutlined, PlusOutlined, } from '@/shared/antd-imports'; import { useTranslation } from 'react-i18next'; import { useDroppable } from '@dnd-kit/core'; import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable'; import { setTaskCardDisabled, initializeGroup } from '@/features/board/create-card.slice'; import TaskCreateCard from '../taskCreateCard/TaskCreateCard'; import TaskCard from '../taskCard/TaskCard'; import { useAppSelector } from '@/hooks/useAppSelector'; import { useAppDispatch } from '@/hooks/useAppDispatch'; import { deleteStatus } from '@features/projects/status/StatusSlice'; import ChangeCategoryDropdown from '../changeCategoryDropdown/ChangeCategoryDropdown'; import { IProjectTask } from '@/types/project/projectTasksViewModel.types'; import './kanban-group.css'; interface KanbanGroupProps { title: string; tasks: IProjectTask[]; id: string; color: string; } interface GroupState { name: string; isEditable: boolean; isLoading: boolean; addTaskCount: number; } const KanbanGroup: React.FC = ({ title, tasks, id, color }) => { // Refs const inputRef = useRef(null); const createTaskInputRef = useRef(null); const taskCardRef = useRef(null); // State const [groupState, setGroupState] = useState({ name: title, isEditable: false, isLoading: false, addTaskCount: 0, }); // Hooks const dispatch = useAppDispatch(); const { t } = useTranslation('kanban-board'); // Selectors const themeMode = useAppSelector(state => state.themeReducer.mode); const isTopCardDisabled = useAppSelector( state => state.createCardReducer.taskCardDisabledStatus[id]?.top ); const isBottomCardDisabled = useAppSelector( state => state.createCardReducer.taskCardDisabledStatus[id]?.bottom ); // Add droppable functionality const { setNodeRef } = useDroppable({ id: id, }); // Effects useEffect(() => { dispatch(initializeGroup(id)); }, [dispatch, id]); useEffect(() => { if (groupState.isEditable && inputRef.current) { inputRef.current.focus(); inputRef.current.select(); } }, [groupState.isEditable]); useEffect(() => { createTaskInputRef.current?.focus(); taskCardRef.current?.scrollIntoView({ behavior: 'smooth', block: 'center', }); }, [tasks, groupState.addTaskCount]); // Handlers const handleAddTaskClick = () => { dispatch(setTaskCardDisabled({ group: id, position: 'bottom', disabled: false })); setGroupState(prev => ({ ...prev, addTaskCount: prev.addTaskCount + 1 })); }; const handleTopAddTaskClick = () => { dispatch(setTaskCardDisabled({ group: id, position: 'top', disabled: false })); setGroupState(prev => ({ ...prev, addTaskCount: prev.addTaskCount + 1 })); }; const handleChange = (e: React.ChangeEvent) => { setGroupState(prev => ({ ...prev, name: e.target.value })); }; const handleBlur = () => { setGroupState(prev => ({ ...prev, isEditable: false, isLoading: true })); setTimeout(() => { setGroupState(prev => ({ ...prev, isLoading: false })); }, 3000); }; const handleEditClick = () => { setGroupState(prev => ({ ...prev, isEditable: true })); }; // Menu items const items: MenuProps['items'] = [ { key: '1', label: (
{t('rename')}
), }, { key: '2', label: , }, { key: '3', label: (
dispatch(deleteStatus(id))} > {t('delete')}
), }, ]; // Styles const containerStyle = { paddingTop: '6px', }; const wrapperStyle = { display: 'flex', flexDirection: 'column' as const, flexGrow: 1, flexBasis: 0, maxWidth: '375px', width: '375px', marginRight: '8px', padding: '8px', borderRadius: '25px', maxHeight: 'calc(100vh - 250px)', backgroundColor: themeMode === 'dark' ? '#282828' : '#F8FAFC', }; const headerStyle = { touchAction: 'none' as const, userSelect: 'none' as const, cursor: 'grab', fontSize: '14px', paddingTop: '0', margin: '0.25rem', }; const titleBarStyle = { fontWeight: 600, marginBottom: '12px', alignItems: 'center', padding: '8px', display: 'flex', justifyContent: 'space-between', backgroundColor: color, borderRadius: '10px', }; return (
{groupState.isLoading ? ( ) : ( )} {groupState.isEditable ? ( ) : ( {groupState.name} )}
{!isTopCardDisabled && ( )} task.id)} strategy={verticalListSortingStrategy} >
{tasks.map(task => ( ))}
{!isBottomCardDisabled && ( )}
); }; export default KanbanGroup;