initial commit

This commit is contained in:
2025-09-24 20:32:28 +05:00
commit 1759326253
184 changed files with 23284 additions and 0 deletions

View File

@@ -0,0 +1,258 @@
.navbar {
display: flex;
flex-direction: column;
align-items: center;
color: #fff;
background-color: #fff;
justify-content: center;
position: sticky;
top: 0;
z-index: 99;
.navbarUp {
width: 100%;
background-color: #fff;
margin-bottom: 1px;
border-bottom: 3px solid #f3f4f6;
}
.btn{
display: flex;
width: max-content;
font-size: 14px;
border-radius: 4px;
border: #000000;
background-color: #000000;
padding: 6px 10px;
font-weight: bold;
color: #ffffff;
}
.navbarDown {
width: 100%;
background-color: #ffffff;
max-width: 1366px;
position: sticky;
top: 0;
padding-top: 12px;
padding-bottom: 12px;
padding-left: 1.375rem;
padding-right: 1.375rem;
box-sizing: border-box;
display: none;
@media screen and (min-width: 1024px) {
display: block;
}
}
.logo {
display: flex;
width: 100%;
padding: 10px 22px 0px;
height: 60px;
gap: 10px;
margin: 0 auto;
cursor: pointer;
@media screen and (max-width: 426px) {
height: 40px;
justify-content: flex-start;
padding: 10px 15px 6px;
}
}
.logoContainer {
display: flex;
justify-content: center;
border-radius: 10px;
padding: 8px 14px 6px;
box-sizing: border-box;
justify-content: center;
flex-direction: column;
@media screen and (max-width: 426px) {
width: 80px;
}
svg {
width: 100%;
height: 100%;
}
}
.stick {
width: 0.5px !important;
background-color: #4b5563;
height: auto;
@media screen and (max-width: 1023px) {
height: 24px;
}
}
.navLinks ul {
list-style: none;
display: flex;
justify-content: center;
margin: 0 auto 0 auto;
box-sizing: border-box;
gap: 5px;
li,
a {
text-decoration: none;
color: #4b5563;
font-size: 14px;
}
li {
display: flex;
align-items: center;
gap: 5px;
margin: 0;
svg {
fill: #4b5563;
width: 20px;
height: 20px;
}
}
.searchWrapper {
display: flex;
align-items: center;
flex: 1;
flex-direction: row-reverse;
svg {
position: absolute;
width: 24px;
height: 24px;
transform: translateX(-35%);
}
input {
width: 100%;
height: 40px;
border-radius: 8px;
font-size: 0.75rem;
padding: 4px 16px;
background-color: #e5e7eb;
box-sizing: border-box;
border: none;
outline: none;
&::placeholder {
color: #9ca3af;
font-size: 0.75rem;
}
}
}
}
.navButton {
display: flex;
gap: 5px;
border: none;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.875rem;
padding-right: 0.875rem;
justify-content: center;
align-items: center;
border-radius: 0.5rem;
height: 2.5rem;
font-size: 0.875rem;
color: #4b5563;
font-weight: 600;
background-color: transparent;
cursor: pointer;
&:hover {
background-color: #f3f4f6;
}
}
.cartSection {
.cartLink {
display: flex;
align-items: center;
text-decoration: none;
color: #fff;
font-size: 16px;
.cartIcon {
margin-right: 5px;
font-size: 20px;
}
}
}
}
// mobile
.navbarContainer {
display: flex;
flex-direction: column;
align-items: center;
padding: 11px 0;
width: 100%;
box-sizing: border-box;
position: sticky;
@media screen and (min-width: 1024px) {
display: none;
}
@media screen and (max-width: 426px) {
padding: 9px 0;
}
}
.navbarContent {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
max-width: 1024px;
color: #4b5563;
font-size: 14px;
padding: 0 1.375rem;
box-sizing: border-box;
}
.categories,
.location {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
gap: 5px;
svg {
width: 16px;
height: 16px;
}
}
.searchIcon {
min-width: 60px;
display: flex;
justify-content: center;
svg {
width: 24px;
height: 24px;
}
}
.searchInputWrapper {
margin-top: 10px;
width: 100%;
max-width: 1024px;
display: flex;
justify-content: center;
padding: 0 1.375rem;
box-sizing: border-box;
}
.searchInput {
width: 100%;
height: 40px;
border-radius: 8px;
font-size: 0.75rem;
padding: 4px 16px;
background-color: #e5e7eb;
box-sizing: border-box;
border: none;
outline: none;
&::placeholder {
color: #9ca3af;
font-size: 0.75rem;
}
}

View File

@@ -0,0 +1,307 @@
import { useState, useEffect } from "react";
import { CartIcon, WishlistIcon, BrandIcon, OrderIcon } from "../Icons";
import styles from "./Navbar.module.scss";
import { UserOutlined, LogoutOutlined, HomeOutlined } from "@ant-design/icons";
import { FaGlobe } from "react-icons/fa6";
import { Input, Badge, Menu, Dropdown } from "antd";
const { Search } = Input;
import DropdownMenu from "../CategoryDropdown/index";
import LoginModal from "../LogIn/index";
import SignUpModal from "../SignUp/index";
import { Link, useNavigate } from "react-router-dom";
import { CiSearch } from "react-icons/ci";
import tm from "../../assets/tm.png";
import ru from "../../assets/ru.png";
import en from "../../assets/en.png";
import { CiLocationOn } from "react-icons/ci";
import Sidebar from "../CategorySideBar";
import { useTranslation } from "react-i18next";
import { useSearchProductQuery } from "../../app/api/searchApi";
import { useGetCartQuery } from "../../app/api/cartApi";
import { useGetOrdersQuery } from "../../app/api/orderApi";
import { useGetFavoritesQuery } from "../../app/api/favoritesApi";
import { useAuth } from "../../context/authContext";
import ProfileModal from "../../components/MyProfileModal/index";
const NavbarDown = () => {
const [isSearchVisible, setSearchVisible] = useState(false);
const { t, i18n } = useTranslation();
const [searchQuery, setSearchQuery] = useState("");
const navigate = useNavigate();
const { data: searchData, refetch } = useSearchProductQuery(searchQuery, {
skip: !searchQuery,
});
const { data: cartData } = useGetCartQuery(undefined, {
refetchOnMountOrArgChange: false,
});
const { isAuthenticated, logout } = useAuth();
const cartItemCount =
cartData?.data?.reduce((total, item) => {
return total + (parseInt(item.product_quantity, 10) || 0);
}, 0) || 0;
const { data: ordersData } = useGetOrdersQuery();
const ordersItemCount = ordersData?.length || 0;
const { data: favoritesData } = useGetFavoritesQuery();
const favoritesItemCount = favoritesData?.length || 0;
const [profileModalVisible, setProfileModalVisible] = useState(false);
const handleSearch = () => {
if (searchQuery.trim()) {
refetch();
navigate(`/search?keyword=${encodeURIComponent(searchQuery)}`, {
state: {
searchData,
searchQuery,
},
});
}
};
const toggleSearch = () => {
setSearchVisible(!isSearchVisible);
};
const changeLanguage = (langCode) => {
i18n.changeLanguage(langCode);
localStorage.setItem("preferredLanguage", langCode);
window.location.reload();
};
const handleLogout = async () => {
await logout();
};
useEffect(() => {}, [isAuthenticated]);
const items = [
{
key: "tk",
label: (
<div onClick={() => changeLanguage("tk")}>
<img
src={tm}
alt={t("navbar.languages.tm")}
style={{ width: "20px", marginRight: "10px" }}
/>
{t("navbar.languages.tm")}
</div>
),
},
{
key: "ru",
label: (
<div onClick={() => changeLanguage("ru")}>
<img
src={ru}
alt={t("navbar.languages.ru")}
style={{ width: "20px", marginRight: "10px" }}
/>
{t("navbar.languages.ru")}
</div>
),
},
{
key: "en",
label: (
<div onClick={() => changeLanguage("en")}>
<img
src={en}
alt={t("navbar.languages.en")}
style={{ width: "20px", marginRight: "10px" }}
/>
{t("navbar.languages.en")}
</div>
),
},
];
const profileItems = [
{
key: "profile",
label: (
<div onClick={() => setProfileModalVisible(true)}>
<UserOutlined style={{ marginRight: "10px" }} />
{t("profile.my_profile")}
</div>
),
},
// {
// key: "address",
// label: (
// <Link to="/addresses">
// <HomeOutlined style={{ marginRight: "10px" }} />
// {t("profile.my_address")}
// </Link>
// ),
// },
{
key: "logout",
label: (
<div onClick={handleLogout}>
<LogoutOutlined style={{ marginRight: "10px" }} />
{t("profile.logout")}
</div>
),
},
];
return (
<header className={styles.navbar}>
<div className={styles.navbarDown} style={{ position: "sticky" }}>
<nav className={styles.navLinks}>
<ul>
<li>
<DropdownMenu />
</li>
<div className={styles.stick}></div>
<li>
{" "}
<Link to={"/brands"}>
<button className={styles.navButton}>
<BrandIcon />
{t("navbar.brands")}
</button>
</Link>
</li>
<li className={styles.searchWrapper}>
<CiSearch />
<input
type="text"
placeholder="Haryt ady boyunca gozle..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
onKeyPress={(e) => {
if (e.key === "Enter") {
handleSearch();
}
}}
/>
</li>
<li>
<Dropdown
menu={{ items }}
placement="bottomLeft"
trigger={["click"]}
>
<span
className={styles.navButton}
style={{ cursor: "pointer" }}
>
<FaGlobe />
</span>
</Dropdown>
</li>
<div className={styles.stick}></div>
{!isAuthenticated ? (
<>
<li>
<LoginModal />
</li>
<div className={styles.stick}></div>
{/* <li>
<SignUpModal />
</li> */}
</>
) : (
<>
<li>
<Dropdown
menu={{ items: profileItems }}
placement="bottomLeft"
trigger={["click"]}
>
<span
className={styles.navButton}
style={{ cursor: "pointer" }}
>
<UserOutlined /> {t("profile.my_profile")}
</span>
</Dropdown>
</li>
<div className={styles.stick}></div>
</>
)}
<li>
<Link to={"/orders"}>
<Badge
style={{ marginRight: "4px" }}
count={ordersItemCount}
offset={[10, 0]}
>
<button className={styles.navButton}>
<OrderIcon />
</button>
</Badge>
</Link>
</li>
<div className={styles.stick}></div>
<li>
<Link to={"/wishlist"}>
<Badge
style={{ marginRight: "4px" }}
count={favoritesItemCount}
offset={[10, 0]}
>
<button className={styles.navButton}>
<WishlistIcon />
</button>
</Badge>
</Link>
</li>
<div className={styles.stick}></div>
<li>
<Link to={"/cart"}>
<Badge count={cartItemCount} offset={[10, 0]}>
<button className={styles.navButton}>
<CartIcon />
</button>
</Badge>
</Link>
</li>
</ul>
</nav>
</div>
{/* Mobile */}
<div className={styles.navbarContainer}>
<div className={styles.navbarContent}>
<div className={styles.categories}>
<Sidebar />
</div>
<div className={styles.stick}></div>
<div className={styles.location}>
<CiLocationOn /> Aşgabat
</div>
<div className={styles.stick}></div>
<div className={styles.searchIcon} onClick={toggleSearch}>
<CiSearch />
</div>
</div>
{isSearchVisible && (
<div className={styles.searchInputWrapper}>
<input
className={styles.searchInput}
type="text"
placeholder="Haryt ady boyunca gozle..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
onKeyPress={(e) => {
if (e.key === "Enter") {
handleSearch();
}
}}
/>
</div>
)}
</div>
{isAuthenticated && (
<ProfileModal
visible={profileModalVisible}
onClose={() => setProfileModalVisible(false)}
/>
)}
</header>
);
};
export default NavbarDown;

View File

@@ -0,0 +1,54 @@
import styles from "./Navbar.module.scss";
import { Modal } from "antd";
import SignupForm from "../BeSeller/index";
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import { LogoWithText } from "../Icons";
import Logo from "../../assets/logo2.png"
const Navbar = () => {
const [isModalVisible, setIsModalVisible] = useState(false);
const navigate = useNavigate();
const showModal = () => {
setIsModalVisible(true);
};
const handleCancel = () => {
setIsModalVisible(false);
};
return (
<>
<header className={styles.navbar}>
<div className={styles.navbarUp}>
<div
style={{ maxWidth: "1366px", display: "flex", margin: "0 auto", alignItems: "center"}}
>
<div className={styles.logo}>
<div
className={styles.logoContainer}
onClick={() => navigate("/")}
>
{/* <LogoWithText /> */}
<img style={{width: "200px"}} src={Logo} alt="" />
</div>
</div>
<div style={{ display: "flex", alignItems: "center", padding: "8px 14px 6px" }}>
<button className={styles.btn} onClick={showModal}>
Satyjy bol
</button>
</div>
</div>
</div>
</header>
<Modal
open={isModalVisible}
onCancel={handleCancel}
footer={null}
width={900}
>
<SignupForm />
</Modal>
</>
);
};
export default Navbar;