Skip to content

Commit

Permalink
feat: add and switch accounts (#2220)
Browse files Browse the repository at this point in the history
  • Loading branch information
blushi authored Nov 28, 2023
1 parent fd541ad commit 508a8d9
Show file tree
Hide file tree
Showing 17 changed files with 313 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ export const ExtraComponent = (): JSX.Element => {
addAccount={async () => {}}
profiles={[
{
id: '123',
name: 'Mary Smith',
address: 'regen189df...dklads',
profileImage: '/illustrations/frog.jpg',
selected: true,
},
{
id: '456',
name: 'Unnamed',
address: 'regen91kd01...120d',
profileImage: '/illustrations/frog.jpg',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import UserAvatar from '../../user/UserAvatar';
import { OnProfileClickType } from './UserMenuItem.types';

export type UserMenuItemProfileProps = {
id: string;
profileImage: string;
name: string;
address?: string | null;
Expand All @@ -15,6 +16,7 @@ export type UserMenuItemProfileProps = {
};

const UserMenuItemProfile: React.FC<UserMenuItemProfileProps> = ({
id,
profileImage,
name,
address,
Expand All @@ -30,7 +32,7 @@ const UserMenuItemProfile: React.FC<UserMenuItemProfileProps> = ({
backgroundColor: selected ? 'grey.50' : 'primary.main',
cursor: 'pointer',
}}
onClick={() => onProfileClick && onProfileClick(selected)}
onClick={() => onProfileClick && onProfileClick(id, selected)}
>
<Grid container>
<Grid item mr={3} position="relative">
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export type OnProfileClickType = (isSelected: boolean) => void;
export type OnProfileClickType = (
accountId: string,
isSelected: boolean,
) => Promise<void>;
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ interface UserMenuItemsProps extends HeaderMenuItemBase {
userMenuItems: HeaderDropdownItemProps[];
disconnect: () => void;
profiles: UserMenuItemProfileProps[];
addAccount?: () => Promise<void>;
addAccount?: () => void;
onProfileClick?: OnProfileClickType;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
import { useQuery } from '@tanstack/react-query';
import { REGEN_DENOM } from 'config/allowedBaseDenoms';
import { useSetAtom } from 'jotai';
import { postData } from 'utils/fetch/postData';

import OutlinedButton from 'web-components/lib/components/buttons/OutlinedButton';
import { EmailConfirmationModal } from 'web-components/lib/components/modal/EmailConfirmationModal/EmailConfirmationModal';

import { useLedger } from 'ledger';
import { apiUri } from 'lib/apiUri';
import { errorBannerTextAtom } from 'lib/atoms/error.atoms';
import { getBalanceQuery } from 'lib/queries/react-query/cosmos/bank/getBalanceQuery/getBalanceQuery';
import { getCsrfTokenQuery } from 'lib/queries/react-query/registry-server/getCsrfTokenQuery/getCsrfTokenQuery';

import { useAuthData } from 'hooks/useAuthData';

import { chainId } from '../../../lib/ledger';
import { useWallet } from '../../../lib/wallet/wallet';
import { useEmailConfirmationData } from '../LoginFlow/hooks/useEmailConfirmationData';
import { LoginFlow } from '../LoginFlow/LoginFlow';
import { LoginModal } from '../LoginModal/LoginModal';
import { useEmailConfirmationData } from './hooks/useEmailConfirmationData';
import { useLoginData } from './hooks/useLoginData';
import {
EMAIL_CONFIRMATION_CANCEL,
Expand All @@ -36,30 +32,16 @@ type Props = {

const LoginButton = ({ size = 'small' }: Props) => {
const styles = useLoginButtonStyles();
const { wallet, walletConnectUri } = useWallet();
const {
isConfirmationModalOpen,
email,
emailModalError,
onConfirmationModalClose,
onMailCodeChange,
onResendPasscode,
setIsConfirmationModalOpen,
setEmail,
} = useEmailConfirmationData();

const { wallet } = useWallet();
const {
connecting,
isModalOpen,
modalState,
onButtonClick,
onModalClose,
qrCodeUri,
isWaitingForSigning,
setIsWaitingForSigningAtom,
walletsUiConfig,
onButtonClick,
} = useLoginData();

const { noAccountAndNoWallet } = useAuthData();

const { bankClient } = useLedger();
Expand All @@ -73,9 +55,6 @@ const LoginButton = ({ size = 'small' }: Props) => {
}),
);

const { data: token } = useQuery(getCsrfTokenQuery({}));
const setErrorBannerTextAtom = useSetAtom(errorBannerTextAtom);

return chainId ? (
<>
<div className={styles.root}>
Expand All @@ -86,59 +65,15 @@ const LoginButton = ({ size = 'small' }: Props) => {
</OutlinedButton>
)}
</>
<LoginFlow
isModalOpen={isModalOpen}
onModalClose={onModalClose}
wallets={walletsUiConfig} // TODO: remove if mobile + remove WC in all cases
modalState={modalState}
qrCodeUri={qrCodeUri}
connecting={connecting}
/>
</div>
<LoginModal
open={isModalOpen}
onClose={onModalClose}
wallets={walletsUiConfig}
socialProviders={socialProviders}
onEmailSubmit={async ({ email }) => {
if (token) {
try {
setEmail(email);
await postData({
url: `${apiUri}/marketplace/v1/auth/passcode`,
data: {
email,
},
token,
});
onModalClose();
setIsConfirmationModalOpen(true);
} catch (e) {
setErrorBannerTextAtom(String(e));
}
}
}}
state={modalState}
qrCodeUri={qrCodeUri}
connecting={connecting}
/>
<EmailConfirmationModal
resendText={RESEND_TEXT}
resendButtonLink={{
text: RESEND_BUTTON_TEXT,
onClick: onResendPasscode,
}}
cancelButton={{
text: EMAIL_CONFIRMATION_CANCEL,
onClick: onConfirmationModalClose,
}}
signInButton={{
text: EMAIL_CONFIRMATION_SUBMIT,
disabled: true,
onClick: () => void 0,
}}
mailLink={{ text: email, href: '#' }}
onClose={onConfirmationModalClose}
open={isConfirmationModalOpen}
error={emailModalError}
onCodeChange={onMailCodeChange}
/>
<MobileSigningModal
isOpen={isWaitingForSigning && !!walletConnectUri}
onClose={() => setIsWaitingForSigningAtom(false)}
/>
</>
) : (
<></>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,7 @@ export const useLoginData = () => {
const qrUrl = current?.qrUrl;

const [isModalOpen, setIsModalOpen] = useState(false);
const [isWaitingForSigning, setIsWaitingForSigningAtom] = useAtom(
isWaitingForSigningAtom,
);
const [isWaitingForSigning] = useAtom(isWaitingForSigningAtom);
const [modalState, setModalState] = useState<LoginModalState>('select');
const [connecting, setConnecting] = useState<boolean>(false);
const [qrCodeUri, setQrCodeUri] = useState<string | undefined>();
Expand Down Expand Up @@ -99,7 +97,5 @@ export const useLoginData = () => {
connecting,
onButtonClick,
onModalClose,
isWaitingForSigning,
setIsWaitingForSigningAtom,
};
};
117 changes: 117 additions & 0 deletions web-marketplace/src/components/organisms/LoginFlow/LoginFlow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { useQuery } from '@tanstack/react-query';
import { useAtom, useSetAtom } from 'jotai';
import { postData } from 'utils/fetch/postData';

import { EmailConfirmationModal } from 'web-components/lib/components/modal/EmailConfirmationModal/EmailConfirmationModal';

import { apiUri } from 'lib/apiUri';
import { errorBannerTextAtom } from 'lib/atoms/error.atoms';
import { isWaitingForSigningAtom } from 'lib/atoms/tx.atoms';
import { getCsrfTokenQuery } from 'lib/queries/react-query/registry-server/getCsrfTokenQuery/getCsrfTokenQuery';
import { useWallet } from 'lib/wallet/wallet';

import {
EMAIL_CONFIRMATION_CANCEL,
EMAIL_CONFIRMATION_SUBMIT,
RESEND_BUTTON_TEXT,
RESEND_TEXT,
socialProviders,
} from '../LoginButton/LoginButton.constants';
import { MobileSigningModal } from '../LoginButton/LoginButton.SigningModal';
import { LoginModal } from '../LoginModal/LoginModal';
import { LoginModalState, LoginProvider } from '../LoginModal/LoginModal.types';
import { useEmailConfirmationData } from './hooks/useEmailConfirmationData';

type Props = {
isModalOpen: boolean;
onModalClose: () => void;
wallets: LoginProvider[];
modalState: LoginModalState;
qrCodeUri?: string;
connecting: boolean;
};

const LoginFlow = ({
isModalOpen,
onModalClose,
wallets,
modalState,
qrCodeUri,
connecting,
}: Props) => {
const { walletConnectUri } = useWallet();
const {
isConfirmationModalOpen,
email,
emailModalError,
onConfirmationModalClose,
onMailCodeChange,
onResendPasscode,
setIsConfirmationModalOpen,
setEmail,
} = useEmailConfirmationData();
const [isWaitingForSigning, setIsWaitingForSigningAtom] = useAtom(
isWaitingForSigningAtom,
);
const { data: token } = useQuery(getCsrfTokenQuery({}));
const setErrorBannerTextAtom = useSetAtom(errorBannerTextAtom);

return (
<>
<LoginModal
open={isModalOpen}
onClose={onModalClose}
wallets={wallets}
socialProviders={socialProviders}
onEmailSubmit={async ({ email }) => {
if (token) {
try {
setEmail(email);
await postData({
url: `${apiUri}/marketplace/v1/auth/passcode`,
data: {
email,
},
token,
});
onModalClose();
setIsConfirmationModalOpen(true);
} catch (e) {
setErrorBannerTextAtom(String(e));
}
}
}}
state={modalState}
qrCodeUri={qrCodeUri}
connecting={connecting}
/>
<EmailConfirmationModal
resendText={RESEND_TEXT}
resendButtonLink={{
text: RESEND_BUTTON_TEXT,
onClick: onResendPasscode,
}}
cancelButton={{
text: EMAIL_CONFIRMATION_CANCEL,
onClick: onConfirmationModalClose,
}}
signInButton={{
text: EMAIL_CONFIRMATION_SUBMIT,
disabled: true,
onClick: () => void 0,
}}
mailLink={{ text: email, href: '#' }}
onClose={onConfirmationModalClose}
open={isConfirmationModalOpen}
error={emailModalError}
onCodeChange={onMailCodeChange}
/>
<MobileSigningModal
isOpen={isWaitingForSigning && !!walletConnectUri}
onClose={() => setIsWaitingForSigningAtom(false)}
/>
</>
);
};

export { LoginFlow };
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import { bannerTextAtom } from 'lib/atoms/banner.atoms';
import { GET_ACCOUNTS_QUERY_KEY } from 'lib/queries/react-query/registry-server/getAccounts/getAccountsQuery.constants';
import { getCsrfTokenQuery } from 'lib/queries/react-query/registry-server/getCsrfTokenQuery/getCsrfTokenQuery';

import { onPostData } from '../../LoginButton/hooks/onLoginPostData';
import {
DEFAULT_RESEND_ERROR,
DEFAULT_VALIDATE_ERROR,
EMAIL_CONFIRMATION_SUCCES,
RESEND_SUCCES,
} from '../LoginButton.constants';
import { getEmailModalError } from '../utils/getEmailModalError';
import { onPostData } from './onLoginPostData';
} from '../../LoginButton/LoginButton.constants';
import { getEmailModalError } from '../../LoginButton/utils/getEmailModalError';

export const useEmailConfirmationData = () => {
const reactQueryClient = useQueryClient();
Expand Down
Loading

0 comments on commit 508a8d9

Please sign in to comment.