Skip to content

Commit 7a1e316

Browse files
committed
feat: add stack sub card layout
1 parent 942d3c8 commit 7a1e316

File tree

5 files changed

+136
-23
lines changed

5 files changed

+136
-23
lines changed

apps/web/app/features/stacking/components/choose-pooling-amount.tsx

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useFormContext } from 'react-hook-form';
1+
import { Controller, useFormContext } from 'react-hook-form';
22

33
import { Box, Stack } from 'leather-styles/jsx';
44
import { ErrorLabel } from '~/components/error-label';
@@ -14,7 +14,7 @@ import { Button, Input, Spinner } from '@leather.io/ui';
1414
import { microStxToStx } from '@leather.io/utils';
1515

1616
export function ChoosePoolingAmount() {
17-
const { getFieldState, setValue, register } = useFormContext<StackingPoolFormSchema>();
17+
const { setValue, control } = useFormContext<StackingPoolFormSchema>();
1818

1919
const { stxAddress } = useLeatherConnect();
2020

@@ -25,18 +25,30 @@ export function ChoosePoolingAmount() {
2525
} = useStxCryptoAssetBalance(stxAddress.address);
2626
const totalAvailableBalance = useStxAvailableUnlockedBalance(stxAddress.address);
2727

28-
const { isTouched, error } = getFieldState('amount');
29-
const showError = isTouched && error;
30-
3128
return (
3229
<Stack>
3330
<Box>
34-
<Input.Root>
35-
<Input.Label>Amount of STX to Stack</Input.Label>
36-
<Input.Field id="stxAmount" {...register('amount')} />
37-
</Input.Root>
38-
39-
{showError && <ErrorLabel>{error.message}</ErrorLabel>}
31+
<Controller
32+
control={control}
33+
name="amount"
34+
render={({ field: { onChange, onBlur, value, ref }, fieldState: { invalid, error } }) => (
35+
<>
36+
<Input.Root>
37+
<Input.Label>Amount of STX to Stack</Input.Label>
38+
<Input.Field
39+
id="amount"
40+
value={value}
41+
onChange={input => {
42+
onChange(input.target.value);
43+
}}
44+
onBlur={onBlur}
45+
ref={ref}
46+
/>
47+
</Input.Root>
48+
{invalid && error && <ErrorLabel>{error.message}</ErrorLabel>}
49+
</>
50+
)}
51+
/>
4052
</Box>
4153

4254
<Box textStyle="body.02" color="ink.text-subdued" aria-busy={isLoading}>
Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useFormContext } from 'react-hook-form';
1+
import { Controller, useFormContext } from 'react-hook-form';
22

33
import { Box } from 'leather-styles/jsx';
44
import { ErrorLabel } from '~/components/error-label';
@@ -7,19 +7,31 @@ import { StackingPoolFormSchema } from '~/features/stacking/utils/stacking-pool-
77
import { Input } from '@leather.io/ui';
88

99
export function ChooseRewardsAddress() {
10-
const { register, getFieldState } = useFormContext<StackingPoolFormSchema>();
11-
12-
const { isTouched, error } = getFieldState('rewardAddress');
13-
14-
const showError = isTouched && error;
10+
const { control } = useFormContext<StackingPoolFormSchema>();
1511

1612
return (
1713
<Box>
18-
<Input.Root>
19-
<Input.Label>Address</Input.Label>
20-
<Input.Field id="rewardAddress" {...register('rewardAddress')} />
21-
</Input.Root>
22-
{showError && <ErrorLabel>{error.message}</ErrorLabel>}
14+
<Controller
15+
control={control}
16+
name="rewardAddress"
17+
render={({ field: { onChange, onBlur, value, ref }, fieldState: { invalid, error } }) => (
18+
<>
19+
<Input.Root>
20+
<Input.Label>Address</Input.Label>
21+
<Input.Field
22+
id="rewardAddress"
23+
value={value}
24+
onChange={input => {
25+
onChange(input.target.value);
26+
}}
27+
onBlur={onBlur}
28+
ref={ref}
29+
/>
30+
</Input.Root>
31+
{invalid && error && <ErrorLabel>{error.message}</ErrorLabel>}
32+
</>
33+
)}
34+
/>
2335
</Box>
2436
);
2537
}

apps/web/app/features/stacking/components/stacking-layout.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export function StartStackingLayout(props: StartStackingLayoutProps) {
1414
<Flex
1515
flexDirection={['column-reverse', 'column-reverse', 'row']}
1616
justifyContent="space-between"
17+
alignItems="flex-start"
1718
>
1819
<Box maxWidth={[null, null, '544px']} mr={[null, null, 'space.05']}>
1920
<Box display={['block', null, 'none']} mt={['space.05', null, null, null, 'space.04']}>
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import { useMemo, useState } from 'react';
2+
3+
import { HStack, VStack, styled } from 'leather-styles/jsx';
4+
5+
import { Button, CheckmarkCircleIcon, CircleIcon } from '@leather.io/ui';
6+
7+
export interface StackingStepsCardProps {
8+
poolAmount: string;
9+
}
10+
11+
const confirmations = [
12+
{
13+
id: 'terms-and-conditions',
14+
text: 'I have read and accepted the pool&apos;s terms and conditions',
15+
},
16+
{
17+
id: 'interact-wallet',
18+
text: 'Allow the pool contract to interact with your wallet',
19+
},
20+
{
21+
id: 'confirm',
22+
text: 'Confirm and start pooling',
23+
},
24+
] as const;
25+
26+
export function StackingStepsCard({ poolAmount }: StackingStepsCardProps) {
27+
const [acceptedConfirmations, setAcceptedConfirmations] = useState<string[]>([]);
28+
29+
const currentConfirmation = useMemo<(typeof confirmations)[number] | undefined>(() => {
30+
const lastAcceptedId = acceptedConfirmations[acceptedConfirmations.length - 1];
31+
const lastAcceptedIndex = confirmations.findIndex(conf => conf.id === lastAcceptedId);
32+
const nextIndex = lastAcceptedIndex + 1;
33+
return confirmations[nextIndex];
34+
}, [acceptedConfirmations]);
35+
36+
function handleConfirmation(confirmationId: string) {
37+
setAcceptedConfirmations(prev => [...prev, confirmationId]);
38+
}
39+
40+
return (
41+
<VStack
42+
alignItems="flex-start"
43+
py="space.05"
44+
borderWidth={1}
45+
borderColor="ink.border-default"
46+
gap="space.03"
47+
>
48+
<VStack alignItems="flex-start" px="space.05" gap="space.01">
49+
<styled.h1 textStyle="label.01">You&apos;ll pool up to</styled.h1>
50+
<styled.span textStyle="heading.04" fontSize="26px" fontWeight={500}>
51+
{poolAmount} STX
52+
</styled.span>
53+
</VStack>
54+
{confirmations.map((confirmation, index) => {
55+
const isAccepted = acceptedConfirmations.includes(confirmation.id);
56+
return (
57+
<HStack
58+
key={confirmation.id}
59+
p="space.05"
60+
borderBottomWidth={index === confirmations.length - 1 ? 0 : 1}
61+
borderColor="ink.border-default"
62+
alignItems="flex-start"
63+
>
64+
{isAccepted ? (
65+
<CheckmarkCircleIcon variant="medium" />
66+
) : (
67+
<CircleIcon variant="medium" />
68+
)}
69+
<VStack alignItems="flex-start" gap="space.02">
70+
<styled.span textStyle="label.02">{confirmation.text}</styled.span>
71+
{currentConfirmation?.id === confirmation.id && (
72+
<Button px="space.06" size="sm" onClick={() => handleConfirmation(confirmation.id)}>
73+
Confirm
74+
</Button>
75+
)}
76+
</VStack>
77+
</HStack>
78+
);
79+
})}
80+
</VStack>
81+
);
82+
}

apps/web/app/features/stacking/start-pooled-stacking.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Stack } from 'leather-styles/jsx';
77
import { ChoosePoolingAmount } from '~/features/stacking/components/choose-pooling-amount';
88
import { StackingFormInfoPanel } from '~/features/stacking/components/stacking-form-info-panel';
99
import { StartStackingLayout } from '~/features/stacking/components/stacking-layout';
10+
import { StackingStepsCard } from '~/features/stacking/components/stacking-steps-card';
1011
import { useStackingClient } from '~/features/stacking/providers/stacking-client-provider';
1112
import {
1213
getPoxContracts,
@@ -130,6 +131,7 @@ function StartPooledStackingLayout({ poolName }: StartPooledStackingLayoutProps)
130131
);
131132

132133
const formMethods = useForm<StackingPoolFormSchema>({
134+
mode: 'onTouched',
133135
defaultValues: {
134136
...initialStackingFormValues,
135137
rewardAddress: btcAddressP2wpkh?.address,
@@ -178,7 +180,11 @@ function StartPooledStackingLayout({ poolName }: StartPooledStackingLayoutProps)
178180
</Stack>
179181
</Form>
180182
}
181-
stackingInfoPanel={<StackingFormInfoPanel>{/*<PoolingInfoCard />*/}</StackingFormInfoPanel>}
183+
stackingInfoPanel={
184+
<StackingFormInfoPanel>
185+
<StackingStepsCard poolAmount="999,999.99" />
186+
</StackingFormInfoPanel>
187+
}
182188
/>
183189
</FormProvider>
184190
);

0 commit comments

Comments
 (0)