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

Set Up Container Component for MTV Checkout Workflows #13334

Merged
merged 12 commits into from
Feb 6, 2020
55 changes: 8 additions & 47 deletions client/app/queue/QueueApp.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,9 @@ import TASK_STATUSES from '../../constants/TASK_STATUSES';
import USER_ROLE_TYPES from '../../constants/USER_ROLE_TYPES';
import DECISION_TYPES from '../../constants/APPEAL_DECISION_TYPES';
import { FlashAlerts } from '../nonComp/components/Alerts';
import AddressMotionToVacateView from './mtv/AddressMotionToVacateView';
import ReviewMotionToVacateView from './mtv/ReviewMotionToVacateView';

import { PulacCerulloReminderModal } from './pulacCerullo/PulacCerulloReminderModal';
import { ReturnToLitSupportModal } from './mtv/ReturnToLitSupportModal';
import { returnToLitSupport } from './mtv/mtvActions';
import { motionToVacateRoutes } from './mtv/motionToVacateRoutes';

class QueueApp extends React.PureComponent {
componentDidMount = () => {
Expand Down Expand Up @@ -214,10 +212,6 @@ class QueueApp extends React.PureComponent {

routedAssignToUser = (props) => <AssignToView {...props.match.params} />;

routedSendMotionToVacateToJudge = () => <ReviewMotionToVacateView />;

routedAddressMotionToVacate = (props) => <AddressMotionToVacateView {...props.match.params} />;

routedPulacCerulloReminder = (props) => {
const { appealId, taskId } = props.match.params;
const pulacRoute = `/queue/appeals/${appealId}/tasks/${taskId}/${TASK_ACTIONS.LIT_SUPPORT_PULAC_CERULLO.value}`;
Expand All @@ -234,21 +228,6 @@ class QueueApp extends React.PureComponent {

routedAssignToPulacCerullo = (props) => <AssignToView isTeamAssign assigneeAlreadySelected {...props.match.params} />;

routedReturnToLitSupport = (props) => {
const { taskId } = props.match.params;

return (
<ReturnToLitSupportModal
{...props.match.params}
onCancel={() => props.history.goBack()}
onSubmit={({ instructions }) => {
this.props.returnToLitSupport({ instructions,
task_id: taskId }, props);
}}
/>
);
};

routedReassignToUser = (props) => <AssignToView isReassignAction {...props.match.params} />;

routedCompleteTaskModal = (props) => <CompleteTaskModal modalType="mark_task_complete" {...props.match.params} />;
Expand Down Expand Up @@ -445,12 +424,6 @@ class QueueApp extends React.PureComponent {
render={this.routedAddColocatedTask}
/>

<PageRoute
path={`/queue/appeals/:appealId/tasks/:taskId/${TASK_ACTIONS.ADDRESS_MOTION_TO_VACATE.value}`}
title="Address Motion to Vacate | Caseflow"
render={this.routedAddressMotionToVacate}
/>

<PageRoute
path="/team_management"
title="Team Management | Caseflow"
Expand All @@ -461,6 +434,8 @@ class QueueApp extends React.PureComponent {
title="User Management | Caseflow"
render={this.routedUserManagement}
/>

{motionToVacateRoutes.page}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very pretty and nicely done!

</Switch>

{/* Modal routes are in their own Switch so they will display above the base routes */}
Expand Down Expand Up @@ -551,10 +526,6 @@ class QueueApp extends React.PureComponent {
path={`/queue/appeals/:appealId/tasks/:taskId/${TASK_ACTIONS.SPECIAL_CASE_MOVEMENT.value}`}
render={this.routedAssignToUser}
/>
<Route
path={`/queue/appeals/:appealId/tasks/:taskId/${TASK_ACTIONS.SEND_MOTION_TO_VACATE_TO_JUDGE.value}`}
render={this.routedSendMotionToVacateToJudge}
/>

<PageRoute
exact
Expand All @@ -574,16 +545,6 @@ class QueueApp extends React.PureComponent {
title="Assign to Pulac-Cerullo | Caseflow"
render={this.routedAssignToPulacCerullo}
/>
<PageRoute
exact
path={[
'/queue/appeals/:appealId/tasks/:taskId',
TASK_ACTIONS.ADDRESS_MOTION_TO_VACATE.value,
TASK_ACTIONS.JUDGE_RETURN_TO_LIT_SUPPORT.value
].join('/')}
title="Return to Litigation Support | Caseflow"
render={this.routedReturnToLitSupport}
/>
<PageRoute
exact
path={`/queue/appeals/:appealId/tasks/:taskId/${
Expand Down Expand Up @@ -657,6 +618,8 @@ class QueueApp extends React.PureComponent {
<Route path="/team_management/add_vso" render={this.routedAddVsoModal} />
<Route path="/team_management/add_private_bar" render={this.routedAddPrivateBarModal} />
<Route path="/team_management/lookup_participant_id" render={this.routedLookupParticipantIdModal} />

{motionToVacateRoutes.modal}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

</Switch>
</div>
</AppFrame>
Expand Down Expand Up @@ -688,8 +651,7 @@ QueueApp.propTypes = {
applicationUrls: PropTypes.array,
flash: PropTypes.array,
reviewActionType: PropTypes.string,
userCanViewHearingSchedule: PropTypes.bool,
returnToLitSupport: PropTypes.func
userCanViewHearingSchedule: PropTypes.bool
};

const mapStateToProps = (state) => ({
Expand All @@ -704,8 +666,7 @@ const mapDispatchToProps = (dispatch) =>
setUserCssId,
setUserIsVsoEmployee,
setFeedbackUrl,
setOrganizations,
returnToLitSupport
setOrganizations
},
dispatch
);
Expand Down
56 changes: 15 additions & 41 deletions client/app/queue/mtv/AddressMotionToVacateView.jsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,33 @@
import React from 'react';
import PropTypes from 'prop-types';

import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { withRouter } from 'react-router-dom';
import { useSelector, useDispatch } from 'react-redux';
import { useRouteMatch, useParams, useHistory } from 'react-router-dom';

import { taskById, appealWithDetailSelector } from '../selectors';
import { MTVJudgeDisposition } from './MTVJudgeDisposition';
import { JUDGE_RETURN_TO_LIT_SUPPORT } from '../../../constants/TASK_ACTIONS';
import { submitMTVJudgeDecision } from './mtvActions';
import { taskActionData } from '../utils';

export const AddressMotionToVacateView = (props) => {
const { task, appeal } = props;
export const AddressMotionToVacateView = () => {
const { taskId, appealId } = useParams();
const match = useRouteMatch();
const history = useHistory();
const dispatch = useDispatch();

const { selected, options } = taskActionData(props);
const task = useSelector((state) => taskById(state, { taskId }));
const appeal = useSelector((state) => appealWithDetailSelector(state, { appealId }));

const { selected, options } = taskActionData({ task,
match });

const attyOptions = options.map(({ value, label }) => ({
label: label + (selected && value === selected.id ? ' (Orig. Attorney)' : ''),
value
}));

const handleSubmit = (result) => {
props.submitMTVJudgeDecision(result, props);
dispatch(submitMTVJudgeDecision(result, { history }));
};

return (
Expand All @@ -32,40 +37,9 @@ export const AddressMotionToVacateView = (props) => {
selectedAttorney={selected}
appeal={appeal}
onSubmit={handleSubmit}
returnToLitSupportLink={`${props.match.url}/${JUDGE_RETURN_TO_LIT_SUPPORT.value}`}
returnToLitSupportLink={`${match.url}/${JUDGE_RETURN_TO_LIT_SUPPORT.value}`}
/>
);
};

AddressMotionToVacateView.propTypes = {
task: PropTypes.object,
appeal: PropTypes.object,
submitMTVJudgeDecision: PropTypes.func,
match: PropTypes.shape({
url: PropTypes.string
})
};

const mapStateToProps = (state, { match }) => {
const { taskId, appealId } = match.params;

return {
task: taskById(state, { taskId }),
appeal: appealWithDetailSelector(state, { appealId })
};
};

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

export default withRouter(
connect(
mapStateToProps,
mapDispatchToProps
)(AddressMotionToVacateView)
);
export default AddressMotionToVacateView;
20 changes: 20 additions & 0 deletions client/app/queue/mtv/MotionToVacateContext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';

const defaultState = {};

// This pattern allows us to access a shared object state using familiar functions
// Components that consume this context can simply use this syntax:
// const [state, setState] = useContext(MotionToVacateContext);
// setState({...state, foo: 'bar'});
export const MotionToVacateContext = React.createContext([{}, () => null]);

export const MotionToVacateContextProvider = ({ initialState = { ...defaultState }, children }) => {
const [state, setState] = useState(initialState);

return <MotionToVacateContext.Provider value={[state, setState]}>{children}</MotionToVacateContext.Provider>;
};
MotionToVacateContextProvider.propTypes = {
initialState: PropTypes.object,
children: PropTypes.element
};
37 changes: 37 additions & 0 deletions client/app/queue/mtv/MotionToVacateFlowContainer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { useParams, useRouteMatch, Switch, Route } from 'react-router';
import { taskById, appealWithDetailSelector } from '../selectors';
import { MotionToVacateContextProvider } from './MotionToVacateContext';

export const MotionToVacateFlowContainer = () => {
const { path } = useRouteMatch();
const { taskId, appealId } = useParams();
const task = useSelector((state) => taskById(state, { taskId }));
const appeal = useSelector((state) => appealWithDetailSelector(state, { appealId }));

// For linter while things are stubbed — remove once used
(() => ({ task,
appeal }))();

return (
<React.Fragment>
<MotionToVacateContextProvider>
jcq marked this conversation as resolved.
Show resolved Hide resolved
{/* MTV Progress Bar (#13319) Here */}

<Switch>
<Route path={`${path}/review_vacatures`}>
{/* Insert component from #13007 here */}
{/* <ReviewVacatedDecisionIssuesView appeal={appeal} /> */}
<></>
</Route>
<Route path={`${path}/add_decisions`}>
{/* Insert component from #13071 here */}
{/* <AddDecisionsView appeal={appeal} /> */}
<></>
</Route>
</Switch>
</MotionToVacateContextProvider>
</React.Fragment>
);
};
62 changes: 62 additions & 0 deletions client/app/queue/mtv/motionToVacateRoutes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React from 'react';
import { Route, useParams, useHistory } from 'react-router';
import PageRoute from '../../components/PageRoute';

import TASK_ACTIONS from '../../../constants/TASK_ACTIONS.json';
import ReviewMotionToVacateView from './ReviewMotionToVacateView';
import { AddressMotionToVacateView } from './AddressMotionToVacateView';
import { ReturnToLitSupportModal } from './ReturnToLitSupportModal';
import { useDispatch } from 'react-redux';
import { returnToLitSupport } from './mtvActions';
import { MotionToVacateFlowContainer } from './MotionToVacateFlowContainer';

const RoutedReturnToLitSupport = (props) => {
const { taskId } = useParams();
const { goBack } = useHistory();
const dispatch = useDispatch();

return (
<ReturnToLitSupportModal
onCancel={() => goBack()}
onSubmit={({ instructions }) => dispatch(returnToLitSupport({ instructions,
task_id: taskId }, props))}
/>
);
};

const PageRoutes = [
<PageRoute
path={`/queue/appeals/:appealId/tasks/:taskId/${TASK_ACTIONS.ADDRESS_MOTION_TO_VACATE.value}`}
title="Address Motion to Vacate | Caseflow"
component={AddressMotionToVacateView}
/>,

// This route handles the remaining checkout flow
<Route
path="/queue/appeals/:appealId/tasks/:taskId/motion_to_vacate_checkout"
leikkisa marked this conversation as resolved.
Show resolved Hide resolved
component={MotionToVacateFlowContainer}
/>
];

const ModalRoutes = [
<PageRoute
exact
path={[
'/queue/appeals/:appealId/tasks/:taskId',
TASK_ACTIONS.ADDRESS_MOTION_TO_VACATE.value,
TASK_ACTIONS.JUDGE_RETURN_TO_LIT_SUPPORT.value
].join('/')}
title="Return to Litigation Support | Caseflow"
component={RoutedReturnToLitSupport}
/>,

<Route
path={`/queue/appeals/:appealId/tasks/:taskId/${TASK_ACTIONS.SEND_MOTION_TO_VACATE_TO_JUDGE.value}`}
component={ReviewMotionToVacateView}
/>
];

export const motionToVacateRoutes = {
page: PageRoutes,
modal: ModalRoutes
};