mirror of
https://github.com/valitydev/checkout.git
synced 2024-11-06 02:25:18 +00:00
IMP-198: Move layout loader to index.html (#294)
This commit is contained in:
parent
1efe8e7b37
commit
39d97e6d63
@ -15,8 +15,37 @@
|
|||||||
/>
|
/>
|
||||||
<title>Checkout</title>
|
<title>Checkout</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body style="background: #163735">
|
||||||
|
<div id="spinner" style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%)">
|
||||||
|
<svg
|
||||||
|
height="64px"
|
||||||
|
viewBox="0 0 57 57"
|
||||||
|
width="64px"
|
||||||
|
style="position: relative; animation: spin 1s linear infinite"
|
||||||
|
>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="loaderGradient" x1="100%" x2="0%" y1="0%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#ff7808" />
|
||||||
|
<stop offset="100%" stop-color="#FFDB57" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<g fill="none" fill-rule="evenodd" stroke="none" stroke-width="1">
|
||||||
|
<g stroke="url(#loaderGradient)" stroke-width="4" transform="translate(-655.000000, -383.000000)">
|
||||||
|
<circle cx="683.5" cy="411.5" r="26.5" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script defer type="module" src="/src/main.tsx"></script>
|
<script defer type="module" src="/src/main.tsx"></script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@keyframes spin {
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
11
src/App.tsx
11
src/App.tsx
@ -1,8 +1,9 @@
|
|||||||
import { ChakraBaseProvider, extendBaseTheme, theme as chakraTheme } from '@chakra-ui/react';
|
import { ChakraBaseProvider, extendBaseTheme, theme as chakraTheme } from '@chakra-ui/react';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
import { CompletePaymentContext } from './common/contexts';
|
import { CompletePaymentContext } from 'checkout/contexts';
|
||||||
import { isNil } from './common/utils';
|
import { isNil } from 'checkout/utils';
|
||||||
|
|
||||||
import { CommunicatorEvents } from './communicator';
|
import { CommunicatorEvents } from './communicator';
|
||||||
import { InitializationFailed, AppLayout } from './components';
|
import { InitializationFailed, AppLayout } from './components';
|
||||||
import { useInitialize } from './useInitialize';
|
import { useInitialize } from './useInitialize';
|
||||||
@ -37,9 +38,8 @@ export function App() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
|
||||||
{state.status === 'SUCCESS' && (
|
|
||||||
<ChakraBaseProvider theme={theme}>
|
<ChakraBaseProvider theme={theme}>
|
||||||
|
{state.status === 'SUCCESS' && (
|
||||||
<CompletePaymentContext.Provider
|
<CompletePaymentContext.Provider
|
||||||
value={{
|
value={{
|
||||||
onComplete: () =>
|
onComplete: () =>
|
||||||
@ -56,9 +56,8 @@ export function App() {
|
|||||||
>
|
>
|
||||||
<AppLayout initParams={state.data[1]} />
|
<AppLayout initParams={state.data[1]} />
|
||||||
</CompletePaymentContext.Provider>
|
</CompletePaymentContext.Provider>
|
||||||
</ChakraBaseProvider>
|
|
||||||
)}
|
)}
|
||||||
{state.status === 'FAILURE' && <InitializationFailed error={state.error} />}
|
{state.status === 'FAILURE' && <InitializationFailed error={state.error} />}
|
||||||
</>
|
</ChakraBaseProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import { toCustomizationContext } from './utils';
|
|||||||
import { CustomizationContext } from '../../common/contexts';
|
import { CustomizationContext } from '../../common/contexts';
|
||||||
import { InitParams } from '../../common/init';
|
import { InitParams } from '../../common/init';
|
||||||
import { getTheme } from '../../common/theme';
|
import { getTheme } from '../../common/theme';
|
||||||
import { LayoutLoader, Overlay, ErrorBoundaryFallback } from '../legacy';
|
import { ErrorBoundaryFallback } from '../legacy';
|
||||||
|
|
||||||
type AppLayoutProps = {
|
type AppLayoutProps = {
|
||||||
initParams: InitParams;
|
initParams: InitParams;
|
||||||
@ -44,9 +44,7 @@ export function AppLayout({ initParams }: AppLayoutProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<Overlay />
|
|
||||||
<ModalContainer>
|
<ModalContainer>
|
||||||
{modelsState.status === 'PROCESSING' && <LayoutLoader />}
|
|
||||||
{modelsState.status === 'INITIALIZED' && (
|
{modelsState.status === 'INITIALIZED' && (
|
||||||
<CustomizationContext.Provider value={toCustomizationContext(initParams.initConfig)}>
|
<CustomizationContext.Provider value={toCustomizationContext(initParams.initConfig)}>
|
||||||
<ErrorBoundary fallback={<ErrorBoundaryFallback />}>
|
<ErrorBoundary fallback={<ErrorBoundaryFallback />}>
|
||||||
|
@ -1,18 +1,9 @@
|
|||||||
/* eslint-disable react/jsx-max-depth */
|
|
||||||
import { Box } from '@chakra-ui/react';
|
import { Box } from '@chakra-ui/react';
|
||||||
import { useState } from 'react';
|
|
||||||
|
|
||||||
import {
|
import { PaymentConditionsContext, PaymentContext, PaymentModelContext } from 'checkout/contexts';
|
||||||
Locale,
|
|
||||||
LocaleContext,
|
|
||||||
PaymentConditionsContext,
|
|
||||||
PaymentContext,
|
|
||||||
PaymentModelContext,
|
|
||||||
} from 'checkout/contexts';
|
|
||||||
import { PaymentCondition } from 'checkout/paymentCondition';
|
import { PaymentCondition } from 'checkout/paymentCondition';
|
||||||
import { PaymentModel } from 'checkout/paymentModel';
|
import { PaymentModel } from 'checkout/paymentModel';
|
||||||
|
|
||||||
import { LocaleSelector } from './LocaleSelector';
|
|
||||||
import { usePaymentCondition } from './usePaymentCondition';
|
import { usePaymentCondition } from './usePaymentCondition';
|
||||||
import { toContainer } from './utils';
|
import { toContainer } from './utils';
|
||||||
import { RedirectContainer } from '../RedirectContainer';
|
import { RedirectContainer } from '../RedirectContainer';
|
||||||
@ -26,21 +17,15 @@ export type GlobalContainerProps = {
|
|||||||
export function GlobalContainer({ paymentModel, initConditions }: GlobalContainerProps) {
|
export function GlobalContainer({ paymentModel, initConditions }: GlobalContainerProps) {
|
||||||
const { conditions, startPayment, startWaitingPaymentResult } = usePaymentCondition(paymentModel, initConditions);
|
const { conditions, startPayment, startWaitingPaymentResult } = usePaymentCondition(paymentModel, initConditions);
|
||||||
const containerName = toContainer(conditions);
|
const containerName = toContainer(conditions);
|
||||||
const [locale, setLocale] = useState<{ l: Locale; localeCode: string }>({ l: {}, localeCode: 'en' });
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PaymentModelContext.Provider value={{ paymentModel }}>
|
<PaymentModelContext.Provider value={{ paymentModel }}>
|
||||||
<PaymentConditionsContext.Provider value={{ conditions }}>
|
<PaymentConditionsContext.Provider value={{ conditions }}>
|
||||||
<PaymentContext.Provider value={{ startPayment, startWaitingPaymentResult }}>
|
<PaymentContext.Provider value={{ startPayment, startWaitingPaymentResult }}>
|
||||||
<LocaleContext.Provider value={locale}>
|
|
||||||
<Box marginBottom={16} marginTop={16} width={['full', '75%', 'auto']}>
|
<Box marginBottom={16} marginTop={16} width={['full', '75%', 'auto']}>
|
||||||
{containerName === 'ViewContainer' && <ViewContainer />}
|
{containerName === 'ViewContainer' && <ViewContainer />}
|
||||||
{containerName === 'RedirectContainer' && <RedirectContainer />}
|
{containerName === 'RedirectContainer' && <RedirectContainer />}
|
||||||
<Box paddingLeft="5" paddingRight="5" paddingTop="3">
|
|
||||||
<LocaleSelector onLocaleChange={setLocale} />
|
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
|
||||||
</LocaleContext.Provider>
|
|
||||||
</PaymentContext.Provider>
|
</PaymentContext.Provider>
|
||||||
</PaymentConditionsContext.Provider>
|
</PaymentConditionsContext.Provider>
|
||||||
</PaymentModelContext.Provider>
|
</PaymentModelContext.Provider>
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import { extractError } from '../common/utils';
|
import { Alert, AlertDescription, AlertIcon, AlertTitle } from '@chakra-ui/react';
|
||||||
|
|
||||||
|
import { extractError } from 'checkout/utils';
|
||||||
|
|
||||||
export type InitializationFailedProps = {
|
export type InitializationFailedProps = {
|
||||||
error: unknown;
|
error: unknown;
|
||||||
@ -6,5 +8,21 @@ export type InitializationFailedProps = {
|
|||||||
|
|
||||||
export function InitializationFailed({ error }: InitializationFailedProps) {
|
export function InitializationFailed({ error }: InitializationFailedProps) {
|
||||||
console.error(`Application Initialization Failed: ${extractError(error)}`, error);
|
console.error(`Application Initialization Failed: ${extractError(error)}`, error);
|
||||||
return <p>Application Initialization Failed: Please check the console for more details.</p>;
|
return (
|
||||||
|
<Alert
|
||||||
|
alignItems="center"
|
||||||
|
flexDirection="column"
|
||||||
|
height="200px"
|
||||||
|
justifyContent="center"
|
||||||
|
status="error"
|
||||||
|
textAlign="center"
|
||||||
|
variant="subtle"
|
||||||
|
>
|
||||||
|
<AlertIcon boxSize="40px" mr={0} />
|
||||||
|
<AlertTitle fontSize="lg" mb={1} mt={4}>
|
||||||
|
Application Initialization Failed!
|
||||||
|
</AlertTitle>
|
||||||
|
<AlertDescription maxWidth="sm">{extractError(error)}</AlertDescription>
|
||||||
|
</Alert>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ import styled from 'styled-components';
|
|||||||
|
|
||||||
import { prepareForm } from './utils';
|
import { prepareForm } from './utils';
|
||||||
import { BrowserRequest } from '../../common/backend/payments';
|
import { BrowserRequest } from '../../common/backend/payments';
|
||||||
import { LayoutLoader } from '../legacy';
|
|
||||||
|
|
||||||
const RedirectContainer = styled.div`
|
const RedirectContainer = styled.div`
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
@ -29,10 +28,5 @@ export function SelfRedirectContainer({ origin, request }: SelfRedirectContainer
|
|||||||
form && form.submit();
|
form && form.submit();
|
||||||
}, [form]);
|
}, [form]);
|
||||||
|
|
||||||
return (
|
return <RedirectContainer ref={containerRef} />;
|
||||||
<>
|
|
||||||
<LayoutLoader />
|
|
||||||
<RedirectContainer ref={containerRef} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,21 @@
|
|||||||
import { Box, Flex } from '@chakra-ui/react';
|
/* eslint-disable react/jsx-max-depth */
|
||||||
import { useContext, useMemo } from 'react';
|
|
||||||
|
|
||||||
import { LocaleContext, PaymentConditionsContext, PaymentModelContext, ViewModelContext } from 'checkout/contexts';
|
import { Box, Flex } from '@chakra-ui/react';
|
||||||
|
import { useContext, useMemo, useState } from 'react';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Locale,
|
||||||
|
LocaleContext,
|
||||||
|
PaymentConditionsContext,
|
||||||
|
PaymentModelContext,
|
||||||
|
ViewModelContext,
|
||||||
|
} from 'checkout/contexts';
|
||||||
import { formatAmount } from 'checkout/utils';
|
import { formatAmount } from 'checkout/utils';
|
||||||
|
|
||||||
import { ApiExtensionView } from './ApiExtensionView';
|
import { ApiExtensionView } from './ApiExtensionView';
|
||||||
import { InfoContainer } from './InfoContainer';
|
import { InfoContainer } from './InfoContainer';
|
||||||
import { Loader } from './Loader';
|
import { Loader } from './Loader';
|
||||||
|
import { LocaleSelector } from './LocaleSelector';
|
||||||
import { NoAvailablePaymentMethodsView } from './NoAvailablePaymentMethodsView';
|
import { NoAvailablePaymentMethodsView } from './NoAvailablePaymentMethodsView';
|
||||||
import { PaymentFormView } from './PaymentFormView';
|
import { PaymentFormView } from './PaymentFormView';
|
||||||
import { PaymentMethodSelectorView } from './PaymentMethodSelectorView';
|
import { PaymentMethodSelectorView } from './PaymentMethodSelectorView';
|
||||||
@ -17,18 +26,19 @@ import { TerminalSelectorView } from './TerminalSelectorView';
|
|||||||
import { useViewModel } from './useViewModel';
|
import { useViewModel } from './useViewModel';
|
||||||
|
|
||||||
export function ViewContainer() {
|
export function ViewContainer() {
|
||||||
const { localeCode } = useContext(LocaleContext);
|
|
||||||
const { conditions } = useContext(PaymentConditionsContext);
|
const { conditions } = useContext(PaymentConditionsContext);
|
||||||
const {
|
const {
|
||||||
paymentModel: { paymentAmount, paymentMethods },
|
paymentModel: { paymentAmount, paymentMethods },
|
||||||
} = useContext(PaymentModelContext);
|
} = useContext(PaymentModelContext);
|
||||||
const { viewModel, goTo, forward, backward } = useViewModel(paymentMethods, conditions);
|
const { viewModel, goTo, forward, backward } = useViewModel(paymentMethods, conditions);
|
||||||
|
const [locale, setLocale] = useState<{ l: Locale; localeCode: string }>({ l: {}, localeCode: 'en' });
|
||||||
const viewAmount = useMemo(() => formatAmount(paymentAmount, localeCode), [localeCode]);
|
const viewAmount = useMemo(() => formatAmount(paymentAmount, locale.localeCode), [locale.localeCode]);
|
||||||
const { views, activeViewId, isLoading } = viewModel;
|
const { views, activeViewId, isLoading } = viewModel;
|
||||||
const activeView = views.get(activeViewId).name;
|
const activeView = views.get(activeViewId).name;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
<LocaleContext.Provider value={locale}>
|
||||||
<Flex
|
<Flex
|
||||||
alignItems="stretch"
|
alignItems="stretch"
|
||||||
background="gray.50"
|
background="gray.50"
|
||||||
@ -60,5 +70,10 @@ export function ViewContainer() {
|
|||||||
</Box>
|
</Box>
|
||||||
</ViewModelContext.Provider>
|
</ViewModelContext.Provider>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
</LocaleContext.Provider>
|
||||||
|
<Box paddingLeft="5" paddingRight="5" paddingTop="3">
|
||||||
|
<LocaleSelector onLocaleChange={setLocale} />
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
import styled, { keyframes } from 'styled-components';
|
|
||||||
|
|
||||||
import { Loader } from './Loader';
|
|
||||||
import { device } from '../../common/utils';
|
|
||||||
|
|
||||||
const growth = keyframes`
|
|
||||||
from {
|
|
||||||
transform: scale(0);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const LayoutLoaderWrapper = styled.div`
|
|
||||||
position: fixed;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
|
|
||||||
@media ${device.desktop} {
|
|
||||||
position: relative;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
transform: translate(0, 0);
|
|
||||||
animation: ${growth} 0.5s;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const LayoutLoader = () => (
|
|
||||||
<LayoutLoaderWrapper>
|
|
||||||
<Loader />
|
|
||||||
</LayoutLoaderWrapper>
|
|
||||||
);
|
|
@ -1,17 +0,0 @@
|
|||||||
import styled, { css } from 'styled-components';
|
|
||||||
|
|
||||||
const OverlayBg = styled.div`
|
|
||||||
position: fixed;
|
|
||||||
left: 0px;
|
|
||||||
top: 0px;
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
|
|
||||||
${({ theme }) => {
|
|
||||||
return css`
|
|
||||||
background: ${theme.background.gradient};
|
|
||||||
`;
|
|
||||||
}}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const Overlay = () => <OverlayBg key="overlay" />;
|
|
@ -1,5 +1,3 @@
|
|||||||
export { LayoutLoader } from './LayoutLoader';
|
|
||||||
export { Overlay } from './Overlay';
|
|
||||||
export { PayButton } from './PayButton';
|
export { PayButton } from './PayButton';
|
||||||
export { HeaderWrapper } from './HeaderWrapper';
|
export { HeaderWrapper } from './HeaderWrapper';
|
||||||
export { Title } from './Title';
|
export { Title } from './Title';
|
||||||
|
Loading…
Reference in New Issue
Block a user