From c80bf3c08ee51efa886f21287e437805223a738d Mon Sep 17 00:00:00 2001 From: katty barroso Date: Fri, 15 Nov 2024 15:01:25 +0100 Subject: [PATCH] Add pool setup section UI --- .../IssuerCreatePool/PoolDetailsSection.tsx | 31 +- .../IssuerCreatePool/PoolSetupSection.tsx | 314 ++++++++++++++++++ .../IssuerCreatePool/PoolStructureSection.tsx | 2 +- .../src/pages/IssuerCreatePool/index.tsx | 9 +- .../src/pages/IssuerCreatePool/types.ts | 11 +- fabric/src/components/TextInput/index.tsx | 6 +- 6 files changed, 343 insertions(+), 30 deletions(-) create mode 100644 centrifuge-app/src/pages/IssuerCreatePool/PoolSetupSection.tsx diff --git a/centrifuge-app/src/pages/IssuerCreatePool/PoolDetailsSection.tsx b/centrifuge-app/src/pages/IssuerCreatePool/PoolDetailsSection.tsx index de9bd5251d..bb9655b0e6 100644 --- a/centrifuge-app/src/pages/IssuerCreatePool/PoolDetailsSection.tsx +++ b/centrifuge-app/src/pages/IssuerCreatePool/PoolDetailsSection.tsx @@ -18,6 +18,12 @@ import { isTestEnv } from '../../../src/config' import { StyledGrid } from './PoolStructureSection' import { validate } from './validate' +export const AddButton = () => ( + +) + const PROVIDERS = [ { label: 'Fund admin', value: 'fundAdmin' }, { label: 'Trustee', value: 'trustee' }, @@ -30,11 +36,6 @@ const PROVIDERS = [ { label: 'Other', value: 'other' }, ] -export const Line = () => { - const theme = useTheme() - return -} - export const PoolDetailsSection = () => { const theme = useTheme() const form = useFormikContext() @@ -125,7 +126,7 @@ export const PoolDetailsSection = () => { - Issuer + Issuer @@ -291,7 +292,7 @@ export const PoolDetailsSection = () => { - Service Providers + Service providers {({ field, meta, form }: FieldProps) => ( @@ -321,15 +322,11 @@ export const PoolDetailsSection = () => { /> )} - - - + - Pool rating + Pool rating {({ field, meta, form }: FieldProps) => ( @@ -366,15 +363,11 @@ export const PoolDetailsSection = () => { /> )} - - - + - Pool analysis + Service analysis {({ field, meta, form }: FieldProps) => ( diff --git a/centrifuge-app/src/pages/IssuerCreatePool/PoolSetupSection.tsx b/centrifuge-app/src/pages/IssuerCreatePool/PoolSetupSection.tsx new file mode 100644 index 0000000000..92dd2f95fe --- /dev/null +++ b/centrifuge-app/src/pages/IssuerCreatePool/PoolSetupSection.tsx @@ -0,0 +1,314 @@ +import { PoolMetadataInput } from '@centrifuge/centrifuge-js' +import { + Box, + Button, + Checkbox, + FileUpload, + Grid, + IconButton, + IconHelpCircle, + IconInfo, + IconTrash, + NumberInput, + Select, + Text, + TextInput, +} from '@centrifuge/fabric' +import { Field, FieldProps, useFormikContext } from 'formik' +import { useTheme } from 'styled-components' +import { FieldWithErrorMessage } from '../../../src/components/FieldWithErrorMessage' +import { Tooltips } from '../../../src/components/Tooltips' +import { feeCategories, isTestEnv } from '../../../src/config' +import { AddButton } from './PoolDetailsSection' +import { CheckboxOption, Line, StyledGrid } from './PoolStructureSection' + +const MAX_FEES = 5 + +const FEE_TYPES = [ + { label: 'Direct charge', value: 'chargedUpTo' }, + { label: 'Fixed %', value: 'fixed' }, +] + +const FEE_POSISTIONS = [{ label: 'Top of waterfall', value: 'Top of waterfall' }] + +export const PoolSetupSection = () => { + const theme = useTheme() + const form = useFormikContext() + const { values } = form + const createLabel = (label: string) => `${label}${isTestEnv ? '' : '*'}` + + return ( + + + + Management setup + + + + + + Pool managers* + + Pool managers can individually add/block investors and manage the liquidity reserve of the pool. + + + + Security requirement + } + /> + } + /> + + + Wallet addresses + + {({ field, form }: FieldProps) => } + + + {({ field, form }: FieldProps) => } + + + + + + + + {({ field, meta, form }: FieldProps) => ( + form.setFieldValue(`poolFees.${index}.category`, event.target.value)} + onBlur={field.onBlur} + errorMessage={meta.touched && meta.error ? meta.error : undefined} + value={field.value} + options={feeCategories.map((cat) => ({ label: cat, value: cat }))} + /> + )} + + + {({ field, meta }: FieldProps) => { + return ( + { + form.setFieldValue(`poolFees.${index}.feeType`, event.target.value) + }} + onBlur={field.onBlur} + errorMessage={meta.touched && meta.error ? meta.error : undefined} + value={field.value} + options={FEE_TYPES} + /> + ) + }} + + + + + + + ))} + + + + + + + Investor onboarding + + + Onboarding experience + } + /> + } + /> + } + /> + + + + {({ field, meta, form }: FieldProps) => ( + { + form.setFieldTouched('poolIcon', true, false) + form.setFieldValue('poolIcon', file) + }} + label="Click to upload" + errorMessage={meta.touched && meta.error ? meta.error : undefined} + accept="application/pdf" + small + /> + )} + + + Tax document requirement + + + + + + + ) +} diff --git a/centrifuge-app/src/pages/IssuerCreatePool/PoolStructureSection.tsx b/centrifuge-app/src/pages/IssuerCreatePool/PoolStructureSection.tsx index 73bb434a43..49a69ca121 100644 --- a/centrifuge-app/src/pages/IssuerCreatePool/PoolStructureSection.tsx +++ b/centrifuge-app/src/pages/IssuerCreatePool/PoolStructureSection.tsx @@ -48,7 +48,7 @@ const ASSET_CLASSES = Object.keys(config.assetClasses).map((key) => ({ value: key, })) -const CheckboxOption = ({ +export const CheckboxOption = ({ name, label, value, diff --git a/centrifuge-app/src/pages/IssuerCreatePool/index.tsx b/centrifuge-app/src/pages/IssuerCreatePool/index.tsx index 6615b99884..9a3330802c 100644 --- a/centrifuge-app/src/pages/IssuerCreatePool/index.tsx +++ b/centrifuge-app/src/pages/IssuerCreatePool/index.tsx @@ -4,6 +4,7 @@ import { useRef, useState } from 'react' import styled, { useTheme } from 'styled-components' import { useIsAboveBreakpoint } from '../../../src/utils/useIsAboveBreakpoint' import { PoolDetailsSection } from './PoolDetailsSection' +import { PoolSetupSection } from './PoolSetupSection' import { Line, PoolStructureSection } from './PoolStructureSection' import { initialValues } from './types' import { validateValues } from './validate' @@ -15,15 +16,11 @@ const StyledBox = styled(Box)` } ` -const PoolSetup = () => { - return
-} - const IssuerCreatePoolPage = () => { const theme = useTheme() const formRef = useRef(null) const isSmall = useIsAboveBreakpoint('S') - const [step, setStep] = useState(2) + const [step, setStep] = useState(1) const form = useFormik({ initialValues: initialValues, @@ -65,7 +62,7 @@ const IssuerCreatePoolPage = () => { {step === 1 && } {step === 2 && } - {step === 3 && } + {step === 3 && } {step !== 1 && ( diff --git a/centrifuge-app/src/pages/IssuerCreatePool/types.ts b/centrifuge-app/src/pages/IssuerCreatePool/types.ts index 4501a18263..65212c90d1 100644 --- a/centrifuge-app/src/pages/IssuerCreatePool/types.ts +++ b/centrifuge-app/src/pages/IssuerCreatePool/types.ts @@ -24,6 +24,15 @@ export const createEmptyTranche = (trancheName: string): Tranche => ({ apy: '90d', }) +export const createPoolFee = () => ({ + name: '', + category: '', + feePosition: '', + feeType: '', + percentOfNav: '', + walletAddress: '', +}) + export type CreatePoolValues = Omit< PoolMetadataInput, 'poolIcon' | 'issuerLogo' | 'executiveSummary' | 'adminMultisig' | 'poolFees' | 'poolReport' | 'poolRatings' @@ -105,6 +114,6 @@ export const initialValues: CreatePoolValues = { threshold: 1, }, adminMultisigEnabled: false, - poolFees: [], + poolFees: [createPoolFee()], poolType: 'open', } diff --git a/fabric/src/components/TextInput/index.tsx b/fabric/src/components/TextInput/index.tsx index 51fc2598b6..926af407a1 100644 --- a/fabric/src/components/TextInput/index.tsx +++ b/fabric/src/components/TextInput/index.tsx @@ -52,10 +52,10 @@ export const StyledTextInput = styled.input` margin: 0; } ` -export const StyledInputBox = styled(Shelf)<{ hideBorder?: boolean }>` +export const StyledInputBox = styled(Shelf)<{ hideBorder?: boolean; disabled?: boolean }>` width: 100%; position: relative; - background: ${({ theme }) => theme.colors.backgroundPage}; + background: ${({ theme, disabled }) => (disabled ? 'transparent' : theme.colors.backgroundPage)}; border: ${({ hideBorder, theme }) => (hideBorder ? 'none' : `1px solid ${theme.colors.borderPrimary}`)}; border-radius: ${({ hideBorder, theme }) => (hideBorder ? 'none' : `${theme.radii.input}px`)}; @@ -121,7 +121,7 @@ export function TextInputBox( ) { const { error, disabled, action, symbol, inputRef, inputElement, row, ...inputProps } = props return ( - + {inputElement ?? } {symbol && (