Skip to content

Commit

Permalink
[Issue-219-220][Story Odyssey] Add popup notification for users who f…
Browse files Browse the repository at this point in the history
…ailed to mint
  • Loading branch information
dungnguyen-art committed Dec 4, 2024
1 parent 8c066c0 commit 0230b0c
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 103 deletions.
82 changes: 6 additions & 76 deletions packages/extension-koni-ui/src/components/Layout/base/Base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,16 @@

import { LanguageType } from '@subwallet/extension-base/background/KoniTypes';
import DefaultLogosMap from '@subwallet/extension-koni-ui/assets/logo';
import { BookaSdk } from '@subwallet/extension-koni-ui/connector/booka/sdk';
import { NftMintingLog } from '@subwallet/extension-koni-ui/connector/booka/types';
import { CONFIRM_SHOW_MINTING_FAILED_MODAL } from '@subwallet/extension-koni-ui/constants';
import { useConfirmModal, useDefaultNavigate, useSelector } from '@subwallet/extension-koni-ui/hooks';
import { LayoutBackgroundImages, LayoutBackgroundStyle, Theme, ThemeProps } from '@subwallet/extension-koni-ui/types';
import { Icon, SwModalFuncProps, SwScreenLayout, SwScreenLayoutProps } from '@subwallet/react-ui';
import { useDefaultNavigate, useSelector } from '@subwallet/extension-koni-ui/hooks';
import { LayoutBackgroundImages, LayoutBackgroundStyle, ThemeProps } from '@subwallet/extension-koni-ui/types';
import { Icon, SwScreenLayout, SwScreenLayoutProps } from '@subwallet/react-ui';
import { SwTabBarItem } from '@subwallet/react-ui/es/sw-tab-bar';
import CN from 'classnames';
import { ArrowLeft, ChartBar, CheckCircle, Gift, House, Target, UserCirclePlus } from 'phosphor-react';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { ArrowLeft, ChartBar, Gift, House, Target, UserCirclePlus } from 'phosphor-react';
import React, { useCallback, useEffect, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useLocation, useNavigate } from 'react-router-dom';
import styled, { useTheme } from 'styled-components';
import { useLocalStorage } from 'usehooks-ts';
import styled from 'styled-components';

import SelectAccount from '../parts/SelectAccount';

Expand All @@ -33,7 +29,6 @@ SwScreenLayoutProps,
const specialLanguages: Array<LanguageType> = ['ja', 'ru'];

type TabItemType = Omit<SwTabBarItem, 'onClick'> & { url: string };
const apiSDK = BookaSdk.instance;

const Component = ({ backgroundImages, backgroundStyle, children, className, headerIcons, onBack, onTabSelected, ...props }: LayoutBaseProps) => {
const navigate = useNavigate();
Expand All @@ -42,11 +37,6 @@ const Component = ({ backgroundImages, backgroundStyle, children, className, hea
const { t } = useTranslation();
const { language } = useSelector((state) => state.settings);

const { token } = useTheme() as Theme;

const [mintingLog, setMintingLog] = useState<NftMintingLog | undefined>();
const [isShowPopupMintFailed, setIsShowPopupMintFailed] = useLocalStorage(CONFIRM_SHOW_MINTING_FAILED_MODAL, 'nonConfirmed');

const tabBarItems = useMemo((): TabItemType[] => ([
// {
// icon: {
Expand Down Expand Up @@ -203,66 +193,6 @@ const Component = ({ backgroundImages, backgroundStyle, children, className, hea
goHome();
}, [goHome]);

const mintingFailedModalProps = useMemo((): Partial<SwModalFuncProps> => ({
id: 'alert-minting-failed',
className: CN('general-confirmation-modal', className),
title: t('Badge minting failed'),
okText: t('I understand'),
content: (
<div className={'__description-modal'}>
<div className={'__title-modal'}>{t('Mint your badge again')}</div>
<div className={'__sub-title-modal'}>{t('Due to technical issues, your badge wasn’t minted in Phase 1. Click the Mint tab to mint your badge again on December 6')}</div>
</div>
),
icon: (
<div className={'__icon-modal'}>
<Icon
customSize={'60px'}
iconColor={token.colorIconHover}
phosphorIcon={Gift}
size='md'
weight={'fill'}
/>
</div>
),
closable: true,
maskClosable: true,
okCancel: false,
okButtonProps: {
icon: (
<Icon
phosphorIcon={CheckCircle}
size='md'
weight={'fill'}
/>
),
shape: 'round'
}
}), [className, t, token.colorIconHover]);

const { handleSimpleConfirmModal: handleMintingFailedModal } = useConfirmModal(mintingFailedModalProps);

useEffect(() => {
const fetchMintingLog = async () => {
try {
const mintingLog = await apiSDK.getNftMintingLog();

setMintingLog(mintingLog);
} catch (error) {
console.error('Error fetching minting log:', error);
}
};

fetchMintingLog().catch(console.error);
}, []);

useEffect(() => {
if (mintingLog?.notify && isShowPopupMintFailed.includes('nonConfirmed')) {
setIsShowPopupMintFailed('confirmed');
handleMintingFailedModal().then().catch(console.error);
}
}, [handleMintingFailedModal, isShowPopupMintFailed, mintingLog?.notify, navigate, setIsShowPopupMintFailed]);

useEffect(() => {
onTabSelected?.(selectedTab);
}, [onTabSelected, selectedTab]);
Expand Down
111 changes: 90 additions & 21 deletions packages/extension-koni-ui/src/components/Layout/base/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@
// SPDX-License-Identifier: Apache-2.0

import { AccountJson } from '@subwallet/extension-base/background/types';
import { Layout, WalletConnect } from '@subwallet/extension-koni-ui/components';
import { AlertModal, Layout, WalletConnect } from '@subwallet/extension-koni-ui/components';
import { LayoutBaseProps } from '@subwallet/extension-koni-ui/components/Layout/base/Base';
import { BookaSdk } from '@subwallet/extension-koni-ui/connector/booka/sdk';
import { NftMintingLog } from '@subwallet/extension-koni-ui/connector/booka/types';
import { TelegramConnector } from '@subwallet/extension-koni-ui/connector/telegram';
import { VISIT_INVITATION_SCREEN_FLAG } from '@subwallet/extension-koni-ui/constants';
import { CONFIRM_SHOW_MINTING_FAILED_MODAL, VISIT_INVITATION_SCREEN_FLAG } from '@subwallet/extension-koni-ui/constants';
import { CUSTOMIZE_MODAL } from '@subwallet/extension-koni-ui/constants/modal';
import { WalletConnectContext } from '@subwallet/extension-koni-ui/contexts/WalletConnectContext';
import { useNotification, useSelector } from '@subwallet/extension-koni-ui/hooks';
import { useAlert, useNotification, useSelector } from '@subwallet/extension-koni-ui/hooks';
import { noop } from '@subwallet/extension-koni-ui/utils';
import { ButtonProps, Icon, ModalContext, Tooltip } from '@subwallet/react-ui';
import { Export, FadersHorizontal, MagnifyingGlass } from 'phosphor-react';
import React, { useCallback, useContext, useMemo, useState } from 'react';
import { CheckCircle, Export, FadersHorizontal, Gift, MagnifyingGlass } from 'phosphor-react';
import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import styled from 'styled-components';
Expand All @@ -34,6 +36,9 @@ type Props = {
};

const telegramConnector = TelegramConnector.instance;
const apiSDK = BookaSdk.instance;

const alertModalId = 'alert-minting-failed-modal';

const Component = (props: Props) => {
const { backgroundImages, backgroundStyle, children, className, onClickFilterIcon, onClickSearchIcon, onTabSelected, showConnectIcon = true, showFilterIcon, showGiftIcon, showSearchIcon, showTabBar } = props;
Expand All @@ -46,6 +51,10 @@ const Component = (props: Props) => {
const { activeModal } = useContext(ModalContext);
const { connectWC, disconnectWC } = useContext(WalletConnectContext);

const [mintingLog, setMintingLog] = useState<NftMintingLog | undefined>();
const [isShowPopupMintFailed, setIsShowPopupMintFailed] = useLocalStorage(CONFIRM_SHOW_MINTING_FAILED_MODAL, 'nonConfirmed');
const { alertProps, closeAlert, openAlert } = useAlert(alertModalId);

const { wcAccount } = useSelector((state) => state.accountState);

const notify = useNotification();
Expand Down Expand Up @@ -181,23 +190,83 @@ const Component = (props: Props) => {
navigate('/settings/list');
}, [navigate]);

const handleMintingFailedModal = useCallback(() => {
openAlert({
className: 'general-confirmation-modal modal-revert-header',
title: t('Badge minting failed'),
iconProps: {
phosphorIcon: Gift,
weight: 'fill'
},
contentTitle: t('Mint your badge again'),
content: (
t('Due to technical issues, your badge wasn’t minted in Phase 1. Click the Mint tab to mint your badge again on December 6')
),
okButton: {
icon: CheckCircle,
iconWeight: 'fill',
text: t('I understand'),
onClick: () => {
setIsShowPopupMintFailed('confirmed');
closeAlert();
}
}
});
}, [closeAlert, openAlert, setIsShowPopupMintFailed, t]);

useEffect(() => {
const fetchMintingLog = async () => {
try {
const mintingLog = await apiSDK.getNftMintingLog();

setMintingLog(mintingLog);
} catch (error) {
console.error('Error fetching minting log:', error);
}
};

fetchMintingLog().catch(console.error);
}, []);

const onCancel = useCallback(() => {
setIsShowPopupMintFailed('confirmed');
}, [setIsShowPopupMintFailed]);

useEffect(() => {
if (mintingLog?.notify && isShowPopupMintFailed.includes('nonConfirmed')) {
handleMintingFailedModal();
}
}, [handleMintingFailedModal, isShowPopupMintFailed, mintingLog?.notify, navigate, setIsShowPopupMintFailed]);

return (
<Layout.Base
backgroundImages={backgroundImages}
backgroundStyle={backgroundStyle}
className={className}
headerCenter={false}
headerIcons={headerIcons}
headerLeft={'default'}
headerOnClickLeft={onClickListIcon}
headerPaddingVertical={true}
onTabSelected={onTabSelected}
showHeader={true}
showLeftButton={true}
showTabBar={showTabBar ?? true}
>
{children}
</Layout.Base>
<>
<Layout.Base
backgroundImages={backgroundImages}
backgroundStyle={backgroundStyle}
className={className}
headerCenter={false}
headerIcons={headerIcons}
headerLeft={'default'}
headerOnClickLeft={onClickListIcon}
headerPaddingVertical={true}
onTabSelected={onTabSelected}
showHeader={true}
showLeftButton={true}
showTabBar={showTabBar ?? true}
>
{children}
</Layout.Base>

{
!!alertProps && (
<AlertModal
_onCancel={onCancel}
modalId={alertModalId}
{...alertProps}
/>
)
}
</>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ const Component: React.FC<Props> = (props: Props) => {

const notifyIneligibleProps = useMemo((): Partial<SwModalFuncProps> => ({
id: 'alert-ineligible-mint',
className: CN('general-confirmation-modal', className),
className: CN('general-confirmation-modal modal-revert-header', className),
title: t('Ineligible to mint'),
okText: t('Back to home'),
content: (
Expand Down Expand Up @@ -119,7 +119,7 @@ const Component: React.FC<Props> = (props: Props) => {

const failedToMintProps = useMemo((): Partial<SwModalFuncProps> => ({
id: 'failed_to_mint',
className: CN('general-confirmation-modal', className),
className: CN('general-confirmation-modal modal-revert-header', className),
title: t('Failed to mint'),
okText: t('Back to home'),
okCancel: false,
Expand Down Expand Up @@ -156,7 +156,7 @@ const Component: React.FC<Props> = (props: Props) => {

const badgeAlreadyMintedProps = useMemo((): Partial<SwModalFuncProps> => ({
id: 'badge_already_minted',
className: CN('general-confirmation-modal', className),
className: CN('general-confirmation-modal modal-revert-header', className),
title: t('Failed to mint'),
okText: t('Got it'),
okCancel: false,
Expand Down Expand Up @@ -193,7 +193,7 @@ const Component: React.FC<Props> = (props: Props) => {

const inSufficientBalanceProps = useMemo((): Partial<SwModalFuncProps> => ({
id: 'in_sufficient_balance',
className: CN('general-confirmation-modal', className),
className: CN('general-confirmation-modal modal-revert-header', className),
title: t('Failed to mint'),
okText: t('Got it'),
okCancel: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import React, { useCallback, useContext } from 'react';
import styled from 'styled-components';

type Props = ThemeProps & AlertDialogProps & {
modalId: string
modalId: string,
_onCancel?: () => void,
}

const alertTypeAndIconMap = {
Expand Down Expand Up @@ -41,13 +42,18 @@ const Component: React.FC<Props> = (props: Props) => {
modalId,
okButton,
title,
_onCancel,
type = NotificationType.INFO, iconProps, contentTitle } = props;

const { inactiveModal } = useContext(ModalContext);

const onCancel = useCallback(() => {
if (_onCancel) {
_onCancel();
}

inactiveModal(modalId);
}, [inactiveModal, modalId]);
}, [_onCancel, inactiveModal, modalId]);

return (
<>
Expand Down

0 comments on commit 0230b0c

Please sign in to comment.