Skip to content

Commit 2699e47

Browse files
Student selection limit message (#415)
* Change the error message for student selection more than 4 * extract the styling class * Add error tooltip for member selection same as others * Add svg for warning icon and replace all its instances * Fix styling for member selection error tooltip * Add a timeline to display the member selection error tooltip * Add test for checking the member selection error
1 parent d00747b commit 2699e47

File tree

4 files changed

+77
-29
lines changed

4 files changed

+77
-29
lines changed

public/assets/warning_icon.svg

Lines changed: 5 additions & 0 deletions
Loading

src/app/components/pages/IsaacCompetition/EntryForm/CompetitionEntryForm.tsx

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useEffect, useState } from "react";
2-
import { Form, Row, Col, Container, FormGroup, Label, Input, Alert } from "reactstrap";
2+
import { Form, Row, Col, Container, FormGroup, Label, Input } from "reactstrap";
33
import { isaacApi, useAppSelector } from "../../../../state";
44
import { selectors } from "../../../../state/selectors";
55
import { SchoolInput } from "../../../elements/inputs/SchoolInput";
@@ -71,17 +71,17 @@ export const CompetitionEntryForm = ({ handleTermsClick }: CompetitionEntryFormP
7171
const selectedValues = selectedOptions ? selectedOptions.map((option: any) => option.value) : [];
7272

7373
if (selectedValues.length > 4) {
74-
setMemberSelectionError("You can only select up to 4 students");
75-
76-
setTimeout(() => {
77-
setMemberSelectionError("");
78-
}, 3000);
74+
setMemberSelectionError("Limit of 4 students reached. To select a new student, remove one first.");
7975

8076
return;
8177
}
8278

8379
setMemberSelectionError("");
8480
setSelectedMembers(selectedValues);
81+
82+
setTimeout(() => {
83+
setMemberSelectionError("");
84+
}, 10000);
8585
};
8686

8787
const isSchoolValid = isSchoolValidForCompetition();
@@ -205,7 +205,7 @@ export const CompetitionEntryForm = ({ handleTermsClick }: CompetitionEntryFormP
205205
<div className="entry-form-validation-tooltip">
206206
<div className="tooltip-content">
207207
<div className="tooltip-arrow"></div>
208-
<div className="tooltip-icon">!</div>
208+
<img src="/assets/warning_icon.svg" alt="invalid school error" />
209209
<div className="tooltip-text">
210210
Please <a href="/account">update</a> your account details to specify your school or college.
211211
Only teachers and students from state-funded schools in England are eligible to participate.
@@ -300,7 +300,7 @@ export const CompetitionEntryForm = ({ handleTermsClick }: CompetitionEntryFormP
300300
<div className="entry-form-validation-tooltip">
301301
<div className="tooltip-content">
302302
<div className="tooltip-arrow"></div>
303-
<div className="tooltip-icon">!</div>
303+
<img src="/assets/warning_icon.svg" alt="no groups found error" />
304304
<div className="tooltip-text" style={{ color: "#000" }}>
305305
You have not created any groups. Please{" "}
306306
<a href="/groups" style={{ color: "#1D70B8", textDecoration: "underline" }}>
@@ -328,9 +328,17 @@ export const CompetitionEntryForm = ({ handleTermsClick }: CompetitionEntryFormP
328328
message="Choose 1-4 students from the selected group who worked on the submitted project."
329329
/>
330330
{memberSelectionError && (
331-
<Alert color="danger" className="mb-2" style={{ zIndex: 9999, position: "relative" }}>
332-
{memberSelectionError}
333-
</Alert>
331+
<div
332+
className="entry-form-validation-tooltip entry-form-validation-tooltip-centered mt-2"
333+
style={{ alignItems: "center" }}
334+
>
335+
<div className="tooltip-content">
336+
<img src="/assets/warning_icon.svg" alt="member selection error" />
337+
<div className="tooltip-text" style={{ color: "#000" }}>
338+
Limit of 4 students reached. To select a new student, remove one first.
339+
</div>
340+
</div>
341+
</div>
334342
)}
335343
</Label>
336344
<Select
@@ -389,7 +397,7 @@ export const CompetitionEntryForm = ({ handleTermsClick }: CompetitionEntryFormP
389397
<div className="entry-form-validation-tooltip" style={{ marginTop: "12px" }}>
390398
<div className="tooltip-content">
391399
<div className="tooltip-arrow"></div>
392-
<div className="tooltip-icon">!</div>
400+
<img src="/assets/warning_icon.svg" alt="no members found error" />
393401
<div className="tooltip-text" style={{ color: "#000" }}>
394402
No students found in the selected group. To add students go to the{" "}
395403
<a href="/groups" style={{ color: "#1D70B8", textDecoration: "underline" }}>

src/app/components/pages/IsaacCompetition/Tests/CompetitionEntryForm.test.tsx

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ describe("CompetitionEntryForm", () => {
231231
});
232232

233233
it("should show member selection error when more than 4 students selected", async () => {
234+
const user = userEvent.setup();
234235
const groupsWithManyMembers = [
235236
{
236237
id: 1,
@@ -244,9 +245,53 @@ describe("CompetitionEntryForm", () => {
244245
],
245246
},
246247
];
247-
setupTest(undefined, groupsWithManyMembers);
248+
setupTest({ schoolId: 123 }, groupsWithManyMembers);
249+
250+
// Select the group first
251+
const groupSelect = screen.getByText("Choose from the groups you've created or create one first");
252+
await user.click(groupSelect);
253+
254+
// Wait for the dropdown option to appear (use findByText instead of getByText)
255+
const largeGroupOption = await screen.findByText("Large Group");
256+
await user.click(largeGroupOption);
257+
258+
// Wait for the member select to be available
259+
await waitFor(() => {
260+
expect(screen.getByText("Choose students from your selected group")).toBeInTheDocument();
261+
});
262+
263+
// Find the select input using its inputId
264+
const getSelectInput = () => document.querySelector("#group-members-select") as HTMLElement;
248265

249-
expect(true).toBe(true);
266+
// Select first 4 students (should work fine)
267+
await user.click(getSelectInput());
268+
const student1Option = await screen.findByText("Student 1");
269+
await user.click(student1Option);
270+
271+
await user.click(getSelectInput());
272+
const student2Option = await screen.findByText("Student 2");
273+
await user.click(student2Option);
274+
275+
await user.click(getSelectInput());
276+
const student3Option = await screen.findByText("Student 3");
277+
await user.click(student3Option);
278+
279+
await user.click(getSelectInput());
280+
const student4Option = await screen.findByText("Student 4");
281+
await user.click(student4Option);
282+
283+
expect(screen.queryByText(/Limit of 4 students reached/)).not.toBeInTheDocument();
284+
285+
await user.click(getSelectInput());
286+
const student5Option = await screen.findByText("Student 5");
287+
await user.click(student5Option);
288+
289+
await waitFor(() => {
290+
const errorTooltip = screen.getByText(
291+
/Limit of 4 students reached. To select a new student, remove one first./,
292+
);
293+
expect(errorTooltip).toBeInTheDocument();
294+
});
250295
});
251296
});
252297

src/scss/cs/competition.scss

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,10 @@
244244
align-items: flex-start;
245245
gap: 8px;
246246
}
247+
248+
&-centered .tooltip-content {
249+
align-items: center;
250+
}
247251

248252
.tooltip-arrow {
249253
position: absolute;
@@ -268,23 +272,9 @@
268272
}
269273
}
270274

271-
.tooltip-icon {
272-
flex-shrink: 0;
273-
width: 16px;
274-
height: 16px;
275-
background-color: #ff6b35;
276-
color: white;
277-
border-radius: 2px;
278-
display: flex;
279-
align-items: center;
280-
justify-content: center;
281-
font-size: 12px;
282-
font-weight: bold;
283-
margin-top: 1px;
284-
}
285-
286275
.tooltip-text {
287276
flex: 1;
277+
font-family: "roboto", Roboto, sans-serif;
288278
color: #dc3545;
289279
font-size: 14px;
290280
line-height: 1.4;

0 commit comments

Comments
 (0)