From 34873f521ecfd72d3cb083a3138c56272abda88b Mon Sep 17 00:00:00 2001 From: Florencia Barreto <32873485+flobarreto@users.noreply.github.com> Date: Mon, 27 Mar 2023 10:31:44 -0300 Subject: [PATCH] Feat: item detail information (#1487) * feat: created owners table with corresponding styles * feat: added connection with nft server * feat: added sort by * feat: some fixes * feat: removed unused container * fix: pr comments * fix: imports * fix: pr commentsg * fix: removed change con dev.json * fix: pr comments * fix: changed component name * feat: create listings table component * feat: listings table with mocked data * fix: dates and sytles * feat: connected with api * feat: added empty state to tables - missing listings empty state * feat: added empty state text * fix: added name as possible filter to support marketplace subraph * fix: test * feat: updated dcl shcemas * feat: created mint or buy component * fix: pr comments * feat: item detail page * fix: some styles * Feat/latest sales table (#1488) * feat: redesign lastest sales table * fix: table title * fix: removed unused file * fix: pr comments * fix: typo --- .../BestBuyingOption.module.css | 8 +- .../ItemDetail/ItemDetail.module.css | 62 +++++++++ .../AssetPage/ItemDetail/ItemDetail.tsx | 129 +++++++++--------- .../ListingsTable/ListingsTable.module.css | 5 + .../AssetPage/ListingsTable/ListingsTable.tsx | 19 ++- .../ListingsTableContainer.module.css | 6 +- .../TransactionHistory/TransactionHistory.css | 28 ++++ .../TransactionHistory/TransactionHistory.tsx | 16 ++- 8 files changed, 192 insertions(+), 81 deletions(-) create mode 100644 webapp/src/components/AssetPage/ItemDetail/ItemDetail.module.css diff --git a/webapp/src/components/AssetPage/BestBuyingOption/BestBuyingOption.module.css b/webapp/src/components/AssetPage/BestBuyingOption/BestBuyingOption.module.css index 6625afbeb..0a574a6e0 100644 --- a/webapp/src/components/AssetPage/BestBuyingOption/BestBuyingOption.module.css +++ b/webapp/src/components/AssetPage/BestBuyingOption/BestBuyingOption.module.css @@ -3,9 +3,7 @@ border-radius: 12px; display: flex; padding: 24px; - /* TODO: when placing this on the correct place, make it's width on percentage to be responsive */ - width: 668px; - margin-top: 50px; + width: 100%; } .BestBuyingOption .cardTitle { @@ -58,3 +56,7 @@ .BestBuyingOption :global(.ui.header.medium) { font-size: 17px; } + +.BestBuyingOption :global(.ui.button + .ui.button) { + margin-left: unset; +} diff --git a/webapp/src/components/AssetPage/ItemDetail/ItemDetail.module.css b/webapp/src/components/AssetPage/ItemDetail/ItemDetail.module.css new file mode 100644 index 000000000..d261456cd --- /dev/null +++ b/webapp/src/components/AssetPage/ItemDetail/ItemDetail.module.css @@ -0,0 +1,62 @@ +.ItemDetail { + display: flex; + flex-direction: column; +} + +.ItemDetail .assetImageContainer :global(.AssetImage) { + border-radius: 12px; + overflow: hidden; +} + +.ItemDetail .assetImageContainer { + width: 48%; +} + +.ItemDetail .badges { + margin-top: 15px; + display: flex; + gap: 8px; + flex-wrap: wrap; +} + +.ItemDetail .information { + display: flex; + flex-direction: column; + justify-content: space-between; + width: 48%; + gap: 30px; +} + +.ItemDetail .informationContainer { + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 30px; +} + +.ItemDetail .basicRow { + display: flex; + flex-direction: row; + justify-content: space-between; + width: 100%; +} + +.ItemDetail :global(.ui.button + .ui.button) { + margin-left: 0px; +} + +@media (max-width: 800px) { + .ItemDetail .information { + width: 100%; + } + .ItemDetail .assetImageContainer { + width: 100%; + } + .ItemDetail .basicRow { + flex-direction: column; + } + + .ItemDetail :global(.dcl.stats + .dcl.stats) { + width: 100%; + } +} diff --git a/webapp/src/components/AssetPage/ItemDetail/ItemDetail.tsx b/webapp/src/components/AssetPage/ItemDetail/ItemDetail.tsx index ba5c179e0..f855cc5f4 100644 --- a/webapp/src/components/AssetPage/ItemDetail/ItemDetail.tsx +++ b/webapp/src/components/AssetPage/ItemDetail/ItemDetail.tsx @@ -1,6 +1,7 @@ import React, { useMemo, useRef } from 'react' -import { t } from 'decentraland-dapps/dist/modules/translation/utils' +import { Container } from 'decentraland-ui' import { BodyShape, EmotePlayMode, NFTCategory } from '@dcl/schemas' +import { t } from 'decentraland-dapps/dist/modules/translation/utils' import { locations } from '../../../modules/routing/locations' import { Section } from '../../../modules/vendor/decentraland' import RarityBadge from '../../RarityBadge' @@ -13,13 +14,13 @@ import SmartBadge from '../SmartBadge' import { Description } from '../Description' import { Owner } from '../Owner' import Collection from '../Collection' -import BaseDetail from '../BaseDetail' import IconBadge from '../IconBadge' import { TransactionHistory } from '../TransactionHistory' -import { SaleActionBox } from '../SaleActionBox' import ListingsTableContainer from '../ListingsTableContainer/ListingsTableContainer' -import { Props } from './ItemDetail.types' import { BestBuyingOption } from '../BestBuyingOption' +import Title from '../Title' +import { Props } from './ItemDetail.types' +import styles from './ItemDetail.module.css' const ItemDetail = ({ item }: Props) => { let description = '' @@ -54,73 +55,71 @@ const ItemDetail = ({ item }: Props) => { ) return ( - } - isOnSale={item.isOnSale} - badges={ - <> - - {category && ( - - )} - {item.category === NFTCategory.EMOTE && ( - - )} - {bodyShapes.length > 0 && !item.data.emote && ( - - )} - {item.category === NFTCategory.WEARABLE && - item.data.wearable!.isSmart && ( - - )} +
+
+
+ +
+
+
+ + <div className={styles.badges}> + <RarityBadge + rarity={item.rarity} + assetType={AssetType.ITEM} + category={NFTCategory.WEARABLE} + /> + {category && ( + <CategoryBadge + category={ + item.data.emote + ? item.data.emote.category + : item.data.wearable!.category + } + assetType={AssetType.ITEM} + /> + )} + {item.category === NFTCategory.EMOTE && ( + <IconBadge + icon={loop ? 'play-loop' : 'play-once'} + text={t(`emote.play_mode.${loop ? 'loop' : 'simple'}`)} + href={emoteBadgeHref} + /> + )} + {bodyShapes.length > 0 && !item.data.emote && ( + <GenderBadge + bodyShapes={bodyShapes} + assetType={AssetType.ITEM} + section={ + item.category === NFTCategory.WEARABLE + ? Section.WEARABLES + : Section.EMOTES + } + /> + )} + {item.category === NFTCategory.WEARABLE && + item.data.wearable!.isSmart && ( + <SmartBadge assetType={AssetType.ITEM} /> + )} + + <CampaignBadge contract={item.contractAddress} /> + </div> + </div> - <CampaignBadge contract={item.contractAddress} /> - </> - } - left={ - <> <Description text={description} /> - <div className="BaseDetail row"> + <div className={styles.basicRow}> <Owner asset={item} /> <Collection asset={item} /> </div> - </> - } - box={null} - showDetails - actions={<SaleActionBox asset={item} />} - below={ - <> <BestBuyingOption asset={item} tableRef={tableRef} /> - <ListingsTableContainer item={item} ref={tableRef} /> - <TransactionHistory asset={item} /> - </> - } - /> + </div> + </div> + + <Container> + <ListingsTableContainer item={item} ref={tableRef} /> + <TransactionHistory asset={item} /> + </Container> + </div> ) } diff --git a/webapp/src/components/AssetPage/ListingsTable/ListingsTable.module.css b/webapp/src/components/AssetPage/ListingsTable/ListingsTable.module.css index b02ca7006..5ab8c869d 100644 --- a/webapp/src/components/AssetPage/ListingsTable/ListingsTable.module.css +++ b/webapp/src/components/AssetPage/ListingsTable/ListingsTable.module.css @@ -30,6 +30,11 @@ align-items: center; } +.ListingsTable .badge { + color: white; + background-color: var(--background) !important; +} + .ListingsTable .goToNFT { color: white; padding-right: 25px; diff --git a/webapp/src/components/AssetPage/ListingsTable/ListingsTable.tsx b/webapp/src/components/AssetPage/ListingsTable/ListingsTable.tsx index 71291f2b5..c309dbcf4 100644 --- a/webapp/src/components/AssetPage/ListingsTable/ListingsTable.tsx +++ b/webapp/src/components/AssetPage/ListingsTable/ListingsTable.tsx @@ -4,7 +4,7 @@ import { ListingStatus, Network } from '@dcl/schemas' import { Table, Loader, Row, Pagination, Icon, Mana } from 'decentraland-ui' import { t } from 'decentraland-dapps/dist/modules/translation/utils' import { Order, OrderFilters, OrderSortBy } from '@dcl/schemas/dist/dapps/order' -import { orderAPI } from '../../../modules/vendor/decentraland' +import { nftAPI, orderAPI } from '../../../modules/vendor/decentraland' import { locations } from '../../../modules/routing/locations' import { formatWeiMANA } from '../../../lib/mana' import { formatDistanceToNow, getDateAndMonthName } from '../../../lib/date' @@ -42,10 +42,25 @@ const ListingsTable = (props: Props) => { params.nftName = asset.name } + asset.itemId && + nftAPI + .getOwners({ + contractAddress: asset.contractAddress, + itemId: asset.itemId, + first: 1, + skip: 0 + }) + .then(response => { + setTotal(response.total) + }) + .finally(() => setIsLoading(false)) + .catch(error => { + console.error(error) + }) + orderAPI .fetchOrders(params, sortBy) .then(response => { - setTotal(response.total) setOrders(response.data) setTotalPages(Math.ceil(response.total / ROWS_PER_PAGE) || 0) }) diff --git a/webapp/src/components/AssetPage/ListingsTableContainer/ListingsTableContainer.module.css b/webapp/src/components/AssetPage/ListingsTableContainer/ListingsTableContainer.module.css index 45b1e9291..d6d8661f6 100644 --- a/webapp/src/components/AssetPage/ListingsTableContainer/ListingsTableContainer.module.css +++ b/webapp/src/components/AssetPage/ListingsTableContainer/ListingsTableContainer.module.css @@ -15,6 +15,7 @@ border-top-left-radius: 10px; align-items: center; border-bottom: 1px solid var(--secondary); + padding-left: 20px; } .tableContainer { @@ -39,10 +40,6 @@ right: 20px; } -.tabStyle { - padding-left: 20px; -} - .ui.dropdown > .icon { color: white !important; height: 100%; @@ -57,6 +54,7 @@ .filtertabsContainer { flex-direction: column; + padding: unset; } .tabStyle { diff --git a/webapp/src/components/AssetPage/TransactionHistory/TransactionHistory.css b/webapp/src/components/AssetPage/TransactionHistory/TransactionHistory.css index ebd9ab5fc..d129bffd7 100644 --- a/webapp/src/components/AssetPage/TransactionHistory/TransactionHistory.css +++ b/webapp/src/components/AssetPage/TransactionHistory/TransactionHistory.css @@ -22,3 +22,31 @@ .TransactionHistory tbody.is-loading tr { opacity: 0.5; } + +.TransactionHistory .titleContainer { + display: flex; + padding: 20 0px; + border-top-right-radius: 10px; + border-top-left-radius: 10px; + align-items: center; + border-bottom: 1px solid var(--secondary); + padding-left: 20px; +} + +.TransactionHistory .tableContainer { + display: flex; + flex-direction: column; + border: 2px solid var(--secondary); + border-radius: 12px; + margin-top: 48px; +} + +.TransactionHistory .firstTabMargin { + padding-left: 20px !important; +} + +@media (max-width: 768px) { + .TransactionHistory .titleContainer { + padding: 20px; + } +} diff --git a/webapp/src/components/AssetPage/TransactionHistory/TransactionHistory.tsx b/webapp/src/components/AssetPage/TransactionHistory/TransactionHistory.tsx index 042a7d9a2..3794f0378 100644 --- a/webapp/src/components/AssetPage/TransactionHistory/TransactionHistory.tsx +++ b/webapp/src/components/AssetPage/TransactionHistory/TransactionHistory.tsx @@ -1,13 +1,13 @@ import React, { useState, useEffect } from 'react' import { Item, Sale } from '@dcl/schemas' import { - Header, Table, Mobile, NotMobile, Pagination, Loader, - Row + Row, + Tabs } from 'decentraland-ui' import { t } from 'decentraland-dapps/dist/modules/translation/utils' import dateFnsFormat from 'date-fns/format' @@ -91,13 +91,15 @@ const TransactionHistory = (props: Props) => { return ( <div className="TransactionHistory"> {isLoading && sales.length === 0 ? null : sales.length > 0 ? ( - <> - <Header sub>{t('transaction_history.title')}</Header> + <div className="tableContainer"> + <div className="titleContainer"> + <Tabs.Tab> {t('transaction_history.title')}</Tabs.Tab> + </div> <NotMobile> <Table basic="very"> <Table.Header> <Table.Row> - <Table.HeaderCell> + <Table.HeaderCell className="firstTabMargin"> {t('transaction_history.from')} </Table.HeaderCell> <Table.HeaderCell> @@ -118,7 +120,7 @@ const TransactionHistory = (props: Props) => { <Table.Body className={isLoading ? 'is-loading' : ''}> {sales.map(sale => ( <Table.Row key={sale.id}> - <Table.Cell> + <Table.Cell className="firstTabMargin"> <LinkedProfile address={sale.seller} /> </Table.Cell> <Table.Cell> @@ -164,7 +166,7 @@ const TransactionHistory = (props: Props) => { /> </Row> ) : null} - </> + </div> ) : null} </div> )