Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Review step redesign #993

Merged
merged 10 commits into from
Oct 28, 2022
53 changes: 49 additions & 4 deletions src/components/new-safe/CreateSafe/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,40 @@ import type { TxStepperProps } from '../CardStepper/useCardStepper'
import CreateSafeStep1 from '../steps/Step1'
import useAddressBook from '@/hooks/useAddressBook'
import CreateSafeStep2 from '../steps/Step2'
import { CardStepper } from '../CardStepper'
import Grid from '@mui/material/Grid'
import { Card, CardContent, Typography } from '@mui/material'
import { useRouter } from 'next/router'
import { AppRoutes } from '@/config/routes'
import { CREATE_SAFE_CATEGORY } from '@/services/analytics'
import CreateSafeStep3 from '@/components/new-safe/steps/Step3'

export type NewSafeFormData = {
name: string
threshold: number
owners: NamedAddress[]
mobileOwners: NamedAddress[]
}

export const CreateSafeSteps: TxStepperProps<NewSafeFormData>['steps'] = [
{
title: 'Select network and name Safe',
subtitle: 'Select the network on which to create your Safe',
render: (data, onSubmit, onBack) => <CreateSafeStep1 onSubmit={onSubmit} onBack={onBack} data={data} />,
},
{
title: 'Owners and confirmations',
subtitle:
'Here you can add owners to your Safe and determine how many owners need to confirm before making a successful transaction',
render: (data, onSubmit, onBack) => <CreateSafeStep2 onSubmit={onSubmit} onBack={onBack} data={data} />,
},
{
title: 'Review',
subtitle: `You're about to create a new Safe and will have to confirm a transaction with your currently connected wallet.`,
render: (data, onSubmit, onBack) => <CreateSafeStep3 onSubmit={onSubmit} onBack={onBack} data={data} />,
},
]

const CreateSafe = () => {
const router = useRouter()
const wallet = useWallet()
Expand Down Expand Up @@ -46,10 +78,23 @@ const CreateSafe = () => {
</Grid>

<Grid item xs={1} />
<Grid item xs={6} sx={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
<CreateSafeStep1 />
<CreateSafeStep2 />
<CreateSafeStep3 />
<Grid item xs={12} md={6}>
{wallet?.address ? (
<CardStepper
initialData={initialData}
onClose={onClose}
steps={CreateSafeSteps}
eventCategory={CREATE_SAFE_CATEGORY}
/>
) : (
<Card>
<CardContent>
<Typography variant="h3" fontWeight={700}>
You need to connect a wallet to create a new Safe.
</Typography>
</CardContent>
</Card>
)}
</Grid>
<Grid item xs={12} md={4}>
{wallet?.address && <OverviewWidget rows={rows} />}
Expand Down
1 change: 0 additions & 1 deletion src/components/new-safe/steps/Step2/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ const CreateSafeStep2 = ({
const { register, handleSubmit, control, watch } = formMethods

const allFormData = watch()
const currentThreshold = watch(CreateSafeStep2Fields.threshold)

const { fields: ownerFields, append: appendOwner, remove: removeOwner } = useFieldArray({ control, name: 'owners' })

Expand Down
184 changes: 83 additions & 101 deletions src/components/new-safe/steps/Step3/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { useMemo, type ReactElement } from 'react'
import { FormProvider, useForm } from 'react-hook-form'
import { Button, Grid, Typography, Divider, Box } from '@mui/material'
import StepCard from '@/components/new-safe/StepCard'
import ChainIndicator from '@/components/common/ChainIndicator'
import EthHashInfo from '@/components/common/EthHashInfo'
import type { NamedAddress } from '@/components/create-safe/types'
import { useCurrentChain } from '@/hooks/useChains'
import useGasPrice from '@/hooks/useGasPrice'
import { useEstimateSafeCreationGas } from '@/components/create-safe/useEstimateSafeCreationGas'
import { formatVisualAmount } from '@/utils/formatters'
import type { StepRenderProps } from '@/components/new-safe/CardStepper/useCardStepper'
import type { NewSafeFormData } from '@/components/new-safe/CreateSafe'
import css from './styles.module.css'

enum CreateSafeStep3Fields {
Expand Down Expand Up @@ -39,39 +40,22 @@ const ReviewRow = ({ name, value }: { name: string; value: ReactElement }) => {
)
}

const CreateSafeStep3 = (): ReactElement => {
const CreateSafeStep3 = ({
onSubmit,
onBack,
data,
}: Pick<StepRenderProps<NewSafeFormData>, 'onSubmit' | 'data' | 'onBack'>): ReactElement => {
const chain = useCurrentChain()
const { maxFeePerGas, maxPriorityFeePerGas } = useGasPrice()
const saltNonce = useMemo(() => Date.now(), [])

// TODO: Get the Safe name from previous steps
const newSafeName = 'My Safe'
const safeOwners = useMemo(
() => [
{
name: 'My Wallet',
address: '0x85380007df137839015c2c1254c4b6cec130c589',
},
{
name: 'Marta',
address: '0xc81DeFC11034BDdFbFeeF299987Cd8f74A5B9bd8',
},
{
name: 'John',
address: '0xE297437d6b53890cbf004e401F3acc67c8b39665',
},
],
[],
)
const safeThreshold = 1

const safeParams = useMemo(() => {
return {
owners: safeOwners.map((owner) => owner.address),
threshold: safeThreshold,
owners: data.owners.map((owner) => owner.address),
threshold: data.threshold,
saltNonce,
}
}, [safeOwners, saltNonce])
}, [data.owners, data.threshold, saltNonce])

const { gasLimit } = useEstimateSafeCreationGas(safeParams)

Expand All @@ -83,92 +67,90 @@ const CreateSafeStep3 = (): ReactElement => {
const formMethods = useForm<CreateSafeStep3Form>({
mode: 'all',
defaultValues: {
[CreateSafeStep3Fields.name]: newSafeName,
[CreateSafeStep3Fields.owners]: safeOwners,
[CreateSafeStep3Fields.threshold]: safeThreshold,
[CreateSafeStep3Fields.name]: data.name,
[CreateSafeStep3Fields.owners]: data.owners,
[CreateSafeStep3Fields.threshold]: data.threshold,
},
})

const { handleSubmit } = formMethods
const { handleSubmit, watch } = formMethods

const onSubmit = (data: CreateSafeStep3Form) => {
console.log(data)
const allFormData = watch()

const handleBack = () => {
onBack(allFormData)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recomment calling getValues inside handleBack. watch causes rerenders.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True! good suggestion also because I don't expect these values to change in the review step.

}

return (
<StepCard
step={3}
title="Review"
subheader={`You're about to create a new Safe on ${chain?.chainName} and will have to confirm a transaction with your currently connected wallet.`}
content={
<form onSubmit={handleSubmit(onSubmit)} id={STEP_3_FORM_ID}>
<FormProvider {...formMethods}>
<form onSubmit={handleSubmit(onSubmit)} id={STEP_3_FORM_ID}>
<FormProvider {...formMethods}>
<Grid container spacing={3}>
<Grid item>
<Grid container spacing={3}>
<Grid item>
<Grid container spacing={3}>
<ReviewRow name="Network" value={<ChainIndicator chainId={chain?.chainId} inline />} />
<ReviewRow name="Name" value={<Typography>{newSafeName}</Typography>} />
<ReviewRow
name="Owners"
value={
<Box className={css.ownersArray}>
{safeOwners.map((owner, index) => (
<EthHashInfo address={owner.address} shortAddress={false} showPrefix={false} key={index} />
))}
</Box>
}
/>
<ReviewRow
name="Threshold"
value={
<Typography>
{safeThreshold} out of {safeOwners.length} owner(s)
</Typography>
}
/>
</Grid>
</Grid>
<ReviewRow name="Network" value={<ChainIndicator chainId={chain?.chainId} inline />} />
<ReviewRow name="Name" value={<Typography>{data.name}</Typography>} />
<ReviewRow
name="Owners"
value={
<Box className={css.ownersArray}>
{data.owners.map((owner, index) => (
<EthHashInfo address={owner.address} shortAddress={false} showPrefix={false} key={index} />
usame-algan marked this conversation as resolved.
Show resolved Hide resolved
))}
</Box>
}
/>
<ReviewRow
name="Threshold"
value={
<Typography>
{data.threshold} out of {data.owners.length} owner(s)
</Typography>
}
/>
</Grid>
</Grid>

<Grid item xs={12}>
<Divider sx={{ ml: '-52px', mr: '-52px', mb: 4, mt: 3 }} />
<Grid item xs={12}>
<Grid container spacing={3}>
<ReviewRow
name="Est. network fee"
value={
<Box p={1} sx={{ backgroundColor: 'secondary.background', width: 'fit-content' }}>
<Typography variant="body1">
<b>
&asymp; {totalFee} {chain?.nativeCurrency.symbol}
</b>
</Typography>
</Box>
}
/>
<ReviewRow
name=""
value={
<Typography color="text.secondary">
You will have to confirm a transaction with your currently connected wallet.
</Typography>
}
/>
</Grid>
</Grid>
<Grid item xs={12}>
<Divider sx={{ ml: '-52px', mr: '-52px', mb: 4, mt: 3 }} />
<Grid item xs={12}>
<Grid container spacing={3}>
<ReviewRow
name="Est. network fee"
value={
<Box p={1} sx={{ backgroundColor: 'secondary.background', width: 'fit-content' }}>
<Typography variant="body1">
<b>
&asymp; {totalFee} {chain?.nativeCurrency.symbol}
</b>
</Typography>
</Box>
}
/>
<ReviewRow
name=""
value={
<Typography color="text.secondary">
You will have to confirm a transaction with your currently connected wallet.
</Typography>
}
/>
usame-algan marked this conversation as resolved.
Show resolved Hide resolved
</Grid>
</Grid>
</FormProvider>
</form>
}
actions={
<>
<Button variant="contained" form={STEP_3_FORM_ID} type="submit">
Continue
</Button>
<Button variant="text">Back</Button>
</>
}
/>
</Grid>
<Grid item xs={12}>
<Divider sx={{ ml: '-52px', mr: '-52px', mb: 4, mt: 3, alignSelf: 'normal' }} />
<Box display="flex" flexDirection="row" gap={3}>
<Button variant="outlined" onClick={handleBack}>
Back
</Button>
<Button type="submit" variant="contained">
Continue
</Button>
</Box>
</Grid>
</Grid>
</FormProvider>
</form>
)
}

Expand Down