aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrián Oliva <adrian.oliva@cimat.mx>2023-05-29 21:49:56 -0600
committerAdrián Oliva <adrian.oliva@cimat.mx>2023-05-29 21:49:56 -0600
commitac0d9f421f1304306d9b3a264a225966fa9d5677 (patch)
tree4673c200a6ccc318b49ac6d42cb87ff123204d1f
parente0ce800a647a1b173979f0e7f20d1d54b9f9bd7d (diff)
downloadToDo-App-FE-ac0d9f421f1304306d9b3a264a225966fa9d5677.tar.gz
ToDo-App-FE-ac0d9f421f1304306d9b3a264a225966fa9d5677.zip
IT NOW HAS PAGING.
-rw-r--r--src/App.jsx2
-rw-r--r--src/ToDo-UI/Pagination.jsx239
-rw-r--r--src/api/axios_methods.js4
-rw-r--r--src/refreshToDos.js28
4 files changed, 262 insertions, 11 deletions
diff --git a/src/App.jsx b/src/App.jsx
index dd81431..ca2c07e 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -2,6 +2,7 @@ import React from "react";
import { Search } from "./ToDo-UI/Search";
import { NewToDo } from "./ToDo-UI/NewToDo";
import { ListToDos } from "./ToDo-UI/ListToDo";
+import { Pagination } from "./ToDo-UI/Pagination";
import { useDispatch, useSelector } from "react-redux";
import {
@@ -25,6 +26,7 @@ function App() {
<Search />
<NewToDo />
<ListToDos />
+ <Pagination />
</div>
);
}
diff --git a/src/ToDo-UI/Pagination.jsx b/src/ToDo-UI/Pagination.jsx
new file mode 100644
index 0000000..61e41bf
--- /dev/null
+++ b/src/ToDo-UI/Pagination.jsx
@@ -0,0 +1,239 @@
+import { useState } from "react";
+import { useDispatch, useSelector } from "react-redux";
+
+import {
+ change_page,
+ select_current_filters,
+ select_current_sorting,
+ select_current_page,
+} from "../features/todo/reducer";
+
+import { refresh_todos } from "../refreshToDos";
+import { get_nu_pages_function } from "../api/axios_methods";
+
+function range(start, end) {
+ return Array.from({ length: end - start + 1 }, (_, i) => i + start);
+}
+
+function render_pagination(current_page, nu_pages, handle_on_click) {
+ const first_page = (
+ <li
+ className={
+ "page-item" +
+ (current_page == 1 || nu_pages == 0 ? " disabled" : "")
+ }
+ >
+ <a className="page-link" onClick={() => handle_on_click(1)}>
+ &laquo;
+ </a>
+ </li>
+ );
+ const previous_page = (
+ <li
+ className={
+ "page-item" +
+ (current_page == 1 || nu_pages == 0 ? " disabled" : "")
+ }
+ >
+ <a
+ className="page-link"
+ onClick={() => handle_on_click(current_page - 1)}
+ >
+ &lt;
+ </a>
+ </li>
+ );
+ const next_page = (
+ <li
+ className={
+ "page-item" +
+ (current_page == nu_pages || nu_pages == 0 ? " disabled" : "")
+ }
+ >
+ <a
+ className="page-link"
+ onClick={() => handle_on_click(current_page + 1)}
+ >
+ &gt;
+ </a>
+ </li>
+ );
+ const last_page = (
+ <li
+ className={
+ "page-item" +
+ (current_page == nu_pages || nu_pages == 0 ? " disabled" : "")
+ }
+ >
+ <a className="page-link" onClick={() => handle_on_click(nu_pages)}>
+ &raquo;
+ </a>
+ </li>
+ );
+
+ let in_between = <></>;
+ // If pages <= 5, render all of them.
+ if (nu_pages <= 5) {
+ in_between = (
+ <>
+ {range(1, nu_pages).map((number) => (
+ <li
+ className={
+ "page-item" +
+ (current_page == number ? " active" : "")
+ }
+ key={number}
+ >
+ <a
+ className="page-link"
+ onClick={(e) =>
+ handle_on_click(parseInt(e.target.innerText))
+ }
+ >
+ {number}
+ </a>
+ </li>
+ ))}
+ </>
+ );
+ } else if (current_page <= 3) {
+ in_between = (
+ <>
+ {range(1, 3).map((number) => (
+ <li
+ className={
+ "page-item" +
+ (current_page == number ? " active" : "")
+ }
+ key={number}
+ >
+ <a
+ className="page-link"
+ onClick={(e) =>
+ handle_on_click(parseInt(e.target.innerText))
+ }
+ >
+ {number}
+ </a>
+ </li>
+ ))}
+ <li className="page-item disabled">
+ <a className="page-link">...</a>
+ </li>
+ <li className="page-item">
+ <a
+ className="page-link"
+ onClick={(e) =>
+ handle_on_click(parseInt(e.target.innerText))
+ }
+ >
+ {nu_pages}
+ </a>
+ </li>
+ </>
+ );
+ } else if (current_page >= nu_pages - 2) {
+ in_between = (
+ <>
+ <li className="page-item">
+ <a className="page-link" onClick={() => handle_on_click(1)}>
+ 1
+ </a>
+ </li>
+ <li className="page-item disabled">
+ <a className="page-link">...</a>
+ </li>
+ {range(nu_pages - 2, nu_pages).map((number) => (
+ <li
+ className={
+ "page-item" +
+ (current_page == number ? " active" : "")
+ }
+ key={number}
+ >
+ <a
+ className="page-link"
+ onClick={(e) =>
+ handle_on_click(parseInt(e.target.innerText))
+ }
+ >
+ {number}
+ </a>
+ </li>
+ ))}
+ </>
+ );
+ } else {
+ in_between = (
+ <>
+ <li className="page-item">
+ <a className="page-link" onClick={() => handle_on_click(1)}>
+ 1
+ </a>
+ </li>
+ <li className="page-item disabled">
+ <a className="page-link">...</a>
+ </li>
+ <li className="page-item active">
+ <a className="page-link">{current_page}</a>
+ </li>
+ <li className="page-item disabled">
+ <a className="page-link">...</a>
+ </li>
+ <li className="page-item">
+ <a
+ className="page-link"
+ onClick={() => handle_on_click(nu_pages)}
+ >
+ {nu_pages}
+ </a>
+ </li>
+ </>
+ );
+ }
+ return (
+ <nav aria-label="To dos page navigation">
+ <ul className="pagination justify-content-center mt-3">
+ {first_page}
+ {previous_page}
+ {in_between}
+ {next_page}
+ {last_page}
+ </ul>
+ </nav>
+ );
+}
+
+export function Pagination() {
+ const [nu_pages, set_nu_pages] = useState(0);
+
+ const nu_pages_api = get_nu_pages_function();
+ nu_pages_api((response) => set_nu_pages(response));
+
+ const dispatch = useDispatch();
+
+ const my_filters = useSelector(select_current_filters);
+ const my_sorters = useSelector(select_current_sorting);
+ const my_curr_page = useSelector(select_current_page);
+
+ function handle_on_click(target) {
+ if (my_curr_page == target) return;
+
+ dispatch(change_page({ page: target }));
+ refresh_todos(my_filters, my_sorters, my_curr_page, dispatch);
+ }
+
+ return (
+ <div
+ className="container mt-3 mb-3"
+ style={{
+ border: "2px solid black",
+ textAlign: "center",
+ width: "400px",
+ padding: "15px",
+ }}
+ >
+ {render_pagination(my_curr_page, nu_pages, handle_on_click)}
+ </div>
+ );
+}
diff --git a/src/api/axios_methods.js b/src/api/axios_methods.js
index 822c334..bea8b79 100644
--- a/src/api/axios_methods.js
+++ b/src/api/axios_methods.js
@@ -126,10 +126,10 @@ export function get_todos_page_function() {
export function get_nu_pages_function() {
// Return the number of pages in total.
// GET "/todos/filtSort/pages"
- return async () => {
+ return async (handler) => {
try {
const response = await api.get("/todos/filtSort/pages");
- return response.data;
+ handler(response.data);
} catch (err) {
console.log(err);
}
diff --git a/src/refreshToDos.js b/src/refreshToDos.js
index a6b1368..250b399 100644
--- a/src/refreshToDos.js
+++ b/src/refreshToDos.js
@@ -29,17 +29,27 @@ export function refresh_todos(my_filters, my_sorters, my_curr_page, dispatch) {
});
// Get the total number of pages. Change the current page if necessary.
- const get_nu_pages_api = get_nu_pages_function();
- const total_pages_api = get_nu_pages_api();
-
- if (total_pages_api < my_curr_page) {
- dispatch(
- change_page({
- page: total_pages_api,
- })
- );
+ function handle_out_of_bounds(total_pages) {
+ if (total_pages == 0) {
+ dispatch(
+ change_page({
+ page: 1,
+ })
+ );
+ } else if (total_pages < my_curr_page) {
+ dispatch(
+ change_page({
+ page: total_pages,
+ })
+ );
+ }
}
+ const get_nu_pages_api = get_nu_pages_function();
+ const total_pages_api = get_nu_pages_api((nu_pages) => {
+ handle_out_of_bounds(nu_pages);
+ });
+
// Delete all current to dos we have stored and retrieve new to dos from API.
const get_todos_api = get_todos_page_function();