Skip to content

Commit

Permalink
Add pagination for quizzes
Browse files Browse the repository at this point in the history
  • Loading branch information
maxidragon committed Sep 20, 2023
1 parent 2ec3de7 commit 7bcc5ec
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 35 deletions.
5 changes: 3 additions & 2 deletions backend/app/controllers/quizzes_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class QuizzesController < ApplicationController

def index
page = params[:page] || 1
per_page = params[:per_page] || 10 # Liczba wyników na stronę (możesz dostosować)
per_page = params[:per_page] || 10

if params[:search] && params[:search] != ""
quizzes = Quiz.where("name LIKE ? OR description LIKE ?", "%#{params[:search]}%", "%#{params[:search]}%")
Expand All @@ -18,7 +18,8 @@ def index
render json: {
quizzes: quizzes,
current_page: page.to_i,
total_pages: total_pages
total_pages: total_pages,
total_items: quizzes.total_entries
}
end

Expand Down
66 changes: 66 additions & 0 deletions frontend/src/Components/Pagination/PaginationFooter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Typography, IconButton, Box } from "@mui/material";
import NavigateNextIcon from "@mui/icons-material/NavigateNext";
import NavigateBeforeIcon from "@mui/icons-material/NavigateBefore";
import { useEffect, useState } from "react";

const PaginationFooter = (props: {
page: number;
totalPages: number;
totalItems: number;
handlePageChange: (page: number) => void;
}) => {
const [isPreviousPageDisabled, setIsPreviousPageDisabled] =
useState<boolean>(false);
const [isNextPageDisabled, setIsNextPageDisabled] = useState<boolean>(false);

useEffect(() => {
setIsPreviousPageDisabled(props.page === 1);
setIsNextPageDisabled(props.page === props.totalPages);
}, [props.page, props.totalPages]);

const nextPage = () => {
if (props.page < props.totalPages) {
props.handlePageChange(props.page + 1);
}
};
const previousPage = () => {
if (props.page > 1) {
props.handlePageChange(props.page - 1);
}
};

return (
<Box
sx={{
display: "flex",
flexDirection: "row",
alignItems: "center",
width: "100%",
borderBottom: "none",
}}
>
<IconButton
onClick={previousPage}
disabled={isPreviousPageDisabled}
role="button"
aria-label="previousPageButton"
>
<NavigateBeforeIcon />
</IconButton>
<Typography>
Page {props.page} of {props.totalPages}
</Typography>
<IconButton
onClick={nextPage}
disabled={isNextPageDisabled}
role="button"
aria-label="nextPageButton"
>
<NavigateNextIcon />
</IconButton>
<Typography>Total quizzes: {props.totalItems}</Typography>
</Box>
);
};

export default PaginationFooter;
2 changes: 1 addition & 1 deletion frontend/src/Layout/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ const Layout = (props: { children: React.ReactNode }) => {
);
};

export default Layout;
export default Layout;
2 changes: 1 addition & 1 deletion frontend/src/Layout/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ const Navbar = () => {
);
};

export default Navbar;
export default Navbar;
44 changes: 35 additions & 9 deletions frontend/src/Pages/Home/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,47 @@
import React, { useEffect, useState } from "react";
import React, { useCallback, useEffect, useState } from "react";
import { Box, CircularProgress, TextField, Typography } from "@mui/material";
import { Quiz } from "../../logic/interfaces";
import { getQuizzes } from "../../logic/quizzes";
import QuizCard from "../../Components/CardComponents/QuizCard";
import PaginationFooter from "../../Components/Pagination/PaginationFooter";

const Home = () => {
const [perPage, setPerPage] = useState(10);
const [quizzes, setQuizzes] = useState<Quiz[]>([]);
const [loading, setLoading] = useState(true);
const [search, setSearch] = useState("");
const [page, setPage] = useState(1);
const [totalPages, setTotalPages] = useState(1);
const [totalItems, setTotalItems] = useState(0);

const fetchQuizzes = async (searchParam?: string) => {
const response = await getQuizzes(searchParam);
setQuizzes(response);
setLoading(false);
};
const fetchQuizzes = useCallback(
async (searchParam?: string, pageParam: number = 1, perPageParam: number = 10) => {
const response = await getQuizzes(searchParam, pageParam, perPageParam);
setQuizzes(response.quizzes);
setTotalPages(response.total_pages);
setTotalItems(response.total_items);
setLoading(false);
},
[]
);
const handleSearch = async (event: React.ChangeEvent<HTMLInputElement>) => {
setSearch(event.target.value);
fetchQuizzes(event.target.value);
fetchQuizzes(event.target.value, 1, perPage);
};

const handlePageChange = async (pageParam: number) => {
setPage(pageParam);
const response = await getQuizzes(search, pageParam, perPage);
setQuizzes(response);
};

useEffect(() => {
fetchQuizzes();
}, []);
setTotalPages(1);
setTotalItems(0);
setPerPage(10); //remove it
setPage(1);
fetchQuizzes("", 1);
}, [fetchQuizzes]);

return (
<>
Expand Down Expand Up @@ -60,6 +80,12 @@ const Home = () => {
))}
</>
)}
<PaginationFooter
page={page}
totalPages={totalPages}
totalItems={totalItems}
handlePageChange={handlePageChange}
/>
</Box>
</>
);
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/logic/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,4 @@ export const logout = async () => {

export const isUserLoggedIn = () => {
return localStorage.getItem("token") !== null;
};
};
37 changes: 18 additions & 19 deletions frontend/src/logic/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
export interface Quiz {
id: number;
name: string;
description: string;
questions: Question[];
id: number;
name: string;
description: string;
questions: Question[];
}

export interface Question {
id: number;
question: string;
answers: Answer[];
id: number;
question: string;
answers: Answer[];
}


export interface Answer {
id: number;
answer: string;
isCorrect: boolean;
id: number;
answer: string;
isCorrect: boolean;
}

export interface User {
id: number;
name: string;
email: string;
password: string;
id: number;
name: string;
email: string;
password: string;
}

export interface UserAnswer {
id: number;
questionId: number;
answerId: number;
}
id: number;
questionId: number;
answerId: number;
}
4 changes: 2 additions & 2 deletions frontend/src/logic/quizzes.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { backendRequest } from "./request";

export const getQuizzes = async (searchParam?: string) => {
export const getQuizzes = async (searchParam?: string, pageParam: number = 1, perPage: number = 10) => {
try {
let url = "quizzes";
if (searchParam) {
url += `?search=${searchParam}`;
url += `?search=${searchParam}&page=${pageParam}&per_page=${perPage}`;
}
const response = await backendRequest(url, "GET", false);
return await response.json();
Expand Down

0 comments on commit 7bcc5ec

Please sign in to comment.