diff --git a/worklenz-frontend/src/components/AssigneeSelector.tsx b/worklenz-frontend/src/components/AssigneeSelector.tsx index c2674c0e..28126441 100644 --- a/worklenz-frontend/src/components/AssigneeSelector.tsx +++ b/worklenz-frontend/src/components/AssigneeSelector.tsx @@ -27,7 +27,7 @@ const AssigneeSelector: React.FC = ({ task, groupId = null, isDarkMode = false, - kanbanMode = false, + kanbanMode = false }) => { const [isOpen, setIsOpen] = useState(false); const [searchQuery, setSearchQuery] = useState(''); @@ -182,9 +182,12 @@ const AssigneeSelector: React.FC = ({ // Emit socket event - the socket handler will update Redux with proper types socket?.emit(SocketEvents.QUICK_ASSIGNEES_UPDATE.toString(), JSON.stringify(body)); - socket?.once(SocketEvents.QUICK_ASSIGNEES_UPDATE.toString(), (data: any) => { - dispatch(updateEnhancedKanbanTaskAssignees(data)); - }); + socket?.once( + SocketEvents.QUICK_ASSIGNEES_UPDATE.toString(), + (data: any) => { + dispatch(updateEnhancedKanbanTaskAssignees(data)); + } + ); // Remove from pending changes after a short delay (optimistic) setTimeout(() => { @@ -232,50 +235,48 @@ const AssigneeSelector: React.FC = ({ - {isOpen && - createPortal( -
e.stopPropagation()} - className={` + {isOpen && createPortal( +
e.stopPropagation()} + className={` fixed z-[99999] w-72 rounded-md shadow-lg border ${isDarkMode ? 'bg-gray-800 border-gray-600' : 'bg-white border-gray-200' } `} - style={{ - top: dropdownPosition.top, - left: dropdownPosition.left, - }} - > - {/* Header */} -
- setSearchQuery(e.target.value)} - placeholder="Search members..." - className={` + style={{ + top: dropdownPosition.top, + left: dropdownPosition.left, + }} + > + {/* Header */} +
+ setSearchQuery(e.target.value)} + placeholder="Search members..." + className={` w-full px-2 py-1 text-xs rounded border - ${ - isDarkMode - ? 'bg-gray-700 border-gray-600 text-gray-100 placeholder-gray-400 focus:border-blue-500' - : 'bg-white border-gray-300 text-gray-900 placeholder-gray-500 focus:border-blue-500' + ${isDarkMode + ? 'bg-gray-700 border-gray-600 text-gray-100 placeholder-gray-400 focus:border-blue-500' + : 'bg-white border-gray-300 text-gray-900 placeholder-gray-500 focus:border-blue-500' } focus:outline-none focus:ring-1 focus:ring-blue-500 `} - /> -
+ /> +
- {/* Members List */} -
- {filteredMembers && filteredMembers.length > 0 ? ( - filteredMembers.map(member => ( -
+ {filteredMembers && filteredMembers.length > 0 ? ( + filteredMembers.map((member) => ( +
= ({ (Pending) )}
+
+
+ )) + ) : ( +
+
No members found
+
+ )} +
{/* Footer */} @@ -359,4 +369,4 @@ const AssigneeSelector: React.FC = ({ ); }; -export default AssigneeSelector; +export default AssigneeSelector; \ No newline at end of file diff --git a/worklenz-frontend/src/components/enhanced-kanban/EnhancedKanbanBoardNativeDnD/KanbanGroup.tsx b/worklenz-frontend/src/components/enhanced-kanban/EnhancedKanbanBoardNativeDnD/KanbanGroup.tsx index 6d094c65..6e92874b 100644 --- a/worklenz-frontend/src/components/enhanced-kanban/EnhancedKanbanBoardNativeDnD/KanbanGroup.tsx +++ b/worklenz-frontend/src/components/enhanced-kanban/EnhancedKanbanBoardNativeDnD/KanbanGroup.tsx @@ -220,43 +220,43 @@ const KanbanGroup: React.FC = memo( }; const handleDelete = () => { - if (groupBy === IGroupBy.STATUS) { - Modal.confirm({ - title: t('deleteStatusTitle'), - content: t('deleteStatusContent'), - okText: t('deleteTaskConfirm'), - okType: 'danger', - cancelText: t('deleteTaskCancel'), - centered: true, - onOk: async () => { - await handleDeleteSection(); - }, - }); - } else if (groupBy === IGroupBy.PHASE) { - Modal.confirm({ - title: t('deletePhaseTitle'), - content: t('deletePhaseContent'), - okText: t('deleteTaskConfirm'), - okType: 'danger', - cancelText: t('deleteTaskCancel'), - centered: true, - onOk: async () => { - await handleDeleteSection(); - }, - }); - } else { - Modal.confirm({ - title: t('deleteConfirmationTitle'), - okText: t('deleteTaskConfirm'), - okType: 'danger', - cancelText: t('deleteTaskCancel'), - centered: true, - onOk: async () => { - await handleDeleteSection(); - }, - }); - } - setShowDropdown(false); + if (groupBy === IGroupBy.STATUS) { + Modal.confirm({ + title: t('deleteStatusTitle'), + content: t('deleteStatusContent'), + okText: t('deleteTaskConfirm'), + okType: 'danger', + cancelText: t('deleteTaskCancel'), + centered: true, + onOk: async () => { + await handleDeleteSection(); + }, + }); + } else if (groupBy === IGroupBy.PHASE) { + Modal.confirm({ + title: t('deletePhaseTitle'), + content: t('deletePhaseContent'), + okText: t('deleteTaskConfirm'), + okType: 'danger', + cancelText: t('deleteTaskCancel'), + centered: true, + onOk: async () => { + await handleDeleteSection(); + }, + }); + } else { + Modal.confirm({ + title: t('deleteConfirmationTitle'), + okText: t('deleteTaskConfirm'), + okType: 'danger', + cancelText: t('deleteTaskCancel'), + centered: true, + onOk: async () => { + await handleDeleteSection(); + }, + }); + } + setShowDropdown(false); }; // Close dropdown when clicking outside @@ -326,180 +326,51 @@ const KanbanGroup: React.FC = memo( if ((isProjectManager || isOwnerOrAdmin) && group.name !== t('unmapped')) setIsEditable(true); }} - onDragOver={e => { e.preventDefault(); onTaskDragOver(e, group.id, null); }} - onDrop={e => { e.preventDefault(); onTaskDrop(e, group.id, null); }} - /> - - {/* Content layer - z-index 1 */} -
-
{ + e.stopPropagation(); + }} + > + {isLoading && ( +
+ )} + {isEditable ? ( + { + e.stopPropagation(); }} - draggable - onDragStart={e => onGroupDragStart(e, group.id)} - onDragOver={onGroupDragOver} - onDrop={e => onGroupDrop(e, group.id)} - onDragEnd={onDragEnd} - > -
setIsHover(true)} - onMouseLeave={() => setIsHover(false)} - > -
{ - e.stopPropagation(); - if ((isProjectManager || isOwnerOrAdmin) && group.name !== t('unmapped')) - setIsEditable(true); - }} - onMouseDown={e => { - e.stopPropagation(); - }} - > - {isLoading && ( -
- )} - {isEditable ? ( - { - e.stopPropagation(); - }} - onClick={e => { - e.stopPropagation(); - }} - /> - ) : ( -
{ - e.stopPropagation(); - e.preventDefault(); - }} - onMouseUp={e => { - e.stopPropagation(); - }} - onClick={e => { - e.stopPropagation(); - }} - > - {name} ({group.tasks.length}) -
- )} -
- -
- - - {(isOwnerOrAdmin || isProjectManager) && name !== t('unmapped') && ( -
- - - {showDropdown && ( -
-
- - - {groupBy === IGroupBy.STATUS && statusCategories && ( -
-
- {t('changeCategory')} -
- {statusCategories.map(status => ( - - ))} -
- )} - - {groupBy !== IGroupBy.PRIORITY && ( -
- -
- )} -
-
- )} -
- )} -
-
-
- - {/* Simple Delete Confirmation */} - {/* Portal-based confirmation removed, now handled by Modal.confirm */} -
- {/* Create card at top */} - {showNewCardTop && ( - - )} + onClick={e => { + e.stopPropagation(); + }} + /> + ) : ( +
{ + e.stopPropagation(); + e.preventDefault(); + }} + onMouseUp={e => { + e.stopPropagation(); + }} + onClick={e => { + e.stopPropagation(); + }} + > + {name} ({group.tasks.length}) +
+ )} +
{/* Simple Delete Confirmation */} - {showDeleteConfirm && ( - -
setShowDeleteConfirm(false)} - > -
e.stopPropagation()} - > -
-
-
- - - -
-
-

- {t('deleteConfirmationTitle')} -

-
-
-
- - -
-
-
-
-
- )} + {/* Portal-based confirmation removed, now handled by Modal.confirm */}
{/* Create card at top */} {showNewCardTop && (