Skip to content

Commit

Permalink
Merge pull request #105 from OlhaD/managed-wallets-list
Browse files Browse the repository at this point in the history
Managed wallets list
  • Loading branch information
OlhaD authored Dec 31, 2023
2 parents eb5fcf8 + c04b87a commit 810ccab
Show file tree
Hide file tree
Showing 18 changed files with 801 additions and 95 deletions.
21 changes: 10 additions & 11 deletions src/api/wallets.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,30 @@ const mapWallet = (walletData, nameProp) => {
tokensInWallet: walletData.tokens_in_wallet,
name: walletData[nameProp],
about: walletData.about,
//createdDate: walletData.created_at,
created_at: walletData.created_at,
};
};

export const getWallets = async (token, name = '', pageNumber = 1) => {
const params = {
offset: pageNumber - 1,
};

if (name) {
params.name = name;
}

export const getWallets = async (
token,
name = '',
{ pagination } = { pagination: { offset: 0, limit: 10 } }
) => {
const { total, wallets } = await apiClient
.setAuthHeader(token)
.get('/wallets', {
params: {
name: name || undefined, // Pass 'name' if it exists, or pass 'undefined' to exclude it
offset: pageNumber - 1,
offset: pagination.offset,
limit: pagination.limit,
},
})
.then((response) => {
const wallets = response.data.wallets.map((wallet) =>
mapWallet(wallet, 'name')
);
return {
return {
total: response.data.total,
wallets,
};
Expand Down
23 changes: 18 additions & 5 deletions src/components/Routes/ClientRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import NotFound from '../../pages/NotFound/NotFound';
import { useContext } from 'react';
import MyTransfers from '../../pages/MyTransfers/MyTransfers';
import { TransfersProvider } from '../../store/TransfersContext';
import ListWallets from '../../pages/ListWallets/ListWallets';
import { WalletsProvider } from '../../store/WalletsContext';

const ProtectedRoute = ({ isLoggedIn, redirectPath = '/login' }) => {
if (!isLoggedIn) {
Expand All @@ -24,7 +26,7 @@ const ClientRoutes = () => {
<Routes>
<Route element={<ProtectedRoute isLoggedIn={authCtx.isLoggedIn} />}>
<Route
path='/'
path="/"
exact
element={
<Layout>
Expand All @@ -33,7 +35,7 @@ const ClientRoutes = () => {
}
/>
<Route
path='/my-transfers'
path="/my-transfers"
exact
element={
<Layout>
Expand All @@ -44,7 +46,7 @@ const ClientRoutes = () => {
}
/>
<Route
path='/send-tokens'
path="/send-tokens"
exact
element={
<Layout>
Expand All @@ -53,15 +55,26 @@ const ClientRoutes = () => {
}
/>
<Route
path='*'
path="/list-wallets"
exact
element={
<Layout>
<WalletsProvider>
<ListWallets />
</WalletsProvider>
</Layout>
}
/>
<Route
path="*"
element={
<Layout>
<NotFound />
</Layout>
}
/>
</Route>
<Route path='login' element={<Login />} />
<Route path="login" element={<Login />} />
</Routes>
);
};
Expand Down
4 changes: 2 additions & 2 deletions src/components/Routes/ClientRoutes.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ describe('ClientRoutes component', () => {
// screen.getByRole('');

//Logo, Home, Send Tokens, and My Trasnfers for now
expect(await screen.findAllByRole('link')).toHaveLength(4);
expect(screen.getAllByRole('button')).toHaveLength(4);
expect(await screen.findAllByRole('link')).toHaveLength(5);
expect(screen.getAllByRole('button')).toHaveLength(5);

expect(screen.getByText(/Home/)).toBeInTheDocument();
expect(screen.getByText(/Send Tokens/)).toBeInTheDocument();
Expand Down
218 changes: 218 additions & 0 deletions src/components/UI/components/Table/Table.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
/* eslint-disable no-unused-vars */
import {
Grid,
Paper,
Table as MuiTable,
TableBody,
TableCell,
TableContainer,
TableHead,
TablePagination,
TableRow,
Typography,
} from '@mui/material';
import React, { useEffect, useRef, useState } from 'react';
import { TableCellStyled, TooltipStyled } from './Table.styled';
import { Loader } from '../Loader/Loader';

/**@function
* @name Header
* @description Renders the table header (title, filters) for the table
* @param {string} tableTitle Name of the table to be displayed
* @param {function} getStatusColor returns color corresponding to state value
*
* @returns {JSX.Element} - Table header component
*/
const Header = ({ tableTitle }) => {
return (
<Grid item container sx={{ paddingBottom: '15px' }}>
<Grid item xs={6} sx={{ display: 'flex', alignItems: 'end' }}>
<Typography variant={'h4'}>{tableTitle}</Typography>
</Grid>
</Grid>
);
};

/**@function
* @name Body
* @description Renders the table body (table rows) for the table
* @param tableColumns
* @param tableRows
* @return {JSX.Element} - Table body component
*/
const Body = ({ tableColumns, tableRows, isLoading }) => {
if (isLoading) {
return (
<TableBody>
<TableRow>
<TableCell colSpan={12}>
<Loader />
</TableCell>
</TableRow>
</TableBody>
);
}

if (tableRows.length === 0)
return (
<TableBody>
<TableRow>
<TableCell colSpan={12} sx={{ textAlign: 'center' }}>
No data available
</TableCell>
</TableRow>
</TableBody>
);

return (
<TableBody>
{tableRows &&
tableRows.map((row, rowIndex) => {
return (
<TableRow key={rowIndex}>
{tableColumns.map((column, colIndex) => {
const cellKey = `${rowIndex}-${colIndex}-${column.description}`;
const cellValue =
row[column.name] || row[column.name] === 0
? column.renderer
? column.renderer(row[column.name])
: row[column.name]
: '--';

return (
<OverflownCell key={cellKey} cellValue={cellValue}>
{cellValue}
</OverflownCell>
);
})}
</TableRow>
);
})}
</TableBody>
);
};

/**@function
* @description Renders a table cell with a tooltip that shows when the cell is overflowed
* @param {string} cellValue Value inside the cell and tooltip
* @param {string} cellColor Color of the cell value
* @param children
* @return {JSX.Element}
* @constructor
*/
const OverflownCell = ({ cellValue, cellColor, children }) => {
const [isOverflown, setIsOverflown] = useState(false);
const textElementRef = useRef();

useEffect(() => {
setIsOverflown(
textElementRef.current.scrollWidth > textElementRef.current.clientWidth
);
}, []);

return (
<TooltipStyled
title={<p style={{ fontSize: '12px' }}>{cellValue}</p>}
disableHoverListener={!isOverflown}
arrow
>
<TableCellStyled
ref={textElementRef}
align={'center'}
sx={{
color: `${cellColor}`,
}}
>
{children}
</TableCellStyled>
</TooltipStyled>
);
};

/**@function
* @name Table
* @description Renders the table
* @param {string} tableTitle Name of the table to be displayed
* @param {object} tableColumns Array of table column objects to be displayed
* @param {object} tableRows Array of table row objects to be displayed
*
* @returns {JSX.Element} - table component
*/
const Table = ({
tableTitle,
tableRows,
totalRowCount,
pagination,
setPagination,
tableColumns,
isLoading,
}) => {
// pagination
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(10);
const handleRowsPerPageChange = (e) => {
const newRowsPerPage = parseInt(e.target.value, 10);
setRowsPerPage(newRowsPerPage);
setPage(0);

const newPagination = {
limit: newRowsPerPage,
offset: 0,
};
setPagination(newPagination);
};

const handlePageChange = (e, newPage) => {
setPage(newPage);
const newPagination = { ...pagination, offset: newPage * rowsPerPage };
setPagination(newPagination);
};

return (
<Grid container direction={'column'} sx={{ height: '100%' }}>
<Header tableTitle={tableTitle} />
<TableContainer component={Paper}>
<MuiTable
stickyHeader
sx={{ minWidth: 650 }}
aria-label="table"
data-testid="table"
>
<TableHead>
<TableRow>
{tableColumns.map((column, id) => {
return (
<TableCellStyled
key={`${id}-${column.description}`}
sx={{ fontSize: '14px' }}
align={'center'}
>
{column.description}
</TableCellStyled>
);
})}
</TableRow>
</TableHead>
<Body
tableColumns={tableColumns}
tableRows={tableRows}
isLoading={isLoading}
/>
</MuiTable>
</TableContainer>

<TablePagination
rowsPerPageOptions={[10, 50]}
component={'div'}
count={totalRowCount}
rowsPerPage={rowsPerPage}
onRowsPerPageChange={handleRowsPerPageChange}
page={page}
onPageChange={(e, newPage) => handlePageChange(e, newPage)}
data-testid="table-pagination"
/>
</Grid>
);
};

export default Table;
17 changes: 17 additions & 0 deletions src/components/UI/components/Table/Table.styled.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { styled } from '@mui/system';
import { TableCell, Tooltip, tooltipClasses } from '@mui/material';

export const TableCellStyled = styled(TableCell)({
fontSize: '14px',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
width: '170px',
maxWidth: '170px',
});

export const TooltipStyled = styled(Tooltip)({
[`& .${tooltipClasses.tooltip}`]: {
margin: '0',
},
});
Loading

0 comments on commit 810ccab

Please sign in to comment.