Skip to content

Commit 0dcf072

Browse files
committed
create profile page and move edit icon
1 parent 065c3ac commit 0dcf072

File tree

2 files changed

+161
-0
lines changed

2 files changed

+161
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fragment UserProfile on User {
2+
...DisplayUser
3+
...UserForm
4+
}
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import { Edit } from '@mui/icons-material';
2+
import {
3+
Box,
4+
IconButton,
5+
Paper,
6+
Skeleton,
7+
Stack,
8+
Tooltip,
9+
Typography,
10+
} from '@mui/material';
11+
import { useInterval } from 'ahooks';
12+
import { DateTime } from 'luxon';
13+
import { useState } from 'react';
14+
import { RoleLabels } from '~/api/schema.graphql';
15+
import { canEditAny, labelsFrom } from '~/common';
16+
import { useDialog } from '~/components/Dialog';
17+
import {
18+
DisplaySimpleProperty,
19+
DisplaySimplePropertyProps,
20+
} from '~/components/DisplaySimpleProperty';
21+
import { PartnerListItemCard } from '~/components/PartnerListItemCard';
22+
import { EditUser } from '../../../Edit';
23+
import { UserProfileFragment } from './UserDetailProfile.graphql';
24+
25+
interface UserDetailProfileProps {
26+
user: UserProfileFragment;
27+
}
28+
29+
export const UserDetailProfile = ({ user }: UserDetailProfileProps) => {
30+
const [editUserState, editUser] = useDialog();
31+
32+
const canEditAnyFields = canEditAny(user);
33+
34+
return (
35+
<Box
36+
component={Paper}
37+
sx={(theme) => ({
38+
display: 'flex',
39+
justifyContent: 'space-between',
40+
width: theme.breakpoints.values.md,
41+
})}
42+
>
43+
<Stack
44+
sx={{
45+
p: 2,
46+
gap: 2,
47+
}}
48+
>
49+
<DisplayProperty
50+
label="Email"
51+
value={user.email.value}
52+
loading={!user}
53+
/>
54+
<DisplayProperty
55+
label="Title"
56+
value={user.title.value}
57+
loading={!user}
58+
/>
59+
<DisplayProperty
60+
label="Roles"
61+
value={labelsFrom(RoleLabels)(user.roles.value)}
62+
loading={!user}
63+
/>
64+
<DisplayProperty
65+
label="Local Time"
66+
value={
67+
user.timezone.value?.name ? (
68+
<LocalTime timezone={user.timezone.value.name} />
69+
) : null
70+
}
71+
loading={!user}
72+
/>
73+
<DisplayProperty
74+
label="Phone"
75+
value={user.phone.value}
76+
loading={!user}
77+
/>
78+
<DisplayProperty
79+
label="About"
80+
value={user.about.value}
81+
loading={!user}
82+
/>
83+
84+
{!!user.partners.items.length && (
85+
<>
86+
<Typography variant="h3">Partners</Typography>
87+
<Box sx={{ mt: 1 }}>
88+
{user.partners.items.map((item) => (
89+
<Box key={item.id} sx={{ mb: 2 }}>
90+
<PartnerListItemCard partner={item} />
91+
</Box>
92+
))}
93+
</Box>
94+
</>
95+
)}
96+
</Stack>
97+
<Box sx={{ p: 1 }}>
98+
{canEditAnyFields ? (
99+
<Tooltip title="Edit Person">
100+
<IconButton aria-label="edit person" onClick={editUser}>
101+
<Edit />
102+
</IconButton>
103+
</Tooltip>
104+
) : null}
105+
</Box>
106+
<EditUser user={user} {...editUserState} />
107+
</Box>
108+
);
109+
};
110+
111+
const LocalTime = ({ timezone }: { timezone?: string }) => {
112+
const now = useNow();
113+
const formatted = now.toLocaleString({
114+
timeZone: timezone,
115+
...DateTime.TIME_SIMPLE,
116+
timeZoneName: 'short',
117+
});
118+
return <>{formatted}</>;
119+
};
120+
121+
const useNow = (updateInterval = 1_000) => {
122+
const [now, setNow] = useState(() => DateTime.local());
123+
useInterval(() => {
124+
setNow(DateTime.local());
125+
}, updateInterval);
126+
return now;
127+
};
128+
129+
const DisplayProperty = (props: DisplaySimplePropertyProps) =>
130+
!props.value && !props.loading ? null : (
131+
<DisplaySimpleProperty
132+
variant="body1"
133+
{...{ component: 'div' }}
134+
{...props}
135+
loading={
136+
props.loading ? (
137+
<>
138+
<Typography variant="body2">
139+
<Skeleton width="10%" />
140+
</Typography>
141+
<Typography variant="body1">
142+
<Skeleton width="40%" />
143+
</Typography>
144+
</>
145+
) : null
146+
}
147+
LabelProps={{
148+
color: 'textSecondary',
149+
variant: 'body2',
150+
...props.LabelProps,
151+
}}
152+
ValueProps={{
153+
color: 'textPrimary',
154+
...props.ValueProps,
155+
}}
156+
/>
157+
);

0 commit comments

Comments
 (0)