Skip to content

Commit

Permalink
Merge pull request #18 from Long6695/feat/artist-page
Browse files Browse the repository at this point in the history
Feat/artist page
  • Loading branch information
Long6695 authored Mar 29, 2023
2 parents 4c2509d + bfb3784 commit 46b4bc1
Show file tree
Hide file tree
Showing 13 changed files with 1,700 additions and 55 deletions.
13 changes: 10 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nft-marketplace-next",
"version": "0.1.0",
"version": "0.1.1",
"private": true,
"scripts": {
"dev": "next dev",
Expand All @@ -11,7 +11,8 @@
"check-lint": "eslint . --ext ts --ext tsx --ext js",
"format": "prettier --write .",
"test-all": "yarn check-format && yarn check-lint && yarn check-types && yarn build",
"prepare": "husky install"
"prepare": "husky install",
"release": "release-it"
},
"dependencies": {
"@heroicons/react": "^2.0.15",
Expand All @@ -31,6 +32,7 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"react-hook-form": "^7.43.1",
"react-icons": "^4.8.0",
"react-toastify": "^9.1.1",
"typescript": "*"
},
Expand All @@ -51,6 +53,11 @@
"lint-staged": "^13.1.1",
"postcss": "^8.4.21",
"prettier": "2.8.4",
"release-it": "^15.8.0",
"tailwindcss": "^3.2.6"
}
},
"main": "index.js",
"repository": "git@github.com-personal:Long6695/nft-marketplace.git",
"author": "Long6695 <thaihothanhlong95@gmail.com>",
"license": "MIT"
}
Binary file added public/images/artist-bg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/ava-artist-square.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions release-it.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"git": {
"tagName": "${version}",
"commitMessage": "chore: Release ${version}"
},
"npm": {
"publish": true
},
"github": {
"release": true
}
}
107 changes: 107 additions & 0 deletions src/components/Artists/ArtistInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import React from 'react'
import UIButton from '../Button/UIButton'
import { UIText } from '../Text/UIText'
import { BiCopy } from 'react-icons/bi'
import { BsPlus } from 'react-icons/bs'
import {
AiOutlineFacebook,
AiOutlineYoutube,
AiOutlineInstagram,
} from 'react-icons/ai'
import { RxDiscordLogo } from 'react-icons/rx'
import { CiTwitter } from 'react-icons/ci'
import { breakStringWith3Dots } from '@/utils/function'
import { useMediaQuery } from '@/hooks/useMediaQuery'

const ArtistInfo = (): JSX.Element => {
const { isMobile } = useMediaQuery()
const renderTotalSale = ({
qty,
text,
}: {
qty: string
text: string
}): JSX.Element => {
return (
<div className="flex flex-col">
<UIText
text={qty}
sizeMobile="h5"
sizeTablet="h5"
sizeDesktop="h4"
font="space-mono"
/>
<UIText
text={text}
sizeMobile="default"
sizeTablet="default"
sizeDesktop="h5"
/>
</div>
)
}
return (
<div className="container flex flex-col gap-5 mt-[120px]">
<div className="flex flex-col items-start gap-5 desktop:flex-row">
<UIText
text="Animakid"
sizeDesktop="h2"
sizeTablet="h3"
sizeMobile="h4"
/>
<div className="w-full flex flex-col gap-5 tablet:flex-row desktop:justify-end">
<UIButton fullWidth={isMobile} customIcon={<BiCopy />}>
{breakStringWith3Dots('0xc0E3123saidA*a9sda89A*DTA*(TD8satd7as8')}
</UIButton>
<UIButton
fullWidth={isMobile}
variant="outlined"
customIcon={<BsPlus />}
>
Follow
</UIButton>
</div>
</div>
<div className="w-full flex items-center gap-10 tablet:justify-start desktop:gap-20">
{renderTotalSale({ qty: '250k+', text: 'Volume' })}
{renderTotalSale({ qty: '50+', text: 'NFTs Sold' })}
{renderTotalSale({ qty: '3000+', text: 'Followers' })}
</div>
<div>
<UIText
text="Bio"
sizeMobile="h5"
sizeTablet="h5"
sizeDesktop="h4"
font="space-mono"
color="gray"
/>
<UIText
text="The internet's friendliest designer kid."
sizeMobile="default"
sizeTablet="default"
sizeDesktop="h5"
/>
</div>
<div>
<UIText
text="Links"
sizeMobile="h5"
sizeTablet="h5"
sizeDesktop="h4"
font="space-mono"
color="gray"
/>
<div className="flex gap-2">
<AiOutlineFacebook />
<RxDiscordLogo />
<AiOutlineYoutube />
<CiTwitter />
<AiOutlineInstagram />
</div>
</div>
</div>
)
}

export default ArtistInfo
79 changes: 79 additions & 0 deletions src/components/Artists/ArtistTabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React, { useState } from 'react'
import cn from 'classnames'
import { UIText } from '../Text/UIText'

const TABS = [
{
label: 'Created',
value: 'created',
quantity: 302,
},
{
label: 'Owned',
value: 'owned',
quantity: 67,
},
{
label: 'Collection',
value: 'collection',
quantity: 4,
},
]

const ArtistTabs = (): JSX.Element => {
const [active, setActive] = useState('created')

const renderQuantities = (tab: {
value: string
quantity: number
}): JSX.Element => {
return (
<div
className={cn('min-w-[40px] text-white rounded-full ml-2', {
'px-1': tab.quantity < 100,
'px-2': tab.quantity > 100,
'bg-black-secondary': active !== tab.value,
'bg-gray': active === tab.value,
})}
>
<UIText
text={tab.quantity.toString()}
font="space-mono"
onlySize="default"
/>
</div>
)
}

return (
<div className="container text-center">
<ul className="flex justify-between">
{TABS.map((tab) => (
<li
key={tab.value}
onClick={() => {
setActive(tab.value)
}}
className={cn(
'w-full cursor-pointer flex justify-center items-center py-4',
{
'border-b-2 border-gray text-white': tab.value === active,
'text-gray': tab.value !== active,
},
)}
>
<UIText
text={tab.label}
sizeDesktop="h5"
sizeMobile="default"
sizeTablet="default"
/>
{renderQuantities(tab)}
</li>
))}
</ul>
</div>
)
}

export default ArtistTabs
5 changes: 4 additions & 1 deletion src/components/Button/UIButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import s from './Button.module.css'
import React from 'react'
import cn from 'classnames'
import Image from 'next/image'
import { type IconType } from 'react-icons'

type ButtonVariant = 'filled' | 'outlined' | 'filled-white'
type ButtonHeight = 'sm' | 'md' | 'lg'
Expand All @@ -15,6 +16,7 @@ type ButtonProps = {
icon?: string
size?: number
width?: string
customIcon?: React.ReactElement<IconType>
} & Omit<React.ComponentProps<'button'>, 'className'>

const UIButton = ({
Expand All @@ -27,18 +29,19 @@ const UIButton = ({
icon,
size = 20,
width,
customIcon,
...props
}: ButtonProps): JSX.Element => {
const classes = cn(s.root, s[variant], s[height], {
[s.fullWidth]: fullWidth,
'min-w-20 px-4': !fullWidth,
[width as string]: !!width,
})

return (
<button className={classes} {...props}>
<div className="mr-2">
{icon && <Image src={icon} alt={icon} width={size} height={size} />}
{customIcon}
</div>
{children}
</button>
Expand Down
7 changes: 7 additions & 0 deletions src/components/Divider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react'

const Divider = (): JSX.Element => {
return <div className="border-b-2 border-black-secondary mt-10" />
}

export default Divider
2 changes: 1 addition & 1 deletion src/components/Footer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const UIFooter = (): JSX.Element => {
return <UIText text={text} onlySize="default" color="gray" />
}
return (
<div className="bg-black-secondary p-10">
<div className="bg-black-secondary p-10 border-t-2 border-black">
<div className="max-w-[1280px] mx-auto grid grid-cols-1 tablet:grid-cols-[500px] desktop:grid-cols-footer gap-10">
<div>
<div className="mb-5">
Expand Down
8 changes: 6 additions & 2 deletions src/components/Home/Discover/DiscoverCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import { useMediaQuery } from '@/hooks/useMediaQuery'
import Image from 'next/image'
import React from 'react'

const DiscoverCard = (): JSX.Element => {
const DiscoverCard = ({
bg = 'bg-black-secondary',
}: {
bg?: string
}): JSX.Element => {
const { isMobile } = useMediaQuery()
return (
<div className="w-[330px] h-[462px] tablet:h-[469px]">
Expand All @@ -15,7 +19,7 @@ const DiscoverCard = (): JSX.Element => {
height={isMobile ? 238 : 300}
alt="discover"
/>
<div className="flex flex-col w-full bg-black-secondary rounded-b-2xl p-4">
<div className={`flex flex-col w-full ${bg} rounded-b-2xl p-4`}>
<Avatar name="Mr Fox" title="DSNG Animals" />
<div className="flex justify-between mt-2">
<div>
Expand Down
51 changes: 51 additions & 0 deletions src/pages/artists/[id].tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react'
import Image from 'next/image'
import ArtistInfo from '@/components/Artists/ArtistInfo'
import { useMediaQuery } from '@/hooks/useMediaQuery'
import cn from 'classnames'
import ArtistTabs from '@/components/Artists/ArtistTabs'
import DiscoverCard from '@/components/Home/Discover/DiscoverCard'
import WrapperCards from '@/components/WrapperCards'
import Divider from '@/components/Divider'

const ArtistPage = (): JSX.Element => {
const { isMobile } = useMediaQuery()

const renderItems = (qty: number): React.ReactNode => {
return Array.from({ length: qty }, (_, idx) => (
<DiscoverCard bg="bg-black" key={idx} />
))
}

return (
<div className="flex flex-col">
<div className="relative w-full h-[320px]">
<Image priority fill src="/images/artist-bg.png" alt="artist" />
<div className="absolute container h-full flex items-end left-1/2 -translate-x-1/2">
<div
className={cn('absolute -bottom-14', {
'left-1/2 -translate-x-1/2': isMobile,
})}
>
<Image
src="/images/ava-artist-square.png"
alt="artist"
width={120}
height={120}
/>
</div>
</div>
</div>
<ArtistInfo />
<Divider />
<ArtistTabs />
<div className="w-full bg-black-secondary">
<div className="container mb-10">
<WrapperCards>{renderItems(9)}</WrapperCards>
</div>
</div>
</div>
)
}

export default ArtistPage
5 changes: 5 additions & 0 deletions src/utils/function.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const breakStringWith3Dots = (text: string): string => {
const get6CharsFirst = text.substring(0, 6)
const get4CharsLast = text.substring(text.length - 4)
return `${get6CharsFirst}...${get4CharsLast}`
}
Loading

0 comments on commit 46b4bc1

Please sign in to comment.