Skip to content

Commit

Permalink
feat: implement loading data after tab chenged (#2526)
Browse files Browse the repository at this point in the history
* feat: implement showing preselected courses after invitation without reloading page

* refactor: remove unused imports

* refactor: remove redundant type assertion

* fix: fix eslit issue

* feat: implement loading data after tab chenged

* fix: fix eslint issues
  • Loading branch information
Alphajax authored Sep 15, 2024
1 parent cb0b76f commit 35a5164
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 48 deletions.
22 changes: 15 additions & 7 deletions client/src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16150,6 +16150,7 @@ export const RegistryApiAxiosParamCreator = function (configuration?: Configurat
},
/**
*
* @param {'new' | 'all'} [status]
* @param {number} [pageSize]
* @param {number} [currentPage]
* @param {string} [githubId]
Expand All @@ -16160,7 +16161,7 @@ export const RegistryApiAxiosParamCreator = function (configuration?: Configurat
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getMentorRegistries: async (pageSize?: number, currentPage?: number, githubId?: string, cityName?: string, preferedCourses?: Array<number>, preselectedCourses?: Array<number>, technicalMentoring?: Array<string>, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
getMentorRegistries: async (status?: 'new' | 'all', pageSize?: number, currentPage?: number, githubId?: string, cityName?: string, preferedCourses?: Array<number>, preselectedCourses?: Array<number>, technicalMentoring?: Array<string>, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/registry/mentors`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
Expand All @@ -16173,6 +16174,10 @@ export const RegistryApiAxiosParamCreator = function (configuration?: Configurat
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;

if (status !== undefined) {
localVarQueryParameter['status'] = status;
}

if (pageSize !== undefined) {
localVarQueryParameter['pageSize'] = pageSize;
}
Expand Down Expand Up @@ -16291,6 +16296,7 @@ export const RegistryApiFp = function(configuration?: Configuration) {
},
/**
*
* @param {'new' | 'all'} [status]
* @param {number} [pageSize]
* @param {number} [currentPage]
* @param {string} [githubId]
Expand All @@ -16301,8 +16307,8 @@ export const RegistryApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async getMentorRegistries(pageSize?: number, currentPage?: number, githubId?: string, cityName?: string, preferedCourses?: Array<number>, preselectedCourses?: Array<number>, technicalMentoring?: Array<string>, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<FilterMentorRegistryResponse>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getMentorRegistries(pageSize, currentPage, githubId, cityName, preferedCourses, preselectedCourses, technicalMentoring, options);
async getMentorRegistries(status?: 'new' | 'all', pageSize?: number, currentPage?: number, githubId?: string, cityName?: string, preferedCourses?: Array<number>, preselectedCourses?: Array<number>, technicalMentoring?: Array<string>, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<FilterMentorRegistryResponse>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getMentorRegistries(status, pageSize, currentPage, githubId, cityName, preferedCourses, preselectedCourses, technicalMentoring, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
Expand Down Expand Up @@ -16356,6 +16362,7 @@ export const RegistryApiFactory = function (configuration?: Configuration, baseP
},
/**
*
* @param {'new' | 'all'} [status]
* @param {number} [pageSize]
* @param {number} [currentPage]
* @param {string} [githubId]
Expand All @@ -16366,8 +16373,8 @@ export const RegistryApiFactory = function (configuration?: Configuration, baseP
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getMentorRegistries(pageSize?: number, currentPage?: number, githubId?: string, cityName?: string, preferedCourses?: Array<number>, preselectedCourses?: Array<number>, technicalMentoring?: Array<string>, options?: any): AxiosPromise<FilterMentorRegistryResponse> {
return localVarFp.getMentorRegistries(pageSize, currentPage, githubId, cityName, preferedCourses, preselectedCourses, technicalMentoring, options).then((request) => request(axios, basePath));
getMentorRegistries(status?: 'new' | 'all', pageSize?: number, currentPage?: number, githubId?: string, cityName?: string, preferedCourses?: Array<number>, preselectedCourses?: Array<number>, technicalMentoring?: Array<string>, options?: any): AxiosPromise<FilterMentorRegistryResponse> {
return localVarFp.getMentorRegistries(status, pageSize, currentPage, githubId, cityName, preferedCourses, preselectedCourses, technicalMentoring, options).then((request) => request(axios, basePath));
},
/**
*
Expand Down Expand Up @@ -16425,6 +16432,7 @@ export class RegistryApi extends BaseAPI {

/**
*
* @param {'new' | 'all'} [status]
* @param {number} [pageSize]
* @param {number} [currentPage]
* @param {string} [githubId]
Expand All @@ -16436,8 +16444,8 @@ export class RegistryApi extends BaseAPI {
* @throws {RequiredError}
* @memberof RegistryApi
*/
public getMentorRegistries(pageSize?: number, currentPage?: number, githubId?: string, cityName?: string, preferedCourses?: Array<number>, preselectedCourses?: Array<number>, technicalMentoring?: Array<string>, options?: AxiosRequestConfig) {
return RegistryApiFp(this.configuration).getMentorRegistries(pageSize, currentPage, githubId, cityName, preferedCourses, preselectedCourses, technicalMentoring, options).then((request) => request(this.axios, this.basePath));
public getMentorRegistries(status?: 'new' | 'all', pageSize?: number, currentPage?: number, githubId?: string, cityName?: string, preferedCourses?: Array<number>, preselectedCourses?: Array<number>, technicalMentoring?: Array<string>, options?: AxiosRequestConfig) {
return RegistryApiFp(this.configuration).getMentorRegistries(status, pageSize, currentPage, githubId, cityName, preferedCourses, preselectedCourses, technicalMentoring, options).then((request) => request(this.axios, this.basePath));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { Form, Table, TablePaginationConfig } from 'antd';
import FilteredTags from 'modules/Schedule/components/FilteredTags';
import { FilterValue } from 'antd/lib/table/interface';
import { MentorRegistryDto } from 'api';
import { MentorsRegistryColumnKey, PAGINATION } from '../constants';
import { MentorRegistryTabsMode, MentorsRegistryColumnKey, PAGINATION } from '../constants';
import { ColumnType } from 'antd/lib/table';

type Props = {
setCurrentPage: Dispatch<SetStateAction<number>>;
total: number;
total: Record<MentorRegistryTabsMode, number>;
currentPage: number;
tagFilters: string[];
filteredData: MentorRegistryDto[];
Expand All @@ -19,6 +19,7 @@ type Props = {
_: TablePaginationConfig,
filters: Record<MentorsRegistryColumnKey, FilterValue | string[] | null>,
) => void;
activeTab: MentorRegistryTabsMode;
};

export function MentorRegistryTable(props: Props) {
Expand All @@ -32,6 +33,7 @@ export function MentorRegistryTable(props: Props) {
handleClearAllButtonClick,
handleTableChange,
setCurrentPage,
activeTab,
} = props;
const [form] = Form.useForm();

Expand All @@ -44,7 +46,7 @@ export function MentorRegistryTable(props: Props) {
onClearAllButtonClick={handleClearAllButtonClick}
/>
<Table<MentorRegistryDto>
pagination={{ pageSize: PAGINATION, current: currentPage, onChange: setCurrentPage, total }}
pagination={{ pageSize: PAGINATION, current: currentPage, onChange: setCurrentPage, total: total[activeTab] }}
rowKey="id"
dataSource={filteredData}
scroll={{ x: tableWidth, y: 'calc(95vh - 340px)' }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ import css from 'styled-jsx/css';
interface ChildrenProp {
setCurrentPage: Dispatch<SetStateAction<number>>;
currentPage: number;
total: number;
total: Record<MentorRegistryTabsMode, number>;
tagFilters: string[];
filteredData: MentorRegistryDto[];
columns: ColumnType<MentorRegistryDto>[];
handleTagClose: (tag: string) => void;
handleClearAllButtonClick: () => void;
handleTableChange: (_: any, filters: Record<MentorsRegistryColumnKey, FilterValue | string[] | null>) => void;
activeTab: MentorRegistryTabsMode;
}

interface Props {
Expand All @@ -39,7 +40,7 @@ interface Props {
setCombinedFilter: Dispatch<SetStateAction<CombinedFilter>>;
setCurrentPage: Dispatch<SetStateAction<number>>;
currentPage: number;
total: number;
total: Record<MentorRegistryTabsMode, number>;
}

export interface CombinedFilter {
Expand All @@ -49,6 +50,7 @@ export interface CombinedFilter {
githubId: string[];
cityName: string[];
filterTags?: string[];
status: MentorRegistryTabsMode;
}

export const MentorRegistryTableContainer = ({
Expand Down Expand Up @@ -119,6 +121,7 @@ export const MentorRegistryTableContainer = ({
technicalMentoring: filters.technicalMentoring?.map(discipline => discipline.toString()) ?? [],
githubId: filters.githubId?.map(discipline => discipline.toString()) ?? [],
cityName: filters.cityName?.map(discipline => discipline.toString()) ?? [],
status: activeTab,
};

const filterTag: string[] = [
Expand Down Expand Up @@ -349,13 +352,14 @@ export const MentorRegistryTableContainer = ({
};

const handleClearAllButtonClick = () => {
setCombinedFilter({
setCombinedFilter(prev => ({
preferredCourses: [],
technicalMentoring: [],
preselectedCourses: [],
githubId: [],
cityName: [],
});
status: prev.status,
}));
setTagFilters([]);
};

Expand All @@ -369,6 +373,7 @@ export const MentorRegistryTableContainer = ({
handleClearAllButtonClick,
handleTableChange,
setCurrentPage,
activeTab,
});
};

Expand Down
58 changes: 24 additions & 34 deletions client/src/pages/admin/mentor-registry.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useState, useMemo, useEffect, useContext } from 'react';
import { useCallback, useState, useMemo, useContext } from 'react';
import { useAsync } from 'react-use';
import FileExcelOutlined from '@ant-design/icons/FileExcelOutlined';
import { Alert, Button, Col, Form, message, notification, Row, Select, Space, Tabs, Typography } from 'antd';
Expand Down Expand Up @@ -56,7 +56,6 @@ function Page() {

const [courses, setCourses] = useState<Course[]>([]);
const [modalLoading, setModalLoading] = useState(false);
const [showAll, setShowAll] = useState(false);
const [data, setData] = useState<MentorRegistryDto[]>([]);
const [allData, setAllData] = useState<MentorRegistryDto[]>([]);
const [maxStudents, setMaxStudents] = useState(0);
Expand All @@ -71,20 +70,18 @@ function Page() {
technicalMentoring: [],
githubId: [],
cityName: [],
status: MentorRegistryTabsMode.New,
});
const [currentPage, setCurrentPage] = useState(1);
const [total, setTotal] = useState(0);

const updateData = (showAll: boolean, allData: MentorRegistryDto[]) => {
setShowAll(showAll);
const data = filterData(allData, showAll);
setData(data);
setMaxStudents(data.reduce((sum, it) => sum + it.maxStudentsLimit, 0));
};
const [total, setTotal] = useState({
[MentorRegistryTabsMode.New]: 0,
[MentorRegistryTabsMode.All]: 0,
});

const loadData = withLoading(async () => {
const [allData, courses] = await Promise.all([
mentorRegistryService.getMentors({
status: activeTab,
pageSize: PAGINATION,
currentPage,
githubId: combinedFilter.githubId?.[0] ?? undefined,
Expand All @@ -101,9 +98,10 @@ function Page() {
]);
const { data: disciplines } = await disciplinesApi.getDisciplines();
setAllData(allData.mentors);
setTotal(allData.total);
setData(allData.mentors);
setTotal(total => ({ ...total, [activeTab]: allData.total }));
setMaxStudents(allData.mentors.reduce((sum, it) => sum + it.maxStudentsLimit, 0));
setCourses(courses);
updateData(showAll, allData.mentors);
setDisciplines(disciplines);
});

Expand All @@ -126,7 +124,7 @@ function Page() {
}
});

useAsync(loadData, [combinedFilter, currentPage]);
useAsync(loadData, [combinedFilter, currentPage, activeTab]);

const openNotificationWithIcon = (type: NotificationType) => {
api[type]({
Expand Down Expand Up @@ -201,20 +199,24 @@ function Page() {

const tabs = useMemo(() => {
const tabs = [
{ key: MentorRegistryTabsMode.New, label: 'New applications', count: filterData(allData, false).length },
{ key: MentorRegistryTabsMode.All, label: 'All Mentors', count: allData.length },
{ key: MentorRegistryTabsMode.New, label: 'New applications', count: Number(total[MentorRegistryTabsMode.New]) },
{ key: MentorRegistryTabsMode.All, label: 'All Mentors', count: Number(total[MentorRegistryTabsMode.All]) },
];
return tabs.map(el => tabRenderer(el, activeTab));
}, [activeTab, allData]);

useEffect(() => {
activeTab === MentorRegistryTabsMode.New ? updateData(false, allData) : updateData(true, allData);
}, [activeTab, allData]);

const handleTabChange = useCallback(() => {
activeTab === MentorRegistryTabsMode.New
? setActiveTab(MentorRegistryTabsMode.All)
: setActiveTab(MentorRegistryTabsMode.New);
if (activeTab === MentorRegistryTabsMode.New) {
setActiveTab(MentorRegistryTabsMode.All);
setAllData([]);
setData([]);
setCurrentPage(1);
} else {
setActiveTab(MentorRegistryTabsMode.New);
setAllData([]);
setData([]);
setCurrentPage(1);
}
}, [activeTab]);

const handleModalDataChange = (mode: ModalDataMode, record: MentorRegistryDto) => {
Expand Down Expand Up @@ -306,18 +308,6 @@ function Page() {
);
}

function filterData(data: MentorRegistryDto[], showAll: boolean) {
if (showAll) {
return data;
}
return data.filter(
it =>
it.courses.length === 0 ||
!it.preselectedCourses.length ||
!it.preselectedCourses.every(c => it.courses.includes(c)),
);
}

export default function () {
return (
<ActiveCourseProvider>
Expand Down
3 changes: 3 additions & 0 deletions client/src/services/mentorRegistry.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import axios, { AxiosInstance, AxiosResponse } from 'axios';
import { MentorRegistryDto, RegistryApi, InviteMentorsDto } from 'api';
import { PreferredStudentsLocation } from 'common/enums/mentor';
import { MentorRegistryTabsMode } from 'modules/MentorRegistry/constants';

export type MentorResponse = {
preselectedCourses: number[];
Expand All @@ -18,6 +19,7 @@ export interface MentorRegistry {
}

export interface GetMentorRegistriesDto {
status: MentorRegistryTabsMode;
currentPage: number;
pageSize: number;
githubId?: string;
Expand Down Expand Up @@ -57,6 +59,7 @@ export class MentorRegistryService {
return response.data;
} else {
const response = await this.registryApi.getMentorRegistries(
options.status,
options.pageSize,
options.currentPage,
options.githubId,
Expand Down
8 changes: 8 additions & 0 deletions nestjs/src/registry/registry.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ import { DEFAULT_PAGE_NUMBER, DEFAULT_PAGE_SIZE } from './constants';
import { CourseInfo } from '@entities/session';
import { InviteMentorsDto } from './dto/invite-mentors.dto';

export enum MentorRegistryTabsMode {
New = 'new',
All = 'all',
}

@Controller('registry')
@ApiTags('registry')
@UseGuards(DefaultGuard, RoleGuard)
Expand Down Expand Up @@ -65,6 +70,7 @@ export class RegistryController {
@ApiOperation({ operationId: 'getMentorRegistries' })
@RequiredRoles([Role.Admin, CourseRole.Manager, CourseRole.Supervisor])
@ApiOkResponse({ type: FilterMentorRegistryResponse })
@ApiQuery({ name: 'status', required: false, enum: MentorRegistryTabsMode })
@ApiQuery({ name: 'pageSize', required: false, type: 'number' })
@ApiQuery({ name: 'currentPage', required: false, type: 'number' })
@ApiQuery({ name: 'githubId', required: false, type: 'string' })
Expand All @@ -74,6 +80,7 @@ export class RegistryController {
@ApiQuery({ name: 'technicalMentoring', required: false, type: 'string', isArray: true })
public async getMentorRegistries(
@Req() req: CurrentRequest,
@Query('status') status: MentorRegistryTabsMode = MentorRegistryTabsMode.All,
@Query('pageSize') pageSize?: number,
@Query('currentPage') currentPage?: number,
@Query('githubId') githubId?: string,
Expand Down Expand Up @@ -105,6 +112,7 @@ export class RegistryController {
)
.map(([key]) => Number(key)),
disciplineNames: req.user.isAdmin ? undefined : await this.getDisciplineNamesByCourseIds(req.user.courses),
status,
});
return {
total: data.total,
Expand Down
Loading

0 comments on commit 35a5164

Please sign in to comment.