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

Commit 2eeec1f

Browse files
authored
Merge pull request #96 from dashu-baba/issue-85
Added capability to inject custom validator
2 parents cd5941f + 4568280 commit 2eeec1f

File tree

8 files changed

+58
-10
lines changed

8 files changed

+58
-10
lines changed

src/components/DateInput/index.jsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,19 @@
66
import React from "react";
77
import PT from "prop-types";
88
import DatePicker from "react-datepicker";
9+
import cn from "classnames";
910
import "./styles.module.scss";
1011

1112
const DateInput = (props) => {
1213
return (
13-
<div styleName="datepicker-wrapper">
14+
<div styleName={cn("datepicker-wrapper", props.className)}>
1415
<DatePicker
1516
dateFormat="MM/dd/yyyy"
1617
placeholderText={props.placeholder}
1718
selected={props.value}
1819
onChange={props.onChange}
1920
onBlur={props.onBlur}
21+
onCalendarClose={props.onBlur}
2022
onFocus={props.onFocus}
2123
/>
2224
</div>
@@ -29,6 +31,7 @@ DateInput.propTypes = {
2931
placeholder: PT.string,
3032
onBlur: PT.func,
3133
onFocus: PT.func,
34+
className: PT.string
3235
};
3336

3437
export default DateInput;

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ const FormField = ({ field, isGroupField }) => {
7272
onChange={input.onChange}
7373
onBlur={input.onBlur}
7474
onFocus={input.onFocus}
75+
className={meta.error && meta.touched ? "error" : ""}
7576
/>
7677
)}
7778
{field.type === FORM_FIELD_TYPE.SELECT && (
@@ -84,7 +85,7 @@ const FormField = ({ field, isGroupField }) => {
8485
onFocus={input.onFocus}
8586
/>
8687
)}
87-
{field.isRequired && meta.error && meta.touched && (
88+
{(field.isRequired || field.customValidator) && meta.error && meta.touched && (
8889
<div styleName="field-error">{meta.error}</div>
8990
)}
9091
</div>

src/components/FormField/styles.module.scss

+3-3
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ input:read-only {
4545
font-family: "Roboto", Helvetica, Arial, sans-serif;
4646
font-weight: 400;
4747
width: 100%;
48-
height: 40px;
49-
line-height: 40px;
50-
padding: 0 10px;
48+
min-height: 40px;
49+
line-height: 20px;
50+
padding: 9px 10px;
5151
margin: 10px 0 5px;
5252
font-size: 15px;
5353
color: #ff5b52;

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

+7-2
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,15 @@ export const getValidator = (fields) => {
7171
return (values) => {
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+
}
7883
}
7984
});
8085
return errors;

src/components/TextInput/index.jsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,13 @@
55
*/
66
import React from "react";
77
import PT from "prop-types";
8+
import cn from "classnames";
89
import "./styles.module.scss";
910

1011
function TextInput(props) {
1112
return (
1213
<input
13-
styleName={`TextInput ${props.className} ${
14-
props.readonly ? "readonly" : ""
15-
}`}
14+
styleName={cn("TextInput", props.className, {"readonly": props.readonly})}
1615
maxLength={props.maxLength}
1716
min={props.minValue}
1817
onChange={(event) => {
@@ -38,6 +37,7 @@ function TextInput(props) {
3837
readOnly={props.readonly ?? false}
3938
onBlur={props.onBlur}
4039
onFocus={props.onFocus}
40+
step={props.type === "number" ? ".01" : null}
4141
/>
4242
);
4343
}

src/routes/ResourceBookingForm/utils.js

+32
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
*
44
* utility class
55
*/
6+
import moment from "moment";
7+
import _ from "lodash";
68
import {
79
STATUS_OPTIONS,
810
FORM_ROW_TYPE,
@@ -45,12 +47,42 @@ export const getEditResourceBookingConfig = (onSubmit) => {
4547
type: FORM_FIELD_TYPE.DATE,
4648
name: "startDate",
4749
placeholder: "Start Date",
50+
customValidator: (field, fields, values) => {
51+
const endDateField = _.find(fields, { name: "endDate" });
52+
const startDate = values[field.name];
53+
const endDate = values["endDate"];
54+
if (
55+
startDate &&
56+
endDate &&
57+
moment(endDate)
58+
.startOf("day")
59+
.isBefore(moment(startDate).startOf("day"))
60+
) {
61+
return "Start Date should not be after End Date";
62+
}
63+
return null;
64+
},
4865
},
4966
{
5067
label: "End Date",
5168
type: FORM_FIELD_TYPE.DATE,
5269
name: "endDate",
5370
placeholder: "End Date",
71+
customValidator: (field, fields, values) => {
72+
const startDateField = _.find(fields, { name: "startDate" });
73+
const endDate = values[field.name];
74+
const startDate = values["startDate"];
75+
if (
76+
startDate &&
77+
endDate &&
78+
moment(endDate)
79+
.startOf("day")
80+
.isBefore(moment(startDate).startOf("day"))
81+
) {
82+
return "End Date should not be before Start Date";
83+
}
84+
return null;
85+
},
5486
},
5587
{
5688
label: "Status",

0 commit comments

Comments
 (0)