-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f7fd3ea
commit 3144067
Showing
7 changed files
with
351 additions
and
0 deletions.
There are no files selected for viewing
23 changes: 23 additions & 0 deletions
23
src/componants/shared/navtools/IconWithCountAndLabel/IconWithCountAndLabel.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { NavLink } from "react-router-dom"; | ||
import SvgIcon from "../../MiniComponents/SvgIcon"; | ||
import s from "./IconWithCountAndLabel.module.scss"; | ||
|
||
const IconWithCountAndLabel = ({ | ||
props: { iconName, visibility, routePath, countLength, title, text }, | ||
}) => { | ||
const count = countLength > 99 ? "99+" : countLength; | ||
|
||
return ( | ||
visibility && ( | ||
<NavLink to={routePath} aria-label={title}> | ||
<div className={s.wrapper}> | ||
<SvgIcon name={iconName} /> | ||
{countLength > 0 && <span className={s.count}>{count}</span>} | ||
</div> | ||
|
||
<span className={s.text}>{text}</span> | ||
</NavLink> | ||
) | ||
); | ||
}; | ||
export default IconWithCountAndLabel; |
38 changes: 38 additions & 0 deletions
38
src/componants/shared/navtools/IconWithCountAndLabel/IconWithCountAndLabel.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
.wrapper { | ||
width: inherit; | ||
height: inherit; | ||
} | ||
|
||
.link svg { | ||
width: inherit; | ||
height: inherit; | ||
fill: var(--black); | ||
transition: fill .2s; | ||
} | ||
|
||
.count { | ||
display: inline-block; | ||
position: absolute; | ||
left: 0; | ||
top: -1px; | ||
background-color: var(--dark-tomato); | ||
color: #fff; | ||
border-radius: 50%; | ||
font-size: .6rem; | ||
width: 28px; | ||
height: 28px; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
user-select: none; | ||
z-index: 2; | ||
transform: scale(.6); | ||
} | ||
|
||
.text { | ||
padding-inline-start: 16px; | ||
} | ||
|
||
.text::selection { | ||
background-color: var(--white) !important; | ||
} |
22 changes: 22 additions & 0 deletions
22
src/componants/shared/navtools/SearchInput/SearchInput.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { useTranslation } from "react-i18next"; | ||
|
||
const SearchInput = ({ searchRef }) => { | ||
const { t } = useTranslation(); | ||
|
||
function handleSearchOnChange(e) { | ||
const inputValue = e.target.value; | ||
searchRef.current = inputValue?.trim()?.toLowerCase(); | ||
} | ||
|
||
return ( | ||
<input | ||
type="text" | ||
id="search-input" | ||
autoComplete="off" | ||
placeholder={t("inputsPlaceholders.whatYouLookingFor")} | ||
onChange={handleSearchOnChange} | ||
aria-label="Search product field" | ||
/> | ||
); | ||
}; | ||
export default SearchInput; |
101 changes: 101 additions & 0 deletions
101
src/componants/shared/navtools/SearchInput/SearchProductsInput.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import { useEffect, useRef } from "react"; | ||
import { useTranslation } from "react-i18next"; | ||
import { useDispatch } from "react-redux"; | ||
import { useLocation, useNavigate, useSearchParams } from "react-router-dom"; | ||
import { productsData } from "src/Data/productsData"; | ||
import { updateLoadingState } from "src/Features/loadingSlice"; | ||
import { updateProductsState } from "src/Features/productsSlice"; | ||
import { searchByObjectKey } from "src/Functions/helper"; | ||
import SvgIcon from "../../MiniComponents/SvgIcon"; | ||
import SearchInput from "./SearchInput"; | ||
import s from "./SearchProductsInput.module.scss"; | ||
|
||
const SearchProductsInput = () => { | ||
const { t } = useTranslation(); | ||
const dispatch = useDispatch(); | ||
const navigateTo = useNavigate(); | ||
const searchRef = useRef(""); | ||
const location = useLocation(); | ||
const pathName = location.pathname; | ||
const [searchParams, setSearchParams] = useSearchParams(); | ||
|
||
function handleSearchProducts(e) { | ||
setSearchParams({ query: searchRef.current }); | ||
e.preventDefault(); | ||
|
||
const isEmptyQuery = searchRef.current?.trim()?.length === 0; | ||
if (isEmptyQuery) return; | ||
|
||
updateSearchProducts(); | ||
} | ||
|
||
function updateSearchProducts() { | ||
dispatch(updateLoadingState({ key: "loadingSearchProducts", value: true })); | ||
|
||
const queryValue = searchRef.current || searchParams.get("query"); | ||
const isEmptyQuery = queryValue?.trim()?.length === 0; | ||
|
||
if (isEmptyQuery) { | ||
dispatch(updateProductsState({ key: "searchProducts", value: [] })); | ||
return; | ||
} | ||
|
||
const productsFound = getProducts(queryValue); | ||
|
||
dispatch( | ||
updateProductsState({ key: "searchProducts", value: productsFound }) | ||
); | ||
navigateTo("/search?query=" + queryValue); | ||
} | ||
|
||
useEffect(() => { | ||
const isSearchPage = pathName === "/search"; | ||
if (isSearchPage) updateSearchProducts(); | ||
|
||
return () => { | ||
dispatch( | ||
updateLoadingState({ key: "loadingSearchProducts", value: true }) | ||
); | ||
}; | ||
}, []); | ||
|
||
return ( | ||
<form | ||
className={s.searchContainer} | ||
onSubmit={handleSearchProducts} | ||
onClick={focusInput} | ||
role="search" | ||
> | ||
<SearchInput searchRef={searchRef} /> | ||
|
||
<button type="submit" aria-label={t("tooltips.searchButton")}> | ||
<SvgIcon name="search" /> | ||
</button> | ||
</form> | ||
); | ||
}; | ||
|
||
export default SearchProductsInput; | ||
|
||
function focusInput(e) { | ||
const searchInput = e.currentTarget.querySelector("#search-input"); | ||
searchInput.focus(); | ||
} | ||
|
||
function getProducts(query) { | ||
let productsFound = searchByObjectKey({ | ||
data: productsData, | ||
key: "shortName", | ||
query, | ||
}); | ||
|
||
if (productsFound.length === 0) { | ||
productsFound = searchByObjectKey({ | ||
data: productsData, | ||
key: "category", | ||
query, | ||
}); | ||
} | ||
|
||
return productsFound; | ||
} |
94 changes: 94 additions & 0 deletions
94
src/componants/shared/navtools/SearchInput/SearchProductsInput.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
@import "src/Styles/mixins"; | ||
|
||
.searchContainer { | ||
background-color: var(--secondary-white); | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
width: 250px; | ||
padding: 10px 12px 10px 20px; | ||
border-radius: 4px; | ||
margin-right: 24px; | ||
user-select: none; | ||
cursor: pointer; | ||
position: relative; | ||
outline: solid 1px var(--black); | ||
border: 6px solid var(--secondary-white); | ||
transition: border-color .1s, outline-color .1s, background-color .1s .05s; | ||
|
||
&:hover { | ||
outline-color: #ff7b00; | ||
} | ||
|
||
&:has(:focus) { | ||
outline-color: #ff7b00; | ||
background-color: rgba(255, 166, 0, .08); | ||
} | ||
} | ||
|
||
.searchContainer>input { | ||
all: unset; | ||
font-size: .75rem; | ||
font-weight: 400; | ||
line-height: 18px; | ||
width: 100%; | ||
} | ||
|
||
.searchContainer>button { | ||
all: unset; | ||
position: relative; | ||
} | ||
|
||
.searchContainer>button::before { | ||
content: ''; | ||
position: absolute; | ||
left: 2.3px; | ||
top: 2.7px; | ||
width: 10px; | ||
height: 10px; | ||
border-radius: 50%; | ||
} | ||
|
||
.searchContainer>button>svg { | ||
width: 18px; | ||
height: 18px; | ||
transition: fill .1s; | ||
fill: #757575; | ||
} | ||
|
||
.searchContainer:has(:focus)>button>svg { | ||
fill: var(--black); | ||
} | ||
|
||
.searchContainer>button:active svg { | ||
fill: var(--black); | ||
} | ||
|
||
.searchContainer>button:active::before { | ||
background-color: var(--white); | ||
} | ||
|
||
.searchContainer>button:focus svg { | ||
fill: var(--black) | ||
} | ||
|
||
// Arabic styles | ||
[lang=ar] .searchContainer { | ||
padding: 10px 12px; | ||
direction: rtl; | ||
} | ||
|
||
@include medium { | ||
[lang=ar] .searchContainer { | ||
padding: 6px 12px 6px 18px; | ||
width: 190px; | ||
} | ||
} | ||
|
||
// Hungarian styles | ||
@include medium { | ||
[lang=hu] .searchContainer { | ||
padding: 6px 12px 6px 18px; | ||
width: 220px; | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
src/componants/shared/navtools/UserMenuIcon/UserMenuIcon.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { useTranslation } from "react-i18next"; | ||
import useToggle from "src/Hooks/Helper/useToggle"; | ||
import SvgIcon from "../../MiniComponents/SvgIcon"; | ||
import ToolTip from "../../MiniComponents/ToolTip"; | ||
import UserMenu from "../../UserMenu/UserMenu"; | ||
import s from "./UserMenuIcon.module.scss"; | ||
|
||
const UserMenuIcon = ({ visibility }) => { | ||
const { t } = useTranslation(); | ||
const [isMenuUserActive, toggleMenuUserActive] = useToggle(false); | ||
const activeClass = isMenuUserActive ? s.active : ""; | ||
|
||
function openMenu() { | ||
toggleMenuUserActive(true); | ||
} | ||
|
||
if (!visibility) return null; | ||
|
||
return ( | ||
<div | ||
className={`${s.userContainer} ${activeClass}`} | ||
onClick={toggleMenuUserActive} | ||
onFocus={openMenu} | ||
aria-label={t("navTools.userMenu")} | ||
aria-haspopup="true" | ||
> | ||
<SvgIcon name="user" /> | ||
<ToolTip bottom="26px" left="50%" content={t("navTools.userMenu")} /> | ||
|
||
<UserMenu isActive={isMenuUserActive} toggler={toggleMenuUserActive} /> | ||
</div> | ||
); | ||
}; | ||
|
||
export default UserMenuIcon; |
38 changes: 38 additions & 0 deletions
38
src/componants/shared/navtools/UserMenuIcon/UserMenuIcon.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
.userContainer { | ||
-webkit-tap-highlight-color: transparent; | ||
position: relative; | ||
padding: 6px; | ||
cursor: pointer; | ||
outline: dashed 0 var(--regular-light-gray); | ||
outline-offset: 0; | ||
|
||
&:focus-visible { | ||
transition: opacity .3s, var(--outline-transition); | ||
outline: 2px dashed var(--very-dark-gray); | ||
outline-offset: 3px; | ||
color: var(--very-dark-gray); | ||
} | ||
|
||
&.active { | ||
background-color: var(--dark-tomato); | ||
fill: var(--white); | ||
border-radius: 50%; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
} | ||
} | ||
|
||
.userContainer>svg { | ||
width: 20px; | ||
height: 20px; | ||
transition: fill .2s; | ||
} | ||
|
||
.userContainer:not(.active):hover>svg { | ||
fill: #6f6f6f; | ||
} | ||
|
||
.userContainer.active>svg { | ||
scale: .7; | ||
} |