diff --git a/src/views/components/AssigneePickerField.jsx b/src/views/components/AssigneePickerField.jsx index b9444c7..e0ac177 100644 --- a/src/views/components/AssigneePickerField.jsx +++ b/src/views/components/AssigneePickerField.jsx @@ -1,30 +1,55 @@ import { Person } from '@mui/icons-material' + import BaseOptionPicker from './BaseOptionPicker' +const ANYONE = 'anyone' + const AssigneePickerField = ({ - value = null, + currentUserId = null, + emptyDisplay, + includeAnyone = true, + isAnyone = false, + members = [], onChange, onClear, - members = [], - includeAnyone = true, - emptyDisplay, - currentUserId = null, + values = [], }) => { const options = [ - ...(includeAnyone ? [{ userId: 'anyone', displayName: 'Anyone' }] : []), + ...(includeAnyone ? [{ userId: ANYONE, displayName: 'Anyone' }] : []), ...members.map(member => ({ userId: member.userId, displayName: member.displayName || member.username || 'Unknown', })), ] - const displayValue = currentUserId && value === currentUserId ? null : value + // An implicit self-assignment is shown as "unset" so the chip stays empty + // until the user picks someone explicitly. + const isImplicitSelf = + !isAnyone && + currentUserId && + values.length === 1 && + values[0] === currentUserId + + const displayValues = isAnyone ? [ANYONE] : isImplicitSelf ? [] : values + + const handleValuesChange = nextValues => { + const wasAnyone = displayValues.includes(ANYONE) + const hasAnyone = nextValues.includes(ANYONE) + + if (hasAnyone && !wasAnyone) { + onChange?.([ANYONE]) + return + } + + onChange?.(nextValues.filter(userId => userId !== ANYONE)) + } return ( item.displayName} renderTriggerIcon={() => } renderItemStart={() => } - getTriggerText={({ selectedItems, isEmpty }) => - isEmpty ? 'Assignee' : selectedItems[0].displayName - } + getTriggerText={({ isEmpty, selectedItems }) => { + if (isEmpty) return 'Assignee' + if (selectedItems.length === 1) return selectedItems[0].displayName + return `${selectedItems.length} assignees` + }} menuMinWidth={220} /> )