diff --git a/hotel-management/src/components/Table/index.tsx b/hotel-management/src/components/Table/index.tsx index 9dae7b2..004f73b 100644 --- a/hotel-management/src/components/Table/index.tsx +++ b/hotel-management/src/components/Table/index.tsx @@ -1,70 +1,70 @@ -import { ReactNode, useContext } from 'react'; - -// Styled +import { ColumnProps } from '@src/types/common'; import { StyledBody, + StyledFooter, StyledHeader, StyledRow, StyledTable, - StyledFooter, } from './styled'; +import Pagination from '../Pagination'; -// Contexts -import TableContext from '@src/contexts/TableContext'; +const parseWidthString = (columnsWidth: number[]): string => { + let result: string = ''; -export interface ITable { - columns?: string; - children: ReactNode; -} + const totalWidth = columnsWidth.reduce((partialSum, a) => partialSum + a, 0); + columnsWidth.forEach((width) => { + result += Math.round((width / totalWidth) * 100).toString() + '% '; + }); -export interface IHeader { - headerColumn: string[]; -} - -interface ITableBody { - data?: T[]; - render?: CallbackMapFunc; -} - -type CallbackMapFunc = (value: T, index: number, array: T[]) => ReactNode; - -const Table = ({ columns, children }: ITable) => { - return ( - - {children} - - ); + return result; }; -const Header = ({ headerColumn }: IHeader) => { - const { columns } = useContext(TableContext); +type Props = { + columns: ColumnProps[]; + rows: T[]; + count?: number | null; +}; + +const Table = ({ rows, columns, count }: Props) => { + const width = parseWidthString(columns.map((item) => item.width)); + + const headers = columns.map((column, index) => { + return
{column.title}
; + }); + + const renderRows = rows.map((row, rowIndex) => { + return ( + + } + > + {columns.map((column, columnIndex) => { + const value = row[column.key as keyof typeof row] as string; + + return
{value}
; + })} +
+ ); + }); return ( - - {headerColumn.map((item) => ( -
{item}
- ))} -
+ + {headers} + + {renderRows} + + {Boolean(count) && ( + + + + )} + ); }; -const Body = ({ data, render }: ITableBody) => { - return ( - data!.length && ( - {data?.map(render as CallbackMapFunc)} - ) - ); -}; - -const Row = ({ children }: ITable) => { - const { columns } = useContext(TableContext); - - return {children}; -}; - -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 7c10749..c0105a5 100644 --- a/hotel-management/src/components/Table/styled.ts +++ b/hotel-management/src/components/Table/styled.ts @@ -1,7 +1,8 @@ import styled from 'styled-components'; -// Interfaces -import { ITable } from '.'; +interface ICommonRow { + width: string; +} const StyledTable = styled.div` border: 1px solid var(--border-color); @@ -10,9 +11,9 @@ const StyledTable = styled.div` font-size: 20px; `; -const CommonRow = styled.div` +const CommonRow = styled.div` display: grid; - grid-template-columns: ${(props) => props.columns}; + grid-template-columns: ${(props) => props.width}; column-gap: 10px; align-items: center; justify-items: center; diff --git a/hotel-management/src/pages/Booking/BookingTable.tsx b/hotel-management/src/pages/Booking/BookingTable.tsx index 473db88..da3677c 100644 --- a/hotel-management/src/pages/Booking/BookingTable.tsx +++ b/hotel-management/src/pages/Booking/BookingTable.tsx @@ -1,12 +1,7 @@ -import { useCallback } from 'react'; - // Components -import Menus from '@src/components/Menus'; import Table from '@src/components/Table'; import Message from '@src/components/Message'; import Search from '@src/components/Search'; -import Pagination from '@src/components/Pagination'; -import BookingRow from './BookingRow'; // Styled import { StyledOperationTable } from './styled'; @@ -17,30 +12,59 @@ import Spinner from '@src/commons/styles/Spinner'; import { useBookings } from '@src/hooks/bookings/useBookings'; // Types -import { TBookingResponse } from '@src/types/booking'; +import { ColumnProps } from '@src/types/common'; +import { formatCurrency } from '@src/helpers/helper'; + +interface IBookingTable { + user: string; + date: string; + room: string; + amount: string; + status: string; + onClick: () => void; +} const BookingTable = () => { - const columnName = [ - 'User', - 'Date', - 'Room', - 'Amount', - 'Status' + const columns: ColumnProps[] = [ + { + key: 'user', + title: 'User', + width: 15, + }, + { + key: 'date', + title: 'Date', + width: 25, + }, + { + key: 'room', + title: 'Room', + width: 20, + }, + { + key: 'amount', + title: 'Amount', + width: 15, + }, + { + key: 'status', + title: 'Status', + width: 15, + }, ]; - const { - isLoading, - bookings, - count - } = useBookings(); - const renderBookingRow = useCallback( - (booking: TBookingResponse) => ( - - ), - [] - ); + const { isLoading, bookings, count } = useBookings(); - return ( + const tempBookings = bookings?.map((booking) => ({ + date: 'Error', + amount: formatCurrency(booking.amount), + room: booking.rooms!.name, + user: booking.users!.name, + status: booking.status ? 'Check in' : 'Check out', + onClick: () => console.log(booking), + })); + + return ( <> @@ -49,19 +73,12 @@ const BookingTable = () => { {isLoading && } - {bookings && bookings.length ? ( - - - - - data={bookings} - render={renderBookingRow} - /> - - - -
-
+ {tempBookings && tempBookings.length ? ( + + columns={columns} + rows={tempBookings} + count={count} + /> ) : ( !isLoading && No data to show here! )} diff --git a/hotel-management/src/pages/Room/RoomTable.tsx b/hotel-management/src/pages/Room/RoomTable.tsx index 3407228..efc1927 100644 --- a/hotel-management/src/pages/Room/RoomTable.tsx +++ b/hotel-management/src/pages/Room/RoomTable.tsx @@ -1,16 +1,13 @@ -import { useCallback } from 'react'; - // Components -import Menus from '@src/components/Menus'; import Table from '@src/components/Table'; import Message from '@src/components/Message'; import Search from '@src/components/Search'; import SortBy from '@src/components/SortBy'; import OrderBy from '@src/components/OrderBy'; -import RoomRow from './RoomRow'; // Types import { IRoom } from '@src/types/room'; +import { ColumnProps } from '@src/types/common'; // Constants import { ORDERBY_OPTIONS, ROOM_PAGE } from '@src/constants/commons'; @@ -22,20 +19,44 @@ import Spinner from '@src/commons/styles/Spinner'; // Hooks import { useRooms } from '@src/hooks/rooms/useRooms'; -import Pagination from '@src/components/Pagination'; + +interface IRoomTable extends Omit{ + status: string; + onClick: () => void; +} const RoomTable = () => { - const columnName = ['Id', 'Name', 'Price', 'Status']; - const { - isLoading, - rooms, - count - } = useRooms(); + const columns: ColumnProps[] = [ + { + key: 'id', + title: 'Id', + width: 10, + }, + { + key: 'name', + title: 'Name', + width: 40, + }, + { + key: 'price', + title: 'Price', + width: 20, + }, + { + key: 'status', + title: 'Status', + width: 20, + }, + ]; + const { isLoading, rooms, count } = useRooms(); - const renderRoomRow = useCallback( - (room: IRoom) => , - [] - ); + const tempRooms = rooms?.map((room) => ({ + ...room, + status: room.status + ? 'Unavailable' + : 'Available', + onClick: () => console.log(room), + })); return ( <> @@ -49,16 +70,8 @@ const RoomTable = () => { {isLoading && } - {rooms && rooms.length ? ( - - - - data={rooms} render={renderRoomRow} /> - - - -
-
+ {tempRooms && tempRooms.length ? ( + columns={columns} rows={tempRooms} count={count}/> ) : ( !isLoading && No data to show here! )} diff --git a/hotel-management/src/pages/User/UserTable.tsx b/hotel-management/src/pages/User/UserTable.tsx index 268f9b5..81eb5f5 100644 --- a/hotel-management/src/pages/User/UserTable.tsx +++ b/hotel-management/src/pages/User/UserTable.tsx @@ -1,17 +1,9 @@ -import { useCallback } from 'react'; - // Components -import Menus from '@src/components/Menus'; import Table from '@src/components/Table'; import Message from '@src/components/Message'; import Search from '@src/components/Search'; import SortBy from '@src/components/SortBy'; import OrderBy from '@src/components/OrderBy'; -import UserRow from './UserRow'; -import Pagination from '@src/components/Pagination'; - -// Types -import { IUser } from '@src/types/user'; // Constants import { ORDERBY_OPTIONS, USER_PAGE } from '@src/constants/commons'; @@ -23,29 +15,46 @@ import Spinner from '@src/commons/styles/Spinner'; // Hooks import { useUsers } from '@src/hooks/users/useUsers'; +import { ColumnProps } from '@src/types/common'; +import { IUser } from '@src/types/user'; + +interface IUserTable extends Omit{ + isBooked: string; + onClick: () => void; +} const UserTable = () => { - const columnName = [ - 'Id', - 'Name', - 'Phone', - 'Is Booked' + const columns: ColumnProps[] = [ + { + key: 'id', + title: 'Id', + width: 10, + }, + { + key: 'name', + title: 'Name', + width: 35, + }, + { + key: 'phone', + title: 'Phone', + width: 30, + }, + { + key: 'isBooked', + title: 'Is Booked', + width: 20, + }, ]; - const { - isLoading, - users, - count - } = useUsers(); + const { isLoading, users, count } = useUsers(); - const renderUserRow = useCallback( - (user: IUser) => ( - - ), - [] - ); + const tempUsers = users?.map((user) => ({ + ...user, + isBooked: user.isBooked + ? 'Yes' + : 'No', + onClick: () => console.log(user), + })); return ( <> @@ -59,16 +68,8 @@ const UserTable = () => { {isLoading && } - {users && users.length ? ( - - - - data={users} render={renderUserRow} /> - - - -
-
+ {tempUsers && tempUsers.length ? ( + columns={columns} rows={tempUsers} count={count}/> ) : ( !isLoading && No data to show here! )} diff --git a/hotel-management/src/types/common.ts b/hotel-management/src/types/common.ts index 08e954e..e9116e5 100644 --- a/hotel-management/src/types/common.ts +++ b/hotel-management/src/types/common.ts @@ -12,6 +12,18 @@ interface ILogin { password: string; } +interface ColumnProps { + key: string; + title: string; + width: number; +} + type TDirection = 'vertical' | 'horizontal'; -export type { Nullable, IDataState, TDirection, ILogin }; +export type { + Nullable, + IDataState, + TDirection, + ILogin, + ColumnProps +};