Skip to content

Commit

Permalink
J hoang/appeals 57366 (#23184)
Browse files Browse the repository at this point in the history
* restrict decision date selector in disposition

* update dateselector snapshot

* update multiple snapshots

* test

* lint

* fix double validation error showing

* code climate and dispositions spec fix attempt

* another attempt at disposition spec

* make minDate inclusive and fix timezone issue

* another attempt

* hopefully disposition is fixed

---------

Co-authored-by: Jonathan Hoang <trinhjoanthan.hoang@va.gov>
  • Loading branch information
jonathanh-va and Jonathan Hoang authored Oct 21, 2024
1 parent d42fbb1 commit dc9c19c
Show file tree
Hide file tree
Showing 21 changed files with 166 additions and 11 deletions.
1 change: 1 addition & 0 deletions client/COPY.json
Original file line number Diff line number Diff line change
Expand Up @@ -1413,6 +1413,7 @@
"VHA_FIRST_LOGIN_INFO_ALERT_TITLE": "VHA Team Access",
"PDF_GENERATION_ERROR_TITLE": "Unable to generate PDF",
"PDF_GENERATION_ERROR_MESSAGE": "There was an error generating the PDF for download. Please try again later.",
"DATE_SELECTOR_DATE_RANGE_ERROR": "Decision date must be between Form Receipt Date (%s) and current date (%s).",
"DATE_SELECTOR_FUTURE_DATE_ERROR": "Dates cannot be in the future",
"DATE_SELECTOR_INVALID_DATE_ERROR": "Please select a valid date",
"VHA_ACTION_PLACE_CUSTOM_HOLD_COPY": "Enter a custom number of days for the hold (Value must be between 1 and 45 for VHA users)",
Expand Down
14 changes: 13 additions & 1 deletion client/app/components/DateSelector.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const DateSelector = (props) => {
value,
dateErrorMessage,
noFutureDates = false,
minDate = null,
inputStyling,
validateDate,
...passthroughProps
Expand All @@ -34,7 +35,7 @@ export const DateSelector = (props) => {
return COPY.DATE_SELECTOR_INVALID_DATE_ERROR;
}

if (noFutureDates && futureDate(date)) {
if (noFutureDates && futureDate(date) && !minDate) {
return COPY.DATE_SELECTOR_FUTURE_DATE_ERROR;
}

Expand All @@ -54,12 +55,17 @@ export const DateSelector = (props) => {
}, [value]);

let max = '9999-12-31';
let min = '0000-01-01';

if (noFutureDates) {
max = new Date().toISOString().
split('T')[0];
}

if (minDate) {
min = minDate;
}

return (
<TextField
errorMessage={errorMessage}
Expand All @@ -74,6 +80,7 @@ export const DateSelector = (props) => {
required={required}
{...passthroughProps}
max={max}
min={min}
dateErrorMessage={dateErrorMessage}
inputStyling={inputStyling}
/>
Expand Down Expand Up @@ -152,6 +159,11 @@ DateSelector.propTypes = {
*/
noFutureDates: PropTypes.bool,

/**
* Specify a minimum date that can be selected
*/
minDate: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]),

/**
* Disables form submission if date is empty or invalid
*/
Expand Down
3 changes: 3 additions & 0 deletions client/app/components/TextField.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const TextField = (props) => {
strongLabel,
maxLength,
max,
min,
autoComplete,
useAriaLabel,
dateErrorMessage,
Expand Down Expand Up @@ -113,6 +114,7 @@ export const TextField = (props) => {
title={title}
maxLength={maxLength}
max={max}
min={min}
autoComplete={autoComplete}
disabled={disabled}
{...inputProps}
Expand Down Expand Up @@ -204,6 +206,7 @@ TextField.propTypes = {
strongLabel: PropTypes.bool,
maxLength: PropTypes.number,
max: PropTypes.any,
min: PropTypes.any,
autoComplete: PropTypes.string,
inputID: PropTypes.string,
placeholder: PropTypes.string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ Object {
class="cf-form-textinput"
id="decision-date"
max="2023-08-10"
min="0000-01-01"
name="decision-date"
placeholder="mm/dd/yyyy"
type="date"
Expand Down Expand Up @@ -241,6 +242,7 @@ Object {
class="cf-form-textinput"
id="decision-date"
max="2023-08-10"
min="0000-01-01"
name="decision-date"
placeholder="mm/dd/yyyy"
type="date"
Expand Down
38 changes: 36 additions & 2 deletions client/app/nonComp/components/Disposition.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
} from '../util';
import Link from 'app/components/Link';
import Alert from '../../components/Alert';
import { sprintf } from 'sprintf-js';

const messageStyling = css({
fontSize: '17px !important',
Expand Down Expand Up @@ -109,7 +110,8 @@ class NonCompDispositions extends React.PureComponent {
requestIssues: formatRequestIssuesWithDecisionIssues(
this.props.task.appeal.activeOrDecidedRequestIssues, this.props.appeal.decisionIssues),
decisionDate: '',
isFilledOut: false
isFilledOut: false,
errorMessage: ''
};
}

Expand All @@ -124,12 +126,40 @@ class NonCompDispositions extends React.PureComponent {
this.props.handleSave(dispositionData);
}

validateDecisionDate = () => {
const decisionDate = formatDateStr(this.state.decisionDate);
const receiptDate = formatDateStr(this.props.appeal.receiptDate);

const dateIsValid = Boolean((new Date(decisionDate)) >= new Date(receiptDate)) &&
Boolean(Date.parse(decisionDate) < new Date());

if (dateIsValid) {
this.setState({ errorMessage: '' });
} else {
this.setState({
errorMessage: sprintf(
COPY.DATE_SELECTOR_DATE_RANGE_ERROR,
formatDateStr(this.props.appeal.receiptDate),
formatDateStr(new Date())),
isFilledOut: false
});
}

return dateIsValid;
}

checkFormFilledOut = () => {
// check if all dispositions have values & date is set
const allDispositionsSet = this.state.requestIssues.every(
(requestIssue) => Boolean(requestIssue.decisionIssue.disposition));

this.setState({ isFilledOut: allDispositionsSet && Boolean(this.state.decisionDate) });
let validDate = null;

if (this.state.decisionDate) {
validDate = this.validateDecisionDate();
}

this.setState({ isFilledOut: (allDispositionsSet && validDate) });
}

onDecisionIssueDispositionChange = (requestIssueIndex, value) => {
Expand Down Expand Up @@ -183,6 +213,7 @@ class NonCompDispositions extends React.PureComponent {
const displayRequestIssueModification = (!displayPOAComponent || isBusinessLineAdmin);

const decisionHasPendingRequestIssues = task.pending_issue_modification_count > 0;
const receiptDate = formatDateStrUtc(appeal.receiptDate, 'YYYY-MM-DD');

if (!task.closed_at) {
completeDiv = <React.Fragment>
Expand Down Expand Up @@ -282,6 +313,9 @@ class NonCompDispositions extends React.PureComponent {
value={decisionDate}
onChange={this.handleDecisionDate}
readOnly={disableIssueFields}
minDate={receiptDate}
errorMessage={this.state.errorMessage}
noFutureDates
type="date"
/>
</InlineForm>
Expand Down
11 changes: 8 additions & 3 deletions client/app/styles/_noncomp.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,23 @@ $validation-error-color: #cd2026;
margin: 2rem -2rem;

.cf-inline-form {
line-height: 2em;
line-height: 2.5em;

.usa-input-error-message {
font-weight: 500;
font-weight: bold;
padding-left: 1rem;
}

.cf-date-error {
input {
border: 1px solid $color-secondary-dark;
border: 2px solid $color-secondary-dark;
}
}
}

.cf-form-textinput {
margin-top: 0;
}
}

.cf-review-details {
Expand Down
4 changes: 4 additions & 0 deletions client/app/util/ValidatorsUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ const ValidatorsUtil = {
return value && Date.parse(value) > new Date();
},

dateBeforeMinimum(value, min) {
return Date.parse(value) < Date.parse(min);
},

validSSN: (input) => input.match(/\d{9}/) || input.match(/\d{3}-\d{2}-\d{4}$/),
validFileNum: (input) => input.match(/\d{7,8}$/),
validDocketNum: (input) => input.match(/\d{6}-{1}\d+$/),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ exports[`DateSelector renders correctly 1`] = `
class="cf-form-textinput"
id="date1"
max="9999-12-31"
min="0000-01-01"
name="date1"
placeholder="mm/dd/yyyy"
type="text"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Object {
class="hearing-day-date"
id="hearingDate"
max="9999-12-31"
min="0000-01-01"
name="hearingDate"
placeholder="mm/dd/yyyy"
type="date"
Expand Down Expand Up @@ -244,6 +245,7 @@ Object {
class="hearing-day-date"
id="hearingDate"
max="9999-12-31"
min="0000-01-01"
name="hearingDate"
placeholder="mm/dd/yyyy"
type="date"
Expand Down Expand Up @@ -511,6 +513,7 @@ Object {
class="hearing-day-date"
id="hearingDate"
max="9999-12-31"
min="0000-01-01"
name="hearingDate"
placeholder="mm/dd/yyyy"
type="date"
Expand Down Expand Up @@ -1122,6 +1125,7 @@ Object {
class="hearing-day-date"
id="hearingDate"
max="9999-12-31"
min="0000-01-01"
name="hearingDate"
placeholder="mm/dd/yyyy"
type="date"
Expand Down Expand Up @@ -1790,6 +1794,7 @@ Object {
class="hearing-day-date"
id="hearingDate"
max="9999-12-31"
min="0000-01-01"
name="hearingDate"
placeholder="mm/dd/yyyy"
type="date"
Expand Down Expand Up @@ -2401,6 +2406,7 @@ Object {
class="hearing-day-date"
id="hearingDate"
max="9999-12-31"
min="0000-01-01"
name="hearingDate"
placeholder="mm/dd/yyyy"
type="date"
Expand Down Expand Up @@ -3066,6 +3072,7 @@ exports[`AddHearingDay Matches snapshot with default props 1`] = `
class="hearing-day-date"
id="hearingDate"
max="9999-12-31"
min="0000-01-01"
name="hearingDate"
placeholder="mm/dd/yyyy"
type="date"
Expand Down
Loading

0 comments on commit dc9c19c

Please sign in to comment.