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

Commit a5fd9e4

Browse files
authored
TILA-2597: Check recurring list against buffers (#679)
When creating a recurring reservation check both the selected and the existing reservation buffers.
1 parent a0a7247 commit a5fd9e4

4 files changed

Lines changed: 79 additions & 34 deletions

File tree

admin-ui/src/component/ReservationsList.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ type NewReservationListItem = {
1313
buttons?: React.ReactNode;
1414
isRemoved?: boolean;
1515
isOverlapping?: boolean;
16+
buffers?: {
17+
before?: number;
18+
after?: number;
19+
};
1620
};
1721

1822
type Props = {

admin-ui/src/component/my-units/MyUnitRecurringReservation/MyUnitRecurringReservationForm.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -201,10 +201,11 @@ const MyUnitRecurringReservationForm = ({ reservationUnits }: Props) => {
201201
const translateError = (errorMsg?: string) =>
202202
errorMsg ? t(`reservationForm:errors.${errorMsg}`) : "";
203203

204-
const newReservations = useMultipleReservation(
204+
const newReservations = useMultipleReservation({
205205
form,
206-
reservationUnit?.reservationStartInterval
207-
);
206+
reservationUnit,
207+
interval: reservationUnit?.reservationStartInterval,
208+
});
208209

209210
const checkedReservations = useFilteredReservationList({
210211
items: newReservations.reservations,

admin-ui/src/component/my-units/MyUnitRecurringReservation/hooks.ts

Lines changed: 69 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,47 +5,63 @@ import type {
55
Query,
66
QueryReservationUnitByPkArgs,
77
QueryUnitsArgs,
8+
ReservationType,
89
ReservationUnitByPkTypeReservationsArgs,
910
ReservationUnitType,
1011
} from "common/types/gql-types";
1112
import { ReservationUnitsReservationUnitReservationStartIntervalChoices } from "common/types/gql-types";
1213
import type { UseFormReturn } from "react-hook-form";
1314
import type { RecurringReservationForm } from "app/schemas";
14-
import { addDays } from "date-fns";
15+
import { addDays, addSeconds } from "date-fns";
1516
import { generateReservations } from "./generateReservations";
1617
import { useNotification } from "../../../context/NotificationContext";
1718
import { RECURRING_RESERVATION_UNIT_QUERY } from "../queries";
1819
import { GET_RESERVATIONS_IN_INTERVAL } from "./queries";
1920
import { NewReservationListItem } from "../../ReservationsList";
20-
import { DateRange, convertToDate, isOverlapping } from "./utils";
21+
import { convertToDate, isOverlapping } from "./utils";
2122

22-
export const useMultipleReservation = (
23-
form: UseFormReturn<RecurringReservationForm>,
24-
interval: ReservationUnitsReservationUnitReservationStartIntervalChoices = ReservationUnitsReservationUnitReservationStartIntervalChoices.Interval_15Mins
25-
) => {
23+
export const useMultipleReservation = ({
24+
form,
25+
reservationUnit,
26+
interval = ReservationUnitsReservationUnitReservationStartIntervalChoices.Interval_15Mins,
27+
}: {
28+
form: UseFormReturn<RecurringReservationForm>;
29+
reservationUnit?: ReservationUnitType;
30+
interval?: ReservationUnitsReservationUnitReservationStartIntervalChoices;
31+
}) => {
2632
const { watch } = form;
2733

28-
const selectedReservationParams = watch([
29-
"startingDate",
30-
"endingDate",
31-
"startTime",
32-
"endTime",
33-
"repeatPattern",
34-
"repeatOnDays",
35-
]);
36-
3734
// NOTE useMemo is useless here, watcher already filters out unnecessary runs
38-
return generateReservations(
35+
const result = generateReservations(
3936
{
40-
startingDate: selectedReservationParams[0],
41-
endingDate: selectedReservationParams[1],
42-
startTime: selectedReservationParams[2],
43-
endTime: selectedReservationParams[3],
44-
repeatPattern: selectedReservationParams[4],
45-
repeatOnDays: selectedReservationParams[5],
37+
startingDate: watch("startingDate"),
38+
endingDate: watch("endingDate"),
39+
startTime: watch("startTime"),
40+
endTime: watch("endTime"),
41+
repeatPattern: watch("repeatPattern"),
42+
repeatOnDays: watch("repeatOnDays"),
4643
},
4744
interval
4845
);
46+
47+
const isBlocked = watch("type") === "BLOCKED";
48+
49+
return {
50+
...result,
51+
reservations: result.reservations.map((item) => ({
52+
...item,
53+
buffers: {
54+
before:
55+
watch("bufferTimeBefore") && !isBlocked
56+
? reservationUnit?.bufferTimeBefore ?? 0
57+
: 0,
58+
after:
59+
watch("bufferTimeAfter") && !isBlocked
60+
? reservationUnit?.bufferTimeAfter ?? 0
61+
: 0,
62+
},
63+
})),
64+
};
4965
};
5066

5167
// NOTE pks are integers even though the query uses strings
@@ -73,6 +89,27 @@ export const useRecurringReservationsUnits = (unitId: number) => {
7389
return { loading, reservationUnits };
7490
};
7591

92+
type TimeInterval = {
93+
begin: Date;
94+
end: Date;
95+
buffers: {
96+
before: number;
97+
after: number;
98+
};
99+
};
100+
101+
const reservationToInterval = (x: ReservationType): TimeInterval | undefined =>
102+
x.begin && x.end
103+
? {
104+
begin: new Date(x.begin),
105+
end: new Date(x.end),
106+
buffers: {
107+
before: x.bufferTimeBefore ?? 0,
108+
after: x.bufferTimeAfter ?? 0,
109+
},
110+
}
111+
: undefined;
112+
76113
export const useReservationsInInterval = ({
77114
begin,
78115
end,
@@ -113,12 +150,8 @@ export const useReservationsInInterval = ({
113150
const reservations = useMemo(
114151
() =>
115152
data?.reservationUnitByPk?.reservations
116-
?.map((x) =>
117-
x?.begin && x?.end
118-
? { begin: new Date(x.begin), end: new Date(x.end) }
119-
: undefined
120-
)
121-
?.filter((x): x is { begin: Date; end: Date } => x != null) ?? [],
153+
?.map((x) => (x ? reservationToInterval(x) : undefined))
154+
?.filter((x): x is TimeInterval => x != null) ?? [],
122155
[data]
123156
);
124157

@@ -144,15 +177,20 @@ export const useFilteredReservationList = ({
144177

145178
const isReservationInsideRange = (
146179
res: NewReservationListItem,
147-
range: DateRange
180+
range: TimeInterval
148181
) => {
149182
const startDate = convertToDate(res.date, res.startTime);
150183
const endDate = convertToDate(res.date, res.endTime);
184+
const bufferBefore = Math.max(
185+
res.buffers?.before ?? 0,
186+
range.buffers.before
187+
);
188+
const bufferAfter = Math.max(res.buffers?.after ?? 0, range.buffers.after);
151189
if (startDate && endDate) {
152190
return isOverlapping(
153191
{
154-
begin: startDate,
155-
end: endDate,
192+
begin: addSeconds(startDate, -bufferBefore),
193+
end: addSeconds(endDate, bufferAfter),
156194
},
157195
range
158196
);

admin-ui/src/component/my-units/MyUnitRecurringReservation/queries.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ export const GET_RESERVATIONS_IN_INTERVAL = gql`
3131
) {
3232
begin
3333
end
34+
bufferTimeBefore
35+
bufferTimeAfter
3436
}
3537
}
3638
}

0 commit comments

Comments
 (0)