diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/App.jsx | 2 | ||||
-rw-r--r-- | src/ToDo-UI/Pagination.jsx | 239 | ||||
-rw-r--r-- | src/api/axios_methods.js | 4 | ||||
-rw-r--r-- | src/refreshToDos.js | 28 |
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)}> + « + </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)} + > + < + </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)} + > + > + </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)}> + » + </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(); |