Skip to content

Commit 3f6a059

Browse files
committed
feat: implement ClientAxios for API requests and update EditUsernameModal to use it
1 parent 44af478 commit 3f6a059

File tree

3 files changed

+76
-36
lines changed

3 files changed

+76
-36
lines changed

web/src/lib/axios/ClientAxios.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import axios from 'axios';
2+
import { getTokenLocal } from './token.utils';
3+
export const baseApiURL = process.env.NEXT_PUBLIC_API_URL;
4+
5+
const ClientAxios = axios.create({
6+
baseURL: baseApiURL,
7+
withCredentials: true,
8+
});
9+
10+
// Add a request interceptor to add the token to the request
11+
ClientAxios.interceptors.request.use(
12+
(config) => {
13+
const token = getTokenLocal();
14+
15+
config.headers.authorization = `Bearer ${token}`;
16+
17+
return config;
18+
},
19+
(error) => {
20+
return Promise.reject(error);
21+
},
22+
);
23+
24+
export default ClientAxios;

web/src/modules/shared/components/client/GenericModal.tsx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,19 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
55
import { Dialog, Transition } from '@headlessui/react';
66
import { Fragment } from 'react';
77

8-
export default function GenericModal({
9-
isOpen,
10-
setIsOpen,
11-
title,
12-
children,
13-
}: {
8+
interface GenericModalProps {
149
isOpen: boolean;
1510
setIsOpen?: (isOpen: boolean) => void;
1611
title: string;
1712
children?: React.ReactNode | React.ReactNode[] | string;
18-
}) {
13+
}
14+
15+
const GenericModal = ({
16+
isOpen,
17+
setIsOpen,
18+
title,
19+
children,
20+
}: GenericModalProps) => {
1921
return (
2022
<Transition appear show={isOpen} as={Fragment}>
2123
<Dialog
@@ -80,4 +82,6 @@ export default function GenericModal({
8082
</Dialog>
8183
</Transition>
8284
);
83-
}
85+
};
86+
87+
export default GenericModal;

web/src/modules/shared/components/layout/EditUsernameModal.tsx

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,45 @@
11
'use client';
22
import { faPen } from '@fortawesome/free-solid-svg-icons';
3-
import { LoggedUserData } from '@web/src/modules/auth/types/User';
43
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
5-
import axiosInstance from '@web/src/lib/axios';
4+
import ClientAxios from '@web/src/lib/axios/ClientAxios';
5+
import { LoggedUserData } from '@web/src/modules/auth/types/User';
66
import { AxiosError } from 'axios';
77
import { useState } from 'react';
8-
import GenericModal from '../client/GenericModal';
98
import { toast } from 'react-hot-toast';
9+
import GenericModal from '../client/GenericModal';
10+
import { SubmitHandler, useForm } from 'react-hook-form';
1011

11-
type EditUsernameModalProps = {
12+
interface EditUsernameModalProps {
1213
isOpen: boolean;
1314
setIsOpen: (value: boolean) => void;
1415
userData: LoggedUserData;
15-
};
16+
}
17+
18+
interface FormValues {
19+
username: string;
20+
}
1621

1722
export const EditUsernameModal = ({
1823
isOpen,
1924
setIsOpen,
2025
userData,
2126
}: EditUsernameModalProps) => {
22-
const [isLoading, setIsLoading] = useState(false);
27+
const {
28+
handleSubmit,
29+
formState: { isSubmitting, errors },
30+
register,
31+
} = useForm<FormValues>();
2332

24-
const onClick = async () => {
33+
const onSubmit: SubmitHandler<FormValues> = async (data) => {
2534
try {
26-
setIsLoading(true);
27-
28-
const result = await axiosInstance.patch('/user/username', {
29-
username: userData.username,
35+
await ClientAxios.patch('/user/username', {
36+
username: data.username,
3037
});
3138

32-
console.log(result);
39+
toast.success('Username updated successfully');
40+
41+
// refresh the page
42+
window.location.reload();
3343
} catch (error: unknown) {
3444
if ((error as any).isAxiosError) {
3545
const axiosError = error as AxiosError;
@@ -53,37 +63,39 @@ export const EditUsernameModal = ({
5363
}
5464

5565
toast.error('An error occurred. Please try again later.');
56-
} finally {
57-
setIsLoading(false);
5866
}
5967
};
6068

6169
return (
6270
<GenericModal title='Edit username' isOpen={isOpen} setIsOpen={setIsOpen}>
6371
<div className='flex flex-col gap-4'>
64-
<div>
72+
<form className='flex flex-col gap-4' onSubmit={handleSubmit(onSubmit)}>
73+
<span className='text-red-500 text-sm font-medium h-4'>
74+
{errors.username && errors.username.message}
75+
</span>
6576
<label htmlFor='username' className='block text-white'>
6677
Username
6778
</label>
6879
<input
80+
autoFocus
6981
type='text'
7082
id='username'
71-
name='username'
83+
{...register('username', { required: 'Username is required' })}
7284
className='w-full bg-zinc-700 text-white rounded-lg p-2'
7385
defaultValue={userData.username}
74-
disabled={isLoading}
86+
disabled={isSubmitting}
7587
/>
76-
</div>
77-
<div className='flex justify-end'>
78-
<button
79-
onClick={onClick}
80-
className='text-sm px-3 py-2 rounded-lg bg-blue-500 hover:bg-blue-400'
81-
disabled={isLoading}
82-
>
83-
Edit username
84-
<FontAwesomeIcon className='ml-2' icon={faPen} />
85-
</button>
86-
</div>
88+
<div className='flex justify-end'>
89+
<button
90+
type='submit'
91+
className='text-sm px-3 py-2 rounded-lg bg-blue-500 hover:bg-blue-400'
92+
disabled={isSubmitting}
93+
>
94+
Edit username
95+
<FontAwesomeIcon className='ml-2' icon={faPen} />
96+
</button>
97+
</div>
98+
</form>
8799
</div>
88100
</GenericModal>
89101
);

0 commit comments

Comments
 (0)