Skip to content

Commit 9f30342

Browse files
committed
Merge branch 'master' of github.com:binary-com/deriv-app into upm_passkeys_add
2 parents 9b171af + 2aac4cf commit 9f30342

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+774
-37
lines changed

package-lock.json

Lines changed: 7 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/api/src/hooks/p2p/entity/advertiser/p2p-advertiser/useAdvertiserInfo.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ const useAdvertiserInfo = (id?: string) => {
2222
is_listed,
2323
is_online,
2424
show_name,
25-
created_time,
2625
} = advertiser_info;
2726

2827
return {
@@ -43,8 +42,6 @@ const useAdvertiserInfo = (id?: string) => {
4342
is_online: Boolean(is_online),
4443
/** When true, the advertiser's real name will be displayed on to other users on adverts and orders. */
4544
show_name: Boolean(show_name),
46-
/** The epoch time that the client became an advertiser. */
47-
created_time: new Date(created_time),
4845
};
4946
}, [data?.p2p_advertiser_info]);
5047

packages/p2p-v2/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"start": "rimraf dist && npm run test && npm run serve"
1313
},
1414
"dependencies": {
15+
"@deriv-com/ui": "0.0.1-beta.5",
1516
"@deriv/api": "^1.0.0",
1617
"@deriv/integration": "^1.0.0",
1718
"@deriv/react-joyride": "^2.6.2",
@@ -24,6 +25,7 @@
2425
"react-dom": "^17.0.2",
2526
"react-i18next": "^11.11.0",
2627
"react-router-dom": "^5.2.0",
28+
"react-simple-star-rating": "4.0.4",
2729
"usehooks-ts": "^2.7.0"
2830
},
2931
"devDependencies": {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
.p2p-v2-advertiser-name {
2+
display: grid;
3+
grid-gap: 1.6rem;
4+
grid-template-columns: min-content auto max-content;
5+
6+
&__details {
7+
display: flex;
8+
flex-direction: column;
9+
justify-content: center;
10+
gap: 0.4rem;
11+
}
12+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import React from 'react';
2+
import { Avatar } from '../Avatar';
3+
import { useAdvertiserStats, useDevice } from '../../hooks';
4+
import AdvertiserNameStats from './AdvertiserNameStats';
5+
import AdvertiserNameBadges from './AdvertiserNameBadges';
6+
import AdvertiserNameToggle from './AdvertiserNameToggle';
7+
import { Text } from '@deriv-com/ui/dist/components/Text';
8+
import './AdvertiserName.scss';
9+
10+
const AdvertiserName = () => {
11+
const { data: advertiserStats, isLoading } = useAdvertiserStats();
12+
const { isDesktop } = useDevice();
13+
14+
if (isLoading || !advertiserStats) return <h1>Loading...</h1>;
15+
16+
return (
17+
<div className='p2p-v2-advertiser-name'>
18+
<Avatar name={advertiserStats.name || ''} />
19+
<div className='p2p-v2-advertiser-name__details'>
20+
<Text size='md' weight='bold'>
21+
{advertiserStats.name}{' '}
22+
{advertiserStats.show_name && (
23+
<Text color='less-prominent' size='sm'>
24+
({advertiserStats.fullName})
25+
</Text>
26+
)}
27+
</Text>
28+
<AdvertiserNameStats />
29+
<AdvertiserNameBadges />
30+
</div>
31+
{isDesktop && <AdvertiserNameToggle />}
32+
</div>
33+
);
34+
};
35+
AdvertiserName.displayName = 'AdvertiserName';
36+
37+
export default AdvertiserName;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.p2p-v2-advertiser-name-badges {
2+
display: flex;
3+
gap: 0.4rem;
4+
padding: 0.4rem 0;
5+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import React from 'react';
2+
import { useAdvertiserStats } from '../../hooks';
3+
import { Badge } from '../Badge';
4+
import './AdvertiserNameBadges.scss';
5+
6+
/**
7+
* This component is used to show an advertiser's badge, for instance:
8+
* +100 Trades, ID verified, Address not verified, etc
9+
*
10+
* Use cases are usually in My Profile page and Advertiser page used under the advertiser's name
11+
*/
12+
const AdvertiserNameBadges = () => {
13+
const { data: advertiserStats, isLoading } = useAdvertiserStats();
14+
15+
if (isLoading || !advertiserStats) return <h1>Loading...</h1>;
16+
17+
const { isAddressVerified, isIdentityVerified, totalOrders } = advertiserStats;
18+
19+
return (
20+
<div className='p2p-v2-advertiser-name-badges'>
21+
{totalOrders >= 100 && <Badge label='100+' status='trades' variant='warning' />}
22+
<Badge
23+
label='ID'
24+
status={isIdentityVerified ? 'verified' : 'not verified'}
25+
variant={isIdentityVerified ? 'success' : 'general'}
26+
/>
27+
<Badge
28+
label='Address'
29+
status={isAddressVerified ? 'verified' : 'not verified'}
30+
variant={isAddressVerified ? 'success' : 'general'}
31+
/>
32+
</div>
33+
);
34+
};
35+
AdvertiserNameBadges.displayName = 'AdvertiserNameBadges';
36+
37+
export default AdvertiserNameBadges;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
.p2p-v2-advertiser-name-stats {
2+
display: flex;
3+
align-items: center;
4+
5+
@include mobile {
6+
flex-direction: column;
7+
align-items: flex-start;
8+
justify-content: center;
9+
gap: 2rem;
10+
}
11+
12+
& div {
13+
display: flex;
14+
align-items: center;
15+
gap: 0.8rem;
16+
padding: 0 0.8rem;
17+
border-left: 1px solid #f2f3f4;
18+
19+
@include mobile {
20+
border-left: none;
21+
padding: 0;
22+
}
23+
24+
&:first-child {
25+
padding-left: 0;
26+
padding-right: 0.8rem;
27+
border-left: none;
28+
}
29+
}
30+
31+
&__rating {
32+
display: flex;
33+
gap: 0.5rem;
34+
}
35+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import React from 'react';
2+
import { useAdvertiserStats, useDevice } from '../../hooks';
3+
import { StarRating } from '../StarRating';
4+
import ThumbUpIcon from '../../public/ic-thumb-up.svg';
5+
import BlockedUserOutlineIcon from '../../public/ic-user-blocked-outline.svg';
6+
import { Text } from '@deriv-com/ui/dist/components/Text';
7+
import './AdvertiserNameStats.scss';
8+
9+
/**
10+
* This component is to show an advertiser's stats, in UI its commonly used under an advertiser's name
11+
* Example:
12+
* Joined 2d | Not rated yet | x x x x x (5 ratings)
13+
*
14+
* Use cases are to show this in My Profile and Advertiser page
15+
*/
16+
const AdvertiserNameStats = () => {
17+
const { data: advertiserStats, isLoading } = useAdvertiserStats();
18+
const { isMobile } = useDevice();
19+
20+
// TODO: Use Skeleton loader here
21+
if (isLoading || !advertiserStats) return <h1>Loading...</h1>;
22+
23+
const { blocked_by_count, daysSinceJoined, rating_average, rating_count, recommended_average } = advertiserStats;
24+
25+
return (
26+
<div className='p2p-v2-advertiser-name-stats'>
27+
<div>
28+
<Text color='less-prominent' size='sm'>
29+
Joined {daysSinceJoined}d
30+
</Text>
31+
</div>
32+
{!rating_average && (
33+
<div>
34+
<Text color='less-prominent' size='sm'>
35+
Not rated yet
36+
</Text>
37+
</div>
38+
)}
39+
{rating_average && (
40+
<>
41+
<div>
42+
<div className='p2p-v2-advertiser-name-stats__rating'>
43+
{isMobile && (
44+
<Text color='less-prominent' size='sm'>
45+
({rating_average})
46+
</Text>
47+
)}
48+
<StarRating ratingValue={rating_average} />
49+
<Text color='less-prominent' size='sm'>
50+
({rating_count} ratings)
51+
</Text>
52+
</div>
53+
</div>
54+
<div>
55+
<ThumbUpIcon />
56+
<Text color='less-prominent' size='sm'>
57+
{recommended_average || 0}%
58+
</Text>
59+
</div>
60+
</>
61+
)}
62+
<div>
63+
<BlockedUserOutlineIcon />
64+
<Text color='less-prominent' size='sm'>
65+
{blocked_by_count}
66+
</Text>
67+
</div>
68+
</div>
69+
);
70+
};
71+
AdvertiserNameStats.displayName = 'AdvertiserNameStats';
72+
73+
export default AdvertiserNameStats;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
.p2p-v2-advertiser-name-toggle {
2+
display: flex;
3+
gap: 0.8rem;
4+
5+
@include mobile {
6+
justify-content: space-between;
7+
}
8+
9+
&__label {
10+
display: flex;
11+
flex-direction: column;
12+
13+
&-real-name {
14+
font-size: 1rem;
15+
}
16+
}
17+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import React, { memo, useEffect, useState } from 'react';
2+
import { p2p } from '@deriv/api';
3+
import { Text } from '@deriv-com/ui/dist/components/Text';
4+
import { useAdvertiserStats } from '../../hooks';
5+
import { ToggleSwitch } from '../ToggleSwitch';
6+
import './AdvertiserNameToggle.scss';
7+
8+
type TAdvertiserNameToggle = {
9+
onToggle?: (shouldShowRealName: boolean) => void;
10+
};
11+
const AdvertiserNameToggle = memo(({ onToggle }: TAdvertiserNameToggle) => {
12+
const { data: advertiserInfo } = useAdvertiserStats();
13+
const [shouldShowRealName, setShouldShowRealName] = useState(false);
14+
const { mutate: advertiserUpdate } = p2p.advertiser.useUpdate();
15+
16+
useEffect(() => {
17+
setShouldShowRealName(advertiserInfo?.show_name || false);
18+
}, [advertiserInfo?.show_name]);
19+
20+
const onToggleShowRealName = () => {
21+
advertiserUpdate({
22+
show_name: !shouldShowRealName ? 1 : 0,
23+
});
24+
setShouldShowRealName(!shouldShowRealName);
25+
onToggle?.(!shouldShowRealName);
26+
};
27+
28+
return (
29+
<div className='p2p-v2-advertiser-name-toggle'>
30+
<div className='p2p-v2-advertiser-name-toggle__label'>
31+
<Text lineHeight='lg' size='sm'>
32+
Show my real name
33+
</Text>
34+
<Text className='p2p-v2-advertiser-name-toggle__label-real-name' color='less-prominent' lineHeight='xs'>
35+
{advertiserInfo?.fullName}
36+
</Text>
37+
</div>
38+
<ToggleSwitch onChange={onToggleShowRealName} value={shouldShowRealName} />
39+
</div>
40+
);
41+
});
42+
AdvertiserNameToggle.displayName = 'AdvertiserNameToggle';
43+
44+
export default AdvertiserNameToggle;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default as AdvertiserName } from './AdvertiserName';
2+
export { default as AdvertiserNameToggle } from './AdvertiserNameToggle';
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
.p2p-v2-avatar {
2+
border-radius: 5rem;
3+
width: 6.4rem;
4+
height: 6.4rem;
5+
background-color: #ff444f;
6+
display: flex;
7+
align-items: center;
8+
justify-content: center;
9+
font-size: 2rem;
10+
color: #ffffff;
11+
line-height: 3rem;
12+
13+
@include mobile {
14+
width: 4.2rem;
15+
height: 4.2rem;
16+
font-size: 1.6rem;
17+
line-height: 1.8rem;
18+
}
19+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import React, { memo } from 'react';
2+
import './Avatar.scss';
3+
4+
type TAvatarProps = {
5+
name: string;
6+
};
7+
8+
export const getShortNickname = (nickname: string): string => nickname?.substring(0, 2).toUpperCase();
9+
10+
const Avatar = ({ name }: TAvatarProps) => {
11+
return <div className='p2p-v2-avatar'>{getShortNickname(name)}</div>;
12+
};
13+
14+
export default memo(Avatar);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as Avatar } from './Avatar';

0 commit comments

Comments
 (0)