From 7eb7192b058df9e1e6708447b6795801d39e7c43 Mon Sep 17 00:00:00 2001 From: Sajad Mirjalili Date: Fri, 26 Sep 2025 00:17:26 +0330 Subject: [PATCH] fix: layout menues --- public/locales/en/setting.json | 10 ++ public/locales/en/sideNav.json | 5 +- public/locales/fa/setting.json | 10 ++ public/locales/fa/sideNav.json | 5 +- src/components/Layout/Header.tsx | 110 ++++++++++++++---- src/components/Layout/ProductsMenu.tsx | 96 +++++++++++++++ src/components/Layout/Toolbar.tsx | 18 ++- src/data/products.ts | 21 ++++ .../userInformation/PersonalInformation.tsx | 1 - 9 files changed, 249 insertions(+), 27 deletions(-) create mode 100644 src/components/Layout/ProductsMenu.tsx create mode 100644 src/data/products.ts diff --git a/public/locales/en/setting.json b/public/locales/en/setting.json index ac12fa7..97a0663 100644 --- a/public/locales/en/setting.json +++ b/public/locales/en/setting.json @@ -133,5 +133,15 @@ "passwordChanged": "Password changed", "passwordAdded": "Password added", "error": "Password change failed" + }, + "products": { + "menu": { + "title": "Harmony Product Family", + "getDemo": "Get Demo" + }, + "harmonyClub": { + "title": "Harmony Club", + "description": "Encourage repeat purchases by sending discount codes and points to your customers." + } } } \ No newline at end of file diff --git a/public/locales/en/sideNav.json b/public/locales/en/sideNav.json index 4057675..37ab853 100644 --- a/public/locales/en/sideNav.json +++ b/public/locales/en/sideNav.json @@ -1,4 +1,7 @@ { + "header": { + "logout": "logout " + }, "side": { "account": "Account", "personalInfo": "Personal information", @@ -10,4 +13,4 @@ "activeSessions": "Active sessions", "setting": "Settings" } -} +} \ No newline at end of file diff --git a/public/locales/fa/setting.json b/public/locales/fa/setting.json index 1d405bf..b49f924 100644 --- a/public/locales/fa/setting.json +++ b/public/locales/fa/setting.json @@ -134,5 +134,15 @@ "passwordChanged": "رمز عبور تعویض شد", "passwordAdded": "رمز عبور اضافه شد", "error": "تعویض رمز عبور با مشکل مواجه شد" + }, + "products": { + "menu": { + "title": "خانواده محصولات هارمونی", + "getDemo": "دریافت دمو" + }, + "harmonyClub": { + "title": "هارمونی کلاب", + "description": "با ارسال کد تخفیف و امتیاز به مشتریان کسب و کارتان آنها را به خرید مجدد ترغیب کنید" + } } } \ No newline at end of file diff --git a/public/locales/fa/sideNav.json b/public/locales/fa/sideNav.json index 166eda6..1098cba 100644 --- a/public/locales/fa/sideNav.json +++ b/public/locales/fa/sideNav.json @@ -1,4 +1,7 @@ { + "header": { + "logout": "خروج از حساب کاربری" + }, "side": { "account": "حساب کاربری", "personalInfo": "اطلاعات شخصی", @@ -10,4 +13,4 @@ "activeSessions": "نشست های فعال", "setting": "تنظیمات" } -} +} \ No newline at end of file diff --git a/src/components/Layout/Header.tsx b/src/components/Layout/Header.tsx index c756189..94b60a1 100644 --- a/src/components/Layout/Header.tsx +++ b/src/components/Layout/Header.tsx @@ -1,34 +1,100 @@ -import { Box, IconButton, Typography } from '@mui/material'; +import { + Box, + IconButton, + ListItemIcon, + ListItemText, + Menu, + MenuItem, + Typography, +} from '@mui/material'; import { Icon } from '@rkheftan/harmony-ui'; -import { More } from 'iconsax-react'; +import { Logout, More } from 'iconsax-react'; import type { UserInfo } from '@/contexts/AuthContext'; import { LTRTypography } from '../common/LTRTypography'; +import { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useAuth } from '@/hooks/useAuth'; interface HeaderProps { user: UserInfo; } export const Header: React.FC = ({ user }) => { - return ( - t.spacing(10.5), - }} - > - - {user.fullName} - - {user.phoneNumber ?? user.email} - - + const { t, i18n } = useTranslation('sideNav'); - - - - + const [anchorEl, setAnchorEl] = useState(null); + const open = Boolean(anchorEl); + + const { logout } = useAuth(); + + const handleClick = (event: React.MouseEvent) => { + event.stopPropagation(); + setAnchorEl(event.currentTarget); + }; + + const handleClose = () => { + setAnchorEl(null); + }; + + const handleLogout = () => { + handleClose(); + logout(); + }; + + return ( + <> + t.spacing(10.5), + }} + > + + + {user.fullName} + + {/* TODO: add ternary text color to palette */} + + {user.phoneNumber ?? user.email} + + + + + + + + + + + + + {t('header.logout')} + + + ); }; diff --git a/src/components/Layout/ProductsMenu.tsx b/src/components/Layout/ProductsMenu.tsx new file mode 100644 index 0000000..299287a --- /dev/null +++ b/src/components/Layout/ProductsMenu.tsx @@ -0,0 +1,96 @@ +import { Menu, Stack, Typography, Box, Button } from '@mui/material'; +import { blue } from '@mui/material/colors'; +import { Icon } from '@rkheftan/harmony-ui'; +import { ArrowLeft, ArrowRight } from 'iconsax-react'; +import { useTranslation } from 'react-i18next'; +import { productsData } from '@/data/products'; + +// --- Props Interface --- +interface ProductsMenuProps { + anchorEl: Element | null; + open: boolean; + onClose: () => void; +} + +export default function ProductsMenu({ + anchorEl, + open, + onClose, +}: ProductsMenuProps) { + const { t, i18n } = useTranslation('setting'); + + return ( + + {/* 1. Header Link */} + + + {t('products.menu.title')} + + + + + {/* 2. Map through products to create MenuItems */} + {productsData.map((product) => ( + + {/* Text Content */} + + {t(product.titleKey)} + + {t(product.descriptionKey)} + + + + + + + + + ))} + + + ); +} diff --git a/src/components/Layout/Toolbar.tsx b/src/components/Layout/Toolbar.tsx index c713c2b..86cbd86 100644 --- a/src/components/Layout/Toolbar.tsx +++ b/src/components/Layout/Toolbar.tsx @@ -1,9 +1,10 @@ import { Avatar, Box, IconButton, Toolbar as MuiToolbar } from '@mui/material'; import { Icon } from '@rkheftan/harmony-ui'; import { HambergerMenu, Menu } from 'iconsax-react'; -import type { Dispatch, SetStateAction } from 'react'; +import { useState, type Dispatch, type SetStateAction } from 'react'; import type { UserInfo } from '@/contexts/AuthContext'; import Logo from '../Logo'; +import ProductsMenu from './ProductsMenu'; interface ToolbarProps { sideNavOpen: boolean; @@ -18,6 +19,18 @@ export const Toolbar: React.FC = ({ isMobile, user, }) => { + const [anchorEl, setAnchorEl] = useState(null); + const open = Boolean(anchorEl); + + const handleClick = (event: React.MouseEvent) => { + event.stopPropagation(); + setAnchorEl(event.currentTarget); + }; + + const handleClose = () => { + setAnchorEl(null); + }; + return ( = ({ {user.firstName.charAt(0) + ' ' + user.lastName.charAt(0)} )} - + + ); }; diff --git a/src/data/products.ts b/src/data/products.ts new file mode 100644 index 0000000..e71cb90 --- /dev/null +++ b/src/data/products.ts @@ -0,0 +1,21 @@ +import Logo from '@/components/Logo'; +import { type FC } from 'react'; + +export interface Product { + id: string; + titleKey: string; + descriptionKey: string; + LogoComponent: FC; + demoLink: string; +} + +export const productsData: Product[] = [ + { + id: 'harmony-club', + titleKey: 'products.harmonyClub.title', + descriptionKey: 'products.harmonyClub.description', + LogoComponent: Logo, // Reference the component + demoLink: '', // FIXME: update this url + }, + // add more products here +]; diff --git a/src/features/profile/components/userInformation/PersonalInformation.tsx b/src/features/profile/components/userInformation/PersonalInformation.tsx index b54e6a9..a652c28 100644 --- a/src/features/profile/components/userInformation/PersonalInformation.tsx +++ b/src/features/profile/components/userInformation/PersonalInformation.tsx @@ -53,7 +53,6 @@ export function PersonalInformation() { ? `${imageBaseUrl}/${profileData.profileImageUrl}` : null, ); - console.log(uploadedImageUrl); setUploadedImageFile(null); } else { showToast({