Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/school 841/pagination student list #150

Merged
merged 18 commits into from
Jul 15, 2024
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ export const ChangeCircleForm = () => {
required={true}
label={
<span>
<span className={styles.requiredMark}>*</span> Название
</span>
<span className={styles.requiredMark}>*</span> Название
</span>
}
name={CIRCLE_NAME}
className={styles.label}
Expand Down
43 changes: 43 additions & 0 deletions apps/schools/domains/common/handlers/paginationChange.ts
Original file line number Diff line number Diff line change
@@ -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()
}
4 changes: 2 additions & 2 deletions apps/schools/domains/common/redux/serializers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
5 changes: 5 additions & 0 deletions apps/schools/domains/common/utils/getTotalPages.ts
Original file line number Diff line number Diff line change
@@ -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)
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ export const CreateEmployeeForm = () => {
required={true}
label={
<span>
<span className={styles.requiredMark}>*</span> Телефон сотрудника
</span>
<span className={styles.requiredMark}>*</span> Телефон сотрудника
</span>
}
name={EMPLOYEE_PHONE}
className={styles.label}
Expand All @@ -62,8 +62,8 @@ export const CreateEmployeeForm = () => {
required
label={
<span>
<span className={styles.requiredMark}>*</span> Ф. И. О. сотрудника
</span>
<span className={styles.requiredMark}>*</span> Ф. И. О. сотрудника
</span>
}
name={EMPLOYEE_NAME}
className={styles.label}
Expand All @@ -72,12 +72,7 @@ export const CreateEmployeeForm = () => {
<Input placeholder='Введите Ф. И. О. сотрудника' />
</Form.Item>

<Form.Item
label='Email сотрудника'
name={EMPLOYEE_EMAIL}
className={styles.label}
rules={validators.email}
>
<Form.Item label='Email сотрудника' name={EMPLOYEE_EMAIL} className={styles.label} rules={validators.email}>
<Input type='email' placeholder='Введите email сотрудника' />
</Form.Item>

Expand Down
23 changes: 23 additions & 0 deletions apps/schools/domains/organization/redux/organizationApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) => ({
Expand Down Expand Up @@ -70,6 +71,17 @@ const organizationApi = commonApi.injectEndpoints({
method: 'GET',
params: params,
}),
transformResponse: (response: ReturnedData<GetStudent[]>) => {
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<ReturnedData<TableTypeCircle[]>, GetOrganizationCircleListData>({
Expand Down Expand Up @@ -168,6 +180,17 @@ const organizationApi = commonApi.injectEndpoints({
method: 'GET',
params: params,
}),
transformResponse: (response: ReturnedData<GetCircleInviteStudent[]>) => {
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<ReturnedData<GetStudentJoinCircle[]>, AllStudentJoinCircleQueriesData>({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ export const CreateStudentForm = () => {
<Form.Item
label={
<span>
<span className={styles.requiredMark}>*</span> Ф. И. О. обучающегося
</span>
<span className={styles.requiredMark}>*</span> Ф. И. О. обучающегося
</span>
}
name={STUDENT_NAME}
className={styles.label}
Expand All @@ -82,8 +82,8 @@ export const CreateStudentForm = () => {
<Form.Item
label={
<span>
<span className={styles.requiredMark}>*</span> Телефон родителя
</span>
<span className={styles.requiredMark}>*</span> Телефон родителя
</span>
}
name={PARENT_PHONE}
className={styles.label}
Expand Down Expand Up @@ -122,8 +122,8 @@ export const CreateStudentForm = () => {
<Form.Item
label={
<span>
<span className={styles.requiredMark}>*</span> Название кружка
</span>
<span className={styles.requiredMark}>*</span> Название кружка
</span>
}
name={CIRCLES}
className={styles.label}
Expand Down
86 changes: 50 additions & 36 deletions apps/schools/domains/student/components/studentList/index.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -14,56 +14,71 @@ 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()

const { data: invites, isLoading: isLoadingInvites } = useGetAllStudentInvitationsQuery({
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({
page: defaultPaginationTablePage,
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 (
Expand Down Expand Up @@ -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']}
Expand Down
23 changes: 23 additions & 0 deletions apps/schools/domains/student/handlers/resultsCalculate.ts
Original file line number Diff line number Diff line change
@@ -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 []
}
Loading
Loading