Skip to content
This repository has been archived by the owner on Apr 5, 2024. It is now read-only.

VAR-73 | show warning when select disabled slot by mistake #930

Merged
merged 1 commit into from
May 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import moment from 'moment';
import first from 'lodash/first';
import last from 'lodash/last';
import orderBy from 'lodash/orderBy';
import debounce from 'lodash/debounce';

import { addNotification } from 'actions/notificationsActions';
import {
Expand Down Expand Up @@ -150,12 +151,12 @@ export class UnconnectedReservationCalendarContainer extends Component {
const isOpen = Boolean(timeSlots.length);
const showTimeSlots = isOpen && !reservingIsRestricted(resource, date);
const selectedDateSlots = this.getSelectedDateSlots(timeSlots, selected);

return (
<div className="reservation-calendar">
{showTimeSlots && (
<TimeSlots
addNotification={actions.addNotification}
addNotification={debounce(actions.addNotification, 100)}
// TODO: Im a h@ck, remove me
isAdmin={isAdmin}
isEditing={isEditing}
isFetching={isFetchingResource}
Expand Down
52 changes: 39 additions & 13 deletions app/pages/resource/reservation-calendar/time-slots/TimeSlot.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import { padLeft } from 'utils/timeUtils';
class TimeSlot extends PureComponent {
static propTypes = {
addNotification: PropTypes.func.isRequired,
// eslint-disable-next-line react/no-unused-prop-types
isDisabled: PropTypes.bool,
isAdmin: PropTypes.bool.isRequired,
showClear: PropTypes.bool.isRequired,
isHighlighted: PropTypes.bool.isRequired,
isLoggedIn: PropTypes.bool.isRequired,
// eslint-disable-next-line react/no-unused-prop-types
isSelectable: PropTypes.bool.isRequired,
isUnderMinPeriod: PropTypes.bool.isRequired,
onClear: PropTypes.func.isRequired,
Expand All @@ -32,9 +34,34 @@ class TimeSlot extends PureComponent {
isDisabled: false,
}

static getDerivedStateFromProps(prop) {
const {
slot, resource, isDisabled, isSelectable, selected, isLoggedIn
} = prop;
const isPast = new Date(slot.end) < new Date();
const isReservable = (resource.reservableAfter
&& moment(slot.start).isBefore(resource.reservableAfter));
const disabled = isDisabled
|| !isLoggedIn
|| (!isSelectable && !selected)
|| !resource.userPermissions.canMakeReservations
|| isReservable
|| (!slot.editing && (slot.reserved || isPast));

return {
disabled,
isPast
};
}

constructor(props) {
super(props);
this.timeSlotRef = React.createRef();

this.state = {
disabled: false,
isPast: false,
};
}

componentDidMount() {
Expand All @@ -43,6 +70,15 @@ class TimeSlot extends PureComponent {
}
}

componentDidUpdate() {
const { selected } = this.props;

if (selected && selected === this.state.disabled) {
this.renderMinPeriodWarning();
this.props.onClear();
}
}

getReservationInfoNotification(isLoggedIn, resource, slot, t) {
if (new Date(slot.end) < new Date() || slot.reserved) {
return null;
Expand Down Expand Up @@ -104,28 +140,18 @@ class TimeSlot extends PureComponent {

render() {
const {
isDisabled,
isAdmin,
showClear,
isHighlighted,
isLoggedIn,
isSelectable,
onClear,
onMouseEnter,
onMouseLeave,
resource,
selected,
slot,
} = this.props;
const isPast = new Date(slot.end) < new Date();
const isReservable = (resource.reservableAfter
&& moment(slot.start).isBefore(resource.reservableAfter));
const disabled = isDisabled
|| !isLoggedIn
|| (!isSelectable && !selected)
|| !resource.userPermissions.canMakeReservations
|| isReservable
|| (!slot.editing && (slot.reserved || isPast));

const { disabled, isPast } = this.state;

const reservation = slot.reservation;
const isOwnReservation = reservation && reservation.isOwn;
const start = new Date(slot.start);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,8 @@ class TimeSlots extends Component {
return null;
}
const slot = timeSlots[0];
const lastSlot = timeSlots[timeSlots.length - 2];
const lastSlot = timeSlots[timeSlots.length - 1];
// last slot is selectable slot, which is slot before last slot in array

const placeholderSize = timeSlotPlaceholderSizes[index];

const slotDate = moment(slot.start).format(constants.DATE_FORMAT);
Expand All @@ -172,9 +171,7 @@ class TimeSlots extends Component {
)}

{timeSlots.map((timeSlot) => {
const isUnderMinPeriod = utils.isUnderMinPeriod(
selected, timeSlot, lastSlot, resource.minPeriod
);
const isUnderMinPeriod = utils.isUnderMinPeriod(timeSlot, lastSlot, resource.minPeriod);

if (!lastSelectableFound && selected.length && timeSlot.reserved) {
lastSelectableFound = utils.isSlotAfterSelected(timeSlot, selected);
Expand Down
8 changes: 3 additions & 5 deletions app/pages/resource/reservation-calendar/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,22 +120,20 @@ function isHighlighted(slot, selected, hovered) {
* by adding minPeriod to slot start time
* and compare with last slot end time
*
* @param {Object} selected
* @param {Object} slot
* @param {Object} lastSlot
* @param {String | undefined} minPeriod: minPeriod limit, usuall HH:MM:SS
* @returns
*/
function isUnderMinPeriod(selected, slot, lastSlot, minPeriod) {
if (!selected || !slot || !lastSlot) {
function isUnderMinPeriod(slot, lastSlot, minPeriod) {
if (!slot || !lastSlot) {
return false;
}

if (!slot.end || !lastSlot.end) {
return false;
}

if (!selected.length && minPeriod) {
if (minPeriod) {
const minPeriodInMinutes = moment.duration(minPeriod).asMinutes();
return moment(slot.start).add(minPeriodInMinutes, 'minutes') > (moment(lastSlot.end));
}
Expand Down
26 changes: 12 additions & 14 deletions app/pages/resource/reservation-calendar/utils.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ describe('pages/resource/reservation-calendar/utils', () => {
});

describe('isUnderMinPeriod', () => {
const minPeriod = '1:00:00';
const minPeriod = '2:00:00';
const lastSlot = {
start: '2015-10-10T15:00:00Z',
end: '2015-10-10T15:30:00Z',
Expand All @@ -206,26 +206,24 @@ describe('pages/resource/reservation-calendar/utils', () => {
};

test('return false if required data is missing, wont throw error', () => {
const noLastSlot = utils.isUnderMinPeriod(selected, slot, undefined, minPeriod);
const noStartSlot = utils.isUnderMinPeriod(selected, undefined, lastSlot, minPeriod);
const noSelected = utils.isUnderMinPeriod(undefined, slot, lastSlot, minPeriod);
const noLastSlot = utils.isUnderMinPeriod(slot, undefined, minPeriod);
const noStartSlot = utils.isUnderMinPeriod(undefined, lastSlot, minPeriod);

expect(noLastSlot).toBeFalsy();
expect(noStartSlot).toBeFalsy();
expect(noSelected).toBeFalsy();
});
test('returns false if minPeriod is not defined', () => {
const actual = utils.isUnderMinPeriod(selected);
const actual = utils.isUnderMinPeriod(slot, lastSlot);
expect(actual).toBe(false);
});

test('returns false if minPeriod is defined but start time slot already selected (allow time slot to be selected if start time is already selected)', () => {
const actual = utils.isUnderMinPeriod(selected, null, null, minPeriod);
const actual = utils.isUnderMinPeriod(null, null, minPeriod);
expect(actual).toBe(false);
});

test('return false if its safe to select slot', () => {
const actual = utils.isUnderMinPeriod(selected, slot, lastSlot, minPeriod);
const actual = utils.isUnderMinPeriod(slot, lastSlot, minPeriod);
expect(actual).toBe(false);
});

Expand All @@ -234,22 +232,22 @@ describe('pages/resource/reservation-calendar/utils', () => {
start: '2015-10-10T15:00:00Z',
};

const actual = utils.isUnderMinPeriod(selected, slot, closeSlot, minPeriod);
const actual = utils.isUnderMinPeriod(slot, closeSlot, minPeriod);
expect(actual).toBe(false);
});

test('return true if selected slot will not fulfill minPeriod', () => {
const actual = utils.isUnderMinPeriod(selected, inValidSlot, lastSlot, minPeriod);
expect(actual).toBe(false);
const actual = utils.isUnderMinPeriod(inValidSlot, lastSlot, minPeriod);
expect(actual).toBe(true);
});

test('return false if selected slot fulfill minPeriod', () => {
const validSlot = {
start: '2015-10-10T14:00:00Z',
end: '2015-10-10T14:30:00Z',
start: '2015-10-10T13:30:00Z',
end: '2015-10-10T14:00:00Z',
};

const actual = utils.isUnderMinPeriod(selected, validSlot, lastSlot, minPeriod);
const actual = utils.isUnderMinPeriod(validSlot, lastSlot, minPeriod);
expect(actual).toBe(false);
});
});
Expand Down