Skip to content

Commit

Permalink
Merge pull request #150 from open-schools/fix/SCHOOL-841/pagination-s…
Browse files Browse the repository at this point in the history
…tudent-list

Fix/school 841/pagination student list
  • Loading branch information
zavarin-michael authored Jul 15, 2024
2 parents df809b1 + f1a0198 commit 41ad5fe
Show file tree
Hide file tree
Showing 12 changed files with 184 additions and 85 deletions.
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

0 comments on commit 41ad5fe

Please sign in to comment.