Skip to content

Commit

Permalink
Support problem pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
slhmy committed Aug 3, 2024
1 parent 28dfa33 commit c511923
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 30 deletions.
12 changes: 10 additions & 2 deletions src/api/problem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,19 @@ export namespace ProblemService {
return res.data;
}

export async function getProblemInfoList() {
export async function getProblemInfoList(limit?: number, offset?: number) {
limit = limit || 10;
offset = offset || 0;

let res = await client.get<{
total: number;
list: ProblemServiceModel.ProblemInfo[];
}>(`/api/v1/problem`);
}>(`/api/v1/problem`, {
params: {
limit,
offset,
},
});
if (res.status !== 200) {
throw Error("failed to get problem list");
}
Expand Down
19 changes: 16 additions & 3 deletions src/hooks/problem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,33 @@ export const useProblemInfoList = () => {
const [problemList, setProblemList] = useState<
ProblemServiceModel.ProblemInfo[]
>([]);
const [total, setTotal] = useState<number>(0);
const [limit, setLimit] = useState<number>(10);
const [offset, setOffset] = useState<number>(0);

useEffect(() => {
ProblemService.getProblemInfoList()
ProblemService.getProblemInfoList(limit, offset)
.then((res) => {
setProblemList(res.list);
setTotal(res.total);
})
.catch((err) => {
console.log(err);
});
}, []);
}, [limit, offset]);

function getProblemInfoList() {
return problemList;
}

return { getProblemInfoList };
function getPageCount(limit: number) {
return Math.ceil(total / limit);
}

function setPagenation(limit: number, offset: number) {
setLimit(limit);
setOffset(offset);
}

return { getProblemInfoList, getPageCount, setPagenation };
};
16 changes: 16 additions & 0 deletions src/mocks/data/problem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ProblemServiceModel } from "@/typings/problem";

export namespace ProblemMockData {
export const ProblemInfoList: ProblemServiceModel.ProblemInfo[] = [
{
slug: "hello-world",
title: "Hello World",
tags: [{ name: "Primer" }],
},
{
slug: "a-plus-b-problem",
title: "A+B Problem",
tags: [{ name: "Primer" }, { name: "Math" }],
},
];
}
33 changes: 16 additions & 17 deletions src/mocks/rest/problem.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { HttpResponse, http } from "msw";
import { ProblemServiceModel } from "../../typings/problem";
import { ProblemMockData } from "../data/problem";

export const getProblemInfo = http.get(
"/api/v1/problem/:slug",
Expand Down Expand Up @@ -43,28 +44,26 @@ Hello! world!
},
);

export const getProblemInfoList = http.get("/api/v1/problem", (info) => {
export const getProblemInfoList = http.get("/api/v1/problem", ({ request }) => {
const url = new URL(request.url);

const limit = url.searchParams.get("limit");
const offset = url.searchParams.get("offset");

let problemInfoList = ProblemMockData.ProblemInfoList.slice(
Number(offset),
Number(offset) + Number(limit),
);

const response: {
total: number;
list: ProblemServiceModel.ProblemInfo[];
} = {
total: 2,
list: [
{
slug: "hello-world",
title: "Hello World",
tags: [{ name: "Primer" }],
},
{
slug: "a-plus-b-problem",
title: "A+B Problem",
tags: [{ name: "Primer" }, { name: "Math" }],
},
],
total: ProblemMockData.ProblemInfoList.length,
list: problemInfoList,
};
return new Response(JSON.stringify(response), {
status: 200,
});

return new Response(JSON.stringify(response), { status: 200 });
});

export const putProblem = http.put("/api/v1/problem", async (info) => {
Expand Down
69 changes: 61 additions & 8 deletions src/pages/ProblemList.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,71 @@
import React, { useEffect } from "react";
import ProblemTable from "../components/problem/ProblemTable";
import { useProblemInfoList } from "../hooks/problem";
import { joinClasses } from "@/utils/common";

const countPerPageSelections = [10, 25, 50];

const ProblemList: React.FC = () => {
const { getProblemInfoList } = useProblemInfoList();
// useEvent();
const { getProblemInfoList, getPageCount, setPagenation } =
useProblemInfoList();
const [countPerPage, setCountPerPage] = React.useState(
countPerPageSelections[0],
);
const [page, setPage] = React.useState(0);

useEffect(() => {
setPagenation(countPerPage, page * countPerPage);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [countPerPage, page]);

return (
<div className="flex w-full flex-auto flex-col gap-8 sm:flex-row">
<div className="h-fit w-full rounded border border-base-content/10 bg-base-100">
<ProblemTable
data={getProblemInfoList()}
showActions={false}
enableRouting
/>
<div className="flex w-full flex-col gap-2">
<div className="h-fit w-full rounded border border-base-content/10 bg-base-100">
<ProblemTable
data={getProblemInfoList()}
showActions={false}
enableRouting
className={
getProblemInfoList().length === 1
? ""
: "border-b border-base-content/10"
}
/>
<div className="flex flex-row-reverse gap-2 p-2">
<select
className="select select-sm rounded bg-base-200 text-sm font-semibold"
onChange={(e) => {
setCountPerPage(Number(e.target.value));
setPage(0);
}}
>
{countPerPageSelections.map((count) => (
<option key={count} value={count}>
{count}
</option>
))}
</select>
{getPageCount(countPerPage) > 1 && (
<div className="join rounded">
{Array.from({ length: getPageCount(countPerPage) }, (_, i) => (
<button
key={i}
className={joinClasses(
"btn join-item btn-sm",
page === i && "btn-active",
)}
onClick={() => {
setPage(i);
}}
>
{i + 1}
</button>
))}
</div>
)}
</div>
</div>
</div>
</div>
);
Expand Down

0 comments on commit c511923

Please sign in to comment.