Skip to content

Commit d9dec15

Browse files
authored
Merge pull request #391 from qa-guru/QAGDEV-723
QAGDEV-723 - [FE] Прикрепления тестов к заданиям v10
2 parents 264f9b9 + 28e008b commit d9dec15

File tree

6 files changed

+111
-38
lines changed

6 files changed

+111
-38
lines changed

src/api/graphql/test/test-attempts-all.graphql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ query testAttemptsAll($offset: Int!, $limit: Int!, $sort: TestAttemptSort) {
77
successfulCount
88
errorsCount
99
result
10+
studentName
11+
trainingName
12+
lectureSubject
13+
testGroupName
1014
}
1115
offset
1216
limit

src/api/schema.graphql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,10 @@ type TestAttemptShortDto {
653653
successfulCount: Int
654654
errorsCount: Int
655655
result: Boolean
656+
studentName: String
657+
trainingName: String
658+
lectureSubject: String
659+
testGroupName: String
656660
}
657661

658662
type TestAttemptDto {
@@ -663,6 +667,10 @@ type TestAttemptDto {
663667
errorsCount: Int
664668
result: Boolean
665669
testAttemptQuestionResults: [TestAttemptQuestionResultDto]
670+
student: UserDto
671+
training: TrainingDto
672+
lecture: LectureInfoDto
673+
testGroup: TestGroupDto
666674
}
667675

668676
type TestAttemptsDto {

src/features/admin-panel/tests-admin/test-attempts-list.tsx

Lines changed: 88 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,17 @@ import {
2424
MenuItem,
2525
SelectChangeEvent,
2626
Pagination,
27+
Avatar,
28+
Stack,
2729
} from "@mui/material";
2830
import {
2931
Visibility as VisibilityIcon,
3032
Refresh as RefreshIcon,
3133
Search as SearchIcon,
3234
Sort as SortIcon,
35+
Person as PersonIcon,
36+
School as SchoolIcon,
37+
Book as BookIcon,
3338
} from "@mui/icons-material";
3439

3540
import {
@@ -94,7 +99,16 @@ const TestAttemptsList: FC = () => {
9499
attemptsData?.testAttemptsAll?.items?.filter((attempt) => {
95100
if (!attempt) return false;
96101

97-
if (searchTerm && !attempt.id?.includes(searchTerm)) return false;
102+
if (searchTerm) {
103+
const searchLower = searchTerm.toLowerCase();
104+
return (
105+
attempt.id?.toLowerCase().includes(searchLower) ||
106+
attempt.studentName?.toLowerCase().includes(searchLower) ||
107+
attempt.trainingName?.toLowerCase().includes(searchLower) ||
108+
attempt.lectureSubject?.toLowerCase().includes(searchLower) ||
109+
attempt.testGroupName?.toLowerCase().includes(searchLower)
110+
);
111+
}
98112

99113
return true;
100114
}) || [];
@@ -158,7 +172,7 @@ const TestAttemptsList: FC = () => {
158172
<Grid item xs={12} md={4}>
159173
<TextField
160174
fullWidth
161-
label="Поиск по ID попытки"
175+
label="Поиск по студенту, курсу или лекции"
162176
value={searchTerm}
163177
onChange={(e) => setSearchTerm(e.target.value)}
164178
InputProps={{
@@ -239,11 +253,12 @@ const TestAttemptsList: FC = () => {
239253
<Table>
240254
<TableHead>
241255
<TableRow>
242-
<TableCell>ID попытки</TableCell>
256+
<TableCell>Студент</TableCell>
257+
<TableCell>Курс</TableCell>
258+
<TableCell>Лекция</TableCell>
259+
<TableCell>Тест</TableCell>
243260
<TableCell>Время начала</TableCell>
244261
<TableCell>Время завершения</TableCell>
245-
<TableCell>Правильных ответов</TableCell>
246-
<TableCell>Ошибок</TableCell>
247262
<TableCell>Результат</TableCell>
248263
<TableCell>Статус</TableCell>
249264
<TableCell>Действия</TableCell>
@@ -255,33 +270,83 @@ const TestAttemptsList: FC = () => {
255270

256271
return (
257272
<TableRow key={attempt.id} hover>
258-
<TableCell>{attempt.id}</TableCell>
259273
<TableCell>
260-
{attempt.startTime ? formatDate(attempt.startTime) : "-"}
274+
<Stack direction="row" alignItems="center" spacing={1}>
275+
<Avatar sx={{ width: 32, height: 32 }}>
276+
<PersonIcon />
277+
</Avatar>
278+
<Box>
279+
<Typography variant="body2" fontWeight="medium">
280+
{attempt.studentName}
281+
</Typography>
282+
<Typography variant="caption" color="text.secondary">
283+
Студент
284+
</Typography>
285+
</Box>
286+
</Stack>
261287
</TableCell>
262288
<TableCell>
263-
{attempt.endTime ? formatDate(attempt.endTime) : "-"}
289+
<Stack direction="row" alignItems="center" spacing={1}>
290+
<SchoolIcon color="primary" />
291+
<Box>
292+
<Typography variant="body2" fontWeight="medium">
293+
{attempt.trainingName}
294+
</Typography>
295+
<Typography variant="caption" color="text.secondary">
296+
Курс
297+
</Typography>
298+
</Box>
299+
</Stack>
300+
</TableCell>
301+
<TableCell>
302+
<Stack direction="row" alignItems="center" spacing={1}>
303+
<BookIcon color="secondary" />
304+
<Box>
305+
<Typography variant="body2" fontWeight="medium">
306+
{attempt.lectureSubject}
307+
</Typography>
308+
<Typography variant="caption" color="text.secondary">
309+
Лекция
310+
</Typography>
311+
</Box>
312+
</Stack>
264313
</TableCell>
265314
<TableCell>
266-
<Chip
267-
label={attempt.successfulCount || 0}
268-
color="success"
269-
variant="outlined"
270-
size="small"
271-
/>
315+
<Box>
316+
<Typography variant="body2" fontWeight="medium">
317+
{attempt.testGroupName}
318+
</Typography>
319+
<Typography variant="caption" color="text.secondary">
320+
Тест
321+
</Typography>
322+
</Box>
272323
</TableCell>
273324
<TableCell>
274-
<Chip
275-
label={attempt.errorsCount || 0}
276-
color="error"
277-
variant="outlined"
278-
size="small"
279-
/>
325+
{attempt.startTime ? formatDate(attempt.startTime) : "-"}
326+
</TableCell>
327+
<TableCell>
328+
{attempt.endTime ? formatDate(attempt.endTime) : "-"}
280329
</TableCell>
281330
<TableCell>
282-
<Typography variant="body2" fontWeight="medium">
283-
{getScoreDisplay(attempt)}
284-
</Typography>
331+
<Box>
332+
<Typography variant="body2" fontWeight="medium">
333+
{getScoreDisplay(attempt)}
334+
</Typography>
335+
<Box sx={{ display: "flex", gap: 0.5, mt: 0.5 }}>
336+
<Chip
337+
label={attempt.successfulCount || 0}
338+
color="success"
339+
variant="outlined"
340+
size="small"
341+
/>
342+
<Chip
343+
label={attempt.errorsCount || 0}
344+
color="error"
345+
variant="outlined"
346+
size="small"
347+
/>
348+
</Box>
349+
</Box>
285350
</TableCell>
286351
<TableCell>
287352
{attempt.result !== null ? (

src/features/admin-panel/tests-admin/tests-admin.tsx

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
CardContent,
88
Typography,
99
Grid,
10-
Fab,
1110
IconButton,
1211
Chip,
1312
} from "@mui/material";
@@ -81,6 +80,7 @@ const TestsAdmin: FC = () => {
8180
variant="contained"
8281
startIcon={<AddIcon />}
8382
onClick={handleCreateTest}
83+
sx={{ color: "white" }}
8484
>
8585
Создать тест
8686
</Button>
@@ -130,7 +130,12 @@ const TestsAdmin: FC = () => {
130130
label={`${test?.successThreshold} правильных ответов`}
131131
size="small"
132132
color="primary"
133-
sx={{ ml: 1 }}
133+
sx={{
134+
ml: 1,
135+
"& .MuiChip-label": {
136+
color: "white",
137+
},
138+
}}
134139
/>
135140
</Box>
136141

@@ -159,25 +164,13 @@ const TestsAdmin: FC = () => {
159164
variant="contained"
160165
startIcon={<AddIcon />}
161166
onClick={handleCreateTest}
167+
sx={{ color: "white" }}
162168
>
163169
Создать первый тест
164170
</Button>
165171
</CardContent>
166172
</Card>
167173
)}
168-
169-
<Fab
170-
color="primary"
171-
aria-label="add"
172-
onClick={handleCreateTest}
173-
sx={{
174-
position: "fixed",
175-
bottom: 16,
176-
right: 16,
177-
}}
178-
>
179-
<AddIcon />
180-
</Fab>
181174
</Box>
182175
);
183176
};

src/features/test/views/test-view.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
} from "@mui/material";
1515

1616
import { TestGroupDto } from "api/graphql/generated/graphql";
17+
1718
import { TestQuestion, TestAnswer, UserAnswer } from "../types";
1819

1920
interface TestViewProps {

src/routes/admin.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import UserDetail from "pages/user-detail";
66
import EditTrainingPage from "pages/edit-training";
77
import EditLecturesPage from "pages/edit-lectures";
88
import EditLecturePage from "pages/edit-lecture";
9+
import { KanbanPage } from "pages/kanban";
910
import {
1011
KanbanMentorHomeworkDetailsFullPage,
1112
KanbanMentorPage,
@@ -57,6 +58,7 @@ const AdminRoutes = [
5758
path="/training/:trainingId/:lectureId"
5859
element={<LectureDetailPage />}
5960
/>,
61+
<Route key="kanban" path="/kanban" element={<KanbanPage />} />,
6062
<Route
6163
key="kanban-mentor"
6264
path="/kanban-mentor"

0 commit comments

Comments
 (0)