diff --git a/index.html b/index.html index 1c1a6b5..7f6a544 100644 --- a/index.html +++ b/index.html @@ -3,10 +3,38 @@ - persian game + پرشین پینگ | فروشگاه + + +
+ diff --git a/src/App.tsx b/src/App.tsx index 889a3fd..45a7c67 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -17,8 +17,17 @@ import Profile from "./pages/profile"; import { Toaster } from "react-hot-toast"; import { IsAuthenticated } from "./utils/auth"; import { HelmetProvider } from "react-helmet-async"; +import InActivePayment from "./pages/inActivePayment"; +import { useSelector } from "react-redux"; +import { RootState } from "./redux/store"; +import Page404 from "./pages/404"; +// import LandingLayout from "./layout/LandingLayout"; +// import Landing from "./pages/landing"; const App = () => { + const { isPaymentGateway } = useSelector( + (state: RootState) => state.isPaymentGatewayState + ); return ( @@ -29,9 +38,13 @@ const App = () => { /> + {/* }> + }> + } /> + */} }> } /> - } /> + } /> } /> } /> } /> @@ -40,10 +53,10 @@ const App = () => { + ) : ( ) @@ -51,6 +64,17 @@ const App = () => { > } /> + + ) : ( + + ) + } + /> + } /> diff --git a/src/assets/product-image/callof/cp-callofduty2400.png b/src/assets/product-image/callof/cp-callofduty2400.png new file mode 100644 index 0000000..6499e21 Binary files /dev/null and b/src/assets/product-image/callof/cp-callofduty2400.png differ diff --git a/src/assets/product-image/callof/cp-callofduty360.png b/src/assets/product-image/callof/cp-callofduty360.png new file mode 100644 index 0000000..23a35d2 Binary files /dev/null and b/src/assets/product-image/callof/cp-callofduty360.png differ diff --git a/src/assets/product-image/callof/cp-callofduty80.png b/src/assets/product-image/callof/cp-callofduty80.png new file mode 100644 index 0000000..e3d4979 Binary files /dev/null and b/src/assets/product-image/callof/cp-callofduty80.png differ diff --git a/src/assets/product-image/callof/cp-callofduty880.png b/src/assets/product-image/callof/cp-callofduty880.png new file mode 100644 index 0000000..9bad943 Binary files /dev/null and b/src/assets/product-image/callof/cp-callofduty880.png differ diff --git a/src/assets/product-image/clash/clashofclans-gem1200.png b/src/assets/product-image/clash/clashofclans-gem1200.png new file mode 100644 index 0000000..6f85f5f Binary files /dev/null and b/src/assets/product-image/clash/clashofclans-gem1200.png differ diff --git a/src/assets/product-image/clash/clashofclans-gem2500.png b/src/assets/product-image/clash/clashofclans-gem2500.png new file mode 100644 index 0000000..a38d045 Binary files /dev/null and b/src/assets/product-image/clash/clashofclans-gem2500.png differ diff --git a/src/assets/product-image/clash/clashofclans-gem500.png b/src/assets/product-image/clash/clashofclans-gem500.png new file mode 100644 index 0000000..9e8809c Binary files /dev/null and b/src/assets/product-image/clash/clashofclans-gem500.png differ diff --git a/src/assets/product-image/clash/clashofclans-gem6500.png b/src/assets/product-image/clash/clashofclans-gem6500.png new file mode 100644 index 0000000..550eccc Binary files /dev/null and b/src/assets/product-image/clash/clashofclans-gem6500.png differ diff --git a/src/assets/product-image/pubg/uc-pubgmobile1875.png b/src/assets/product-image/pubg/uc-pubgmobile1875.png new file mode 100644 index 0000000..69bdbdc Binary files /dev/null and b/src/assets/product-image/pubg/uc-pubgmobile1875.png differ diff --git a/src/assets/product-image/pubg/uc-pubgmobile340.png b/src/assets/product-image/pubg/uc-pubgmobile340.png new file mode 100644 index 0000000..13585a3 Binary files /dev/null and b/src/assets/product-image/pubg/uc-pubgmobile340.png differ diff --git a/src/assets/product-image/pubg/uc-pubgmobile63.png b/src/assets/product-image/pubg/uc-pubgmobile63.png new file mode 100644 index 0000000..29750fd Binary files /dev/null and b/src/assets/product-image/pubg/uc-pubgmobile63.png differ diff --git a/src/assets/product-image/pubg/uc-pubgmobile690.png b/src/assets/product-image/pubg/uc-pubgmobile690.png new file mode 100644 index 0000000..ae4591a Binary files /dev/null and b/src/assets/product-image/pubg/uc-pubgmobile690.png differ diff --git a/src/assets/svg/404.svg b/src/assets/svg/404.svg new file mode 100644 index 0000000..b9bf23c --- /dev/null +++ b/src/assets/svg/404.svg @@ -0,0 +1,340 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/footer/components/SocialMedia.tsx b/src/components/footer/components/SocialMedia.tsx index 5afaac7..ecc5869 100644 --- a/src/components/footer/components/SocialMedia.tsx +++ b/src/components/footer/components/SocialMedia.tsx @@ -2,7 +2,7 @@ import { FaInstagram, FaTelegram, FaTwitter } from "react-icons/fa6"; const SocialMedia = () => { return ( -
+
diff --git a/src/components/footer/index.tsx b/src/components/footer/index.tsx index 3cb17e9..ff515a4 100644 --- a/src/components/footer/index.tsx +++ b/src/components/footer/index.tsx @@ -2,12 +2,33 @@ import CopyRight from "./components/CopyRight"; import SocialMedia from "./components/SocialMedia"; const Footer = () => { + const code = "k8K3Na16cdzB31hBnriumB3rvZOblawy"; + return ( -
-
- -
- +
+
+
); diff --git a/src/components/header/components/navbar/Navbar.tsx b/src/components/header/components/navbar/Navbar.tsx index 571dbdc..fca6d00 100644 --- a/src/components/header/components/navbar/Navbar.tsx +++ b/src/components/header/components/navbar/Navbar.tsx @@ -44,7 +44,7 @@ const Navbar = ({extra}:{extra?:string}) => { })}
{auth ? ( - + ) : ( )} diff --git a/src/components/header/components/navbar/NavbarLink.tsx b/src/components/header/components/navbar/NavbarLink.tsx index fc093fc..7dd95b4 100644 --- a/src/components/header/components/navbar/NavbarLink.tsx +++ b/src/components/header/components/navbar/NavbarLink.tsx @@ -1,12 +1,13 @@ -import { NavLink } from "react-router-dom"; +import { NavLink, useLocation } from "react-router-dom"; import { NavbarLinkProps, NavData } from "../../../../types/props"; const NavbarLink = ({ to, children, onClick }: NavbarLinkProps) => { + const location = useLocation(); return ( - navData.isActive + navData.isActive && location.pathname === to ? "block px-2 mx-3 py-2 text-base font-medium text-secondTheme border-b-2 border-secondTheme" : "block px-2 mx-3 py-2 rounded-md text-base font-medium text-white" } diff --git a/src/components/landing-header/components/navbar/MobileMenu.tsx b/src/components/landing-header/components/navbar/MobileMenu.tsx new file mode 100644 index 0000000..a3b7609 --- /dev/null +++ b/src/components/landing-header/components/navbar/MobileMenu.tsx @@ -0,0 +1,51 @@ +// src/components/Header/Navbar/MobileMenu.tsx +import { MobileMenuProps } from "../../../../types/props"; +import NavbarLink from "./NavbarLink"; +const MobileMenu = ({ isOpen, toggleMenu, routes }: MobileMenuProps) => { + return ( + <> +
+
+ +
+
+ {routes?.map((i) => { + return ( + + {i.name} + + ); + })} +
+
+ {isOpen && ( +
+ )} + + ); +}; + +export default MobileMenu; diff --git a/src/components/landing-header/components/navbar/MobileMenuButton.tsx b/src/components/landing-header/components/navbar/MobileMenuButton.tsx new file mode 100644 index 0000000..3bcb7eb --- /dev/null +++ b/src/components/landing-header/components/navbar/MobileMenuButton.tsx @@ -0,0 +1,48 @@ +import { MobileMenuButtonProps } from "../../../../types/props"; + +const MobileMenuButton = ({ isOpen, onClick }: MobileMenuButtonProps) => { + return ( + + ); +}; + +export default MobileMenuButton; diff --git a/src/components/landing-header/components/navbar/Navbar.tsx b/src/components/landing-header/components/navbar/Navbar.tsx new file mode 100644 index 0000000..83d1f84 --- /dev/null +++ b/src/components/landing-header/components/navbar/Navbar.tsx @@ -0,0 +1,53 @@ +// src/components/Header/Navbar/Navbar.tsx +import { useState, useEffect } from "react"; +import MobileMenuButton from "./MobileMenuButton"; +import MobileMenu from "./MobileMenu"; +import NavbarLink from "./NavbarLink"; +import router from "../../../../routes/routes"; +import Button from "../../../button"; +import { Route } from "../../../../types/props"; + +const Navbar = ({extra}:{extra?:string}) => { + const [isOpen, setIsOpen] = useState(false); + const [routes] = useState(router); + + const toggleMenu = () => { + setIsOpen(!isOpen); + }; + + useEffect(() => { + if (isOpen) { + document.body.style.overflow = "hidden"; + } else { + document.body.style.overflow = "auto"; + } + }, [isOpen]); + + return ( +
+ + +
+ ); +}; + +export default Navbar; diff --git a/src/components/landing-header/components/navbar/NavbarLink.tsx b/src/components/landing-header/components/navbar/NavbarLink.tsx new file mode 100644 index 0000000..7dd95b4 --- /dev/null +++ b/src/components/landing-header/components/navbar/NavbarLink.tsx @@ -0,0 +1,21 @@ +import { NavLink, useLocation } from "react-router-dom"; +import { NavbarLinkProps, NavData } from "../../../../types/props"; + +const NavbarLink = ({ to, children, onClick }: NavbarLinkProps) => { + const location = useLocation(); + return ( + + navData.isActive && location.pathname === to + ? "block px-2 mx-3 py-2 text-base font-medium text-secondTheme border-b-2 border-secondTheme" + : "block px-2 mx-3 py-2 rounded-md text-base font-medium text-white" + } + onClick={onClick} + > + {children} + + ); +}; + +export default NavbarLink; diff --git a/src/components/landing-header/index.tsx b/src/components/landing-header/index.tsx new file mode 100644 index 0000000..f2764cd --- /dev/null +++ b/src/components/landing-header/index.tsx @@ -0,0 +1,29 @@ +import { useEffect, useState } from "react"; +import Navbar from "./components/navbar/Navbar"; +const LandingHeader = () => { + const [isFixed, setIsFixed] = useState(false); + + useEffect(() => { + const handleScroll = () => { + if (window.scrollY > 50) { + setIsFixed(true); + } else { + setIsFixed(false); + } + }; + window.addEventListener("scroll", handleScroll); + return () => { + window.removeEventListener("scroll", handleScroll); + }; + }, []); + + return ( +
+
+ +
+
+ ); +}; + +export default LandingHeader; diff --git a/src/components/progressSpace/index.tsx b/src/components/progressSpace/index.tsx index b79865e..29dd1f2 100644 --- a/src/components/progressSpace/index.tsx +++ b/src/components/progressSpace/index.tsx @@ -4,10 +4,22 @@ import { ProgressSpaceProps } from "../../types/props"; const ProgressSpace = ({ startSpace, endSpace }: ProgressSpaceProps) => { let startSpacePercentage; let remaining; - if (typeof endSpace === "number") { - startSpacePercentage = (startSpace / endSpace) * 100; - remaining = endSpace - startSpace; + let startSpaceToNumber = Number(startSpace); + let endSpaceToNumber = Number(endSpace); + + const isMaxSpace = startSpaceToNumber >= endSpaceToNumber; + + if (!isNaN(startSpaceToNumber) && !isNaN(endSpaceToNumber) && startSpaceToNumber <= endSpaceToNumber) { + startSpacePercentage = (startSpaceToNumber / endSpaceToNumber) * 100; + remaining = endSpaceToNumber - startSpaceToNumber; + } else if (isMaxSpace) { + remaining = 0; + startSpacePercentage = 100; + } else { + remaining = 0; + startSpacePercentage = 0; } + return ( <>
@@ -18,7 +30,7 @@ const ProgressSpace = ({ startSpace, endSpace }: ProgressSpaceProps) => {
{
-

- {" "} - حجم باقیمانده کانفیگ شما از{" "} - {endSpace === "unlimited" ? "نامحدود" : endSpace} گیگ{" "} - {remaining} - گیگ میباشد{" "} -

+ {isMaxSpace ? ( +

حجم شما به پایان رسیده است

+ ) : ( +

+ حجم باقیمانده کانفیگ شما از{" "} + {endSpace === "unlimited" ? "نامحدود" : endSpace} گیگ{" "} + + {remaining.toFixed(2)} + {" "} + گیگ می‌باشد +

+ )}
); diff --git a/src/layout/LandingLayout.tsx b/src/layout/LandingLayout.tsx new file mode 100644 index 0000000..8f76afa --- /dev/null +++ b/src/layout/LandingLayout.tsx @@ -0,0 +1,58 @@ +import { Helmet } from "react-helmet-async"; +import Particle from "../components/particle"; +import { Outlet, useLocation, useNavigate, useParams } from "react-router-dom"; +import Footer from "../components/footer"; +import LandingHeader from "../components/landing-header"; +import { useEffect } from "react"; +import { setConfigId } from "../redux/slices/configId"; +import { useDispatch } from "react-redux"; + +const LandingLayout = () => { + const location = useLocation(); + const navigate = useNavigate(); + useEffect(() => { + if (location.hash === "#shoppingConfig") { + navigate("/shopping-config"); + } + }, [location]); + + const { configs } = useParams<{ configs: string }>(); + const dispatch = useDispatch(); + console.log(configs) + useEffect(() => { + if (configs === "1" || configs === "2" || configs === "3") { + dispatch(setConfigId(configs)) + } + }, [configs]); + + return ( + <> + + پرشین پینگ | Persian Ping + + + + + +
+
+
+ +
+ +
+
+
+
+
+ + ); +}; + +export default LandingLayout; diff --git a/src/layout/index.tsx b/src/layout/index.tsx index 1fdc1e5..0060108 100644 --- a/src/layout/index.tsx +++ b/src/layout/index.tsx @@ -11,8 +11,9 @@ const Layout = () => { const { configs } = useParams<{ configs: string }>(); const dispatch = useDispatch(); useEffect(() => { - if (configs === "1" || configs === "2" || configs === "3") + if (configs === "1" || configs === "2" || configs === "3") { dispatch(setConfigId(configs)); + } if (configs) setTimeout(() => { const element = document.getElementById("configs"); diff --git a/src/pages/404/index.tsx b/src/pages/404/index.tsx new file mode 100644 index 0000000..fab39dc --- /dev/null +++ b/src/pages/404/index.tsx @@ -0,0 +1,31 @@ +import Particle from "../../components/particle" +import Svg404 from '../../assets/svg/404.svg' +import { Helmet } from "react-helmet-async" +const Page404 = () => { + return ( + <> + + + صفحه پیدا نشد 404 + + + + + +
+
+ 404 +

صفحه مورد نظر یافت نشد

+
+
+ + ) +} + +export default Page404 \ No newline at end of file diff --git a/src/pages/about/index.tsx b/src/pages/about/index.tsx index c12769c..8ad39e9 100644 --- a/src/pages/about/index.tsx +++ b/src/pages/about/index.tsx @@ -5,15 +5,16 @@ const About = () => { return ( <> - درباره ما + پرشین پینگ | درباره ما +
diff --git a/src/pages/inActivePayment/components/NoPayment.tsx b/src/pages/inActivePayment/components/NoPayment.tsx new file mode 100644 index 0000000..4a986f8 --- /dev/null +++ b/src/pages/inActivePayment/components/NoPayment.tsx @@ -0,0 +1,44 @@ +import { BiError } from "react-icons/bi"; +import Button from "../../../components/button"; +import { FaTelegram } from "react-icons/fa6"; + +const NoPayment = () => { + return ( +
+
+
+ +

+ درگاه پرداخت به صورت موقت غیر فعال شده است +

+
+
+

+ کاربر گرامی بابت پیش آمدن این مشکل صمیمانه از شما عذر خواهی می کنیم + و در تلاشیم هرچه زودتر مشکل درگاه پرداخت را بررسی کرده و سریع به + روال قبلی برگردانیم،
+ + برای خرید کانفیگ مورد نظر می توانید به پشتیبانی ما در تلگرام پیام + دهید + {" "} + ، از صبر شما سپاسگذاریم .{" "} +

+
+
+

+ برای خرید از پشتیبانی در تلگرام لطفا دکمه زیر را کلیک کنید +

+ +
+
+
+ ); +}; + +export default NoPayment; diff --git a/src/pages/inActivePayment/index.tsx b/src/pages/inActivePayment/index.tsx new file mode 100644 index 0000000..7d43128 --- /dev/null +++ b/src/pages/inActivePayment/index.tsx @@ -0,0 +1,17 @@ +import Particle from "../../components/particle"; +import NoPayment from "./components/NoPayment"; + +const InActivePayment = () => { + return ( + <> + +
+
+ +
+
+ + ); +}; + +export default InActivePayment; diff --git a/src/pages/landing/index.tsx b/src/pages/landing/index.tsx new file mode 100644 index 0000000..8fa0dee --- /dev/null +++ b/src/pages/landing/index.tsx @@ -0,0 +1,37 @@ +import { Helmet } from "react-helmet-async"; +import BestQuality from "./section/bestQuality/BestQuality"; +import FastSell from "./section/fastSell/FastSell"; +import Intro from "./section/intro/Intro"; +import NowSell from "./section/nowSell/NowSell"; +import ProductList from "./section/productList/ProductList"; + +const Landing = () => { + return ( + <> + + پرشین پینگ | فروشگاه + + + + + +
+
+ + + + + +
+
+ + ); +}; + +export default Landing; diff --git a/src/pages/landing/section/bestQuality/BestQuality.tsx b/src/pages/landing/section/bestQuality/BestQuality.tsx new file mode 100644 index 0000000..52d65d0 --- /dev/null +++ b/src/pages/landing/section/bestQuality/BestQuality.tsx @@ -0,0 +1,25 @@ +import PulsatingCircle from "../../../../components/pulsatingCircle"; + +const BestQuality = () => { + return ( +
+
+ +
+
+

+ به عنوان{" "} + + اولین و بهترین + {" "} + ارائه دهنده{" "} +

+

+ مفتخریم که در خدمت شما باشیم +

+
+
+ ); +}; + +export default BestQuality; diff --git a/src/pages/landing/section/fastSell/FastSell.tsx b/src/pages/landing/section/fastSell/FastSell.tsx new file mode 100644 index 0000000..983a099 --- /dev/null +++ b/src/pages/landing/section/fastSell/FastSell.tsx @@ -0,0 +1,19 @@ +import { FaPowerOff } from "react-icons/fa6"; +import LoaderSpin from "../../../../components/loaderSpin"; +import Typewriter from "../../../../components/typeWriter"; + +const FastSell = () => { + return ( +
+
+ + + + + +
+
+ ); +}; + +export default FastSell; diff --git a/src/pages/landing/section/intro/Intro.tsx b/src/pages/landing/section/intro/Intro.tsx new file mode 100644 index 0000000..83bc910 --- /dev/null +++ b/src/pages/landing/section/intro/Intro.tsx @@ -0,0 +1,34 @@ +import Button from "../../../../components/button"; + +import Rocket3D from "../../../../assets/ui/Rocket.png"; +import SmoothScrollLink from "../../../../components/scrollLink"; + +const Intro = () => { + return ( +
+
+

+ بزرگترین فروشگاه + + خرید سی پی تنها با چند کلیک + +

+

+ سال ها تجربه پشت یک خرید شماست +

+ + + +
+
+ intro +
+
+ ); +}; + +export default Intro; diff --git a/src/pages/landing/section/nowSell/NowSell.tsx b/src/pages/landing/section/nowSell/NowSell.tsx new file mode 100644 index 0000000..2dec480 --- /dev/null +++ b/src/pages/landing/section/nowSell/NowSell.tsx @@ -0,0 +1,13 @@ +import Content from "./components/Content"; + +const NowSell = () => { + return ( +
+
+ +
+
+ ); +}; + +export default NowSell; diff --git a/src/pages/landing/section/nowSell/components/Content.tsx b/src/pages/landing/section/nowSell/components/Content.tsx new file mode 100644 index 0000000..f615df5 --- /dev/null +++ b/src/pages/landing/section/nowSell/components/Content.tsx @@ -0,0 +1,23 @@ +import Button from "../../../../../components/button"; + +const Content = () => { + return ( +
+

+ با چندین سال +

+

+ تجربـــــــــــــــــــه +

+

+ بهترین نتیجه رو بهتون تقدیم میکنیم +

+ +
+ ); +}; + +export default Content; diff --git a/src/pages/landing/section/productList/ProductList.tsx b/src/pages/landing/section/productList/ProductList.tsx new file mode 100644 index 0000000..7a45f7a --- /dev/null +++ b/src/pages/landing/section/productList/ProductList.tsx @@ -0,0 +1,24 @@ +import { useState } from "react"; +import ButtonList from "./components/ButtonList"; +import ListAllProduct from "./components/ListAllProduct"; + +const ProductList = () => { + const [activeId, setActiveId] = useState(0); + + return ( +
+
+

+ برای انتخاب سی پی یا جم مورد نظر کلیک کنید تا براتون نمایش داده شود +

+ + +
+
+ ); +}; + +export default ProductList; diff --git a/src/pages/landing/section/productList/components/ButtonList.tsx b/src/pages/landing/section/productList/components/ButtonList.tsx new file mode 100644 index 0000000..74b64fc --- /dev/null +++ b/src/pages/landing/section/productList/components/ButtonList.tsx @@ -0,0 +1,27 @@ +import { Dispatch, SetStateAction } from "react"; +import Button from "../../../../../components/button"; + +const ButtonList = ({ activeId, setActiveId } : {activeId:number;setActiveId:Dispatch>}) => { + const ProductsList: { id: number; name: string; label?: string }[] = [ + { id: 0, name: "یوسی پابجی", label: "uc pubg" }, + { id: 1, name: "سی پی کالاف", label: "cp callof" }, + { id: 2, name: "جم کلش", label: "gem clash" }, + ]; + return ( +
+ {ProductsList?.map((product) => ( + + ))} +
+ ); +}; + +export default ButtonList; diff --git a/src/pages/landing/section/productList/components/ListAllProduct.tsx b/src/pages/landing/section/productList/components/ListAllProduct.tsx new file mode 100644 index 0000000..02a258f --- /dev/null +++ b/src/pages/landing/section/productList/components/ListAllProduct.tsx @@ -0,0 +1,67 @@ +import { useEffect, useState } from "react"; +import Button from "../../../../../components/button"; + +import clash1 from "../../../../../assets/product-image/clash/clashofclans-gem500.png"; +import clash2 from "../../../../../assets/product-image/clash/clashofclans-gem1200.png"; +import clash3 from "../../../../../assets/product-image/clash/clashofclans-gem2500.png"; +import clash4 from "../../../../../assets/product-image/clash/clashofclans-gem6500.png"; + +import pubg1 from "../../../../../assets/product-image/pubg/uc-pubgmobile63.png"; +import pubg2 from "../../../../../assets/product-image/pubg/uc-pubgmobile340.png"; +import pubg3 from "../../../../../assets/product-image/pubg/uc-pubgmobile690.png"; +import pubg4 from "../../../../../assets/product-image/pubg/uc-pubgmobile1875.png"; + +import callof1 from "../../../../../assets/product-image/callof/cp-callofduty80.png"; +import callof2 from "../../../../../assets/product-image/callof/cp-callofduty360.png"; +import callof3 from "../../../../../assets/product-image/callof/cp-callofduty880.png"; +import callof4 from "../../../../../assets/product-image/callof/cp-callofduty2400.png"; + +const ListAllProduct = ({ activeId }: { activeId: number }) => { + const allProducts = [ + [ + { id: 1, title: "پابجی 1", image: pubg1 }, + { id: 2, title: "پابجی 2", image: pubg2 }, + { id: 3, title: "پابجی 3", image: pubg3 }, + { id: 4, title: "پابجی 4", image: pubg4 }, + ], + [ + { id: 1, title: "کالاف 1", image: callof1 }, + { id: 2, title: "کالاف 2", image: callof2 }, + { id: 3, title: "کالاف 3", image: callof3 }, + { id: 4, title: "کالاف 4", image: callof4 }, + ], + + [ + { id: 1, title: "جم کلش 1", image: clash1 }, + { id: 2, title: "جم کلش 2", image: clash2 }, + { id: 3, title: "جم کلش 3", image: clash3 }, + { id: 4, title: "جم کلش 4", image: clash4 }, + ], + ]; + const [product, setProduct] = useState(allProducts[activeId]); + useEffect(() => { + setProduct(allProducts[activeId]); + }, [activeId]); + + return ( + <> +
+ {product.map((item) => { + return ( +
+ {item.title} +
+ +
+
+ ); + })} +
+ + ); +}; + +export default ListAllProduct; diff --git a/src/pages/profile/index.tsx b/src/pages/profile/index.tsx index a76423e..5c64bd8 100644 --- a/src/pages/profile/index.tsx +++ b/src/pages/profile/index.tsx @@ -74,7 +74,6 @@ const Profile = () => { return axios.get("/profile"); }, }); - return ( <> {!mutation.isPending && ( diff --git a/src/pages/profile/section/ProductConfigList.tsx b/src/pages/profile/section/ProductConfigList.tsx index 6ac758b..552f059 100644 --- a/src/pages/profile/section/ProductConfigList.tsx +++ b/src/pages/profile/section/ProductConfigList.tsx @@ -34,7 +34,7 @@ const ProductConfigList = ({ لیست کانفیگ ها

{isLoading || isFetching ? ( @@ -59,15 +59,15 @@ const ProductConfigList = ({ return ( ); diff --git a/src/pages/profile/section/components/ConfigItem.tsx b/src/pages/profile/section/components/ConfigItem.tsx index 59be119..b09bbed 100644 --- a/src/pages/profile/section/components/ConfigItem.tsx +++ b/src/pages/profile/section/components/ConfigItem.tsx @@ -9,37 +9,44 @@ import toast from "react-hot-toast"; import { useNavigate } from "react-router-dom"; import { useDispatch } from "react-redux"; import { setCategoryId } from "../../../../redux/slices/categoryId"; +import { useQuery } from "@tanstack/react-query"; +import useAxios from "../../../../hooks/useAxios"; +import LoaderSpaceConfig from "./LoaderSpaceConfig"; const ConfigItem = ({ + id, dateBuy, configName, isDisabled, isShowTraffic, textCopy, - maxTraffic, - traffic, type, categoryId, + useMaxTraffic }: ConfigItemProps) => { const [isOpen, setIsOpen] = useState(false); const [isOpenDropDown, setIsOpenDropDown] = useState(false); + const [configId, setConfigId] = useState(""); const dispatch = useDispatch(); const navigate = useNavigate(); + const [spaceConfig, setSpaceConfig] = useState({ + maxTraffic: 0, + traffic: 0, + }); + const axios = useAxios(); const handleToggle = () => { - setIsOpenDropDown(!isOpen); + console.log(id); + setConfigId(id); + setIsOpenDropDown(!isOpenDropDown); }; - const [copyText, setCopyText] = useState(""); + const [_, setCopyText] = useState(""); const copyToClipboard = async (textToCopy: string) => { try { await navigator.clipboard.writeText(textToCopy); toast.success("متن با موفقیت کپی شد!"); } catch (err) { - try { - await navigator.clipboard.writeText(copyText); - toast.success("متن با موفقیت کپی شد!"); - } catch (err) { - toast.error(`Failed to copy: , ${err}`); - } + toast.error(`Failed to copy: , ${err}`); + setIsOpen(true); } }; @@ -57,6 +64,25 @@ const ConfigItem = ({ } }, [textCopy]); + const queryUpdateConfig = useQuery({ + queryKey: ["updateConfig", isOpenDropDown || isOpen], + queryFn: () => { + if (configId) { + console.log("fethed"); + return axios.get(`/update-config/${configId}`); + }else{ + throw new Error("داده دریافتی یا پیدا نشده یا نامعتبر است") + } + }, + enabled: isOpenDropDown || isShowTraffic, + }); + useEffect(() => { + if (!queryUpdateConfig.isLoading || !queryUpdateConfig.isFetching) + setSpaceConfig({ + maxTraffic: queryUpdateConfig?.data?.data?.result?.max_traffic, + traffic: queryUpdateConfig?.data?.data?.result?.traffic, + }); + }, [queryUpdateConfig?.data, queryUpdateConfig.error]); return ( <>
- {isDisabled && ( + {isDisabled || useMaxTraffic && (
-
+
کانفیگ {configName} غیر فعال است .{" "}
@@ -101,16 +132,6 @@ const ConfigItem = ({
{type === "gaming" ? ( <> - + ) : ( - {isShowTraffic && ( + {isShowTraffic && !useMaxTraffic && ( diff --git a/src/pages/profile/section/components/LoaderSpaceConfig.tsx b/src/pages/profile/section/components/LoaderSpaceConfig.tsx new file mode 100644 index 0000000..ea16d1f --- /dev/null +++ b/src/pages/profile/section/components/LoaderSpaceConfig.tsx @@ -0,0 +1,60 @@ +export default function LoaderSpaceConfig() { + return ( + + + + + + + + + + + + ); +} diff --git a/src/pages/profile/section/components/ModalConfigDetails.tsx b/src/pages/profile/section/components/ModalConfigDetails.tsx index ba1b6a1..2c05960 100644 --- a/src/pages/profile/section/components/ModalConfigDetails.tsx +++ b/src/pages/profile/section/components/ModalConfigDetails.tsx @@ -8,6 +8,9 @@ import toast from "react-hot-toast"; import { useNavigate } from "react-router-dom"; import { useDispatch } from "react-redux"; import { setCategoryId } from "../../../../redux/slices/categoryId"; +import Input from "../../../../components/input"; +import LoaderSpaceConfig from "./LoaderSpaceConfig"; +import { AxiosError } from "axios"; const ModalConfigDetails = ({ isOpen, @@ -23,6 +26,9 @@ const ModalConfigDetails = ({ username, password, categoryId, + isLoadSpaceConfig, + error, + useMaxTraffic, }: { isOpen: boolean; setIsOpen: Dispatch>; @@ -37,10 +43,14 @@ const ModalConfigDetails = ({ username: string; password: string; categoryId: number; + isLoadSpaceConfig: boolean; + error: AxiosError | any; + useMaxTraffic: boolean; }) => { const navigate = useNavigate(); const dispatch = useDispatch(); - const [copyText, setCopyText] = useState(""); + const [_, setCopyText] = useState(""); + const [isCopyError, setIsCopyError] = useState(false); const copyToClipboard = async (textToCopy: string) => { try { @@ -48,12 +58,8 @@ const ModalConfigDetails = ({ toast.success("متن با موفقیت کپی شد!"); } catch (err) { - try { - await navigator.clipboard.writeText(copyText); - toast.success("متن با موفقیت کپی شد!"); - } catch (err) { - toast.error(`Failed to copy: , ${err}`); - } + setIsCopyError(true); + toast.error(`Failed to copy: , ${err}`); } }; return ( @@ -68,48 +74,95 @@ const ModalConfigDetails = ({ تاریخ خرید : {dateBuy}
- {isDisabled ? ( + {isDisabled || useMaxTraffic ? (
- + */} +
+ {useMaxTraffic ? ( +

مشترک گرامی کانفیگ شما به دلیل اتمام حجم غیر فعال است

+ ) : isDisabled && ( +

مشترک گرامی کانفیگ شما به دلیل پایان اعتبار غیر فعال است

+ )} +
) : ( <> {type === "gaming" ? ( <> - - + {isCopyError ? ( +
+

+ کاربر گرامی کپی خودکار موفقیت آمیز نبود لطفا به صورت + دستی از زیر انتخاب کرده و کپی کنید +

+ + +
+ ) : ( + <> + + + + )} ) : ( - + <> + {isCopyError ? ( + <> +
+

+ کاربر گرامی کپی خودکار موفقیت آمیز نبود لطفا به صورت + دستی از زیر انتخاب کرده و کپی کنید +

+ +
+ + ) : ( + + )} + )}
{!isDisabled && isShowTraffic && (
- + {isLoadSpaceConfig ? ( +
+ +
+ ) : error ? ( +
+ {" "} + خطایی رخ داد : {error?.message} +
+ ) : ( + + )}
)}
diff --git a/src/pages/rule/index.tsx b/src/pages/rule/index.tsx index 42faeb3..846e2cf 100644 --- a/src/pages/rule/index.tsx +++ b/src/pages/rule/index.tsx @@ -5,15 +5,16 @@ const Rule = () => { return ( <> - قوانین + پرشین پینگ | قوانین +
diff --git a/src/pages/shop/index.tsx b/src/pages/shop/index.tsx index 8869f81..9c82b5f 100644 --- a/src/pages/shop/index.tsx +++ b/src/pages/shop/index.tsx @@ -9,15 +9,16 @@ const Shop = () => { return ( <> - فروشگاه + پرشین پینگ | فروشگاه +
diff --git a/src/pages/shop/section/productList/components/ModalBuy.tsx b/src/pages/shop/section/productList/components/ModalBuy.tsx index 509b997..0a1ad4c 100644 --- a/src/pages/shop/section/productList/components/ModalBuy.tsx +++ b/src/pages/shop/section/productList/components/ModalBuy.tsx @@ -148,6 +148,9 @@ const ModalBuy = ({ isOpen, setIsOpen, configId }: ModalBuyProps) => { ) { errorMessage = (err.response.data as { alert: string }).alert; } + toast.error(`خطایی رخ داد : ${errorMessage}`) + // dispatch(setIsPaymentGateway(false)); + // navigate("/noactive-payment"); return errorMessage; }, }); @@ -157,7 +160,7 @@ const ModalBuy = ({ isOpen, setIsOpen, configId }: ModalBuyProps) => { { )} -

- در صورت نداشتن کد تخفیف پرداخت رو بزنید -

-
-
- - -
-
- - - -
-
+
+ + +
+
+ + + +
+ + + )}

حجم

-

{`${data?.data?.result?.traffic} GB`}

+

{`${data?.data?.result?.traffic} ${ + data?.data?.result?.is_test ? "MB" : "GB" + }`}

محدودیت کاربر

diff --git a/src/pages/tutorial/index.tsx b/src/pages/tutorial/index.tsx index d00fe58..13442b5 100644 --- a/src/pages/tutorial/index.tsx +++ b/src/pages/tutorial/index.tsx @@ -5,15 +5,16 @@ const Tutorial = () => { return ( <> - اموزش + پرشین پینگ | آموزش +
diff --git a/src/pages/tutorial/section/components/Leran.tsx b/src/pages/tutorial/section/components/Leran.tsx index fb969a2..dd2070f 100644 --- a/src/pages/tutorial/section/components/Leran.tsx +++ b/src/pages/tutorial/section/components/Leran.tsx @@ -90,7 +90,12 @@ const Learn = ({ activeTutorial }: LearnProps) => { {/* Render learning items */} {data?.data?.result?.learning.map( - (i: { id: string; title: string; medias: string[] }) => ( + (i: { + id: string; + title: string; + medias: string[]; + url_file: string; + }) => (
{ ); })}
+ {i.url_file && ( + <> + + + )} +
) )} diff --git a/src/redux/slices/isPaymentGateway.ts b/src/redux/slices/isPaymentGateway.ts new file mode 100644 index 0000000..ed2ce44 --- /dev/null +++ b/src/redux/slices/isPaymentGateway.ts @@ -0,0 +1,23 @@ +import { createSlice, PayloadAction } from "@reduxjs/toolkit"; + +interface isPaymentGatewayState { + isPaymentGateway: boolean; +} + +const initialState: isPaymentGatewayState = { + isPaymentGateway: true, +}; + +const isPaymentGatewaySlice = createSlice({ + name: "isPaymentGateway", + initialState, + reducers: { + setIsPaymentGateway: (state, action: PayloadAction) => { + state.isPaymentGateway = action.payload; + }, + }, +}); + +export const { setIsPaymentGateway } = isPaymentGatewaySlice.actions; + +export default isPaymentGatewaySlice.reducer; diff --git a/src/redux/store.ts b/src/redux/store.ts index 596e161..3439394 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -16,6 +16,7 @@ import { import tokenReducer from "./slices/token"; import configId from "./slices/configId"; import categoryId from "./slices/categoryId"; +import isPaymentGateway from "./slices/isPaymentGateway"; // Encryption settings const secretKey = "token-encrypt-api"; @@ -47,6 +48,7 @@ const store = configureStore({ token: persistedTokenReducer, configIdState: configId, categoryIdState: categoryId, + isPaymentGatewayState: isPaymentGateway, }, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ diff --git a/src/routes/routes.tsx b/src/routes/routes.tsx index 722e299..e6392d4 100644 --- a/src/routes/routes.tsx +++ b/src/routes/routes.tsx @@ -1,8 +1,8 @@ const router = [ { id: 1, name: "فروشگاه", path: "/" }, - { id: 2, name: "آموزش", path: "tutorial" }, - { id: 3, name: "قوانین و مقررات", path: "rule" }, - { id: 4, name: "درباره ما", path: "about" }, + { id: 2, name: "آموزش", path: "/tutorial" }, + { id: 3, name: "قوانین و مقررات", path: "/rule" }, + { id: 4, name: "درباره ما", path: "/about" }, ]; export default router; diff --git a/src/types/props.d.ts b/src/types/props.d.ts index d93d98d..927151b 100644 --- a/src/types/props.d.ts +++ b/src/types/props.d.ts @@ -119,15 +119,15 @@ export interface MuiModalProps { } export interface ConfigItemProps { + id: string; dateBuy: string; configName: string; isDisabled: boolean; isShowTraffic: boolean; textCopy: string; - maxTraffic: number | "unlimited"; - traffic: number; type: string; categoryId: number; + useMaxTraffic: boolean; } // نوع Item برای آیتم‌های داخل Dropdown @@ -203,6 +203,8 @@ type Config = { traffic: number; type: string; category_id: number; + is_expired: boolean; + use_max_traffic: boolean; }; // تعریف تایپ داده‌های برگشتی @@ -215,6 +217,7 @@ type ProfileResponseData = { }; status: boolean; alert: string; + ""; }; // تایپ خطا