Skip to content

Commit

Permalink
Add NFT details modal
Browse files Browse the repository at this point in the history
  • Loading branch information
ThibautBremand committed Jun 28, 2023
1 parent 7246b5d commit 1d64c5a
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 74 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { render, screen, waitFor, fireEvent, act } from '@testing-library/react';
import { render, screen, waitFor, act } from '@testing-library/react';

import { LedgerContext } from '../../../contexts';
import { valueLedgerContext } from '../../../mocks';
Expand Down Expand Up @@ -72,15 +72,4 @@ describe('NFTCard', () => {
// Check that the NFT data is not displayed when an error occurs
expect(screen.queryByTestId('nft_name')).not.toBeInTheDocument();
});

test('button redirects to the correct URL', async () => {
const windowOpenSpy = jest.spyOn(window, 'open').mockImplementation();

renderNFTCard({ NFT: mockNFT });
await waitFor(() => expect(mockGetNFTData).toHaveBeenCalled());

fireEvent.click(screen.getByRole('button'));

expect(windowOpenSpy).toHaveBeenCalledWith('someurl', '_blank');
});
});
150 changes: 88 additions & 62 deletions packages/extension/src/components/molecules/NFTCard/NFTCard.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,42 @@
import { FC, useContext, useEffect, useState } from 'react';
import { FC, forwardRef, useCallback, useContext, useEffect, useState } from 'react';

import { OpenInNewOutlined } from '@mui/icons-material';
import { Button, CircularProgress, ListItem, Paper, Tooltip } from '@mui/material';
import { Button, CircularProgress, Dialog, ListItem, Paper, Slide, Tooltip } from '@mui/material';
import { TransitionProps } from '@mui/material/transitions';
import { LazyLoadImage } from 'react-lazy-load-image-component';

import { AccountNFToken, NFTData } from '@gemwallet/constants';

import { LedgerContext } from '../../../contexts';
import { GemWallet } from '../../atoms';
import { NFTDetails } from '../../organisms';

export interface NFTCardProps {
NFT: AccountNFToken;
}

const Transition = forwardRef(function Transition(
props: TransitionProps & {
children: React.ReactElement;
},
ref: React.Ref<unknown>
) {
return <Slide direction="up" ref={ref} {...props} />;
});

export const NFTCard: FC<NFTCardProps> = ({ NFT }) => {
const { getNFTData } = useContext(LedgerContext);
const [NFTData, setNFTData] = useState<NFTData | null>(null);
const [loading, setLoading] = useState<boolean>(true);
const [dialogOpen, setDialogOpen] = useState<boolean>(false);

const handleViewNFTClick = useCallback(() => {
setDialogOpen(true);
}, []);

const handleCloseDialog = useCallback(() => {
setDialogOpen(false);
}, []);

useEffect(() => {
const fetchNFTImg = async () => {
Expand All @@ -33,77 +53,83 @@ export const NFTCard: FC<NFTCardProps> = ({ NFT }) => {
fetchNFTImg();
}, [getNFTData, NFT]);

const handleViewNFTClick = () => {
window.open('someurl', '_blank'); // TODO: Add redirection url (Potential collaboration with NFT marketplace)?
};

const handleTokenIdClick = (tokenId: string) => {
navigator.clipboard.writeText(tokenId);
};

return (
<Paper
elevation={5}
style={{
padding: '10px',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: '10px'
}}
>
<ListItem
<>
<Dialog
open={dialogOpen}
onClose={handleCloseDialog}
fullScreen
TransitionComponent={Transition}
>
{NFTData && <NFTDetails NFTData={NFTData} handleClose={handleCloseDialog} />}
</Dialog>
<Paper
elevation={5}
style={{
flexDirection: 'column',
textAlign: 'center'
padding: '10px',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: '10px'
}}
>
{loading ? (
<CircularProgress data-testid="progressbar" />
) : NFTData?.image ? (
<LazyLoadImage
alt="nft"
height={150}
style={{ borderRadius: '4px', boxShadow: '4px 4px 0px black' }}
beforeLoad={() => <CircularProgress />}
effect="blur"
src={NFTData?.image}
width={150}
/>
) : (
<GemWallet />
)}
{NFTData ? (
<Tooltip title={NFTData.NFTokenID}>
<ListItem
style={{
flexDirection: 'column',
textAlign: 'center'
}}
>
{loading ? (
<CircularProgress data-testid="progressbar" />
) : NFTData?.image ? (
<LazyLoadImage
alt="nft"
height={150}
style={{ borderRadius: '4px', boxShadow: '4px 4px 0px black' }}
beforeLoad={() => <CircularProgress />}
effect="blur"
src={NFTData?.image}
width={150}
/>
) : (
<GemWallet />
)}
{NFTData ? (
<Tooltip title={NFTData.NFTokenID}>
<div
style={{ fontSize: '14px', color: 'grey', marginTop: '10px', cursor: 'pointer' }}
onClick={() => handleTokenIdClick(NFTData.NFTokenID)}
>
{NFTData.NFTokenID.substring(0, 10) + '...'}
</div>
</Tooltip>
) : null}
{NFTData?.name ? (
<div
style={{ fontSize: '14px', color: 'grey', marginTop: '10px', cursor: 'pointer' }}
onClick={() => handleTokenIdClick(NFTData.NFTokenID)}
style={{ fontSize: '16px', color: 'white', marginTop: '10px' }}
data-testid="nft_name"
>
{NFTData.NFTokenID.substring(0, 10) + '...'}
{NFTData.name}
</div>
</Tooltip>
) : null}
{NFTData?.name ? (
<div
style={{ fontSize: '16px', color: 'white', marginTop: '10px' }}
data-testid="nft_name"
) : null}
{NFTData?.description ? (
<div style={{ fontSize: '14px', color: 'grey', marginTop: '10px' }}>
{NFTData.description}
</div>
) : null}
<Button
variant="outlined"
style={{ marginTop: '10px', fontSize: '14px', gap: '10px' }}
onClick={handleViewNFTClick}
>
{NFTData.name}
</div>
) : null}
{NFTData ? (
<div style={{ fontSize: '14px', color: 'grey', marginTop: '10px' }}>
{NFTData.description}
</div>
) : null}
<Button
variant="outlined"
style={{ marginTop: '10px', fontSize: '14px', gap: '10px' }}
onClick={handleViewNFTClick}
>
View <OpenInNewOutlined style={{ fontSize: '16px' }} />
</Button>
</ListItem>
</Paper>
View <OpenInNewOutlined style={{ fontSize: '16px' }} />
</Button>
</ListItem>
</Paper>
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React, { FC } from 'react';

import CloseIcon from '@mui/icons-material/Close';
import {
AppBar,
CircularProgress,
IconButton,
List,
ListItem,
ListItemText,
Toolbar,
Typography
} from '@mui/material';
import { LazyLoadImage } from 'react-lazy-load-image-component';

import { NFTData } from '@gemwallet/constants';

import { GemWallet } from '../../atoms';

interface NFTDetailsProps {
NFTData: NFTData;
handleClose: () => void;
}

export const NFTDetails: FC<NFTDetailsProps> = ({ NFTData, handleClose }) => {
return (
<>
<AppBar sx={{ position: 'relative' }}>
<Toolbar>
<IconButton
edge="start"
color="inherit"
aria-label="close"
onClick={handleClose}
style={{ cursor: 'pointer' }}
data-testid="close-button"
>
<CloseIcon />
</IconButton>
<Typography sx={{ ml: 2, flex: 1 }} variant="h6" component="div">
NFT Details
</Typography>
</Toolbar>
</AppBar>
<List sx={{ width: '100%', wordBreak: 'break-word' }}>
{NFTData.image ? (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
<LazyLoadImage
alt="nft"
height={250}
style={{ borderRadius: '4px', boxShadow: '4px 4px 0px black' }}
beforeLoad={() => <CircularProgress />}
effect="blur"
src={NFTData?.image}
width={250}
/>
</div>
) : (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
<GemWallet />
</div>
)}
<ListItem style={{ padding: '8px 24px' }}>
<ListItemText primary="Token ID" secondary={NFTData.NFTokenID} />
</ListItem>
{NFTData.name ? (
<ListItem style={{ padding: '8px 24px' }}>
<ListItemText primary="Name" secondary={NFTData.name} />
</ListItem>
) : null}
{NFTData.description ? (
<ListItem style={{ padding: '8px 24px' }}>
<ListItemText primary="Description" secondary={NFTData.description} />
</ListItem>
) : null}
</List>
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './NFTDetails';
2 changes: 2 additions & 0 deletions packages/extension/src/components/organisms/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export * from './BaseTransaction';
export * from './Header';
export * from './NavMenu';
export * from './NFTDetails';
export * from './NFTListing';
export * from './TokenListing';
export * from './TransactionListing';

0 comments on commit 1d64c5a

Please sign in to comment.