diff --git a/backend/app/base/utils.py b/backend/app/base/utils.py index a4487f2..91e6feb 100644 --- a/backend/app/base/utils.py +++ b/backend/app/base/utils.py @@ -20,8 +20,7 @@ def order_by_column_name(query: BaseQuery, model_field: str, order_by_col_name: return query -def paginate_models(page: str, query: BaseQuery) -> PaginationResponse or Tuple[dict, int]: - per_page = 10 +def paginate_models(page: str, query: BaseQuery, per_page = 10) -> PaginationResponse or Tuple[dict, int]: default_page = 1 if page is not None: diff --git a/backend/app/coordinator/routes/students.py b/backend/app/coordinator/routes/students.py index 0b6c7c9..8706969 100644 --- a/backend/app/coordinator/routes/students.py +++ b/backend/app/coordinator/routes/students.py @@ -26,11 +26,12 @@ def list_students(query: dict) -> dict: order_by_first_name = query.get('order_by_first_name') order_by_last_name = query.get('order_by_last_name') page = query.get('page') + per_page = query.get('per_page') student_query = Student.search_by_fullname_and_order_by_first_name_or_last_name(fullname, order_by_first_name, order_by_last_name) - response = paginate_models(page, student_query) + response = paginate_models(page, student_query, per_page) if (message := response.get('message')) is not None: abort(response['status_code'], message) # print(get_debug_queries()[0]) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c80190c..d9a3267 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -16,6 +16,7 @@ "@types/react": "^18.0.9", "@types/react-dom": "^18.0.4", "axios": "^0.27.2", + "classnames": "^2.3.1", "daisyui": "^2.15.2", "react": "^18.1.0", "react-dom": "^18.1.0", @@ -5260,6 +5261,11 @@ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==" }, + "node_modules/classnames": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", + "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" + }, "node_modules/clean-css": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.0.tgz", @@ -20237,6 +20243,11 @@ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==" }, + "classnames": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", + "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" + }, "clean-css": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index d9a6894..faf5710 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,6 +11,7 @@ "@types/react": "^18.0.9", "@types/react-dom": "^18.0.4", "axios": "^0.27.2", + "classnames": "^2.3.1", "daisyui": "^2.15.2", "react": "^18.1.0", "react-dom": "^18.1.0", diff --git a/frontend/src/api/students.ts b/frontend/src/api/students.ts index 22fc39e..a8f9c98 100644 --- a/frontend/src/api/students.ts +++ b/frontend/src/api/students.ts @@ -1,5 +1,7 @@ import axiosInstance from './axiosInstance' +type OrderType = 'asc' | 'desc' + interface StudentResponse { max_pages: number students: Student[] @@ -13,9 +15,18 @@ export interface Student { group?: any } -export const getStudents = () => +export const getStudents = ( + params: Partial<{ + fullname: string + order_by_first_name: OrderType + order_by_last_name: OrderType + page: number + per_page: number + }> = {}, +) => axiosInstance.get( 'http://127.0.0.1:5000/api/coordinator/students', + { params }, ) export const createStudent = (payload: Student) => diff --git a/frontend/src/components/TopBar.tsx b/frontend/src/components/TopBar.tsx index eb6af27..779e2ad 100644 --- a/frontend/src/components/TopBar.tsx +++ b/frontend/src/components/TopBar.tsx @@ -4,7 +4,7 @@ const TopBar = () => { const linkClass = ({ isActive }: { isActive: boolean }) => isActive ? 'underline font-bold' : '' return ( -
+

System PRI

diff --git a/frontend/src/views/coordinator/Students.tsx b/frontend/src/views/coordinator/Students.tsx index f786551..9128fbf 100644 --- a/frontend/src/views/coordinator/Students.tsx +++ b/frontend/src/views/coordinator/Students.tsx @@ -1,17 +1,40 @@ -import React, { useState } from 'react' +import React, { useEffect, useState } from 'react' import { useMutation, useQuery } from 'react-query' import { useNavigate } from 'react-router-dom' import { getStudents, uploadStudents } from '../../api/students' +import classNames from 'classnames' const Students = () => { let navigate = useNavigate() const [showGroupless, setShowGroupless] = useState(false) + const [page, setPage] = useState(1) + const [perPage, setPerPage] = useState(10) + const perPageOptions = [ + { + value: 10, + label: '10 rekordów', + }, + { + value: 20, + label: '20 rekordów', + }, + { + value: 50, + label: '50 rekordów', + }, + { + value: 1000, + label: 'Pokaż wszystkie', + }, + ] const { isLoading: isStudentsLoading, data: students, refetch: refetchStudents, - } = useQuery('students', () => getStudents()) + } = useQuery(['students', page, perPage], () => + getStudents({ page, per_page: perPage }), + ) const { mutate: mutateUpload } = useMutation( 'uploadStudents', @@ -28,65 +51,115 @@ const Students = () => { mutateUpload(payload) } - if (isStudentsLoading) { - return
Ładowanie
- } + useEffect(() => { + setPage(1) + }, [perPage]) + return (
-
- - - -
+
+
+ + {[ + ...Array( + students?.data?.max_pages && students?.data?.max_pages + 1, + ).keys(), + ] + .slice(1) + .map((p) => ( + + ))} + +
+
+ + )}
) } diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index a273b0c..d48d3f4 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es5", + "target": "es2015", "lib": [ "dom", "dom.iterable",