diff --git a/moped-editor/src/views/projects/projectView/ProjectTeam/ProjectTeamTable.js b/moped-editor/src/views/projects/projectView/ProjectTeam/ProjectTeamTable.js index 935f894347..546e265ee0 100644 --- a/moped-editor/src/views/projects/projectView/ProjectTeam/ProjectTeamTable.js +++ b/moped-editor/src/views/projects/projectView/ProjectTeam/ProjectTeamTable.js @@ -49,6 +49,14 @@ const useWorkgroupLookup = (data) => }, {}); }, [data]); +// returns a list of user ids for the existing team members on this project +const useExistingTeamMembers = (data) => + useMemo(() => { + return data?.moped_project_by_pk?.moped_proj_personnel.map( + (option) => option.moped_user.user_id + ); + }, [data]); + const requiredFields = ["moped_user", "moped_proj_personnel_roles"]; const useColumns = ({ @@ -61,6 +69,7 @@ const useColumns = ({ classes, usingShiftKey, workgroupLookup, + existingTeamMembers, }) => useMemo(() => { return [ @@ -73,13 +82,27 @@ const useColumns = ({ return user ? `${user.first_name} ${user.last_name}` : ""; }, renderEditCell: (props) => { + // the team member object for the current row + const currentRowMember = + data?.moped_project_by_pk?.moped_proj_personnel.find( + (user) => user.project_personnel_id === props.id + ); + // filter out existing team members from list of options unless they are the current row member + // that way the current member remains an option when editing a row + const unassignedTeamMembers = data?.moped_users.filter((user) => { + return ( + !existingTeamMembers.includes(user.user_id) || + user.user_id === currentRowMember?.moped_user.user_id + ); + }); return ( ); }, @@ -194,6 +217,7 @@ const useColumns = ({ classes, usingShiftKey, workgroupLookup, + existingTeamMembers, ]); const ProjectTeamTable = ({ projectId, handleSnackbar }) => { @@ -233,6 +257,8 @@ const ProjectTeamTable = ({ projectId, handleSnackbar }) => { const workgroupLookup = useWorkgroupLookup(data); + const existingTeamMembers = useExistingTeamMembers(data); + /** * Construct a moped_project_personnel object that can be passed to an insert mutation * @param {Object} newData - a table row object with { moped_user, notes, roleIds } @@ -496,6 +522,7 @@ const ProjectTeamTable = ({ projectId, handleSnackbar }) => { classes, usingShiftKey, workgroupLookup, + existingTeamMembers, }); const processRowUpdateMemoized = useCallback( diff --git a/moped-editor/src/views/projects/projectView/ProjectTeam/TeamAutocompleteComponent.js b/moped-editor/src/views/projects/projectView/ProjectTeam/TeamAutocompleteComponent.js index 0c90a28040..2139c7b017 100644 --- a/moped-editor/src/views/projects/projectView/ProjectTeam/TeamAutocompleteComponent.js +++ b/moped-editor/src/views/projects/projectView/ProjectTeam/TeamAutocompleteComponent.js @@ -14,10 +14,10 @@ import { useTheme } from "@mui/material/styles"; * @param {String} value - field value * @param {String} field - name of field * @param {Boolean} hasFocus - does this field have focus - * @param {Object} nameLookup - maps user id to user name * @param {Boolean} error - toggles error style in textfield * @param {Object} name - name of the field - * @param {Object} userWorkgroupLookup - mapping of user ids to their corresponding workgroup ids + * @param {Object} options - moped users to use in team member select + * @param {Object} workgroupLookup - lookup object to map workgroup ids to names * @return {JSX.Element} */ const TeamAutocompleteComponent = ({ @@ -28,6 +28,7 @@ const TeamAutocompleteComponent = ({ error, name, options, + workgroupLookup, }) => { const theme = useTheme(); const apiRef = useGridApiContext(); @@ -49,7 +50,10 @@ const TeamAutocompleteComponent = ({ apiRef.current.setEditCellValue({ id, field: "moped_workgroup", - value: { workgroup_id: newValue?.workgroup_id }, + value: { + workgroup_id: newValue?.workgroup_id, + workgroup_name: workgroupLookup[newValue?.workgroup_id], + }, }); };