Skip to content

Commit 2963943

Browse files
committed
Fix restrictions integration
1 parent 3b41f6b commit 2963943

File tree

4 files changed

+63
-21
lines changed

4 files changed

+63
-21
lines changed

course-matrix/backend/src/controllers/restrictionsController.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export default {
3333
}
3434

3535
// Function to construct date in local time
36-
if (!start_time && !end_time) {
36+
if (!["Restrict Day", "Days Off"].includes(type) && !start_time && !end_time) {
3737
return res
3838
.status(400)
3939
.json({ error: "Start time or end time must be provided" });
@@ -78,12 +78,6 @@ export default {
7878
endTime = restriction_end_time.toISOString().split("T")[1];
7979
}
8080

81-
if (!start_time && !end_time) {
82-
return res
83-
.status(400)
84-
.json({ error: "Start time or end time must be provided" });
85-
}
86-
8781
const { data: restrictionData, error: restrictionError } = await supabase
8882
.schema("timetable")
8983
.from("restriction")
@@ -359,7 +353,7 @@ export default {
359353
return res.status(400).json({ error: restrictionError.message });
360354
}
361355

362-
return res.status(200).send("Restriction successfully deleted");
356+
return res.status(200).json({ message: "Restriction succesfully deleted" });
363357
} catch (error) {
364358
return res.status(500).send({ error });
365359
}

course-matrix/frontend/src/api/restrictionsApiSlice.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ export const restrictionsApiSlice = apiSlice.injectEndpoints({
3030
invalidatesTags: ["Restrictions"],
3131
}),
3232
deleteRestriction: builder.mutation({
33-
query: (id) => ({
34-
url: `${TIMETABLES_URL}/restrictions/${id}`,
33+
query: (data) => ({
34+
url: `${TIMETABLES_URL}/restrictions/${data.id}`,
3535
method: "DELETE",
36+
params: data,
3637
headers: {
3738
"Content-Type": "application/json",
3839
Accept: "application/json, text/plain, */*",

course-matrix/frontend/src/pages/TimetableBuilder/Calendar.tsx

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import {
2929
useGetTimetablesQuery,
3030
useCreateTimetableMutation,
3131
} from "@/api/timetableApiSlice";
32-
import { useCreateRestrictionMutation } from "@/api/restrictionsApiSlice";
32+
import { useGetRestrictionsQuery, useCreateRestrictionMutation, useDeleteRestrictionMutation} from "@/api/restrictionsApiSlice";
3333
import { z } from "zod";
3434
import React, { useEffect, useRef } from "react";
3535
import { useGetNumberOfCourseSectionsQuery } from "@/api/coursesApiSlice";
@@ -40,14 +40,15 @@ import {
4040
} from "@/api/eventsApiSlice";
4141
import { useGetOfferingEventsQuery } from "@/api/offeringsApiSlice";
4242
import { useNavigate, useSearchParams } from "react-router-dom";
43-
import { Event, Timetable, TimetableEvents } from "@/utils/type-utils";
43+
import { Event, Timetable, TimetableEvents, Restriction } from "@/utils/type-utils";
4444
import { TimetableForm } from "@/models/timetable-form";
4545
import { getSemesterStartAndEndDates } from "@/utils/semester-utils";
4646

4747
interface CalendarProps {
4848
semester: string;
4949
selectedCourses: TimetableForm["courses"];
5050
newOfferingIds: number[];
51+
restrictions: TimetableForm["restrictions"];
5152
}
5253

5354
function parseEvent(id: number, event: Event, calendarId: string) {
@@ -71,7 +72,7 @@ function parseEvent(id: number, event: Event, calendarId: string) {
7172
}
7273

7374
const Calendar = React.memo<CalendarProps>(
74-
({ semester, selectedCourses, newOfferingIds }) => {
75+
({ semester, selectedCourses, newOfferingIds, restrictions }) => {
7576
const form = useForm<z.infer<typeof TimetableFormSchema>>();
7677

7778
const navigate = useNavigate();
@@ -83,6 +84,7 @@ const Calendar = React.memo<CalendarProps>(
8384
const [createEvent] = useCreateEventMutation();
8485
const [deleteEvent] = useDeleteEventMutation();
8586
const [createRestriction] = useCreateRestrictionMutation();
87+
const [deleteRestriction] = useDeleteRestrictionMutation();
8688

8789
const semesterStartDate = getSemesterStartAndEndDates(semester).start;
8890
const semesterEndDate = getSemesterStartAndEndDates(semester).end;
@@ -139,17 +141,26 @@ const Calendar = React.memo<CalendarProps>(
139141
},
140142
});
141143

142-
const { data: oldTimetableEvents } = useGetEventsQuery(editingTimetableId, {
144+
const { data: timetableEvents } = useGetEventsQuery(editingTimetableId, {
143145
skip: !isEditingTimetable,
144146
}) as {
145147
data: TimetableEvents;
146148
};
149+
147150
const oldOfferingIds = [
148151
...new Set(
149-
oldTimetableEvents?.courseEvents.map((event) => event.offering_id),
152+
timetableEvents?.courseEvents.map((event) => event.offering_id),
150153
),
151154
].sort((a, b) => a - b);
152155

156+
const { data: restrictionsData } = useGetRestrictionsQuery(editingTimetableId, {
157+
skip: !isEditingTimetable,
158+
}) as {
159+
data: Restriction[];
160+
};
161+
162+
const oldRestrictions = restrictionsData ?? [];
163+
153164
const timetableTitleRef = useRef<HTMLInputElement>(null);
154165
const selectedCourseIds = selectedCourses.map((course) => course.id);
155166

@@ -204,7 +215,6 @@ const Calendar = React.memo<CalendarProps>(
204215
}
205216

206217
// Create restrictions for the newly created timetable
207-
const restrictions = form.getValues("restrictions") ?? [];
208218
for (const restriction of restrictions) {
209219
const restrictionObject = {
210220
calendar_id: newTimetableId,
@@ -259,8 +269,38 @@ const Calendar = React.memo<CalendarProps>(
259269
console.error(createError);
260270
}
261271
}
272+
262273
form.setValue("offeringIds", newOfferingIds);
263274

275+
// Delete restrictions
276+
for (const restriction of oldRestrictions) {
277+
const { error: deleteError } = await deleteRestriction({
278+
id: restriction.id,
279+
calendar_id: editingTimetableId,
280+
});
281+
if (deleteError) {
282+
console.error(deleteError);
283+
}
284+
}
285+
286+
// Create restrictions
287+
for (const restriction of restrictions) {
288+
const restrictionObject = {
289+
calendar_id: editingTimetableId,
290+
type: restriction.type,
291+
days: restriction.days,
292+
start_time: restriction.startTime,
293+
end_time: restriction.endTime,
294+
disabled: restriction.disabled,
295+
num_days: restriction.numDays,
296+
};
297+
const { error: restrictionError } =
298+
await createRestriction(restrictionObject);
299+
if (restrictionError) {
300+
console.error(restrictionError);
301+
}
302+
}
303+
264304
navigate("/home");
265305
};
266306

course-matrix/frontend/src/pages/TimetableBuilder/TimetableBuilder.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,17 @@ const TimetableBuilder = () => {
191191
form.setValue("courses", existingCourses);
192192
setLoadedCourses(true);
193193

194+
// Parse restrictions data (For startTime and endTime, we just care about the time, so we use the random date of 2025-01-01 so that the date can be parsed correctly)
195+
// We also add 1 hour (i.e. 60 * 60 * 1000 milliseconds) to the time to account for the timezone difference between the server and the client
194196
const parsedRestrictions = restrictionsData.map(
195197
(restriction: Restriction) => ({
196-
...restriction,
197-
days: JSON.parse(restriction?.days),
198-
}),
198+
days: JSON.parse(restriction?.days) as string[],
199+
disabled: restriction?.disabled,
200+
startTime: restriction?.start_time ? new Date(new Date(`2025-01-01T${restriction.start_time}.00Z`).getTime() + 60 * 60 * 1000) : undefined,
201+
endTime: restriction?.end_time ? new Date(new Date(`2025-01-01T${restriction.end_time}.00Z`).getTime() + 60 * 60 * 1000) : undefined,
202+
type: restriction?.type,
203+
numDays: restriction?.num_days,
204+
}) as z.infer<typeof RestrictionSchema>,
199205
);
200206
form.setValue("restrictions", parsedRestrictions);
201207
setLoadedRestrictions(true);
@@ -380,7 +386,7 @@ const TimetableBuilder = () => {
380386
{!isEditingTimetable ||
381387
(isEditingTimetable &&
382388
loadedCourses &&
383-
loadedOfferingIds) ? (
389+
loadedOfferingIds && selectedCourses) ? (
384390
selectedCourses.map((course, index) => {
385391
return (
386392
<div key={index}>
@@ -460,7 +466,7 @@ const TimetableBuilder = () => {
460466
)}
461467
/>
462468
<div className="flex gap-2 flex-col">
463-
{enabledRestrictions.map((restric, index) => (
469+
{enabledRestrictions && enabledRestrictions.map((restric, index) => (
464470
<div
465471
key={index}
466472
className="flex p-2 justify-between bg-red-100/50 text-xs rounded-md w-[64%]"
@@ -513,6 +519,7 @@ const TimetableBuilder = () => {
513519
semester={selectedSemester}
514520
selectedCourses={selectedCourses}
515521
newOfferingIds={offeringIds}
522+
restrictions={enabledRestrictions}
516523
/>
517524
</div>
518525

0 commit comments

Comments
 (0)