Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Commit bf72bec

Browse files
committed
Added capability to inject custom validator
1 parent cbd5869 commit bf72bec

File tree

7 files changed

+47
-8
lines changed

7 files changed

+47
-8
lines changed

src/components/DateInput/index.jsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ import "./styles.module.scss";
1010

1111
const DateInput = (props) => {
1212
return (
13-
<div styleName="datepicker-wrapper">
13+
<div styleName={`datepicker-wrapper ${props.className}`}>
1414
<DatePicker
1515
dateFormat="MM/dd/yyyy"
1616
placeholderText={props.placeholder}
1717
selected={props.value}
1818
onChange={props.onChange}
1919
onBlur={props.onBlur}
20+
onCalendarClose={props.onBlur}
2021
onFocus={props.onFocus}
2122
/>
2223
</div>

src/components/DateInput/styles.module.scss

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44
& > div {
55
width: 100%;
66
}
7+
&.error {
8+
input{
9+
border-color: #fe665d;
10+
}
11+
12+
}
713
}
814

915
.datepicker-wrapper > div:nth-child(2) > div:nth-child(2) {

src/components/FormField/index.jsx

+8-1
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,16 @@ import ReactSelect from "../../components/ReactSelect";
1313
import DateInput from "../../components/DateInput";
1414
import "./styles.module.scss";
1515

16+
const updateInput = (field, input) => {
17+
field.input = input;
18+
}
19+
1620
const FormField = ({ field, isGroupField }) => {
1721
return (
1822
<Field name={field.name}>
1923
{({ input, meta }) => (
2024
<div styleName={isGroupField ? "field-group-field" : ""}>
25+
{updateInput(field, input)}
2126
{ !field.readonly && (
2227
<label
2328
styleName={
@@ -71,6 +76,7 @@ const FormField = ({ field, isGroupField }) => {
7176
onChange={input.onChange}
7277
onBlur={input.onBlur}
7378
onFocus={input.onFocus}
79+
className={meta.error && meta.touched ? "error" : ""}
7480
/>
7581
)}
7682
{field.type === FORM_FIELD_TYPE.SELECT && (
@@ -83,7 +89,7 @@ const FormField = ({ field, isGroupField }) => {
8389
onFocus={input.onFocus}
8490
/>
8591
)}
86-
{field.isRequired && meta.error && meta.touched && (
92+
{(field.isRequired || field.customValidator) && meta.error && meta.touched && (
8793
<div styleName="field-error">{meta.error}</div>
8894
)}
8995
</div>
@@ -111,6 +117,7 @@ FormField.prototype = {
111117
maxLength: PT.number,
112118
styleName: PT.string,
113119
readonly: PT.string,
120+
input: PT.object
114121
})
115122
).isRequired,
116123
isGroupField: PT.bool,

src/components/TCForm/index.jsx

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ TCForm.propTypes = {
106106
label: PT.string,
107107
type: PT.oneOf(Object.values(FORM_FIELD_TYPE)).isRequired,
108108
isRequired: PT.bool,
109+
customValidator: PT.func,
109110
validationMessage: PT.string,
110111
name: PT.string.isRequired,
111112
component: PT.element,

src/components/TCForm/utils.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,19 @@ export const createConfigurationObject = (fields) => {
6868
* @returns {Function} configuration object
6969
*/
7070
export const getValidator = (fields) => {
71-
return (values) => {
71+
return (values, inputs) => {
7272
const errors = {};
7373
fields
74-
.filter((f) => f.isRequired)
74+
.filter((f) => f.isRequired || f.customValidator)
7575
.forEach((f) => {
76-
if (!values[f.name]) {
76+
if (f.isRequired && !values[f.name]) {
7777
errors[f.name] = f.validationMessage;
78+
}else if (f.customValidator){
79+
const error = f.customValidator(f, fields, values);
80+
if(error){
81+
errors[f.name] = error;
82+
f.input.onBlur();
83+
}
7884
}
7985
});
8086
return errors;

src/components/TextInput/index.jsx

+2-3
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ import "./styles.module.scss";
1010
function TextInput(props) {
1111
return (
1212
<input
13-
styleName={`TextInput ${props.className} ${
14-
props.readonly ? "readonly" : ""
15-
}`}
13+
styleName={`TextInput ${props.className} ${props.readonly ? "readonly" : ""}`}
1614
maxLength={props.maxLength}
1715
min={props.minValue}
1816
onChange={(event) => {
@@ -33,6 +31,7 @@ function TextInput(props) {
3331
readOnly={props.readonly ?? false}
3432
onBlur={props.onBlur}
3533
onFocus={props.onFocus}
34+
step={props.type === "number" ? ".01" : null}
3635
/>
3736
);
3837
}

src/routes/ResourceBookingForm/utils.js

+19
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*
44
* utility class
55
*/
6+
import moment from 'moment';
67
import {
78
STATUS_OPTIONS,
89
FORM_ROW_TYPE,
@@ -45,12 +46,30 @@ export const getEditResourceBookingConfig = (onSubmit) => {
4546
type: FORM_FIELD_TYPE.DATE,
4647
name: "startDate",
4748
placeholder: "Start Date",
49+
customValidator: (field, fields, values) => {
50+
const startDate = values[field.name];
51+
const endDate = values['endDate'];
52+
if(startDate && endDate && moment(endDate).startOf('day').isBefore(moment(startDate).startOf('day'))){
53+
return 'Start Date should not be after End Date';
54+
}
55+
return null;
56+
}
4857
},
4958
{
5059
label: "End Date",
5160
type: FORM_FIELD_TYPE.DATE,
5261
name: "endDate",
5362
placeholder: "End Date",
63+
customValidator: (field, fields, values) => {
64+
const endDate = values[field.name];
65+
const startDate = values['startDate'];
66+
if(startDate && endDate && moment(endDate).startOf('day').isBefore(moment(startDate).startOf('day'))){
67+
return 'End Date should not be before Start Date';
68+
}else if(!startDate && endDate){
69+
return 'End Date should not be before Start Date';
70+
}
71+
return null;
72+
}
5473
},
5574
{
5675
label: "Status",

0 commit comments

Comments
 (0)