Skip to content

Commit

Permalink
feat: add logout in profile
Browse files Browse the repository at this point in the history
  • Loading branch information
egor-kolesnikov committed Nov 19, 2023
1 parent 14f48fd commit 0103af2
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 16 deletions.
61 changes: 52 additions & 9 deletions src/components/profile-components/profile-menu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import ExitIcon from '@images/profile/exit.svg?react';
import HeartIcon from '@images/profile/heart.svg?react';
import MarkerIcon from '@images/profile/marker.svg?react';
import UserIcon from '@images/profile/user.svg?react';
// import { useAuth } from '@hooks/use-auth';
import { useAuth } from '@hooks/use-auth';
import clsx from 'clsx';
import { usePopup } from '@hooks/use-popup';
import Popup from '@components/popup';
import { useState } from 'react';

const menuArray = [
{ title: 'Мои заказы', Icon: BagIcon, path: '.' },
Expand All @@ -18,11 +21,17 @@ const menuArray = [

export default function ProfileMenu() {
const navigate = useNavigate();
// const { logout } = useAuth();
const { logout } = useAuth();
const { handleOpenPopup, handleClosePopup, popupState } = usePopup();
const [isLoadingExit, setIsLoadingExit] = useState(false);

const onClick = () => {
// logout();
navigate('/');
const handleExit = () => {
setIsLoadingExit(true);
logout().then(() => {
handleClosePopup('openPopupLogout');
setIsLoadingExit(false);
navigate('/');
});
};
return (
<ul className={styles.list}>
Expand All @@ -38,10 +47,44 @@ export default function ProfileMenu() {
<span className={clsx('text_type_u', styles.link__title)}>{title}</span>
</NavLink>
) : (
<button className={styles.button} type="button" onClick={onClick}>
<Icon className={styles.button__icon} />
<span className={clsx('text_type_u', styles.button__title)}>{title}</span>
</button>
<>
<button
className={styles.button}
type="button"
onClick={() => handleOpenPopup('openPopupLogout')}
>
<Icon className={styles.button__icon} />
<span className={clsx('text_type_u', styles.button__title)}>{title}</span>
</button>
<Popup
openPopup={popupState.openPopupLogout}
onClickClose={() => !isLoadingExit && handleClosePopup('openPopupLogout')}
>
<div className={styles['popup-logout']}>
<h3 className={styles['popup-logout__title']}>
Хотите выйти из профиля?
</h3>
<div className={styles['popup-logout__buttons']}>
<button
onClick={handleExit}
type="button"
className={styles['popup-logout__button-confirm']}
disabled={isLoadingExit}
>
Да
</button>
<button
disabled={isLoadingExit}
onClick={() => handleClosePopup('openPopupLogout')}
type="button"
className={styles['popup-logout__button-cancel']}
>
Нет
</button>
</div>
</div>
</Popup>
</>
)}
</li>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,42 @@
fill: $accent-color-bright-green;
}
}

.popup-logout {
padding: 40px 72px;

&__title {
padding: 30px 0;
}

&__buttons {
display: flex;
justify-content: space-between;
gap: 40px;
}

&__button-confirm,
&__button-cancel {
padding: 8px 16px;
display: flex;
justify-content: center;
align-items: center;
border: none;
border-radius: 16px;
font-size: 18px;
font-family: $ubuntu-font;
line-height: 1.4;
cursor: pointer;
}

&__button-confirm {
color: #fff;
background: $form-button-color;
}

&__button-cancel {
background: #fff;
color: $active-text-color;
border: 1px solid $form-button-color;
}
}
13 changes: 12 additions & 1 deletion src/contexts/auth-context.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React, { createContext, useState, ReactNode, useEffect } from 'react';
import api from '@services/api.ts';
import Cookies from 'js-cookie';

type AuthContextType = {
isLoggedIn: boolean;
user: Record<string, unknown>;
loading: boolean;
updateUsers: (newUserData: Record<string, unknown>) => void;
checkAuthentication: () => Promise<void>;
logout: () => Promise<void>;
};

const AuthContext = createContext<AuthContextType>({
Expand All @@ -15,6 +17,7 @@ const AuthContext = createContext<AuthContextType>({
loading: true,
updateUsers: () => {},
checkAuthentication: () => Promise.resolve(),
logout: () => Promise.resolve(),
});

type AuthProviderProps = {
Expand All @@ -38,6 +41,14 @@ export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
}
};

const logout = () => {
return api.tokenLogoutCreate().finally(() => {
Cookies.remove('token');
setIsLoggedIn(false);
setUser({});
});
};

useEffect(() => {
checkAuthentication();
}, []);
Expand All @@ -48,7 +59,7 @@ export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {

return (
<AuthContext.Provider
value={{ isLoggedIn, user, updateUsers, loading, checkAuthentication }}
value={{ isLoggedIn, user, updateUsers, loading, checkAuthentication, logout }}
>
{!loading && children}
</AuthContext.Provider>
Expand Down
2 changes: 2 additions & 0 deletions src/contexts/popup-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ type PopupContextType = {
openPopup: boolean;
openPopupLogin: boolean;
openPopupRegistration: boolean;
openPopupLogout: boolean;
};
handleOpenPopup: (popupName: string) => void;
handleClosePopup: (popupName: string) => void;
Expand All @@ -17,6 +18,7 @@ export const PopupProvider: React.FC<{ children: ReactNode }> = ({ children }) =
openPopup: false,
openPopupLogin: false,
openPopupRegistration: false,
openPopupLogout: false,
});

const handleOpenPopup = (popupName: string) => {
Expand Down
30 changes: 24 additions & 6 deletions src/services/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class Api {

_checkResponse(res: Response) {
if (res.ok) {
if (res.status === 204) return res;
return res.json();
}
return Promise.reject(new Error(`Ошибка: ${res.statusText}`));
Expand All @@ -58,6 +59,9 @@ class Api {
tokenLogoutCreate() {
return this._request('token/logout/', {
method: 'POST',
headers: {
Authorization: `Token ${Cookies.get('token')}`,
},
});
}

Expand Down Expand Up @@ -99,13 +103,21 @@ class Api {
usersMeUpdate(data: User) {
return this._request('users/me/', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
Authorization: `Token ${Cookies.get('token')}`,
},
body: JSON.stringify(data),
});
}

usersMePartialUpdate(data: User) {
return this._request('users/me/', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
Authorization: `Token ${Cookies.get('token')}`,
},
body: JSON.stringify(data),
});
}
Expand Down Expand Up @@ -198,12 +210,20 @@ class Api {
usersAddressesList(userId: string) {
return this._request(`users/${userId}/addresses/`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: `Token ${Cookies.get('token')}`,
},
});
}

usersAddressesRead(userId: string, id: string) {
return this._request(`users/${userId}/addresses/${id}/`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: `Token ${Cookies.get('token')}`,
},
});
}

Expand Down Expand Up @@ -270,14 +290,12 @@ class Api {

/* ----------------------------- Products ----------------------------- */
productsList(slug: string) {
const token = Cookies.get('token');
const headers: Record<string, unknown> = { 'Content-Type': 'application/json' };
if (token) {
headers.Authorization = `Token ${Cookies.get('token')}`;
}
return this._request(`products${'/' + slug}`, {
method: 'GET',
headers,
headers: {
'Content-Type': 'application/json',
Authorization: `Token ${Cookies.get('token')}`,
},
});
}

Expand Down

0 comments on commit 0103af2

Please sign in to comment.