diff --git a/apps/schools/domains/circle/components/changeCircleForm/index.tsx b/apps/schools/domains/circle/components/changeCircleForm/index.tsx
index 8ad76a1a..1df2e8f3 100644
--- a/apps/schools/domains/circle/components/changeCircleForm/index.tsx
+++ b/apps/schools/domains/circle/components/changeCircleForm/index.tsx
@@ -82,8 +82,8 @@ export const ChangeCircleForm = () => {
required={true}
label={
- * Название
-
+ * Название
+
}
name={CIRCLE_NAME}
className={styles.label}
diff --git a/apps/schools/domains/common/handlers/paginationChange.ts b/apps/schools/domains/common/handlers/paginationChange.ts
new file mode 100644
index 00000000..bbd0217c
--- /dev/null
+++ b/apps/schools/domains/common/handlers/paginationChange.ts
@@ -0,0 +1,43 @@
+export const handlePaginationChange = (
+ setPaginationParams: (params: { page: number; pageSize: number }) => void,
+ setQueryPaginationParams: (params: { [key: string]: { page: number; pageSize: number } }) => void,
+ counts: { [key: string]: number | undefined },
+ newPage: number,
+ newPageSize: number,
+ defaultPaginationTablePage: number,
+ defaultPaginationTablePageSize: number,
+ scrollToTop: () => void,
+) => {
+ setPaginationParams({
+ page: newPage,
+ pageSize: newPageSize,
+ })
+
+ const newQueryParams: { [key: string]: { page: number; pageSize: number } } = {}
+
+ let currentPage = newPage
+ let currentOffset = 0
+
+ Object.keys(counts).forEach((key, index) => {
+ const count = counts[key] ?? 0
+ const maxPages = Math.ceil(count / newPageSize)
+
+ if (currentPage <= maxPages) {
+ newQueryParams[key] = {
+ page: currentPage,
+ pageSize: newPageSize,
+ }
+ } else {
+ currentPage -= maxPages
+ newQueryParams[key] = {
+ page: defaultPaginationTablePage,
+ pageSize: defaultPaginationTablePageSize,
+ }
+ }
+
+ currentOffset += count
+ })
+
+ setQueryPaginationParams(newQueryParams)
+ scrollToTop()
+}
diff --git a/apps/schools/domains/common/redux/serializers.ts b/apps/schools/domains/common/redux/serializers.ts
index 6165fb90..b16df007 100644
--- a/apps/schools/domains/common/redux/serializers.ts
+++ b/apps/schools/domains/common/redux/serializers.ts
@@ -125,10 +125,10 @@ interface GetStudentProfile {
id?: string
name: string
age?: number
- phone?: string
+ phone: string
photo: GetPhoto
parent_names?: string
- parent_phones?: string
+ parent_phones: string
}
export interface GetAnalytics {
diff --git a/apps/schools/domains/common/utils/getTotalPages.ts b/apps/schools/domains/common/utils/getTotalPages.ts
new file mode 100644
index 00000000..7ebaea31
--- /dev/null
+++ b/apps/schools/domains/common/utils/getTotalPages.ts
@@ -0,0 +1,5 @@
+export const getTotalPages = (counts: { [key: string]: { count: number | undefined } }, pageSize: number) => {
+ return Object.keys(counts).reduce((total, key) => {
+ return total + Math.ceil((counts[key].count ?? 0) / pageSize) * pageSize
+ }, 0)
+}
diff --git a/apps/schools/domains/employee/components/createEmployeeForm/index.tsx b/apps/schools/domains/employee/components/createEmployeeForm/index.tsx
index 1660b138..239b47e1 100644
--- a/apps/schools/domains/employee/components/createEmployeeForm/index.tsx
+++ b/apps/schools/domains/employee/components/createEmployeeForm/index.tsx
@@ -48,8 +48,8 @@ export const CreateEmployeeForm = () => {
required={true}
label={
- * Телефон сотрудника
-
+ * Телефон сотрудника
+
}
name={EMPLOYEE_PHONE}
className={styles.label}
@@ -62,8 +62,8 @@ export const CreateEmployeeForm = () => {
required
label={
- * Ф. И. О. сотрудника
-
+ * Ф. И. О. сотрудника
+
}
name={EMPLOYEE_NAME}
className={styles.label}
@@ -72,12 +72,7 @@ export const CreateEmployeeForm = () => {
-
+
diff --git a/apps/schools/domains/organization/redux/organizationApi.ts b/apps/schools/domains/organization/redux/organizationApi.ts
index 6dcafe3d..2307d8a5 100644
--- a/apps/schools/domains/organization/redux/organizationApi.ts
+++ b/apps/schools/domains/organization/redux/organizationApi.ts
@@ -37,6 +37,7 @@ import { mapReturnedData } from '@domains/common/redux/utils'
import { TableType as TableTypeCircle } from '@domains/circle/components/circleList/interfaces'
import { TableType as TableTypeTickets } from '@domains/ticket/components/ticketList/interfaces'
import { TableType as TableTypeQuery } from '@domains/query/components/queryList/interfaces'
+import { TableType as TableTypeStudent } from '@domains/student/components/studentList/interfaces'
const organizationApi = commonApi.injectEndpoints({
endpoints: (build) => ({
@@ -70,6 +71,17 @@ const organizationApi = commonApi.injectEndpoints({
method: 'GET',
params: params,
}),
+ transformResponse: (response: ReturnedData) => {
+ return mapReturnedData(response, (query) => {
+ const transformedQuery = structuredClone(query) as unknown as TableTypeStudent
+ transformedQuery.id = query.id
+ transformedQuery.student_name = query.name
+ transformedQuery.student_phone = query.student_profile.phone
+ transformedQuery.parent_phone = query.student_profile.parent_phones?.replaceAll(',', '\n')
+ transformedQuery.circle_name = query.circle.name
+ return transformedQuery
+ })!
+ },
providesTags: (result) => providesList(result?.results, 'Student'),
}),
getAllCircles: build.query, GetOrganizationCircleListData>({
@@ -168,6 +180,17 @@ const organizationApi = commonApi.injectEndpoints({
method: 'GET',
params: params,
}),
+ transformResponse: (response: ReturnedData) => {
+ return mapReturnedData(response, (query) => {
+ const transformedQuery = structuredClone(query) as unknown as TableTypeStudent
+ transformedQuery.id = query.body.id
+ transformedQuery.student_name = query.body.name
+ transformedQuery.student_phone = query.additional.phone
+ transformedQuery.parent_phone = query.recipient.parent_phones.replaceAll(',', '\n')
+ transformedQuery.circle_name = query.sender.name
+ return transformedQuery
+ })!
+ },
providesTags: (result) => providesList(result?.results, 'Student'),
}),
getAllJoinCircleQueries: build.query, AllStudentJoinCircleQueriesData>({
diff --git a/apps/schools/domains/student/components/createStudentForm/index.tsx b/apps/schools/domains/student/components/createStudentForm/index.tsx
index e61141c0..30b656b8 100644
--- a/apps/schools/domains/student/components/createStudentForm/index.tsx
+++ b/apps/schools/domains/student/components/createStudentForm/index.tsx
@@ -66,8 +66,8 @@ export const CreateStudentForm = () => {
- * Ф. И. О. обучающегося
-
+ * Ф. И. О. обучающегося
+
}
name={STUDENT_NAME}
className={styles.label}
@@ -82,8 +82,8 @@ export const CreateStudentForm = () => {
- * Телефон родителя
-
+ * Телефон родителя
+
}
name={PARENT_PHONE}
className={styles.label}
@@ -122,8 +122,8 @@ export const CreateStudentForm = () => {
- * Название кружка
-
+ * Название кружка
+
}
name={CIRCLES}
className={styles.label}
diff --git a/apps/schools/domains/student/components/studentList/index.tsx b/apps/schools/domains/student/components/studentList/index.tsx
index f5af871a..f035c9a2 100644
--- a/apps/schools/domains/student/components/studentList/index.tsx
+++ b/apps/schools/domains/student/components/studentList/index.tsx
@@ -1,4 +1,4 @@
-import React, { useState } from 'react'
+import React, { useCallback, useEffect, useState } from 'react'
import { Typography } from 'antd'
import router from 'next/router'
import styles from './styles/styles.module.scss'
@@ -14,8 +14,22 @@ import EmptyWrapper from '@domains/common/components/containers/EmptyWrapper'
import { AppRoutes, RoutePath } from '@domains/common/constants/routerEnums'
import { defaultPaginationTablePage, defaultPaginationTablePageSize } from '@domains/common/constants/Table'
import { scrollToTop } from '@domains/common/utils/scrollInDirection'
+import { handlePaginationChange } from '@domains/common/handlers/paginationChange'
+import { calculateResults } from '@domains/student/handlers/resultsCalculate'
+import { getTotalPages } from '@domains/common/utils/getTotalPages'
export function StudentList() {
+ const [queryPaginationParams, setQueryPaginationParams] = useState({
+ invites: {
+ page: defaultPaginationTablePage,
+ pageSize: defaultPaginationTablePageSize,
+ },
+ students: {
+ page: defaultPaginationTablePage,
+ pageSize: defaultPaginationTablePageSize,
+ },
+ })
+
const [searchRequestText, setSearchRequestText] = useState('')
const { organizationId } = useOrganization()
@@ -23,6 +37,15 @@ export function StudentList() {
circle__organization__id: organizationId,
status: StatusesEnum.SENT,
or_search: createSearchTextForRequest(searchRequestText, searchInvitesColumns),
+ page: queryPaginationParams.invites.page,
+ page_size: queryPaginationParams.invites.pageSize,
+ })
+
+ const { data: students, isFetching: isFetchingStudents } = useGetAllStudentsQuery({
+ circle__organization: organizationId,
+ or_search: createSearchTextForRequest(searchRequestText, searchStudentsColumns),
+ page: queryPaginationParams.students.page,
+ page_size: queryPaginationParams.students.pageSize,
})
const [paginationParams, setPaginationParams] = useState({
@@ -30,40 +53,32 @@ export function StudentList() {
pageSize: defaultPaginationTablePageSize,
})
- const { data: students, isFetching: isFetchingStudents } = useGetAllStudentsQuery({
- circle__organization: organizationId,
- or_search: createSearchTextForRequest(searchRequestText, searchStudentsColumns),
- page: paginationParams.page,
- page_size: paginationParams.pageSize,
- })
+ const resultsCalculate = useCallback(
+ () => calculateResults(paginationParams, { invites, students }),
+ [paginationParams, invites, students],
+ )
const data = {
count: (invites?.count ?? 0) + (students?.count ?? 0),
next: invites?.next ?? '',
previous: invites?.previous ?? '',
- results: (invites?.results ?? [])
- .map(
- (x) =>
- ({
- id: x.body.id,
- student_name: x.body.name,
- student_phone: x.additional.phone,
- parent_phone: x.recipient.parent_phones.replaceAll(',', '\n'),
- circle_name: x.sender.name,
- }) as RowType,
- )
- .concat(
- (students?.results ?? []).map(
- (x) =>
- ({
- id: x.id,
- student_name: x.name,
- student_phone: x.student_profile.phone,
- parent_phone: x.student_profile.parent_phones?.replaceAll(',', '\n'),
- circle_name: x.circle.name,
- }) as RowType,
- ),
- ),
+ results: resultsCalculate(),
+ }
+
+ const handlePageChange = (newPage: number, newPageSize: number) => {
+ handlePaginationChange(
+ setPaginationParams,
+ setQueryPaginationParams as any,
+ {
+ invites: invites?.count,
+ students: students?.count,
+ },
+ newPage,
+ newPageSize,
+ defaultPaginationTablePage,
+ defaultPaginationTablePageSize,
+ scrollToTop,
+ )
}
return (
@@ -99,13 +114,12 @@ export function StudentList() {
pagination={{
current: paginationParams.page,
pageSize: paginationParams.pageSize,
- total: students?.count,
+ total: getTotalPages(
+ { invites: { count: invites?.count }, students: { count: students?.count } },
+ paginationParams.pageSize,
+ ),
onChange: (page, pageSize) => {
- setPaginationParams({
- page,
- pageSize,
- })
- scrollToTop()
+ handlePageChange(page, pageSize)
},
}}
filterFields={['circle_name']}
diff --git a/apps/schools/domains/student/handlers/resultsCalculate.ts b/apps/schools/domains/student/handlers/resultsCalculate.ts
new file mode 100644
index 00000000..b1fcde23
--- /dev/null
+++ b/apps/schools/domains/student/handlers/resultsCalculate.ts
@@ -0,0 +1,23 @@
+import { RowType } from '@domains/student/components/studentList/interfaces'
+
+export const calculateResults = (
+ paginationParams: { page: number; pageSize: number },
+ data: {
+ [key: string]: { count: number | undefined; results: any[] } | undefined
+ },
+): RowType[] => {
+ const dataArray = Object.values(data)
+ const pageIndex = paginationParams.page - 1
+ let offset = 0
+
+ for (const item of dataArray) {
+ const count = item?.count ?? 0
+ const pageCount = Math.ceil(count / paginationParams.pageSize)
+ if (pageIndex < offset + pageCount) {
+ return item?.results ?? []
+ }
+ offset += pageCount
+ }
+
+ return []
+}
diff --git a/apps/schools/domains/user/components/auth/registerForm/index.tsx b/apps/schools/domains/user/components/auth/registerForm/index.tsx
index a9c1c849..2bd20dd7 100644
--- a/apps/schools/domains/user/components/auth/registerForm/index.tsx
+++ b/apps/schools/domains/user/components/auth/registerForm/index.tsx
@@ -1,5 +1,5 @@
import { Col, Form, Row } from 'antd'
-import React, {PropsWithChildren, useCallback, useContext, useEffect, useState} from 'react'
+import React, { PropsWithChildren, useCallback, useContext, useEffect, useState } from 'react'
import styles from '../styles/formStyles.module.scss'
import { ResponsiveCol } from '../containers/ResponsiveCol'
@@ -10,9 +10,9 @@ import { IRegisterFormProps } from './interfaces'
import { BUTTON_FORM_GUTTER_20 } from '../constants/styles'
import { FirebaseReCaptchaContext } from '@domains/user/providers/firebaseReCaptchaProvider'
import { registrationHandler } from '@domains/user/handlers/auth/register'
-import {useUsersMutation} from '@domains/user/redux/userApi'
-import {useUpdateEmployeeProfileByIdMutation} from "@domains/employee/redux/employeeApi";
-import {useLazyGetUserQuery} from "@domains/user/redux/authenticationApi";
+import { useUsersMutation } from '@domains/user/redux/userApi'
+import { useUpdateEmployeeProfileByIdMutation } from '@domains/employee/redux/employeeApi'
+import { useLazyGetUserQuery } from '@domains/user/redux/authenticationApi'
const RequiredFlagWrapper: React.FC> = (props) => {
return {props.children}
@@ -30,35 +30,34 @@ export const RegisterForm: React.FC = ({ onFinish, onError }
signInByPhone: () => {},
}
- const [updateProfile] = useUpdateEmployeeProfileByIdMutation();
- const [getLazyUser, {data}] = useLazyGetUserQuery();
+ const [updateProfile] = useUpdateEmployeeProfileByIdMutation()
+ const [getLazyUser, { data }] = useLazyGetUserQuery()
const registerComplete = useCallback(() => {
- const { password } = form.getFieldsValue(['password']);
+ const { password } = form.getFieldsValue(['password'])
- registrationHandler(phone, password, userRegistration, onError, form)
- .then(async () => {
- await getLazyUser({});
- });
- }, [form, signInByPhone, getLazyUser]);
+ registrationHandler(phone, password, userRegistration, onError, form).then(async () => {
+ await getLazyUser({})
+ })
+ }, [form, signInByPhone, getLazyUser])
useEffect(() => {
- const { email } = form.getFieldsValue(['email']);
- const { name } = form.getFieldsValue(['name']);
+ const { email } = form.getFieldsValue(['email'])
+ const { name } = form.getFieldsValue(['name'])
if (data && data.user.employee_profile?.id) {
const updateEmail = {
employee_profile_id: data.user.employee_profile.id,
name: name,
- email: email
- };
- updateProfile(updateEmail);
- onFinish();
+ email: email,
+ }
+ updateProfile(updateEmail)
+ onFinish()
}
- }, [data, updateProfile]);
+ }, [data, updateProfile])
const initialValues = {
- phone
+ phone,
}
return (
@@ -104,10 +103,7 @@ export const RegisterForm: React.FC = ({ onFinish, onError }
data-cy='register-email-item'
validateFirst
>
-
+
diff --git a/apps/schools/domains/user/handlers/auth/register.ts b/apps/schools/domains/user/handlers/auth/register.ts
index 648de720..356a3ef0 100644
--- a/apps/schools/domains/user/handlers/auth/register.ts
+++ b/apps/schools/domains/user/handlers/auth/register.ts
@@ -80,14 +80,14 @@ export async function registrationHandler(
password: string,
userRegistrationMutation: any,
onError: () => void,
- formComponent: FormInstance
+ formComponent: FormInstance,
) {
let token = localStorage.getItem('token')
const cookies = new Cookies()
cookies.remove('jwtToken')
- const { email } = formComponent.getFieldsValue(['email']);
- const { name } = formComponent.getFieldsValue(['name']);
+ const { email } = formComponent.getFieldsValue(['email'])
+ const { name } = formComponent.getFieldsValue(['name'])
let response = await withLoadingMessage(LoadingMsg, userRegistrationMutation, {
token: token,
diff --git a/apps/schools/domains/user/redux/userApi.ts b/apps/schools/domains/user/redux/userApi.ts
index 1bf4f97a..f5463a82 100644
--- a/apps/schools/domains/user/redux/userApi.ts
+++ b/apps/schools/domains/user/redux/userApi.ts
@@ -53,9 +53,9 @@ const userApi = commonApi.injectEndpoints({
method: 'PATCH',
body: { otp: data.otp },
}),
- })
+ }),
}),
})
-export const { useTokenMutation, useVerifyMutation, useUsersMutation, useResetPasswordMutation, useResendMutation} =
+export const { useTokenMutation, useVerifyMutation, useUsersMutation, useResetPasswordMutation, useResendMutation } =
userApi