Add final check modal

This commit is contained in:
HeesungB 2022-12-18 01:51:29 +09:00
parent e0151666b2
commit 68d8ba31aa
6 changed files with 301 additions and 58 deletions

View File

@ -0,0 +1,196 @@
import { FunctionComponent } from "react";
import color from "../../styles/color";
import ReactModal from "react-modal";
import styled from "styled-components";
import TwitterIcon from "../../public/images/svg/twitter-modal-icon.svg";
import Image from "next/image";
import { PrimaryButton } from "../primary-button";
import { SecondaryButton } from "../secondary-button";
import { MINIMUM_OSMO_FEE } from "../../constants/wallet";
import { useRouter } from "next/router";
interface Props {
twitterUserName: string | undefined;
walletInfo:
| { name: string; pubKey: Uint8Array; bech32Address: string }
| undefined;
isModalOpen: boolean;
onCloseModal: () => void;
onClickRegisterButton: () => Promise<void>;
}
export const FinalCheckModal: FunctionComponent<Props> = (props) => {
const {
twitterUserName,
walletInfo,
isModalOpen,
onCloseModal,
onClickRegisterButton,
} = props;
const router = useRouter();
return (
<ReactModal
isOpen={isModalOpen}
onRequestClose={onCloseModal}
ariaHideApp={false}
style={{
overlay: { background: "#121212cc" },
content: {
top: "50%",
left: "50%",
right: "auto",
bottom: "auto",
padding: 0,
marginRight: "-50%",
transform: "translate(-50%, -50%)",
background: color.grey["800"],
border: 0,
},
}}
>
<ModalContainer>
<ModalTitle>Final Checks</ModalTitle>
<MainText>You are claiming the ICNS name</MainText>
<ICNSNameContainer>
<BoldText>{twitterUserName}</BoldText>
<TwitterImageContainer>
<Image
src={TwitterIcon}
fill={true}
sizes="2rem"
alt="twitter icon"
/>
</TwitterImageContainer>
</ICNSNameContainer>
<MainText>on</MainText>
<BoldText>{walletInfo?.name}</BoldText>
<MainText>({walletInfo?.bech32Address})</MainText>
<Divider />
<SubText>
ICNS name can only be claimed once per Twitter account.
<br />
ICNS name cant be transferred at this time.
<br />
Please make sure youve selected the right account on your wallet.
</SubText>
<SubText>
<SubBoldText>{MINIMUM_OSMO_FEE}</SubBoldText> will be spent as a
spam-prevention fee.
</SubText>
<ButtonContainer>
<SecondaryButton
onClick={async () => {
await router.push("/");
}}
>
Use a different account
</SecondaryButton>
<RegisterButton>
<PrimaryButton onClick={onClickRegisterButton}>
Register
</PrimaryButton>
</RegisterButton>
</ButtonContainer>
</ModalContainer>
</ReactModal>
);
};
const ModalContainer = styled.div`
display: flex;
flex-direction: column;
gap: 0.625rem;
width: 50rem;
padding: 1.75rem 2rem;
`;
const ModalTitle = styled.div`
font-family: "Inter", serif;
font-style: normal;
font-weight: 700;
font-size: 1.5rem;
line-height: 1.8rem;
margin-bottom: 1rem;
color: ${color.white};
`;
const ICNSNameContainer = styled.div`
display: flex;
flex-direction: row;
align-items: center;
gap: 0.5rem;
`;
const TwitterImageContainer = styled.div`
width: 2rem;
height: 2rem;
margin-top: 0.4rem;
position: relative;
`;
const MainText = styled.div`
font-family: "Inter", serif;
font-style: normal;
font-weight: 600;
font-size: 1rem;
line-height: 1.2rem;
color: ${color.white};
`;
const SubText = styled.div`
font-family: "Inter", serif;
font-style: normal;
font-weight: 500;
font-size: 1rem;
line-height: 1.5rem;
color: ${color.grey["300"]};
`;
const SubBoldText = styled.span`
color: ${color.grey["100"]};
`;
const BoldText = styled.div`
font-family: "Inter", serif;
font-style: normal;
font-weight: 600;
font-size: 2rem;
line-height: 2.5rem;
color: ${color.orange["50"]};
`;
const Divider = styled.div`
width: 100%;
margin: 1.625rem 0;
border: 0.5px solid ${color.grey["500"]};
`;
const ButtonContainer = styled.div`
display: flex;
flex-direction: row;
height: 3.5rem;
margin-top: 2.5rem;
padding: 0 4.25rem;
gap: 3.5rem;
`;
const RegisterButton = styled.div`
width: 10rem;
`;

View File

@ -0,0 +1,24 @@
import styled from "styled-components";
import color from "../../styles/color";
export const SecondaryButton = styled.button`
width: 100%;
height: 100%;
border: none;
padding: 11px 30px;
font-family: "Inter", serif;
font-style: normal;
font-weight: 600;
font-size: 1.25rem;
line-height: 1.25rem;
letter-spacing: 0.07em;
text-transform: uppercase;
color: ${color.white};
background-color: ${color.grey["300"]};
cursor: pointer;
`;

View File

@ -107,8 +107,6 @@ const SkeletonButton = styled.div`
width: 12rem;
height: 4rem;
padding-top: 1.5rem;
background-color: ${color.grey["800"]};
`;

View File

@ -56,6 +56,7 @@ import {
import { makeClaimMessage, makeSetRecordMessage } from "../../messages";
import Axios from "axios";
import { BackButton } from "../../components/back-button";
import { FinalCheckModal } from "../../components/final-check-modal";
export default function VerificationPage() {
const router = useRouter();
@ -64,6 +65,11 @@ export default function VerificationPage() {
const [isLoading, setIsLoading] = useState(true);
const [wallet, setWallet] = useState<KeplrWallet>();
const [walletKey, setWalletKey] = useState<{
name: string;
pubKey: Uint8Array;
bech32Address: string;
}>();
const [chainList, setChainList] = useState<ChainItemType[]>([]);
const [disabledChainList, setDisabledChainList] = useState<ChainItemType[]>(
@ -77,7 +83,9 @@ export default function VerificationPage() {
const [searchValue, setSearchValue] = useState("");
const [isOwner, setIsOwner] = useState(false);
const [isAgree, setIsAgree] = useState(false);
// const [isAgree, setIsAgree] = useState(false);
const [isModalOpen, setModalOpen] = useState(false);
useEffect(() => {
init();
@ -147,15 +155,15 @@ export default function VerificationPage() {
registeredQueryResponse.data.name,
);
const addressesQueryResponse = await queryAddressesFromTwitterName(
registeredQueryResponse.data.name,
);
if (keplrWallet) {
const key = await keplrWallet.getKey(MainChainId);
setIsOwner(ownerOfQueryResponse.data.owner === key.bech32Address);
}
const addressesQueryResponse = await queryAddressesFromTwitterName(
registeredQueryResponse.data.name,
);
setRegisteredChainList(addressesQueryResponse.data.addresses);
}
} catch (error) {
@ -175,9 +183,11 @@ export default function VerificationPage() {
if (keplr) {
const keplrWallet = new KeplrWallet(keplr);
const key = await keplrWallet.getKey(MainChainId);
await fetchChainList(keplrWallet);
setWallet(keplrWallet);
setWalletKey(key);
return keplrWallet;
} else {
@ -253,8 +263,18 @@ export default function VerificationPage() {
}
};
const onClickRegistration = async () => {
const onClickRegistration = () => {
amplitude.track("click register button");
console.log(isOwner);
if (isOwner) {
handleRegistration();
} else {
setModalOpen(true);
}
};
const handleRegistration = async () => {
try {
const { state, code } = checkTwitterAuthQueryParameter(
window.location.search,
@ -263,16 +283,14 @@ export default function VerificationPage() {
const adr36Infos = await checkAdr36();
if (wallet && adr36Infos) {
const key = await wallet.getKey(MainChainId);
if (wallet && walletKey && adr36Infos) {
const icnsVerificationList = await verifyTwitterAccount(
key.bech32Address,
walletKey.bech32Address,
twitterInfo.accessToken,
);
const registerMsg = makeClaimMessage(
key.bech32Address,
walletKey.bech32Address,
twitterInfo.username,
icnsVerificationList,
localStorage.getItem(REFERRAL_KEY) ?? undefined,
@ -280,7 +298,7 @@ export default function VerificationPage() {
const addressMsgs = adr36Infos.map((adr36Info) => {
return makeSetRecordMessage(
key.bech32Address,
walletKey.bech32Address,
twitterInfo.username,
adr36Info,
);
@ -305,7 +323,7 @@ export default function VerificationPage() {
const simulated = await simulateMsgs(
chainInfo,
key.bech32Address,
walletKey.bech32Address,
{
proto: protoMsgs,
},
@ -317,7 +335,7 @@ export default function VerificationPage() {
const txHash = await sendMsgs(
wallet,
chainInfo,
key.bech32Address,
walletKey.bech32Address,
{
amino: aminoMsgs,
proto: protoMsgs,
@ -346,11 +364,7 @@ export default function VerificationPage() {
const isRegisterButtonDisable = (() => {
const hasCheckedItem = checkedItems.size > 0;
if (isOwner) {
return !hasCheckedItem;
} else {
return !(isAgree && hasCheckedItem);
}
return !hasCheckedItem;
})();
return (
@ -398,16 +412,14 @@ export default function VerificationPage() {
setCheckedItems={setCheckedItems}
/>
{!isOwner && (
<AgreeContainer
onClick={() => {
setIsAgree(!isAgree);
}}
>
<AgreeCheckBox type="checkbox" checked={isAgree} readOnly />I
check that Osmo is required for this transaction
</AgreeContainer>
)}
{/*<AgreeContainer*/}
{/* onClick={() => {*/}
{/* setIsAgree(!isAgree);*/}
{/* }}*/}
{/*>*/}
{/* <AgreeCheckBox type="checkbox" checked={isAgree} readOnly />I*/}
{/* check that Osmo is required for this transaction*/}
{/*</AgreeContainer>*/}
{chainList.length > 0 && (
<ButtonContainer disabled={isRegisterButtonDisable}>
@ -422,6 +434,14 @@ export default function VerificationPage() {
</ContentContainer>
)}
</MainContainer>
<FinalCheckModal
twitterUserName={twitterAuthInfo?.username}
walletInfo={walletKey}
isModalOpen={isModalOpen}
onCloseModal={() => setModalOpen(false)}
onClickRegisterButton={handleRegistration}
/>
</Container>
);
}
@ -461,6 +481,8 @@ export const ButtonContainer = styled.div<{ disabled?: boolean }>`
width: 11rem;
height: 3.5rem;
margin-top: 1.5rem;
background-color: ${(props) =>
props.disabled ? color.orange["300"] : color.orange["100"]};
`;
@ -485,30 +507,30 @@ const ChainListTitle = styled.div`
color: ${color.white};
`;
const AgreeContainer = styled.div`
display: flex;
align-items: center;
gap: 0.5rem;
font-family: "Inter", serif;
font-style: normal;
font-weight: 500;
font-size: 0.8rem;
line-height: 0.8rem;
text-transform: uppercase;
user-select: none;
color: ${color.grey["400"]};
padding: 2rem 0;
cursor: pointer;
`;
const AgreeCheckBox = styled.input.attrs({ type: "checkbox" })`
width: 1.2rem;
height: 1.2rem;
accent-color: ${color.orange["200"]};
`;
// const AgreeContainer = styled.div`
// display: flex;
// align-items: center;
// gap: 0.5rem;
//
// font-family: "Inter", serif;
// font-style: normal;
// font-weight: 500;
// font-size: 0.8rem;
// line-height: 0.8rem;
//
// text-transform: uppercase;
// user-select: none;
//
// color: ${color.grey["400"]};
//
// padding: 2rem 0;
//
// cursor: pointer;
// `;
//
// const AgreeCheckBox = styled.input.attrs({ type: "checkbox" })`
// width: 1.2rem;
// height: 1.2rem;
//
// accent-color: ${color.orange["200"]};
// `;

View File

@ -0,0 +1,3 @@
<svg width="32" height="33" viewBox="0 0 32 33" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M28 8.786C27.118 9.17667 26.1694 9.43733 25.1687 9.56067C26.186 8.95667 26.9687 7.99333 27.336 6.85533C26.384 7.41333 25.3294 7.82333 24.2074 8.03933C23.3114 7.08933 22.0334 6.5 20.6174 6.5C17.8974 6.5 15.6927 8.68533 15.6927 11.38C15.6927 11.7613 15.7374 12.1327 15.8214 12.4933C11.7294 12.288 8.10005 10.3427 5.67205 7.39067C5.24538 8.112 5.00538 8.95667 5.00538 9.848C5.00538 11.542 5.87271 13.0333 7.19538 13.912C6.38805 13.8873 5.62805 13.6627 4.96271 13.3027C4.96271 13.3173 4.96271 13.3393 4.96271 13.36C4.96271 15.7273 6.66071 17.6987 8.91138 18.1473C8.50005 18.26 8.06538 18.3227 7.61738 18.3227C7.29938 18.3227 6.98938 18.2867 6.68938 18.2327C7.31605 20.1673 9.13405 21.5813 11.288 21.6233C9.60271 22.93 7.48005 23.7127 5.17205 23.7127C4.77338 23.7127 4.38338 23.69 3.99805 23.6433C6.17871 25.024 8.76805 25.8333 11.5474 25.8333C20.604 25.8333 25.5587 18.396 25.5587 11.944C25.5587 11.7327 25.552 11.522 25.542 11.314C26.5087 10.6313 27.342 9.77 28 8.786Z" fill="#03A9F4"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB