const { useState, useEffect } = React;
const duration = 15;
const format = "YYYY-MM-DDTHH:mm";
const getRange = (timePart) => {
const [hour, minute] = timePart.split(':').map(pr => Number(pr));
const from = moment().startOf('day').set({
hour,
minute
});
const to = from.clone().add(duration, 'minutes');
return [from.format(format), to.format(format)];
}
const getWorkingHours = (() => {
const today = moment().startOf('day');
const from = today.set({hour: 8})
const to = today.clone().set({hour: 18})
const result = [from.format(format), to.format(format)];
return () => result
})()
const getMockReservedDate = () => {
const today = moment().startOf('day');
const from = today.set({hour: 8, minute: 10});
const to = today.clone().add(duration, 'minutes');
const result = [from.format(format), to.format(format)];
return result;
}
const App = () => {
const [reserved, setReserved] = useState([
getMockReservedDate()
]);
const [value, setValue] = useState('');
const [hasError, setError] = useState('');
const [disabled, setDisabled] = useState(false);
useEffect(() => {
moment();
}, [])
const isBetweenWorkingHours = ([from, to]) => {
const [start, end] = getWorkingHours()
const fromMomentObj = moment(from);
const toMomentObj = moment(to);
if((!fromMomentObj.isBetween(start, end)
&& !fromMomentObj.isSame(start))
||
(!toMomentObj.isBetween(start, end)
&& !toMomentObj.isSame(end))
) {
return false;
}
return true;
}
const onChange = ({target: {value}}) => {
setValue(value);
const range = getRange(value);
if(!isBetweenWorkingHours(range)) {
setError('Outside working hours');
setDisabled(true);
return;
}
for(const [from, to] of reserved) {
const fromMomentObj = moment(range[0]);
const toMomentObj = moment(range[1]);
if(fromMomentObj.isBetween(from, to) ||
toMomentObj.isBetween(from, to) ||
fromMomentObj.isSame(from) ||
toMomentObj.isSame(to)
) {
setError(`Dates overlap ${from} -> ${to}`);
setDisabled(true);
return;
}
}
setError('');
setDisabled(false);
}
const onClick = () => {
const range = getRange(value);
setReserved(reserved => [...reserved, range])
setValue('');
}
return <div>
<div>Reserved {JSON.stringify(reserved)}</div>
<div>
<input min="08:00" max="18:00" required type="time" value={value} onChange={onChange}/>
<div className={`message ${hasError ? 'error': ''}`}>{hasError}</div>
<button disabled={disabled} onClick={onClick}>Submit</button>
</div>
</div>
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
.message {
display: none;
}
.error {
display: block;
color: red;
}
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"></script>
<div id="root"></div>