Skip to content

Commit

Permalink
chore: Fix create, update, and delete schedules
Browse files Browse the repository at this point in the history
  • Loading branch information
mathhulk committed Oct 11, 2024
1 parent 7912f9e commit 1d9c1ec
Show file tree
Hide file tree
Showing 15 changed files with 345 additions and 185 deletions.
3 changes: 2 additions & 1 deletion apps/backend/src/modules/schedule/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ export const updateSchedule = async (
) => {
const schedule = await ScheduleModel.findOneAndUpdate(
{ _id: id, createdBy: context.user._id },
input
input,
{ new: true }
);

if (!schedule) throw new Error("Not found");
Expand Down
8 changes: 4 additions & 4 deletions apps/backend/src/modules/schedule/formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ export const formatSchedule = async (schedule: ScheduleType) => {

for (const selectedClass of schedule.classes) {
const _class = await ClassModel.findOne({
number: selectedClass.classNumber,
number: selectedClass.number,
"course.subjectArea.code": selectedClass.subject,
"course.catalogNumber.formatted": selectedClass.courseNumber,
"session.term.name": `${schedule.term.year} ${schedule.term.semester}`,
"session.term.name": `${schedule.year} ${schedule.semester}`,
}).lean();

if (!_class) continue;
Expand All @@ -33,8 +33,8 @@ export const formatSchedule = async (schedule: ScheduleType) => {
createdBy: schedule.createdBy,
public: schedule.public,
classes,
year: schedule.term.year,
semester: schedule.term.semester,
year: schedule.year,
semester: schedule.semester,
term: null,
events: schedule.events,
} as IntermediateSchedule;
Expand Down
11 changes: 6 additions & 5 deletions apps/backend/src/modules/schedule/typedefs/schedule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ const typedef = gql`
semester: String!
term: Term!
public: Boolean!
classes: [SelectedClass!]
events: [Event!]
classes: [SelectedClass!]!
events: [Event!]!
}
type Query {
schedules: [Schedule] @auth
schedule(id: String!): Schedule
schedule(id: ID!): Schedule
}
input EventInput {
Expand All @@ -44,7 +44,7 @@ const typedef = gql`
input SelectedClassInput {
subject: String!
courseNumber: String!
classNumber: String!
number: String!
sections: [String!]!
}
Expand All @@ -57,7 +57,8 @@ const typedef = gql`
input CreateScheduleInput {
name: String!
term: TermInput!
year: Int!
semester: String!
events: [EventInput!]
classes: [SelectedClassInput!]
public: Boolean
Expand Down
37 changes: 4 additions & 33 deletions apps/frontend/src/app/Schedule/index.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,16 @@
import { useState } from "react";

import { useQuery } from "@apollo/client";
import { Outlet } from "react-router";
import { useNavigate, useParams } from "react-router-dom";

import { Boundary, LoadingIndicator } from "@repo/theme";

import { GET_SCHEDULE, GetScheduleResponse, IClass, ISection } from "@/lib/api";

import { ScheduleContextType } from "./schedule";
import { useSchedule } from "@/hooks/schedules/useSchedule";
import { ScheduleIdentifier } from "@/lib/api";

export default function Schedule() {
const { scheduleId } = useParams();

const navigate = useNavigate();

const { data } = useQuery<GetScheduleResponse>(GET_SCHEDULE, {
const { data: schedule } = useSchedule(scheduleId as ScheduleIdentifier, {
onError: () => navigate("/schedules"),
variables: { id: scheduleId },
});

const [selectedSections, setSelectedSections] = useState<ISection[]>([]);
const [classes, setClasses] = useState<IClass[]>([]);
const [expanded, setExpanded] = useState<boolean[]>([]);

return data ? (
<Outlet
context={
{
selectedSections,
setSelectedSections,
classes,
setClasses,
expanded,
setExpanded,
} satisfies ScheduleContextType
}
/>
) : (
<Boundary>
<LoadingIndicator size="lg" />
</Boundary>
);
return schedule ? schedule.name : <></>;
}
79 changes: 0 additions & 79 deletions apps/frontend/src/app/Schedules/Test.tsx

This file was deleted.

41 changes: 37 additions & 4 deletions apps/frontend/src/app/Schedules/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ import { Link } from "react-router-dom";

import { Container } from "@repo/theme";

import useSchedules from "@/hooks/useSchedules";
import { useCreateSchedule } from "@/hooks/schedules/useCreateSchedule";
import { useDeleteSchedule } from "@/hooks/schedules/useDeleteSchedule";
import useSchedules from "@/hooks/schedules/useSchedules";
import { useUpdateSchedule } from "@/hooks/schedules/useUpdateSchedule";
import useUser from "@/hooks/useUser";
import { Semester } from "@/lib/api";

export default function Schedules() {
const { data: user, loading: userLoading } = useUser();
Expand All @@ -12,17 +16,46 @@ export default function Schedules() {
skip: !user,
});

const [deleteSchedule] = useDeleteSchedule();

const [updateSchedule] = useUpdateSchedule();

const [createSchedule] = useCreateSchedule();

if (userLoading || schedulesLoading) return <></>;

if (!user) return <></>;

if (schedules) {
return (
<Container>
<button
onClick={() =>
createSchedule({
name: "Test",
year: 2024,
semester: Semester.Fall,
})
}
>
Create Schedule
</button>
{schedules?.map((schedule) => (
<Link to={schedule._id} key={schedule._id}>
{schedule.name}
</Link>
<div key={schedule._id}>
<Link to={schedule._id}>{schedule.name}</Link>
<button onClick={() => deleteSchedule(schedule._id)}>
Delete Schedule
</button>
<button
onClick={() =>
updateSchedule(schedule._id, {
name: "Updated",
})
}
>
Update Schedule
</button>
</div>
))}
</Container>
);
Expand Down
11 changes: 11 additions & 0 deletions apps/frontend/src/contexts/ScheduleContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { createContext } from "react";

import { ISchedule } from "@/lib/api";

export interface ScheduleContextType {
schedule: ISchedule;
}

const ScheduleContext = createContext<ScheduleContextType | null>(null);

export default ScheduleContext;
63 changes: 63 additions & 0 deletions apps/frontend/src/hooks/schedules/useCreateSchedule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { useCallback } from "react";

import { gql, useMutation } from "@apollo/client";

import {
CREATE_SCHEDULE,
CreateScheduleResponse,
IScheduleInput,
} from "@/lib/api";

export const useCreateSchedule = () => {
const mutation = useMutation<CreateScheduleResponse>(CREATE_SCHEDULE, {
update(cache, { data }) {
const schedule = data?.createSchedule;

if (!schedule) return;

cache.modify({
fields: {
schedules: (existingSchedules = []) => {
const reference = cache.writeFragment({
data: schedule,
fragment: gql`
fragment CreatedSchedule on Schedule {
_id
name
public
createdBy
year
semester
classes {
class {
subject
courseNumber
number
}
selectedSections
}
}
`,
});

return [...existingSchedules, reference];
},
},
});
},
});

const createSchedule = useCallback(
async (schedule: IScheduleInput) => {
const mutate = mutation[0];

return await mutate({ variables: { schedule } });
},
[mutation]
);

return [createSchedule, mutation[1]] as [
mutate: typeof createSchedule,
result: (typeof mutation)[1],
];
};
42 changes: 42 additions & 0 deletions apps/frontend/src/hooks/schedules/useDeleteSchedule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useCallback } from "react";

import { useMutation } from "@apollo/client";

import {
DELETE_SCHEDULE,
DeleteScheduleResponse,
ScheduleIdentifier,
} from "@/lib/api";

export const useDeleteSchedule = () => {
const mutation = useMutation<DeleteScheduleResponse>(DELETE_SCHEDULE, {
update(cache, { data }) {
const id = data?.deleteSchedule;

if (!id) return;

cache.modify({
fields: {
schedules: (existingSchedules = [], { readField }) =>
existingSchedules.filter(
(reference: any) => readField("_id", reference) !== id
),
},
});
},
});

const deleteSchedule = useCallback(
async (id: ScheduleIdentifier) => {
const mutate = mutation[0];

return await mutate({ variables: { id } });
},
[mutation]
);

return [deleteSchedule, mutation[1]] as [
mutate: typeof deleteSchedule,
result: (typeof mutation)[1],
];
};
Loading

0 comments on commit 1d9c1ec

Please sign in to comment.