diff --git a/components/chain-list/chain-list.tsx b/components/chain-list/chain-list.tsx index edf572b..4fad5e4 100644 --- a/components/chain-list/chain-list.tsx +++ b/components/chain-list/chain-list.tsx @@ -53,7 +53,7 @@ export const ChainContainer = styled.div` flex-direction: column; width: 100%; //max-height: 33rem; - overflow: scroll; + overflow-y: scroll; flex: 1; diff --git a/components/error-modal/index.tsx b/components/error-modal/index.tsx new file mode 100644 index 0000000..de154a8 --- /dev/null +++ b/components/error-modal/index.tsx @@ -0,0 +1,151 @@ +import color from "../../styles/color"; +import { FunctionComponent } from "react"; +import ReactModal from "react-modal"; +import { ErrorMessage } from "../../types"; +import styled from "styled-components"; + +import Image from "next/image"; +interface Props { + isModalOpen: boolean; + onCloseModal: () => void; + errorMessage?: ErrorMessage; +} + +import ErrorIcon from "../../public/images/svg/error-icon.svg"; +import ArrowLeftIcon from "../../public/images/svg/arrow-left.svg"; +import { useRouter } from "next/router"; + +export const ErrorModal: FunctionComponent = (props) => { + const router = useRouter(); + const { isModalOpen, onCloseModal, errorMessage } = props; + + const onClose = async () => { + if (errorMessage?.path) { + await router.push(errorMessage.path); + } + + onCloseModal(); + }; + + return ( + + + + + error icon + + Error + + + {errorMessage?.message} + + {errorMessage?.path ? ( + + + back button icon + + GO BACK TO HOME + + ) : null} + + + ); +}; + +const ModalContainer = styled.div` + display: flex; + flex-direction: column; + + width: 32rem; + + padding: 2.5rem 2.25rem; +`; + +const ErrorTitleContainer = styled.div` + display: flex; + flex-direction: row; + gap: 1rem; + + align-items: center; + + font-family: "Inter", serif; + font-style: normal; + font-weight: 600; + font-size: 2rem; + line-height: 2.5rem; + + color: ${color.white}; +`; + +const ErrorImageContainer = styled.div` + width: 2.5rem; + height: 2.5rem; + + position: relative; +`; + +const ErrorDescription = styled.div` + margin-top: 1rem; + + font-family: "Inter", serif; + font-style: normal; + font-weight: 400; + font-size: 1rem; + line-height: 1.25rem; + + color: ${color.grey["300"]}; +`; + +const ErrorBackButton = styled.div` + display: flex; + flex-direction: row; + align-items: center; + gap: 0.3rem; + + margin-top: 2.5rem; + + font-family: "Inter", serif; + font-style: normal; + font-weight: 600; + font-size: 1.125rem; + line-height: 1.125rem; + + color: ${color.grey["100"]}; + + cursor: pointer; +`; + +const ErrorBackIconContainer = styled.div` + width: 1.5rem; + height: 1.5rem; + + position: relative; +`; diff --git a/components/final-check-modal/index.tsx b/components/final-check-modal/index.tsx index b102d5d..6960003 100644 --- a/components/final-check-modal/index.tsx +++ b/components/final-check-modal/index.tsx @@ -54,7 +54,7 @@ export const FinalCheckModal: FunctionComponent = (props) => { > Final Checks - {`You are claiming the ICNS name ${twitterUserName} on main keplr account`} + {`You are claiming the ICNS name ${twitterUserName} on keplr account`} = (props) => { }} /> } - title="Main Keplr Account" + title={walletInfo?.name || "Keplr account"} content={Bech32Address.shortenAddress( walletInfo?.bech32Address || "", 28, diff --git a/components/logo/index.tsx b/components/logo/index.tsx index dbca3be..9d22f2a 100644 --- a/components/logo/index.tsx +++ b/components/logo/index.tsx @@ -36,4 +36,8 @@ export const LogoContainer = styled.div` margin-top: 5rem; margin-left: 5rem; + + @media screen and (max-width: 1280px) { + display: none; + } `; diff --git a/pages/verification/index.tsx b/pages/verification/index.tsx index d9f1a2e..252975c 100644 --- a/pages/verification/index.tsx +++ b/pages/verification/index.tsx @@ -7,6 +7,7 @@ import { useEffect, useState } from "react"; import { ChainItemType, DisabledChainItemType, + ErrorMessage, QueryError, RegisteredAddresses, TwitterProfileType, @@ -49,7 +50,6 @@ import { queryRegisteredTwitterId, verifyTwitterAccount, } from "../../queries"; -import { ErrorHandler } from "../../utils/error"; import { KEPLR_NOT_FOUND_ERROR, TWITTER_LOGIN_ERROR, @@ -58,8 +58,10 @@ import { makeClaimMessage, makeSetRecordMessage } from "../../messages"; import Axios from "axios"; import { BackButton } from "../../components/back-button"; import { FinalCheckModal } from "../../components/final-check-modal"; +import { ErrorModal } from "../../components/error-modal"; +import * as process from "process"; -export default function VerificationPage() { +export default function VerificationPage(props: { blockList: string[] }) { const router = useRouter(); const [twitterAuthInfo, setTwitterAuthInfo] = useState(); @@ -93,6 +95,8 @@ export default function VerificationPage() { const [isOwner, setIsOwner] = useState(false); const [isModalOpen, setModalOpen] = useState(false); + const [isErrorModalOpen, setErrorModalOpen] = useState(false); + const [errorMessage, setErrorMessage] = useState(); useEffect(() => { init(); @@ -203,8 +207,11 @@ export default function VerificationPage() { setRegisteredChainList(addressesQueryResponse.data.addresses); } } catch (error) { - if (error instanceof Error && error.message === TWITTER_LOGIN_ERROR) { - await router.push("/"); + if (error instanceof Error) { + if (error.message === TWITTER_LOGIN_ERROR) { + setErrorMessage({ message: TWITTER_LOGIN_ERROR, path: "/" }); + setErrorModalOpen(true); + } } console.error(error); @@ -227,7 +234,8 @@ export default function VerificationPage() { return keplrWallet; } else { - ErrorHandler(KEPLR_NOT_FOUND_ERROR); + setErrorMessage({ message: KEPLR_NOT_FOUND_ERROR, path: "/" }); + setErrorModalOpen(true); } }; @@ -255,6 +263,10 @@ export default function VerificationPage() { const chainArray = []; for (let i = 0; i < chainKeys.length; i++) { + if (props.blockList.includes(chainInfos[i].prefix)) { + continue; + } + const chainKey = chainKeys[i]; if (chainKey.status !== "fulfilled") { console.log("Failed to get key from wallet", chainKey); @@ -399,7 +411,17 @@ export default function VerificationPage() { } } catch (error) { if (Axios.isAxiosError(error)) { - console.error((error?.response?.data as QueryError).message); + setErrorMessage({ + message: (error?.response?.data as QueryError).message, + }); + setErrorModalOpen(true); + return; + } + + if (error instanceof Error) { + console.log(error.message); + setErrorMessage({ message: error.message }); + setErrorModalOpen(true); } } finally { setIsLoadingRegistration(false); @@ -407,7 +429,7 @@ export default function VerificationPage() { }; const isRegisterButtonDisable = (() => { - if (!isOwner) { + if (!isOwner && nftOwnerAddress) { return true; } @@ -490,10 +512,25 @@ export default function VerificationPage() { onClickRegisterButton={handleRegistration} isLoadingRegistration={isLoadingRegistration} /> + + setErrorModalOpen(false)} + errorMessage={errorMessage} + /> ); } +export async function getStaticProps() { + let blockList: string[] = []; + if (process.env.BLOCK_LIST) { + blockList = process.env.BLOCK_LIST.trim().split(","); + } + + return { props: { blockList } }; +} + const Container = styled.div` width: 100vw; height: 100vh; diff --git a/public/images/svg/error-icon.svg b/public/images/svg/error-icon.svg new file mode 100644 index 0000000..3ab520f --- /dev/null +++ b/public/images/svg/error-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/types/error-message.ts b/types/error-message.ts new file mode 100644 index 0000000..07e207c --- /dev/null +++ b/types/error-message.ts @@ -0,0 +1,4 @@ +export interface ErrorMessage { + message: string; + path?: string; +} diff --git a/types/index.ts b/types/index.ts index a14cb5f..7a6f5e9 100644 --- a/types/index.ts +++ b/types/index.ts @@ -4,3 +4,4 @@ export * from "./chain-item-type"; export * from "./msg"; export * from "./twitter"; export * from "./icns"; +export * from "./error-message";