diff --git a/src/app/features/container/containers/headers/header.stories.tsx b/src/app/features/container/containers/headers/header.stories.tsx deleted file mode 100644 index ccb5a215a6a..00000000000 --- a/src/app/features/container/containers/headers/header.stories.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import type { Meta } from '@storybook/react'; - -import { Header as Component } from './header'; - -const meta: Meta = { - component: Component, - tags: ['autodocs'], - title: 'Containers/Header', -}; - -export default meta; - -export function Header() { - return null} onGoBack={() => null} />; -} diff --git a/src/app/features/container/containers/headers/header.tsx b/src/app/features/container/containers/headers/header.tsx deleted file mode 100644 index d2e6cfab06c..00000000000 --- a/src/app/features/container/containers/headers/header.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { ReactNode } from 'react'; - -import { SharedComponentsSelectors } from '@tests/selectors/shared-component.selectors'; -import { Flex, Grid, GridItem, HStack, styled } from 'leather-styles/jsx'; - -import { ArrowLeftIcon, CloseIcon } from '@leather.io/ui'; - -import { usePageContext } from '../page/page.context'; -import { HeaderActionButton } from './components/header-action-button'; - -interface HeaderProps { - onClose?(): void; - onGoBack?(): void; - // title?: ReactNode; - account?: ReactNode; - totalBalance?: ReactNode; - settingsMenu?: ReactNode; - networkBadge?: ReactNode; - logo?: ReactNode; -} - -export function Header({ - onClose, - onGoBack, - account, - totalBalance, - settingsMenu, - networkBadge, - logo, -}: HeaderProps) { - const logoItem = onGoBack || logo || account; - - const { - state: { title }, - } = usePageContext(); - return ( - - - - {logoItem && ( - - {onGoBack && ( - } - onAction={onGoBack} - dataTestId={SharedComponentsSelectors.HeaderBackBtn} - /> - )} - {account ? account : logo} - - )} - - - {title && {title}} - - - - {networkBadge} - {settingsMenu} - {onClose && ( - } - dataTestId={SharedComponentsSelectors.HeaderCloseBtn} - onAction={onClose} - /> - )} - - - - - ); -} diff --git a/src/app/features/container/containers/page/page.context.tsx b/src/app/features/container/containers/page/page.context.tsx index d8ee00ad530..67a1f7e702e 100644 --- a/src/app/features/container/containers/page/page.context.tsx +++ b/src/app/features/container/containers/page/page.context.tsx @@ -1,16 +1,17 @@ import { ReactNode, createContext, useContext, useEffect, useReducer } from 'react'; -interface State { +interface HeaderPayloadState { title?: string; -} - -interface HeaderPayload { - title: string; + isSummaryPage?: boolean; + isSessionLocked?: boolean; + isSettingsVisibleOnSm?: boolean; + onGoBack?(): void; + onClose?(): void; } interface UpdateAction { type: 'update'; - payload: HeaderPayload; + payload: HeaderPayloadState; } interface ResetAction { @@ -18,22 +19,23 @@ interface ResetAction { } type Action = UpdateAction | ResetAction; -const pageReducer = (state: State, action: Action): State => { +const initialPageState = { isSessionLocked: false, isSettingsVisibleOnSm: true }; +const pageReducer = (state: HeaderPayloadState, action: Action): HeaderPayloadState => { switch (action.type) { case 'update': return { ...state, ...action.payload }; case 'reset': default: - return {}; + return initialPageState; } }; -const PageContext = createContext<{ state: State; dispatch: React.Dispatch } | undefined>( - undefined -); +const PageContext = createContext< + { state: HeaderPayloadState; dispatch: React.Dispatch } | undefined +>(undefined); export function PageProvider({ children }: { children: ReactNode }) { - const [state, dispatch] = useReducer(pageReducer, {}); + const [state, dispatch] = useReducer(pageReducer, initialPageState); const value = { state, dispatch }; return {children}; } @@ -46,10 +48,11 @@ export const usePageContext = () => { return context; }; -export function useUpdatePageHeaderContext(payload: HeaderPayload) { +export function useUpdatePageHeaderContext(payload: HeaderPayloadState) { const { dispatch } = usePageContext(); useEffect(() => { dispatch({ type: 'update', payload }); }, [dispatch, payload]); + // Pete could be as simple as firing a reset action here on close } diff --git a/src/app/features/container/containers/page/page.header.tsx b/src/app/features/container/containers/page/page.header.tsx new file mode 100644 index 00000000000..e7dcca0b285 --- /dev/null +++ b/src/app/features/container/containers/page/page.header.tsx @@ -0,0 +1,129 @@ +import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; + +import { ChainID } from '@stacks/transactions'; +import { OnboardingSelectors } from '@tests/selectors/onboarding.selectors'; +import { SettingsSelectors } from '@tests/selectors/settings.selectors'; +import { SharedComponentsSelectors } from '@tests/selectors/shared-component.selectors'; +import { Box, Flex, Grid, GridItem, HStack, styled } from 'leather-styles/jsx'; + +import { ArrowLeftIcon, CloseIcon, HamburgerIcon, Logo, NetworkModeBadge } from '@leather.io/ui'; + +import { RouteUrls } from '@shared/route-urls'; + +import { useCurrentNetworkState } from '@app/store/networks/networks.hooks'; + +import { Settings } from '../../../settings/settings'; +import { HeaderActionButton } from '../headers/components/header-action-button'; +import { usePageContext } from './page.context'; + +// PETE - test this onGoBack function to see if its needed +// TODO: Refactor? This is very hard to manage with dynamic routes. Temporarily +// added a fix to catch the swap route: '/swap/:base/:quote?' +// function getOnGoBackLocation(pathname: RouteUrls) { +// if (pathname.includes('/swap')) return navigate(RouteUrls.Home); +// switch (pathname) { +// case RouteUrls.Fund.replace(':currency', 'STX'): +// case RouteUrls.Fund.replace(':currency', 'BTC'): +// case RouteUrls.SendCryptoAssetForm.replace(':symbol', 'stx'): +// case RouteUrls.SendCryptoAssetForm.replace(':symbol', 'btc'): +// return navigate(RouteUrls.Home); +// case RouteUrls.SendStxConfirmation: +// return navigate(RouteUrls.SendCryptoAssetForm.replace(':symbol', 'stx')); +// case RouteUrls.SendBtcConfirmation: +// return navigate(RouteUrls.SendCryptoAssetForm.replace(':symbol', 'btc')); +// default: +// return navigate(-1); +// } +// } + +function LogoBox({ isSessionLocked }: { isSessionLocked: boolean | undefined }) { + const navigate = useNavigate(); + return ( + + navigate(RouteUrls.Home)} + /> + + ); +} + +export function Header() { + const navigate = useNavigate(); + const { chain, name: chainName } = useCurrentNetworkState(); + + const [isShowingSwitchAccount, setIsShowingSwitchAccount] = useState(false); + const { + state: { title, isSummaryPage, isSessionLocked, isSettingsVisibleOnSm }, + } = usePageContext(); + + // const onGoBack = onGoBack ? onGoBack : () => navigate(RouteUrls.Home); + const canGoBack = !isSummaryPage && !isSessionLocked; + return ( + + + + + {canGoBack && ( + } + onAction={() => navigate(-1)} + dataTestId={SharedComponentsSelectors.HeaderBackBtn} + /> + )} + + + + + {title && {title}} + + + + + + {!isSummaryPage && ( + + } + toggleSwitchAccount={() => setIsShowingSwitchAccount(!isShowingSwitchAccount)} + /> + )} + {isSummaryPage && ( + } + dataTestId={SharedComponentsSelectors.HeaderCloseBtn} + onAction={() => navigate(RouteUrls.Home)} + /> + )} + + + + + ); +} diff --git a/src/app/features/container/containers/page/page.layout.tsx b/src/app/features/container/containers/page/page.layout.tsx index 59f3c849444..346aaefc7ad 100644 --- a/src/app/features/container/containers/page/page.layout.tsx +++ b/src/app/features/container/containers/page/page.layout.tsx @@ -1,136 +1,14 @@ -import { useState } from 'react'; -import { useLocation, useNavigate } from 'react-router-dom'; - -import { ChainID } from '@stacks/transactions'; -import { OnboardingSelectors } from '@tests/selectors/onboarding.selectors'; -import { SettingsSelectors } from '@tests/selectors/settings.selectors'; -import { Box } from 'leather-styles/jsx'; - -import { HamburgerIcon, Logo, NetworkModeBadge } from '@leather.io/ui'; - -import { RouteUrls } from '@shared/route-urls'; - -import { usePageContext } from '@app/features/container/containers/page/page.context'; -import { useCurrentNetworkState } from '@app/store/networks/networks.hooks'; - -import { Settings } from '../../../settings/settings'; import { ContainerLayout } from '../container.layout'; -import { Header } from '../headers/header'; +import { Header } from './header'; import { PageProvider } from './page.context'; -function getIsSessionLocked(pathname: RouteUrls) { - return pathname === RouteUrls.Unlock; -} - -function hideSettingsOnSm(pathname: RouteUrls) { - switch (pathname) { - case RouteUrls.SendCryptoAsset: - case RouteUrls.FundChooseCurrency: - return true; - default: - return false; - } -} -// TODO: Refactor this to make it cleaner - set something in reducer for is locked -// otherwise don't show the back button if onClose is set -function canGoBack(pathname: RouteUrls) { - if (getIsSessionLocked(pathname) || isSummaryPage(pathname)) { - return false; - } - return true; -} - -function isSummaryPage(pathname: RouteUrls) { - /* TODO refactor the summary routes to make this cleaner - we need to block going back from summary pages catching the dynamic routes: - SentBtcTxSummary = '/sent/btc/:txId', - SentStxTxSummary = '/sent/stx/:txId', - SentBrc20Summary = '/send/brc20/:ticker/summary', - RpcSignPsbtSummary = '/sign-psbt/summary', - RpcSendTransferSummary = '/send-transfer/summary', - */ - return pathname.match('/sent/stx/') || pathname.match('/sent/btc/' || pathname.match('summary')); -} - interface PageLayoutProps { children?: React.JSX.Element | React.JSX.Element[]; } export function PageLayout({ children }: PageLayoutProps) { - const [isShowingSwitchAccount, setIsShowingSwitchAccount] = useState(false); - const navigate = useNavigate(); - const { pathname: locationPathname } = useLocation(); - const pathname = locationPathname as RouteUrls; - - const { chain, name: chainName } = useCurrentNetworkState(); - - const isSessionLocked = getIsSessionLocked(pathname); - - // TODO: Refactor? This is very hard to manage with dynamic routes. Temporarily - // added a fix to catch the swap route: '/swap/:base/:quote?' - function getOnGoBackLocation(pathname: RouteUrls) { - if (pathname.includes('/swap')) return navigate(RouteUrls.Home); - switch (pathname) { - case RouteUrls.Fund.replace(':currency', 'STX'): - case RouteUrls.Fund.replace(':currency', 'BTC'): - case RouteUrls.SendCryptoAssetForm.replace(':symbol', 'stx'): - case RouteUrls.SendCryptoAssetForm.replace(':symbol', 'btc'): - return navigate(RouteUrls.Home); - case RouteUrls.SendStxConfirmation: - return navigate(RouteUrls.SendCryptoAssetForm.replace(':symbol', 'stx')); - case RouteUrls.SendBtcConfirmation: - return navigate(RouteUrls.SendCryptoAssetForm.replace(':symbol', 'btc')); - default: - return navigate(-1); - } - } - const hideSettings = isSummaryPage(pathname); - return ( - getOnGoBackLocation(pathname) : undefined} - onClose={isSummaryPage(pathname) ? () => navigate(RouteUrls.Home) : undefined} - settingsMenu={ - hideSettings ? null : ( - - } - toggleSwitchAccount={() => setIsShowingSwitchAccount(!isShowingSwitchAccount)} - /> - ) - } - networkBadge={ - - } - // title={getTitleFromUrl(pathname)} - logo={ - - navigate(RouteUrls.Home)} - /> - - } - /> - } - content={children} - /> + } content={children} /> ); } diff --git a/src/app/pages/fund/choose-asset-to-fund/choose-asset-to-fund.tsx b/src/app/pages/fund/choose-asset-to-fund/choose-asset-to-fund.tsx index d67188eab31..3c8ca6a3e04 100644 --- a/src/app/pages/fund/choose-asset-to-fund/choose-asset-to-fund.tsx +++ b/src/app/pages/fund/choose-asset-to-fund/choose-asset-to-fund.tsx @@ -11,11 +11,13 @@ import { CurrentStacksAccountLoader } from '@app/components/loaders/stacks-accou import { StxAssetItemBalanceLoader } from '@app/components/loaders/stx-balance-loader'; import { BtcCryptoAssetItem } from '@app/features/asset-list/bitcoin/btc-crypto-asset-item/btc-crypto-asset-item'; import { StxCryptoAssetItem } from '@app/features/asset-list/stacks/stx-crypo-asset-item/stx-crypto-asset-item'; +import { useUpdatePageHeaderContext } from '@app/features/container/containers/page/page.context'; import { Card } from '@app/ui/layout/card/card'; import { Page } from '@app/ui/layout/page/page.layout'; export function ChooseCryptoAssetToFund() { const navigate = useNavigate(); + useUpdatePageHeaderContext({ isSettingsVisibleOnSm: false }); const navigateToFund = useCallback( (symbol: string) => navigate(RouteUrls.Fund.replace(':currency', symbol)), diff --git a/src/app/pages/send/choose-crypto-asset/choose-crypto-asset.tsx b/src/app/pages/send/choose-crypto-asset/choose-crypto-asset.tsx index 3942c3452c1..5e10a715e1f 100644 --- a/src/app/pages/send/choose-crypto-asset/choose-crypto-asset.tsx +++ b/src/app/pages/send/choose-crypto-asset/choose-crypto-asset.tsx @@ -5,12 +5,14 @@ import { Box, styled } from 'leather-styles/jsx'; import { RouteUrls } from '@shared/route-urls'; import { AssetList } from '@app/features/asset-list/asset-list'; +import { useUpdatePageHeaderContext } from '@app/features/container/containers/page/page.context'; import { useConfigBitcoinSendEnabled } from '@app/query/common/remote-config/remote-config.query'; import { Card } from '@app/ui/layout/card/card'; export function ChooseCryptoAsset() { const navigate = useNavigate(); const isBitcoinSendEnabled = useConfigBitcoinSendEnabled(); + useUpdatePageHeaderContext({ isSettingsVisibleOnSm: false }); function navigateToSendForm(symbol: string, contractId?: string) { if (symbol === 'BTC' && !isBitcoinSendEnabled) return navigate(RouteUrls.SendBtcDisabled); diff --git a/src/app/pages/send/send-crypto-asset-form/send-crypto-asset-form.routes.tsx b/src/app/pages/send/send-crypto-asset-form/send-crypto-asset-form.routes.tsx index 89299bccc72..eb569f3036a 100644 --- a/src/app/pages/send/send-crypto-asset-form/send-crypto-asset-form.routes.tsx +++ b/src/app/pages/send/send-crypto-asset-form/send-crypto-asset-form.routes.tsx @@ -5,7 +5,6 @@ import { RouteUrls } from '@shared/route-urls'; import { BroadcastErrorDialog } from '@app/components/broadcast-error-dialog/broadcast-error-dialog'; import { FullPageWithHeaderLoadingSpinner } from '@app/components/loading-spinner'; -import { useUpdatePageHeaderContext } from '@app/features/container/containers/page/page.context'; import { EditNonceDialog } from '@app/features/dialogs/edit-nonce-dialog/edit-nonce-dialog'; import { ledgerBitcoinTxSigningRoutes } from '@app/features/ledger/flows/bitcoin-tx-signing/ledger-bitcoin-sign-tx-container'; import { ledgerStacksTxSigningRoutes } from '@app/features/ledger/flows/stacks-tx-signing/ledger-sign-stacks-tx-container'; @@ -31,11 +30,6 @@ import { Sip10TokenSendForm } from './form/sip10/sip10-token-send-form'; import { StacksSendFormConfirmation } from './form/stacks/stacks-send-form-confirmation'; import { StxSendForm } from './form/stx/stx-send-form'; -// export function SendWrapper() { -// useUpdatePageHeaderContext({ title: 'Send' }); -// return ; -// } - const recipientAccountsDialogRoute = ( - {/* }> */} }> navigate(-1);