import { Do } from 'fp-ts-contrib/lib/Do'
import { either, Either, right, left, getValidation } from 'fp-ts/lib/Either'
import { getMonoid } from 'fp-ts/lib/Array'
type Form = {
name: string,
startDate: string,
endDate: string,
}
type ValidatedForm = {
name: string,
start: Date,
end: Date
}
function nonEmpty(error: string, s: string): Either<string[], string> {
return s === "" ? left([error]) : right(s)
}
function isDate(error: string, dateStr: string): Either<string[], Date> {
const date = Date.parse(dateStr)
return isNaN(date) ? left([error]) : right(new Date(date))
}
function isBefore(error: string, start: Date, end: Date): Either<string[], number> {
const difference = end.getTime() - start.getTime()
return difference > 0 ? right(difference) : left([error])
}
const validateForm = (form: Form) =>
Do(getValidation(getMonoid<string>()))
.sequenceS({
nameIsNotEmpty: nonEmpty("Name cannot be empty", form.name),
start: isDate("Start date is invalid", form.startDate),
end: isDate("End date is invalid", form.endDate)
})
.bindL("lengthOfEvent", ({start, end}) =>
isBefore("Start date must be before end date.", start, end)
)
.bindL("lengthIsValid", ({lengthOfEvent}) =>
lengthOfEvent / 1000 / 60 / 30 > 1 ?
left(["The event cannot be longer than 30 minutes"])
: right(lengthOfEvent)
).return(({start, end}) => ({
start,
end,
name: form.name
}))
console.log(
validateForm({
name: "Event",
startDate: "2020-03-27T01:35:00Z",
endDate: "2020-03-27T01:45:00Z"
})
)
console.log(
validateForm({
name: "",
startDate: "asdf",
endDate: "2020-03-27T01:45:00Z"
})
)
console.log(
validateForm({
name: "Event",
startDate: "2020-03-27T01:35:00Z",
endDate: "2020-03-27T02:55:00Z"
})
)
console.log(
validateForm({
name: "Event",
startDate: "2020-03-27T08:35:00Z",
endDate: "2020-03-27T02:55:00Z"
})
)