Skip to content

Commit 500ecb6

Browse files
committed
refactor(tsx): convert User view
1 parent 9f44215 commit 500ecb6

File tree

3 files changed

+187
-124
lines changed

3 files changed

+187
-124
lines changed

src/ui/services/user.js

Lines changed: 0 additions & 99 deletions
This file was deleted.

src/ui/services/user.ts

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import axios, { AxiosError, AxiosResponse } from 'axios';
2+
import { getCookie } from '../utils';
3+
4+
export interface UserData {
5+
username: string;
6+
email?: string;
7+
displayName?: string;
8+
title?: string;
9+
gitAccount?: string;
10+
admin?: boolean;
11+
}
12+
13+
type SetStateCallback<T> = (value: T | ((prevValue: T) => T)) => void;
14+
15+
const baseUrl = import.meta.env.VITE_API_URI
16+
? `${import.meta.env.VITE_API_URI}`
17+
: `${location.origin}`;
18+
19+
const config = {
20+
withCredentials: true,
21+
};
22+
23+
const getUser = async (
24+
setIsLoading?: SetStateCallback<boolean>,
25+
setData?: (userData: UserData) => void,
26+
setAuth?: SetStateCallback<boolean>,
27+
setIsError?: SetStateCallback<boolean>,
28+
id: string | null = null,
29+
): Promise<void> => {
30+
let url = `${baseUrl}/api/auth/profile`;
31+
if (id) {
32+
url = `${baseUrl}/api/v1/user/${id}`;
33+
}
34+
console.log(url);
35+
36+
try {
37+
const response: AxiosResponse<UserData> = await axios(url, config);
38+
const data = response.data;
39+
40+
if (setData) {
41+
setData(data);
42+
}
43+
if (setIsLoading) {
44+
setIsLoading(false);
45+
}
46+
} catch (error) {
47+
const axiosError = error as AxiosError;
48+
if (axiosError.response && axiosError.response.status === 401) {
49+
if (setAuth) {
50+
setAuth(false);
51+
}
52+
} else {
53+
if (setIsError) {
54+
setIsError(true);
55+
}
56+
}
57+
if (setIsLoading) {
58+
setIsLoading(false);
59+
}
60+
}
61+
};
62+
63+
const getUsers = async (
64+
setIsLoading: SetStateCallback<boolean>,
65+
setData: SetStateCallback<UserData[]>,
66+
setAuth: SetStateCallback<boolean>,
67+
setIsError: SetStateCallback<boolean>,
68+
query: Record<string, string> = {},
69+
): Promise<void> => {
70+
const url = new URL(`${baseUrl}/api/v1/user`);
71+
url.search = new URLSearchParams(query).toString();
72+
73+
setIsLoading(true);
74+
75+
try {
76+
const response: AxiosResponse<UserData[]> = await axios(url.toString(), {
77+
withCredentials: true,
78+
});
79+
const data = response.data;
80+
setData(data);
81+
setIsLoading(false);
82+
} catch (error) {
83+
setIsLoading(false);
84+
const axiosError = error as AxiosError;
85+
if (axiosError.response && axiosError.response.status === 401) {
86+
setAuth(false);
87+
} else {
88+
setIsError(true);
89+
}
90+
}
91+
};
92+
93+
const updateUser = async (data: UserData): Promise<void> => {
94+
console.log(data);
95+
const url = new URL(`${baseUrl}/api/auth/gitAccount`);
96+
97+
try {
98+
await axios.post(url.toString(), data, {
99+
withCredentials: true,
100+
headers: { 'X-CSRF-TOKEN': getCookie('csrf') },
101+
});
102+
} catch (error) {
103+
const axiosError = error as AxiosError;
104+
if (axiosError.response) {
105+
console.log((axiosError.response.data as any).message);
106+
}
107+
throw error;
108+
}
109+
};
110+
111+
const getUserLoggedIn = async (
112+
setIsLoading: SetStateCallback<boolean>,
113+
setIsAdmin: SetStateCallback<boolean>,
114+
setIsError: SetStateCallback<boolean>,
115+
setAuth: SetStateCallback<boolean>,
116+
): Promise<void> => {
117+
const url = new URL(`${baseUrl}/api/auth/me`);
118+
119+
try {
120+
const response: AxiosResponse<UserData> = await axios(url.toString(), {
121+
withCredentials: true,
122+
});
123+
const data = response.data;
124+
setIsLoading(false);
125+
setIsAdmin(data.admin || false);
126+
} catch (error) {
127+
setIsLoading(false);
128+
const axiosError = error as AxiosError;
129+
if (axiosError.response && axiosError.response.status === 401) {
130+
setAuth(false);
131+
} else {
132+
setIsError(true);
133+
}
134+
}
135+
};
136+
137+
export { getUser, getUsers, updateUser, getUserLoggedIn };

src/ui/views/User/User.jsx renamed to src/ui/views/User/User.tsx

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ import Card from '../../components/Card/Card';
66
import CardBody from '../../components/Card/CardBody';
77
import Button from '../../components/CustomButtons/Button';
88
import FormLabel from '@material-ui/core/FormLabel';
9-
import { getUser, updateUser, getUserLoggedIn } from '../../services/user';
9+
import { getUser, updateUser, getUserLoggedIn, UserData } from '../../services/user';
1010
import { makeStyles } from '@material-ui/core/styles';
1111

1212
import { LogoGithubIcon } from '@primer/octicons-react';
1313
import CloseRounded from '@material-ui/icons/CloseRounded';
1414
import { Check, Save } from '@material-ui/icons';
15-
import { TextField } from '@material-ui/core';
15+
import { TextField, Theme } from '@material-ui/core';
1616

17-
const useStyles = makeStyles((theme) => ({
17+
const useStyles = makeStyles((theme: Theme) => ({
1818
root: {
1919
'& .MuiTextField-root': {
2020
margin: theme.spacing(1),
@@ -23,56 +23,78 @@ const useStyles = makeStyles((theme) => ({
2323
},
2424
}));
2525

26-
export default function Dashboard() {
26+
export default function UserProfile(): React.ReactElement {
2727
const classes = useStyles();
28-
const [data, setData] = useState([]);
29-
const [auth, setAuth] = useState(true);
30-
const [isLoading, setIsLoading] = useState(true);
31-
const [isError, setIsError] = useState(false);
32-
const [isProfile, setIsProfile] = useState(false);
33-
const [isAdmin, setIsAdmin] = useState(false);
34-
const [gitAccount, setGitAccount] = useState('');
28+
const [data, setData] = useState<UserData | null>(null);
29+
const [auth, setAuth] = useState<boolean>(true);
30+
const [isLoading, setIsLoading] = useState<boolean>(true);
31+
const [isError, setIsError] = useState<boolean>(false);
32+
const [isProfile, setIsProfile] = useState<boolean>(false);
33+
const [isAdmin, setIsAdmin] = useState<boolean>(false);
34+
const [gitAccount, setGitAccount] = useState<string>('');
3535
const navigate = useNavigate();
36-
const { id } = useParams();
36+
const { id } = useParams<{ id?: string }>();
3737

3838
useEffect(() => {
3939
if (id == null) {
4040
setIsProfile(true);
4141
}
4242

4343
if (id) {
44-
getUser(setIsLoading, setData, setAuth, setIsError, id);
44+
getUser(
45+
setIsLoading,
46+
(userData: UserData) => {
47+
setData(userData);
48+
setGitAccount(userData.gitAccount || '');
49+
},
50+
setAuth,
51+
setIsError,
52+
id,
53+
);
4554
getUserLoggedIn(setIsLoading, setIsAdmin, setIsError, setAuth);
4655
} else {
4756
console.log('getting user data');
4857
setIsProfile(true);
49-
getUser(setIsLoading, setData, setAuth, setIsError);
58+
getUser(
59+
setIsLoading,
60+
(userData: UserData) => {
61+
setData(userData);
62+
setGitAccount(userData.gitAccount || '');
63+
},
64+
setAuth,
65+
setIsError,
66+
);
5067
}
51-
}, []);
68+
}, [id]);
5269

5370
if (isLoading) return <div>Loading...</div>;
5471
if (isError) return <div>Something went wrong ...</div>;
5572
if (!auth && window.location.pathname === '/dashboard/profile') {
5673
return <Navigate to='/login' />;
5774
}
75+
if (!data) return <div>No user data available</div>;
5876

59-
const updateProfile = async () => {
77+
const updateProfile = async (): Promise<void> => {
6078
try {
61-
data.gitAccount = escapeHTML(gitAccount);
62-
await updateUser(data);
79+
const updatedData = {
80+
...data,
81+
gitAccount: escapeHTML(gitAccount),
82+
};
83+
await updateUser(updatedData);
6384
navigate(`/dashboard/profile`);
6485
} catch {
6586
setIsError(true);
6687
}
6788
};
6889

69-
const UpdateButton = () => (
90+
const UpdateButton = (): React.ReactElement => (
7091
<Button variant='outlined' color='success' onClick={updateProfile}>
71-
<Save></Save>Update
92+
<Save />
93+
Update
7294
</Button>
7395
);
7496

75-
const escapeHTML = (str) => {
97+
const escapeHTML = (str: string): string => {
7698
return str
7799
.replace(/&/g, '&amp;')
78100
.replace(/</g, '&lt;')
@@ -104,7 +126,8 @@ export default function Dashboard() {
104126
width={'75px'}
105127
style={{ borderRadius: '5px' }}
106128
src={`https://github.com/${data.gitAccount}.png`}
107-
></img>
129+
alt={`${data.displayName}'s GitHub avatar`}
130+
/>
108131
</GridItem>
109132
)}
110133
<GridItem xs={2} sm={2} md={2}>
@@ -138,7 +161,7 @@ export default function Dashboard() {
138161
<Check fontSize='small' />
139162
</span>
140163
) : (
141-
<CloseRounded color='error'></CloseRounded>
164+
<CloseRounded color='error' />
142165
)}
143166
</GridItem>
144167
</GridContainer>
@@ -147,7 +170,7 @@ export default function Dashboard() {
147170
<hr style={{ opacity: 0.2 }} />
148171
<div style={{ marginTop: '25px' }}>
149172
<FormLabel component='legend'>
150-
What is your <LogoGithubIcon></LogoGithubIcon> username?
173+
What is your <LogoGithubIcon /> username?
151174
</FormLabel>
152175
<div style={{ textAlign: 'right' }}>
153176
<TextField
@@ -156,7 +179,9 @@ export default function Dashboard() {
156179
variant='outlined'
157180
placeholder='Enter a new GitHub username...'
158181
value={gitAccount}
159-
onChange={(e) => setGitAccount(e.target.value)}
182+
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
183+
setGitAccount(e.target.value)
184+
}
160185
/>
161186
<UpdateButton />
162187
</div>

0 commit comments

Comments
 (0)