import { ContractWrappers } from '@0x/contract-wrappers'; import { LedgerSubprovider } from '@0x/subproviders'; import { BigNumber } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { DialogContent, DialogOverlay } from '@reach/dialog'; import '@reach/dialog/styles.css'; import { ZeroExProvider } from 'ethereum-types'; import * as React from 'react'; import styled from 'styled-components'; import { Button } from 'ts/components/button'; import { Icon } from 'ts/components/icon'; import { Heading, Paragraph } from 'ts/components/text'; import { GlobalStyle } from 'ts/constants/globalStyle'; import { ConnectForm, WalletConnectedProps } from 'ts/pages/governance/connect_form'; import { ErrorModal } from 'ts/pages/governance/error_modal'; import { VoteForm, VoteInfo } from 'ts/pages/governance/vote_form'; import { colors } from 'ts/style/colors'; import { constants } from 'ts/utils/constants'; interface Props { theme?: GlobalStyle; isOpen?: boolean; onDismiss?: () => void; onWalletConnected?: (providerName: string) => void; onVoted?: (voteInfo: VoteInfo) => void; zeipId: number; } interface State { currentBalance: BigNumber; isWalletConnected: boolean; providerName: string; isSubmitting: boolean; isLedger: boolean; ledgerSubproviderIfExists?: LedgerSubprovider; isSuccessful: boolean; isErrorModalOpen?: boolean; isU2fSupported: boolean; isVoted: boolean; votePreference: string | null; voteHash?: string; signedVote?: any; errorMessage?: string; errors: ErrorProps; web3Wrapper?: Web3Wrapper; contractWrappers?: ContractWrappers; providerEngine?: ZeroExProvider; web3?: any; selectedAddress?: string; } interface FormProps { isSuccessful?: boolean; isSubmitting?: boolean; } interface ErrorProps { [key: string]: string; } // This is a copy of the generic form and includes a number of extra fields // TODO remove the extraneous fields export class ModalVote extends React.Component { public networkId: number; public state: State = { currentBalance: new BigNumber(0), isWalletConnected: false, isU2fSupported: false, providerName: 'Metamask', selectedAddress: null, isSubmitting: false, isLedger: false, ledgerSubproviderIfExists: null, providerEngine: null, isSuccessful: false, isVoted: false, votePreference: null, errors: {}, }; // shared fields public constructor(props: Props) { super(props); } public render(): React.ReactNode { const { isOpen, onDismiss, zeipId } = this.props; const { isSuccessful, selectedAddress, currentBalance, isErrorModalOpen, errorMessage } = this.state; const bigNumberFormat = { decimalSeparator: '.', groupSeparator: ',', groupSize: 3, secondaryGroupSize: 0, fractionGroupSeparator: ' ', fractionGroupSize: 0, }; const formattedBalance = Web3Wrapper.toUnitAmount(currentBalance, constants.DECIMAL_PLACES_ETH).toFormat( 0, BigNumber.ROUND_FLOOR, bigNumberFormat, ); return ( <> {this._renderFormContent()} Vote Received! Your vote will help to decide the future of the protocol. You will be receiving a custom “I voted” NFT as a token of our appreciation. You voted from {selectedAddress} with {formattedBalance} ZRX Close ); } public _renderFormContent(): React.ReactNode { switch (this.state.isWalletConnected) { case true: return this._renderVoteFormContent(); case false: default: return this._renderConnectWalletFormContent(); } } private _shareViaTwitterAsync(): void { const { zeipId } = this.props; const tweetText = encodeURIComponent(`I voted on ZEIP-${zeipId}! 🗳️#VoteWithZRX https://0x.org/vote`); window.open(`https://twitter.com/intent/tweet?text=${tweetText}`, 'Share your vote', 'width=500,height=400'); } private _renderConnectWalletFormContent(): React.ReactNode { const { web3Wrapper } = this.state; return ( <> ); } private _renderVoteFormContent(): React.ReactNode { const { currentBalance, selectedAddress, web3Wrapper, isLedger, web3, ledgerSubproviderIfExists, providerEngine, } = this.state; return ( <> ); } private _onWalletConnected(props: WalletConnectedProps): void { const { contractWrappers, selectedAddress, currentBalance, providerName, injectedProviderIfExists, web3Wrapper, isLedger, ledgerSubproviderIfExists, providerEngine, } = props; this.setState({ ...this.state, web3Wrapper, contractWrappers, web3: injectedProviderIfExists, isWalletConnected: true, providerName, currentBalance, selectedAddress, isLedger, ledgerSubproviderIfExists, providerEngine, }); this.props.onWalletConnected(providerName); } private _onVoted(voteInfo: VoteInfo): void { this.setState({ isSuccessful: true, }); if (this.props.onVoted) { this.props.onVoted(voteInfo); } } private _onDone(): void { this.setState({ isErrorModalOpen: false, isSuccessful: false, }); this.props.onDismiss(); } private _onError(errorMessage: string): void { this.setState({ errorMessage, isErrorModalOpen: true, }); } private _onCloseError(): void { this.setState({ errorMessage: '', isErrorModalOpen: false, }); } } const ButtonClose = styled.button.attrs({})` cursor: pointer; position: absolute; right: 0; top: 0; overflow: hidden; width: 27px; height: 27px; border: 0; background-color: transparent; padding: 0; transform: translateY(-47px); span { opacity: 0; visibility: hidden; position: absolute; } `; const StyledDialogContent = styled(DialogContent)` position: relative; max-width: 800px; background-color: #f6f6f6 !important; padding: 60px 60px !important; @media (max-width: 768px) { width: calc(100vw - 40px) !important; margin: 40px auto !important; padding: 30px 30px !important; } `; const Confirmation = styled.div` position: absolute; top: 50%; text-align: center; width: 100%; left: 0; transition: opacity 0.3s ease-in-out, visibility 0.3s ease-in-out; transition-delay: 0.4s; padding: 60px 60px; transform: translateY(-50%); opacity: ${props => (props.isSuccessful ? `1` : `0`)}; visibility: ${props => (props.isSuccessful ? 'visible' : `hidden`)}; p { max-width: 492px; margin-left: auto; margin-right: auto; } `; const ButtonWrap = styled.div` display: inline-block; @media (min-width: 768px) { * + * { margin-left: 15px; } } @media (max-width: 768px) { a, button { display: block; width: 220px; } * + * { margin-top: 15px; } } `;