какие-то изменения
This commit is contained in:
parent
1e435ad24b
commit
8ceed9a2c7
386
data.json
386
data.json
@ -1,155 +1,233 @@
|
||||
{
|
||||
"users": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Никита",
|
||||
"surname": "Потапов",
|
||||
"username": "nspotapov",
|
||||
"password": "123456",
|
||||
"isTeacher": false,
|
||||
"groupId": 1
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Алексей",
|
||||
"surname": "Филиппов",
|
||||
"username": "afilippov",
|
||||
"password": "123456",
|
||||
"isTeacher": true,
|
||||
"groupId": null
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Елена",
|
||||
"surname": "Бакальская",
|
||||
"username": "ekallin",
|
||||
"password": "123456",
|
||||
"isTeacher": false,
|
||||
"groupId": 1
|
||||
},
|
||||
{
|
||||
"name": "Алексей",
|
||||
"surname": "Крюков",
|
||||
"username": "akrukov",
|
||||
"password": "123",
|
||||
"isTeacher": false,
|
||||
"groupId": 1,
|
||||
"id": 4
|
||||
}
|
||||
],
|
||||
"groups": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "пибд-21"
|
||||
}
|
||||
],
|
||||
"subjects": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Интернет программирование"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "РПП"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Физическая культура"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Системный анализ"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Системное администрирование"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "Основы теории систем"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Иностранный язык"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "Философия"
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "Теория вероятностей"
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"name": "Операционные системы"
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"name": "Основы ЭВМ и систем"
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"name": "Базы данных"
|
||||
}
|
||||
],
|
||||
"marks": [
|
||||
{
|
||||
"id": 2,
|
||||
"name": "неуд",
|
||||
"controltypeId": 1
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "удов",
|
||||
"controltypeId": 1
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "хорошо",
|
||||
"controltypeId": 1
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "отлично",
|
||||
"controltypeId": 1
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "зачтено",
|
||||
"controltypeId": 2
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "незачет",
|
||||
"controltypeId": 2
|
||||
}
|
||||
],
|
||||
"statements": [
|
||||
{
|
||||
"id": 1,
|
||||
"subjectId": 1,
|
||||
"groupId": 1,
|
||||
"controlTypeId": 2,
|
||||
"date": "Dec 23 2023"
|
||||
}
|
||||
],
|
||||
"controltypes": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Экзамен"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Зачет"
|
||||
}
|
||||
],
|
||||
"usermarks": [
|
||||
{
|
||||
"id": 1,
|
||||
"userId": 1,
|
||||
"markId": 1,
|
||||
"statementId": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
"users": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Никита",
|
||||
"surname": "Потапов",
|
||||
"username": "nspotapov",
|
||||
"password": "123456",
|
||||
"isTeacher": false,
|
||||
"groupId": 1
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Алексей",
|
||||
"surname": "Филиппов",
|
||||
"username": "afilippov",
|
||||
"password": "123456",
|
||||
"isTeacher": true,
|
||||
"groupId": null
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Елена",
|
||||
"surname": "Бакальская",
|
||||
"username": "ekallin",
|
||||
"password": "123456",
|
||||
"isTeacher": false,
|
||||
"groupId": 1
|
||||
},
|
||||
{
|
||||
"name": "Алексей",
|
||||
"surname": "Крюков",
|
||||
"username": "akrukov",
|
||||
"password": "123",
|
||||
"isTeacher": false,
|
||||
"groupId": 1,
|
||||
"id": 4
|
||||
},
|
||||
{
|
||||
"name": "Данил",
|
||||
"surname": "Горячев",
|
||||
"username": "danilgor",
|
||||
"password": "123456",
|
||||
"isTeacher": false,
|
||||
"groupId": 2,
|
||||
"id": 5
|
||||
},
|
||||
{
|
||||
"name": "Максим",
|
||||
"surname": "Кузярин",
|
||||
"username": "maximkuzyarin",
|
||||
"password": "123456",
|
||||
"isTeacher": false,
|
||||
"groupId": 3,
|
||||
"id": 6
|
||||
},
|
||||
{
|
||||
"name": "dfgfdgb",
|
||||
"surname": "fdfdbdf",
|
||||
"username": "afilippovffb",
|
||||
"password": "123456",
|
||||
"isTeacher": true,
|
||||
"groupId": null,
|
||||
"id": 7
|
||||
},
|
||||
{
|
||||
"name": "Оксана",
|
||||
"surname": "Потапова",
|
||||
"username": "opotapova",
|
||||
"password": "123456",
|
||||
"isTeacher": false,
|
||||
"groupId": 3,
|
||||
"id": 8
|
||||
}
|
||||
],
|
||||
"groups": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "пибд-21"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "пибд-22"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "пибд-23"
|
||||
}
|
||||
],
|
||||
"subjects": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Интернет программирование"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "РПП"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Физическая культура"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Системный анализ"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Системное администрирование"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "Основы теории систем"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Иностранный язык"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "Философия"
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "Теория вероятностей"
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"name": "Операционные системы"
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"name": "Основы ЭВМ и систем"
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"name": "Базы данных"
|
||||
}
|
||||
],
|
||||
"marks": [
|
||||
{
|
||||
"id": 2,
|
||||
"name": "неуд",
|
||||
"controltypeId": 1
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "удов",
|
||||
"controltypeId": 1
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "хорошо",
|
||||
"controltypeId": 1
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "отлично",
|
||||
"controltypeId": 1
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "зачтено",
|
||||
"controltypeId": 2
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "незачет",
|
||||
"controltypeId": 2
|
||||
}
|
||||
],
|
||||
"statements": [
|
||||
{
|
||||
"id": 1,
|
||||
"subjectId": 1,
|
||||
"groupId": 1,
|
||||
"controltypeId": 2,
|
||||
"date": "Dec 23 2023"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"subjectId": 2,
|
||||
"groupId": 1,
|
||||
"controltypeId": 1,
|
||||
"date": "Dec 25 2023"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"subjectId": 4,
|
||||
"groupId": 1,
|
||||
"controltypeId": 1,
|
||||
"date": "Dec 26 2023"
|
||||
},
|
||||
{
|
||||
"subjectId": "1",
|
||||
"groupId": "1",
|
||||
"controltypeId": "2",
|
||||
"id": 4
|
||||
},
|
||||
{
|
||||
"subjectId": "3",
|
||||
"groupId": "2",
|
||||
"controltypeId": "2",
|
||||
"date": "2024-01-12T00:00:00.000Z",
|
||||
"id": 5
|
||||
},
|
||||
{
|
||||
"subjectId": "3",
|
||||
"groupId": "2",
|
||||
"controltypeId": "2",
|
||||
"date": "2024-01-12T00:00:00.000Z",
|
||||
"id": 6
|
||||
}
|
||||
],
|
||||
"controltypes": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Экзамен"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Зачет"
|
||||
}
|
||||
],
|
||||
"usermarks": [
|
||||
{
|
||||
"id": 1,
|
||||
"userId": 1,
|
||||
"markId": 1,
|
||||
"statementId": 1
|
||||
}
|
||||
]
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import axios from "axios";
|
||||
import { Toast } from "react-bootstrap";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
export class HttpError extends Error {
|
||||
constructor(message = "") {
|
||||
@ -25,7 +26,7 @@ function responseErrorHandler(error) {
|
||||
if (error === null) {
|
||||
throw new Error("Unrecoverable error!! Error is null!");
|
||||
}
|
||||
Toast.error(error.message, { id: "AxiosError" });
|
||||
toast.error(error.message, { id: "AxiosError" });
|
||||
return Promise.reject(error.message);
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,8 @@ const Header = ({ routes }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<header className='sticky-top'>
|
||||
<Navbar expand='md bg-dark'>
|
||||
<header className='sticky-top bg-dark mb-2'>
|
||||
<Navbar expand='md'>
|
||||
<Container fluid>
|
||||
<Navbar.Brand as={Link} to={indexPageLink?.path ?? '/'}>
|
||||
Учебный процесс
|
||||
|
23
src/components/statementtablerow/statementtablerow.jsx
Normal file
23
src/components/statementtablerow/statementtablerow.jsx
Normal file
@ -0,0 +1,23 @@
|
||||
import { PropTypes } from "prop-types";
|
||||
import { Trash } from "react-bootstrap-icons";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
const StatementTableRow = ({ statement, onDelete }) => {
|
||||
return (
|
||||
<tr>
|
||||
<th scope='row'>{statement.id}</th>
|
||||
<td>{statement.subject.name}</td>
|
||||
<td>{statement.group.name}</td>
|
||||
<td>{statement.controltype.name}</td>
|
||||
<td>{new Date(statement.date).toLocaleDateString('ru')}</td>
|
||||
<td><Link><Trash fill="red" onClick={() => { onDelete(statement.id); }} /></Link></td>
|
||||
</tr>
|
||||
);
|
||||
};
|
||||
|
||||
StatementTableRow.propTypes = {
|
||||
statement: PropTypes.object,
|
||||
onDelete: PropTypes.func
|
||||
};
|
||||
|
||||
export default StatementTableRow;
|
23
src/hooks/ControlTypesHook.js
Normal file
23
src/hooks/ControlTypesHook.js
Normal file
@ -0,0 +1,23 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import ControlTypesApiService from "../services/CotrolTypesApiService";
|
||||
|
||||
export const useControlTypes = () => {
|
||||
const [controlTypesRefresh, setControlTypesRefresh] = useState(false);
|
||||
const [controlTypes, setControlTypes] = useState([]);
|
||||
const handleControlTypesChange = () =>
|
||||
setControlTypesRefresh(!controlTypesRefresh);
|
||||
|
||||
const getControlTypes = async () => {
|
||||
const data = await ControlTypesApiService.getAll();
|
||||
setControlTypes(data ?? []);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getControlTypes();
|
||||
}, [controlTypesRefresh]);
|
||||
|
||||
return {
|
||||
controlTypes,
|
||||
handleControlTypesChange,
|
||||
};
|
||||
};
|
30
src/hooks/FilterHook.js
Normal file
30
src/hooks/FilterHook.js
Normal file
@ -0,0 +1,30 @@
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import { useState } from "react";
|
||||
|
||||
const useQueryParamFilter = (queryParamName) => {
|
||||
const [filterValue, setFilterValue] = useState(null);
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
|
||||
const onFilterChange = (event) => {
|
||||
let targetValue = event.target.value;
|
||||
try {
|
||||
targetValue = parseInt(targetValue);
|
||||
} catch (e) {
|
||||
targetValue = null;
|
||||
}
|
||||
|
||||
if (targetValue) {
|
||||
searchParams.set(queryParamName, event.target.value);
|
||||
} else {
|
||||
searchParams.delete(queryParamName);
|
||||
}
|
||||
setSearchParams(searchParams);
|
||||
};
|
||||
|
||||
return {
|
||||
filterValue: searchParams.get(queryParamName) || null,
|
||||
onFilterChange,
|
||||
};
|
||||
};
|
||||
|
||||
export default useQueryParamFilter;
|
@ -4,7 +4,7 @@ import GroupsApiService from "../services/GroupsApiService";
|
||||
export const useGroups = () => {
|
||||
const [groupsRefresh, setGroupsRefresh] = useState(false);
|
||||
const [groups, setGroups] = useState([]);
|
||||
const handleGroupsRefresh = () => setGroupsRefresh(!groupsRefresh);
|
||||
const handleGroupsChange = () => setGroupsRefresh(!groupsRefresh);
|
||||
|
||||
const getGroups = async () => {
|
||||
const data = await GroupsApiService.getAll();
|
||||
@ -17,6 +17,6 @@ export const useGroups = () => {
|
||||
|
||||
return {
|
||||
groups,
|
||||
handleGroupsRefresh,
|
||||
handleGroupsChange,
|
||||
};
|
||||
};
|
||||
|
@ -0,0 +1,34 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import StatementsApiService from "../services/StatementsApiService";
|
||||
|
||||
export const useStatements = (filters) => {
|
||||
const [statementsRefresh, setStatementsRefresh] = useState(false);
|
||||
const [statements, setStatements] = useState([]);
|
||||
const handleStatementsChange = () =>
|
||||
setStatementsRefresh(!statementsRefresh);
|
||||
|
||||
const getStatements = async () => {
|
||||
let expand = `?_expand=group&_expand=controltype&_expand=subject&_sort=date&_order=desc`;
|
||||
if (Object.keys(filters).length !== 0) {
|
||||
for (let index = 0; index < Object.keys(filters).length; index++) {
|
||||
const key = Object.keys(filters)[index];
|
||||
const v = filters[key];
|
||||
if (v) {
|
||||
expand += `&${key}=${v}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
const data = await StatementsApiService.getAll(expand);
|
||||
setStatements(data ?? []);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getStatements();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [statementsRefresh]);
|
||||
|
||||
return {
|
||||
statements,
|
||||
handleStatementsChange,
|
||||
};
|
||||
};
|
@ -1,13 +1,23 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import SubjectsApiService from "../services/SubjectsApiService";
|
||||
|
||||
export const useSubjects = () => {
|
||||
export const useSubjects = (filters = null) => {
|
||||
const [subjectsRefresh, setSubjectsRefresh] = useState(false);
|
||||
const [subjects, setSubjects] = useState([]);
|
||||
const handleSubjectsRefresh = () => setSubjectsRefresh(!subjectsRefresh);
|
||||
const handleSubjectsChange = () => setSubjectsRefresh(!subjectsRefresh);
|
||||
|
||||
const getSubjects = async () => {
|
||||
const data = await SubjectsApiService.getAll();
|
||||
let expand = "";
|
||||
if (filters && Object.keys(filters).length !== 0) {
|
||||
for (let index = 0; index < Object.keys(filters).length; index++) {
|
||||
const key = Object.keys(filters)[index];
|
||||
const v = filters[key];
|
||||
if (v) {
|
||||
expand += `&${key}=${v}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
const data = await SubjectsApiService.getAll(expand);
|
||||
setSubjects(data ?? []);
|
||||
};
|
||||
|
||||
@ -17,6 +27,6 @@ export const useSubjects = () => {
|
||||
|
||||
return {
|
||||
subjects,
|
||||
handleSubjectsRefresh,
|
||||
handleSubjectsChange,
|
||||
};
|
||||
};
|
||||
|
@ -62,7 +62,7 @@ export const useUsers = () => {
|
||||
|
||||
useEffect(() => {
|
||||
getUsers();
|
||||
}, [usersRefresh]);
|
||||
});
|
||||
|
||||
return {
|
||||
users,
|
||||
@ -70,23 +70,33 @@ export const useUsers = () => {
|
||||
};
|
||||
};
|
||||
|
||||
export const useStudents = () => {
|
||||
export const useStudents = (filters = null) => {
|
||||
const [studentsRefresh, setStudentsRefresh] = useState(false);
|
||||
const [students, setStudents] = useState([]);
|
||||
const handleStudentsRefresh = () => setStudentsRefresh(!studentsRefresh);
|
||||
const handleStudentsChange = () => setStudentsRefresh(!studentsRefresh);
|
||||
|
||||
const getStudents = async () => {
|
||||
const expand = `?isTeacher=false&_expand=group`;
|
||||
let expand = `?isTeacher=false&_expand=group&_sort=surname,name`;
|
||||
if (filters && Object.keys(filters).length !== 0) {
|
||||
for (let index = 0; index < Object.keys(filters).length; index++) {
|
||||
const key = Object.keys(filters)[index];
|
||||
const v = filters[key];
|
||||
if (v) {
|
||||
expand += `&${key}=${v}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
const data = await UsersApiService.getAll(expand);
|
||||
setStudents(data ?? []);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getStudents();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [studentsRefresh]);
|
||||
|
||||
return {
|
||||
students,
|
||||
handleStudentsRefresh,
|
||||
handleStudentsChange,
|
||||
};
|
||||
};
|
||||
|
@ -1,11 +1,104 @@
|
||||
import StatementTableRow from "../../components/statementtablerow/statementtablerow";
|
||||
import { useGroups } from "../../hooks/GroupHook";
|
||||
import { useStatements } from "../../hooks/StatementsHook";
|
||||
import { useSubjects } from "../../hooks/SubjectsHook";
|
||||
import { useOnlyTeachers } from "../../hooks/UserHooks";
|
||||
import { Container } from "react-bootstrap";
|
||||
import useQueryParamFilter from "../../hooks/FilterHook";
|
||||
import { useControlTypes } from "../../hooks/ControlTypesHook";
|
||||
import StatementsApiService from "../../services/StatementsApiService";
|
||||
import { useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
const StatementsPage = () => {
|
||||
useOnlyTeachers();
|
||||
const [statementDate, setStatementDate] = useState('');
|
||||
const { subjects, handleSubjectsChange } = useSubjects();
|
||||
const { groups, handleGroupsChange } = useGroups();
|
||||
const { controlTypes, handleControlTypesChange } = useControlTypes();
|
||||
|
||||
const { filterValue: subjectFilter, onFilterChange: onSubjectChange } = useQueryParamFilter("subjectId");
|
||||
const { filterValue: groupFilter, onFilterChange: onGroupChange } = useQueryParamFilter("groupId");
|
||||
const { filterValue: controlTypeFilter, onFilterChange: onControlTypeChange } = useQueryParamFilter("controltypeId");
|
||||
const { statements, handleStatementsChange } = useStatements({
|
||||
"subjectId": subjectFilter,
|
||||
"groupId": groupFilter,
|
||||
"controltypeId": controlTypeFilter
|
||||
});
|
||||
|
||||
const onDateChange = () => {
|
||||
const date = document.getElementById('inputStatementDate').value;
|
||||
setStatementDate(date);
|
||||
};
|
||||
|
||||
const onButtonAddStatementClick = async () => {
|
||||
if (subjectFilter && groupFilter && controlTypeFilter && statementDate) {
|
||||
await StatementsApiService.create(
|
||||
{
|
||||
subjectId: subjectFilter,
|
||||
groupId: groupFilter,
|
||||
controltypeId: controlTypeFilter,
|
||||
date: new Date(statementDate)
|
||||
}
|
||||
);
|
||||
toast.success('Ведомость создана');
|
||||
handleStatementsChange();
|
||||
}
|
||||
};
|
||||
|
||||
const onButtonDeleteStatementClick = async (statementId) => {
|
||||
if (statementId) {
|
||||
await StatementsApiService.delete(statementId);
|
||||
toast.success("Ведомость успешно удалена");
|
||||
handleStatementsChange();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<h5>StatementsPage</h5>
|
||||
<Container>
|
||||
<div className="d-flex flex-column flex-md-row">
|
||||
<select name="subjectId" id="subjectId" className="me-none me-md-2 mb-2 mb-md-0" onChange={(e) => { onSubjectChange(e); handleStatementsChange(); }}>
|
||||
<option value={null}>Выберите предмет</option>
|
||||
{
|
||||
subjects.map((subject, index) => <option key={index} value={subject.id}>{subject.name}</option>)
|
||||
}
|
||||
</select>
|
||||
<select name="groupId" id="groupId" className="me-none me-md-2 mb-2 mb-md-0" onChange={(e) => { onGroupChange(e); handleStatementsChange(); }}>
|
||||
<option value={null}>Выберите группу</option>
|
||||
{
|
||||
groups.map((group, index) => <option key={index} value={group.id}>{group.name}</option>)
|
||||
}
|
||||
</select>
|
||||
<select name="controltypeId" id="controltypeId" className="mb-2 mb-md-0 me-none me-md-2" onChange={(e) => { onControlTypeChange(e); handleStatementsChange(); }}>
|
||||
<option value={null}>Выберите тип</option>
|
||||
{
|
||||
controlTypes.map((ct, index) => <option key={index} value={ct.id}>{ct.name}</option>)
|
||||
}
|
||||
</select>
|
||||
<input id="inputStatementDate" type="date" className="mb-2 mb-md-0 me-none me-md-2" value={statementDate} onChange={(e) => { onDateChange(e); handleStatementsChange(); }} />
|
||||
<button className="btn btn-success btn-sm" onClick={onButtonAddStatementClick}>
|
||||
Добавить ведомость
|
||||
</button>
|
||||
</div>
|
||||
<table className="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">ID</th>
|
||||
<th scope="col">Предмет</th>
|
||||
<th scope="col">Группа</th>
|
||||
<th scope="col">Тип</th>
|
||||
<th scope="col">Дата</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{
|
||||
statements.map((statement, index) => <StatementTableRow key={index} statement={statement} onDelete={onButtonDeleteStatementClick} />)
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</Container>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -1,14 +1,26 @@
|
||||
import StudentTableRow from "../../components/studenttablerow/studenttablerow";
|
||||
import { useOnlyTeachers, useStudents } from "../../hooks/UserHooks";
|
||||
import { Container } from "react-bootstrap";
|
||||
import { useGroups } from "../../hooks/GroupHook";
|
||||
import useQueryParamFilter from "../../hooks/FilterHook";
|
||||
|
||||
const StudentsPage = () => {
|
||||
useOnlyTeachers();
|
||||
const { students, handleStudentsChange } = useStudents();
|
||||
const { filterValue: groupFilter, onFilterChange: onGroupChange } = useQueryParamFilter("groupId");
|
||||
const { groups, handleGroupsChange } = useGroups();
|
||||
const { students, handleStudentsChange } = useStudents({
|
||||
'groupId': groupFilter
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<Container>
|
||||
<select name="groupId" id="groupId" className="me-none me-md-2 mb-2 mb-md-0" onChange={(e) => { onGroupChange(e); handleStudentsChange(); }}>
|
||||
<option value={null}>Выберите группу</option>
|
||||
{
|
||||
groups.map((group, index) => <option key={index} value={group.id}>{group.name}</option>)
|
||||
}
|
||||
</select>
|
||||
<table className="table">
|
||||
<thead>
|
||||
<tr>
|
||||
|
Loading…
Reference in New Issue
Block a user