Skip to content

Commit 5671d8e

Browse files
committed
add changes
1 parent f858d5b commit 5671d8e

File tree

2 files changed

+58
-9
lines changed

2 files changed

+58
-9
lines changed

backend/degree/views.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,42 @@ def degrees(self, request, pk=None):
134134
status=status.HTTP_400_BAD_REQUEST,
135135
)
136136

137+
# Handle updating fulfillments when a new degree is added to the degree plan.
138+
def update_fulfillments():
139+
rules_per_degree, rule_to_degree = map_rules_and_degrees(degree_plan)
140+
# Helper to track satisfaction
141+
satisfied_lookup = defaultdict(int)
142+
satisfied_rules = set()
143+
144+
def is_satisfied(rule):
145+
f = satisfied_lookup[rule.id]
146+
return (rule.num and f >= rule.num) or (rule.credits and f >= rule.credits)
147+
148+
fulfillments = Fulfillment.objects.filter(degree_plan=degree_plan).order_by(
149+
"semester", "full_code"
150+
)
151+
152+
for fulfillment in fulfillments:
153+
selected_rules, unselected_rules, legal = allocate_rules(
154+
fulfillment.full_code,
155+
rules_per_degree,
156+
rule_to_degree,
157+
degree_plan=degree_plan,
158+
satisfied_rules=satisfied_rules,
159+
)
160+
161+
fulfillment.rules.set(selected_rules)
162+
fulfillment.unselected_rules.set(unselected_rules)
163+
fulfillment.legal = legal
164+
fulfillment.save()
165+
166+
for rule in selected_rules:
167+
satisfied_lookup[rule.id] += 1
168+
if is_satisfied(rule):
169+
satisfied_rules.add(rule)
170+
171+
update_fulfillments()
172+
137173
serializer = self.get_serializer(degree_plan)
138174
return Response(serializer.data, status=status.HTTP_200_OK)
139175

frontend/degree-plan/components/FourYearPlan/DegreeModal.tsx

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ const ModalButton = styled.button`
7979
padding: 0.25rem 0.5rem;
8080
color: white;
8181
border: none;
82+
&:disabled {
83+
opacity: 0.6;
84+
cursor: not-allowed;
85+
}
8286
`;
8387

8488
const ButtonRow = styled.div<{ $center?: boolean }>`
@@ -205,14 +209,22 @@ const ModalInterior = ({
205209

206210
if (!modalKey && !modalObject) return <div></div>;
207211

212+
const [isAddingDegree, setIsAddingDegree] = useState(false);
208213
const add_degree = async (degreeplanId: number, degreeId: number) => {
209214
// const { mutate } = useSWR(`/api/degree/degreeplans/${degreeplanId}/degrees`, getFetcher);
210-
const updated = await postFetcher(
211-
`/api/degree/degreeplans/${degreeplanId}/degrees`,
212-
{ degree_ids: [degreeId] }
213-
);
214-
await mutate(`/api/degree/degreeplans/${degreeplanId}`); // use updated degree plan returned
215-
await mutate(`/api/degree/degreeplans/${degreeplanId}/fulfillments`);
215+
setIsAddingDegree(true);
216+
try {
217+
const updated = await postFetcher(
218+
`/api/degree/degreeplans/${degreeplanId}/degrees`,
219+
{ degree_ids: [degreeId] }
220+
);
221+
await mutate(`/api/degree/degreeplans/${degreeplanId}`); // use updated degree plan returned
222+
await mutate(`/api/degree/degreeplans/${degreeplanId}/fulfillments`);
223+
} catch (error) {
224+
console.error(error);
225+
} finally {
226+
setIsAddingDegree(false);
227+
}
216228
};
217229

218230
const remove_degree = async (degreeplanId: number, degreeId: number) => {
@@ -334,13 +346,14 @@ const ModalInterior = ({
334346
</SelectList>
335347
<ButtonRow $center={true}>
336348
<ModalButton
337-
onClick={() => {
349+
disabled={isAddingDegree}
350+
onClick={async () => {
338351
if (!major?.value.id) return;
339-
add_degree((modalObject as Degree).id, major?.value.id);
352+
await add_degree((modalObject as Degree).id, major?.value.id);
340353
close();
341354
}}
342355
>
343-
Add
356+
{isAddingDegree ? "Adding..." : "Add"}
344357
</ModalButton>
345358
</ButtonRow>
346359
</DegreeAddInterior>

0 commit comments

Comments
 (0)