Skip to content

Commit

Permalink
select provider flow
Browse files Browse the repository at this point in the history
  • Loading branch information
lendihop committed Feb 12, 2025
1 parent 9752f99 commit 8232eec
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 25 deletions.
8 changes: 7 additions & 1 deletion public/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -2602,6 +2602,9 @@
"PriceImpactInfo": {
"message": "The difference between the market price and estimated price due to trade size"
},
"newQuote": {
"message": "New quote:"
},
"selectProvider": {
"message": "Select Provider"
},
Expand Down Expand Up @@ -3139,6 +3142,9 @@
"provider": {
"message": "Provider"
},
"providers": {
"message": "Providers"
},
"selectPaymentProvider": {
"message": "Select payment provider"
},
Expand Down Expand Up @@ -3217,7 +3223,7 @@
"message": "Supports USDT"
},
"bestPrice": {
"message": "Best price"
"message": "Best Price"
},
"topUpCrypto": {
"message": "Crypto"
Expand Down
10 changes: 7 additions & 3 deletions src/app/pages/Market/components/InfoBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,19 @@ import { T, TID } from 'lib/i18n';

interface InfoContainerProps extends PropsWithChildren {
className?: string;
onClick?: EmptyFn;
}

export const InfoContainer: FC<InfoContainerProps> = ({ className, children }) => (
<div className={clsx('flex flex-col px-4 py-2 rounded-lg shadow-bottom border-0.5 border-transparent', className)}>
export const InfoContainer: FC<InfoContainerProps> = ({ className, onClick, children }) => (
<div
className={clsx('flex flex-col px-4 py-2 rounded-lg shadow-bottom border-0.5 border-transparent', className)}
onClick={onClick}
>
{children}
</div>
);

interface InfoRawProps extends InfoContainerProps {
interface InfoRawProps extends Omit<InfoContainerProps, 'onClick'> {
title: TID;
bottomSeparator?: boolean;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, { memo } from 'react';

import clsx from 'clsx';

import { T, TID } from 'lib/i18n';

interface Props {
title: TID;
className?: string;
}

export const NewQuoteLabel = memo<Props>(({ title, className }) => {
return (
<div className={clsx('flex flex-row justify-between py-1', className)}>
<span className="text-font-description-bold">
<T id={title} />
</span>

<span>
<span className="text-font-description text-grey-2 mr-0.5">
<T id="newQuote" />
</span>
<span className="w-7 inline-block text-font-description-bold text-end">0:22</span>
</span>
</div>
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,24 @@ import { ReactComponent as CompactDown } from 'app/icons/base/compact_down.svg';
import { TopUpProviderIcon } from 'app/templates/TopUpProviderIcon';
import { TestIDProperty } from 'lib/analytics';

import { TopUpProviderId } from '../top-up-provider-id.enum';
import { PaymentProviderInterface } from '../topup.interface';

interface Props extends TestIDProperty {
providerId: TopUpProviderId;
provider: PaymentProviderInterface;
onClick?: EmptyFn;
}

export const SelectProviderButton = memo<Props>(({ providerId, onClick, testID }) => {
export const SelectProviderButton = memo<Props>(({ provider, onClick, testID }) => {
return (
<Button
className="w-full cursor-pointer flex justify-between items-center p-3 rounded-lg shadow-bottom border-0.5 border-transparent hover:border-lines"
testID={testID}
onClick={onClick}
>
<div className="flex justify-center items-center gap-2">
<TopUpProviderIcon providerId={providerId} />
<TopUpProviderIcon providerId={provider.id} />

<span className="text-font-medium-bold">MoonPay</span>
<span className="text-font-medium-bold">{provider.name}</span>
</div>
<IconBase Icon={CompactDown} className="text-primary" size={16} />
</Button>
Expand Down
16 changes: 4 additions & 12 deletions src/app/pages/Market/debit-credit-card/contents/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import { StyledButton } from 'app/atoms/StyledButton';
import { T, t } from 'lib/i18n';

import { InfoCard } from '../components/InfoCard';
import { NewQuoteLabel } from '../components/NewQuoteLabel';
import { SelectAssetButton } from '../components/SelectAssetButton';
import { SelectProviderButton } from '../components/SelectProviderButton';
import { FormData, VALUE_PLACEHOLDER } from '../config';
import { TopUpProviderId } from '../top-up-provider-id.enum';

const MIN_ERROR = 'min';
const MAX_ERROR = 'max';
Expand All @@ -35,6 +35,7 @@ export const Form: FC<Props> = ({ setModalContent }) => {

const inputCurrency = watch('inputCurrency');
const outputCurrency = watch('outputToken');
const provider = watch('provider');

const handleSelectCurrency = useCallback(() => void setModalContent('send'), []);
const handleSelectToken = useCallback(() => void setModalContent('get'), []);
Expand Down Expand Up @@ -88,18 +89,9 @@ export const Form: FC<Props> = ({ setModalContent }) => {
containerClassName="pb-8"
/>

<div className="flex flex-row justify-between py-1 mb-1">
<span className="text-font-description-bold">
<T id="provider" />
</span>
<NewQuoteLabel title="provider" className="mb-1" />

<span>
<span className="text-font-description text-grey-2 mr-0.5">New Quote:</span>
<span className="w-7 inline-block text-font-description-bold text-end">0:22</span>
</span>
</div>

<SelectProviderButton providerId={TopUpProviderId.MoonPay} onClick={handleSelectProvider} />
<SelectProviderButton provider={provider} onClick={handleSelectProvider} />

<InfoCard
rate={0.35}
Expand Down
145 changes: 141 additions & 4 deletions src/app/pages/Market/debit-credit-card/contents/SelectProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
import React, { FC, useLayoutEffect } from 'react';
import React, { FC, memo, useCallback, useLayoutEffect } from 'react';

import clsx from 'clsx';
import { useFormContext } from 'react-hook-form-v7';

import { FadeTransition } from 'app/a11y/FadeTransition';
import Money from 'app/atoms/Money';
import { BackButton } from 'app/atoms/PageModal';
import { t } from 'lib/i18n';
import { TopUpProviderIcon } from 'app/templates/TopUpProviderIcon';
import { T, t, TID } from 'lib/i18n';

import { InfoContainer } from '../../components/InfoBlock';
import { ModalHeaderConfig } from '../../types';
import { NewQuoteLabel } from '../components/NewQuoteLabel';
import { FormData, VALUE_PLACEHOLDER } from '../config';
import { TopUpProviderId } from '../top-up-provider-id.enum';
import { PaymentProviderInterface } from '../topup.interface';

interface Props {
setModalHeaderConfig: SyncFn<ModalHeaderConfig>;
Expand All @@ -13,8 +24,134 @@ interface Props {
export const SelectProvider: FC<Props> = ({ setModalHeaderConfig, onGoBack }) => {
useLayoutEffect(
() => void setModalHeaderConfig({ title: t('selectProvider'), titleLeft: <BackButton onClick={onGoBack} /> }),
[]
[setModalHeaderConfig, onGoBack]
);

const { watch, setValue } = useFormContext<FormData>();

const activeProvider = watch('provider');

const onProviderSelect = useCallback(
(p: PaymentProviderInterface) => {
setValue('provider', p);
onGoBack();
},
[setValue, onGoBack]
);

return <div></div>;
return (
<FadeTransition>
<NewQuoteLabel title="providers" className="m-4" />
<div className="flex flex-col px-4 pb-4">
{providersMock.map(p => (
<Provider key={p.id} current={p} activeId={activeProvider.id} onClick={onProviderSelect} />
))}
</div>
</FadeTransition>
);
};

interface ProviderProps {
current: PaymentProviderInterface;
activeId: TopUpProviderId;
onClick?: SyncFn<PaymentProviderInterface>;
}

const Provider = memo<ProviderProps>(({ current, activeId, onClick }) => {
const active = current.id === activeId;

const handleClick = useCallback(() => onClick?.(current), [current, onClick]);

return (
<InfoContainer className={clsx('cursor-pointer mb-4 pt-3 pb-0', active && '!border-primary')} onClick={handleClick}>
<div className="flex flex-row justify-between pb-3">
<div className="flex flex-row gap-x-2">
<TopUpProviderIcon providerId={current.id} size={40} />
<div className="flex flex-col">
<span className="text-font-medium-bold">{current.name}</span>
<span className="text-font-num-12 text-grey-1">
{current.minInputAmount && current.maxInputAmount ? (
<>
<Money smallFractionFont={false}>{current.minInputAmount}</Money>
{' - '}
<Money smallFractionFont={false}>{current.maxInputAmount}</Money> {current.inputSymbol}
</>
) : (
VALUE_PLACEHOLDER
)}
</span>
</div>
</div>
<div className="flex flex-row justify-end items-start gap-x-1">
{!current.kycRequired && <Tag title="noKycRequired" className="bg-black" />}
{current.isBestPrice && <Tag title="bestPrice" className="bg-success" />}
</div>
</div>
<div className="py-3 flex flex-row justify-between items-center border-t-0.5">
<p className="p-1 text-font-medium text-grey-1">
<T id="youGet" />:
</p>
<span className="text-font-num-14 p-1">
{current.outputAmount ? (
<>
{'≈ '}
<Money smallFractionFont={false}>{current.outputAmount}</Money> {current.outputSymbol}
</>
) : (
VALUE_PLACEHOLDER
)}
</span>
</div>
</InfoContainer>
);
});

interface TagProps {
title: TID;
className?: string;
}

const Tag = memo<TagProps>(({ title, className }) => (
<div className={clsx('p-1 text-font-small-bold text-white rounded', className)}>
<T id={title} />
</div>
));

const providersMock: PaymentProviderInterface[] = [
{
name: 'MoonPay',
id: TopUpProviderId.MoonPay,
isBestPrice: true,
kycRequired: false,
minInputAmount: 30,
maxInputAmount: 30000,
inputSymbol: 'USD',
inputDecimals: 2,
outputAmount: 1000,
outputSymbol: 'TEZ'
},
{
name: 'Alice&Bob',
id: TopUpProviderId.AliceBob,
isBestPrice: false,
kycRequired: false,
minInputAmount: 30,
maxInputAmount: 30000,
inputSymbol: 'USD',
inputDecimals: 2,
outputAmount: 1000,
outputSymbol: 'TEZ'
},
{
name: 'Utorg',
id: TopUpProviderId.Utorg,
isBestPrice: false,
kycRequired: true,
minInputAmount: 30,
maxInputAmount: 30000,
inputSymbol: 'USD',
inputDecimals: 2,
outputAmount: 1000,
outputSymbol: 'TEZ'
}
];

0 comments on commit 8232eec

Please sign in to comment.