Skip to content

Commit dc2f1b8

Browse files
committed
feat: add grouped students label
1 parent 4b1b3c2 commit dc2f1b8

1 file changed

Lines changed: 33 additions & 11 deletions

File tree

hwproj.front/src/components/Common/GroupSelector.tsx

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import {
88
CircularProgress,
99
Chip,
1010
Alert,
11-
AlertTitle
11+
AlertTitle,
12+
Typography
1213
} from "@mui/material";
1314
import ApiSingleton from "../../api/ApiSingleton";
1415
import {GroupViewModel, AccountDataDto} from "@/api";
@@ -47,12 +48,25 @@ const GroupSelector: FC<GroupSelectorProps> = (props) => {
4748
}, [props.selectedGroupId, props.groups])
4849

4950
const [isSubmitting, setIsSubmitting] = useState(false);
50-
const [isError, setIsError] = useState(false);
5151

52-
const studentsInGroups = useMemo(() => groups.flatMap(g => g.studentsIds),
53-
[groups, props.groups]);
54-
const studentsWithoutGroup = useMemo(() => props.courseStudents.filter((cm) => !studentsInGroups.includes(cm.userId)),
55-
[groups, props.courseStudents]);
52+
const studentToGroups = useMemo(() => {
53+
const map = new Map<string, string[]>();
54+
(props.groups || []).forEach(g => {
55+
g.studentsIds?.forEach(stId => {
56+
if (!map.has(stId)) map.set(stId, []);
57+
map.get(stId)!.push(g.name!);
58+
});
59+
});
60+
return map;
61+
}, [props.groups, props.selectedGroupId]);
62+
63+
const studentsInMultipleGroups = useMemo(() => {
64+
const set = new Set<string>();
65+
studentToGroups.forEach((groups, studentId) => {
66+
if (groups.length > 1) set.add(studentId);
67+
});
68+
return set;
69+
}, [studentToGroups]);
5670

5771
const handleSubmitEdit = async () => {
5872
setIsSubmitting(true);
@@ -78,7 +92,6 @@ const GroupSelector: FC<GroupSelectorProps> = (props) => {
7892
}
7993
} catch (error) {
8094
console.error('Failed to update group:', error);
81-
setIsError(true);
8295
} finally {
8396
setIsSubmitting(false);
8497
}
@@ -129,12 +142,15 @@ const GroupSelector: FC<GroupSelectorProps> = (props) => {
129142
fullWidth
130143
options={props.courseStudents}
131144
value={props.courseStudents?.filter(s => formState.memberIds.includes(s.userId!)) || []}
132-
getOptionLabel={(option) =>
133-
`${option.surname ?? ""} ${option.name ?? ""} / ${option.email ?? ""}`.trim()
134-
}
145+
getOptionLabel={(option) => {
146+
const groups = studentToGroups.get(option.userId!);
147+
const groupSuffix = groups && groups.length > 0
148+
? ' — в группе: ' + groups[0]
149+
: '';
150+
return `${option.surname ?? ""} ${option.name ?? ""} / ${option.email ?? ""}${groupSuffix}`.trim();
151+
}}
135152
filterSelectedOptions
136153
onChange={(_, value) => {
137-
if (value.map(x => x.userId!).filter(Boolean).length === 0) return;
138154
setFormState(prev => ({
139155
...prev,
140156
memberIds: value
@@ -149,6 +165,7 @@ const GroupSelector: FC<GroupSelectorProps> = (props) => {
149165
{...getTagProps({index})}
150166
label={`${option.surname ?? ""} ${option.name ?? ""} / ${option.email ?? ""}`.trim()}
151167
key={option.userId}
168+
style={studentsInMultipleGroups.has(option.userId!) ? {color: "#3f51b5"} : undefined}
152169
/>
153170
))
154171
}
@@ -159,6 +176,7 @@ const GroupSelector: FC<GroupSelectorProps> = (props) => {
159176
placeholder="Выберите студентов"
160177
/>
161178
)}
179+
noOptionsText={'Больше нет студентов для выбора'}
162180
/>
163181
<Button
164182
onClick={handleSubmitEdit}
@@ -169,6 +187,10 @@ const GroupSelector: FC<GroupSelectorProps> = (props) => {
169187
>
170188
{isSubmitting ? <CircularProgress size={24}/> : "Сохранить группу"}
171189
</Button>
190+
{studentsInMultipleGroups.size > 0 && formState.memberIds.some(id => studentsInMultipleGroups.has(id)) &&
191+
<Typography align="center" variant={"caption"} color={"#3f51b5"}>
192+
Синим выделены студенты, состоящие в нескольких группах
193+
</Typography>}
172194
</Stack>
173195
</Grid>}
174196
{props.selectedGroupId == undefined && <Grid item xs={12}>

0 commit comments

Comments
 (0)