@blocklet/ui-react 2.10.90 → 2.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/lib/@types/index.d.ts +1 -0
  2. package/lib/UserCenter/components/config-profile.js +1 -1
  3. package/lib/UserCenter/components/notification.js +1 -2
  4. package/lib/UserCenter/components/privacy.d.ts +1 -0
  5. package/lib/UserCenter/components/privacy.js +3 -0
  6. package/lib/UserCenter/components/settings.d.ts +1 -1
  7. package/lib/UserCenter/components/settings.js +20 -18
  8. package/lib/UserCenter/components/third-party-login/index.js +4 -3
  9. package/lib/UserCenter/components/user-center.d.ts +1 -1
  10. package/lib/UserCenter/components/user-center.js +192 -195
  11. package/lib/UserCenter/components/user-info/index.d.ts +1 -0
  12. package/lib/UserCenter/components/user-info/index.js +1 -0
  13. package/lib/UserCenter/components/user-info/switch-role.d.ts +7 -0
  14. package/lib/UserCenter/components/user-info/switch-role.js +43 -0
  15. package/lib/UserCenter/components/user-info/user-basic-info.d.ts +1 -2
  16. package/lib/UserCenter/components/user-info/user-basic-info.js +33 -85
  17. package/lib/UserCenter/libs/locales.d.ts +4 -0
  18. package/lib/UserCenter/libs/locales.js +6 -2
  19. package/lib/common/header-addons.js +8 -0
  20. package/lib/common/notification-addon.d.ts +13 -0
  21. package/lib/common/notification-addon.js +41 -0
  22. package/package.json +5 -5
  23. package/src/@types/index.ts +1 -0
  24. package/src/UserCenter/components/config-profile.tsx +3 -1
  25. package/src/UserCenter/components/notification.tsx +1 -2
  26. package/src/UserCenter/components/privacy.tsx +4 -0
  27. package/src/UserCenter/components/settings.tsx +27 -27
  28. package/src/UserCenter/components/third-party-login/index.tsx +10 -3
  29. package/src/UserCenter/components/user-center.tsx +195 -180
  30. package/src/UserCenter/components/user-info/index.tsx +1 -0
  31. package/src/UserCenter/components/user-info/switch-role.tsx +44 -0
  32. package/src/UserCenter/components/user-info/user-basic-info.tsx +33 -81
  33. package/src/UserCenter/libs/locales.ts +4 -0
  34. package/src/common/header-addons.jsx +10 -0
  35. package/src/common/notification-addon.jsx +49 -0
@@ -1,7 +1,7 @@
1
1
  import { useContext } from 'react';
2
- import { Box, CircularProgress, Typography } from '@mui/material';
2
+ import { Box, CircularProgress, Divider, Typography } from '@mui/material';
3
3
  import type { BoxProps } from '@mui/material';
4
- import { useCreation, useMemoizedFn, useMount, useRequest, useUpdateEffect } from 'ahooks';
4
+ import { useCreation, useMemoizedFn, useRequest } from 'ahooks';
5
5
  import pWaitFor from 'p-wait-for';
6
6
 
7
7
  import { SessionContext } from '@arcblock/did-connect/lib/Session';
@@ -15,14 +15,15 @@ import { translate } from '@arcblock/ux/lib/Locale/util';
15
15
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
16
16
  import { ErrorFallback } from '@arcblock/ux/lib/ErrorBoundary';
17
17
  import cloneDeep from 'lodash/cloneDeep';
18
- import { getQuery, withQuery } from 'ufo';
18
+ import { getQuery, withQuery, joinURL } from 'ufo';
19
19
  import type { AxiosError } from 'axios';
20
20
  import type { UserPublicInfo } from '@blocklet/js-sdk';
21
21
 
22
+ import { PROFILE_URL } from '@arcblock/ux/lib/Util/constant';
22
23
  import Footer from '../../Footer';
23
24
  import Header from '../../Header';
24
25
  import { translations } from '../libs/locales';
25
- import { UserInfo, UserBasicInfo } from './user-info';
26
+ import { UserInfo, UserBasicInfo, SwitchRole } from './user-info';
26
27
  import type { SessionContext as TSessionContext, User, UserCenterTab } from '../../@types';
27
28
  // @ts-ignore
28
29
  import { formatBlockletInfo, getLocalizedNavigation } from '../../blocklets';
@@ -37,7 +38,6 @@ export default function UserCenter({
37
38
  currentTab,
38
39
  contentProps = {},
39
40
  disableAutoRedirect = false,
40
- autoPopupSetting = false,
41
41
  hideFooter = false,
42
42
  headerProps = {},
43
43
  footerProps = {},
@@ -118,7 +118,7 @@ export default function UserCenter({
118
118
  }
119
119
  );
120
120
 
121
- const { confirmHolder, confirmApi } = useConfirm({
121
+ const { confirmHolder } = useConfirm({
122
122
  fullScreen: isMobile,
123
123
  sx: {
124
124
  '.MuiDialog-paper': {
@@ -150,21 +150,44 @@ export default function UserCenter({
150
150
  }
151
151
  }, []);
152
152
 
153
+ const defaultTabs = useCreation((): any => {
154
+ const tabs: any = [
155
+ {
156
+ label: t('common.profile'),
157
+ protected: false,
158
+ url: joinURL(PROFILE_URL, '/profile'),
159
+ },
160
+ ];
161
+ if (isMyself) {
162
+ tabs.push({
163
+ label: t('common.setting'),
164
+ protected: true,
165
+ isPrivate: true,
166
+ url: joinURL(PROFILE_URL, '/settings'),
167
+ });
168
+ }
169
+ return tabs;
170
+ }, [isMyself]);
171
+
153
172
  const userCenterTabs = useCreation<UserCenterTab[]>(() => {
154
173
  const menus = formattedBlocklet?.navigation?.userCenter || [];
155
174
  const localizedMenus = getLocalizedNavigation(menus, locale) || [];
156
- return localizedMenus.map((x: any) => {
157
- const value = x._rawLink ?? x.link;
175
+ const allMenus = localizedMenus.concat(defaultTabs);
176
+ return allMenus
177
+ .map((x: any) => {
178
+ const value = x._rawLink ?? x.link ?? x.url;
158
179
 
159
- return {
160
- value,
161
- label: x.title,
162
- url: x.link,
163
- protected: privacyState?.data?.[value] ?? false,
164
- // icon: x.icon,
165
- };
166
- });
167
- }, [formattedBlocklet, userState.data, privacyState?.data, locale]);
180
+ return {
181
+ value,
182
+ label: x.title || x.label,
183
+ url: x.link || x.url,
184
+ protected: privacyState?.data?.[value] ?? false,
185
+ isPrivate: x.isPrivate,
186
+ // icon: x.icon,
187
+ };
188
+ })
189
+ .filter((x: any) => isMyself || !x.isPrivate);
190
+ }, [formattedBlocklet, userState.data, privacyState?.data, locale, defaultTabs, isMyself]);
168
191
 
169
192
  const currentActiveTab = useCreation(() => {
170
193
  return userCenterTabs.find((x) => x.value === currentTab);
@@ -199,27 +222,59 @@ export default function UserCenter({
199
222
  );
200
223
  }, [userState.data, userCenterTabs, privacyState.data, privacyState.runAsync]);
201
224
 
202
- const openSettings = useMemoizedFn(() => {
203
- confirmApi.open({
204
- title: t('settings'),
205
- content: settingContent,
206
- showCancelButton: false,
207
- confirmButtonText: t('done'),
208
- onConfirm: confirmApi.close,
209
- });
210
- });
225
+ const isSettingTab = useCreation(() => {
226
+ return currentActiveTab && currentActiveTab?.value === joinURL(PROFILE_URL, '/settings');
227
+ }, [currentActiveTab]);
211
228
 
212
- useUpdateEffect(() => {
213
- confirmApi.update({
214
- content: settingContent,
215
- });
216
- }, [settingContent]);
229
+ const isProfileTab = useCreation(() => {
230
+ return currentActiveTab && currentActiveTab?.value === joinURL(PROFILE_URL, '/profile');
231
+ }, [currentActiveTab]);
217
232
 
218
- useMount(() => {
219
- if (autoPopupSetting) {
220
- openSettings();
233
+ const renderDefaultTab = useCreation(() => {
234
+ if (isProfileTab) {
235
+ return (
236
+ <Box
237
+ sx={{
238
+ width: {
239
+ sx: '100%',
240
+ md: 420,
241
+ },
242
+ maxWidth: '100%',
243
+ position: 'relative',
244
+ }}>
245
+ <Box
246
+ sx={{
247
+ display: 'flex',
248
+ flexDirection: 'column',
249
+ gap: 2.5,
250
+ position: {
251
+ xs: 'static',
252
+ md: stickySidebar ? 'sticky' : 'static',
253
+ },
254
+ top: (theme) => (stickySidebar ? theme.spacing(3) : 'unset'),
255
+ }}>
256
+ <Box>
257
+ <Box display="flex" justifyContent="space-between">
258
+ <Typography sx={{ fontWeight: 600, mb: 1.5 }}>{isMyself ? t('myInfo') : t('hisInfo')}</Typography>
259
+ {isMyself ? <SwitchRole user={userState.data as User} switchPassport={session.switchPassport} /> : null}
260
+ </Box>
261
+ <UserInfo user={userState.data as User} isMySelf={isMyself} />
262
+ </Box>
263
+ {isMyself ? (
264
+ <Box>
265
+ <Typography sx={{ fontWeight: 600, mb: 1.5 }}>{t('passport')}</Typography>
266
+ <Passport user={userState.data as User} />
267
+ </Box>
268
+ ) : null}
269
+ </Box>
270
+ </Box>
271
+ );
221
272
  }
222
- });
273
+ if (isSettingTab && isMyself) {
274
+ return settingContent;
275
+ }
276
+ return null;
277
+ }, [isSettingTab, isProfileTab, userState, isMyself, stickySidebar, settingContent]);
223
278
 
224
279
  const content = useCreation(() => {
225
280
  if (userState.loading || session.loading) {
@@ -274,165 +329,126 @@ export default function UserCenter({
274
329
  }
275
330
 
276
331
  return (
277
- <>
278
- <Box
279
- sx={[
280
- {
281
- flex: {
282
- xs: 'revert',
283
- md: 1,
284
- },
285
- overflow: 'hidden',
332
+ <Box
333
+ sx={[
334
+ {
335
+ flex: {
336
+ xs: 'revert',
337
+ md: 1,
286
338
  },
287
- ]}>
288
- {userState?.data?.fullName ? (
289
- <Typography
290
- variant="h4"
291
- sx={{
292
- py: 1.5,
293
- fontSize: '18px !important',
294
- fontWeight: 700,
295
- lineHeight: 1.5,
296
- display: {
297
- xs: 'none',
298
- md: 'block',
299
- },
300
- }}>
301
- {userState.data.fullName}
302
- </Typography>
303
- ) : null}
304
- <UserBasicInfo
305
- isMyself={isMyself}
306
- switchPassport={session.switchPassport}
307
- switchProfile={session.switchProfile}
308
- openSettings={openSettings}
309
- user={userState.data as User}
310
- showFullDid={false}
311
- sx={{
312
- display: {
313
- md: 'none',
314
- xs: 'block',
315
- },
316
- mb: 1.5,
317
- }}
318
- />
319
- {userCenterTabs.length > 0 && currentTab ? (
320
- <Box
321
- sx={{
322
- overflow: 'auto',
323
- padding: '1px',
324
- }}>
325
- <Tabs
326
- variant="line"
327
- tabs={userCenterTabs}
328
- current={currentTab}
329
- onChange={handleChangeTab}
330
- sx={{ mb: 1.5 }}
331
- />
332
- {!privacyState.data || privacyState.loading ? (
333
- <Box
334
- sx={{
335
- height: '100%',
336
- minWidth: '160px',
337
- minHeight: '160px',
338
- display: 'flex',
339
- justifyContent: 'center',
340
- alignItems: 'center',
341
- }}>
342
- <CircularProgress sx={{ color: colors.primary100 }} />
343
- </Box>
344
- ) : (
345
- // eslint-disable-next-line react/jsx-no-useless-fragment
346
- <>
347
- {currentActiveTab?.protected && !isMyself ? (
348
- <Box>
349
- <Empty>{t('underProtected')}</Empty>
350
- </Box>
351
- ) : (
352
- // eslint-disable-next-line react/jsx-no-useless-fragment
353
- <>{children && <Box {...contentProps}>{children}</Box>}</>
354
- )}
355
- </>
356
- )}
357
- </Box>
358
- ) : null}
359
- {userCenterTabs.length === 0 ? (
360
- <Box
361
- sx={{
362
- display: {
363
- xs: isMyself ? 'none' : 'block',
364
- md: 'block',
365
- },
366
- py: 3,
367
- }}>
368
- <Empty>{t('emptyContent')}</Empty>
369
- </Box>
370
- ) : null}
371
- </Box>
372
- <Box
339
+ overflow: 'hidden',
340
+ },
341
+ ]}>
342
+ <UserBasicInfo
343
+ isMyself={isMyself}
344
+ switchPassport={session.switchPassport}
345
+ switchProfile={session.switchProfile}
346
+ user={userState.data as User}
347
+ showFullDid={false}
373
348
  sx={{
374
- display: {
375
- xs: 'none',
376
- md: 'block',
377
- },
378
- width: '1px',
379
- my: -3,
380
- backgroundColor: colors.strokeSep,
349
+ display: 'flex',
350
+ gap: 3,
351
+ mt: 2,
381
352
  }}
382
353
  />
383
- <Box
384
- sx={{
385
- width: {
386
- sx: '100%',
387
- md: 420,
388
- },
389
- maxWidth: '100%',
390
- position: 'relative',
391
- }}>
354
+ <Divider sx={{ mt: 3, mb: 3 }} />
355
+ {userCenterTabs.length > 0 && currentTab ? (
392
356
  <Box
357
+ display={isMobile ? 'block' : 'flex'}
358
+ gap={2}
393
359
  sx={{
394
- display: 'flex',
395
- flexDirection: 'column',
396
- gap: 2.5,
397
- position: {
398
- xs: 'static',
399
- md: stickySidebar ? 'sticky' : 'static',
400
- },
401
- top: (theme) => (stickySidebar ? theme.spacing(3) : 'unset'),
360
+ overflow: 'auto',
361
+ padding: '1px',
402
362
  }}>
403
- <UserBasicInfo
404
- isMyself={isMyself}
405
- switchPassport={session.switchPassport}
406
- switchProfile={session.switchProfile}
407
- openSettings={openSettings}
408
- user={userState.data as User}
363
+ <Tabs
364
+ orientation={isMobile ? 'horizontal' : 'vertical'}
365
+ variant="line"
366
+ tabs={userCenterTabs}
367
+ current={currentTab}
368
+ onChange={handleChangeTab}
409
369
  sx={{
410
- display: {
411
- xs: 'none',
412
- md: 'block',
370
+ width: isMobile ? '100%' : 180,
371
+ '.MuiTabs-flexContainer': {
372
+ gap: 1.5,
373
+ '.MuiButtonBase-root': {
374
+ fontSize: 16,
375
+ },
376
+ '.MuiTab-root': {
377
+ display: 'block',
378
+ textAlign: 'left',
379
+ },
413
380
  },
414
381
  }}
415
382
  />
416
-
417
- <Box>
418
- <Typography sx={{ fontWeight: 600, mb: 1.5 }}>{isMyself ? t('myInfo') : t('hisInfo')}</Typography>
419
- <UserInfo user={userState.data as User} isMySelf={isMyself} />
420
- </Box>
421
- {isMyself ? (
422
- <Box>
423
- <Typography sx={{ fontWeight: 600, mb: 1.5 }}>{t('passport')}</Typography>
424
- <Passport user={userState.data as User} />
383
+ {!privacyState.data || privacyState.loading ? (
384
+ <Box
385
+ sx={{
386
+ height: '100%',
387
+ minWidth: '160px',
388
+ minHeight: '160px',
389
+ display: 'flex',
390
+ justifyContent: 'center',
391
+ alignItems: 'center',
392
+ }}>
393
+ <CircularProgress sx={{ color: colors.primary100 }} />
425
394
  </Box>
426
- ) : null}
395
+ ) : (
396
+ // eslint-disable-next-line react/jsx-no-useless-fragment
397
+ <Box sx={{ flex: 1 }}>
398
+ {currentActiveTab?.protected && !isMyself ? (
399
+ <Box>
400
+ <Empty>{t('underProtected')}</Empty>
401
+ </Box>
402
+ ) : (
403
+ // eslint-disable-next-line react/jsx-no-useless-fragment
404
+ <>{children ? <Box {...contentProps}>{children}</Box> : <>{renderDefaultTab}</>}</>
405
+ )}
406
+ </Box>
407
+ )}
427
408
  </Box>
428
- </Box>
429
- </>
409
+ ) : null}
410
+ {userCenterTabs.length === 0 ? (
411
+ <Box
412
+ sx={{
413
+ display: {
414
+ xs: isMyself ? 'none' : 'block',
415
+ md: 'block',
416
+ },
417
+ py: 3,
418
+ }}>
419
+ <Empty>{t('emptyContent')}</Empty>
420
+ </Box>
421
+ ) : null}
422
+ </Box>
430
423
  );
431
- }, [userState, userCenterTabs, isMyself, currentActiveTab, privacyState, currentTab, stickySidebar]);
424
+ }, [
425
+ userState,
426
+ userCenterTabs,
427
+ isMyself,
428
+ currentActiveTab,
429
+ privacyState,
430
+ currentTab,
431
+ stickySidebar,
432
+ renderDefaultTab,
433
+ ]);
434
+
435
+ // 如果当前URL指向的是 private tab需要重定向
436
+ const isPrivateActive = useCreation(() => {
437
+ if (isMyself) {
438
+ return false;
439
+ }
440
+ return currentActiveTab?.isPrivate;
441
+ }, [isMyself, currentActiveTab]);
432
442
 
433
- if (!disableAutoRedirect && !currentTab && formattedBlocklet?.navigation?.userCenter?.length > 0) {
443
+ // TODO 过滤 !mySelf 是的URL跳转
444
+ if (
445
+ (!disableAutoRedirect && !currentTab && formattedBlocklet?.navigation?.userCenter?.length > 0) ||
446
+ !currentActiveTab ||
447
+ isPrivateActive
448
+ ) {
434
449
  const firstUserCenterUrl = formattedBlocklet?.navigation?.userCenter[0]?.link;
435
- if (firstUserCenterUrl) {
450
+ const firstTab = userCenterTabs.find((x) => x.value === firstUserCenterUrl);
451
+ if (firstUserCenterUrl && !firstTab?.isPrivate) {
436
452
  window.location.replace(
437
453
  withQuery(firstUserCenterUrl, {
438
454
  did: isMyself ? undefined : currentDid,
@@ -445,12 +461,11 @@ export default function UserCenter({
445
461
  return (
446
462
  <Box
447
463
  sx={{
448
- backgroundColor: colors.backgroundsBgSubtitle,
449
464
  minHeight: '100vh',
450
465
  display: 'flex',
451
466
  flexDirection: 'column',
452
467
  }}>
453
- <Header bordered {...headerProps} />
468
+ <Header bordered {...headerProps} maxWidth="100%" />
454
469
  <Box
455
470
  flex={1}
456
471
  sx={{
@@ -1,3 +1,4 @@
1
1
  export { default as UserBasicInfo } from './user-basic-info';
2
2
  export { default as UserInfoItem } from './user-info-item';
3
3
  export { default as UserInfo } from './user-info';
4
+ export { default as SwitchRole } from './switch-role';
@@ -0,0 +1,44 @@
1
+ import { memo } from 'react';
2
+ import { Chip } from '@mui/material';
3
+ import { Icon } from '@iconify/react';
4
+ import { useCreation } from 'ahooks';
5
+ import SwapHorizRoundedIcon from '@iconify-icons/material-symbols/swap-horiz-rounded';
6
+ import { temp as colors } from '@arcblock/ux/lib/Colors';
7
+ import type { User } from '../../../@types';
8
+
9
+ function SwitchRole({ user, switchPassport }: { user: User; switchPassport: () => void }) {
10
+ const currentRole = useCreation(
11
+ () => (user?.passports || [])?.find((item) => item.name === user.role),
12
+ [user?.passports, user?.role]
13
+ );
14
+ return (
15
+ <Chip
16
+ label={currentRole?.title || user?.role || 'Guest'}
17
+ size="small"
18
+ variant="outlined"
19
+ sx={{
20
+ flexShrink: 0,
21
+ fontWeight: 'bold',
22
+ fontSize: '12px',
23
+ color: colors.textBase,
24
+ borderColor: colors.strokeBorderStrong,
25
+ backgroundColor: 'transparent',
26
+ textTransform: 'capitalize',
27
+ pr: 1,
28
+ pl: 0.5,
29
+ '&:hover': {
30
+ backgroundColor: 'rgba(0, 0, 0, 0.04)',
31
+ },
32
+ '&:active': {
33
+ boxShadow: 'none',
34
+ },
35
+ }}
36
+ clickable
37
+ deleteIcon={<Icon icon={SwapHorizRoundedIcon} color={colors.textBase} />}
38
+ onDelete={switchPassport}
39
+ onClick={switchPassport}
40
+ />
41
+ );
42
+ }
43
+
44
+ export default memo(SwitchRole);
@@ -1,13 +1,9 @@
1
- import { Box, Chip, CircularProgress, IconButton, Tooltip, Typography } from '@mui/material';
1
+ import { Box, CircularProgress, Tooltip, Typography } from '@mui/material';
2
2
  import type { BoxProps } from '@mui/material';
3
- import { Icon } from '@iconify/react';
4
- import SwapHorizRoundedIcon from '@iconify-icons/material-symbols/swap-horiz-rounded';
5
- import SettingsOutlineRoundedIcon from '@iconify-icons/material-symbols/settings-outline-rounded';
6
3
  import Avatar from '@arcblock/ux/lib/Avatar';
7
- import { temp as colors } from '@arcblock/ux/lib/Colors';
8
4
  import { useTheme } from '@arcblock/ux/lib/Theme';
9
5
  import DID from '@arcblock/ux/lib/DID';
10
- import { useCreation, useMemoizedFn } from 'ahooks';
6
+ import { useMemoizedFn } from 'ahooks';
11
7
  import { translate } from '@arcblock/ux/lib/Locale/util';
12
8
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
13
9
  import noop from 'lodash/noop';
@@ -22,6 +18,7 @@ import { SessionContext as TSessionContext } from '../../../@types';
22
18
  import { translations } from '../../libs/locales';
23
19
  import type { User } from '../../../@types';
24
20
  import { formatAxiosError } from '../../libs/utils';
21
+ import SwitchRole from './switch-role';
25
22
 
26
23
  export default function UserBasicInfo({
27
24
  user,
@@ -29,7 +26,6 @@ export default function UserBasicInfo({
29
26
  showFullDid = true,
30
27
  switchPassport,
31
28
  switchProfile,
32
- openSettings,
33
29
  ...rest
34
30
  }: {
35
31
  user: User;
@@ -37,7 +33,6 @@ export default function UserBasicInfo({
37
33
  showFullDid?: boolean;
38
34
  switchPassport: () => void;
39
35
  switchProfile: () => void;
40
- openSettings: () => void;
41
36
  } & BoxProps) {
42
37
  const { locale } = useLocaleContext();
43
38
  const { session } = useContext<TSessionContext>(SessionContext);
@@ -46,10 +41,7 @@ export default function UserBasicInfo({
46
41
  const t = useMemoizedFn((key, data = {}) => {
47
42
  return translate(translations, key, locale, 'en', data);
48
43
  });
49
- const currentRole = useCreation(
50
- () => (user?.passports || [])?.find((item) => item.name === user.role),
51
- [user?.passports, user?.role]
52
- );
44
+
53
45
  const theme = useTheme();
54
46
 
55
47
  const isSmallView = theme.breakpoints.down('md');
@@ -91,7 +83,6 @@ export default function UserBasicInfo({
91
83
  backgroundColor: '#fff',
92
84
  position: 'relative',
93
85
  overflow: 'hidden',
94
- mb: 1.5,
95
86
  ...(isMyself
96
87
  ? {
97
88
  cursor: 'pointer',
@@ -114,75 +105,36 @@ export default function UserBasicInfo({
114
105
  }}
115
106
  onClick={isMyself ? switchProfile : noop}
116
107
  />
117
- <Typography
118
- variant="h6"
119
- sx={{
120
- fontWeight: 'bold',
121
- display: 'flex',
122
- alignItems: 'center',
123
- gap: 1,
124
- fontSize: '24px !important',
125
- }}>
126
- {user?.fullName}
127
- {isMyself ? (
128
- <>
129
- <Chip
130
- label={currentRole?.title || user?.role || 'Guest'}
131
- size="small"
132
- variant="outlined"
133
- sx={{
134
- flexShrink: 0,
135
- fontWeight: 'bold',
136
- fontSize: '12px',
137
- color: colors.textBase,
138
- borderColor: colors.strokeBorderStrong,
139
- backgroundColor: 'transparent',
140
- textTransform: 'capitalize',
141
- pr: 1,
142
- pl: 0.5,
143
- '&:hover': {
144
- backgroundColor: 'rgba(0, 0, 0, 0.04)',
145
- },
146
- '&:active': {
147
- boxShadow: 'none',
148
- },
149
- }}
150
- clickable
151
- deleteIcon={<Icon icon={SwapHorizRoundedIcon} color={colors.textBase} />}
152
- onDelete={switchPassport}
153
- onClick={switchPassport}
154
- />
155
- {!isEmpty(user.url) && (
156
- <Tooltip
157
- title={!loading && translate(translations, 'refreshProfile.title', locale)}
158
- sx={{ display: 'flex', alignItems: 'center' }}>
159
- {loading ? (
160
- <CircularProgress size="16px" sx={{ color: theme?.colors?.primary, ml: 0.5 }} />
161
- ) : (
162
- <RefreshOutlinedIcon onClick={refreshProfile} />
163
- )}
164
- </Tooltip>
165
- )}
166
- </>
167
- ) : null}
168
- </Typography>
169
- <DID did={user.did} showQrcode copyable compact={!showFullDid} responsive={!showFullDid} locale={locale} />
170
- {isMyself ? (
171
- <IconButton
108
+ <Box>
109
+ <Typography
110
+ variant="h6"
172
111
  sx={{
173
- borderRadius: 2,
174
- color: colors.textBase,
175
- backgroundColor: 'white',
176
- border: `1px solid ${colors.strokeBorderBase}`,
177
- position: 'absolute',
178
- top: 0,
179
- right: 0,
180
- }}
181
- disableFocusRipple
182
- onClick={openSettings}>
183
- <Icon icon={SettingsOutlineRoundedIcon} />
184
- </IconButton>
185
- ) : null}
112
+ fontWeight: 'bold',
113
+ display: 'flex',
114
+ alignItems: 'center',
115
+ gap: 1,
116
+ fontSize: '24px !important',
117
+ }}>
118
+ {user?.fullName}
119
+ {isMyself ? (
120
+ <>
121
+ <SwitchRole user={user} switchPassport={switchPassport} />
122
+ {!isEmpty(user.url) && (
123
+ <Tooltip
124
+ title={!loading && translate(translations, 'refreshProfile.title', locale)}
125
+ sx={{ display: 'flex', alignItems: 'center' }}>
126
+ {loading ? (
127
+ <CircularProgress size="16px" sx={{ color: theme?.colors?.primary, ml: 0.5 }} />
128
+ ) : (
129
+ <RefreshOutlinedIcon onClick={refreshProfile} />
130
+ )}
131
+ </Tooltip>
132
+ )}
133
+ </>
134
+ ) : null}
135
+ </Typography>
136
+ <DID did={user.did} showQrcode copyable compact={!showFullDid} responsive={!showFullDid} locale={locale} />
137
+ </Box>
186
138
  </Box>
187
139
  );
188
140
  }