Skip to content

Instantly share code, notes, and snippets.

@zeusdeux
Created April 7, 2020 14:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zeusdeux/125e3128c666a23ebd2632b117b6a857 to your computer and use it in GitHub Desktop.
Save zeusdeux/125e3128c666a23ebd2632b117b6a857 to your computer and use it in GitHub Desktop.
Intense validations using yupjs
const workingHoursSchema = yup
.object()
.shape(
{
startHour: yup.number().when(["startMinute", "endHour", "endMinute"], {
is: (...args: string[]) => args.reduce((acc, v) => !!v || acc, false as boolean), // really typescript :|
then: yup
.number()
.integer()
.min(0)
.max(23)
.required(),
otherwise: yup
.number()
.integer()
.min(0)
.max(23)
}),
startMinute: yup.number().when(["startHour", "endHour", "endMinute"], {
is: (...args: string[]) => args.reduce((acc, v) => !!v || acc, false as boolean),
then: yup
.number()
.integer()
.min(0)
.max(59)
.required(),
otherwise: yup
.number()
.integer()
.min(0)
.max(59)
}),
endHour: yup.number().when(["startHour", "startMinute", "endMinute"], {
is: (...args: string[]) => args.reduce((acc, v) => !!v || acc, false as boolean),
then: yup
.number()
.integer()
.min(0)
.max(23)
.required(),
otherwise: yup
.number()
.integer()
.min(0)
.max(23)
}),
endMinute: yup.number().when(["startHour", "startMinute", "endHour"], {
is: (...args: string[]) => args.reduce((acc, v) => !!v || acc, false as boolean),
then: yup
.number()
.integer()
.min(0)
.max(59)
.required(),
otherwise: yup
.number()
.integer()
.min(0)
.max(59)
})
},
[
// for more info on these: https://github.com/jquense/yup/issues/176#issuecomment-369925782
["startHour", "startMinute"],
["startHour", "endHour"],
["startHour", "endMinute"],
["startMinute", "endHour"],
["startMinute", "endMinute"],
["endHour", "endMinute"]
]
)
.test("validate-working-hours", "Start of working hours should be smaller than end", function(val) {
const workingHours = Object.values(val);
// when there are no more non-numeric values for working hours, validate end time > start time
if (workingHours.length && !workingHours.filter(v => typeof v !== "number" || Number.isNaN(v)).length) {
const startTime = Number.parseInt(`${val.startHour}${val.startMinute.toString().padEnd(2, "0")}`, 10);
const endTime = Number.parseInt(`${val.endHour}${val.endMinute.toString().padEnd(2, "0")}`, 10);
return startTime < endTime;
}
return true;
})
// this transform lets the default `initialWorkingHours` value
// which contains strings instead of numbers
// (cuz react, see comment near initialWorkingHours)
.transform((v, ov) => {
if (!Object.values(ov).filter(val => val !== "").length) {
return {};
}
return v;
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment