From d843667b012fb8232487d63ed4753cd7463d4b38 Mon Sep 17 00:00:00 2001 From: Loi Phan Date: Wed, 29 Nov 2023 14:31:06 +0700 Subject: [PATCH] Add pagination components and update some other components --- hotel-management/src/commons/styles/Button.ts | 2 +- .../src/components/OrderBy/index.tsx | 1 - .../src/components/OrderBy/styled.ts | 6 +- .../src/components/Pagination/index.tsx | 68 +++++++++++++++++++ .../src/components/Pagination/styled.ts | 50 ++++++++++++++ .../src/components/Table/index.tsx | 19 ++++-- .../src/components/Table/styled.ts | 17 ++++- hotel-management/src/constants/config.ts | 13 +++- 8 files changed, 163 insertions(+), 13 deletions(-) create mode 100644 hotel-management/src/components/Pagination/index.tsx create mode 100644 hotel-management/src/components/Pagination/styled.ts diff --git a/hotel-management/src/commons/styles/Button.ts b/hotel-management/src/commons/styles/Button.ts index 2324d3a..00c8db1 100644 --- a/hotel-management/src/commons/styles/Button.ts +++ b/hotel-management/src/commons/styles/Button.ts @@ -36,7 +36,7 @@ const Button = styled.button` &:disabled, &[disabled] { - cursor: no-drop; + cursor: not-allowed; } `; diff --git a/hotel-management/src/components/OrderBy/index.tsx b/hotel-management/src/components/OrderBy/index.tsx index f4ceaa8..1461c95 100644 --- a/hotel-management/src/components/OrderBy/index.tsx +++ b/hotel-management/src/components/OrderBy/index.tsx @@ -26,7 +26,6 @@ const OrderBy = ({ options }: IOrderProps) => { handleClick(option.value)} - active={option.value === currentOrder} disabled={option.value === currentOrder} > {option.label} diff --git a/hotel-management/src/components/OrderBy/styled.ts b/hotel-management/src/components/OrderBy/styled.ts index bfbfa56..80e3f51 100644 --- a/hotel-management/src/components/OrderBy/styled.ts +++ b/hotel-management/src/components/OrderBy/styled.ts @@ -9,7 +9,7 @@ const StyledOrder = styled.div` `; interface IOrderBtn { - active: boolean; + disabled: boolean; } const OrderButton = styled.button` @@ -25,11 +25,11 @@ const OrderButton = styled.button` padding: 5px 10px; ${(props) => - props.active && + props.disabled && css` background-color: var(--primary-color); color: var(--light-text); - cursor: no-drop; + cursor: not-allowed; `} &:hover:not(:disabled) { diff --git a/hotel-management/src/components/Pagination/index.tsx b/hotel-management/src/components/Pagination/index.tsx new file mode 100644 index 0000000..2f73a23 --- /dev/null +++ b/hotel-management/src/components/Pagination/index.tsx @@ -0,0 +1,68 @@ +import { DEFAULT_PAGE_SIZE } from '@constant/config'; +import { useCallback, useMemo } from 'react'; +import { useSearchParams } from 'react-router-dom'; +import { Buttons, PaginationBtn, StyledPagination } from './styled'; +import { MdKeyboardArrowRight, MdKeyboardArrowLeft } from 'react-icons/md'; + +interface IPagination { + count: number; +} + +const Pagination = ({ count }: IPagination) => { + const [searchParams, setSearchParams] = useSearchParams(); + const currentPage = !searchParams.get('page') + ? 1 + : Number(searchParams.get('page')); + + const totalPage = Math.ceil(count / DEFAULT_PAGE_SIZE); + + const nextPage = useCallback(() => { + const next = currentPage === totalPage ? currentPage : currentPage + 1; + + searchParams.set('page', next.toString()); + setSearchParams(searchParams); + }, [currentPage, searchParams, totalPage, setSearchParams]); + + const previousPage = useCallback(() => { + const previous = currentPage === 1 ? currentPage : currentPage - 1; + + searchParams.set('page', previous.toString()); + setSearchParams(searchParams); + }, [currentPage, searchParams, setSearchParams]); + + const fromIndex = useMemo( + () => (currentPage - 1) * DEFAULT_PAGE_SIZE + 1, + [currentPage] + ); + + const toIndex = useMemo( + () => (currentPage === totalPage ? count : currentPage * DEFAULT_PAGE_SIZE), + [currentPage, count, totalPage] + ); + + return ( + totalPage > 1 && ( + +

+ Showing {fromIndex} to {toIndex} of {count} results +

+ + + + Previous + + + + Next + + + +
+ ) + ); +}; + +export default Pagination; diff --git a/hotel-management/src/components/Pagination/styled.ts b/hotel-management/src/components/Pagination/styled.ts new file mode 100644 index 0000000..83074b5 --- /dev/null +++ b/hotel-management/src/components/Pagination/styled.ts @@ -0,0 +1,50 @@ +import styled from 'styled-components'; + +interface IPaginationBtn { + disabled: boolean; +} + +const StyledPagination = styled.div` + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + font-size: var(--fs-sm-x); +`; + +const Buttons = styled.div` + display: flex; + gap: 30px; +`; + +const PaginationBtn = styled.button` + background-color: var(--secondary-btn-color); + border: none; + border-radius: var(--radius-sm); + font-weight: 500; + + display: flex; + align-items: center; + justify-content: center; + gap: 10px; + + padding: 5px 10px; + + transition: all 0.3s; + + & svg { + height: 20px; + width: 20px; + } + + &:hover:not(:disabled) { + background-color: var(--primary-color); + color: var(--light-text); + } + + &:disabled { + cursor: not-allowed; + } +`; + +export { StyledPagination, PaginationBtn, Buttons }; diff --git a/hotel-management/src/components/Table/index.tsx b/hotel-management/src/components/Table/index.tsx index 1cea173..3dca4cd 100644 --- a/hotel-management/src/components/Table/index.tsx +++ b/hotel-management/src/components/Table/index.tsx @@ -1,7 +1,13 @@ import { ReactNode, useContext } from 'react'; // Components -import { StyledBody, StyledHeader, StyledRow, StyledTable } from './styled'; +import { + StyledBody, + StyledHeader, + StyledRow, + StyledTable, + StyledFooter, +} from './styled'; // Contexts import TableContext from '@context/TableContext'; @@ -33,9 +39,13 @@ const Table = ({ columns, children }: ITable) => { const Header = ({ headerColumn }: IHeader) => { const { columns } = useContext(TableContext); - return - {headerColumn.map((item) =>
{item}
)} -
; + return ( + + {headerColumn.map((item) => ( +
{item}
+ ))} +
+ ); }; const Body = ({ data, render }: ITableBody) => { @@ -55,5 +65,6 @@ const Row = ({ children }: ITable) => { Table.Header = Header; Table.Body = Body; Table.Row = Row; +Table.Footer = StyledFooter; export default Table; diff --git a/hotel-management/src/components/Table/styled.ts b/hotel-management/src/components/Table/styled.ts index 9b1f31e..7c10749 100644 --- a/hotel-management/src/components/Table/styled.ts +++ b/hotel-management/src/components/Table/styled.ts @@ -43,4 +43,19 @@ const StyledHeader = styled(CommonRow)` font-weight: 600; `; -export { StyledBody, StyledHeader, StyledRow, StyledTable }; +const StyledFooter = styled.div` + display: flex; + justify-content: center; + padding: 15px; + background-color: var(--footer-table-color); + border-bottom-left-radius: var(--radius-md); + border-bottom-right-radius: var(--radius-md); + + border-top: 1px solid var(--border-color); + + &:not(:has(*)) { + display: none; + } +`; + +export { StyledBody, StyledHeader, StyledRow, StyledTable, StyledFooter }; diff --git a/hotel-management/src/constants/config.ts b/hotel-management/src/constants/config.ts index 2ce25b2..cfffd62 100644 --- a/hotel-management/src/constants/config.ts +++ b/hotel-management/src/constants/config.ts @@ -1,6 +1,13 @@ const DEFAULT_SORT_BY = 'id'; const DEFAULT_ORDER_BY = 'asc'; -const supabaseUrl = 'https://pjqujsjzzdrlrgqbxepe.supabase.co' -const supabaseKey = process.env.VITE_SUPABASE_KEY +const DEFAULT_PAGE_SIZE = 5; +const supabaseUrl = 'https://pjqujsjzzdrlrgqbxepe.supabase.co'; +const supabaseKey = process.env.VITE_SUPABASE_KEY; -export { DEFAULT_SORT_BY, DEFAULT_ORDER_BY, supabaseKey, supabaseUrl }; +export { + DEFAULT_SORT_BY, + DEFAULT_ORDER_BY, + supabaseKey, + supabaseUrl, + DEFAULT_PAGE_SIZE, +};