Skip to content

Commit

Permalink
Merge pull request #2 from wakeuplabs-io/SAF-13_withdraw-components
Browse files Browse the repository at this point in the history
SAF-13 Withdraw components
  • Loading branch information
matzapata authored Aug 9, 2024
2 parents 8434d4b + 292ef14 commit babaf69
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,24 +1,41 @@
import React, { FC } from 'react';
import React, { FC, useCallback, useState } from 'react';

import { t } from 'i18next';

import { Button, ButtonStyle } from '@sovryn/ui';

import { translations } from '../../../../../../../locales/i18n';
import { LendPosition } from '../../LendPositionsList.types';
import { WithdrawModalContainer } from '../WithdrawModal/WithdrawModalContainer';

type LendPositionActionProps = {
position: LendPosition;
};

export const LendPositionAction: FC<LendPositionActionProps> = () => {
const [isWithdrawModalOpen, setIsWithdrawModalOpen] =
useState<boolean>(false);

const handleWithdrawClick = () => {
setIsWithdrawModalOpen(true);
};

const handleWithdrawClose = () => {
setIsWithdrawModalOpen(false);
};

return (
<div className="flex items-center justify-center lg:justify-end space-x-2">
{/* TODO: these should be modal triggers */}
<Button
style={ButtonStyle.secondary}
className="flex-grow"
text={t(translations.aavePage.lendPositionsList.withdraw)}
text={t(translations.common.buttons.withdraw)}
onClick={handleWithdrawClick}
/>

<WithdrawModalContainer
handleCloseModal={handleWithdrawClose}
isOpen={isWithdrawModalOpen}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import React, { FC, useCallback, useMemo, useState } from 'react';

import { t } from 'i18next';

import {
AmountInput,
Button,
ErrorBadge,
ErrorLevel,
Select,
SimpleTable,
SimpleTableRow,
Tabs,
TabType,
} from '@sovryn/ui';
import { Decimal } from '@sovryn/utils';

import { AmountRenderer } from '../../../../../../2_molecules/AmountRenderer/AmountRenderer';
import { AssetRenderer } from '../../../../../../2_molecules/AssetRenderer/AssetRenderer';
import { useDecimalAmountInput } from '../../../../../../../hooks/useDecimalAmountInput';
import { translations } from '../../../../../../../locales/i18n';

const pageTranslations = translations.aavePage;

type WithdrawFormProps = {
onSuccess: () => unknown;
};

export const WithdrawForm: FC<WithdrawFormProps> = () => {
const withdrawableAssets = useMemo(() => ['BTC', 'SOV'], []); // TODO: this is mocked data. Replace with proper hook
const [maximumWithdrawAmount] = useState<Decimal>(Decimal.from(10)); // TODO: this is mocked data. Replace with proper hook
const [withdrawAsset, setWithdrawAsset] = useState<string>(
withdrawableAssets[0],
);
const [withdrawAmount, setWithdrawAmount, withdrawSize] =
useDecimalAmountInput('');

const onWithdrawAssetChange = useCallback(v => {
setWithdrawAsset(v);
}, []);

const withdrawableAssetsOptions = useMemo(
() =>
withdrawableAssets.map(token => ({
value: token,
label: (
<AssetRenderer
showAssetLogo
asset={token}
assetClassName="font-medium"
/>
),
})),
[withdrawableAssets],
);

const isValidWithdrawAmount = useMemo(
() => (withdrawSize.gt(0) ? withdrawSize.lte(maximumWithdrawAmount) : true),
[withdrawSize, maximumWithdrawAmount],
);

const remainingSupply = useMemo(
() => maximumWithdrawAmount.sub(withdrawSize),
[withdrawSize, maximumWithdrawAmount],
);

const submitButtonDisabled = useMemo(
() => !isValidWithdrawAmount || withdrawSize.lte(0),
[isValidWithdrawAmount, withdrawSize],
);

const withdrawLabelRenderer = useCallback(
({ value }) => (
<AssetRenderer
dataAttribute="withdraw-asset-select"
showAssetLogo
asset={value}
/>
),
[],
);

return (
<form className="flex flex-col gap-6">
<div className="space-y-3">
<div className="flex justify-between items-end">
<Tabs
type={TabType.secondary}
index={0}
items={[
// For now just withdraw is supported
{
activeClassName: 'text-primary-20',
dataAttribute: 'withdraw',
label: t(translations.common.withdraw),
},
]}
/>
<span className="text-xs underline">
(Max{' '}
<AmountRenderer
value={maximumWithdrawAmount}
suffix={withdrawAsset}
prefix="~"
/>
)
</span>
</div>

<div className="flex space-x-3">
<div className="text-right flex-grow space-y-1">
<AmountInput
label={t(translations.common.amount)}
value={withdrawAmount}
onChangeText={setWithdrawAmount}
placeholder="0"
invalid={!isValidWithdrawAmount}
/>
<div className=" pr-4">
<AmountRenderer
className="text-gray-40"
value={0} // TODO: usd equivalent
prefix="$"
/>
</div>
</div>

<Select
value={withdrawAsset}
onChange={onWithdrawAssetChange}
options={withdrawableAssetsOptions}
labelRenderer={withdrawLabelRenderer}
className="min-w-[6.7rem]"
menuClassName="max-h-[10rem] sm:max-h-[20rem]"
dataAttribute="withdraw-asset-select"
/>
</div>
</div>

<div>
{!isValidWithdrawAmount && (
<ErrorBadge
level={ErrorLevel.Critical}
message={t(pageTranslations.withdrawForm.invalidAmountError)}
dataAttribute="withdraw-amount-error"
/>
)}
</div>

<SimpleTable>
<SimpleTableRow
label={t(translations.aavePage.withdrawForm.remainingSupply)}
value={
<AmountRenderer
value={remainingSupply.toNumber()}
suffix={withdrawAsset}
/>
}
/>
</SimpleTable>

<Button
disabled={submitButtonDisabled}
text={t(translations.common.buttons.confirm)}
/>
</form>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React, { FC } from 'react';

import { t } from 'i18next';

import { Dialog, DialogBody, DialogHeader } from '@sovryn/ui';

import { translations } from '../../../../../../../locales/i18n';
import { WithdrawForm } from './WithdrawForm';

type WithdrawModalContainerProps = {
isOpen: boolean;
handleCloseModal: () => unknown;
};

export const WithdrawModalContainer: FC<WithdrawModalContainerProps> = ({
isOpen,
handleCloseModal,
}) => {
return (
<Dialog disableFocusTrap isOpen={isOpen}>
<DialogHeader
title={t(translations.aavePage.common.withdraw)}
onClose={handleCloseModal}
/>
<DialogBody className="flex flex-col gap-6">
<WithdrawForm onSuccess={handleCloseModal} />
</DialogBody>
</Dialog>
);
};
12 changes: 8 additions & 4 deletions apps/frontend/src/locales/en/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,9 @@
"borrow": "Borrow",
"lend": "Lend",
"variable": "Variable",
"fixed": "Fixed"
"fixed": "Fixed",
"withdraw": "Withdraw"

},
"topPanel": {
"title": "Lend and borrow",
Expand All @@ -827,16 +829,18 @@
},
"lendPositionsList": {
"title": "Your lending deposits",
"usedAsCollateral": "Used as collateral",
"withdraw": "Withdraw"
"usedAsCollateral": "Used as collateral"
},
"lendAssetsList": {
"title": "Assets to lend",
"showZeroBalances": "Show assets with 0 balance",
"walletBalance": "Wallet balance",
"canBeCollateral": "Can be collateral"
},
"assetCard": {}
"withdrawForm": {
"remainingSupply": "Remaining supply",
"invalidAmountError": "Invalid amount"
}
},
"bitocracyPage": {
"meta": {
Expand Down

0 comments on commit babaf69

Please sign in to comment.