(force) Update project: Added 60 new features and made various changes

{warning: this all chnaged}
This commit is contained in:
alij
2024-08-26 23:28:34 +03:30
parent 69d728485e
commit b0c9276e52
54 changed files with 1452 additions and 170 deletions

31
src/pages/404/index.tsx Normal file
View File

@@ -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 (
<>
<Particle />
<Helmet>
<title>صفحه پیدا نشد 404</title>
<meta
name="description"
content="بهترین خدمات فروشگاه جم و سی پی برای بازی‌های آنلاین با پرشین پینگ"
/>
<meta
name="keywords"
content="پرشین پینگ, خدمات بازی, بازی آنلاین, خرید یوسی پابجی موبایل"
/>
</Helmet>
<div className="w-full h-full min-h-screen flex p-6 justify-center items-center">
<div className="w-full max-w-96 relative glass h-96 flex flex-col justify-center items-center">
<img src={Svg404} alt="404" />
<h1 className="absolute bottom-24 -rotate-[30deg] text-[#407BFF]">صفحه مورد نظر یافت نشد</h1>
</div>
</div>
</>
)
}
export default Page404

View File

@@ -5,15 +5,16 @@ const About = () => {
return (
<>
<Helmet>
<title>درباره ما</title>
<title>پرشین پینگ | درباره ما </title>
<meta
name="description"
content="بهترین خدمات پینگ برای بازی‌های آنلاین با پرشین پینگ"
content="درباره پرشین پینگ - تیم ما و ماموریت ما در ارائه بهترین پینگ برای بازی‌های آنلاین ."
/>
<meta
name="keywords"
content="پرشین پینگ, خدمات پینگ, بازی آنلاین, کاهش پینگ , درباره ما"
/>
<meta name="robots" content="index, follow" />
</Helmet>
<div className="relative w-full h-full py-2">

View File

@@ -0,0 +1,44 @@
import { BiError } from "react-icons/bi";
import Button from "../../../components/button";
import { FaTelegram } from "react-icons/fa6";
const NoPayment = () => {
return (
<div className="w-full h-full glass flex-1 p-5">
<div className="w-full h-full flex flex-col gap-5 items-center justify-between">
<div className="w-full h-full flex flex-col justify-center items-center">
<BiError className="w-24 h-24" />
<h1 className="font-bold md:text-lg">
درگاه پرداخت به صورت موقت غیر فعال شده است
</h1>
</div>
<div className="w-full h-full flex justify-center items-center">
<p className="text-xs md:text-sm">
کاربر گرامی بابت پیش آمدن این مشکل صمیمانه از شما عذر خواهی می کنیم
و در تلاشیم هرچه زودتر مشکل درگاه پرداخت را بررسی کرده و سریع به
روال قبلی برگردانیم، <br />
<span className="text-secondTheme">
برای خرید کانفیگ مورد نظر می توانید به پشتیبانی ما در تلگرام پیام
دهید
</span>{" "}
، از صبر شما سپاسگذاریم .{" "}
</p>
</div>
<div className="w-full h-full flex flex-col gap-3 justify-center items-center">
<p className="text-xs md:text-sm text-[#229ED9]">
برای خرید از پشتیبانی در تلگرام لطفا دکمه زیر را کلیک کنید
</p>
<div className="w-full h-full flex">
<Button extra="!flex-1 !bg-[#229ED9]">
<a href="https://t.me/PersianPingSupport" className="w-full h-full flex justify-between items-center gap-4">
<FaTelegram className="w-7 h-7"/> <span>ورود به پشتیبانی تلگرام</span> <br />
</a>
</Button>
</div>
</div>
</div>
</div>
);
};
export default NoPayment;

View File

@@ -0,0 +1,17 @@
import Particle from "../../components/particle";
import NoPayment from "./components/NoPayment";
const InActivePayment = () => {
return (
<>
<Particle />
<div className="w-full h-full overflow-hidden bg-noisy">
<div className="max-w-5xl mx-auto min-h-screen flex justify-center items-center p-5">
<NoPayment />
</div>
</div>
</>
);
};
export default InActivePayment;

View File

@@ -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 (
<>
<Helmet>
<title>پرشین پینگ | فروشگاه </title>
<meta
name="description"
content="پرشین پینگ - بهترین خدمات برای بازی‌های آنلاین با پرشین پینگ"
/>
<meta
name="keywords"
content="پرشین پینگ, خدمات بازی آنلاین, فروشگاه"
/>
<meta name="robots" content="index, follow" />
</Helmet>
<div className="relative w-full h-full py-2">
<div className="relative w-full h-full glass px-4 py-2">
<Intro />
<FastSell />
<NowSell />
<ProductList />
<BestQuality />
</div>
</div>
</>
);
};
export default Landing;

View File

@@ -0,0 +1,25 @@
import PulsatingCircle from "../../../../components/pulsatingCircle";
const BestQuality = () => {
return (
<div className="w-full h-full mt-8 md:mt-10 mb-10 flex gap-10 flex-col justify-center items-center">
<div className="w-full h-full flex justify-center items-center">
<PulsatingCircle />
</div>
<div className="w-full h-full flex flex-col gap-2 md:gap-4 justify-center items-center">
<h1 className="text-base md:text-3xl lg:text-4xl font-bold">
به عنوان{" "}
<span className="text-base md:text-3xl lg:text-4xl text-secondTheme font-bold">
اولین و بهترین
</span>{" "}
ارائه دهنده{" "}
</h1>
<h1 className="relative max-md:right-5 max-lg:right-20 lg:right-40 text-base md:text-3xl lg:text-4xl font-bold">
مفتخریم که در خدمت شما باشیم
</h1>
</div>
</div>
);
};
export default BestQuality;

View File

@@ -0,0 +1,19 @@
import { FaPowerOff } from "react-icons/fa6";
import LoaderSpin from "../../../../components/loaderSpin";
import Typewriter from "../../../../components/typeWriter";
const FastSell = () => {
return (
<div className="relative w-full h-full mb-6 flex justify-center items-center">
<div className="w-full h-full flex flex-col justify-center items-center">
<LoaderSpin>
<FaPowerOff className="max-md:text-6xl text-8xl text-white" />
</LoaderSpin>
<Typewriter text="میبینی ؟ همینقدر" />
<Typewriter text="ساده و سریــــــــــــــع" />
</div>
</div>
);
};
export default FastSell;

View File

@@ -0,0 +1,34 @@
import Button from "../../../../components/button";
import Rocket3D from "../../../../assets/ui/Rocket.png";
import SmoothScrollLink from "../../../../components/scrollLink";
const Intro = () => {
return (
<div className="relative w-full h-full gap-6 grid grid-cols-1 py-6 md:grid-cols-2">
<div className="w-full h-full flex flex-col max-md:gap-5 gap-8 justify-center mx-auto items-center">
<h1 className="text-start flex flex-col gap-3 md:gap-4 text-3xl md:text-4xl lg:text-5xl">
<span className="inline-block text-center">بزرگترین فروشگاه</span>
<span className="text-secondTheme font-bold max-md:text-center">
خرید سی پی تنها با چند کلیک
</span>
</h1>
<p className="text-center text-xl text-gray-600">
سال ها تجربه پشت یک خرید شماست
</p>
<SmoothScrollLink to="#configs">
<Button >برو به فروشگاه</Button>
</SmoothScrollLink>
</div>
<div className="w-full h-full flex justify-center py-4 mx-auto items-center max-md:hidden">
<img
src={Rocket3D}
alt="intro"
className="w-60 md:w-72 lg:w-[25rem] animate-bounce"
/>
</div>
</div>
);
};
export default Intro;

View File

@@ -0,0 +1,13 @@
import Content from "./components/Content";
const NowSell = () => {
return (
<div className="relative w-full h-full p-5">
<div className="relative w-full max-md:h-[15rem] md:h-[20rem] lg:h-[25rem] p-2 rounded-2xl bg-white shadow-lg bg-banner bg-center bg-cover shadow-current flex justify-center items-center">
<Content />
</div>
</div>
);
};
export default NowSell;

View File

@@ -0,0 +1,23 @@
import Button from "../../../../../components/button";
const Content = () => {
return (
<div className="w-full h-full flex flex-col text-center max-md:gap-3 gap-5 justify-center text-black items-center max-md:py-5 px-5 py-10">
<h1 className="text-4xl max-md:text-2xl lg:text-5xl font-bold">
با چندین سال
</h1>
<h1 className="text-4xl max-md:text-2xl lg:text-5xl font-bold">
تجربـــــــــــــــــــه
</h1>
<p className="text-2xl max-md:text-sm text-gray-500">
بهترین نتیجه رو بهتون تقدیم میکنیم
</p>
<Button extra="!bg-black text-white text-2xl max-md:text-lg max-md:!py-2 mt-4 !py-4 !px-10 !rounded-xl">
{" "}
همین الان میخرم
</Button>
</div>
);
};
export default Content;

View File

@@ -0,0 +1,24 @@
import { useState } from "react";
import ButtonList from "./components/ButtonList";
import ListAllProduct from "./components/ListAllProduct";
const ProductList = () => {
const [activeId, setActiveId] = useState<number>(0);
return (
<div className="relative w-full h-full max-md:mt-4 md:mt-8 " id="configs">
<div className="w-full h-full gap-4 md:gap-6 flex flex-col p-5 justify-center items-center">
<h1 className="max-md:text-sm text-center text-2xl font-bold">
برای انتخاب سی پی یا جم مورد نظر کلیک کنید تا براتون نمایش داده شود
</h1>
<ButtonList
activeId={activeId}
setActiveId={setActiveId}
/>
<ListAllProduct activeId={activeId} />
</div>
</div>
);
};
export default ProductList;

View File

@@ -0,0 +1,27 @@
import { Dispatch, SetStateAction } from "react";
import Button from "../../../../../components/button";
const ButtonList = ({ activeId, setActiveId } : {activeId:number;setActiveId:Dispatch<SetStateAction<number>>}) => {
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 (
<div className="w-full h-full gap-4 flex flex-wrap flex-row justify-center">
{ProductsList?.map((product) => (
<Button
key={product.id}
active={product.id === activeId}
extra="md:py-2 md:text-lg max-sm:!px-1"
name={product.label || product.name}
onClick={() => setActiveId(product.id)}
>
{product.name}
</Button>
))}
</div>
);
};
export default ButtonList;

View File

@@ -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 (
<>
<div
className="w-full h-full border-4 gap-5 border-spacing-1 shadow-lg shadow-white border-solid border-white rounded-lg p-3 grid max-sm:grid-cols-1 max-md:grid-cols-2 max-lg:grid-cols-3 lg:grid-cols-4"
id="listConfig"
>
{product.map((item) => {
return (
<div className="w-full h-full flex flex-col" key={item.id}>
<img src={item.image} alt={item.title} />
<div className="w-full h-full flex justify-center items-center">
<Button extra="!w-4/5">خرید</Button>
</div>
</div>
);
})}
</div>
</>
);
};
export default ListAllProduct;

View File

@@ -74,7 +74,6 @@ const Profile = () => {
return axios.get("/profile");
},
});
return (
<>
{!mutation.isPending && (

View File

@@ -34,7 +34,7 @@ const ProductConfigList = ({
لیست کانفیگ ها
</p>
<div
className="w-full h-full p-3 flex flex-col gap-3
className="w-full h-full p-3 max-sm:px-0 flex flex-col gap-3
justify-center items-center"
>
{isLoading || isFetching ? (
@@ -59,15 +59,15 @@ const ProductConfigList = ({
return (
<Fragment key={item.id}>
<ConfigItem
id={String(item.id)}
configName={item.title}
dateBuy={item.created_at || "تاریخ نامعتبر"}
isDisabled={false}
isDisabled={item.is_expired}
isShowTraffic={item.show_traffic}
textCopy={item.url}
maxTraffic={item.max_traffic}
traffic={item.traffic}
type={item.type}
categoryId={item.category_id}
useMaxTraffic={item.use_max_traffic}
/>
</Fragment>
);

View File

@@ -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<string>("");
const [_, setCopyText] = useState<string>("");
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 (
<>
<ModalConfigDetails
@@ -67,24 +93,29 @@ const ConfigItem = ({
nameConfig={configName}
isShowTraffic={isShowTraffic}
textCopy={textCopy}
maxTraffic={maxTraffic}
traffic={traffic}
maxTraffic={spaceConfig.maxTraffic}
traffic={spaceConfig.traffic}
type={type}
username={username}
password={password}
categoryId={categoryId}
isLoadSpaceConfig={
queryUpdateConfig.isLoading || queryUpdateConfig.isFetching
}
error={queryUpdateConfig?.error ? queryUpdateConfig?.error : null}
useMaxTraffic={useMaxTraffic}
/>
<div className="relative w-full h-full rounded-md">
{isDisabled && (
{isDisabled || useMaxTraffic && (
<div className="absolute inset-0 flex items-center justify-center bg-opacity-50 rounded-md backdrop-blur-sm z-10">
<div className="text-white font-bold max-sm:p-[2px] p-1 bg-red-600 max-sm:text-[10px] text-xs md:text-base rounded-md shadow-md">
<div className="text-white font-bold max-sm:p-[2px] p-1 bg-rose-600 max-sm:text-[9px] sm:text-xs md:text-base rounded-md shadow-md">
کانفیگ <span className="text-secondTheme">{configName}</span> غیر
فعال است .{" "}
<Button
extra="cursor-pointer !px-1 !py-0 rounded-md bg-white"
onClick={() => setIsOpen(true)}
>
برای تمدید کلیک کنید
مشاهده
</Button>
</div>
</div>
@@ -101,16 +132,6 @@ const ConfigItem = ({
<div className="max-md:hidden flex flex-row-reverse gap-2 justify-end items-center">
{type === "gaming" ? (
<>
<Button
onClick={() => {
setCopyText(username);
copyToClipboard(username);
}}
extra="!m-0 !px-2 !py-1.5 flex flex-row-reverse justify-center items-center gap-1 shadow-md shadow-white"
>
کپی یوزرنیم
<IoCopy />
</Button>
<Button
onClick={() => {
setCopyText(password);
@@ -121,6 +142,16 @@ const ConfigItem = ({
کپی پسورد
<IoCopy />
</Button>
<Button
onClick={() => {
setCopyText(username);
copyToClipboard(username);
}}
extra="!m-0 !px-2 !py-1.5 flex flex-row-reverse justify-center items-center gap-1 shadow-md shadow-white"
>
کپی یوزرنیم
<IoCopy />
</Button>
</>
) : (
<Button
@@ -145,7 +176,7 @@ const ConfigItem = ({
>
آموزش
</Button>
{isShowTraffic && (
{isShowTraffic && !useMaxTraffic && (
<Dropdown isOpen={isOpenDropDown} setIsOpen={setIsOpenDropDown}>
<Button
id="dropdownDefaultButton"
@@ -157,7 +188,21 @@ const ConfigItem = ({
حجم
</Button>
<DropdownItem widthTailwind="w-[20rem] left-0">
<ProgressSpace startSpace={traffic} endSpace={maxTraffic} />
{queryUpdateConfig.isLoading ||
queryUpdateConfig.isFetching ? (
<div className="w-full h-full p-5 flex justify-center items-center">
<LoaderSpaceConfig />
</div>
) : queryUpdateConfig.error ? (
<div className="w-full h-full p-5 flex justify-center items-center">
خطایی رخ داد : {queryUpdateConfig?.error?.message}
</div>
) : (
<ProgressSpace
startSpace={spaceConfig.traffic}
endSpace={spaceConfig.maxTraffic}
/>
)}
</DropdownItem>
</Dropdown>
)}
@@ -165,7 +210,10 @@ const ConfigItem = ({
<div className="md:hidden flex flex-row-reverse gap-2 justify-end items-center">
<Button
extra="!m-0 !px-2 !py-1 shadow-md"
onClick={() => setIsOpen(true)}
onClick={() => {
setConfigId(id);
setIsOpen(true);
}}
>
مشاهده جزئیات
</Button>

View File

@@ -0,0 +1,60 @@
export default function LoaderSpaceConfig() {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width={70}>
<circle
fill="#71FBB2"
stroke="#71FBB2"
strokeWidth="15"
r="15"
cx="40"
cy="65"
>
<animate
attributeName="cy"
calcMode="spline"
dur="2"
values="65;135;65;"
keySplines=".5 0 .5 1;.5 0 .5 1"
repeatCount="indefinite"
begin="-.4"
></animate>
</circle>
<circle
fill="#71FBB2"
stroke="#71FBB2"
strokeWidth="15"
r="15"
cx="100"
cy="65"
>
<animate
attributeName="cy"
calcMode="spline"
dur="2"
values="65;135;65;"
keySplines=".5 0 .5 1;.5 0 .5 1"
repeatCount="indefinite"
begin="-.2"
></animate>
</circle>
<circle
fill="#71FBB2"
stroke="#71FBB2"
strokeWidth="15"
r="15"
cx="160"
cy="65"
>
<animate
attributeName="cy"
calcMode="spline"
dur="2"
values="65;135;65;"
keySplines=".5 0 .5 1;.5 0 .5 1"
repeatCount="indefinite"
begin="0"
></animate>
</circle>
</svg>
);
}

View File

@@ -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<SetStateAction<boolean>>;
@@ -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<string>("");
const [_, setCopyText] = useState<string>("");
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}
</h1>
<div className="w-full h-full flex flex-row-reverse gap-2 flex-wrap justify-center items-center">
{isDisabled ? (
{isDisabled || useMaxTraffic ? (
<div className="w-full h-full flex flex-wrap justify-center items-center">
<Button extra="!m-0 !px-2 !py-1 shadow-md flex-1 shadow-secondTheme !bg-secondTheme font-bold hover:!bg-gray-800 hover:!shadow-gray-800 ">
{/* <Button extra="!m-0 !px-2 !py-1 shadow-md flex-1 shadow-secondTheme !bg-secondTheme font-bold hover:!bg-gray-800 hover:!shadow-gray-800 ">
تمدید
</Button>
</Button> */}
<div className="w-full h-full text-xs sm:text-sm md:text-base">
{useMaxTraffic ? (
<h1>مشترک گرامی کانفیگ شما به دلیل اتمام حجم غیر فعال است</h1>
) : isDisabled && (
<h1>مشترک گرامی کانفیگ شما به دلیل پایان اعتبار غیر فعال است</h1>
)}
</div>
</div>
) : (
<>
{type === "gaming" ? (
<>
<Button
onClick={() => {
setCopyText(username);
copyToClipboard(username);
}}
extra="!m-0 !px-2 !py-1.5 flex flex-row-reverse justify-center items-center gap-1 shadow-md shadow-white"
>
کپی یوزرنیم
<IoCopy />
</Button>
<Button
onClick={() => {
setCopyText(password);
copyToClipboard(password);
}}
extra="!m-0 !px-2 !py-1.5 flex flex-row-reverse justify-center items-center gap-1 shadow-md shadow-white"
>
کپی پسورد
<IoCopy />
</Button>
{isCopyError ? (
<div className="w-full h-full flex flex-col gap-2">
<h1 className="bg-red-600 rounded-md p-1">
کاربر گرامی کپی خودکار موفقیت آمیز نبود لطفا به صورت
دستی از زیر انتخاب کرده و کپی کنید
</h1>
<Input
type="text"
value={`نام کاربری : ${username}`}
disabled={true}
/>
<Input
type="text"
value={`رمز عبور : ${password}`}
disabled={true}
/>
</div>
) : (
<>
<Button
onClick={() => {
setCopyText(password);
copyToClipboard(password);
}}
extra="!m-0 !px-2 !py-1.5 flex flex-row-reverse justify-center items-center gap-1 shadow-md shadow-white"
>
کپی پسورد
<IoCopy />
</Button>
<Button
onClick={() => {
setCopyText(username);
copyToClipboard(username);
}}
extra="!m-0 !px-2 !py-1.5 flex flex-row-reverse justify-center items-center gap-1 shadow-md shadow-white"
>
کپی یوزرنیم
<IoCopy />
</Button>
</>
)}
</>
) : (
<Button
onClick={() => {
setCopyText(textCopy);
copyToClipboard(textCopy);
}}
extra="!m-0 !px-2 !py-1.5 flex flex-row-reverse justify-center items-center gap-1 shadow-md shadow-white"
>
کپی
<IoCopy />
</Button>
<>
{isCopyError ? (
<>
<div className="w-full h-full flex flex-col gap-2">
<h1 className="bg-red-600 rounded-md p-1">
کاربر گرامی کپی خودکار موفقیت آمیز نبود لطفا به صورت
دستی از زیر انتخاب کرده و کپی کنید
</h1>
<textarea
value={textCopy}
className="outline-none border-none sm:text-sm rounded-lg block w-full p-2.5 md:p-3 bg-gray-700 border-gray-600 placeholder-gray-400 text-white"
disabled={true}
rows={8}
></textarea>
</div>
</>
) : (
<Button
onClick={() => {
setCopyText(textCopy);
copyToClipboard(textCopy);
}}
extra="!m-0 !px-2 !py-1.5 flex flex-row-reverse justify-center items-center gap-1 shadow-md shadow-white"
>
کپی
<IoCopy />
</Button>
)}
</>
)}
<Button
onClick={() => {
@@ -127,7 +180,18 @@ const ModalConfigDetails = ({
</div>
{!isDisabled && isShowTraffic && (
<div className="w-full h-full">
<ProgressSpace startSpace={traffic} endSpace={maxTraffic} />
{isLoadSpaceConfig ? (
<div className="flex w-full h-full justify-center items-center">
<LoaderSpaceConfig />
</div>
) : error ? (
<div className="w-full h-full text-center">
{" "}
خطایی رخ داد : {error?.message}
</div>
) : (
<ProgressSpace startSpace={traffic} endSpace={maxTraffic} />
)}
</div>
)}
</div>

View File

@@ -5,15 +5,16 @@ const Rule = () => {
return (
<>
<Helmet>
<title>قوانین</title>
<title>پرشین پینگ | قوانین </title>
<meta
name="description"
content="بهترین خدمات پینگ برای بازی‌های آنلاین با پرشین پینگ"
content="قوانین و مقررات بازی‌های پرشین پینگ - بهترین خدمات پینگ برای بازی‌های آنلاین با پرشین پینگ"
/>
<meta
name="keywords"
content="پرشین پینگ, خدمات پینگ, بازی آنلاین, کاهش پینگ , قوانین"
/>
<meta name="robots" content="index, follow" />
</Helmet>
<div className="relative w-full h-full py-2">
<div className="relative w-full h-full glass px-4 py-2">

View File

@@ -9,15 +9,16 @@ const Shop = () => {
return (
<>
<Helmet>
<title>فروشگاه</title>
<title>پرشین پینگ | فروشگاه </title>
<meta
name="description"
content="بهترین خدمات پینگ برای بازی‌های آنلاین با پرشین پینگ"
content="پرشین پینگ - بهترین خدمات پینگ برای بازی‌های آنلاین با پرشین پینگ"
/>
<meta
name="keywords"
content="پرشین پینگ, خدمات پینگ, بازی آنلاین, کاهش پینگ و فروشگاه"
/>
<meta name="robots" content="index, follow" />
</Helmet>
<div className="relative w-full h-full py-2">

View File

@@ -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) => {
<MuiModal
isOpenModal={isOpen}
setIsOpenModal={setIsOpen}
submitText="خرید"
submitText={data?.data?.result?.max_config === 0 ? undefined : "خرید"}
submitOnClick={submitHandler}
disabled={isLoading || isFetching}
nameService={
@@ -212,66 +215,76 @@ const ModalBuy = ({ isOpen, setIsOpen, configId }: ModalBuyProps) => {
)}
</span>
</h1>
<h3 className="text-xs md:text-sm text-gray-400">
در صورت نداشتن کد تخفیف پرداخت رو بزنید
</h3>
<form
className="flex flex-col gap-3 justify-center items-center"
onSubmit={formik.handleSubmit}
>
<div className="w-full h-full flex justify-center items-center gap-2">
<Input
type="text"
extra="max-md:!p-1 md:!p-2"
{...formik.getFieldProps("discount")}
/>
<Button
extra="md:!py-1 disabled:!bg-gray-300"
onClick={discountHandler}
disabled={formik.values.discount === ""}
{data?.data?.result?.max_config === 0 ? (
<>
<Alert type="info" extra="mt-5"> موجودی کانفیگ به اتمام رسیده </Alert>
</>
) : (
<>
<h3 className="text-xs md:text-sm text-gray-400">
در صورت نداشتن کد تخفیف پرداخت رو بزنید
</h3>
<form
className="flex flex-col gap-3 justify-center items-center"
onSubmit={formik.handleSubmit}
>
اعمال
</Button>
</div>
<div className="w-2/3 h-full flex justify-center items-center gap-1">
<Button
extra="!px-2 max-md:!py-1.5 md:!py-1 disabled:!bg-gray-300"
onClick={() => {
if (formik.values.count > 1) {
chnageCountHandler("dec");
}
}}
disabled={formik.values.count === 1}
>
<BiMinus />
</Button>
<Input
type="text"
extra="max-md:py-0 !p-1 !text-center"
{...formik.getFieldProps("count")}
/>
<Button
extra="!px-2 max-md:!py-1.5 md:!py-1 disabled:!bg-gray-300"
onClick={() => {
if (
formik.values.count.toString() <
data?.data?.result?.max_config
)
chnageCountHandler("inc");
}}
disabled={
formik.values.count.toString() ===
data?.data?.result?.max_config
}
>
<BiPlus />
</Button>
</div>
</form>
<div className="w-full h-full flex justify-center items-center gap-2">
<Input
type="text"
extra="max-md:!p-1 md:!p-2"
{...formik.getFieldProps("discount")}
/>
<Button
extra="md:!py-1 disabled:!bg-gray-300"
onClick={discountHandler}
disabled={formik.values.discount === ""}
>
اعمال
</Button>
</div>
<div className="w-2/3 h-full flex justify-center items-center gap-1">
<Button
extra="!px-2 max-md:!py-1.5 md:!py-1 disabled:!bg-gray-300"
onClick={() => {
if (formik.values.count > 1) {
chnageCountHandler("dec");
}
}}
disabled={formik.values.count === 1}
>
<BiMinus />
</Button>
<Input
type="text"
extra="max-md:py-0 !p-1 !text-center"
{...formik.getFieldProps("count")}
/>
<Button
extra="!px-2 max-md:!py-1.5 md:!py-1 disabled:!bg-gray-300"
onClick={() => {
if (
formik.values.count.toString() <
data?.data?.result?.max_config
)
chnageCountHandler("inc");
}}
disabled={
formik.values.count.toString() ===
data?.data?.result?.max_config
}
>
<BiPlus />
</Button>
</div>
</form>
</>
)}
<div className="w-full h-full flex flex-col justify-between items-center gap-2 text-xs md:text-sm">
<div className="w-full h-full bg-gray-900/50 rounded-md shadow flex justify-between items-center p-3">
<p>حجم</p>
<p dir="ltr">{`${data?.data?.result?.traffic} GB`}</p>
<p dir="ltr">{`${data?.data?.result?.traffic} ${
data?.data?.result?.is_test ? "MB" : "GB"
}`}</p>
</div>
<div className="w-full h-full bg-gray-900/50 rounded-md shadow flex justify-between items-center p-3">
<p>محدودیت کاربر</p>

View File

@@ -5,15 +5,16 @@ const Tutorial = () => {
return (
<>
<Helmet>
<title>اموزش</title>
<title>پرشین پینگ | آموزش </title>
<meta
name="description"
content="بهترین خدمات پینگ برای بازی‌های آنلاین با پرشین پینگ"
content="آموزش بازی‌های آنلاین پرشین پینگ - بهترین خدمات پینگ برای بازی‌های آنلاین با پرشین پینگ"
/>
<meta
name="keywords"
content="پرشین پینگ, خدمات پینگ, بازی آنلاین, کاهش پینگ و آموزش"
/>
<meta name="robots" content="index, follow" />
</Helmet>
<div className="relative w-full h-full py-2">

View File

@@ -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;
}) => (
<div
key={i.id}
className="relative w-full h-full flex flex-col justify-center items-center"
@@ -125,6 +130,14 @@ const Learn = ({ activeTutorial }: LearnProps) => {
);
})}
</div>
{i.url_file && (
<>
<Button extra="!mb-4" onClick={() => saveAs(i.url_file)}>
دانلود برنامه
</Button>
</>
)}
<hr className="border-2 w-full rounded-md my-5 border-gray-800" />
</div>
)
)}