Skip to content

Commit 6ea6942

Browse files
committed
Refactor AgentsListRow and AgentsPage components to replace Avatar with ReportActionAvatars for improved visual consistency. Remove avatar prop from AgentsPage and update related styles. Integrate usePersonalDetails hook for better data handling in AgentsPage.
1 parent 919a440 commit 6ea6942

4 files changed

Lines changed: 36 additions & 52 deletions

File tree

src/pages/settings/Agents/AgentsListRow.tsx

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import React from 'react';
22
import {View} from 'react-native';
3-
import Avatar from '@components/Avatar';
3+
import ReportActionAvatars from '@components/ReportActionAvatars';
44
import Text from '@components/Text';
5+
import useStyleUtils from '@hooks/useStyleUtils';
56
import useThemeStyles from '@hooks/useThemeStyles';
6-
import type {AvatarSource} from '@libs/UserAvatarUtils';
7+
import variables from '@styles/variables';
78
import CONST from '@src/CONST';
89

910
type AgentsListRowProps = {
@@ -15,25 +16,19 @@ type AgentsListRowProps = {
1516

1617
/** Login email of the agent */
1718
login: string;
18-
19-
/** Avatar source of the agent */
20-
avatar: AvatarSource;
2119
};
2220

23-
function AgentsListRow({accountID, displayName, login, avatar}: AgentsListRowProps) {
21+
function AgentsListRow({accountID, displayName, login}: AgentsListRowProps) {
2422
const styles = useThemeStyles();
23+
const StyleUtils = useStyleUtils();
2524

2625
return (
2726
<View style={[styles.flexRow, styles.alignItemsCenter, styles.highlightBG, styles.br3, styles.mh5, styles.mb3, styles.ph5, styles.pv3, styles.gap5]}>
28-
<Avatar
29-
size={CONST.AVATAR_SIZE.DEFAULT}
30-
source={avatar}
31-
avatarID={accountID}
32-
name={displayName}
33-
type={CONST.ICON_TYPE_AVATAR}
34-
containerStyles={styles.agentsListRowAvatar}
35-
imageStyles={styles.agentsListRowAvatar}
36-
iconAdditionalStyles={styles.agentsListRowAvatarInner}
27+
<ReportActionAvatars
28+
accountIDs={[accountID]}
29+
size={CONST.AVATAR_SIZE.LARGE_NORMAL}
30+
shouldShowTooltip={false}
31+
singleAvatarContainerStyle={[StyleUtils.getWidthAndHeightStyle(variables.avatarSizeLargeNormal)]}
3732
/>
3833
<View style={[styles.flex1, styles.gap2]}>
3934
<Text

src/pages/settings/Agents/AgentsPage.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {FlatList, View} from 'react-native';
33
import Button from '@components/Button';
44
import GenericEmptyStateComponent from '@components/EmptyStateComponent/GenericEmptyStateComponent';
55
import HeaderWithBackButton from '@components/HeaderWithBackButton';
6+
import {usePersonalDetails} from '@components/OnyxListItemProvider';
67
import ScreenWrapper from '@components/ScreenWrapper';
78
import ScrollView from '@components/ScrollView';
89
import Text from '@components/Text';
@@ -24,21 +25,20 @@ type AgentItem = {
2425
accountID: number;
2526
displayName: string;
2627
login: string;
27-
avatar: string;
2828
};
2929

3030
function AgentsPage() {
3131
const {translate} = useLocalize();
3232
const styles = useThemeStyles();
3333
const {shouldUseNarrowLayout} = useResponsiveLayout();
3434
const illustrations = useMemoizedLazyIllustrations(['TvScreenRobot', 'AiBot']);
35-
const icons = useMemoizedLazyExpensifyIcons(['Plus', 'FallbackAvatar']);
35+
const icons = useMemoizedLazyExpensifyIcons(['Plus']);
3636
const {isBetaEnabled} = usePermissions();
3737
const isCustomAgentEnabled = isBetaEnabled(CONST.BETAS.CUSTOM_AGENT);
3838
useDocumentTitle(translate('agentsPage.title'));
3939

4040
const [agentPrompts] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT);
41-
const [personalDetailsList] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
41+
const personalDetailsList = usePersonalDetails();
4242

4343
useEffect(() => {
4444
if (!isCustomAgentEnabled) {
@@ -60,19 +60,17 @@ function AgentsPage() {
6060
accountID,
6161
displayName: details.displayName ?? details.login ?? '',
6262
login: details.login ?? '',
63-
avatar: (details.avatar as string) ?? (icons.FallbackAvatar as string),
6463
};
6564
})
6665
.filter((item): item is AgentItem => item !== null),
67-
[agentPrompts, personalDetailsList, icons.FallbackAvatar],
66+
[agentPrompts, personalDetailsList],
6867
);
6968

7069
const renderItem = ({item}: {item: AgentItem}) => (
7170
<AgentsListRow
7271
accountID={item.accountID}
7372
displayName={item.displayName}
7473
login={item.login}
75-
avatar={item.avatar}
7674
/>
7775
);
7876

src/styles/index.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5496,19 +5496,6 @@ const staticStyles = (theme: ThemeColors) =>
54965496
alignSelf: 'center',
54975497
},
54985498

5499-
agentsListRowAvatar: {
5500-
width: variables.avatarSizeLargeNormal,
5501-
height: variables.avatarSizeLargeNormal,
5502-
},
5503-
5504-
agentsListRowAvatarInner: {
5505-
width: variables.avatarSizeLargeNormal,
5506-
height: variables.avatarSizeLargeNormal,
5507-
borderRadius: 24,
5508-
alignItems: 'center',
5509-
justifyContent: 'center',
5510-
},
5511-
55125499
emptyStateFolderWithPaperIconSize: {
55135500
width: 160,
55145501
height: 100,

tests/unit/pages/settings/AgentsPageTest.tsx

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {render} from '@testing-library/react-native';
22
import React from 'react';
3+
import {usePersonalDetails} from '@components/OnyxListItemProvider';
34
import useOnyx from '@hooks/useOnyx';
45
import usePermissions from '@hooks/usePermissions';
56
import AgentsPage from '@pages/settings/Agents/AgentsPage';
@@ -36,11 +37,19 @@ jest.mock('@hooks/useDocumentTitle', () => jest.fn());
3637

3738
jest.mock('@hooks/useLazyAsset', () => ({
3839
useMemoizedLazyIllustrations: jest.fn(() => ({TvScreenRobot: 1, AiBot: 1})),
39-
useMemoizedLazyExpensifyIcons: jest.fn(() => ({Plus: 1, FallbackAvatar: 1})),
40+
useMemoizedLazyExpensifyIcons: jest.fn(() => ({Plus: 1})),
4041
}));
4142

4243
jest.mock('@hooks/useOnyx', () => jest.fn(() => [undefined, {status: 'loaded'}]));
4344

45+
jest.mock('@components/OnyxListItemProvider', () => ({
46+
usePersonalDetails: jest.fn(() => ({})),
47+
useSession: jest.fn(() => ({})),
48+
usePolicyCategories: jest.fn(() => ({})),
49+
usePolicyTags: jest.fn(() => ({})),
50+
useAllReportsTransactionsAndViolations: jest.fn(() => ({})),
51+
}));
52+
4453
jest.mock('@libs/Navigation/Navigation', () => ({
4554
goBack: jest.fn(),
4655
}));
@@ -103,12 +112,14 @@ jest.mock('@pages/ErrorPage/NotFoundPage', () => {
103112
const mockUsePermissions = jest.mocked(usePermissions);
104113
const mockOpenAgentsPage = jest.mocked(openAgentsPage);
105114
const mockUseOnyx = jest.mocked(useOnyx);
115+
const mockUsePersonalDetails = jest.mocked(usePersonalDetails);
106116

107117
describe('AgentsPage', () => {
108118
beforeEach(() => {
109119
jest.clearAllMocks();
110120
mockUsePermissions.mockReturnValue({isBetaEnabled: () => true});
111121
mockUseOnyx.mockReturnValue([undefined, {status: 'loaded'}]);
122+
mockUsePersonalDetails.mockReturnValue({});
112123
});
113124

114125
it('renders page content when customAgent beta is enabled', () => {
@@ -155,21 +166,16 @@ describe('AgentsPage', () => {
155166
if (key === ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT) {
156167
return [{[`${ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT}${TEST_ACCOUNT_ID}`]: {prompt: 'Test prompt'}}, {status: 'loaded'}];
157168
}
158-
if (key === ONYXKEYS.PERSONAL_DETAILS_LIST) {
159-
return [
160-
{
161-
[TEST_ACCOUNT_ID]: {
162-
accountID: TEST_ACCOUNT_ID,
163-
displayName: 'Test Agent',
164-
login: 'agent@example.com',
165-
avatar: undefined,
166-
},
167-
},
168-
{status: 'loaded'},
169-
];
170-
}
171169
return [undefined, {status: 'loaded'}];
172170
});
171+
mockUsePersonalDetails.mockReturnValue({
172+
[TEST_ACCOUNT_ID]: {
173+
accountID: TEST_ACCOUNT_ID,
174+
displayName: 'Test Agent',
175+
login: 'agent@example.com',
176+
avatar: undefined,
177+
},
178+
});
173179

174180
const {toJSON} = render(<AgentsPage />);
175181
const output = JSON.stringify(toJSON());
@@ -184,12 +190,10 @@ describe('AgentsPage', () => {
184190
if (key === ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT) {
185191
return [{[`${ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT}${TEST_ACCOUNT_ID}`]: {prompt: 'Test prompt'}}, {status: 'loaded'}];
186192
}
187-
// personalDetailsList has no entry for TEST_ACCOUNT_ID
188-
if (key === ONYXKEYS.PERSONAL_DETAILS_LIST) {
189-
return [{}, {status: 'loaded'}];
190-
}
191193
return [undefined, {status: 'loaded'}];
192194
});
195+
// personalDetailsList has no entry for TEST_ACCOUNT_ID
196+
mockUsePersonalDetails.mockReturnValue({});
193197

194198
const {toJSON} = render(<AgentsPage />);
195199

0 commit comments

Comments
 (0)