Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(404 Page, Empty State): Implement 404 page and empty state in marketplace #46

Merged
merged 5 commits into from Apr 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Binary file added public/assets/images/404/nft_error_bg.webp
Binary file not shown.
Binary file added public/assets/images/404/nft_error_bg_dark.webp
Binary file not shown.
Binary file not shown.
Binary file not shown.
12 changes: 12 additions & 0 deletions src/components/Alert/AlertInfo.jsx
@@ -0,0 +1,12 @@
import { Icon } from '@/elements/Icon'

const AlertInfo = () => {
return (
<div className='alert default'>
<Icon variant='info-circle' size='lg' />
<span>Please connect your wallet to view milestones and minting levels.</span>
</div>
)
}

export default AlertInfo
21 changes: 21 additions & 0 deletions src/components/Alert/AlertInfo.scss
@@ -0,0 +1,21 @@
@use "../../design-system/colors";
@use "../../design-system/typography/styles";
@use "../../design-system/typography/weights";

.alert {
display: flex;
padding: 8px 12px;
border-radius: 8px;
color: colors.$base-white;
align-items: center;
gap: 4px;

span {
@include styles.text-md;
@include weights.regular;
}

&.default {
background: colors.$gray-900;
}
}
4 changes: 4 additions & 0 deletions src/components/CountUp/CountUp.jsx
Expand Up @@ -61,6 +61,10 @@ const CountUp = ({ number, symbol, prefix = false, localized = false }) => {

const counterValue = getReadableCounterValue({ localized, val, number })

if (number <= 0) {
return <span ref={countRef}>{prefix && symbol}{localized ? number.toLocaleString('en-US') : number}{!prefix && symbol}</span>
}

return (
<span ref={countRef}>{prefix && symbol}{counterValue}{!prefix && symbol}</span>
)
Expand Down
1 change: 1 addition & 0 deletions src/elements/icons/paths.js
Expand Up @@ -20,6 +20,7 @@ const paths = {
'trash-01': import('./variants/General/trash-01.svg?raw'),
'help-cirlce': import('./variants/General/help-circle.svg?raw'),
'share-01': import('./variants/General/share-01.svg?raw'),
'info-circle': import('./variants/General/info-circle.svg?raw'),
eye: import('./variants/General/eye.svg?raw'),
heart: import('./variants/General/heart.svg?raw'),
minus: import('./variants/General/minus.svg?raw'),
Expand Down
2 changes: 1 addition & 1 deletion src/layouts/BaseLayout.jsx
Expand Up @@ -35,7 +35,7 @@ const BaseLayout = ({ children, videos }) => {
<Header headerStyle={router.pathname === '/marketplace' ? 'colored' : null} videos={videos} />
<div className='header gap' />
{children}
<Footer />
{router.pathname !== '/404' && <Footer />}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why footer is not there is 404 route?

@flashburst Sharad says it wasn't there in design.

</div>
)
}
Expand Down
35 changes: 35 additions & 0 deletions src/pages/404.jsx
@@ -0,0 +1,35 @@
import Seo from '@/components/Seo/Seo'
import { BaseLayout } from '@/layouts/BaseLayout'
import { resourcesVideoData } from '@/service/video-api'
import Error404 from '@/views/404'

export async function getStaticProps () {
const videoData = await resourcesVideoData()

return {
props: {
videos: videoData
},
revalidate: 60 * 60 // one hour
}
}

const PageNotFound = (props) => {
return (
<>
<Seo
ogURL='/404'
title='Page Not Found / Neptune Mutual'
ogImage='/assets/images/meta/home.png'
ogImageAlt='Neptune Mutual NFT 404'
description='The page you requested either does not exist or has been deleted'
/>

<BaseLayout videos={props.videos}>
<Error404 />
</BaseLayout>
</>
)
}

export default PageNotFound
1 change: 1 addition & 0 deletions src/pages/404.scss
@@ -0,0 +1 @@
@import "../views/404.scss";
28 changes: 20 additions & 8 deletions src/pages/marketplace/[tokenId].jsx
Expand Up @@ -13,15 +13,27 @@ import { resourcesVideoData } from '@/service/video-api'
import { NftDetails } from '@/views/NftDetails'

export async function getStaticProps (context) {
const [nftDetailsResponse, premiumNftsResponse, videoResponse] = await Promise.all([NftApi.getNftDetails(context.params.tokenId), NftApi.premiumNfts(), resourcesVideoData()])
try {
const [nftDetailsResponse, premiumNftsResponse, videoResponse] = await Promise.all([NftApi.getNftDetails(context.params.tokenId), NftApi.premiumNfts(), resourcesVideoData()])

return {
props: {
nftDetails: nftDetailsResponse.data[0],
premiumNfts: premiumNftsResponse.data,
videos: videoResponse
},
revalidate: 60 * 60 // one hour
if (nftDetailsResponse.data.length === 0) {
return {
notFound: true
}
}

return {
props: {
nftDetails: nftDetailsResponse.data[0],
premiumNfts: premiumNftsResponse.data,
videos: videoResponse
},
revalidate: 60 * 60 // one hour
}
} catch (error) {
return {
notFound: true
}
}
}

Expand Down
68 changes: 56 additions & 12 deletions src/pages/marketplace/mint/[tokenId].jsx
@@ -1,28 +1,44 @@
import {
useCallback,
useEffect,
useRef
useRef,
useState
} from 'react'

import { useRouter } from 'next/router'

import Seo from '@/components/Seo/Seo'
import { AppConstants } from '@/constants/AppConstants'
import { BaseLayout } from '@/layouts/BaseLayout'
import { NftApi } from '@/service/nft-api'
import { resourcesVideoData } from '@/service/video-api'
import { weiToToken } from '@/utils/currencyHelpers'
import { MintNft } from '@/views/MintNft'
import { useWeb3React } from '@web3-react/core'

export async function getStaticProps (context) {
const [nftDetailsResponse, premiumNftsResponse, mintingLevelResponse, videoResponse] = await Promise.all([NftApi.getNftDetails(context.params.tokenId), NftApi.premiumNfts(), NftApi.mintingLevels(), resourcesVideoData()])

return {
props: {
nftDetails: nftDetailsResponse.data[0],
premiumNfts: premiumNftsResponse.data,
mintingLevels: mintingLevelResponse.data,
videos: videoResponse
},
revalidate: 60 * 60 // one hour
try {
const [nftDetailsResponse, premiumNftsResponse, mintingLevelResponse, videoResponse] = await Promise.all([NftApi.getNftDetails(context.params.tokenId), NftApi.premiumNfts(), NftApi.mintingLevels(), resourcesVideoData()])

if (nftDetailsResponse.data.length === 0) {
return {
notFound: true
}
}

return {
props: {
nftDetails: nftDetailsResponse.data[0],
premiumNfts: premiumNftsResponse.data,
mintingLevels: mintingLevelResponse.data,
videos: videoResponse
},
revalidate: 60 * 60 // one hour
}
} catch (error) {
return {
notFound: true
}
}
}

Expand All @@ -33,8 +49,15 @@ export async function getStaticPaths () {
const MintNftPage = ({ nftDetails, premiumNfts, mintingLevels, videos }) => {
const router = useRouter()

const { account } = useWeb3React()

const logWantToMintExecuted = useRef(false)

const [userProgress, setUserProgress] = useState({
totalLiquidityAdded: 0,
totalPolicyPurchased: 0
})

const logWantToMint = useCallback(async () => {
// This is because react in strict mode, executes useEffect twice.
if (logWantToMintExecuted.current === false) {
Expand All @@ -53,6 +76,27 @@ const MintNftPage = ({ nftDetails, premiumNfts, mintingLevels, videos }) => {
logWantToMint()
}, [logWantToMint])

useEffect(() => {
const fetchMilestones = async () => {
const data = await NftApi.mintingLevelsMilestone(account)

setUserProgress({
totalLiquidityAdded: weiToToken(data.data[0].totalLiquidityAdded, AppConstants.FALLBACK_LIQUIDITY_TOKEN_DECIMALS),
totalPolicyPurchased: weiToToken(data.data[0].totalPolicyPurchased, AppConstants.FALLBACK_LIQUIDITY_TOKEN_DECIMALS)
})
}

if (account) fetchMilestones()
}, [account])

useEffect(() => {
if (!account) {
document.querySelector('body').style.overflow = 'hidden'
} else {
document.querySelector('body').style.overflow = 'auto'
}
}, [account])

if (!nftDetails) {
return <></>
}
Expand All @@ -68,7 +112,7 @@ const MintNftPage = ({ nftDetails, premiumNfts, mintingLevels, videos }) => {
/>

<BaseLayout videos={videos}>
<MintNft nftDetails={nftDetails} premiumNfts={premiumNfts} mintingLevels={mintingLevels} />
<MintNft nftDetails={nftDetails} premiumNfts={premiumNfts} mintingLevels={mintingLevels} currentProgress={userProgress} />
</BaseLayout>
</>
)
Expand Down
28 changes: 20 additions & 8 deletions src/pages/marketplace/page/[page].jsx
Expand Up @@ -5,15 +5,27 @@ import { getSSRData } from '@/utils/ssr'
import { Marketplace } from '@/views/Marketplace'

export async function getServerSideProps (context) {
const { data, marketplaceFilters, pageData } = await getSSRData(context)
const videoData = await resourcesVideoData()
try {
const { data, marketplaceFilters, pageData } = await getSSRData(context)
const videoData = await resourcesVideoData()

return {
props: {
data,
marketplaceFilters,
pageData,
videos: videoData
if (data.length === 0) {
return {
notFound: true
}
}

return {
props: {
data,
marketplaceFilters,
pageData,
videos: videoData
}
}
} catch (error) {
return {
notFound: true
}
}
}
Expand Down
11 changes: 10 additions & 1 deletion src/service/nft-api.js
Expand Up @@ -70,6 +70,14 @@ const mintingLevels = async () => {
return data
}

const mintingLevelsMilestone = async (address) => {
const response = await fetch(origin + '/minting-levels/milestones/' + address)

const data = await response.json()

return data
}

const NftApi = {
knowTheCharacters,
mostViewedNfts,
Expand All @@ -78,7 +86,8 @@ const NftApi = {
getNftDetails,
logView,
logWantToMint,
mintingLevels
mintingLevels,
mintingLevelsMilestone
}

export { NftApi }
2 changes: 2 additions & 0 deletions src/styles/global.scss
Expand Up @@ -122,6 +122,7 @@ button,
@import "../components/Button/LinkColorButton.scss";
@import "../components/Progress/Progress.scss";
@import "../components/IconButton/IconButton.scss";
@import "../components/Alert/AlertInfo.scss";

@import "../components/NftImageWithExpand.scss";
@import "../components/NftNickname.scss";
Expand All @@ -144,6 +145,7 @@ button,
//Pages
@import "../pages/index.scss";
@import "../pages/marketplace/index.scss";
@import "../pages/404.scss";
@import "../views/NftDetails.scss";
@import "../views/MintNft.scss";
@import "../views/mint-nft/MintingLevels.scss";
Expand Down
24 changes: 24 additions & 0 deletions src/views/404.jsx
@@ -0,0 +1,24 @@
import { Button } from '@/components/Button/Button'

const Error404 = () => {
return (
<div className='pagenotfound page'>
<div className='inner container'>
<h2>404 Error</h2>
<h1>Page Not Found</h1>
<p>Sorry, the page you are looking for doesn’t exist or has been moved.</p>
</div>
<Button
type='anchor'
variant='primary'
size='xl'
href='/'
iconTrailing='arrow-narrow-right'
>
Take me to homepage
</Button>
</div>
)
}

export default Error404