Skip to content

Commit

Permalink
allow staff users to select a past date in CustomDatePicker
Browse files Browse the repository at this point in the history
  • Loading branch information
glen-aot committed Dec 11, 2024
1 parent 25f684e commit ebefc55
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 57 deletions.
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,12 @@ export const ApplicationStepPage = ({
);
};

if (isInvalidApplication || !isValidApplicationStatus() || !companyId || !isPermitTypeAllowed()) {
if (
isInvalidApplication ||
!isValidApplicationStatus() ||
!companyId ||
!isPermitTypeAllowed()
) {
return <Navigate to={ERROR_ROUTES.UNEXPECTED} />;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,7 @@ export const ApplicationForm = ({
// When "Continue" button is clicked
const onContinue = async (data: ApplicationFormData) => {
const updatedViolations = await triggerPolicyValidation();
// prevent CV client continuing if there are policy engine validation errors
if (Object.keys(updatedViolations).length > 0 && !isStaffUser) {
if (Object.keys(updatedViolations).length > 0) {
return;
}

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

0 comments on commit ebefc55

Please sign in to comment.