Skip to content

Commit

Permalink
refactor: my exam summaries pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
alstn113 committed Dec 24, 2024
1 parent 872442e commit 3b87f08
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 35 deletions.
7 changes: 5 additions & 2 deletions server/src/main/java/com/fluffy/exam/api/ExamController.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,14 @@ public ResponseEntity<PageResponse<ExamSummaryDto>> getPublishedExamSummaries(
}

@GetMapping("/api/v1/exams/mine")
public ResponseEntity<List<ExamSummaryDto>> getMyExamSummaries(
public ResponseEntity<PageResponse<ExamSummaryDto>> getMyExamSummaries(
@RequestParam(value = "status", defaultValue = "draft") ExamStatus status,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@Auth Accessor accessor
) {
List<ExamSummaryDto> response = examQueryService.getMyExamSummaries(status, accessor);
Pageable pageable = PageRequest.of(page, size);
PageResponse<ExamSummaryDto> response = examQueryService.getMyExamSummaries(status, pageable, accessor);

return ResponseEntity.ok(response);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ public PageResponse<ExamSummaryDto> getPublishedExamSummaries(Pageable pageable)
}

@Transactional(readOnly = true)
public List<ExamSummaryDto> getMyExamSummaries(ExamStatus status, Accessor accessor) {
return examRepository.findMySummaries(status, accessor.id());
public PageResponse<ExamSummaryDto> getMyExamSummaries(ExamStatus status, Pageable pageable, Accessor accessor) {
Page<ExamSummaryDto> examSummaries = examRepository.findMySummaries(status, pageable, accessor.id());

return PageResponse.of(examSummaries);
}

@Transactional(readOnly = true)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package com.fluffy.exam.domain;

import com.fluffy.exam.domain.dto.ExamSummaryDto;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

public interface ExamRepositoryCustom {

Page<ExamSummaryDto> findPublishedSummaries(Pageable pageable);

List<ExamSummaryDto> findMySummaries(ExamStatus status, Long memberId);
Page<ExamSummaryDto> findMySummaries(ExamStatus status, Pageable pageable, Long memberId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ public Page<ExamSummaryDto> findPublishedSummaries(Pageable pageable) {

return PageableExecutionUtils.getPage(content, pageable, countQuery::fetchOne);
}

@Override
public List<ExamSummaryDto> findMySummaries(ExamStatus status, Long memberId) {
return queryFactory
public Page<ExamSummaryDto> findMySummaries(ExamStatus status, Pageable pageable, Long memberId) {
List<ExamSummaryDto> content = queryFactory
.selectDistinct(new QExamSummaryDto(
exam.id,
exam.title.value,
Expand All @@ -101,6 +101,14 @@ public List<ExamSummaryDto> findMySummaries(ExamStatus status, Long memberId) {
exam.updatedAt
)
.orderBy(exam.updatedAt.desc())
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();

JPAQuery<Long> countQuery = queryFactory.select(exam.count())
.from(exam)
.where(exam.memberId.eq(memberId), exam.status.eq(status));

return PageableExecutionUtils.getPage(content, pageable, countQuery::fetchOne);
}
}
12 changes: 9 additions & 3 deletions web/src/api/examAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ export const ExamAPI = {
return data;
},

getMyExamSummaries: async (status: ExamStatusType) => {
const { data } = await apiV1Client.get<ExamSummaryResponse[]>('/exams/mine', {
params: { status },
getMyExamSummaries: async ({ page, size, status }: MyExamSummaryParams) => {
const { data } = await apiV1Client.get<PageResponse<ExamSummaryResponse>>('/exams/mine', {
params: { status, page, size },
});
return data;
},
Expand Down Expand Up @@ -75,6 +75,12 @@ export interface ExamSummaryResponse {
updatedAt: string;
}

export interface MyExamSummaryParams {
page: number;
size: number;
status: ExamStatusType;
}

interface AuthorResponse {
id: number;
name: string;
Expand Down
14 changes: 10 additions & 4 deletions web/src/hooks/api/exam/useGetMyExamSummaries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,23 @@ import { ExamAPI, ExamStatusType } from '@/api/examAPI.ts';

const useGetMyExamSummaries = (
status: ExamStatusType,
page: number = 0,
size: number = 12,
options: UseQueryOptionsOf<typeof ExamAPI.getMyExamSummaries> = {},
) => {
return useSuspenseQuery({
...options,
queryKey: getKey(status),
queryFn: fetcher(status),
queryKey: getKey(status, page, size),
queryFn: fetcher(status, page, size),
});
};

const getKey = (status: ExamStatusType) => ['my-exam-summaries', status];
const fetcher = (status: ExamStatusType) => () => ExamAPI.getMyExamSummaries(status);
const getKey = (status: ExamStatusType, page: number, size: number) => [
'myExamSummaries',
{ status, page, size },
];
const fetcher = (status: ExamStatusType, page: number, size: number) => () =>
ExamAPI.getMyExamSummaries({ status, page, size });

useGetMyExamSummaries.getKey = getKey;
useGetMyExamSummaries.fetcher = fetcher;
Expand Down
4 changes: 2 additions & 2 deletions web/src/pages/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const HomePage = () => {

const ExamListContent = () => {
const [page, setPage] = useState(1);
const { data } = useGetExamSummaries(page - 1); // page는 0부터 시작
const { data } = useGetExamSummaries(page - 1);
const { content, pageInfo } = data;

return (
Expand All @@ -27,7 +27,7 @@ const ExamListContent = () => {
return <ExamSummaryCard key={exam.id} exam={exam} />;
})}
</div>
<div className="flex justify-center mt-5">
<div className="flex justify-center mt-10">
<Pagination
color="primary"
showControls
Expand Down
65 changes: 48 additions & 17 deletions web/src/pages/dashboard/DashboardPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import AsyncBoundary from '@/components/AsyncBoundary';
import useGetMyExamSummaries from '@/hooks/api/exam/useGetMyExamSummaries';
import DraftExamCard from '@/components/dashboard/DraftExamCard';
import PublishedExamCard from '@/components/dashboard/PublishedExamCard';
import { Tab, Tabs } from '@nextui-org/react';
import { Pagination, Tab, Tabs } from '@nextui-org/react';
import { BsFillFileEarmarkCheckFill } from 'react-icons/bs';
import { PiPencilLineBold } from 'react-icons/pi';
import NewExamButton from '@/components/exams/NewExamButton';
import { useState } from 'react';

const DashboardPage = () => {
return (
Expand Down Expand Up @@ -64,40 +65,70 @@ const DashboardPage = () => {
};

const DraftExamContent = () => {
const { data } = useGetMyExamSummaries('DRAFT');
const [page, setPage] = useState(1);
const { data } = useGetMyExamSummaries('DRAFT', page - 1);
const { content, pageInfo } = data;

if (!data || data.length === 0) {
if (!content || pageInfo.totalElements === 0) {
return (
<div className="w-full text-center text-xl text-gray-500">
<div className="w-full text-center text-xl text-gray-500 mt-24">
출제 준비 중인 시험이 없습니다.
</div>
);
}

return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 gap-5">
{data?.map((exam) => {
return <DraftExamCard key={exam.id} exam={exam} />;
})}
</div>
<>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 gap-5">
{content.map((exam) => {
return <DraftExamCard key={exam.id} exam={exam} />;
})}
</div>
<div className="flex justify-center mt-10">
<Pagination
color="primary"
showControls
showShadow
page={page}
total={pageInfo.totalPages}
onChange={(page) => setPage(page)}
/>
</div>
</>
);
};

const PublishedExamContent = () => {
const { data } = useGetMyExamSummaries('PUBLISHED');
const [page, setPage] = useState(1);
const { data } = useGetMyExamSummaries('PUBLISHED', page - 1);
const { content, pageInfo } = data;

if (!data || data.length === 0) {
if (!content || pageInfo.totalElements === 0) {
return (
<div className="w-full text-center text-xl text-gray-500">출제 완료된 시험이 없습니다.</div>
<div className="w-full text-center text-xl text-gray-500 mt-24">
출제 완료된 시험이 없습니다.
</div>
);
}

return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 gap-5">
{data?.map((exam) => {
return <PublishedExamCard key={exam.id} exam={exam} />;
})}
</div>
<>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 gap-5">
{content.map((exam) => {
return <PublishedExamCard key={exam.id} exam={exam} />;
})}
</div>
<div className="flex justify-center mt-10">
<Pagination
color="primary"
showControls
showShadow
page={page}
total={pageInfo.totalPages}
onChange={(page) => setPage(page)}
/>
</div>
</>
);
};

Expand Down

0 comments on commit 3b87f08

Please sign in to comment.