Skip to content

Commit

Permalink
Set Up Container Component for MTV Checkout Workflows (#13334)
Browse files Browse the repository at this point in the history
Connects #13318

### Description
This does multiple things:
- refactors `QueueApp` to break out MTV routes into their own file
- creates MotionToVacateContext for data handling as part of MTV checkout flow
- creates MotionToVacateFlowContainer that will serve as a container for the MTV checkout flows

### Acceptance Criteria
- [ ] Code compiles correctly
  • Loading branch information
jcq authored Feb 6, 2020
1 parent b3441c2 commit 5239ba2
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 88 deletions.
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}
</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}
</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>
{/* 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"
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
};

0 comments on commit 5239ba2

Please sign in to comment.