Skip to content

Commit 8795da1

Browse files
authored
Merge branch 'development' into fix/th-294-user-unlogging-when-server-is-dead
2 parents 10d8b52 + 769dca6 commit 8795da1

File tree

14 files changed

+128
-46
lines changed

14 files changed

+128
-46
lines changed

backend/src/packages/auth/auth.controller.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,18 @@ class AuthController extends Controller {
8383
}>,
8484
),
8585
});
86+
87+
this.addRoute({
88+
path: AuthApiPath.LOGOUT,
89+
method: 'GET',
90+
authStrategy: AuthStrategy.VERIFY_JWT,
91+
handler: (options) =>
92+
this.logOut(
93+
options as ApiHandlerOptions<{
94+
user: UserEntityObjectWithGroupT;
95+
}>,
96+
),
97+
});
8698
}
8799

88100
private async signUpCustomer(
@@ -131,6 +143,17 @@ class AuthController extends Controller {
131143
payload: await this.authService.getCurrent(options.user),
132144
};
133145
}
146+
147+
private async logOut(
148+
options: ApiHandlerOptions<{
149+
user: UserEntityObjectWithGroupT;
150+
}>,
151+
): Promise<ApiHandlerResponse> {
152+
return {
153+
status: HttpCode.NO_CONTENT,
154+
payload: await this.authService.logOut(options.user),
155+
};
156+
}
134157
}
135158

136159
export { AuthController };

backend/src/packages/auth/auth.service.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,10 @@ class AuthService {
223223
return user;
224224
}
225225

226+
public async logOut(user: UserEntityObjectWithGroupT): Promise<void> {
227+
return await this.userService.removeAccessToken(user.id);
228+
}
229+
226230
public async generateAccessTokenAndUpdateUser(
227231
userId: UserEntityT['id'],
228232
): Promise<UserEntityObjectT> {

backend/src/packages/users/user.service.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ class UserService implements IService<UserEntityObjectT> {
146146

147147
return UserEntity.initialize(result).toObject();
148148
}
149+
150+
public async removeAccessToken(id: UserEntityT['id']): Promise<void> {
151+
await this.userRepository.update(id, { accessToken: null });
152+
}
149153
}
150154

151155
export { UserService };

frontend/src/libs/components/burger-menu/burger-menu.tsx

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { IconName } from '~/libs/enums/enums.js';
1+
import { BurgerMenuItemsName, IconName } from '~/libs/enums/enums.js';
22
import { getValidClassNames } from '~/libs/helpers/helpers.js';
33
import {
4+
useAppDispatch,
45
useCallback,
56
useEffect,
67
useLocation,
@@ -9,6 +10,7 @@ import {
910
useState,
1011
} from '~/libs/hooks/hooks.js';
1112
import { type BurgerMenuItem } from '~/libs/types/types.js';
13+
import { actions as authActions } from '~/slices/auth/auth.js';
1214

1315
import { Button, Icon } from '../components.js';
1416
import styles from './styles.module.scss';
@@ -21,6 +23,7 @@ const BurgerMenu: React.FC<Properties> = ({ burgerItems }: Properties) => {
2123
const [isOpen, setIsOpen] = useState(false);
2224
const location = useLocation();
2325
const navigate = useNavigate();
26+
const dispatch = useAppDispatch();
2427

2528
const menuReference = useRef<HTMLDivElement | null>(null);
2629

@@ -29,10 +32,17 @@ const BurgerMenu: React.FC<Properties> = ({ burgerItems }: Properties) => {
2932
}, [isOpen]);
3033

3134
const handleNavigate = useCallback(
32-
(navigateTo: string) => () => navigate(navigateTo),
35+
(navigateTo: string) => () => {
36+
navigate(navigateTo);
37+
},
3338
[navigate],
3439
);
3540

41+
const handleLogOutClick = useCallback(
42+
() => dispatch(authActions.logOut()),
43+
[dispatch],
44+
);
45+
3646
useEffect(() => {
3747
setIsOpen(false);
3848
}, [location]);
@@ -67,22 +77,28 @@ const BurgerMenu: React.FC<Properties> = ({ burgerItems }: Properties) => {
6777
{isOpen && (
6878
<div className={styles.menu}>
6979
<ul>
70-
{burgerItems.map((item, index) => (
71-
<li key={index}>
72-
<Icon
73-
iconName={item.icon}
74-
onClick={handleNavigate(item.navigateTo)}
75-
className={styles.menuIcon}
76-
/>
77-
<Button
78-
frontIcon={item.icon}
79-
isFullWidth
80-
label={item.name}
81-
onClick={handleNavigate(item.navigateTo)}
82-
className={styles.btn}
83-
/>
84-
</li>
85-
))}
80+
{burgerItems.map((item, index) => {
81+
const clickHandler =
82+
item.name === BurgerMenuItemsName.LOG_OUT
83+
? handleLogOutClick
84+
: handleNavigate(item.navigateTo);
85+
86+
return (
87+
<li key={index}>
88+
<Button
89+
frontIcon={item.icon}
90+
onClick={clickHandler}
91+
className={styles.menuIcon}
92+
/>
93+
<Button
94+
frontIcon={item.icon}
95+
label={item.name}
96+
onClick={clickHandler}
97+
className={styles.btn}
98+
/>
99+
</li>
100+
);
101+
})}
86102
</ul>
87103
</div>
88104
)}

frontend/src/libs/components/burger-menu/styles.module.scss

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,29 @@
2727

2828
.btn {
2929
justify-content: start;
30+
width: 100%;
3031
background-color: $blue-dark;
3132
border-radius: 0;
3233

33-
&:hover {
34+
&:hover,
35+
&:active,
36+
&:focus {
3437
background-color: $blue;
3538
}
3639
}
3740

3841
.menuIcon {
3942
width: 100%;
43+
padding: 10px 20px;
4044
color: $white;
4145
font-size: 24px;
46+
background-color: $blue-dark;
47+
48+
&:hover,
49+
&:active,
50+
&:focus {
51+
background-color: $blue;
52+
}
4253
}
4354
}
4455

@@ -50,23 +61,17 @@
5061
.btn {
5162
display: none;
5263
}
53-
54-
li {
55-
padding: 10px 20px;
56-
57-
&:hover {
58-
background-color: $blue;
59-
}
60-
}
6164
}
6265
}
6366

6467
@media (width > $screen-size-lg) {
65-
.btn {
66-
display: inline-flex;
67-
}
68+
.menu {
69+
.btn {
70+
display: inline-flex;
71+
}
6872

69-
.menuIcon {
70-
display: none;
73+
.menuIcon {
74+
display: none;
75+
}
7176
}
7277
}

frontend/src/libs/components/button/button.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import styles from './styles.module.scss';
77

88
type Properties = {
99
className?: Parameters<typeof getValidClassNames>[0];
10-
label: string | number;
10+
label?: string | number;
1111
type?: 'button' | 'submit';
1212
size?: 'sm' | 'md';
1313
variant?: 'contained' | 'outlined' | 'text';
@@ -24,7 +24,7 @@ const Button: React.FC<Properties> = ({
2424
type = 'button',
2525
size = 'md',
2626
variant = 'contained',
27-
label,
27+
label = '',
2828
isDisabled = false,
2929
isFullWidth = false,
3030
frontIcon,

frontend/src/libs/components/input/styles.module.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ $error-message-height: calc($error-font-size * $line-height-coefficient);
8787
top: 8px;
8888
right: 10px;
8989
color: $grey-dark;
90-
background-color: $white;
90+
background-color: transparent;
9191
border: 0;
9292
cursor: pointer;
9393
user-select: none;

frontend/src/libs/enums/breakpoint.ts

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

frontend/src/libs/enums/enums.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
export { AppRoute } from './app-route.enum.js';
2-
export { Breakpoint } from './breakpoint.js';
32
export { BurgerMenuItemsName } from './burger-menu-items-name.enum.js';
43
export { DataStatus } from './data-status.enum.js';
54
export { FormLabel, FormName } from './form.enum.js';

frontend/src/packages/auth/auth-api.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,14 @@ class AuthApi extends HttpApi {
7777
CustomerSignUpResponseDto | BusinessSignUpResponseDto
7878
>();
7979
}
80+
81+
public async logOut(): Promise<unknown> {
82+
return await this.load(this.getFullEndpoint(AuthApiPath.LOGOUT, {}), {
83+
method: 'GET',
84+
contentType: ContentType.JSON,
85+
hasAuth: true,
86+
});
87+
}
8088
}
8189

8290
export { AuthApi };

0 commit comments

Comments
 (0)