Skip to content

Commit bab04d3

Browse files
chore: refactor into a form-group component
1 parent af2b786 commit bab04d3

12 files changed

Lines changed: 850 additions & 878 deletions

File tree

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import type { ReactNode } from 'react'
2+
3+
type FormGroupProps = {
4+
title: string
5+
subtitle?: ReactNode
6+
children: ReactNode
7+
className?: string
8+
}
9+
10+
export const FormGroup = ({
11+
title,
12+
subtitle,
13+
children,
14+
className = ''
15+
}: FormGroupProps) => {
16+
return (
17+
<div
18+
className={`grid grid-cols-1 py-3 gap-6 md:grid-cols-3 border-b border-pearl ${className}`}
19+
>
20+
<div className='col-span-1 pt-3'>
21+
<h3 className='text-lg font-medium'>{title}</h3>
22+
{subtitle && <div className='text-sm'>{subtitle}</div>}
23+
</div>
24+
<div className='md:col-span-2 bg-white rounded-md shadow-md'>
25+
{children}
26+
</div>
27+
</div>
28+
)
29+
}
30+

localenv/mock-account-servicing-entity/app/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ export * from './Button'
66
export * from './ErrorPanel'
77
export * from './Input'
88
export * from './Select'
9+
export * from './FormGroup'

localenv/mock-account-servicing-entity/app/routes/accounts.$accountId.tsx

Lines changed: 90 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
} from '@remix-run/react'
1313
import { ChangeEvent, useEffect, useState } from 'react'
1414
import {
15+
FormGroup,
1516
PageHeader,
1617
Table,
1718
Button,
@@ -100,128 +101,109 @@ export default function EditAccount() {
100101
</div>
101102

102103
<fieldset disabled={isSubmitting}>
103-
<div className='grid grid-cols-1 px-0 py-3 gap-6 md:grid-cols-3 border-b border-pearl'>
104-
<div className='col-span-1 pt-3'>
105-
<h3 className='text-lg font-medium'>General Information</h3>
104+
<FormGroup title='General Information'>
105+
<div className='w-full p-4 space-y-3'>
106+
<input type='hidden' name='id' value={account.id} />
107+
<Input
108+
name='name'
109+
label='Account name'
110+
placeholder='Account name'
111+
defaultValue={account?.name}
112+
error={response?.errors.general.fieldErrors.name}
113+
/>
114+
<Input
115+
disabled
116+
name='path'
117+
label='Wallet address'
118+
placeholder='jdoe'
119+
value={`${getOpenPaymentsUrl()}/${account?.path}`}
120+
/>
121+
<Select
122+
options={assets.map(
123+
(asset: {
124+
node: { id: string; code: string; scale: number }
125+
}) => ({
126+
value: asset.node.id,
127+
label: `${asset.node.code} (Scale: ${asset.node.scale})`
128+
})
129+
)}
130+
name='assetId'
131+
placeholder='Select asset...'
132+
label='Asset'
133+
selectedValue={account?.assetId}
134+
disabled
135+
/>
106136
</div>
107-
<div className='md:col-span-2 bg-white rounded-md shadow-md'>
108-
<div className='w-full p-4 space-y-3'>
109-
<input type='hidden' name='id' value={account.id} />
110-
<Input
111-
name='name'
112-
label='Account name'
113-
placeholder='Account name'
114-
defaultValue={account?.name}
115-
error={response?.errors.general.fieldErrors.name}
116-
/>
117-
<Input
118-
disabled
119-
name='path'
120-
label='Wallet address'
121-
placeholder='jdoe'
122-
value={`${getOpenPaymentsUrl()}/${account?.path}`}
123-
/>
124-
<Select
125-
options={assets.map(
126-
(asset: {
127-
node: { id: string; code: string; scale: number }
128-
}) => ({
129-
value: asset.node.id,
130-
label: `${asset.node.code} (Scale: ${asset.node.scale})`
131-
})
132-
)}
133-
name='assetId'
134-
placeholder='Select asset...'
135-
label='Asset'
136-
selectedValue={account?.assetId}
137-
disabled
138-
/>
139-
</div>
140-
<div className='flex justify-end py-3 px-4'>
141-
<Button
142-
aria-label='update account'
143-
name='intent'
144-
value='general'
145-
type='submit'
146-
>
147-
{isSubmitting ? 'Updating account ...' : 'Update'}
148-
</Button>
149-
</div>
137+
<div className='flex justify-end py-3 px-4'>
138+
<Button
139+
aria-label='update account'
140+
name='intent'
141+
value='general'
142+
type='submit'
143+
>
144+
{isSubmitting ? 'Updating account ...' : 'Update'}
145+
</Button>
150146
</div>
151-
</div>
147+
</FormGroup>
152148
</fieldset>
153149
</Form>
154150
{/* Update Account form - END */}
155151
<fieldset key={`liquidity_${key}`} disabled={isSubmitting}>
156-
<div className='grid grid-cols-1 px-0 py-3 gap-6 md:grid-cols-3 border-b border-pearl'>
157-
<div className='col-span-1 pt-3'>
158-
<h3 className='text-lg font-medium'>Balance</h3>
152+
<FormGroup title='Balance'>
153+
<div className='w-full p-4 space-y-3'>
154+
<p className='font-medium'>Available</p>
155+
<p className='mt-1'>{`${(Number(account.balance) / 100).toFixed(
156+
account.assetScale
157+
)} ${account.assetCode}`}</p>
159158
</div>
160-
<div className='md:col-span-2 bg-white rounded-md shadow-md'>
161-
<div className='w-full p-4 space-y-3'>
162-
<p className='font-medium'>Available</p>
163-
<p className='mt-1'>{`${(
164-
Number(account.balance) / 100
165-
).toFixed(account.assetScale)} ${account.assetCode}`}</p>
166-
</div>
167-
<div className='w-full p-4 space-y-3'>
168-
<Input
169-
type='number'
170-
name='balance'
171-
label='Amount to add'
172-
placeholder='0'
173-
min={1}
174-
error={response?.errors.addLiquidity.fieldErrors.amount}
175-
onChange={onAmountChange}
176-
/>
177-
<div className='flex justify-end'>
178-
<Button
179-
aria-label='add liquidity'
180-
type='button'
181-
disabled={amountToAdd <= 0}
182-
onClick={() => setLiquidityModalOpen(true)}
183-
>
184-
Add
185-
</Button>
186-
</div>
159+
<div className='w-full p-4 space-y-3'>
160+
<Input
161+
type='number'
162+
name='balance'
163+
label='Amount to add'
164+
placeholder='0'
165+
min={1}
166+
error={response?.errors.addLiquidity.fieldErrors.amount}
167+
onChange={onAmountChange}
168+
/>
169+
<div className='flex justify-end'>
170+
<Button
171+
aria-label='add liquidity'
172+
type='button'
173+
disabled={amountToAdd <= 0}
174+
onClick={() => setLiquidityModalOpen(true)}
175+
>
176+
Add
177+
</Button>
187178
</div>
188179
</div>
189-
</div>
180+
</FormGroup>
190181
</fieldset>
191182
{/* Transsactions */}
192-
<div className='grid grid-cols-1 px-0 py-3 gap-6 md:grid-cols-3 border-b border-pearl'>
193-
<div className='col-span-1 pt-3'>
194-
<h3 className='text-lg font-medium'>Transactions</h3>
195-
</div>
196-
<div className='md:col-span-2 bg-white rounded-md shadow-md'>
197-
<div className='w-full p-4 space-y-3'>
198-
<Table>
199-
<Table.Head
200-
columns={['Date', 'Type', 'Metadata', 'Amount']}
201-
/>
183+
<FormGroup title='Transactions'>
184+
<div className='w-full p-4 space-y-3'>
185+
<Table>
186+
<Table.Head columns={['Date', 'Type', 'Metadata', 'Amount']} />
202187

203-
{transactions.map((trx) => (
204-
<Table.Row key={trx.id}>
205-
<Table.Cell>{trx.createdAt}</Table.Cell>
206-
<Table.Cell>{trx.type}</Table.Cell>
207-
<Table.Cell>
208-
<code>{JSON.stringify(trx.metadata)}</code>
209-
</Table.Cell>
210-
<Table.Cell>
211-
{(Number(trx.amountValue) / 100).toFixed(
212-
trx.assetScale
213-
)}{' '}
214-
{trx.assetCode}
215-
</Table.Cell>
216-
</Table.Row>
217-
))}
218-
</Table>
219-
<div className='flex items-center justify-between p-5'>
220-
&nbsp;
221-
</div>
188+
{transactions.map((trx) => (
189+
<Table.Row key={trx.id}>
190+
<Table.Cell>{trx.createdAt}</Table.Cell>
191+
<Table.Cell>{trx.type}</Table.Cell>
192+
<Table.Cell>
193+
<code>{JSON.stringify(trx.metadata)}</code>
194+
</Table.Cell>
195+
<Table.Cell>
196+
{(Number(trx.amountValue) / 100).toFixed(trx.assetScale)}{' '}
197+
{trx.assetCode}
198+
</Table.Cell>
199+
</Table.Row>
200+
))}
201+
</Table>
202+
<div className='flex items-center justify-between p-5'>
203+
&nbsp;
222204
</div>
223205
</div>
224-
</div>
206+
</FormGroup>
225207
{/* Transsactions - END */}
226208
</div>
227209
</div>

localenv/mock-account-servicing-entity/app/routes/accounts.create.tsx

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,14 @@ import {
55
useActionData,
66
useNavigation
77
} from '@remix-run/react'
8-
import { PageHeader, Button, ErrorPanel, Input, Select } from '~/components'
8+
import {
9+
FormGroup,
10+
PageHeader,
11+
Button,
12+
ErrorPanel,
13+
Input,
14+
Select
15+
} from '~/components'
916
import { loadAssets } from '~/lib/asset.server'
1017
import { createAccount } from '~/lib/accounts.server'
1118
import { createWallet } from '~/lib/wallet.server'
@@ -47,44 +54,39 @@ export default function CreateAccountPage() {
4754
</div>
4855

4956
<fieldset disabled={isSubmitting}>
50-
<div className='grid grid-cols-1 px-0 py-3 gap-6 md:grid-cols-3 border-b border-pearl'>
51-
<div className='col-span-1 pt-3'>
52-
<h3 className='text-lg font-medium'>General Information</h3>
53-
</div>
54-
<div className='md:col-span-2 bg-white rounded-md shadow-md'>
55-
<div className='w-full p-4 space-y-3'>
56-
<Input
57-
name='name'
58-
label='Account name'
59-
placeholder='Account name'
60-
error={response?.errors?.fieldErrors.name}
61-
/>
62-
<Input
63-
required
64-
addOn={`${options?.walletAddressPrefix ?? getOpenPaymentsUrl()}/accounts/`}
65-
name='path'
66-
label='Wallet address'
67-
placeholder='jdoe'
68-
error={response?.errors?.fieldErrors.path}
69-
/>
70-
<Select
71-
options={assets.map(
72-
(asset: {
73-
node: { id: string; code: string; scale: number }
74-
}) => ({
75-
value: asset.node.id,
76-
label: `${asset.node.code} (Scale: ${asset.node.scale})`
77-
})
78-
)}
79-
error={response?.errors.fieldErrors.assetId}
80-
name='assetId'
81-
placeholder='Select asset...'
82-
label='Asset'
83-
required
84-
/>
85-
</div>
57+
<FormGroup title='General Information'>
58+
<div className='w-full p-4 space-y-3'>
59+
<Input
60+
name='name'
61+
label='Account name'
62+
placeholder='Account name'
63+
error={response?.errors?.fieldErrors.name}
64+
/>
65+
<Input
66+
required
67+
addOn={`${options?.walletAddressPrefix ?? getOpenPaymentsUrl()}/accounts/`}
68+
name='path'
69+
label='Wallet address'
70+
placeholder='jdoe'
71+
error={response?.errors?.fieldErrors.path}
72+
/>
73+
<Select
74+
options={assets.map(
75+
(asset: {
76+
node: { id: string; code: string; scale: number }
77+
}) => ({
78+
value: asset.node.id,
79+
label: `${asset.node.code} (Scale: ${asset.node.scale})`
80+
})
81+
)}
82+
error={response?.errors.fieldErrors.assetId}
83+
name='assetId'
84+
placeholder='Select asset...'
85+
label='Asset'
86+
required
87+
/>
8688
</div>
87-
</div>
89+
</FormGroup>
8890
<div className='flex justify-end py-3'>
8991
<Button aria-label='create account' type='submit'>
9092
{isSubmitting ? 'Creating account ...' : 'Create'}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import type { ReactNode } from 'react'
2+
3+
type FormGroupProps = {
4+
title: string
5+
subtitle?: ReactNode
6+
children: ReactNode
7+
className?: string
8+
}
9+
10+
export const FormGroup = ({
11+
title,
12+
subtitle,
13+
children,
14+
className = ''
15+
}: FormGroupProps) => {
16+
return (
17+
<div
18+
className={`grid grid-cols-1 py-3 gap-6 md:grid-cols-3 border-b border-pearl ${className}`}
19+
>
20+
<div className='col-span-1 pt-3'>
21+
<h3 className='text-lg font-medium'>{title}</h3>
22+
{subtitle && <div className='text-sm'>{subtitle}</div>}
23+
</div>
24+
<div className='md:col-span-2 bg-white rounded-md shadow-md'>
25+
{children}
26+
</div>
27+
</div>
28+
)
29+
}

packages/frontend/app/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ export * from './PageHeader'
33
export * from './Sidebar'
44
export * from './Snackbar'
55
export * from './Badge'
6+
export * from './FormGroup'

0 commit comments

Comments
 (0)