Skip to content

Commit 8e389d8

Browse files
authored
Merge branch 'development' into task/th-257-geolocation-service-use-truckId-instead-of-driverId
2 parents f1f4642 + 2e04f8f commit 8e389d8

18 files changed

+287
-9
lines changed

.stylelintrc.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ rules:
88
selector-class-pattern: null
99
color-hex-length: long
1010
declaration-no-important: true
11-
max-nesting-depth: 0
11+
max-nesting-depth: 2
1212
no-descending-specificity: true
1313
scss/at-import-partial-extension: always
1414
import-notation: string
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { Breakpoint, IconName } from '~/libs/enums/enums.js';
2+
import { getValidClassNames } from '~/libs/helpers/helpers.js';
3+
import {
4+
useCallback,
5+
useEffect,
6+
useLocation,
7+
useNavigate,
8+
useRef,
9+
useState,
10+
} from '~/libs/hooks/hooks.js';
11+
import { type BurgerMenuItem } from '~/libs/types/types.js';
12+
13+
import { Button, Icon } from '../components.js';
14+
import styles from './styles.module.scss';
15+
16+
type Properties = {
17+
burgerItems: BurgerMenuItem[];
18+
};
19+
20+
const BurgerMenu: React.FC<Properties> = ({ burgerItems }: Properties) => {
21+
const [isOpen, setIsOpen] = useState(false);
22+
const location = useLocation();
23+
const navigate = useNavigate();
24+
25+
const menuReference = useRef<HTMLDivElement | null>(null);
26+
27+
const toggleMenu = useCallback(() => {
28+
setIsOpen(!isOpen);
29+
}, [isOpen]);
30+
31+
const handleNavigate = useCallback(
32+
(navigateTo: string) => () => navigate(navigateTo),
33+
[navigate],
34+
);
35+
36+
useEffect(() => {
37+
setIsOpen(false);
38+
}, [location]);
39+
40+
useEffect(() => {
41+
const handleDocumentClick = (event: MouseEvent): void => {
42+
if (
43+
menuReference.current &&
44+
!menuReference.current.contains(event.target as Node)
45+
) {
46+
setIsOpen(false);
47+
}
48+
};
49+
50+
document.addEventListener('click', handleDocumentClick);
51+
52+
return () => {
53+
document.removeEventListener('click', handleDocumentClick);
54+
};
55+
}, []);
56+
57+
const isMobile = window.innerWidth <= Breakpoint.MOBILE;
58+
59+
return (
60+
<div
61+
ref={menuReference}
62+
className={getValidClassNames(styles.burgerMenu, isOpen && styles.open)}
63+
>
64+
<Icon
65+
iconName={isOpen ? IconName.XMARK : IconName.BARS}
66+
onClick={toggleMenu}
67+
className={styles.burgerIcon}
68+
/>
69+
{isOpen && (
70+
<div className={styles.menu}>
71+
<ul>
72+
{burgerItems.map((item, index) => (
73+
<li key={index}>
74+
{isMobile ? (
75+
<Icon
76+
iconName={item.icon}
77+
onClick={handleNavigate(item.navigateTo)}
78+
className={styles.menuIcon}
79+
/>
80+
) : (
81+
<Button
82+
frontIcon={item.icon}
83+
isFullWidth
84+
label={item.name}
85+
onClick={handleNavigate(item.navigateTo)}
86+
className={styles.btn}
87+
/>
88+
)}
89+
</li>
90+
))}
91+
</ul>
92+
</div>
93+
)}
94+
</div>
95+
);
96+
};
97+
98+
export { BurgerMenu };
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
@import "src/assets/css/vars.scss";
2+
3+
.burgerMenu {
4+
position: relative;
5+
cursor: pointer;
6+
}
7+
8+
.burgerIcon {
9+
width: 100%;
10+
color: $red;
11+
font-size: 24px;
12+
}
13+
14+
.open .burgerIcon {
15+
color: $red-light;
16+
}
17+
18+
.menu {
19+
position: absolute;
20+
top: 110%;
21+
right: 0;
22+
z-index: 10;
23+
width: 220px;
24+
overflow: hidden;
25+
border: none;
26+
border-radius: 16px;
27+
28+
.btn {
29+
display: inline-flex;
30+
justify-content: start;
31+
background-color: $blue-dark;
32+
border-radius: 0;
33+
34+
&:hover {
35+
background-color: $blue;
36+
}
37+
}
38+
39+
.menuIcon {
40+
width: 100%;
41+
color: $white;
42+
font-size: 24px;
43+
}
44+
}
45+
46+
@media (width <= $screen-size-lg) {
47+
.menu {
48+
width: 80px;
49+
background-color: $blue-dark;
50+
51+
li {
52+
padding: 10px 20px;
53+
54+
&:hover {
55+
background-color: $blue;
56+
}
57+
}
58+
}
59+
}

frontend/src/libs/components/components.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export { App } from './app/app.js';
22
export { AppLogo } from './app-logo/app-logo.js';
33
export { Badge } from './badge/badge.js';
4+
export { BurgerMenu } from './burger-menu/burger-menu.js';
45
export { BusinessCard } from './business-card/business-card.js';
56
export { Button } from './button/button.js';
67
export { Checkbox } from './checkbox/checkbox.js';

frontend/src/libs/components/header/header.tsx

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,43 @@
11
import { AppRoute } from '~/libs/enums/enums.js';
2-
import { useCallback, useNavigate } from '~/libs/hooks/hooks.js';
2+
import {
3+
useAppSelector,
4+
useCallback,
5+
useNavigate,
6+
} from '~/libs/hooks/hooks.js';
7+
import { selectUser } from '~/slices/auth/selectors.js';
38

4-
import { AppLogo, Button, Link } from '../components.js';
9+
import { AppLogo, BurgerMenu, Button, Link } from '../components.js';
10+
import { getBurgerMenuItems } from './libs/helpers/helpers.js';
511
import styles from './styles.module.scss';
612

713
const Header: React.FC = () => {
814
const navigate = useNavigate();
15+
const user = useAppSelector(selectUser);
16+
const hasUser = Boolean(user);
917

1018
const handleSignIn = useCallback(() => {
1119
navigate(AppRoute.WELCOME);
1220
}, [navigate]);
1321

22+
const burgerItems = getBurgerMenuItems(user?.group.key ?? null);
23+
1424
return (
1525
<header className={styles.container}>
1626
<div className={styles.content}>
1727
<Link className={styles.logoContainer} to={AppRoute.ROOT}>
1828
<AppLogo />
1929
</Link>
2030
<div className={styles.navMenu}>
21-
<Button
22-
label="Sign In"
23-
className={styles.btn}
24-
type="button"
25-
onClick={handleSignIn}
26-
/>
31+
{hasUser ? (
32+
<BurgerMenu burgerItems={burgerItems} />
33+
) : (
34+
<Button
35+
label="Sign In"
36+
className={styles.btn}
37+
type="button"
38+
onClick={handleSignIn}
39+
/>
40+
)}
2741
</div>
2842
</div>
2943
</header>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { AppRoute, BurgerMenuItemsName, IconName } from '~/libs/enums/enums.js';
2+
3+
const BURGER_MENU_ITEMS = {
4+
businessMenu: [
5+
{
6+
name: BurgerMenuItemsName.HISTORY,
7+
navigateTo: AppRoute.ORDER_HISTORY,
8+
icon: IconName.CLOCK_ROTATE_LEFT,
9+
},
10+
{
11+
name: BurgerMenuItemsName.EDIT,
12+
navigateTo: AppRoute.EDIT_PROFILE,
13+
icon: IconName.USER_PEN,
14+
},
15+
{
16+
name: BurgerMenuItemsName.LOG_OUT,
17+
navigateTo: AppRoute.SIGN_IN,
18+
icon: IconName.RIGHT_FROM_BRACKET,
19+
},
20+
],
21+
customerMenu: [
22+
{
23+
name: BurgerMenuItemsName.LOG_OUT,
24+
navigateTo: AppRoute.SIGN_IN,
25+
icon: IconName.RIGHT_FROM_BRACKET,
26+
},
27+
],
28+
driverMenu: [
29+
{
30+
name: BurgerMenuItemsName.LOG_OUT,
31+
navigateTo: AppRoute.SIGN_IN,
32+
icon: IconName.RIGHT_FROM_BRACKET,
33+
},
34+
],
35+
};
36+
37+
export { BURGER_MENU_ITEMS };
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { BURGER_MENU_ITEMS } from './burger-menu-items.js';
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { type BurgerMenuItem } from '~/libs/types/types.js';
2+
import { UserGroupKey } from '~/packages/users/libs/enums/enums.js';
3+
4+
import { BURGER_MENU_ITEMS } from '../constants/constants.js';
5+
6+
const getBurgerMenuItems = (group: string | null): BurgerMenuItem[] => {
7+
switch (group) {
8+
case UserGroupKey.BUSINESS: {
9+
return BURGER_MENU_ITEMS.businessMenu;
10+
}
11+
case UserGroupKey.DRIVER: {
12+
return BURGER_MENU_ITEMS.driverMenu;
13+
}
14+
default: {
15+
return BURGER_MENU_ITEMS.customerMenu;
16+
}
17+
}
18+
};
19+
20+
export { getBurgerMenuItems };
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { getBurgerMenuItems } from './get-burger-menu-items.helper.js';

frontend/src/libs/components/icon/icon.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,20 @@ type Properties = {
99
iconName: ValueOf<typeof IconName>;
1010
className?: string;
1111
size?: ValueOf<typeof IconSize>;
12+
onClick?: () => void;
1213
};
1314

1415
const Icon: React.FC<Properties> = ({
1516
iconName,
1617
className,
1718
size,
19+
onClick,
1820
}: Properties) => (
1921
<FontAwesomeIcon
2022
className={className}
2123
icon={iconNameToSvg[iconName]}
2224
size={size}
25+
onClick={onClick}
2326
/>
2427
);
2528

0 commit comments

Comments
 (0)