Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Review Package: Reassign Package APPEALS-36344 #21321

Merged
merged 11 commits into from
Apr 4, 2024
1 change: 1 addition & 0 deletions app/controllers/correspondence_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def mail_team_users
end

def review_package
@mail_team_users = User.mail_team_users.pluck(:css_id)
render "correspondence/review_package"
end

Expand Down
1 change: 1 addition & 0 deletions app/views/correspondence/review_package.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
organizations: current_user.selectable_organizations.map {|o| o.slice(:name, :url)},
caseSearchHomePage: case_search_home_page,
dropdownUrls: dropdown_urls,
mailTeamUsers: @mail_team_users,
featureToggles: {
correspondence_queue: FeatureToggle.enabled?(:correspondence_queue, user: current_user)
}
Expand Down
2 changes: 2 additions & 0 deletions client/COPY.json
Original file line number Diff line number Diff line change
Expand Up @@ -1442,7 +1442,9 @@
"CORRESPONDENCE_DOC_UPLOAD_FAILED_MESSAGE": "You can upload it from this page to the veteran's eFolder at a later time.",
"CORRESPONDENCE_HEADER_REMOVE_PACKAGE": "Review request",
"CORRESPONDENCE_TITLE_REMOVE_PACKAGE": "Reason for removal:",
"CORRESPONDENCE_TITLE_REASSIGN_PACKAGE": "Reason for reassign:",
"CORRRESPONDENCE_LABEL_OPTION_REMOVE_PACKAGE": " Choose whether to approve the request for removal or reject it.",
"CORRRESPONDENCE_LABEL_OPTION_REASSIGN_PACKAGE": " Choose whether to approve the request for reassign or reject it.",
"CORRRESPONDENCE_TEXT_REMOVE_PACKAGE": "\nThis is the reason for removal provided by the general user.",
"CORRRESPONDENCE_SECOND_TEXT_REMOVE_PACKAGE": "\nThis is the reason for removal provided by the user that submitted the request.",
"CORRESPONDENCE_TITLE_REMOVE_PACKAGE_REASON_REJECT": "Provide a reason for rejection",
Expand Down
8 changes: 6 additions & 2 deletions client/app/queue/QueueApp.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -633,8 +633,11 @@ class QueueApp extends React.PureComponent {
);

routedReviewPackage = (props) => (
<ReviewPackageLoadingScreen {...props.match.params}>
<CorrespondenceReviewPackage {...props.match.params} />
<ReviewPackageLoadingScreen mailTeamUsers= {props.mailTeamUsers} {...props.match.params}>
<CorrespondenceReviewPackage
mailTeamUsers= {this.props.mailTeamUsers}
{...props.match.params}
/>
</ReviewPackageLoadingScreen>
);

Expand Down Expand Up @@ -1511,6 +1514,7 @@ QueueApp.propTypes = {
isMailTeamUser: PropTypes.bool,
isMailSupervisor: PropTypes.bool,
isMailSuperUser: PropTypes.bool,
mailTeamUsers: PropTypes.array,
organizations: PropTypes.array,
setUserIsVsoEmployee: PropTypes.func,
userIsVsoEmployee: PropTypes.bool,
Expand Down
267 changes: 267 additions & 0 deletions client/app/queue/correspondence/component/ReassignPackageModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
import React from 'react';
import PropTypes from 'prop-types';
import ApiUtil from '../../../util/ApiUtil';
import { sprintf } from 'sprintf-js';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { updateLastReassignAction } from '../correspondenceReducer/reviewPackageActions';
import TextareaField from '../../../components/TextareaField';
import ReactSelectDropdown from '../../../components/ReactSelectDropdown';
import COPY from '../../../../COPY';
import Modal from '../../../components/Modal';
import Button from '../../../components/Button';
import { Redirect } from 'react-router-dom';
import RadioFieldWithChildren from '../../../components/RadioFieldWithChildren';

class ReassignPackageModal extends React.Component {

constructor(props) {
super(props);

this.state = {
reasonForRemove: null,
disabledSaveButton: true,
reasonReject: '',
updateCancelSuccess: false,
selectedMailTeamUser: '',
selectedRequestChoice: '',
decisionReason: '',
vetName: ''
};
}

handleSelect(reasonForRemove) {
if (reasonForRemove === 'Approve request') {
this.setState({ reasonForRemove,
disabledSaveButton: false
});
} else {
this.setState({ reasonForRemove,
disabledSaveButton: true });
}
}

reasonChange = (value) => {
if (value.trim().length > 0) {
this.setState({
reasonReject: value,
disabledSaveButton: false
});
} else {
this.setState({
reasonReject: '',
disabledSaveButton: true
});
}
}

removePackage = async () => {
try {
ApiUtil.post(`/queue/correspondence/${this.props.correspondence_id}/remove_package`).
then(() => {
this.setState({
updateCancelSuccess: true
});
this.props.updateLastAction('DeleteReviewPackage');
});

} catch (error) {
console.error(error);
}
}

completePackage = async () => {
try {
const data = {
correspondence_id: this.props.correspondence_id,
instructions: []
};

data.instructions.push(this.state.reasonReject);

ApiUtil.post(`/queue/correspondence/${this.props.correspondence_id}/completed_package`, { data }).
then(() => {
this.setState({
updateCancelSuccess: true
});
this.props.updateLastAction('InProgressReviewPackage');
});

} catch (error) {
console.error(error);
}
}

render() {
const { onCancel } = this.props;
const submit = (operation) => {
let newUrl = new URL(window.location.href);
const modifyURL = newUrl.href;
const searchString = '/queue/correspondence';
const index = modifyURL.indexOf(searchString);
const updatedUrl = `${modifyURL.substring(0, index + searchString.length)}/team`;

newUrl = new URL(updatedUrl);
const searchParams = new URLSearchParams(newUrl.search);

// Encode and set the query parameters
searchParams.set('user', encodeURIComponent(this.state.selectedMailTeamUser));
searchParams.set('taskId', encodeURIComponent(this.props.veteranInformation.correspondence_tasks[2].id));
searchParams.set('userAction', encodeURIComponent(this.state.selectedRequestChoice));
searchParams.set('decisionReason', encodeURIComponent(this.state.decisionReason));
searchParams.set('operation', encodeURIComponent(operation));

// Construct the new URL with encoded query parameters
newUrl.search = searchParams.toString();
window.location.href = newUrl.href;
};

const confirmButtonDisabled = () => {
const selectedRequestChoice = this.state.selectedRequestChoice;
const selectedMailTeamUser = this.state.selectedMailTeamUser;
const reassignModalVisible = this.props.modalState;
const decisionReason = this.state.decisionReason;

if (selectedRequestChoice === 'approve' && selectedMailTeamUser === '' && reassignModalVisible) {
return true;
}

if (selectedRequestChoice === 'reject' && decisionReason === '') {
return true;
}

if (selectedRequestChoice === '') {
return true;
}

return false;
};

const buildMailUserData = (data) => {

if (typeof data === 'undefined') {
return [];
}

return data.map((user) => {
return {
value: user,
label: user
};
});
};

const handleSetSelectedMailTeamUser = (selectedUser) => {
this.setState({ selectedMailTeamUser: selectedUser });
};

const handleDecisionReason = (decisionText) => {
this.setState({ decisionReason: decisionText });
};

const resetState = () => {
this.setState({ selectedMailTeamUser: '' });
this.setState({ selectedRequestChoice: '' });
this.setState({ decisionReason: '' });
};

const handleSelectedRequestChoice = (selectedRequest) => {
resetState();
this.setState({ selectedRequestChoice: selectedRequest });
};

const approveElement = (<div style={{ width: '16vw' }}>
<ReactSelectDropdown
HunJerBAH marked this conversation as resolved.
Show resolved Hide resolved
className="cf-margin-left-2rem img"
label="Assign to person"
onChangeMethod={(val) => handleSetSelectedMailTeamUser(val.value)}
options={buildMailUserData(this.props.mailTeamUsers)}
/>
</div>);

const textAreaElement = (
<div style={{ width: '100%' }}>
<TextareaField label="Provide a reason for rejection"
HunJerBAH marked this conversation as resolved.
Show resolved Hide resolved
onChange={handleDecisionReason}
value={this.state.decisionReason} />
</div>);

const reassignReasonOptions = [
{
displayText: 'Approve request',
value: 'approve',
element: approveElement,
displayElement: this.state.selectedRequestChoice === 'approve'
},
{
displayText: 'Reject request',
value: 'reject',
element: textAreaElement,
displayElement: this.state.selectedRequestChoice === 'reject'
}
];

if (this.state.updateCancelSuccess) {
return <Redirect to="/queue/correspondence" />;
}

return (
<Modal
title= {sprintf(COPY.CORRESPONDENCE_HEADER_REMOVE_PACKAGE)}
closeHandler={onCancel}
confirmButton={<Button disabled={(confirmButtonDisabled())}
onClick={() => (submit('reassign'))}>Confirm</Button>}
cancelButton={<Button linkStyling onClick={onCancel}>Cancel</Button>}
>
<p>
<span style= {{ fontWeight: 'bold' }}>{sprintf(COPY.CORRESPONDENCE_TITLE_REASSIGN_PACKAGE)}</span><br />
{this.props.reasonRemovePackage[0]}
</p>

<p>{this.props.veteranInformation.correspondence_tasks[2].instructions[0]}</p>

<RadioFieldWithChildren
vertical
label= {sprintf(COPY.CORRRESPONDENCE_LABEL_OPTION_REASSIGN_PACKAGE)}
name="merge-package"
value={this.state.selectedRequestChoice}
options={reassignReasonOptions}
onChange={(val) => handleSelectedRequestChoice(val)}
/>

</Modal>
);

}
}

const mapStateToProps = (state) => {
return { vetInfo: state.reviewPackage.lastAction,
reasonRemovePackage: state.reviewPackage.reasonForRemovePackage,
reassignModalVisible: state.intakeCorrespondence.showReassignPackageModal,
currentAction: state.reviewPackage.lastAction,
veteranInformation: state.reviewPackage.veteranInformation,
currentSelectedVeteran: state.intakeCorrespondence.selectedVeteranDetails
};
};

ReassignPackageModal.propTypes = {
modalState: PropTypes.bool,
onCancel: PropTypes.func,
mailTeamUsers: PropTypes.array,
setModalState: PropTypes.func,
correspondence_id: PropTypes.number,
vetInfo: PropTypes.object,
reasonRemovePackage: PropTypes.object,
veteranInformation: PropTypes.object,
updateLastAction: PropTypes.func,
};

const mapDispatchToProps = (dispatch) => bindActionCreators({
updateLastReassignAction
}, dispatch);

export default connect(
mapStateToProps,
mapDispatchToProps
)(ReassignPackageModal);
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,17 @@ class RemovePackageModal extends React.Component {
const { onCancel } = this.props;
const submit = () => {
let selectedRequestChoice;

if (this.state.reasonForRemove === 'Approve request') {
selectedRequestChoice ='approve';
selectedRequestChoice = 'approve';
} else {
selectedRequestChoice ='reject';
selectedRequestChoice = 'reject';
}
const newUrl = new URL(window.location.href);
const searchParams = new URLSearchParams(newUrl.search);
const taskId = this.props.reviewDetails.taskId;
const veteranName = this.props.reviewDetails.veteranName;

// Encode and set the query parameters
searchParams.set('taskId', encodeURIComponent(taskId));
searchParams.set('veteranName', encodeURIComponent(veteranName));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,23 @@ export const setReasonRemovePackage = (reasonForRemove) =>
}
});
};

export const updateLastReassignAction = (currentAction) =>
(dispatch) => {
dispatch({
type: ACTIONS.REASSIGN_PACKAGE_ACTION,
payload: {
currentAction
}
});
};

export const setReasonReassignPackage = (reasonForReassign) =>
(dispatch) => {
dispatch({
type: ACTIONS.SET_REASON_REASSIGN_PACKAGE,
payload: {
reasonForReassign
}
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ export const ACTIONS = {
UPDATE_DOCUMENT_TYPE_NAME: 'UPDATE_DOCUMENT_TYPE_NAME',
REMOVE_PACKAGE_ACTION: 'REMOVE_PACKAGE_ACTION',
SET_REASON_REMOVE_PACKAGE: 'SET_REASON_REMOVE_PACKAGE',
REASSIGN_PACKAGE_ACTION: 'REASSIGN_PACKAGE_ACTION',
SET_REASON_REASSIGN_PACKAGE: 'SET_REASON_REASSIGN_PACKAGE',
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ export const initialState = {
packageDocumentType: {},
veteranInformation: {},
lastAction: {},
reasonForRemovePackage: {}
reasonForRemovePackage: {},
reasonForReassignPackage: {}
};

export const reviewPackageReducer = (state = initialState, action = {}) => {
Expand Down Expand Up @@ -87,6 +88,22 @@ export const reviewPackageReducer = (state = initialState, action = {}) => {
}
});

case ACTIONS.REASSIGN_PACKAGE_ACTION:
return update(state, {
lastAction: {
action_type: {
$set: action.payload.currentAction
}
}
});

case ACTIONS.SET_REASON_REASSIGN_PACKAGE:
return update(state, {
reasonForReassignPackage: {
$set: action.payload.reasonForReassignPackage
}
});

default:
return state;
}
Expand Down
Loading
Loading