From c24d03487b77b370b47e7978131eda38b4190ac8 Mon Sep 17 00:00:00 2001 From: sergey filyanin Date: Mon, 15 Jan 2024 12:27:06 +0100 Subject: [PATCH 01/34] Create Dockerfile --- frontend/Dockerfile | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 frontend/Dockerfile diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..3fbd832 --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,27 @@ +FROM node:18-alpine + +COPY ./frontend /opt + +RUN apk update + +RUN apk add xsel + +ARG VITE_NODE_ADDRESS \ + VITE_IPFS_ADDRESS \ + VITE_IPFS_GATEWAY_ADDRESS \ + VITE_CONTRACT_ADDRESS +ENV VITE_NODE_ADDRESS=${VITE_NODE_ADDRESS} \ + VITE_IPFS_ADDRESS=${VITE_IPFS_ADDRESS} \ + VITE_IPFS_GATEWAY_ADDRESS=${VITE_IPFS_GATEWAY_ADDRESS} \ + VITE_CONTRACT_ADDRESS=${VITE_CONTRACT_ADDRESS} \ + DISABLE_ESLINT_PLUGIN=true + +WORKDIR /opt + +RUN pnpm install + +RUN pnpm build + +RUN npm install --global serve + +CMD ["serve", "-s", "/opt/dist"] From 3258667ef10e398be293c1808280e467abcc05ce Mon Sep 17 00:00:00 2001 From: sergey filyanin Date: Mon, 15 Jan 2024 12:34:19 +0100 Subject: [PATCH 02/34] Update Dockerfile --- frontend/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 3fbd832..0fb5e49 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -6,6 +6,8 @@ RUN apk update RUN apk add xsel +RUN npm install -g pnpm + ARG VITE_NODE_ADDRESS \ VITE_IPFS_ADDRESS \ VITE_IPFS_GATEWAY_ADDRESS \ From 9ddcd5fc294dee91b8fcbdc628e3c00b8917b876 Mon Sep 17 00:00:00 2001 From: sergey filyanin Date: Mon, 15 Jan 2024 13:04:58 +0100 Subject: [PATCH 03/34] Update Dockerfile --- frontend/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 0fb5e49..2b35fe8 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,4 +1,5 @@ FROM node:18-alpine +MAINTAINER GEAR COPY ./frontend /opt From 06fe0f0c85ffe09e5715c393e58b4d84d7b55a98 Mon Sep 17 00:00:00 2001 From: Nikita Yutanov Date: Mon, 15 Jan 2024 16:20:19 +0300 Subject: [PATCH 04/34] Add collection header component --- .../collection-header.module.scss | 98 +++++++++++++++++++ .../collection-header/collection-header.tsx | 66 +++++++++++++ .../components/collection-header/index.ts | 3 + .../components/collection-header/nft 350.svg | 1 + .../collection/collection.module.scss | 81 --------------- .../components/collection/collection.tsx | 73 +++----------- 6 files changed, 184 insertions(+), 138 deletions(-) create mode 100644 frontend/src/features/collections/components/collection-header/collection-header.module.scss create mode 100644 frontend/src/features/collections/components/collection-header/collection-header.tsx create mode 100644 frontend/src/features/collections/components/collection-header/index.ts create mode 100644 frontend/src/features/collections/components/collection-header/nft 350.svg diff --git a/frontend/src/features/collections/components/collection-header/collection-header.module.scss b/frontend/src/features/collections/components/collection-header/collection-header.module.scss new file mode 100644 index 0000000..8210bcf --- /dev/null +++ b/frontend/src/features/collections/components/collection-header/collection-header.module.scss @@ -0,0 +1,98 @@ +.container { + --logo-size: 196px; + --outer-padding: 48px; + --inner-padding: 24px; + --padding-left: calc(var(--logo-size) + var(--outer-padding) + var(--inner-padding)); + + background-color: #fff; + + border-radius: 15px; + overflow: hidden; +} + +.header { + min-height: 260px; + padding-left: var(--padding-left); + padding-bottom: 24px; + + display: flex; + align-items: flex-end; + + position: relative; + + .banner { + position: absolute; + bottom: 0; + left: 0; + + width: 100%; + height: 100%; + object-fit: cover; + } + + .logo { + position: absolute; + bottom: 0; + left: 0; + transform: translate(48px, 50%); + + width: var(--logo-size); + height: var(--logo-size); + object-fit: cover; + + border: 1px solid #fff; + border-radius: 50%; + } + + .cards { + display: flex; + gap: 32px; + + position: relative; + } +} + +.footer { + min-height: 128px; + padding: 16px 16px 32px var(--padding-left); + + display: grid; + grid-template-columns: 7.77fr 2.23fr; + gap: 40px; + + .name { + margin-bottom: 4px; + + font-size: 20px; + font-weight: 600; + line-height: 26px; + letter-spacing: 0.01em; + } + + .description { + line-height: 25px; + letter-spacing: 0.01em; + color: #93989a; + } + + .socials { + margin-bottom: 24px; + + display: flex; + align-items: center; + justify-content: center; + gap: 12px; + + a { + transition: opacity 0.25s; + + &:hover { + opacity: 0.75; + } + } + + svg path { + fill: #000; + } + } +} diff --git a/frontend/src/features/collections/components/collection-header/collection-header.tsx b/frontend/src/features/collections/components/collection-header/collection-header.tsx new file mode 100644 index 0000000..2f40bf5 --- /dev/null +++ b/frontend/src/features/collections/components/collection-header/collection-header.tsx @@ -0,0 +1,66 @@ +import { HexString } from '@gear-js/api'; + +import LandscapeSVG from '../../assets/landscape.svg?react'; +import UserSVG from '../../assets/user.svg?react'; +import { SOCIAL_ICON } from '../../consts'; +import { InfoCard } from '../info-card'; +import { MintNFT } from '../mint-nft'; + +import styles from './collection-header.module.scss'; + +type Props = { + id: HexString; + banner: string; + logo: string; + owner: HexString; + tokensCount: number; + name: string; + description: string; + socials: Record; +}; + +function CollectionHeader({ id, banner, logo, owner, tokensCount, name, description, socials }: Props) { + const socialEntries = Object.entries(socials).filter(([, value]) => !!value) as [string, string][]; + + const renderSocials = () => + socialEntries.map(([key, value]) => { + const SVG = SOCIAL_ICON[key as keyof typeof SOCIAL_ICON]; + + return ( +
  • + + + +
  • + ); + }); + + return ( +
    +
    + + + +
    + + +
    +
    + +
    +
    +

    {name}

    +

    {description}

    +
    + +
    +
      {renderSocials()}
    + + +
    +
    +
    + ); +} + +export { CollectionHeader }; diff --git a/frontend/src/features/collections/components/collection-header/index.ts b/frontend/src/features/collections/components/collection-header/index.ts new file mode 100644 index 0000000..e864625 --- /dev/null +++ b/frontend/src/features/collections/components/collection-header/index.ts @@ -0,0 +1,3 @@ +import { CollectionHeader } from './collection-header'; + +export { CollectionHeader }; diff --git a/frontend/src/features/collections/components/collection-header/nft 350.svg b/frontend/src/features/collections/components/collection-header/nft 350.svg new file mode 100644 index 0000000..0615749 --- /dev/null +++ b/frontend/src/features/collections/components/collection-header/nft 350.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/src/features/collections/components/collection/collection.module.scss b/frontend/src/features/collections/components/collection/collection.module.scss index e85ed86..3046ee0 100644 --- a/frontend/src/features/collections/components/collection/collection.module.scss +++ b/frontend/src/features/collections/components/collection/collection.module.scss @@ -1,84 +1,3 @@ -.header { - border-radius: 15px; - overflow: hidden; - background-color: #fff; - - .cover { - min-height: 260px; - padding: 24px; - - display: flex; - align-items: flex-end; - justify-content: center; - - background-position: center; - background-size: cover; - background-repeat: no-repeat; - } - - .infoCards { - display: flex; - gap: 32px; - - position: relative; - } -} - -.summary { - margin-top: -98px; - padding: 0 32px 32px 48px; - - display: flex; - align-items: flex-end; - gap: 40px; - - .logo { - width: 196px; - height: 196px; - object-fit: cover; - - border: 1px solid #fff; - border-radius: 50%; - } - - .name { - margin-bottom: 4px; - - font-size: 20px; - font-weight: 600; - line-height: 26px; - letter-spacing: 0.01em; - } - - .description { - line-height: 25px; - letter-spacing: 0.01em; - color: #93989a; - } - - .container { - flex: 1; - display: flex; - justify-content: space-between; - gap: 40px; - } - - .actions { - min-width: 200px; - - display: flex; - flex-direction: column; - align-items: center; - } - - .socials { - margin-bottom: 24px; - - display: flex; - gap: 12px; - } -} - .nfts { margin-top: 32px; diff --git a/frontend/src/features/collections/components/collection/collection.tsx b/frontend/src/features/collections/components/collection/collection.tsx index 1e50ec1..3305f19 100644 --- a/frontend/src/features/collections/components/collection/collection.tsx +++ b/frontend/src/features/collections/components/collection/collection.tsx @@ -6,11 +6,7 @@ import { Container } from '@/components'; import { useCollection } from '@/hooks'; import { getIpfsLink } from '@/utils'; -import LandscapeSVG from '../../assets/landscape.svg?react'; -import UserSVG from '../../assets/user.svg?react'; -import { SOCIAL_ICON } from '../../consts'; -import { InfoCard } from '../info-card'; -import { MintNFT } from '../mint-nft'; +import { CollectionHeader } from '../collection-header'; import { NFTCard } from '../nft-card'; import styles from './collection.module.scss'; @@ -23,70 +19,33 @@ function Collection() { const { id } = useParams() as Params; const collection = useCollection(id); - - const socialEntries = Object.entries(collection?.config.additionalLinks || {}).filter(([, value]) => !!value) as [ - string, - string, - ][]; - - const getSocials = () => - socialEntries.map(([key, value]) => { - const SVG = SOCIAL_ICON[key as keyof typeof SOCIAL_ICON]; - - return ( -
  • - - - -
  • - ); - }); + const { config, tokens, collectionOwner } = collection || {}; + const tokensCount = tokens?.length; const getNFTs = () => collection?.tokens.map(([nftId, nft]) => ( )); - return collection ? ( + return config && collectionOwner && tokensCount !== undefined ? ( -
    -
    -
    - - -
    -
    - -
    - - -
    -
    -

    {collection.config.name}

    -

    {collection.config.description}

    -
    - -
    - {!!socialEntries.length &&
      {getSocials()}
    } - -
    -
    -
    -
    +
    -
    - {collection.tokens.length ? ( + {tokensCount ? (
      {getNFTs()}
    ) : (
    From a163643bed32fb059d9db4fb5dc34cba844bc2e4 Mon Sep 17 00:00:00 2001 From: Nikita Yutanov Date: Mon, 15 Jan 2024 16:48:16 +0300 Subject: [PATCH 05/34] Fix token limit display --- .../collection-card.module.scss | 6 ++++++ .../collection-card/collection-card.tsx | 10 ++++++++-- .../collection-header/collection-header.tsx | 7 ++++--- .../components/collection/collection.tsx | 5 +++-- .../info-card/info-card.module.scss | 4 ++++ .../components/mint-limit-info-card/index.ts | 3 +++ .../mint-limit-info-card.tsx | 20 +++++++++++++++++++ frontend/src/features/collections/types.ts | 1 + 8 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 frontend/src/features/collections/components/mint-limit-info-card/index.ts create mode 100644 frontend/src/features/collections/components/mint-limit-info-card/mint-limit-info-card.tsx diff --git a/frontend/src/features/collections/components/collection-card/collection-card.module.scss b/frontend/src/features/collections/components/collection-card/collection-card.module.scss index cf8e2ee..a926d05 100644 --- a/frontend/src/features/collections/components/collection-card/collection-card.module.scss +++ b/frontend/src/features/collections/components/collection-card/collection-card.module.scss @@ -66,3 +66,9 @@ line-height: 13px; color: #93989a; } + +.cards { + padding: 12px 16px; + + border-top: 1px solid #f3f3f3; +} diff --git a/frontend/src/features/collections/components/collection-card/collection-card.tsx b/frontend/src/features/collections/components/collection-card/collection-card.tsx index 1747777..ce78a35 100644 --- a/frontend/src/features/collections/components/collection-card/collection-card.tsx +++ b/frontend/src/features/collections/components/collection-card/collection-card.tsx @@ -6,6 +6,8 @@ import { ROUTE } from '@/consts'; import { useCollection } from '@/hooks'; import { getIpfsLink } from '@/utils'; +import { MintLimitInfoCard } from '../mint-limit-info-card'; + import styles from './collection-card.module.scss'; type Props = { @@ -14,9 +16,9 @@ type Props = { function CollectionCard({ id }: Props) { const collection = useCollection(id); - const { config, collectionOwner } = collection || {}; + const { config, collectionOwner, tokens, totalNumberOfTokens } = collection || {}; - return config && collectionOwner ? ( + return config && collectionOwner && tokens !== undefined && totalNumberOfTokens !== undefined ? (
  • @@ -35,6 +37,10 @@ function CollectionCard({ id }: Props) {
  • + +
    + +
    ) : null; diff --git a/frontend/src/features/collections/components/collection-header/collection-header.tsx b/frontend/src/features/collections/components/collection-header/collection-header.tsx index 2f40bf5..9f08131 100644 --- a/frontend/src/features/collections/components/collection-header/collection-header.tsx +++ b/frontend/src/features/collections/components/collection-header/collection-header.tsx @@ -1,9 +1,9 @@ import { HexString } from '@gear-js/api'; -import LandscapeSVG from '../../assets/landscape.svg?react'; import UserSVG from '../../assets/user.svg?react'; import { SOCIAL_ICON } from '../../consts'; import { InfoCard } from '../info-card'; +import { MintLimitInfoCard } from '../mint-limit-info-card'; import { MintNFT } from '../mint-nft'; import styles from './collection-header.module.scss'; @@ -14,12 +14,13 @@ type Props = { logo: string; owner: HexString; tokensCount: number; + tokensLimit: string | null; name: string; description: string; socials: Record; }; -function CollectionHeader({ id, banner, logo, owner, tokensCount, name, description, socials }: Props) { +function CollectionHeader({ id, banner, logo, owner, tokensCount, tokensLimit, name, description, socials }: Props) { const socialEntries = Object.entries(socials).filter(([, value]) => !!value) as [string, string][]; const renderSocials = () => @@ -43,7 +44,7 @@ function CollectionHeader({ id, banner, logo, owner, tokensCount, name, descript
    - +
    diff --git a/frontend/src/features/collections/components/collection/collection.tsx b/frontend/src/features/collections/components/collection/collection.tsx index 3305f19..0c7dd8b 100644 --- a/frontend/src/features/collections/components/collection/collection.tsx +++ b/frontend/src/features/collections/components/collection/collection.tsx @@ -19,7 +19,7 @@ function Collection() { const { id } = useParams() as Params; const collection = useCollection(id); - const { config, tokens, collectionOwner } = collection || {}; + const { config, tokens, collectionOwner, totalNumberOfTokens } = collection || {}; const tokensCount = tokens?.length; const getNFTs = () => @@ -27,7 +27,7 @@ function Collection() { )); - return config && collectionOwner && tokensCount !== undefined ? ( + return config && collectionOwner && tokensCount !== undefined && totalNumberOfTokens !== undefined ? ( & { + heading: string | null; + text: number; +}; + +function MintLimitInfoCard({ heading, text, ...props }: Props) { + return ( + + ); +} + +export { MintLimitInfoCard }; diff --git a/frontend/src/features/collections/types.ts b/frontend/src/features/collections/types.ts index 69ad798..30a040c 100644 --- a/frontend/src/features/collections/types.ts +++ b/frontend/src/features/collections/types.ts @@ -81,6 +81,7 @@ type CollectionState = { }, ][]; collectionOwner: HexString; + totalNumberOfTokens: string | null; }; }; From 9c4c176bfc0d4f7cb1eb2941348144244e4053c8 Mon Sep 17 00:00:00 2001 From: Nikita Yutanov Date: Mon, 15 Jan 2024 19:36:25 +0300 Subject: [PATCH 06/34] Fix nft mint with price --- .../collection-header/collection-header.tsx | 16 ++++++++++++++-- .../components/collection-header/nft 350.svg | 1 - .../components/collection/collection.tsx | 2 ++ .../collections/components/mint-nft/mint-nft.tsx | 5 +++-- 4 files changed, 19 insertions(+), 5 deletions(-) delete mode 100644 frontend/src/features/collections/components/collection-header/nft 350.svg diff --git a/frontend/src/features/collections/components/collection-header/collection-header.tsx b/frontend/src/features/collections/components/collection-header/collection-header.tsx index 9f08131..30f8578 100644 --- a/frontend/src/features/collections/components/collection-header/collection-header.tsx +++ b/frontend/src/features/collections/components/collection-header/collection-header.tsx @@ -15,12 +15,24 @@ type Props = { owner: HexString; tokensCount: number; tokensLimit: string | null; + mintPrice: string; name: string; description: string; socials: Record; }; -function CollectionHeader({ id, banner, logo, owner, tokensCount, tokensLimit, name, description, socials }: Props) { +function CollectionHeader({ + id, + banner, + logo, + owner, + tokensCount, + tokensLimit, + name, + description, + mintPrice, + socials, +}: Props) { const socialEntries = Object.entries(socials).filter(([, value]) => !!value) as [string, string][]; const renderSocials = () => @@ -57,7 +69,7 @@ function CollectionHeader({ id, banner, logo, owner, tokensCount, tokensLimit, n
      {renderSocials()}
    - +
    diff --git a/frontend/src/features/collections/components/collection-header/nft 350.svg b/frontend/src/features/collections/components/collection-header/nft 350.svg deleted file mode 100644 index 0615749..0000000 --- a/frontend/src/features/collections/components/collection-header/nft 350.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/src/features/collections/components/collection/collection.tsx b/frontend/src/features/collections/components/collection/collection.tsx index 0c7dd8b..11b5290 100644 --- a/frontend/src/features/collections/components/collection/collection.tsx +++ b/frontend/src/features/collections/components/collection/collection.tsx @@ -1,4 +1,5 @@ import { HexString } from '@gear-js/api'; +import { withoutCommas } from '@gear-js/react-hooks'; import { Button } from '@gear-js/vara-ui'; import { useParams } from 'react-router-dom'; @@ -38,6 +39,7 @@ function Collection() { tokensLimit={totalNumberOfTokens} name={config.name} description={config.description} + mintPrice={withoutCommas(config.paymentForMint)} socials={config.additionalLinks || {}} /> diff --git a/frontend/src/features/collections/components/mint-nft/mint-nft.tsx b/frontend/src/features/collections/components/mint-nft/mint-nft.tsx index d41b602..20a257b 100644 --- a/frontend/src/features/collections/components/mint-nft/mint-nft.tsx +++ b/frontend/src/features/collections/components/mint-nft/mint-nft.tsx @@ -6,12 +6,13 @@ import { useCollectionSendMessage } from '@/hooks'; type Props = { collectionId: HexString; + value: string; }; -function Component({ collectionId }: Props) { +function Component({ collectionId, value }: Props) { const sendMessage = useCollectionSendMessage(collectionId); - const handleClick = () => sendMessage({ payload: { Mint: null } }); + const handleClick = () => sendMessage({ payload: { Mint: null }, value }); return - - )); - - return ( - <> -
      {getCollectionTypes()}
    - - {isModalOpen && } - - ); -} - -export { CreateCollection }; diff --git a/frontend/src/features/create-collection/components/index.ts b/frontend/src/features/create-collection/components/index.ts deleted file mode 100644 index 154916f..0000000 --- a/frontend/src/features/create-collection/components/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { CreateCollection } from './create-collection'; - -export { CreateCollection }; diff --git a/frontend/src/features/create-collection/consts.ts b/frontend/src/features/create-collection/consts.ts deleted file mode 100644 index a3402d1..0000000 --- a/frontend/src/features/create-collection/consts.ts +++ /dev/null @@ -1,27 +0,0 @@ -import NoteSVG from './assets/note.svg?react'; -import PictureSVG from './assets/picture.svg?react'; -import PuzzleSVG from './assets/puzzle.svg?react'; - -const COLLECTION_TYPES = [ - { - heading: 'Simple NFT collection', - text: 'Create unique compositions by using a single image or combining multiple, with the ability to customize repetition for each.', - tag: 'gNFT', - SVG: PictureSVG, - }, - - { - heading: 'Composable NFT collection', - text: 'Allows to combine and customize individual NFTs to create unique compositions, adding a layer of creativity to the digital assets.', - tag: 'gCNFT', - SVG: PuzzleSVG, - }, - { - heading: 'NFT Collection for Music creators', - text: 'Upload MP3 music compositions and fine-tune demo playback parameters for a personalized and immersive experience.', - tag: 'gMNFT', - SVG: NoteSVG, - }, -]; - -export { COLLECTION_TYPES }; diff --git a/frontend/src/features/create-collection/index.ts b/frontend/src/features/create-collection/index.ts deleted file mode 100644 index b8d0828..0000000 --- a/frontend/src/features/create-collection/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { CreateCollection } from './components'; - -export { CreateCollection }; diff --git a/frontend/src/features/create-collection/assets/picture.svg b/frontend/src/features/create-simple-collection/assets/picture.svg similarity index 100% rename from frontend/src/features/create-collection/assets/picture.svg rename to frontend/src/features/create-simple-collection/assets/picture.svg diff --git a/frontend/src/features/create-collection/assets/right-arrow.svg b/frontend/src/features/create-simple-collection/assets/right-arrow.svg similarity index 100% rename from frontend/src/features/create-collection/assets/right-arrow.svg rename to frontend/src/features/create-simple-collection/assets/right-arrow.svg diff --git a/frontend/src/features/create-collection/components/create-collection/create-collection.module.scss b/frontend/src/features/create-simple-collection/components/create-collection/create-collection.module.scss similarity index 91% rename from frontend/src/features/create-collection/components/create-collection/create-collection.module.scss rename to frontend/src/features/create-simple-collection/components/create-collection/create-collection.module.scss index 3a3929b..aa4dde0 100644 --- a/frontend/src/features/create-collection/components/create-collection/create-collection.module.scss +++ b/frontend/src/features/create-simple-collection/components/create-collection/create-collection.module.scss @@ -1,9 +1,3 @@ -.buttons { - display: flex; - flex-direction: column; - gap: 16px; -} - .button { display: flex; align-items: center; diff --git a/frontend/src/features/create-simple-collection/components/create-collection/create-collection.tsx b/frontend/src/features/create-simple-collection/components/create-collection/create-collection.tsx new file mode 100644 index 0000000..8a757fe --- /dev/null +++ b/frontend/src/features/create-simple-collection/components/create-collection/create-collection.tsx @@ -0,0 +1,42 @@ +import { ModalProps } from '@gear-js/vara-ui'; + +import { useModal } from '@/hooks'; +import { SVGComponent } from '@/types'; + +import ArrowSVG from '../../assets/right-arrow.svg?react'; + +import styles from './create-collection.module.scss'; + +type Props = { + heading: string; + tag: string; + text: string; + SVG: SVGComponent; + modal: (props: Pick) => JSX.Element; +}; + +function CreateCollection({ heading, tag, text, SVG, modal: Modal }: Props) { + const [isOpen, open, close] = useModal(); + + return ( + <> + + + {isOpen && } + + ); +} + +export { CreateCollection }; diff --git a/frontend/src/features/create-collection/components/create-collection/index.ts b/frontend/src/features/create-simple-collection/components/create-collection/index.ts similarity index 100% rename from frontend/src/features/create-collection/components/create-collection/index.ts rename to frontend/src/features/create-simple-collection/components/create-collection/index.ts diff --git a/frontend/src/features/create-simple-collection/components/create-simple-collection-modal/create-simple-collection-modal.tsx b/frontend/src/features/create-simple-collection/components/create-simple-collection-modal/create-simple-collection-modal.tsx index 4b5b816..5d42dd1 100644 --- a/frontend/src/features/create-simple-collection/components/create-simple-collection-modal/create-simple-collection-modal.tsx +++ b/frontend/src/features/create-simple-collection/components/create-simple-collection-modal/create-simple-collection-modal.tsx @@ -4,7 +4,8 @@ import { useState } from 'react'; import { Container } from '@/components'; import { useIPFS } from '@/context'; -import { useProgramMetadata, useMarketplaceSendMessage } from '@/hooks'; +import { useMarketplaceSendMessage } from '@/features/marketplace'; +import { useProgramMetadata } from '@/hooks'; import nftMetadataSource from '../../assets/nft.meta.txt'; import { diff --git a/frontend/src/features/create-simple-collection/components/create-simple-collection/create-simple-collection.tsx b/frontend/src/features/create-simple-collection/components/create-simple-collection/create-simple-collection.tsx new file mode 100644 index 0000000..bf3b568 --- /dev/null +++ b/frontend/src/features/create-simple-collection/components/create-simple-collection/create-simple-collection.tsx @@ -0,0 +1,17 @@ +import PictureSVG from '../../assets/picture.svg?react'; +import { CreateCollection } from '../create-collection'; +import { CreateSimpleCollectionModal } from '../create-simple-collection-modal'; + +function CreateSimpleCollection() { + return ( + + ); +} + +export { CreateSimpleCollection }; diff --git a/frontend/src/features/create-simple-collection/components/create-simple-collection/index.ts b/frontend/src/features/create-simple-collection/components/create-simple-collection/index.ts new file mode 100644 index 0000000..291c694 --- /dev/null +++ b/frontend/src/features/create-simple-collection/components/create-simple-collection/index.ts @@ -0,0 +1,3 @@ +import { CreateSimpleCollection } from './create-simple-collection'; + +export { CreateSimpleCollection }; diff --git a/frontend/src/features/create-simple-collection/components/index.ts b/frontend/src/features/create-simple-collection/components/index.ts index d38e992..291c694 100644 --- a/frontend/src/features/create-simple-collection/components/index.ts +++ b/frontend/src/features/create-simple-collection/components/index.ts @@ -1,3 +1,3 @@ -import { CreateSimpleCollectionModal } from './create-simple-collection-modal'; +import { CreateSimpleCollection } from './create-simple-collection'; -export { CreateSimpleCollectionModal }; +export { CreateSimpleCollection }; diff --git a/frontend/src/features/create-simple-collection/index.ts b/frontend/src/features/create-simple-collection/index.ts index 4aa7105..9bd1a9b 100644 --- a/frontend/src/features/create-simple-collection/index.ts +++ b/frontend/src/features/create-simple-collection/index.ts @@ -1,3 +1,3 @@ -import { CreateSimpleCollectionModal } from './components'; +import { CreateSimpleCollection } from './components'; -export { CreateSimpleCollectionModal }; +export { CreateSimpleCollection }; diff --git a/frontend/src/features/lists/assets/large-grid.svg b/frontend/src/features/lists/assets/large-grid.svg new file mode 100644 index 0000000..7fc09fa --- /dev/null +++ b/frontend/src/features/lists/assets/large-grid.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/src/features/lists/assets/small-grid.svg b/frontend/src/features/lists/assets/small-grid.svg new file mode 100644 index 0000000..d81a6f5 --- /dev/null +++ b/frontend/src/features/lists/assets/small-grid.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/src/features/lists/components/grid-size/grid-size.tsx b/frontend/src/features/lists/components/grid-size/grid-size.tsx new file mode 100644 index 0000000..85bd7f6 --- /dev/null +++ b/frontend/src/features/lists/components/grid-size/grid-size.tsx @@ -0,0 +1,27 @@ +import { FilterButton } from '@/components'; + +import LargeGridSVG from '../../assets/large-grid.svg?react'; +import SmallGridSVG from '../../assets/small-grid.svg?react'; +import { GRID_SIZE } from '../../consts'; +import { GridSize as GridSizeType } from '../../types'; + +const BUTTONS = [ + { SVG: SmallGridSVG, value: GRID_SIZE.SMALL }, + { SVG: LargeGridSVG, value: GRID_SIZE.LARGE }, +] as const; + +type Props = { + value: GridSizeType; + onChange: (value: GridSizeType) => void; +}; + +function GridSize({ value, onChange }: Props) { + const renderButtons = () => + BUTTONS.map(({ value: _value, SVG }) => { + return onChange(_value)} isActive={_value === value} />; + }); + + return
    {renderButtons()}
    ; +} + +export { GridSize }; diff --git a/frontend/src/features/lists/components/grid-size/index.ts b/frontend/src/features/lists/components/grid-size/index.ts new file mode 100644 index 0000000..ea2cf2b --- /dev/null +++ b/frontend/src/features/lists/components/grid-size/index.ts @@ -0,0 +1,3 @@ +import { GridSize } from './grid-size'; + +export { GridSize }; diff --git a/frontend/src/features/lists/components/index.ts b/frontend/src/features/lists/components/index.ts new file mode 100644 index 0000000..ea2cf2b --- /dev/null +++ b/frontend/src/features/lists/components/index.ts @@ -0,0 +1,3 @@ +import { GridSize } from './grid-size'; + +export { GridSize }; diff --git a/frontend/src/features/lists/consts.ts b/frontend/src/features/lists/consts.ts new file mode 100644 index 0000000..c7c19a3 --- /dev/null +++ b/frontend/src/features/lists/consts.ts @@ -0,0 +1,6 @@ +const GRID_SIZE = { + SMALL: 'smallGrid', + LARGE: 'largeGrid', +} as const; + +export { GRID_SIZE }; diff --git a/frontend/src/features/lists/hooks.ts b/frontend/src/features/lists/hooks.ts new file mode 100644 index 0000000..38dbb8d --- /dev/null +++ b/frontend/src/features/lists/hooks.ts @@ -0,0 +1,12 @@ +import { useState } from 'react'; + +import { GRID_SIZE } from './consts'; +import { GridSize } from './types'; + +function useGridSize() { + const [gridSize, setGridSize] = useState(GRID_SIZE.SMALL); + + return { gridSize, setGridSize }; +} + +export { useGridSize }; diff --git a/frontend/src/features/lists/index.ts b/frontend/src/features/lists/index.ts new file mode 100644 index 0000000..32cb980 --- /dev/null +++ b/frontend/src/features/lists/index.ts @@ -0,0 +1,4 @@ +import { GridSize } from './components'; +import { useGridSize } from './hooks'; + +export { GridSize, useGridSize }; diff --git a/frontend/src/features/lists/types.ts b/frontend/src/features/lists/types.ts new file mode 100644 index 0000000..253a6fb --- /dev/null +++ b/frontend/src/features/lists/types.ts @@ -0,0 +1,5 @@ +import { GRID_SIZE } from './consts'; + +type GridSize = typeof GRID_SIZE.LARGE | typeof GRID_SIZE.SMALL; + +export type { GridSize }; diff --git a/frontend/src/assets/nft_marketplace.meta.txt b/frontend/src/features/marketplace/assets/nft_marketplace.meta.txt similarity index 100% rename from frontend/src/assets/nft_marketplace.meta.txt rename to frontend/src/features/marketplace/assets/nft_marketplace.meta.txt diff --git a/frontend/src/features/marketplace/components/buy-nft/buy-nft.tsx b/frontend/src/features/marketplace/components/buy-nft/buy-nft.tsx index a07ab5b..63bca75 100644 --- a/frontend/src/features/marketplace/components/buy-nft/buy-nft.tsx +++ b/frontend/src/features/marketplace/components/buy-nft/buy-nft.tsx @@ -2,7 +2,8 @@ import { HexString } from '@gear-js/api'; import { Button } from '@gear-js/vara-ui'; import { withAccount } from '@/components'; -import { useMarketplaceSendMessage } from '@/hooks'; + +import { useMarketplaceSendMessage } from '../../hooks'; type Props = { id: string; diff --git a/frontend/src/features/marketplace/components/index.ts b/frontend/src/features/marketplace/components/index.ts index dba00c0..b70cf27 100644 --- a/frontend/src/features/marketplace/components/index.ts +++ b/frontend/src/features/marketplace/components/index.ts @@ -2,6 +2,5 @@ import { BuyNFT } from './buy-nft'; import { MakeBid } from './make-bid'; import { StartAuction } from './start-auction'; import { StartSale } from './start-sale'; -import { TransferNFT } from './transfer-nft'; -export { BuyNFT, MakeBid, StartAuction, StartSale, TransferNFT }; +export { BuyNFT, MakeBid, StartAuction, StartSale }; diff --git a/frontend/src/features/marketplace/components/make-bid/make-bid.tsx b/frontend/src/features/marketplace/components/make-bid/make-bid.tsx index e3b24fb..b5d6e5e 100644 --- a/frontend/src/features/marketplace/components/make-bid/make-bid.tsx +++ b/frontend/src/features/marketplace/components/make-bid/make-bid.tsx @@ -1,14 +1,11 @@ import { HexString } from '@gear-js/api'; -import { useBalanceFormat } from '@gear-js/react-hooks'; -import { Button, ModalProps } from '@gear-js/vara-ui'; -import { zodResolver } from '@hookform/resolvers/zod'; -import { useForm } from 'react-hook-form'; +import { Button } from '@gear-js/vara-ui'; import { z } from 'zod'; -import { PriceInput, withAccount } from '@/components'; -import { useMarketplaceSendMessage, useModal } from '@/hooks'; +import { NFTActionFormModal, PriceInput, withAccount } from '@/components'; +import { useModal } from '@/hooks'; -import { NFTActionFormModal } from '../nft-action-form-modal'; +import { useMarketplaceSendMessage, usePriceSchema } from '../../hooks'; type Props = { nft: { id: string; name: string; mediaUrl: string }; @@ -20,52 +17,36 @@ const defaultValues = { value: '', }; -const getSchema = (minBid: number) => - z.object({ - value: z.coerce.number().min(minBid), - }); - -const getResolver = (minBid: number) => zodResolver(getSchema(minBid)); +function Component({ nft, collection, auction }: Props) { + const [isOpen, open, close] = useModal(); -function MakeBidModal({ nft, collection, auction, close }: Props & Pick) { - const { handleSubmit, register, formState } = useForm({ defaultValues, resolver: getResolver(+auction.minBid) }); - const { errors } = formState; + const { getPriceSchema } = usePriceSchema(); + const schema = z.object({ value: getPriceSchema(auction.minBid, true) }); - const { getChainBalanceValue } = useBalanceFormat(); const sendMessage = useMarketplaceSendMessage(); - const onSubmit = handleSubmit((data) => { + const onSubmit = ({ value }: typeof defaultValues) => { const tokenId = nft.id; const collectionAddress = collection.id; const payload = { AddBid: { tokenId, collectionAddress } }; - const value = getChainBalanceValue(data.value).toFixed(); const onSuccess = close; sendMessage({ payload, value, onSuccess }); - }); - - const modalProps = { - heading: 'Make bid', - close, - onSubmit, }; - return ( - - - - ); -} - -function Component(props: Props) { - const [isOpen, open, close] = useModal(); + const modalProps = { heading: 'Make bid', close }; + const formProps = { defaultValues, schema, onSubmit }; return ( <>