Skip to content

Commit 105d2f5

Browse files
aaa123eeecuteWarmFrogsavvyer
authored
refactor(operation): card layout (#5578)
* refactor(operations): mv logs button * refactor(operations): update styles * chore: avoid toggle * chore: avoid toggle --------- Co-authored-by: Vitya Livshits <64482828+cuteWarmFrog@users.noreply.github.com> Co-authored-by: Anton <653026+savvyer@users.noreply.github.com>
1 parent 060eaab commit 105d2f5

File tree

4 files changed

+66
-78
lines changed

4 files changed

+66
-78
lines changed
Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,42 @@
11
import { type PropsWithChildren } from 'react';
22

3-
import { type Chain } from '@/shared/core';
43
import { cnTw } from '@/shared/lib/utils';
5-
import { type AccountId } from '@/shared/polkadotjs-schemas';
6-
import { type IconNames, Icon } from '@/shared/ui';
7-
import { AccountExplorers } from '@/shared/ui-entities';
4+
import { CaptionText } from '@/shared/ui';
85
import { type MultisigEvent } from '@/domains/network';
96

10-
const IconProps: Record<MultisigEvent['status'], { className: string; name: IconNames }> = {
11-
approve: { className: 'text-text-positive', name: 'checkmarkOutline' },
12-
reject: { className: 'text-text-negative', name: 'closeOutline' },
7+
type StatusConfig = {
8+
className: string;
9+
label: string;
10+
};
11+
12+
const StatusProps: Record<MultisigEvent['status'] | 'unsigned', StatusConfig> = {
13+
approve: { className: 'text-text-positive', label: 'Signed' },
14+
reject: { className: 'text-text-negative', label: 'Rejected' },
15+
unsigned: { className: 'text-text-secondary', label: 'Unsigned' },
1316
};
1417

1518
type Props = {
1619
className?: string;
17-
accountId: AccountId;
18-
chain?: Chain;
1920
status: MultisigEvent['status'] | null;
2021
};
2122

22-
export const SignatoryCard = ({ className, accountId, chain, status, children }: PropsWithChildren<Props>) => {
23-
const statusProps = status ? IconProps[status] : null;
23+
export const SignatoryCard = ({ className, status, children }: PropsWithChildren<Props>) => {
24+
const statusKey = status ?? 'unsigned';
25+
const statusConfig = StatusProps[statusKey];
2426

2527
return (
2628
<div
2729
className={cnTw(
28-
'group flex flex-1 cursor-pointer items-center justify-between gap-x-2 rounded-sm px-2 py-1.5 text-text-secondary',
29-
'transition-colors hover:bg-action-background-hover hover:text-text-primary',
30+
'flex flex-1 items-center justify-between gap-x-2 rounded-sm px-2 py-1.5 text-text-secondary',
3031
className,
3132
)}
3233
>
3334
{children}
34-
{chain && (
35-
<div className={cnTw(statusProps && 'opacity-0 transition-opacity group-hover:opacity-100')}>
36-
<AccountExplorers accountId={accountId} chain={chain} />
37-
</div>
38-
)}
39-
{statusProps && (
40-
<Icon size={16} className={cnTw('group-hover:hidden', statusProps.className)} name={statusProps.name} />
41-
)}
35+
<div className="flex shrink-0 items-center rounded-[20px] border border-shade-8 px-2.5 py-1">
36+
<CaptionText align="center" className={cnTw('uppercase', statusConfig.className)}>
37+
{statusConfig.label}
38+
</CaptionText>
39+
</div>
4240
</div>
4341
);
4442
};

src/renderer/features/multisig-operations/components/OperationAdvancedDetails.tsx

Lines changed: 13 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,34 @@
11
import { useUnit } from 'effector-react';
22

3-
import { type FlexibleMultisigAccount, type MultisigAccount } from '@/shared/core';
43
import { useI18n } from '@/shared/i18n';
5-
import { useToggle } from '@/shared/lib/hooks';
64
import { cnTw, getNativeAsset, truncate } from '@/shared/lib/utils';
7-
import { Button, CaptionText, DetailRow, FootnoteText, Icon, SmallTitleText } from '@/shared/ui';
5+
import { DetailRow, FootnoteText, Icon, SmallTitleText } from '@/shared/ui';
86
import { IconButton } from '@/shared/ui/Buttons';
97
import { AssetBalance } from '@/shared/ui-entities';
108
import { Copy, Tooltip, useNotification } from '@/shared/ui-kit';
119
import { type MultisigOperation } from '@/domains/network';
12-
import { contactModel } from '@/entities/contact';
13-
import { type ExtendedChain, networkModel } from '@/entities/network';
10+
import { networkModel } from '@/entities/network';
1411
import { operationDetailsUtils } from '@/entities/operations';
1512
import { type TabFilter, operationsContextModel } from '../model/context';
1613

17-
import LogModal from './LogModal';
18-
1914
type Props = {
2015
operation: MultisigOperation;
21-
account: MultisigAccount | FlexibleMultisigAccount;
22-
connection: ExtendedChain;
2316
tab: TabFilter;
2417
};
2518

2619
const InteractionStyle =
2720
'rounded-sm hover:bg-action-background-hover hover:text-text-primary cursor-pointer py-[3px] px-2 -mr-2';
2821

29-
export const OperationAdvancedDetails = ({ operation, account, connection, tab }: Props) => {
22+
export const OperationAdvancedDetails = ({ operation, tab }: Props) => {
3023
const { t } = useI18n();
3124
const { toast } = useNotification();
3225

3326
const chains = useUnit(networkModel.$chains);
3427
const chain = chains[operation.chainId];
35-
const contacts = useUnit(contactModel.$contacts);
3628

3729
const nativeAsset = getNativeAsset(chain?.assets ?? []);
3830
const explorers = chain?.explorers;
3931

40-
const [isLogModalOpen, toggleLogModal] = useToggle();
41-
4232
const { indexCreated, blockCreated, deposit, callHash, callData } = operation;
4333

4434
const extrinsicLink = operationDetailsUtils.getMultisigExtrinsicLink(callHash, indexCreated, blockCreated, explorers);
@@ -74,33 +64,16 @@ export const OperationAdvancedDetails = ({ operation, account, connection, tab }
7464
<div className="flex items-center justify-between">
7565
<SmallTitleText>{t('operation.advanced')}</SmallTitleText>
7666

77-
<div className="flex items-center gap-x-2">
78-
<Tooltip>
79-
<Tooltip.Trigger>
80-
<IconButton
81-
name={isHiddenTab ? 'eye' : 'eyeSlashed'}
82-
className="text-icon-default"
83-
onClick={isHiddenTab ? handleUnhideOperation : handleHideOperation}
84-
/>
85-
</Tooltip.Trigger>
86-
<Tooltip.Content>{isHiddenTab ? t('operation.unhideButton') : t('operation.hideButton')}</Tooltip.Content>
87-
</Tooltip>
88-
89-
<Button
90-
pallet="secondary"
91-
variant="fill"
92-
size="sm"
93-
prefixElement={<Icon name="chat" size={16} />}
94-
suffixElement={
95-
<CaptionText className="rounded-full bg-chip-icon px-1.5 pt-px pb-[2px] text-white!">
96-
{operation.events.length}
97-
</CaptionText>
98-
}
99-
onClick={toggleLogModal}
100-
>
101-
{t('operation.logButton')}
102-
</Button>
103-
</div>
67+
<Tooltip>
68+
<Tooltip.Trigger>
69+
<IconButton
70+
name={isHiddenTab ? 'eye' : 'eyeSlashed'}
71+
className="text-icon-default"
72+
onClick={isHiddenTab ? handleUnhideOperation : handleHideOperation}
73+
/>
74+
</Tooltip.Trigger>
75+
<Tooltip.Content>{isHiddenTab ? t('operation.unhideButton') : t('operation.hideButton')}</Tooltip.Content>
76+
</Tooltip>
10477
</div>
10578

10679
<div className="flex flex-col gap-y-2">
@@ -152,15 +125,6 @@ export const OperationAdvancedDetails = ({ operation, account, connection, tab }
152125
</DetailRow>
153126
)}
154127
</div>
155-
156-
<LogModal
157-
isOpen={isLogModalOpen}
158-
operation={operation}
159-
account={account}
160-
connection={connection}
161-
contacts={contacts}
162-
onClose={toggleLogModal}
163-
/>
164128
</div>
165129
);
166130
};

src/renderer/features/multisig-operations/components/OperationFullInfo.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export const OperationFullInfo = memo(({ operation, account, tab }: Props) => {
3737

3838
{account && <OperationSignatories operation={operation} connection={extendedChain} account={account} />}
3939

40-
<OperationAdvancedDetails operation={operation} account={account} connection={extendedChain} tab={tab} />
40+
<OperationAdvancedDetails operation={operation} tab={tab} />
4141
</div>
4242
);
4343
});

src/renderer/features/multisig-operations/components/OperationSignatories.tsx

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { useUnit } from 'effector-react';
2-
import { useMemo } from 'react';
2+
import { useCallback, useMemo, useState } from 'react';
33

44
import { type FlexibleMultisigAccount, type MultisigAccount, type Signatory, type Wallet } from '@/shared/core';
55
import { useI18n } from '@/shared/i18n';
66
import { nonNullable, toAddress } from '@/shared/lib/utils';
7-
import { BodyText, FootnoteText, SmallTitleText } from '@/shared/ui';
7+
import { BodyText, Button, CaptionText, FootnoteText, Icon, SmallTitleText } from '@/shared/ui';
88
import { Address, WalletIcon } from '@/shared/ui-entities';
99
import { type MultisigOperation, accounts } from '@/domains/network';
1010
import { contactModel } from '@/entities/contact';
@@ -13,6 +13,8 @@ import { operationDetailsUtils } from '@/entities/operations';
1313
import { SignatoryCard } from '@/entities/signatory';
1414
import { walletModel } from '@/entities/wallet';
1515

16+
import LogModal from './LogModal';
17+
1618
type WalletSignatory = Signatory & { wallet: Wallet };
1719

1820
type Props = {
@@ -28,6 +30,9 @@ export const OperationSignatories = ({ operation, connection, account }: Props)
2830
const accountsList = useUnit(accounts.$list);
2931
const contacts = useUnit(contactModel.$contacts);
3032

33+
const [isLogModalOpen, setIsLogModalOpen] = useState(false);
34+
const closeLogModal = useCallback(() => setIsLogModalOpen(false), []);
35+
3136
const approvals = operation.events.filter(e => e.status === 'approve');
3237
const cancellation = operation.events.filter(e => e.status === 'reject');
3338

@@ -65,7 +70,23 @@ export const OperationSignatories = ({ operation, connection, account }: Props)
6570

6671
return (
6772
<div className="flex flex-col border-r border-divider p-4">
68-
<SmallTitleText className="mb-4">{t('operation.signatoriesTitle')}</SmallTitleText>
73+
<div className="mb-4 flex items-center justify-between">
74+
<SmallTitleText>{t('operation.signatoriesTitle')}</SmallTitleText>
75+
<Button
76+
pallet="secondary"
77+
variant="fill"
78+
size="sm"
79+
prefixElement={<Icon name="chat" size={16} />}
80+
suffixElement={
81+
<CaptionText className="rounded-full bg-chip-icon px-1.5 pt-px pb-[2px] text-white!">
82+
{operation.events.length}
83+
</CaptionText>
84+
}
85+
onClick={() => setIsLogModalOpen(true)}
86+
>
87+
{t('operation.logButton')}
88+
</Button>
89+
</div>
6990

7091
<div className="flex flex-col gap-y-2">
7192
{Boolean(walletSignatories.length) && (
@@ -77,8 +98,6 @@ export const OperationSignatories = ({ operation, connection, account }: Props)
7798
{walletSignatories.map(signatory => (
7899
<SignatoryCard
79100
key={signatory.accountId}
80-
accountId={signatory.accountId}
81-
chain={connection}
82101
status={operationDetailsUtils.getSignatoryStatus(operation.events, signatory.accountId)}
83102
>
84103
<WalletIcon type={signatory.wallet.type} size={20} />
@@ -98,8 +117,6 @@ export const OperationSignatories = ({ operation, connection, account }: Props)
98117
{contactSignatories.map(signatory => (
99118
<SignatoryCard
100119
key={signatory.accountId}
101-
accountId={signatory.accountId}
102-
chain={connection}
103120
status={operationDetailsUtils.getSignatoryStatus(operation.events, signatory.accountId)}
104121
>
105122
<Address
@@ -121,6 +138,15 @@ export const OperationSignatories = ({ operation, connection, account }: Props)
121138
</div>
122139
)}
123140
</div>
141+
142+
<LogModal
143+
isOpen={isLogModalOpen}
144+
operation={operation}
145+
account={account}
146+
connection={connection}
147+
contacts={contacts}
148+
onClose={closeLogModal}
149+
/>
124150
</div>
125151
);
126152
};

0 commit comments

Comments
 (0)