Skip to content

Commit c5fdc33

Browse files
refactor: LoanCreateTabs
1 parent 1f6825e commit c5fdc33

File tree

8 files changed

+108
-134
lines changed

8 files changed

+108
-134
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { useCallback } from 'react'
2+
import LoanFormCreate from '@/lend/components/PageLoanCreate/LoanFormCreate'
3+
import type { FormValues } from '@/lend/components/PageLoanCreate/types'
4+
import { DEFAULT_FORM_VALUES } from '@/lend/components/PageLoanCreate/utils'
5+
import networks from '@/lend/networks'
6+
import useStore from '@/lend/store/useStore'
7+
import { type MarketUrlParams, type PageContentProps } from '@/lend/types/lend.types'
8+
import { CreateLoanForm } from '@/llamalend/features/borrow/components/CreateLoanForm'
9+
import type { OnBorrowFormUpdate } from '@/llamalend/features/borrow/types'
10+
import { hasLeverage } from '@/llamalend/llama.utils'
11+
import { useCreateLoanMuiForm } from '@ui-kit/hooks/useFeatureFlags'
12+
import { t } from '@ui-kit/lib/i18n'
13+
import { type FormTab, FormTabs } from '@ui-kit/shared/ui/FormTabs/FormTabs'
14+
15+
type CreateLoanProps = PageContentProps<MarketUrlParams>
16+
17+
/**
18+
* Callback that synchronizes the `ChartOhlc` component with the `RangeSlider` component in the new `BorrowTabContents`.
19+
*/
20+
const useOnFormUpdate = ({ api, market }: Pick<CreateLoanProps, 'api' | 'market'>): OnBorrowFormUpdate =>
21+
useCallback(
22+
async ({ debt, userCollateral, range, slippage, leverageEnabled }) => {
23+
const { setFormValues, setStateByKeys } = useStore.getState().loanCreate
24+
const formValues: FormValues = {
25+
...DEFAULT_FORM_VALUES,
26+
n: range,
27+
debt: `${debt ?? ''}`,
28+
userCollateral: `${userCollateral ?? ''}`,
29+
}
30+
await setFormValues(api, market, formValues, `${slippage}`, leverageEnabled)
31+
setStateByKeys({ isEditLiqRange: true })
32+
},
33+
[api, market],
34+
)
35+
36+
function CreateLoanTab({ market, api, rChainId }: CreateLoanProps) {
37+
const onLoanCreated = useStore((state) => state.loanCreate.onLoanCreated)
38+
return (
39+
<CreateLoanForm
40+
networks={networks}
41+
chainId={rChainId}
42+
market={market}
43+
onUpdate={useOnFormUpdate({ market, api })}
44+
onCreated={useCallback(
45+
async () => api && market && (await onLoanCreated(api, market)),
46+
[api, market, onLoanCreated],
47+
)}
48+
/>
49+
)
50+
}
51+
52+
export const LendCreateTabsNewMenu = [
53+
{ value: 'create', label: t`Borrow`, component: CreateLoanTab },
54+
] satisfies FormTab<CreateLoanProps>[]
55+
56+
export const LendCreateTabsOldMenu = [
57+
{ value: 'create', label: t`Create Loan`, component: LoanFormCreate },
58+
{
59+
value: 'leverage',
60+
label: t`Leverage`,
61+
component: (p) => <LoanFormCreate {...p} isLeverage />,
62+
visible: ({ market }) => market && hasLeverage(market),
63+
},
64+
] satisfies FormTab<CreateLoanProps>[]
65+
66+
const LoanCreate = (pageProps: CreateLoanProps) => {
67+
const menu = useCreateLoanMuiForm() ? LendCreateTabsNewMenu : LendCreateTabsOldMenu
68+
return (
69+
<FormTabs<CreateLoanProps>
70+
params={pageProps}
71+
menu={menu}
72+
shouldWrap={menu === LendCreateTabsOldMenu}
73+
defaultTab={pageProps.rFormType}
74+
/>
75+
)
76+
}
77+
78+
export default LoanCreate

apps/main/src/lend/components/PageLoanCreate/Page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { Address } from 'viem'
33
import CampaignRewardsBanner from '@/lend/components/CampaignRewardsBanner'
44
import { MarketInformationComp } from '@/lend/components/MarketInformationComp'
55
import { MarketInformationTabs } from '@/lend/components/MarketInformationTabs'
6-
import LoanCreate from '@/lend/components/PageLoanCreate/index'
6+
import LoanCreate from '@/lend/components/PageLoanCreate/LoanCreateTabs'
77
import { useOneWayMarket } from '@/lend/entities/chain'
88
import { useLendPageTitle } from '@/lend/hooks/useLendPageTitle'
99
import { useMarketDetails } from '@/lend/hooks/useMarketDetails'

apps/main/src/lend/components/PageLoanCreate/index.tsx

Lines changed: 0 additions & 103 deletions
This file was deleted.

apps/main/src/lend/components/PageLoanCreate/types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
import type { HealthMode } from '@/llamalend/llamalend.types'
1111
import type { Step } from '@ui/Stepper/types'
1212

13-
export type FormType = 'create' | 'vault' | 'leverage'
1413
export type StepKey = 'APPROVAL' | 'CREATE' | ''
1514
export type InpError = 'too-much' | 'too-much-max' | ''
1615

apps/main/src/lend/components/PageLoanManage/ManageLoanTabs.tsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { useClosePositionTab } from '@/llamalend/features/manage-soft-liquidatio
1212
import { useImproveHealthTab } from '@/llamalend/features/manage-soft-liquidation/hooks/useImproveHealthTab'
1313
import { ClosePosition } from '@/llamalend/features/manage-soft-liquidation/ui/tabs/ClosePosition'
1414
import { ImproveHealth } from '@/llamalend/features/manage-soft-liquidation/ui/tabs/ImproveHealth'
15-
import { useManageLoanMuiForm } from '@ui-kit/hooks/useFeatureFlags'
15+
import { useManageLoanMuiForm, useManageSoftLiquidation } from '@ui-kit/hooks/useFeatureFlags'
1616
import { t } from '@ui-kit/lib/i18n'
1717
import { type FormTab, FormTabs } from '@ui-kit/shared/ui/FormTabs/FormTabs'
1818

@@ -74,6 +74,9 @@ export const LendManageNewMenu = [
7474
{ value: 'remove', label: t`Remove`, component: LoanRemoveCollateralTab },
7575
],
7676
},
77+
] satisfies FormTab<ManageLoanProps>[]
78+
79+
export const LendManageSoftLiquidationMenu = [
7780
{
7881
value: 'soft-liquidation',
7982
label: t`Manage soft liquidation`,
@@ -84,13 +87,22 @@ export const LendManageNewMenu = [
8487
},
8588
] satisfies FormTab<ManageLoanProps>[]
8689

87-
export const ManageLoanTabs = (pageProps: ManageLoanProps) => {
90+
export const ManageLoanTabs = ({
91+
isInSoftLiquidation,
92+
...pageProps
93+
}: ManageLoanProps & { isInSoftLiquidation: boolean | undefined }) => {
94+
const shouldUseSoftLiquidation = useManageSoftLiquidation() && isInSoftLiquidation
8895
const shouldUseManageLoanMuiForm = useManageLoanMuiForm()
96+
const menu = shouldUseSoftLiquidation
97+
? LendManageSoftLiquidationMenu
98+
: shouldUseManageLoanMuiForm
99+
? LendManageNewMenu
100+
: LendManageLegacyMenu
89101
return (
90102
<FormTabs<ManageLoanProps>
91103
params={pageProps}
92-
menu={shouldUseManageLoanMuiForm ? LendManageNewMenu : LendManageLegacyMenu}
93-
shouldWrap={!shouldUseManageLoanMuiForm}
104+
menu={menu}
105+
shouldWrap={menu === LendManageLegacyMenu}
94106
defaultTab={pageProps.rFormType}
95107
/>
96108
)

apps/main/src/lend/components/PageLoanManage/Page.tsx

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import useStore from '@/lend/store/useStore'
1616
import { type MarketUrlParams } from '@/lend/types/lend.types'
1717
import { getVaultPathname, parseMarketParams } from '@/lend/utils/helpers'
1818
import { getCollateralListPathname } from '@/lend/utils/utilsRouter'
19-
import { ManageSoftLiquidation } from '@/llamalend/features/manage-soft-liquidation'
2019
import { MarketDetails } from '@/llamalend/features/market-details'
2120
import { BorrowPositionDetails, NoPosition } from '@/llamalend/features/market-position-details'
2221
import { UserPositionHistory } from '@/llamalend/features/user-position-history'
@@ -30,7 +29,6 @@ import Box from '@ui/Box'
3029
import { ConnectWalletPrompt, isLoading, useConnection, useWallet } from '@ui-kit/features/connect-wallet'
3130
import { useLayoutStore } from '@ui-kit/features/layout'
3231
import { useParams } from '@ui-kit/hooks/router'
33-
import { useManageSoftLiquidation } from '@ui-kit/hooks/useFeatureFlags'
3432
import { t } from '@ui-kit/lib/i18n'
3533
import { REFRESH_INTERVAL } from '@ui-kit/lib/model'
3634
import { ErrorPage } from '@ui-kit/pages/ErrorPage'
@@ -46,7 +44,6 @@ const Page = () => {
4644
const { data: market, isSuccess } = useOneWayMarket(rChainId, rMarket)
4745
const rOwmId = market?.id ?? ''
4846
const userActiveKey = helpers.getUserActiveKey(api, market!)
49-
const isMdUp = useLayoutStore((state) => state.isMdUp)
5047
const isPageVisible = useLayoutStore((state) => state.isPageVisible)
5148
const fetchAllMarketDetails = useStore((state) => state.markets.fetchAll)
5249
const fetchAllUserMarketDetails = useStore((state) => state.user.fetchAll)
@@ -88,9 +85,8 @@ const Page = () => {
8885
network,
8986
})
9087

91-
const isManageSoftLiq =
92-
useManageSoftLiquidation() &&
93-
(borrowPositionDetails.liquidationAlert.softLiquidation || borrowPositionDetails.liquidationAlert.hardLiquidation)
88+
const isInSoftLiquidation =
89+
borrowPositionDetails.liquidationAlert.softLiquidation || borrowPositionDetails.liquidationAlert.hardLiquidation
9490

9591
// set tabs
9692
const DETAIL_INFO_TYPES: { key: DetailInfoTypes; label: string }[] = [{ label: t`Market Details`, key: 'market' }]
@@ -142,13 +138,7 @@ const Page = () => {
142138
<>
143139
<DetailPageStack>
144140
<AppPageFormsWrapper>
145-
{rChainId &&
146-
rOwmId &&
147-
(isManageSoftLiq ? (
148-
<ManageSoftLiquidation marketId={rOwmId} chainId={rChainId} network={network} />
149-
) : (
150-
<ManageLoanTabs {...pageProps} />
151-
))}
141+
{rChainId && rOwmId && <ManageLoanTabs isInSoftLiquidation={isInSoftLiquidation} {...pageProps} />}
152142
</AppPageFormsWrapper>
153143
<Stack flexDirection="column" flexGrow={1} sx={{ gap: Spacing.md }}>
154144
<CampaignRewardsBanner

apps/main/src/lend/components/PageLoanManage/types.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
import { FutureRates } from '@/lend/types/lend.types'
22

33
export type DetailInfoTypes = 'user' | 'market'
4-
export type FormType = 'loan' | 'collateral' | 'leverage'
5-
export type LoanFormType = 'loan-increase' | 'loan-decrease' | 'loan-liquidate'
6-
export type CollateralFormType = 'collateral-increase' | 'collateral-decrease'
7-
export type LeverageFormType = 'leverage-borrow-more'
84

95
export type FormStatus = {
106
isApproved: boolean

packages/curve-ui-kit/src/shared/ui/FormTabs/FormTabs.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { type ComponentType, type ReactNode, useState } from 'react'
2+
import { notFalsy } from '@curvefi/prices-api/objects.util'
23
import Stack from '@mui/material/Stack'
34
import { AppFormContentWrapper } from '@ui/AppForm'
45
import { type TabOption, TabsSwitcher } from '@ui-kit/shared/ui/TabsSwitcher'
@@ -36,7 +37,7 @@ const createOptions = <Props extends object>(
3637
params: Props,
3738
): TabOption<string>[] =>
3839
tabs
39-
?.filter(({ visible }) => applyFnOrValue(visible, params))
40+
?.filter(({ visible }) => applyFnOrValue(visible, params) !== false)
4041
.map(({ value, label, disabled }) => ({
4142
value,
4243
label: applyFnOrValue(label, params),
@@ -48,8 +49,10 @@ const selectVisible = <Props extends object, Tab extends FormSubTab<Props>>(
4849
key: string | undefined,
4950
params: Props,
5051
) => {
51-
const visible = tabs.filter(({ visible }) => applyFnOrValue(visible, params))
52-
return visible.find(({ value }) => value === key) ?? visible[0]
52+
const visible = tabs.filter(({ visible }) => applyFnOrValue(visible, params) !== false)
53+
const result = visible.find(({ value }) => value === key) ?? visible[0]
54+
if (!result) throw new Error(`No visible tab found for key ${key} in menu ${JSON.stringify(tabs)}`)
55+
return result
5356
}
5457

5558
type UseFormTabOptions<T extends object> = {
@@ -67,10 +70,10 @@ function useFormTabs<T extends object>({ menu, defaultTab, params }: UseFormTabO
6770
const subTab = tab.subTabs && selectVisible(tab.subTabs, subTabKey, params)
6871
const subTabs = createOptions(tab.subTabs, params)
6972

70-
const Component = subTab?.component ?? tab.component
71-
if (!Component) throw new Error(`No component found for tab ${tab.value} and subTab ${subTab?.value}`)
73+
const components = notFalsy(subTab?.component, tab.component)
74+
if (components.length != 1) throw new Error(`${components.length} components found for [${tabKey}, ${subTabKey}]`)
7275

73-
return { tab, tabs, subTabs, subTab, Component, onChangeTab, onChangeSubTab }
76+
return { tab, tabs, subTabs, subTab, Component: components[0], onChangeTab, onChangeSubTab }
7477
}
7578

7679
/**
@@ -89,7 +92,6 @@ const LegacyFormWrapper = ({ children }: { children: ReactNode }) => (
8992
*/
9093
export function FormTabs<T extends object>({ shouldWrap, ...options }: UseFormTabOptions<T> & { shouldWrap: boolean }) {
9194
const { tab, tabs, subTabs, subTab, Component, onChangeTab, onChangeSubTab } = useFormTabs(options)
92-
const params = options.params
9395
return (
9496
<Stack
9597
sx={{ width: { mobile: '100%', tablet: MaxWidth.actionCard }, marginInline: { mobile: 'auto', desktop: 0 } }}
@@ -109,7 +111,7 @@ export function FormTabs<T extends object>({ shouldWrap, ...options }: UseFormTa
109111
)}
110112

111113
<WithWrapper shouldWrap={shouldWrap} Wrapper={LegacyFormWrapper}>
112-
<Component {...params} />
114+
<Component {...options.params} />
113115
</WithWrapper>
114116
</Stack>
115117
)

0 commit comments

Comments
 (0)