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

ORV2-3201 - Allow Staff to use date picker to select start date in past #1711

Merged
merged 5 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { DatePicker, DateValidationError } from "@mui/x-date-pickers";
import { Dayjs } from "dayjs";
import dayjs, { Dayjs } from "dayjs";
import { Box, FormControl, FormHelperText, FormLabel } from "@mui/material";
import {
useState,
useEffect,
} from "react";
import { useState, useEffect } from "react";

import {
FieldValues,
Expand All @@ -18,13 +15,18 @@ import {
} from "react-hook-form";

import "./CustomDatePicker.scss";
import { Nullable, ORBC_FormTypes, RequiredOrNull } from "../../../types/common";
import {
Nullable,
ORBC_FormTypes,
RequiredOrNull,
} from "../../../types/common";
import { getStartOfDate, now } from "../../../helpers/formatDate";
import { getErrorMessage } from "../CustomFormComponents";
import {
invalidDate,
invalidMaxStartDate,
invalidPastStartDate,
warnPastStartDate,
} from "../../../helpers/validationMessages";

export const PAST_START_DATE_STATUSES = {
Expand All @@ -34,7 +36,7 @@ export const PAST_START_DATE_STATUSES = {
} as const;

export type PastStartDateStatus =
typeof PAST_START_DATE_STATUSES[keyof typeof PAST_START_DATE_STATUSES];
(typeof PAST_START_DATE_STATUSES)[keyof typeof PAST_START_DATE_STATUSES];

// Properties of the onrouteBC customized Date Picker MUI component/
export interface CustomDatePickerProps<T extends FieldValues> {
Expand Down Expand Up @@ -101,25 +103,28 @@ export const CustomDatePicker = <T extends ORBC_FormTypes>({
validate: {
...rules.validate,
disablePast: (value: Nullable<Dayjs>) => {
return pastStartDateStatus !== PAST_START_DATE_STATUSES.FAIL
|| (dateError !== "disablePast" && dateError !== "minDate")
|| !value
|| (value.isAfter(getStartOfDate(now())))
|| (value.isSame(getStartOfDate(now())))
|| invalidPastStartDate();
return (
pastStartDateStatus !== PAST_START_DATE_STATUSES.FAIL ||
(dateError !== "disablePast" && dateError !== "minDate") ||
!value ||
value.isAfter(getStartOfDate(now())) ||
value.isSame(getStartOfDate(now())) ||
invalidPastStartDate()
);
},
maxDate: (value: Nullable<Dayjs>) => {
return !maxDaysInFuture
|| (dateError !== "maxDate")
|| !maxDate
|| !value
|| (value.isBefore(getStartOfDate(maxDate)))
|| (value.isSame(getStartOfDate(maxDate)))
|| invalidMaxStartDate(maxDaysInFuture);
return (
!maxDaysInFuture ||
dateError !== "maxDate" ||
!maxDate ||
!value ||
value.isBefore(getStartOfDate(maxDate)) ||
value.isSame(getStartOfDate(maxDate)) ||
invalidMaxStartDate(maxDaysInFuture)
);
},
invalidDate: () => {
return (dateError !== "invalidDate")
|| invalidDate();
return dateError !== "invalidDate" || invalidDate();
},
},
};
Expand All @@ -137,12 +142,13 @@ export const CustomDatePicker = <T extends ORBC_FormTypes>({
// Revalidate whenever the date picker error is updated (new error or no errors)
trigger(name);
}, [dateError]);

const rulesViolationMessage = getErrorMessage(errors, name);
const startDateWarningMessage =
(dateError === "minDate" || dateError === "disablePast")
&& (pastStartDateStatus === PAST_START_DATE_STATUSES.WARNING)
? invalidPastStartDate() : null;
dayjs().isAfter(value, "day") &&
pastStartDateStatus === PAST_START_DATE_STATUSES.WARNING
? warnPastStartDate()
: null;

return (
<Box className={`custom-date-picker ${className ? className : ""}`}>
Expand Down Expand Up @@ -173,9 +179,13 @@ export const CustomDatePicker = <T extends ORBC_FormTypes>({
disabled={disabled}
readOnly={readOnly}
onChange={(value) => handleDateChange(value)}
disablePast={pastStartDateStatus !== PAST_START_DATE_STATUSES.ALLOWED}
disablePast={
pastStartDateStatus === PAST_START_DATE_STATUSES.FAIL
}
maxDate={maxDate}
onError={(dateValidationError) => setDateError(dateValidationError)}
onError={(dateValidationError) =>
setDateError(dateValidationError)
}
slotProps={{
textField: {
inputProps: {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/common/constants/validation_messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
"defaultMessage": "Your date is not valid",
"start": {
"past": {
"defaultMessage": "Start Date cannot be in the past."
"defaultMessage": "Start Date cannot be in the past.",
"warningMessage": "Start Date is in the past."
},
"max": {
"messageTemplate": "Start Date must be within :max days.",
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/common/helpers/validationMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ export const invalidDate = () => validationMessages.date.defaultMessage;
export const invalidPastStartDate = () =>
validationMessages.date.start.past.defaultMessage;

export const warnPastStartDate = () =>
validationMessages.date.start.past.warningMessage;

export const invalidMaxStartDate = (max: number) => {
const { messageTemplate, placeholders } = validationMessages.date.start.max;
return replacePlaceholders(messageTemplate, placeholders, max);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import { Loading } from "../../../../common/pages/Loading";
import { ApplicationInQueueReview } from "../../../queue/components/ApplicationInQueueReview";
import { useApplicationForStepsQuery } from "../../hooks/hooks";
import { PERMIT_STATUSES } from "../../types/PermitStatus";
import { applyWhenNotNullable, getDefaultRequiredVal } from "../../../../common/helpers/util";
import {
applyWhenNotNullable,
getDefaultRequiredVal,
} from "../../../../common/helpers/util";
import { useFeatureFlagsQuery } from "../../../../common/hooks/hooks";
import {
DEFAULT_PERMIT_TYPE,
Expand Down Expand Up @@ -54,8 +57,8 @@ export const ApplicationStepPage = ({

const companyId: number = getDefaultRequiredVal(
0,
applyWhenNotNullable(id => Number(id), companyIdParam),
applyWhenNotNullable(id => Number(id), getCompanyIdFromSession()),
applyWhenNotNullable((id) => Number(id), companyIdParam),
applyWhenNotNullable((id) => Number(id), getCompanyIdFromSession()),
);

const { data: featureFlags } = useFeatureFlagsQuery();
Expand Down Expand Up @@ -98,14 +101,9 @@ export const ApplicationStepPage = ({

// Currently onRouteBC only handles TROS and TROW permits, and STOS only if feature flag is enabled
const isPermitTypeAllowed = () => {
const allowedPermitTypes: string[] = enableSTOS ? [
PERMIT_TYPES.TROS,
PERMIT_TYPES.TROW,
PERMIT_TYPES.STOS,
] : [
PERMIT_TYPES.TROS,
PERMIT_TYPES.TROW,
];
const allowedPermitTypes: string[] = enableSTOS
? [PERMIT_TYPES.TROS, PERMIT_TYPES.TROW, PERMIT_TYPES.STOS]
: [PERMIT_TYPES.TROS, PERMIT_TYPES.TROW];

return allowedPermitTypes.includes(applicationPermitType);
};
Expand All @@ -117,19 +115,18 @@ export const ApplicationStepPage = ({
!isInvalidApplication &&
(!applicationData?.permitStatus ||
applicationData?.permitStatus === PERMIT_STATUSES.IN_PROGRESS ||
applicationData?.permitStatus === PERMIT_STATUSES.IN_QUEUE
)
applicationData?.permitStatus === PERMIT_STATUSES.IN_QUEUE)
);
};

const renderApplicationStep = () => {
if (applicationStep === APPLICATION_STEPS.REVIEW) {
return applicationStepContext === APPLICATION_STEP_CONTEXTS.QUEUE ? (
<ApplicationInQueueReview applicationData={contextData.applicationData} />
) : (
<ApplicationReview
companyId={companyId}
<ApplicationInQueueReview
applicationData={contextData.applicationData}
/>
) : (
<ApplicationReview companyId={companyId} />
);
}

Expand All @@ -141,7 +138,13 @@ export const ApplicationStepPage = ({
);
};

if (isInvalidApplication || !isValidApplicationStatus() || !companyId || !isPermitTypeAllowed()) {
if (
isInvalidApplication ||
!isValidApplicationStatus() ||
!companyId ||
!isPermitTypeAllowed()
) {
console.error("The application cannot be displayed or edited");
return <Navigate to={ERROR_ROUTES.UNEXPECTED} />;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@ export const PermitForm = () => {
<Box className="permit-form__form">
<ApplicationDetails
permitType={permitType}
infoNumber={
isAmendAction ? permitNumber : applicationNumber
}
infoNumber={isAmendAction ? permitNumber : applicationNumber}
infoNumberType={isAmendAction ? "permit" : "application"}
createdDateTime={createdDateTime}
updatedDateTime={updatedDateTime}
Expand Down Expand Up @@ -103,7 +101,7 @@ export const PermitForm = () => {
selectedCommodityType={commodityType}
onChangeCommodityType={onChangeCommodityType}
/>

<VehicleInformationSection
permitType={permitType}
feature={feature}
Expand Down Expand Up @@ -135,10 +133,7 @@ export const PermitForm = () => {
onUpdateHighwaySequence={onUpdateHighwaySequence}
/>

<ApplicationNotesSection
feature={feature}
permitType={permitType}
/>
<ApplicationNotesSection feature={feature} permitType={permitType} />

{isAmendAction ? (
<>
Expand Down
Loading