Skip to content

Commit

Permalink
Merge pull request #13 from vichannnnn/feat/developer-search-paginate
Browse files Browse the repository at this point in the history
feat/developer search paginate
  • Loading branch information
ddaarrrryyll authored Jun 20, 2023
2 parents 4f692d2 + 6b77973 commit 483caaf
Show file tree
Hide file tree
Showing 3 changed files with 189 additions and 108 deletions.
13 changes: 11 additions & 2 deletions holy-grail-frontend/src/components/Pagination/Pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,22 @@ import debounce from "lodash/debounce";
interface PaginationProps {
pageInfo: { page: number; size: number; total: number; pages: number };
handlePageChange: (newPage: number) => void;
styles?: { mt: string };
}

export const Pagination = ({ pageInfo, handlePageChange }: PaginationProps) => {
export const Pagination = ({
pageInfo,
handlePageChange,
styles,
}: PaginationProps) => {
const debouncedHandlePageChange = debounce(handlePageChange, 100);

return (
<HStack spacing={4} justifyContent="center" mt="10%">
<HStack
spacing={4}
justifyContent="center"
mt={styles?.mt ? styles.mt : "10%"}
>
<Button
onClick={() => debouncedHandlePageChange(pageInfo.page - 1)}
isDisabled={pageInfo.page === 1}
Expand Down
148 changes: 74 additions & 74 deletions holy-grail-frontend/src/features/Developer/DeveloperScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const DeveloperScreen = () => {
const [editUserId, setEditUserId] = useState<number | null>(null);
const [editUserRole, setEditUserRole] = useState<RoleEnum | null>(null);
const [isEditUserModalOpen, setIsEditUserModalOpen] =
useState<boolean>(false);
useState<boolean>(false);

const handleAdd = async (newName: string) => {
if (addType !== null) {
Expand Down Expand Up @@ -124,79 +124,79 @@ const DeveloperScreen = () => {
}, []);

return (
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
{isAddModalOpen && (
<AddModal
isOpen={true}
onClose={() => setIsAddModalOpen(false)}
onSubmit={handleAdd}
/>
)}
<Tabs
value={value}
onChange={handleChange}
aria-label="basic tabs example"
>
<Tab label="Categories" />
<Tab label="Subjects" />
<Tab label="Types" />
<Tab label="Users" />
</Tabs>
{value === 0 && (
<TabContent
title="Categories"
data={data.categories}
handleEdit={openEditModal}
handleAdd={() => openAddModal("categories")}
type="categories"
/>
)}
{value === 1 && (
<TabContent
title="Subjects"
data={data.subjects}
handleEdit={openEditModal}
handleAdd={() => openAddModal("subjects")}
type="subjects"
/>
)}
{value === 2 && (
<TabContent
title="Types"
data={data.types}
handleEdit={openEditModal}
handleAdd={() => openAddModal("types")}
type="types"
/>
)}
{value === 3 && (
<TabContentUsers data={users} handleEdit={openEditUserModal} />
)}
{editId !== null && editType !== null && (
<EditModal
isOpen={true}
onClose={closeEditModal}
onSubmit={handleUpdate}
initialName={
data[editType as DataTypeKey].find(
(item: CommonType) => item.id === editId
)?.name || ""
}
/>
)}
{editUserId !== null && editUserRole !== null && (
<EditUserModal
isOpen={isEditUserModalOpen}
onClose={closeEditUserModal}
onSubmit={handleUpdateUser}
initialRole={editUserRole}
userName={
users.find((user) => user.user_id === editUserId)?.username || ""
}
userId={editUserId}
/>
)}
</Box>
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
{isAddModalOpen && (
<AddModal
isOpen={true}
onClose={() => setIsAddModalOpen(false)}
onSubmit={handleAdd}
/>
)}
<Tabs
value={value}
onChange={handleChange}
aria-label="basic tabs example"
>
<Tab label="Categories" />
<Tab label="Subjects" />
<Tab label="Types" />
<Tab label="Users" />
</Tabs>
{value === 0 && (
<TabContent
title="Categories"
data={data.categories}
handleEdit={openEditModal}
handleAdd={() => openAddModal("categories")}
type="categories"
/>
)}
{value === 1 && (
<TabContent
title="Subjects"
data={data.subjects}
handleEdit={openEditModal}
handleAdd={() => openAddModal("subjects")}
type="subjects"
/>
)}
{value === 2 && (
<TabContent
title="Types"
data={data.types}
handleEdit={openEditModal}
handleAdd={() => openAddModal("types")}
type="types"
/>
)}
{value === 3 && (
<TabContentUsers data={users} handleEdit={openEditUserModal} />
)}
{editId !== null && editType !== null && (
<EditModal
isOpen={true}
onClose={closeEditModal}
onSubmit={handleUpdate}
initialName={
data[editType as DataTypeKey].find(
(item: CommonType) => item.id === editId
)?.name || ""
}
/>
)}
{editUserId !== null && editUserRole !== null && (
<EditUserModal
isOpen={isEditUserModalOpen}
onClose={closeEditUserModal}
onSubmit={handleUpdateUser}
initialRole={editUserRole}
userName={
users.find((user) => user.user_id === editUserId)?.username || ""
}
userId={editUserId}
/>
)}
</Box>
);
};

Expand Down
136 changes: 104 additions & 32 deletions holy-grail-frontend/src/features/Developer/TabContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@ import {
TableContainer,
TableHead,
TableRow,
TablePagination,
OutlinedInput,
} from "@mui/material";
import EditIcon from "@mui/icons-material/Edit";
import React from "react";
import { useState, ChangeEvent, MouseEvent } from "react";
import { ChakraProvider, Flex } from "@chakra-ui/react";
import { Pagination } from "../../components/Pagination/Pagination";

type DataTypeKey = "categories" | "subjects" | "types";

Expand All @@ -27,45 +31,113 @@ interface TabContentProps {
}

export const TabContent = ({
title,
data,
handleEdit,
handleAdd,
type,
}: TabContentProps) => {
title,
data,
handleEdit,
handleAdd,
type,
}: TabContentProps) => {
const [query, setQuery] = useState<string>("");
const [page, setPage] = useState<number>(0);
const [chunkSize, setChunkSize] = useState<number>(10);

const handleEditClick = (id: number) => {
handleEdit(id, type);
};

const handleFilterContent = () => {
let validData: Array<CategoryType | SubjectType | DocumentType> =
data.filter((option) => {
return option.name.toLowerCase().includes(query.toLowerCase());
});
return validData;
};

const handlePaging = () => {
let pagedData: Array<Array<CategoryType | SubjectType | DocumentType>> = [];
let validData: Array<CategoryType | SubjectType | DocumentType> =
handleFilterContent();
for (let i = 0; i < validData.length; i += chunkSize) {
pagedData.push(validData.slice(i, i + chunkSize));
}
return pagedData;
};

return (
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell>{title}</TableCell>
<TableCell align="right">
<Button onClick={handleAdd}>+</Button>
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.map((item) => (
<TableRow key={item.id}>
<TableCell component="th" scope="row">
{item.name}
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell>
<OutlinedInput
sx={{ width: "120%" }}
placeholder={`Search for ${title}`}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
setQuery(event.target.value);
//go back to first page to prevent overflow
setPage(0);
handleFilterContent();
}}
/>
</TableCell>

<TableCell align="right">
<Button onClick={() => handleEditClick(item.id)}>
<EditIcon />
</Button>
{/*<Button onClick={() => handleDelete(item.id)}>*/}
{/* <DeleteIcon />*/}
{/*</Button>*/}
<Button onClick={handleAdd}>+ {title}</Button>
</TableCell>
</TableRow>
<TableRow>
<TableCell colSpan={2}>
<ChakraProvider>
<Pagination
pageInfo={{
page: page + 1,
size: chunkSize,
total: handleFilterContent().length,
pages: handlePaging().length,
}}
handlePageChange={(newPage: number) => {
setPage(newPage - 1);
}}
styles={{ mt: "0%" }}
/>
</ChakraProvider>
<Button onClick={handleAdd}>+ {title}</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<TablePagination
count={handleFilterContent().length}
onPageChange={(event: React.MouseEvent<HTMLButtonElement> | null, page: number) =>{
setPage(page);
}}
page={page}
rowsPerPage={chunkSize}
rowsPerPageOptions={[5,10,15,20]}
onRowsPerPageChange={(event: React.ChangeEvent<HTMLInputElement>) => {
setChunkSize(parseInt(event.target.value));
//go back to first page to prevent overflow
setPage(0);
handlePaging();
}}
/>
</TableHead>
<TableBody>
{(handlePaging()[page] || []).map((item) => (
<TableRow key={item.id}>
<TableCell component="th" scope="row">
{item.name}
</TableCell>
<TableCell align="right">
<Button onClick={() => handleEditClick(item.id)}>
<EditIcon />
</Button>
{/*<Button onClick={() => handleDelete(item.id)}>*/}
{/* <DeleteIcon />*/}
{/*</Button>*/}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
};

0 comments on commit 483caaf

Please sign in to comment.