diff --git a/public/assets/images/404/nft_error_bg.webp b/public/assets/images/404/nft_error_bg.webp new file mode 100644 index 0000000..0ea9625 Binary files /dev/null and b/public/assets/images/404/nft_error_bg.webp differ diff --git a/public/assets/images/404/nft_error_bg_dark.webp b/public/assets/images/404/nft_error_bg_dark.webp new file mode 100644 index 0000000..50642d7 Binary files /dev/null and b/public/assets/images/404/nft_error_bg_dark.webp differ diff --git a/public/assets/images/marketplace/lower-symbol.webp b/public/assets/images/marketplace/lower-symbol.webp new file mode 100644 index 0000000..16b9a09 Binary files /dev/null and b/public/assets/images/marketplace/lower-symbol.webp differ diff --git a/public/assets/images/marketplace/upper-symbol.webp b/public/assets/images/marketplace/upper-symbol.webp new file mode 100644 index 0000000..e74be94 Binary files /dev/null and b/public/assets/images/marketplace/upper-symbol.webp differ diff --git a/src/components/Alert/AlertInfo.jsx b/src/components/Alert/AlertInfo.jsx new file mode 100644 index 0000000..56e4a96 --- /dev/null +++ b/src/components/Alert/AlertInfo.jsx @@ -0,0 +1,12 @@ +import { Icon } from '@/elements/Icon' + +const AlertInfo = () => { + return ( +
+ + Please connect your wallet to view milestones and minting levels. +
+ ) +} + +export default AlertInfo diff --git a/src/components/Alert/AlertInfo.scss b/src/components/Alert/AlertInfo.scss new file mode 100644 index 0000000..f3609a7 --- /dev/null +++ b/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; + } +} diff --git a/src/components/CountUp/CountUp.jsx b/src/components/CountUp/CountUp.jsx index 387289e..9166624 100644 --- a/src/components/CountUp/CountUp.jsx +++ b/src/components/CountUp/CountUp.jsx @@ -61,6 +61,10 @@ const CountUp = ({ number, symbol, prefix = false, localized = false }) => { const counterValue = getReadableCounterValue({ localized, val, number }) + if (number <= 0) { + return {prefix && symbol}{localized ? number.toLocaleString('en-US') : number}{!prefix && symbol} + } + return ( {prefix && symbol}{counterValue}{!prefix && symbol} ) diff --git a/src/elements/icons/paths.js b/src/elements/icons/paths.js index a8492ce..8b80196 100644 --- a/src/elements/icons/paths.js +++ b/src/elements/icons/paths.js @@ -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'), diff --git a/src/layouts/BaseLayout.jsx b/src/layouts/BaseLayout.jsx index 646d31a..da0f86f 100644 --- a/src/layouts/BaseLayout.jsx +++ b/src/layouts/BaseLayout.jsx @@ -35,7 +35,7 @@ const BaseLayout = ({ children, videos }) => {
{children} -
+ {router.pathname !== '/404' &&
}
) } diff --git a/src/pages/404.jsx b/src/pages/404.jsx new file mode 100644 index 0000000..1a44c96 --- /dev/null +++ b/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 ( + <> + + + + + + + ) +} + +export default PageNotFound diff --git a/src/pages/404.scss b/src/pages/404.scss new file mode 100644 index 0000000..87a0323 --- /dev/null +++ b/src/pages/404.scss @@ -0,0 +1 @@ +@import "../views/404.scss"; diff --git a/src/pages/marketplace/[tokenId].jsx b/src/pages/marketplace/[tokenId].jsx index e6eb0bf..e00d5f9 100644 --- a/src/pages/marketplace/[tokenId].jsx +++ b/src/pages/marketplace/[tokenId].jsx @@ -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 + } } } diff --git a/src/pages/marketplace/mint/[tokenId].jsx b/src/pages/marketplace/mint/[tokenId].jsx index 7a1b04b..c230cda 100644 --- a/src/pages/marketplace/mint/[tokenId].jsx +++ b/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 + } } } @@ -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) { @@ -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 <> } @@ -68,7 +112,7 @@ const MintNftPage = ({ nftDetails, premiumNfts, mintingLevels, videos }) => { /> - + ) diff --git a/src/pages/marketplace/page/[page].jsx b/src/pages/marketplace/page/[page].jsx index 97cf715..1b81189 100644 --- a/src/pages/marketplace/page/[page].jsx +++ b/src/pages/marketplace/page/[page].jsx @@ -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 } } } diff --git a/src/service/nft-api.js b/src/service/nft-api.js index 0b0e34d..4cbb782 100644 --- a/src/service/nft-api.js +++ b/src/service/nft-api.js @@ -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, @@ -78,7 +86,8 @@ const NftApi = { getNftDetails, logView, logWantToMint, - mintingLevels + mintingLevels, + mintingLevelsMilestone } export { NftApi } diff --git a/src/styles/global.scss b/src/styles/global.scss index bf78a7e..6b0a09e 100644 --- a/src/styles/global.scss +++ b/src/styles/global.scss @@ -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"; @@ -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"; diff --git a/src/views/404.jsx b/src/views/404.jsx new file mode 100644 index 0000000..912522b --- /dev/null +++ b/src/views/404.jsx @@ -0,0 +1,24 @@ +import { Button } from '@/components/Button/Button' + +const Error404 = () => { + return ( +
+
+

404 Error

+

Page Not Found

+

Sorry, the page you are looking for doesn’t exist or has been moved.

+
+ +
+ ) +} + +export default Error404 diff --git a/src/views/404.scss b/src/views/404.scss new file mode 100644 index 0000000..8a23f11 --- /dev/null +++ b/src/views/404.scss @@ -0,0 +1,79 @@ +@use "../design-system/utils"; +@use "../design-system/colors"; +@use "../design-system/typography/styles"; +@use "../design-system/typography/weights"; + +.pagenotfound.page { + display: flex; + justify-content: center; + align-items: center; + text-align: center; + flex-direction: column; + gap: 32px; + height: calc(100vh - var(--header-height)); + position: relative; + + &::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: url("../../public/assets/images/404/nft_error_bg.webp") no-repeat center top; + background-size: 100% 100%; + z-index: -1; + } + + .inner.container { + display: flex; + flex-direction: column; + gap: 12px; + padding: 0 16px; + + h1 { + @include styles.display-xl; + + @media (max-width: 767px) { + @include styles.display-md; + } + } + + h2 { + @include styles.text-md; + @include weights.semibold; + color: colors.$primary-600; + } + + p { + @include styles.text-xl; + @include weights.regular; + + @media (max-width: 767px) { + @include styles.text-lg; + } + } + } + + .ui.primary.button { + display: inline-flex; + } +} + +.dark .pagenotfound.page { + &::before { + background: url("../../public/assets/images/404/nft_error_bg_dark.webp") no-repeat center top; + background-size: 100% 100%; + mix-blend-mode: overlay; + } + + .inner.container { + h2 { + color: colors.$primary-300; + } + + p { + color: colors.$gray-25; + } + } +} diff --git a/src/views/MintNft.jsx b/src/views/MintNft.jsx index 66bb1d2..7a366a3 100644 --- a/src/views/MintNft.jsx +++ b/src/views/MintNft.jsx @@ -1,5 +1,4 @@ -import { useState } from 'react' - +import AlertInfo from '@/components/Alert/AlertInfo' import { Breadcrumb } from '@/components/Breadcrumb/Breadcrumb' import { ConnectWallet } from '@/components/ConnectWallet/ConnectWallet' import CountUp from '@/components/CountUp/CountUp' @@ -13,18 +12,12 @@ import { Progress } from '@/components/Progress/Progress' import { Tags } from '@/components/Tags/Tags' import { CustomTooltip } from '@/components/Tooltip/Tooltip' import { mintingLevelRequirements } from '@/config/minting-levels' -import { AppConstants } from '@/constants/AppConstants' import { Icon } from '@/elements/Icon' -import { weiToToken } from '@/utils/currencyHelpers' import { MintingLevels } from '@/views/mint-nft/MintingLevels' import { Summary } from '@/views/mint-nft/Summary' +import { useWeb3React } from '@web3-react/core' -const userProgress = { - totalPolicyPurchased: 80000000, - totalLiquidityAdded: 2500000000 -} - -const MintNft = ({ nftDetails, premiumNfts, mintingLevels }) => { +const MintNft = ({ nftDetails, premiumNfts, mintingLevels, currentProgress }) => { const crumbs = [ { link: '/', @@ -44,10 +37,7 @@ const MintNft = ({ nftDetails, premiumNfts, mintingLevels }) => { } ] - const [currentProgress] = useState({ - totalLiquidityAdded: weiToToken(userProgress.totalLiquidityAdded, AppConstants.FALLBACK_LIQUIDITY_TOKEN_DECIMALS), - totalPolicyPurchased: weiToToken(userProgress.totalPolicyPurchased, AppConstants.FALLBACK_LIQUIDITY_TOKEN_DECIMALS) - }) + const { account } = useWeb3React() const requirements = mintingLevelRequirements[nftDetails.level] @@ -67,7 +57,7 @@ const MintNft = ({ nftDetails, premiumNfts, mintingLevels }) => {
Required:
-
${required.toLocaleString('en-US')}
+
${required?.toLocaleString('en-US')}

Your Policy Purchase:
${current.toLocaleString('en-US')}
@@ -90,81 +80,88 @@ const MintNft = ({ nftDetails, premiumNfts, mintingLevels }) => { ) return ( -
-
- - -
+ <> +
+
+ + +
-
-
- {nftDetails.level && ( - - )} - - -
Mint {nftDetails.name} for Free
- - - -
-
- - - {/* - - */} - - {/* Remove the style below when enabling the above button */} -
- people want to mint this. +
+
+ {nftDetails.level && ( + + )} + + +
Mint {nftDetails.name} for Free
+ + + +
+
+ + + {/* + + */} + + {/* Remove the style below when enabling the above button */} +
+ people want to mint this. +
-
-
-

Your Milestones

- {buildProgress({ - title: 'Policy Purchase', - required: requirements.policyPurchase, - current: currentProgress.totalPolicyPurchased, - percent: policyPurchasePercent, - remaining: policyPurchaseRemaining - })} - {buildProgress({ - title: 'Added Liquidity', - required: requirements.liquidity, - current: currentProgress.totalLiquidityAdded, - percent: liquidityPercent, - remaining: liquidityRemaining - })} - +
+

Your Milestones

+ {buildProgress({ + title: 'Policy Purchase', + required: requirements?.policyPurchase, + current: currentProgress.totalPolicyPurchased, + percent: policyPurchasePercent, + remaining: policyPurchaseRemaining + })} + {buildProgress({ + title: 'Added Liquidity', + required: requirements?.liquidity, + current: currentProgress.totalLiquidityAdded, + percent: liquidityPercent, + remaining: liquidityRemaining + })} + +
-
-
+ - - -
-
-

Explore Our Collection

-
- {premiumNfts.slice(0, 6).map(nft => )} + + +
+
+

Explore Our Collection

+
+ {premiumNfts.slice(0, 6).map(nft => )} +
-
+ + {!account && +
+ +
} + ) } diff --git a/src/views/MintNft.scss b/src/views/MintNft.scss index 9ebc842..5a7b35b 100644 --- a/src/views/MintNft.scss +++ b/src/views/MintNft.scss @@ -30,6 +30,10 @@ .content.inset { margin: 58px 0; + &[data-connect="false"] { + opacity: 0.4; + } + @media (max-width: 1024px) { margin-top: 32px; } @@ -228,6 +232,20 @@ } } +.info.box { + position: fixed; + bottom: 38px; + display: flex; + width: 100%; + justify-content: center; + align-items: center; + padding: 0 16px; + + @media (max-width: 767px) { + bottom: 16px; + } +} + .dark .mint.nft.page { .hero { border-color: colors.$gray-800; diff --git a/src/views/marketplace/MarketplaceSection.jsx b/src/views/marketplace/MarketplaceSection.jsx index 87074ef..650caa9 100644 --- a/src/views/marketplace/MarketplaceSection.jsx +++ b/src/views/marketplace/MarketplaceSection.jsx @@ -134,17 +134,25 @@ const MarketPlaceSection = ({ data = [], filters = [], pageData }) => { ))} {(!loading || isNavigating) && - data.map((nft) => ( - - ))} + data.map((nft) => ( + + ))}
+ + {!loading && !isNavigating && data.length === 0 && +
+
+

No Results Found

+

Adjust your filters and try again.

+
+
}