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

Implementing pagination in task progresses #1316

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 57 additions & 2 deletions __tests__/Unit/Components/Tasks/ProgressCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { setupServer } from 'msw/node';
import handlers from '../../../../__mocks__/handlers';
import { mockGetTaskProgress } from '../../../../__mocks__/db/progresses';
import ProgressCard from '@/components/ProgressCard';

import { useRouter } from 'next/router';
const server = setupServer(...handlers);

const dateMay29 = moment(mockGetTaskProgress.data[0].createdAt).fromNow();
Expand All @@ -28,17 +28,72 @@ beforeAll(() => {
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

jest.mock('@/hooks/useIntersection', () => {
return jest.fn().mockImplementation(() => ({
loadingRef: { current: {} },
onLoadMore: jest.fn(),
}));
});

jest.mock('next/router', () => ({
useRouter: jest.fn(),
}));

describe('ProgressCard Component', () => {
const mockFetchMoreProgresses = jest.fn();

it('should render the ProgressCard', async () => {
const mockRouter = {
query: { dev: 'false' },
};
(useRouter as jest.Mock).mockReturnValue(mockRouter);
renderWithRouter(
<Provider store={store()}>
<ProgressCard taskProgress={mockGetTaskProgress.data} />
<ProgressCard
taskProgress={mockGetTaskProgress.data}
fetchMoreProgresses={mockFetchMoreProgresses}
isFetchingProgress={false}
devFlag={false}
/>
</Provider>
);
const progress = screen.getByTestId('progressCard');
expect(progress).toBeInTheDocument();
expect(progress).toHaveTextContent('Progress Updates');
});

it('should show loading ref only when devFlag is true', () => {
const mockRouter = {
query: { dev: 'true' },
};
(useRouter as jest.Mock).mockReturnValue(mockRouter);
const { rerender } = renderWithRouter(
<Provider store={store()}>
<ProgressCard
taskProgress={mockGetTaskProgress.data}
fetchMoreProgresses={mockFetchMoreProgresses}
isFetchingProgress={false}
devFlag={false}
/>
</Provider>
);

expect(screen.queryByText('Loading...')).not.toBeInTheDocument();

rerender(
<Provider store={store()}>
<ProgressCard
taskProgress={mockGetTaskProgress.data}
fetchMoreProgresses={mockFetchMoreProgresses}
isFetchingProgress={true}
devFlag={true}
/>
</Provider>
);

expect(screen.getByText('Loading...')).toBeInTheDocument();
});

it('should render Asc/Dsc button ', async () => {
const { getByRole } = renderWithRouter(
<Provider store={store()}>
Expand Down
13 changes: 11 additions & 2 deletions __tests__/Unit/Components/Tasks/TaskDetails.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ jest.mock('@/hooks/useUserData', () => {
});
});

jest.mock('@/hooks/useIntersection', () => {
return jest.fn().mockImplementation(() => ({
loadingRef: { current: {} },
onLoadMore: jest.fn(),
}));
});

const mockNavigateToUpdateProgressPage = jest.fn();
const mockHandleEditedTaskDetails = jest.fn();

Expand Down Expand Up @@ -464,8 +471,10 @@ test('Should render No task progress', async () => {
progressUpdatesSection = screen.getByText('Progress Updates');
});
expect(progressUpdatesSection).toBeInTheDocument();
const noProgressText = screen.getByText('No Progress found');
expect(noProgressText).toBeInTheDocument();
await waitFor(() => {
const noProgressText = screen.getByText('No Progress found');
expect(noProgressText).toBeInTheDocument();
});
});

test('should call progress details query', async () => {
Expand Down
6 changes: 4 additions & 2 deletions src/app/services/progressesApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ type queryParamsType = {
userId?: string;
taskId?: string;
dev?: boolean;
size?: number;
page?: number;
};

export const progressesApi = api.injectEndpoints({
Expand All @@ -21,10 +23,10 @@ export const progressesApi = api.injectEndpoints({
}),
}),
getProgressDetails: builder.query<progressDetails, queryParamsType>({
query: ({ userId, taskId, dev }: queryParamsType) => {
query: ({ userId, taskId, dev, size, page }: queryParamsType) => {
return {
url: '/progresses',
params: { userId, taskId, dev },
params: { userId, taskId, dev, size, page },
};
},
providesTags: ['Progress_Details'],
Expand Down
7 changes: 7 additions & 0 deletions src/components/ProgressCard/ProgressCard.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,10 @@
margin-left: 0.25rem;
cursor: pointer;
}

.loadingContainer {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
}
38 changes: 33 additions & 5 deletions src/components/ProgressCard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,38 @@
import React, { useEffect, useState } from 'react';
import React, { ElementRef, useEffect, useRef, useState } from 'react';
import TaskContainer from '../taskDetails/TaskContainer';
import { ProgressDetailsData } from '@/types/standup.type';
import styles from '@/components/ProgressCard/ProgressCard.module.scss';
import LatestProgressUpdateCard from '../taskDetails/ProgressUpdateCard/LatestProgressUpdateCard';
import ProgressUpdateCard from '../taskDetails/ProgressUpdateCard/ProgressUpdateCard';

import useIntersection from '@/hooks/useIntersection';
type SortedProgressType = { data: ProgressDetailsData[]; order: number };

type Props = { taskProgress: ProgressDetailsData[] };
type Props = {
taskProgress: ProgressDetailsData[];
fetchMoreProgresses: () => void;
isFetchingProgress: boolean;
devFlag: boolean;
};

export default function ProgressCard({ taskProgress }: Props) {
export default function ProgressCard({
taskProgress,
fetchMoreProgresses,
isFetchingProgress,
devFlag,
}: Props) {
const [sortedProgress, setSortedProgress] = useState<SortedProgressType>();
const sortedProgressLength = sortedProgress?.data?.length;

const loadingRef = useRef<ElementRef<'div'>>(null);
const [hasFetched, setHasFetched] = useState(false);
useIntersection({
loadingRef,
onLoadMore: () => {
if (hasFetched) {
fetchMoreProgresses();
}
},
earlyReturn: sortedProgressLength === 0,
});
const reverseSortingOrder = () => {
if (sortedProgress && sortedProgressLength) {
const newSortedArr: ProgressDetailsData[] = [];
Expand All @@ -38,6 +58,7 @@ export default function ProgressCard({ taskProgress }: Props) {
: 1;
});
setSortedProgress({ data: sorted, order: 1 });
setHasFetched(true);
}
}, [taskProgress]);

Expand Down Expand Up @@ -82,9 +103,16 @@ export default function ProgressCard({ taskProgress }: Props) {
>
{sortedProgress && sortedProgressLength ? (
<div>{cardsToShow}</div>
) : isFetchingProgress ? (
''
) : (
'No Progress found'
)}
{devFlag && (
<div ref={loadingRef} className={styles.loadingContainer}>
{isFetchingProgress && 'Loading...'}
</div>
)}
</TaskContainer>
);
}
53 changes: 46 additions & 7 deletions src/components/taskDetails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,48 @@ const TaskDetails: FC<Props> = ({ taskID }) => {
const { isUserAuthorized } = useUserData();
const [isEditing, setIsEditing] = useState<boolean>(false);
const [isOpen, setIsOpen] = useState<boolean>(false);
const [page, setPage] = useState<number>(0);
const [loading, setLoading] = useState<boolean>(false);
const [progressesDataPaginated, setProgressesDataPaginated] = useState<
ProgressDetailsData[]
>([]);
const { data, isError, isLoading, isFetching, refetch } =
useGetTaskDetailsQuery(taskID);
const { data: extensionRequests } =
useGetExtensionRequestDetailsQuery(taskID);
const { data: progressData, refetch: refetchProgress } =
useGetProgressDetailsQuery({
taskId: taskID,
dev: isDev,
const {
data: progressData,
refetch: refetchProgress,
isFetching: isFetchingProgress,
} = useGetProgressDetailsQuery({
taskId: taskID,
dev: isDev,
size: 10,
page: page,
});

useEffect(() => {
setProgressesDataPaginated((prevProgressesDataPaginated) => {
if (progressData?.data) {
return [...prevProgressesDataPaginated, ...progressData.data];
}
return prevProgressesDataPaginated;
});
}, [progressData]);

const fetchMoreProgresses = () => {
if (progressData?.links?.next) {
const nextPageUrl = progressData.links.next;
const urlParams = new URLSearchParams(nextPageUrl.split('?')[1]);
const nextPage = parseInt(urlParams.get('page') || '0', 10);
setPage(nextPage);
}
};
useEffect(() => {
if (page > 0) {
refetchProgress();
}
}, [page, refetchProgress]);

const isExtensionRequestPending = Boolean(
extensionRequests?.allExtensionRequests.length
Expand Down Expand Up @@ -224,8 +256,10 @@ const TaskDetails: FC<Props> = ({ taskID }) => {
}

const shouldRenderParentContainer = () => !isLoading && !isError && data;

const taskProgress: ProgressDetailsData[] = progressData?.data || [];
const progressDataToSend = isDev
? progressesDataPaginated
: progressData?.data || [];
const taskProgress: ProgressDetailsData[] = progressDataToSend || [];

return (
<Layout hideHeader={true}>
Expand Down Expand Up @@ -271,7 +305,12 @@ const TaskDetails: FC<Props> = ({ taskID }) => {
taskDetailsData={taskDetailsData}
/>
</TaskContainer>
<Progress taskProgress={taskProgress} />
<Progress
taskProgress={taskProgress}
fetchMoreProgresses={fetchMoreProgresses}
isFetchingProgress={isFetchingProgress}
devFlag={isDev}
/>
<TaskContainer
title="Task Dependencies"
hasImg={false}
Expand Down
6 changes: 5 additions & 1 deletion src/types/standup.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,15 @@ export type ProgressDetailsData = {
userData?: userDataType;
taskId?: string;
};

type Links = {
prev: string | null;
next: string | null;
};
export type progressDetails = {
data: Array<ProgressDetailsData>;
message: string;
count: number;
links?: Links;
};

type Section = {
Expand Down
Loading