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

Commit 4bb8c1f

Browse files
committed
fix: calendar drag with min duration > 30
1 parent bb4e21c commit 4bb8c1f

5 files changed

Lines changed: 94 additions & 72 deletions

File tree

apps/ui/components/reservation-unit/utils.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,15 +107,15 @@ const getAvailableTimesForDay = ({
107107
const endDate = addMinutes(startDate, duration ?? 0);
108108
const startTime = new Date(start);
109109
startTime.setHours(timeHours, timeMinutes, 0, 0);
110-
return isReservationReservable({
110+
const isReservable = isReservationReservable({
111111
reservationUnit,
112112
activeApplicationRounds,
113113
start: startDate,
114114
end: endDate,
115115
skipLengthCheck: false,
116-
}) && !isBefore(startDate, startTime)
117-
? n.label
118-
: null;
116+
});
117+
118+
return isReservable && !isBefore(startDate, startTime) ? n.label : null;
119119
})
120120
.filter((n): n is NonNullable<typeof n> => n != null);
121121
};
@@ -190,7 +190,9 @@ const isSlotReservable = (
190190
activeApplicationRounds?: RoundPeriod[],
191191
skipLengthCheck = false
192192
): boolean => {
193-
if (!reservationUnit || !activeApplicationRounds) return false;
193+
if (!reservationUnit || !activeApplicationRounds) {
194+
return false;
195+
}
194196
return isReservationReservable({
195197
reservationUnit,
196198
activeApplicationRounds,

apps/ui/components/reservation/EditStep0.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,12 +266,10 @@ const EditStep0 = ({
266266
: undefined;
267267

268268
const bufferTimeBefore =
269-
reservationUnit?.bufferTimeBefore != null &&
270269
reservationUnit.bufferTimeBefore !== 0
271270
? reservationUnit.bufferTimeBefore.toString()
272271
: reservationBufferTimeBefore;
273272
const bufferTimeAfter =
274-
reservationUnit?.bufferTimeAfter != null &&
275273
reservationUnit.bufferTimeAfter !== 0
276274
? reservationUnit.bufferTimeAfter.toString()
277275
: reservationBufferTimeAfter;

apps/ui/modules/reservation.ts

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,9 @@ export const getNormalizedReservationOrderStatus = (
217217
return null;
218218
};
219219

220-
export const isReservationReservable = ({
220+
/// NOTE don't return [boolean, string] causes issues in TS / JS
221+
/// instead break this function into cleaner separate functions
222+
export function isReservationReservable({
221223
reservationUnit,
222224
activeApplicationRounds,
223225
start,
@@ -229,7 +231,7 @@ export const isReservationReservable = ({
229231
start: Date;
230232
end: Date;
231233
skipLengthCheck: boolean;
232-
}): boolean => {
234+
}): boolean {
233235
if (!reservationUnit) {
234236
return false;
235237
}
@@ -297,17 +299,27 @@ export const isReservationReservable = ({
297299
) {
298300
return false;
299301
}
302+
300303
if (
301-
(!skipLengthCheck &&
302-
!isReservationLongEnough(start, end, minReservationDuration ?? 0)) ||
303-
!isReservationShortEnough(start, end, maxReservationDuration ?? 0) ||
304-
doReservationsCollide({ start, end }, reservationsArr)
304+
!skipLengthCheck &&
305+
!isReservationLongEnough(start, end, minReservationDuration ?? 0)
305306
) {
306307
return false;
307308
}
308309

310+
if (
311+
!skipLengthCheck &&
312+
!isReservationShortEnough(start, end, maxReservationDuration ?? 0)
313+
) {
314+
return false;
315+
}
316+
317+
if (doReservationsCollide({ start, end }, reservationsArr)) {
318+
return false;
319+
}
320+
309321
return true;
310-
};
322+
}
311323

312324
export const isReservationConfirmed = (reservation: ReservationNode): boolean =>
313325
reservation.state === "CONFIRMED";
@@ -323,7 +335,10 @@ export type CanReservationBeChangedProps = {
323335
activeApplicationRounds?: RoundPeriod[];
324336
};
325337

326-
// TODO disable undefined from reservation and reservationUnit
338+
/// NOTE [boolean, string] causes issues in TS / JS
339+
/// ![false] === ![true] === false, with no type errors
340+
/// either refactor the return value or add lint rules to disable ! operator
341+
/// TODO disable undefined from reservation and reservationUnit
327342
export const canReservationTimeBeChanged = ({
328343
reservation,
329344
newReservation,
@@ -363,23 +378,25 @@ export const canReservationTimeBeChanged = ({
363378
return [false, "RESERVATION_MODIFICATION_NOT_ALLOWED"];
364379
}
365380

366-
if (reservation && newReservation) {
381+
if (newReservation) {
367382
// new reservation is free
368383
if (!isReservationFreeOfCharge(newReservation)) {
369384
return [false, "RESERVATION_MODIFICATION_NOT_ALLOWED"];
370385
}
371386

387+
if (reservationUnit == null) {
388+
return [false, "RESERVATION_UNIT_NOT_FOUND"];
389+
}
390+
372391
// new reservation is valid
373-
if (
374-
reservationUnit != null &&
375-
!isReservationReservable({
376-
reservationUnit,
377-
activeApplicationRounds,
378-
start: new Date(newReservation.begin),
379-
end: new Date(newReservation.end),
380-
skipLengthCheck: false,
381-
})
382-
) {
392+
const isReservable = isReservationReservable({
393+
reservationUnit,
394+
activeApplicationRounds,
395+
start: new Date(newReservation.begin),
396+
end: new Date(newReservation.end),
397+
skipLengthCheck: false,
398+
});
399+
if (!isReservable) {
383400
return [false, "RESERVATION_TIME_INVALID"];
384401
}
385402
}

apps/ui/modules/reservationUnit.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -381,16 +381,14 @@ export function getPossibleTimesForDay(
381381
const [slotH, slotM] = span.split(":").map(Number);
382382
const slotDate = new Date(date);
383383
slotDate.setHours(slotH, slotM, 0, 0);
384-
return (
385-
slotDate >= new Date() &&
386-
isReservationReservable({
387-
reservationUnit,
388-
activeApplicationRounds,
389-
start: slotDate,
390-
end: addMinutes(slotDate, durationValue),
391-
skipLengthCheck: false,
392-
})
393-
);
384+
const isReservable = isReservationReservable({
385+
reservationUnit,
386+
activeApplicationRounds,
387+
start: slotDate,
388+
end: addMinutes(slotDate, durationValue),
389+
skipLengthCheck: false,
390+
});
391+
return slotDate >= new Date() && isReservable;
394392
})
395393
.map((time) => ({ label: time, value: time }));
396394
}

apps/ui/pages/reservation-unit/[id].tsx

Lines changed: 43 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ const ReservationUnit = ({
468468
searchUIDate != null && isValidDate(searchUIDate)
469469
? searchDate ?? ""
470470
: defaultDateString,
471-
duration: searchDuration ?? minReservationDurationMinutes,
471+
duration: Math.max(searchDuration ?? 0, minReservationDurationMinutes),
472472
time: searchTime ?? getTimeString(defaultDate),
473473
};
474474

@@ -519,16 +519,18 @@ const ReservationUnit = ({
519519
const [hours, minutes] = timeValue.split(":").map(Number);
520520
start.setHours(hours, minutes, 0, 0);
521521
const end = addMinutes(start, durationValue);
522+
const isReservable = isReservationReservable({
523+
reservationUnit,
524+
activeApplicationRounds,
525+
start,
526+
end,
527+
skipLengthCheck: false,
528+
});
529+
522530
return {
523531
start,
524532
end,
525-
isReservable: isReservationReservable({
526-
reservationUnit,
527-
activeApplicationRounds,
528-
start,
529-
end,
530-
skipLengthCheck: false,
531-
}),
533+
isReservable,
532534
durationMinutes: durationValue,
533535
};
534536
}, [
@@ -639,23 +641,28 @@ const ReservationUnit = ({
639641
return false;
640642
}
641643

642-
if (
643-
!isReservationReservable({
644-
reservationUnit,
645-
activeApplicationRounds,
646-
start,
647-
end,
648-
skipLengthCheck: false,
649-
})
650-
) {
644+
// the next check is going to systematically fail unless the times are at least minReservationDuration apart
645+
const { minReservationDuration } = reservationUnit;
646+
const minEnd = addSeconds(start, minReservationDuration ?? 0);
647+
const newEnd = new Date(Math.max(end.getTime(), minEnd.getTime()));
648+
649+
const isReservable = isReservationReservable({
650+
reservationUnit,
651+
activeApplicationRounds,
652+
start,
653+
end: newEnd,
654+
skipLengthCheck: false,
655+
});
656+
657+
if (!isReservable) {
651658
return false;
652659
}
653660

654661
// Limit the duration to the max reservation duration
655662
// TODO should be replaced with a utility function that is properly named
656663
const newReservation = getNewReservation({
657664
start,
658-
end,
665+
end: newEnd,
659666
reservationUnit,
660667
});
661668

@@ -698,15 +705,14 @@ const ReservationUnit = ({
698705
? addSeconds(start, reservationUnit?.minReservationDuration ?? 0)
699706
: new Date(end);
700707

701-
if (
702-
!isReservationReservable({
703-
reservationUnit,
704-
activeApplicationRounds,
705-
start,
706-
end: normalizedEnd,
707-
skipLengthCheck: false,
708-
})
709-
) {
708+
const isReservable = isReservationReservable({
709+
reservationUnit,
710+
activeApplicationRounds,
711+
start,
712+
end: normalizedEnd,
713+
skipLengthCheck: false,
714+
});
715+
if (!isReservable) {
710716
return false;
711717
}
712718

@@ -749,16 +755,17 @@ const ReservationUnit = ({
749755
end: focusSlot?.end,
750756
state: "INITIAL",
751757
};
758+
const isReservable = isReservationReservable({
759+
reservationUnit,
760+
activeApplicationRounds,
761+
start: focusSlot?.start,
762+
end: focusSlot?.end,
763+
skipLengthCheck: false,
764+
});
765+
752766
const shouldDisplayFocusSlot =
753-
focusSlot?.start != null &&
754-
focusSlot?.end != null &&
755-
isReservationReservable({
756-
reservationUnit,
757-
activeApplicationRounds,
758-
start: focusSlot?.start,
759-
end: focusSlot?.end,
760-
skipLengthCheck: false,
761-
});
767+
focusSlot?.start != null && focusSlot?.end != null && isReservable;
768+
762769
return [
763770
...existingReservations,
764771
...(shouldDisplayFocusSlot ? [focusEvent] : []),

0 commit comments

Comments
 (0)