feat(assignee-selector): enhance real-time updates and UI interactions
- Added socket event handling for quick assignee updates, dispatching changes to the enhanced Kanban state. - Updated AssigneeSelector component to prevent event propagation on dropdown interactions. - Integrated AvatarGroup and LazyAssigneeSelectorWrapper in EnhancedKanbanTaskCard for improved assignee display and selection.
This commit is contained in:
@@ -14,6 +14,7 @@ import { sortTeamMembers } from '@/utils/sort-team-members';
|
|||||||
import { useAppDispatch } from '@/hooks/useAppDispatch';
|
import { useAppDispatch } from '@/hooks/useAppDispatch';
|
||||||
import { toggleProjectMemberDrawer } from '@/features/projects/singleProject/members/projectMembersSlice';
|
import { toggleProjectMemberDrawer } from '@/features/projects/singleProject/members/projectMembersSlice';
|
||||||
import { updateTask } from '@/features/task-management/task-management.slice';
|
import { updateTask } from '@/features/task-management/task-management.slice';
|
||||||
|
import { updateEnhancedKanbanTaskAssignees } from '@/features/enhanced-kanban/enhanced-kanban.slice';
|
||||||
|
|
||||||
interface AssigneeSelectorProps {
|
interface AssigneeSelectorProps {
|
||||||
task: IProjectTask;
|
task: IProjectTask;
|
||||||
@@ -177,6 +178,12 @@ const AssigneeSelector: React.FC<AssigneeSelectorProps> = ({
|
|||||||
|
|
||||||
// Emit socket event - the socket handler will update Redux with proper types
|
// Emit socket event - the socket handler will update Redux with proper types
|
||||||
socket?.emit(SocketEvents.QUICK_ASSIGNEES_UPDATE.toString(), JSON.stringify(body));
|
socket?.emit(SocketEvents.QUICK_ASSIGNEES_UPDATE.toString(), JSON.stringify(body));
|
||||||
|
socket?.once(
|
||||||
|
SocketEvents.QUICK_ASSIGNEES_UPDATE.toString(),
|
||||||
|
(data: any) => {
|
||||||
|
dispatch(updateEnhancedKanbanTaskAssignees(data));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// Remove from pending changes after a short delay (optimistic)
|
// Remove from pending changes after a short delay (optimistic)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -226,6 +233,7 @@ const AssigneeSelector: React.FC<AssigneeSelectorProps> = ({
|
|||||||
{isOpen && createPortal(
|
{isOpen && createPortal(
|
||||||
<div
|
<div
|
||||||
ref={dropdownRef}
|
ref={dropdownRef}
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
className={`
|
className={`
|
||||||
fixed z-9999 w-72 rounded-md shadow-lg border
|
fixed z-9999 w-72 rounded-md shadow-lg border
|
||||||
${isDarkMode
|
${isDarkMode
|
||||||
@@ -284,12 +292,14 @@ const AssigneeSelector: React.FC<AssigneeSelectorProps> = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<Checkbox
|
<span onClick={e => e.stopPropagation()}>
|
||||||
checked={checkMemberSelected(member.id || '')}
|
<Checkbox
|
||||||
onChange={(checked) => handleMemberToggle(member.id || '', checked)}
|
checked={checkMemberSelected(member.id || '')}
|
||||||
disabled={member.pending_invitation || pendingChanges.has(member.id || '')}
|
onChange={(checked) => handleMemberToggle(member.id || '', checked)}
|
||||||
isDarkMode={isDarkMode}
|
disabled={member.pending_invitation || pendingChanges.has(member.id || '')}
|
||||||
/>
|
isDarkMode={isDarkMode}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
{pendingChanges.has(member.id || '') && (
|
{pendingChanges.has(member.id || '') && (
|
||||||
<div className={`absolute inset-0 flex items-center justify-center ${
|
<div className={`absolute inset-0 flex items-center justify-center ${
|
||||||
isDarkMode ? 'bg-gray-800/50' : 'bg-white/50'
|
isDarkMode ? 'bg-gray-800/50' : 'bg-white/50'
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import { useAppDispatch } from '@/hooks/useAppDispatch';
|
|||||||
import { setShowTaskDrawer, setSelectedTaskId } from '@/features/task-drawer/task-drawer.slice';
|
import { setShowTaskDrawer, setSelectedTaskId } from '@/features/task-drawer/task-drawer.slice';
|
||||||
import PrioritySection from '../board/taskCard/priority-section/priority-section';
|
import PrioritySection from '../board/taskCard/priority-section/priority-section';
|
||||||
import Typography from 'antd/es/typography';
|
import Typography from 'antd/es/typography';
|
||||||
import CustomAvatarGroup from '../board/custom-avatar-group';
|
|
||||||
import CustomDueDatePicker from '../board/custom-due-date-picker';
|
import CustomDueDatePicker from '../board/custom-due-date-picker';
|
||||||
import { themeWiseColor } from '@/utils/themeWiseColor';
|
import { themeWiseColor } from '@/utils/themeWiseColor';
|
||||||
import { ForkOutlined } from '@ant-design/icons';
|
import { ForkOutlined } from '@ant-design/icons';
|
||||||
@@ -29,6 +28,8 @@ import BoardSubTaskCard from '@/pages/projects/projectView/board/board-section/b
|
|||||||
import BoardCreateSubtaskCard from '@/pages/projects/projectView/board/board-section/board-sub-task-card/board-create-sub-task-card';
|
import BoardCreateSubtaskCard from '@/pages/projects/projectView/board/board-section/board-sub-task-card/board-create-sub-task-card';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import EnhancedKanbanCreateSubtaskCard from './EnhancedKanbanCreateSubtaskCard';
|
import EnhancedKanbanCreateSubtaskCard from './EnhancedKanbanCreateSubtaskCard';
|
||||||
|
import LazyAssigneeSelectorWrapper from '@/components/task-management/lazy-assignee-selector';
|
||||||
|
import AvatarGroup from '@/components/AvatarGroup';
|
||||||
|
|
||||||
interface EnhancedKanbanTaskCardProps {
|
interface EnhancedKanbanTaskCardProps {
|
||||||
task: IProjectTask;
|
task: IProjectTask;
|
||||||
@@ -179,8 +180,15 @@ const EnhancedKanbanTaskCard: React.FC<EnhancedKanbanTaskCardProps> = React.memo
|
|||||||
marginBlock: 8,
|
marginBlock: 8,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{task && <CustomAvatarGroup task={task} sectionId={sectionId} />}
|
<Flex align="center" gap={2}>
|
||||||
|
<AvatarGroup
|
||||||
|
members={task.names || []}
|
||||||
|
maxCount={3}
|
||||||
|
isDarkMode={themeMode === 'dark'}
|
||||||
|
size={24}
|
||||||
|
/>
|
||||||
|
<LazyAssigneeSelectorWrapper task={task} groupId={sectionId} isDarkMode={themeMode === 'dark'} />
|
||||||
|
</Flex>
|
||||||
<Flex gap={4} align="center">
|
<Flex gap={4} align="center">
|
||||||
<CustomDueDatePicker task={task} onDateChange={setDueDate} />
|
<CustomDueDatePicker task={task} onDateChange={setDueDate} />
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user