From 33777690fca16c9cde7f50d32b90c5f985a37cdf Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Tue, 19 Aug 2025 23:34:02 +0200 Subject: [PATCH 1/4] fix: sort from server side --- .../src/pages/copilot-requests/index.tsx | 14 ++++++++-- .../copilots/src/services/copilot-requests.ts | 27 +++++++++++-------- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/apps/copilots/src/pages/copilot-requests/index.tsx b/src/apps/copilots/src/pages/copilot-requests/index.tsx index 1f4cc6f64..e46d0cde1 100644 --- a/src/apps/copilots/src/pages/copilot-requests/index.tsx +++ b/src/apps/copilots/src/pages/copilot-requests/index.tsx @@ -1,4 +1,4 @@ -import { FC, useCallback, useContext, useMemo } from 'react' +import { FC, useCallback, useContext, useMemo, useState } from 'react' import { find } from 'lodash' import { NavigateFunction, Params, useNavigate, useParams } from 'react-router-dom' import classNames from 'classnames' @@ -27,6 +27,7 @@ import { Project } from '../../models/Project' import { CopilotRequestModal } from './copilot-request-modal' import styles from './CopilotRequestsPage.module.scss' +import { Sort } from '~/apps/admin/src/platform/gamification-admin/src/game-lib' const CopilotTableActions: FC<{request: CopilotRequest}> = props => { const navigate: NavigateFunction = useNavigate() @@ -136,6 +137,10 @@ const CopilotTableActions: FC<{request: CopilotRequest}> = props => { const CopilotRequestsPage: FC = () => { const navigate: NavigateFunction = useNavigate() const routeParams: Params = useParams() + const [sort, setSort] = useState({ + direction: 'desc', + fieldName: 'createdAt', + }); const { profile }: ProfileContextData = useContext(profileContext) const isAdminOrPM: boolean = useMemo( @@ -148,7 +153,7 @@ const CopilotRequestsPage: FC = () => { isValidating: requestsLoading, hasMoreCopilotRequests, setSize, - size }: CopilotRequestsResponse = useCopilotRequests() + size }: CopilotRequestsResponse = useCopilotRequests(sort) const viewRequestDetails = useMemo(() => ( routeParams.requestId && find(requests, { id: +routeParams.requestId }) as CopilotRequest @@ -234,6 +239,10 @@ const CopilotRequestsPage: FC = () => { setSize(size + 1) } + const onToggleSort = (s: Sort) => { + setSort(s); + } + // header button config const addNewRequestButton: ButtonProps = { label: 'New Copilot Request', @@ -260,6 +269,7 @@ const CopilotRequestsPage: FC = () => { data={tableData} moreToLoad={hasMoreCopilotRequests} onLoadMoreClick={loadMore} + onToggleSort={onToggleSort} /> {requestsLoading && } {viewRequestDetails && ( diff --git a/src/apps/copilots/src/services/copilot-requests.ts b/src/apps/copilots/src/services/copilot-requests.ts index 56af61630..af70da5f2 100644 --- a/src/apps/copilots/src/services/copilot-requests.ts +++ b/src/apps/copilots/src/services/copilot-requests.ts @@ -6,6 +6,8 @@ import { xhrGetAsync, xhrPatchAsync, xhrPostAsync } from '~/libs/core' import { buildUrl } from '~/libs/shared/lib/utils/url' import { CopilotRequest } from '../models/CopilotRequest' +import { Sort } from '~/apps/admin/src/platform/gamification-admin/src/game-lib' +import { getPaginatedAsync, PaginatedResponse } from '~/libs/core/lib/xhr/xhr-functions/xhr.functions' const baseUrl = `${EnvironmentConfig.API.V5}/projects` const PAGE_SIZE = 20 @@ -43,32 +45,35 @@ export type CopilotRequestsResponse = { * @param {string} [projectId] - Optional project ID to fetch copilot requests for a specific project. * @returns {CopilotRequestsResponse} - The response containing copilot requests. */ -export const useCopilotRequests = (projectId?: string): CopilotRequestsResponse => { +export const useCopilotRequests = (sort: Sort, projectId?: string): CopilotRequestsResponse => { + const getKey = (pageIndex: number, previousPageData: CopilotRequest[]): string | undefined => { if (previousPageData && previousPageData.length < PAGE_SIZE) return undefined const url = buildUrl(`${baseUrl}${projectId ? `/${projectId}` : ''}/copilots/requests`) return ` - ${url}?page=${pageIndex + 1}&pageSize=${PAGE_SIZE}&sort=createdAt desc + ${url}?page=${pageIndex + 1}&pageSize=${PAGE_SIZE}&sort=${sort.fieldName} ${sort.direction} ` } - const fetcher = (url: string): Promise => xhrGetAsync(url) - .then((data: any) => data.map(copilotRequestFactory)) + const fetcher = (url: string): Promise> => getPaginatedAsync(url) + .then((data: any) => { + return { + ...data, + data: data.data.map(copilotRequestFactory), + } + }) const { isValidating, data = [], size, setSize, - }: SWRInfiniteResponse = useSWRInfinite(getKey, fetcher, { + }: SWRInfiniteResponse> = useSWRInfinite(getKey, fetcher, { revalidateOnFocus: false, }) - - // Flatten data array - const copilotRequests = data ? data.flat() : [] - - const lastPage = data[data.length - 1] || [] - const hasMoreCopilotRequests = lastPage.length === PAGE_SIZE + const latestPage = data[data.length - 1] || {} + const copilotRequests = data.flatMap(page => page.data) + const hasMoreCopilotRequests = latestPage.page + 1 < latestPage.totalPages return { data: copilotRequests, hasMoreCopilotRequests, isValidating, setSize: (s: number) => { setSize(s) }, size } } From fa225690400307d451166af6c6990fa9cc93a12b Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Tue, 19 Aug 2025 23:48:23 +0200 Subject: [PATCH 2/4] fix: project type column --- src/apps/copilots/src/pages/copilot-requests/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/copilots/src/pages/copilot-requests/index.tsx b/src/apps/copilots/src/pages/copilot-requests/index.tsx index e46d0cde1..e23696ac1 100644 --- a/src/apps/copilots/src/pages/copilot-requests/index.tsx +++ b/src/apps/copilots/src/pages/copilot-requests/index.tsx @@ -200,7 +200,7 @@ const CopilotRequestsPage: FC = () => { }, { label: 'Type', - propertyName: 'type', + propertyName: 'projectType', type: 'text', }, { @@ -232,7 +232,7 @@ const CopilotRequestsPage: FC = () => { const tableData = useMemo(() => requests.map(request => ({ ...request, projectName: request.project?.name, - type: ProjectTypeLabels[request.projectType] ?? '', + projectType: ProjectTypeLabels[request.projectType] ?? '', })), [requests]) function loadMore(): void { From 3baf08a0b2f7f59dcfcad536d3ca699304ece2ee Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Wed, 20 Aug 2025 00:05:38 +0200 Subject: [PATCH 3/4] fix: lint --- .../src/pages/copilot-requests/index.tsx | 8 ++++---- .../copilots/src/services/copilot-requests.ts | 16 +++++++++------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/apps/copilots/src/pages/copilot-requests/index.tsx b/src/apps/copilots/src/pages/copilot-requests/index.tsx index e23696ac1..2bc53f485 100644 --- a/src/apps/copilots/src/pages/copilot-requests/index.tsx +++ b/src/apps/copilots/src/pages/copilot-requests/index.tsx @@ -18,6 +18,7 @@ import { } from '~/libs/ui' import { profileContext, ProfileContextData, UserRole } from '~/libs/core' import { EnvironmentConfig } from '~/config' +import { Sort } from '~/apps/admin/src/platform/gamification-admin/src/game-lib' import { ProjectTypeLabels } from '../../constants' import { approveCopilotRequest, CopilotRequestsResponse, useCopilotRequests } from '../../services/copilot-requests' @@ -27,7 +28,6 @@ import { Project } from '../../models/Project' import { CopilotRequestModal } from './copilot-request-modal' import styles from './CopilotRequestsPage.module.scss' -import { Sort } from '~/apps/admin/src/platform/gamification-admin/src/game-lib' const CopilotTableActions: FC<{request: CopilotRequest}> = props => { const navigate: NavigateFunction = useNavigate() @@ -140,7 +140,7 @@ const CopilotRequestsPage: FC = () => { const [sort, setSort] = useState({ direction: 'desc', fieldName: 'createdAt', - }); + }) const { profile }: ProfileContextData = useContext(profileContext) const isAdminOrPM: boolean = useMemo( @@ -239,8 +239,8 @@ const CopilotRequestsPage: FC = () => { setSize(size + 1) } - const onToggleSort = (s: Sort) => { - setSort(s); + function onToggleSort(s: Sort): void { + setSort(s) } // header button config diff --git a/src/apps/copilots/src/services/copilot-requests.ts b/src/apps/copilots/src/services/copilot-requests.ts index af70da5f2..a1b725b9d 100644 --- a/src/apps/copilots/src/services/copilot-requests.ts +++ b/src/apps/copilots/src/services/copilot-requests.ts @@ -4,11 +4,11 @@ import useSWRInfinite, { SWRInfiniteResponse } from 'swr/infinite' import { EnvironmentConfig } from '~/config' import { xhrGetAsync, xhrPatchAsync, xhrPostAsync } from '~/libs/core' import { buildUrl } from '~/libs/shared/lib/utils/url' - -import { CopilotRequest } from '../models/CopilotRequest' import { Sort } from '~/apps/admin/src/platform/gamification-admin/src/game-lib' import { getPaginatedAsync, PaginatedResponse } from '~/libs/core/lib/xhr/xhr-functions/xhr.functions' +import { CopilotRequest } from '../models/CopilotRequest' + const baseUrl = `${EnvironmentConfig.API.V5}/projects` const PAGE_SIZE = 20 @@ -46,7 +46,7 @@ export type CopilotRequestsResponse = { * @returns {CopilotRequestsResponse} - The response containing copilot requests. */ export const useCopilotRequests = (sort: Sort, projectId?: string): CopilotRequestsResponse => { - + const getKey = (pageIndex: number, previousPageData: CopilotRequest[]): string | undefined => { if (previousPageData && previousPageData.length < PAGE_SIZE) return undefined const url = buildUrl(`${baseUrl}${projectId ? `/${projectId}` : ''}/copilots/requests`) @@ -55,13 +55,15 @@ export const useCopilotRequests = (sort: Sort, projectId?: string): CopilotReque ` } - const fetcher = (url: string): Promise> => getPaginatedAsync(url) - .then((data: any) => { - return { + const fetcher = ( + url: string, + ): Promise> => getPaginatedAsync(url) + .then((data: any) => ( + { ...data, data: data.data.map(copilotRequestFactory), } - }) + )) const { isValidating, From b8e3be2fa992df295c09a05b363c250f496a4dab Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Wed, 20 Aug 2025 00:09:05 +0200 Subject: [PATCH 4/4] fix: column width of copilot requests table --- .../pages/copilot-requests/CopilotRequestsPage.module.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/apps/copilots/src/pages/copilot-requests/CopilotRequestsPage.module.scss b/src/apps/copilots/src/pages/copilot-requests/CopilotRequestsPage.module.scss index 8c5108caa..43f1e21e2 100644 --- a/src/apps/copilots/src/pages/copilot-requests/CopilotRequestsPage.module.scss +++ b/src/apps/copilots/src/pages/copilot-requests/CopilotRequestsPage.module.scss @@ -7,6 +7,10 @@ padding: $sp-2 0; } +.title { + max-width: 200px; +} + @media (max-width: 767px) { .title { min-width: 200px;