(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

View File

@@ -3,10 +3,38 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>persian game</title> <title>پرشین پینگ | فروشگاه</title>
<meta
name="description"
content="پرشین پینگ - بهترین خدمات پینگ برای بازی‌های آنلاین با پرشین پینگ"
/>
<meta
name="keywords"
content="پرشین پینگ, خدمات پینگ, بازی آنلاین, کاهش پینگ و فروشگاه"
/>
<meta name="robots" content="index, follow" />
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
<script type="module" src="/src/main.tsx"></script> <script type="module" src="/src/main.tsx"></script>
<script type="text/javascript">
!(function () {
var i = "3QWWxH",
a = window,
d = document;
function g() {
var g = d.createElement("script"),
s = "https://www.goftino.com/widget/" + i,
l = localStorage.getItem("goftino_" + i);
(g.async = !0), (g.src = l ? s + "?o=" + l : s);
d.getElementsByTagName("head")[0].appendChild(g);
}
"complete" === d.readyState
? g()
: a.attachEvent
? a.attachEvent("onload", g)
: a.addEventListener("load", g, !1);
})();
</script>
</body> </body>
</html> </html>

View File

@@ -17,8 +17,17 @@ import Profile from "./pages/profile";
import { Toaster } from "react-hot-toast"; import { Toaster } from "react-hot-toast";
import { IsAuthenticated } from "./utils/auth"; import { IsAuthenticated } from "./utils/auth";
import { HelmetProvider } from "react-helmet-async"; 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 App = () => {
const { isPaymentGateway } = useSelector(
(state: RootState) => state.isPaymentGatewayState
);
return ( return (
<Router basename="/"> <Router basename="/">
<HelmetProvider> <HelmetProvider>
@@ -29,9 +38,13 @@ const App = () => {
/> />
<ProgressBar /> <ProgressBar />
<Routes> <Routes>
{/* <Route path="/" element={<LandingLayout />}>
<Route index element={<Landing />}></Route>
<Route path="/configs/:configs" element={<Navigate to='/shopping-config' />} />
</Route> */}
<Route path="/" element={<Layout />}> <Route path="/" element={<Layout />}>
<Route index element={<Shop />} /> <Route index element={<Shop />} />
<Route path="configs/:configs" element={<Navigate to="/" />} /> <Route path="/configs/:configs" element={<Navigate to='/' />} />
<Route path="tutorial" element={<Tutorial />} /> <Route path="tutorial" element={<Tutorial />} />
<Route path="rule" element={<Rule />} /> <Route path="rule" element={<Rule />} />
<Route path="about" element={<About />} /> <Route path="about" element={<About />} />
@@ -40,10 +53,10 @@ const App = () => {
</Route> </Route>
</Route> </Route>
<Route <Route
path="login" path="/login"
element={ element={
IsAuthenticated() ? ( IsAuthenticated() ? (
<Navigate to="/" replace={true} /> <Navigate to="/profile" replace={true} />
) : ( ) : (
<AuthLayout /> <AuthLayout />
) )
@@ -51,6 +64,17 @@ const App = () => {
> >
<Route index element={<Login />} /> <Route index element={<Login />} />
</Route> </Route>
<Route
path="/noactive-payment"
element={
isPaymentGateway ? (
<Navigate to="/" />
) : (
<InActivePayment />
)
}
/>
<Route path="*" element={<Page404 />} />
</Routes> </Routes>
</HelmetProvider> </HelmetProvider>
</Router> </Router>

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

340
src/assets/svg/404.svg Normal file
View File

@@ -0,0 +1,340 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 500 500" style="enable-background:new 0 0 500 500;" xml:space="preserve">
<g id="Background_Complete">
<g>
<path style="fill:#EBEBEB;" d="M238.401,445.047H45.302c-3.147,0-5.708-2.56-5.708-5.708V60.66c0-3.147,2.561-5.708,5.708-5.708
h193.099c3.146,0,5.707,2.561,5.707,5.708v378.679C244.108,442.487,241.547,445.047,238.401,445.047z M45.302,55.203
c-3.01,0-5.458,2.448-5.458,5.458v378.679c0,3.01,2.448,5.458,5.458,5.458h193.099c3.009,0,5.457-2.448,5.457-5.458V60.66
c0-3.009-2.448-5.458-5.457-5.458H45.302z"/>
<path style="fill:#EBEBEB;" d="M454.698,445.047H261.599c-3.146,0-5.707-2.56-5.707-5.708V60.66c0-3.147,2.561-5.708,5.707-5.708
h193.099c3.148,0,5.708,2.561,5.708,5.708v378.679C460.406,442.487,457.845,445.047,454.698,445.047z M261.599,55.203
c-3.009,0-5.457,2.448-5.457,5.458v378.679c0,3.01,2.448,5.458,5.457,5.458h193.099c3.01,0,5.458-2.448,5.458-5.458V60.66
c0-3.009-2.448-5.458-5.458-5.458H261.599z"/>
</g>
<g>
<g>
<polygon style="fill:#EBEBEB;" points="113.054,168.247 114.671,171.523 118.286,172.049 115.67,174.599 116.288,178.2
113.054,176.5 109.82,178.2 110.438,174.599 107.821,172.049 111.437,171.523 "/>
<polygon style="fill:#F5F5F5;" points="436.705,322.483 438.322,325.759 441.937,326.285 439.321,328.835 439.939,332.436
436.705,330.736 433.471,332.436 434.088,328.835 431.472,326.285 435.088,325.759 "/>
<polygon style="fill:#F5F5F5;" points="372.599,417.566 374.216,420.842 377.832,421.367 375.215,423.918 375.833,427.519
372.599,425.819 369.365,427.519 369.983,423.918 367.366,421.367 370.982,420.842 "/>
<path style="fill:#EBEBEB;" d="M225.945,110.154l0.6,1.216l1.342,0.195c0.335,0.049,0.469,0.46,0.226,0.697l-0.971,0.947
l0.229,1.337c0.057,0.334-0.293,0.588-0.592,0.431l-1.201-0.631l-1.201,0.631c-0.3,0.158-0.65-0.097-0.592-0.431l0.229-1.337
l-0.971-0.947c-0.242-0.236-0.109-0.648,0.226-0.697l1.342-0.195l0.6-1.216C225.362,109.85,225.795,109.85,225.945,110.154z"/>
<path style="fill:#F5F5F5;" d="M60.777,402.008l0.6,1.216l1.342,0.195c0.335,0.049,0.469,0.46,0.226,0.697l-0.971,0.947
l0.229,1.337c0.057,0.334-0.293,0.588-0.592,0.431l-1.201-0.631l-1.201,0.631c-0.3,0.157-0.65-0.097-0.592-0.431l0.229-1.337
l-0.971-0.947c-0.242-0.236-0.109-0.648,0.226-0.697l1.342-0.195l0.6-1.216C60.194,401.704,60.627,401.704,60.777,402.008z"/>
<path style="fill:#EBEBEB;" d="M87.755,97.301l0.6,1.216l1.342,0.195c0.335,0.049,0.469,0.46,0.226,0.697l-0.971,0.947
l0.229,1.337c0.057,0.334-0.293,0.588-0.593,0.43l-1.201-0.631l-1.2,0.631c-0.3,0.158-0.65-0.097-0.593-0.43l0.229-1.337
l-0.971-0.947c-0.242-0.236-0.109-0.648,0.226-0.697l1.342-0.195l0.6-1.216C87.172,96.997,87.605,96.997,87.755,97.301z"/>
<path style="fill:#EBEBEB;" d="M86.131,338.319c0,0.733-0.594,1.327-1.327,1.327c-0.733,0-1.327-0.594-1.327-1.327
c0-0.733,0.594-1.327,1.327-1.327C85.536,336.992,86.131,337.586,86.131,338.319z"/>
<path style="fill:#EBEBEB;" d="M275.671,171.894c0,0.733-0.594,1.327-1.327,1.327c-0.733,0-1.327-0.594-1.327-1.327
c0-0.733,0.594-1.327,1.327-1.327C275.077,170.567,275.671,171.161,275.671,171.894z"/>
<path style="fill:#F5F5F5;" d="M206.707,98.4c0,0.733-0.594,1.327-1.327,1.327c-0.733,0-1.327-0.594-1.327-1.327
c0-0.733,0.594-1.327,1.327-1.327C206.113,97.073,206.707,97.668,206.707,98.4z"/>
</g>
<g>
<ellipse transform="matrix(0.9732 -0.2298 0.2298 0.9732 -89.8924 58.7029)" style="fill:#F0F0F0;" cx="207.142" cy="415.377" rx="7.348" ry="7.348"/>
</g>
<path style="fill:#E6E6E6;" d="M204.597,411.09c-1.56,0-3.01,0.5-4.19,1.36c-0.39,0.9-0.61,1.89-0.61,2.93
c0,4.06,3.29,7.34,7.35,7.34c1.37,0,2.66-0.38,3.76-1.039c-0.01-0.01-0.01-0.01,0-0.01c0.55-1.02,0.86-2.18,0.86-3.42
C211.767,414.3,208.557,411.09,204.597,411.09z"/>
</g>
</g>
<g id="Background_Simple" style="display:none;">
<g style="display:inline;">
<path style="fill:#407BFF;" d="M104.695,145.876c-15.325,40.812-2.099,95.899,21.577,138.996
c60.957,111.899,209.435,48.626,206.875-2.188c3.485-48.487-40.113-62.884-54.906-90.068
C195.42,39.207,117.023,111.471,104.695,145.876z"/>
<path style="opacity:0.9;fill:#FFFFFF;" d="M104.695,145.876c-15.325,40.812-2.099,95.899,21.577,138.996
c60.957,111.899,209.435,48.626,206.875-2.188c3.485-48.487-40.113-62.884-54.906-90.068
C195.42,39.207,117.023,111.471,104.695,145.876z"/>
</g>
</g>
<g id="_x34_04">
<g>
<path style="fill:#407BFF;" d="M147.68,287.645H86.825V260.17l60.855-72.337h29.115v73.895h15.09v25.917h-15.09v22.472H147.68
V287.645z M147.68,261.728V223.89l-32.156,37.838H147.68z"/>
<path style="fill:#407BFF;" d="M202.302,249.508c0-22.854,4.113-38.846,12.343-47.978c8.229-9.131,20.762-13.697,37.604-13.697
c8.091,0,14.735,0.999,19.929,2.994c5.194,1.996,9.432,4.593,12.712,7.791c3.28,3.199,5.864,6.561,7.75,10.088
c1.887,3.526,3.404,7.641,4.552,12.344c2.241,8.967,3.362,18.317,3.362,28.049c0,21.815-3.691,37.782-11.072,47.896
c-7.382,10.116-20.094,15.172-38.137,15.172c-10.116,0-18.29-1.614-24.522-4.839c-6.234-3.225-11.347-7.955-15.337-14.188
c-2.9-4.428-5.155-10.484-6.766-18.166C203.107,267.292,202.302,258.804,202.302,249.508z M235.436,249.59
c0,15.31,1.353,25.767,4.059,31.372c2.707,5.604,6.63,8.406,11.769,8.406c3.39,0,6.329-1.189,8.817-3.568
c2.488-2.378,4.319-6.136,5.496-11.276c1.175-5.139,1.763-13.15,1.763-24.031c0-15.964-1.353-26.695-4.059-32.19
c-2.707-5.496-6.766-8.243-12.18-8.243c-5.523,0-9.514,2.803-11.975,8.407C236.666,224.071,235.436,234.446,235.436,249.59z"/>
<path style="fill:#407BFF;" d="M371.744,287.645h-60.855V260.17l60.855-72.337h29.115v73.895h15.09v25.917h-15.09v22.472h-29.115
V287.645z M371.744,261.728V223.89l-32.155,37.838H371.744z"/>
</g>
</g>
<g id="Planets">
<g>
<g style="opacity:0.3;">
<path style="fill:#407BFF;" d="M200.952,145.618c0,1.03-0.835,1.865-1.865,1.865c-1.03,0-1.865-0.835-1.865-1.865
c0-1.03,0.835-1.865,1.865-1.865C200.117,143.753,200.952,144.588,200.952,145.618z"/>
<circle style="fill:#407BFF;" cx="72.966" cy="216.129" r="1.323"/>
<circle style="fill:#407BFF;" cx="291.054" cy="408.333" r="1.893"/>
<circle style="fill:#407BFF;" cx="336.498" cy="332" r="1.323"/>
<path style="fill:#407BFF;" d="M424.173,95.619c0,0.731-0.592,1.323-1.323,1.323c-0.731,0-1.323-0.592-1.323-1.323
c0-0.731,0.592-1.323,1.323-1.323C423.581,94.296,424.173,94.888,424.173,95.619z"/>
<path style="fill:#407BFF;" d="M172.754,68.963c0,0.731-0.592,1.323-1.323,1.323c-0.731,0-1.323-0.592-1.323-1.323
s0.592-1.323,1.323-1.323C172.162,67.64,172.754,68.232,172.754,68.963z"/>
<circle style="fill:#407BFF;" cx="277.695" cy="136.943" r="1.323"/>
</g>
<g>
<g>
<circle style="fill:#407BFF;" cx="141.233" cy="116.361" r="21.91"/>
<circle style="opacity:0.7;fill:#FFFFFF;" cx="141.233" cy="116.361" r="21.91"/>
</g>
<path style="opacity:0.2;fill:#407BFF;" d="M133.682,99.83c-3.071,0-5.986,0.635-8.641,1.77
c-3.55,3.893-5.716,9.078-5.716,14.762c0,12.097,9.807,21.904,21.904,21.904c3.081,0,6.017-0.635,8.683-1.78c0,0,0,0,0-0.01
c3.529-3.894,5.684-9.058,5.684-14.731C155.597,109.637,145.79,99.83,133.682,99.83z"/>
<path style="opacity:0.2;fill:#407BFF;" d="M131.504,105.623c0,1.106-0.897,2.003-2.003,2.003c-1.106,0-2.003-0.897-2.003-2.003
c0-1.106,0.897-2.003,2.003-2.003C130.607,103.62,131.504,104.517,131.504,105.623z"/>
<path style="opacity:0.2;fill:#407BFF;" d="M155.064,103.62c0,1.106-0.897,2.003-2.003,2.003c-1.106,0-2.003-0.897-2.003-2.003
c0-1.106,0.897-2.003,2.003-2.003C154.167,101.618,155.064,102.514,155.064,103.62z"/>
<path style="opacity:0.2;fill:#407BFF;" d="M151.058,117.901c0,1.81-1.467,3.278-3.278,3.278c-1.81,0-3.278-1.468-3.278-3.278
c0-1.81,1.467-3.278,3.278-3.278C149.59,114.623,151.058,116.091,151.058,117.901z"/>
<path style="opacity:0.2;fill:#407BFF;" d="M140.642,127.246c0,2.42-1.962,4.381-4.381,4.381c-2.42,0-4.381-1.962-4.381-4.381
c0-2.42,1.962-4.381,4.381-4.381C138.68,122.865,140.642,124.827,140.642,127.246z"/>
</g>
<g>
<g>
<ellipse transform="matrix(0.2298 -0.9732 0.9732 0.2298 -71.7981 661.7775)" style="fill:#407BFF;" cx="382.197" cy="376.249" rx="19.226" ry="19.226"/>
<ellipse transform="matrix(0.2298 -0.9732 0.9732 0.2298 -71.7981 661.7775)" style="opacity:0.3;fill:#FFFFFF;" cx="382.197" cy="376.249" rx="19.226" ry="19.226"/>
</g>
<path style="opacity:0.4;fill:#407BFF;" d="M394.333,361.339c-1.749-0.531-3.612-0.812-5.538-0.812
c-10.619,0-19.229,8.61-19.229,19.228c0,6.018,2.759,11.379,7.09,14.908c1.749,0.531,3.612,0.812,5.539,0.812
c10.619,0,19.228-8.61,19.228-19.228C401.423,370.23,398.664,364.858,394.333,361.339z"/>
<path style="fill:#407BFF;" d="M363.83,381.948c-20.534,9.662-5.216,17.109,23.712,6.713
c26.784-9.626,36.967-21.769,13.052-18.006C401.828,375.763,368.282,388.834,363.83,381.948z"/>
</g>
</g>
</g>
<g id="Astronaut">
<g>
<path style="opacity:0.2;" d="M394.097,187.83c-26.89,18.17-61.7,42.13-71.31,99.81h-2.05c9.35-56.98,42.89-81.57,69.79-99.81
H394.097z"/>
<g>
<path style="fill:#407BFF;" d="M255.019,368.267c-16.97,0.001-33.809-7.662-41.986-20.186c-5.053-7.739-10.92-23.95,6.555-45.578
l1.556,1.258c-12.362,15.299-14.648,30.65-6.436,43.227c9.994,15.309,33.596,23.006,53.73,17.528
c20.628-5.613,33.152-23.557,34.361-49.228c4.135-87.807,50.784-114.855,84.846-134.605
c21.162-12.27,36.452-21.136,33.091-39.838c-0.466-2.595-1.501-4.388-3.163-5.481c-4.353-2.868-12.853-0.886-22.694,1.408
c-19.306,4.497-45.746,10.657-61.497-16.134l1.724-1.014c15.006,25.523,39.577,19.8,59.319,15.199
c10.29-2.396,19.177-4.467,24.248-1.131c2.145,1.412,3.464,3.636,4.032,6.799c3.609,20.082-13.013,29.72-34.057,41.922
c-33.664,19.519-79.768,46.251-83.852,132.968c-1.252,26.596-14.313,45.208-35.834,51.064
C264.427,367.679,259.716,368.266,255.019,368.267z"/>
<path style="opacity:0.2;fill:#FFFFFF;" d="M255.019,368.267c-16.97,0.001-33.809-7.662-41.986-20.186
c-5.053-7.739-10.92-23.95,6.555-45.578l1.556,1.258c-12.362,15.299-14.648,30.65-6.436,43.227
c9.994,15.309,33.596,23.006,53.73,17.528c20.628-5.613,33.152-23.557,34.361-49.228c4.135-87.807,50.784-114.855,84.846-134.605
c21.162-12.27,36.452-21.136,33.091-39.838c-0.466-2.595-1.501-4.388-3.163-5.481c-4.353-2.868-12.853-0.886-22.694,1.408
c-19.306,4.497-45.746,10.657-61.497-16.134l1.724-1.014c15.006,25.523,39.577,19.8,59.319,15.199
c10.29-2.396,19.177-4.467,24.248-1.131c2.145,1.412,3.464,3.636,4.032,6.799c3.609,20.082-13.013,29.72-34.057,41.922
c-33.664,19.519-79.768,46.251-83.852,132.968c-1.252,26.596-14.313,45.208-35.834,51.064
C264.427,367.679,259.716,368.266,255.019,368.267z"/>
</g>
<g>
<g>
<path style="fill:#407BFF;" d="M312.758,96.949c6.855-0.125,13.582,2.134,13.582,2.134s10.965,18.771,12.302,23.067
c-0.461,4.24-7.615,11.191-7.615,11.191L312.758,96.949z"/>
<path style="opacity:0.3;fill:#FFFFFF;" d="M312.758,96.949c6.855-0.125,13.582,2.134,13.582,2.134s10.965,18.771,12.302,23.067
c-0.461,4.24-7.615,11.191-7.615,11.191L312.758,96.949z"/>
</g>
<g>
<g>
<path style="fill:#407BFF;" d="M345.339,188.133c-4.136-5.248-8.197-10.594-11.559-16.385c-0.84-1.447-1.636-2.921-2.389-4.415
c-0.428-0.849-0.842-1.705-1.244-2.567c-0.351-0.753-1.126-1.862-1.204-2.684c-1.201-12.672,3.137-22-1.028-32.172
l-16.471,6.437c0,0,1.401,18.122,4.598,28.963c1.984,6.726,6.475,12.549,10.803,17.937c1.354,1.686,2.659,3.41,4.01,5.098
c1.279,1.598,2.712,3.064,3.994,4.654c1.947,2.413,2.595,4.716,1.115,7.561c-0.079,0.152-0.162,0.303-0.247,0.453
c-0.42,0.741,1.546,1.581,2.781,0.021c2.042-2.581,1.721-2.422,3.462-4.623c1.057-1.336,2.271-2.779,3.319-4.033
C346.303,191.155,346.326,189.385,345.339,188.133z"/>
<path style="opacity:0.7;fill:#FFFFFF;" d="M345.339,188.133c-4.136-5.248-8.197-10.594-11.559-16.385
c-0.84-1.447-1.636-2.921-2.389-4.415c-0.428-0.849-0.842-1.705-1.244-2.567c-0.351-0.753-1.126-1.862-1.204-2.684
c-1.201-12.672,3.137-22-1.028-32.172l-16.471,6.437c0,0,1.401,18.122,4.598,28.963c1.984,6.726,6.475,12.549,10.803,17.937
c1.354,1.686,2.659,3.41,4.01,5.098c1.279,1.598,2.712,3.064,3.994,4.654c1.947,2.413,2.595,4.716,1.115,7.561
c-0.079,0.152-0.162,0.303-0.247,0.453c-0.42,0.741,1.546,1.581,2.781,0.021c2.042-2.581,1.721-2.422,3.462-4.623
c1.057-1.336,2.271-2.779,3.319-4.033C346.303,191.155,346.326,189.385,345.339,188.133z"/>
</g>
<path style="opacity:0.3;fill:#407BFF;" d="M341.312,182.918c-2.205,2.665-6.688,6.122-8.664,7.523
c0.43,0.479,0.856,0.968,1.283,1.457c4.068-2.657,7.284-6.104,8.504-7.504C342.058,183.909,341.685,183.413,341.312,182.918z"/>
<path style="opacity:0.3;fill:#407BFF;" d="M345.335,188.135c-0.038-0.052-0.078-0.094-0.116-0.145
c-0.694,0.723-1.183,1.876-1.265,3.17c-0.066,0.894,0.084,1.712,0.377,2.351c0.333-0.386,0.644-0.768,0.949-1.131
C346.308,191.156,346.322,189.387,345.335,188.135z"/>
</g>
<g>
<g>
<path style="fill:#407BFF;" d="M308.842,108.951c-1.723,2.506-3.754,4.976-6.375,7.194c-1.301,1.115-2.786,2.124-4.417,2.98
c-0.823,0.42-1.688,0.784-2.583,1.085l-0.675,0.217l-0.218,0.068c-0.158,0.048-0.317,0.091-0.477,0.129
c-0.302,0.068-0.605,0.114-0.873,0.136c-1.083,0.082-1.868-0.072-2.515-0.233c-1.277-0.348-2.13-0.813-2.937-1.264
c-0.795-0.459-1.493-0.929-2.154-1.414c-1.302-0.991-2.48-1.986-3.578-3.048c-2.21-2.11-4.17-4.298-5.99-6.735
c-0.83-1.111-0.602-2.684,0.509-3.513c0.857-0.641,1.99-0.651,2.843-0.112l0.076,0.049c2.36,1.498,4.741,3.078,7.064,4.492
c1.173,0.692,2.319,1.388,3.446,1.93c0.554,0.28,1.097,0.535,1.587,0.716c0.477,0.186,0.953,0.292,1.077,0.267
c0.052-0.003-0.01-0.074-0.378-0.061c-0.089,0.005-0.215,0.017-0.343,0.045c-0.074,0.014-0.146,0.033-0.218,0.056
c-0.069,0.023,0.029-0.019,0.035-0.025l0.331-0.169c0.44-0.224,0.862-0.504,1.29-0.789c0.856-0.579,1.671-1.314,2.503-2.12
c1.646-1.635,3.23-3.67,4.902-5.786l0.022-0.029c1.712-2.168,4.858-2.537,7.026-0.825
C309.898,103.831,310.315,106.8,308.842,108.951z"/>
<path style="opacity:0.7;fill:#FFFFFF;" d="M308.842,108.951c-1.723,2.506-3.754,4.976-6.375,7.194
c-1.301,1.115-2.786,2.124-4.417,2.98c-0.823,0.42-1.688,0.784-2.583,1.085l-0.675,0.217l-0.218,0.068
c-0.158,0.048-0.317,0.091-0.477,0.129c-0.302,0.068-0.605,0.114-0.873,0.136c-1.083,0.082-1.868-0.072-2.515-0.233
c-1.277-0.348-2.13-0.813-2.937-1.264c-0.795-0.459-1.493-0.929-2.154-1.414c-1.302-0.991-2.48-1.986-3.578-3.048
c-2.21-2.11-4.17-4.298-5.99-6.735c-0.83-1.111-0.602-2.684,0.509-3.513c0.857-0.641,1.99-0.651,2.843-0.112l0.076,0.049
c2.36,1.498,4.741,3.078,7.064,4.492c1.173,0.692,2.319,1.388,3.446,1.93c0.554,0.28,1.097,0.535,1.587,0.716
c0.477,0.186,0.953,0.292,1.077,0.267c0.052-0.003-0.01-0.074-0.378-0.061c-0.089,0.005-0.215,0.017-0.343,0.045
c-0.074,0.014-0.146,0.033-0.218,0.056c-0.069,0.023,0.029-0.019,0.035-0.025l0.331-0.169c0.44-0.224,0.862-0.504,1.29-0.789
c0.856-0.579,1.671-1.314,2.503-2.12c1.646-1.635,3.23-3.67,4.902-5.786l0.022-0.029c1.712-2.168,4.858-2.537,7.026-0.825
C309.898,103.831,310.315,106.8,308.842,108.951z"/>
</g>
<g>
<path style="fill:#407BFF;" d="M272.285,102.416l1.172,1.966c0,0,0.895,2.616,2.686,3.1l4.854-1.572l-0.243-0.408
c0.002,0.001,0.005,0.001,0.007,0.001c-0.622-0.947-0.555-2.773-0.336-4.292c0.218-1.519-0.57-1.573-1.152-1.195
c-0.336,0.218-0.574,0.911-0.847,1.658c-0.239-0.329-0.495-0.646-0.784-0.934l-1.483-1.477c-0.64-0.637-1.665-0.666-2.34-0.066
l-1.202,1.068C272.005,100.809,271.866,101.712,272.285,102.416z"/>
<path style="opacity:0.7;fill:#FFFFFF;" d="M272.285,102.416l1.172,1.966c0,0,0.895,2.616,2.686,3.1l4.854-1.572l-0.243-0.408
c0.002,0.001,0.005,0.001,0.007,0.001c-0.622-0.947-0.555-2.773-0.336-4.292c0.218-1.519-0.57-1.573-1.152-1.195
c-0.336,0.218-0.574,0.911-0.847,1.658c-0.239-0.329-0.495-0.646-0.784-0.934l-1.483-1.477c-0.64-0.637-1.665-0.666-2.34-0.066
l-1.202,1.068C272.005,100.809,271.866,101.712,272.285,102.416z"/>
</g>
</g>
<g>
<path style="fill:#407BFF;" d="M317.674,95.224c-4.649,1.128-11.036,3.781-15.349,6.468c-1.529,0.952-2.292,2.76-1.932,4.525
c1.924,9.44,6.314,22.085,11.053,30.129l22.111-9.147c0.152-3.9-5.216-16.52-10.684-28.717
C321.891,96.288,320.01,94.658,317.674,95.224z"/>
<path style="opacity:0.8;fill:#FFFFFF;" d="M317.674,95.224c-4.649,1.128-11.036,3.781-15.349,6.468
c-1.529,0.952-2.292,2.76-1.932,4.525c1.924,9.44,6.314,22.085,11.053,30.129l22.111-9.147c0.152-3.9-5.216-16.52-10.684-28.717
C321.891,96.288,320.01,94.658,317.674,95.224z"/>
</g>
<path style="opacity:0.3;fill:#407BFF;" d="M326.296,106.214l-4.388-1.471c0.982,2.567,4.533,5.821,7.03,7.732
C328.115,110.469,327.223,108.372,326.296,106.214z"/>
<g>
<path style="fill:#407BFF;" d="M316.217,85.32c-1.825-3.481-5.774-5.233-10.516-4.837c-3.998,0.334-7.544,4.416-7.123,6.622
c0.42,2.206,3.785,3.14,4.394,3.906l-2.773,2.01c-1.38,1.001-1.65,2.947-0.596,4.287c1.167,1.482,2.703,3.03,3.598,4.123
c7.664-0.199,13.332-3.123,15.374-5.936C317.841,91.916,318.032,88.782,316.217,85.32z"/>
<path style="opacity:0.8;fill:#FFFFFF;" d="M316.217,85.32c-1.825-3.481-5.774-5.233-10.516-4.837
c-3.998,0.334-7.544,4.416-7.123,6.622c0.42,2.206,3.785,3.14,4.394,3.906l-2.773,2.01c-1.38,1.001-1.65,2.947-0.596,4.287
c1.167,1.482,2.703,3.03,3.598,4.123c7.664-0.199,13.332-3.123,15.374-5.936C317.841,91.916,318.032,88.782,316.217,85.32z"/>
</g>
<path style="fill:#263238;" d="M312.461,87.476c1.522,3.896-0.401,8.288-4.297,9.81c-3.896,1.522-8.288-0.401-9.81-4.297
c-1.522-3.895,0.401-8.288,4.297-9.81C306.546,81.657,310.938,83.581,312.461,87.476z"/>
<g>
<g>
<path style="fill:#407BFF;" d="M377.388,177.596c-0.111-3.289-0.253-2.96-0.349-5.764c-0.058-1.703-0.065-3.589-0.076-5.223
c-0.011-1.595-1.138-2.96-2.701-3.277c-1.325-0.269-2.654-0.525-3.977-0.807c-1.726-0.368-3.432-0.764-5.127-1.256
c-1.314-0.382-2.617-0.803-3.905-1.267c-1.38-0.497-2.741-1.042-4.089-1.62c-1.576-0.676-3.133-1.396-4.678-2.138
c-1.725-0.828-3.437-1.684-5.143-2.551c-6.581-10.895-6.723-18.074-13.786-26.495l-15.16,6.858
c0,0,11.139,19.765,18.725,28.145c4.367,4.823,11.218,6.997,17.328,8.575c4.408,1.138,8.878,2.009,13.353,2.831
c1.74,0.319,3.631,0.443,5.128,1.482c1.179,0.818,1.789,2.095,2.137,3.452c0.071,0.277,0.131,0.557,0.185,0.839
C375.413,180.217,377.456,179.585,377.388,177.596z"/>
<path style="opacity:0.8;fill:#FFFFFF;" d="M377.388,177.596c-0.111-3.289-0.253-2.96-0.349-5.764
c-0.058-1.703-0.065-3.589-0.076-5.223c-0.011-1.595-1.138-2.96-2.701-3.277c-1.325-0.269-2.654-0.525-3.977-0.807
c-1.726-0.368-3.432-0.764-5.127-1.256c-1.314-0.382-2.617-0.803-3.905-1.267c-1.38-0.497-2.741-1.042-4.089-1.62
c-1.576-0.676-3.133-1.396-4.678-2.138c-1.725-0.828-3.437-1.684-5.143-2.551c-6.581-10.895-6.723-18.074-13.786-26.495
l-15.16,6.858c0,0,11.139,19.765,18.725,28.145c4.367,4.823,11.218,6.997,17.328,8.575c4.408,1.138,8.878,2.009,13.353,2.831
c1.74,0.319,3.631,0.443,5.128,1.482c1.179,0.818,1.789,2.095,2.137,3.452c0.071,0.277,0.131,0.557,0.185,0.839
C375.413,180.217,377.456,179.585,377.388,177.596z"/>
</g>
<path style="opacity:0.3;fill:#407BFF;" d="M369.7,162.4c-0.597-0.131-1.203-0.265-1.806-0.408
c0.047,3.453-1.572,9.417-2.167,11.224c0.631,0.119,1.271,0.241,1.902,0.361C369.384,168.832,369.66,163.809,369.7,162.4z"/>
<path style="opacity:0.3;fill:#407BFF;" d="M376.961,166.61c-0.011-1.599-1.134-2.961-2.694-3.281
c-0.314-0.064-0.638-0.132-0.954-0.186c0.066,0.94,0.65,2.031,1.628,2.897c0.641,0.578,1.366,0.962,2.032,1.143
C376.963,166.984,376.962,166.797,376.961,166.61z"/>
</g>
<path style="fill:#FFFFFF;" d="M311.046,87.54c0.405,1.516-1.292,3.11-2.65,1.799c-1.102-1.064-2.762-2.846-4.117-3.693
c-1.392-0.871,0.464-2.387,2.65-1.799C308.97,84.397,310.641,86.023,311.046,87.54z"/>
<g>
<path style="fill:#407BFF;" d="M311.161,135.86c-0.705,0.26,0.583,1.456,0.583,1.456s13.97-4.787,22.495-9.716
c0.072-1.031-0.678-1.578-0.678-1.578S323.189,131.426,311.161,135.86z"/>
<path style="opacity:0.5;fill:#FFFFFF;" d="M311.161,135.86c-0.705,0.26,0.583,1.456,0.583,1.456s13.97-4.787,22.495-9.716
c0.072-1.031-0.678-1.578-0.678-1.578S323.189,131.426,311.161,135.86z"/>
</g>
<g>
<g>
<path style="fill:#407BFF;" d="M321.46,94.563c2.758,1.393,5.354,2.868,7.947,4.501c1.291,0.813,2.576,1.648,3.842,2.549
c1.276,0.883,2.535,1.814,3.798,2.862l0.474,0.388l0.591,0.533c0.42,0.37,0.728,0.711,1.037,1.051
c0.324,0.351,0.591,0.689,0.854,1.026c0.273,0.339,0.532,0.676,0.765,1.008c0.989,1.328,1.795,2.679,2.586,4.019
c1.537,2.717,2.868,5.43,3.966,8.349c0.49,1.302-0.168,2.754-1.471,3.245c-0.978,0.368-2.042,0.088-2.718-0.626l-0.049-0.054
c-2.009-2.128-3.936-4.373-5.875-6.458c-1.897-2.079-3.912-4.213-5.537-5.141c-2.27-1.416-4.798-2.822-7.31-4.207l-7.563-4.198
l-0.019-0.01c-2.415-1.34-3.286-4.384-1.946-6.799C316.141,94.246,319.077,93.363,321.46,94.563z"/>
<path style="opacity:0.8;fill:#FFFFFF;" d="M321.46,94.563c2.758,1.393,5.354,2.868,7.947,4.501
c1.291,0.813,2.576,1.648,3.842,2.549c1.276,0.883,2.535,1.814,3.798,2.862l0.474,0.388l0.591,0.533
c0.42,0.37,0.728,0.711,1.037,1.051c0.324,0.351,0.591,0.689,0.854,1.026c0.273,0.339,0.532,0.676,0.765,1.008
c0.989,1.328,1.795,2.679,2.586,4.019c1.537,2.717,2.868,5.43,3.966,8.349c0.49,1.302-0.168,2.754-1.471,3.245
c-0.978,0.368-2.042,0.088-2.718-0.626l-0.049-0.054c-2.009-2.128-3.936-4.373-5.875-6.458
c-1.897-2.079-3.912-4.213-5.537-5.141c-2.27-1.416-4.798-2.822-7.31-4.207l-7.563-4.198l-0.019-0.01
c-2.415-1.34-3.286-4.384-1.946-6.799C316.141,94.246,319.077,93.363,321.46,94.563z"/>
</g>
<g>
<path style="fill:#407BFF;" d="M349.733,125.738l-0.849-2.125c0,0-0.474-2.724-2.167-3.483l-5.04,0.792l0.176,0.441
c-0.002-0.001-0.004-0.002-0.007-0.002c0.466,1.032,0.113,2.826-0.341,4.291c-0.454,1.466,0.316,1.643,0.95,1.361
c0.366-0.163,0.71-0.81,1.096-1.505c0.185,0.363,0.388,0.716,0.628,1.045l1.233,1.691c0.532,0.729,1.54,0.919,2.301,0.432
l1.354-0.867C349.758,127.368,350.038,126.499,349.733,125.738z"/>
<path style="opacity:0.8;fill:#FFFFFF;" d="M349.733,125.738l-0.849-2.125c0,0-0.474-2.724-2.167-3.483l-5.04,0.792
l0.176,0.441c-0.002-0.001-0.004-0.002-0.007-0.002c0.466,1.032,0.113,2.826-0.341,4.291c-0.454,1.466,0.316,1.643,0.95,1.361
c0.366-0.163,0.71-0.81,1.096-1.505c0.185,0.363,0.388,0.716,0.628,1.045l1.233,1.691c0.532,0.729,1.54,0.919,2.301,0.432
l1.354-0.867C349.758,127.368,350.038,126.499,349.733,125.738z"/>
</g>
</g>
<g>
<g>
<path style="opacity:0.3;fill:#407BFF;" d="M317.236,106.057l-1.219,0.099l-7.485,18.084c0.44,0.03,0.844-0.007,1.218-0.099
c0,0,9.76-3.637,12.714-4.97C320.476,115.051,317.236,106.057,317.236,106.057z"/>
<path style="fill:#FFFFFF;" d="M303.568,110.802c0.417,3.257,2.859,10.179,4.965,13.438c3.655-1.26,9.76-3.637,12.714-4.97
c-1.989-4.119-4.083-9.795-5.229-13.113C312.869,106.366,306.006,108.951,303.568,110.802z"/>
</g>
<path style="opacity:0.3;fill:#407BFF;" d="M311,114.713c-0.408,1.365-1.846,2.14-3.21,1.731s-2.14-1.846-1.731-3.21
c0.409-1.365,1.846-2.14,3.21-1.731C310.633,111.911,311.408,113.348,311,114.713z"/>
<path style="opacity:0.6;fill:#407BFF;" d="M312.913,111.268c-0.134,0.447-0.605,0.701-1.052,0.567
c-0.447-0.134-0.701-0.605-0.568-1.052c0.134-0.447,0.605-0.701,1.052-0.567C312.793,110.349,313.047,110.82,312.913,111.268z"
/>
<path style="opacity:0.6;fill:#407BFF;" d="M315.145,110.399c-0.134,0.447-0.605,0.701-1.052,0.567
c-0.447-0.134-0.701-0.605-0.567-1.052c0.134-0.447,0.605-0.701,1.052-0.567C315.025,109.481,315.279,109.952,315.145,110.399z"
/>
<polygon style="opacity:0.5;fill:#407BFF;" points="318.291,118.187 309.044,121.841 308.485,120.023 317.732,116.368 "/>
</g>
</g>
</g>
</g>
<g id="Rocket">
<g>
<path style="opacity:0.2;" d="M267.257,257.17c-0.2,7.54-0.76,13.33-1.68,17.35c-1.18,5.14-3.01,8.9-5.5,11.28
c-2.48,2.38-5.42,3.57-8.81,3.57c-5.14,0-9.07-2.8-11.77-8.41c-0.44-0.91-0.84-1.95-1.21-3.11c-5.71,4.91-11.03,10.27-15.92,16.03
l-5.31,6.26c2.87,2.91,6.13,5.3,9.77,7.19c6.23,3.22,14.4,4.84,24.52,4.84c1.78,0,3.5-0.05,5.17-0.15
c6.12-9.06,11.19-18.8,15.1-29.02l14.85-38.72L267.257,257.17z"/>
<g>
<g>
<path style="fill:#263238;" d="M133.388,309.958c5.597,5.597,17.502,17.502,17.502,17.502l49.011-46.167
C183.035,274.881,150.159,293.188,133.388,309.958z"/>
<path style="fill:#263238;" d="M194.422,370.992c-5.597-5.597-17.502-17.502-17.502-17.502l46.167-49.01
C229.499,321.345,211.193,354.221,194.422,370.992z"/>
<g>
<path style="fill:#407BFF;" d="M261.399,260.699l19.091-36.809l-36.809,19.091c-11.826,6.134-22.744,13.877-32.444,23.008
l-62.747,59.07l30.83,30.83l59.07-62.747C247.522,283.443,255.265,272.525,261.399,260.699z"/>
<path style="opacity:0.6;fill:#FFFFFF;" d="M261.399,260.699l19.091-36.809l-36.809,19.091
c-11.826,6.134-22.744,13.877-32.444,23.008l-62.747,59.07l30.83,30.83l59.07-62.747
C247.522,283.443,255.265,272.525,261.399,260.699z"/>
</g>
<circle style="fill:#FFFFFF;" cx="222.198" cy="282.183" r="12.899"/>
<circle style="fill:#407BFF;" cx="222.197" cy="282.183" r="8.285"/>
<polygon style="opacity:0.3;fill:#407BFF;" points="189.746,344.816 159.564,314.635 184.275,291.371 213.009,320.105 "/>
<g>
<path style="fill:#407BFF;" d="M140.22,337.616c-22.605,1.839-30.093,16.306-32.647,35.539
c-1.302,9.809-1.88,19.733-10.117,25.475c-2.286,1.594-1.151,5.147,1.635,5.06c30.339-0.947,44.49-15.804,46.267-22.025
c-0.612,3.933-1.504,7.035-2.492,9.475c-1.016,2.507,1.737,4.827,4.029,3.391c8.517-5.336,19.199-15.155,19.909-31.078
C160.507,354.603,140.22,337.616,140.22,337.616z"/>
<path style="opacity:0.2;fill:#FFFFFF;" d="M140.22,337.616c-22.605,1.839-30.093,16.306-32.647,35.539
c-1.302,9.809-1.88,19.733-10.117,25.475c-2.286,1.594-1.151,5.147,1.635,5.06c30.339-0.947,44.49-15.804,46.267-22.025
c-0.612,3.933-1.504,7.035-2.492,9.475c-1.016,2.507,1.737,4.827,4.029,3.391c8.517-5.336,19.199-15.155,19.909-31.078
C160.507,354.603,140.22,337.616,140.22,337.616z"/>
</g>
<polygon style="fill:#407BFF;" points="170.276,370.3 134.08,334.104 153.363,329.933 174.448,351.017 "/>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -2,7 +2,7 @@ import { FaInstagram, FaTelegram, FaTwitter } from "react-icons/fa6";
const SocialMedia = () => { const SocialMedia = () => {
return ( return (
<div className="w-full h-full flex pt-2 gap-5 justify-center items-center"> <div className="w-full h-full flex p-3 gap-5 justify-center items-center">
<FaInstagram /> <FaInstagram />
<FaTwitter /> <FaTwitter />
<FaTelegram /> <FaTelegram />

View File

@@ -2,12 +2,33 @@ import CopyRight from "./components/CopyRight";
import SocialMedia from "./components/SocialMedia"; import SocialMedia from "./components/SocialMedia";
const Footer = () => { const Footer = () => {
const code = "k8K3Na16cdzB31hBnriumB3rvZOblawy";
return ( return (
<div className="relative w-full p-5 h-[10rem]"> <div className="relative w-full p-5 h-full">
<footer className="glass w-full flex flex-col justify-center items-center gap-2 h-full"> <div className="w-full h-full"></div>
<SocialMedia /> <footer className="glass w-full flex flex-row-reverse h-full">
<hr className="w-3/4 border-gray-700" /> <div className="w-full h-full flex flex-col py-4 justify-center items-center gap-2">
<CopyRight /> <SocialMedia />
<hr className="w-5/6 border-gray-700" />
<CopyRight />
</div>
<div className="w-auto h-full flex my-auto mr-4 md:mr-10 justify-center items-center">
<a
referrerPolicy="origin"
target="_blank"
href={`https://trustseal.enamad.ir/?id=515269&Code=${code}`}
rel="noopener noreferrer"
>
<img
referrerPolicy="origin"
src={`https://trustseal.enamad.ir/logo.aspx?id=515269&Code=${code}`}
alt="Enamad Trust Seal"
style={{ cursor: "pointer" }}
className="w-20"
/>
</a>
</div>
</footer> </footer>
</div> </div>
); );

View File

@@ -44,7 +44,7 @@ const Navbar = ({extra}:{extra?:string}) => {
})} })}
</div> </div>
{auth ? ( {auth ? (
<Button onClick={() => navigate("/profile")}>پروفایل</Button> <Button onClick={() => navigate("/profile")}>صفحه کاربری</Button>
) : ( ) : (
<Button onClick={() => navigate("/login")}>ورود یا ثبت نام</Button> <Button onClick={() => navigate("/login")}>ورود یا ثبت نام</Button>
)} )}

View File

@@ -1,12 +1,13 @@
import { NavLink } from "react-router-dom"; import { NavLink, useLocation } from "react-router-dom";
import { NavbarLinkProps, NavData } from "../../../../types/props"; import { NavbarLinkProps, NavData } from "../../../../types/props";
const NavbarLink = ({ to, children, onClick }: NavbarLinkProps) => { const NavbarLink = ({ to, children, onClick }: NavbarLinkProps) => {
const location = useLocation();
return ( return (
<NavLink <NavLink
to={to} to={to}
className={(navData: NavData) => className={(navData: NavData) =>
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 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" : "block px-2 mx-3 py-2 rounded-md text-base font-medium text-white"
} }

View File

@@ -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 (
<>
<div
className={`fixed inset-y-0 right-0 w-1/2 glass transform ${
isOpen ? "translate-x-0" : "translate-x-full"
} transition-transform duration-300 ease-in-out z-50 md:hidden`}
>
<div className="absolute top-0 left-0 p-4">
<button onClick={toggleMenu} className="text-white">
<svg
className="h-6 w-6"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
aria-hidden="true"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</div>
<div className="p-8 mt-4 ">
{routes?.map((i) => {
return (
<NavbarLink key={i.id} to={"#"} onClick={toggleMenu}>
{i.name}
</NavbarLink>
);
})}
</div>
</div>
{isOpen && (
<div
className="fixed inset-0 bg-black bg-opacity-50 backdrop-filter backdrop-blur-sm z-40 md:hidden"
onClick={toggleMenu}
></div>
)}
</>
);
};
export default MobileMenu;

View File

@@ -0,0 +1,48 @@
import { MobileMenuButtonProps } from "../../../../types/props";
const MobileMenuButton = ({ isOpen, onClick }: MobileMenuButtonProps) => {
return (
<button
onClick={onClick}
type="button"
className="p-2 rounded-md scale-110 text-gray-400 hover:text-white hover:bg-gray-700 focus:outline-none"
>
<span className="sr-only">{"باز کردن منو"}</span>
{!isOpen ? (
<svg
className="block h-6 w-6"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
aria-hidden="true"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M4 6h16M4 12h16M4 18h16"
/>
</svg>
) : (
<svg
className="block h-6 w-6"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
aria-hidden="true"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
)}
</button>
);
};
export default MobileMenuButton;

View File

@@ -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<boolean>(false);
const [routes] = useState<Route[]>(router);
const toggleMenu = () => {
setIsOpen(!isOpen);
};
useEffect(() => {
if (isOpen) {
document.body.style.overflow = "hidden";
} else {
document.body.style.overflow = "auto";
}
}, [isOpen]);
return (
<div className="relative">
<nav className={`glass text-white p-4 flex justify-between items-center ${extra}`}>
<div className="flex items-center">
<h1 className="text-xl font-bold">پرشین پینگ</h1>
</div>
<div className="flex gap-3 md:space-x-4">
<div className="hidden md:flex space-x-4">
{routes?.map((i) => {
return (
<NavbarLink key={i.id} to={"#"}>
{i.name}
</NavbarLink>
);
})}
</div>
<Button>ورود یا ثبت نام</Button>
<div className="md:hidden">
<MobileMenuButton isOpen={isOpen} onClick={toggleMenu} />
</div>
</div>
</nav>
<MobileMenu isOpen={isOpen} toggleMenu={toggleMenu} routes={routes} />
</div>
);
};
export default Navbar;

View File

@@ -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 (
<NavLink
to={to}
className={(navData: NavData) =>
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}
</NavLink>
);
};
export default NavbarLink;

View File

@@ -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 (
<div className="w-full p-5 h-[7rem]">
<header className={`w-full transition-all duration-300 ease-in-out ${isFixed ? "fixed max-w-[1400px] h-[6rem] mx-auto z-[1000] inset-0 p-2" : ""}`}>
<Navbar extra={`${isFixed && '!bg-gray-800/90'}`}/>
</header>
</div>
);
};
export default LandingHeader;

View File

@@ -4,10 +4,22 @@ import { ProgressSpaceProps } from "../../types/props";
const ProgressSpace = ({ startSpace, endSpace }: ProgressSpaceProps) => { const ProgressSpace = ({ startSpace, endSpace }: ProgressSpaceProps) => {
let startSpacePercentage; let startSpacePercentage;
let remaining; let remaining;
if (typeof endSpace === "number") { let startSpaceToNumber = Number(startSpace);
startSpacePercentage = (startSpace / endSpace) * 100; let endSpaceToNumber = Number(endSpace);
remaining = endSpace - startSpace;
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 ( return (
<> <>
<div className="relative w-full h-full p-3 bg-gray-800 rounded-md flex gap-2 justify-center items-center"> <div className="relative w-full h-full p-3 bg-gray-800 rounded-md flex gap-2 justify-center items-center">
@@ -18,7 +30,7 @@ const ProgressSpace = ({ startSpace, endSpace }: ProgressSpaceProps) => {
</div> </div>
<div className="w-full rounded-full h-2 md:h-2.5 bg-gray-700"> <div className="w-full rounded-full h-2 md:h-2.5 bg-gray-700">
<motion.div <motion.div
className="bg-secondTheme h-2 md:h-2.5 rounded-full" className={`${isMaxSpace ? 'bg-rose-600' : 'bg-secondTheme'} h-2 md:h-2.5 rounded-full`}
initial={{ width: 0 }} initial={{ width: 0 }}
animate={{ animate={{
width: `${ width: `${
@@ -35,13 +47,18 @@ const ProgressSpace = ({ startSpace, endSpace }: ProgressSpaceProps) => {
</div> </div>
</div> </div>
<div className="w-full h-full mt-1 p-2 text-center text-xs md:text-base"> <div className="w-full h-full mt-1 p-2 text-center text-xs md:text-base">
<p> {isMaxSpace ? (
{" "} <p>حجم شما به پایان رسیده است</p>
حجم باقیمانده کانفیگ شما از{" "} ) : (
{endSpace === "unlimited" ? "نامحدود" : endSpace} گیگ{" "} <p>
<span className="mx-1 border-b border-secondTheme">{remaining}</span> حجم باقیمانده کانفیگ شما از{" "}
گیگ میباشد{" "} {endSpace === "unlimited" ? "نامحدود" : endSpace} گیگ{" "}
</p> <span className="mx-1 border-b border-secondTheme">
{remaining.toFixed(2)}
</span>{" "}
گیگ می‌باشد
</p>
)}
</div> </div>
</> </>
); );

View File

@@ -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 (
<>
<Helmet>
<title>پرشین پینگ | Persian Ping</title>
<meta
name="description"
content="بهترین خدمات فروشگاه جم و سی پی برای بازی‌های آنلاین با پرشین پینگ"
/>
<meta
name="keywords"
content="پرشین پینگ, خدمات بازی, بازی آنلاین, خرید یوسی پابجی موبایل"
/>
</Helmet>
<Particle />
<div className={`relative bg-noisy w-full min-h-screen`}>
<div className="relative max-w-[1400px] mx-auto h-full flex flex-col justify-between">
<div className="relative w-full h-full">
<LandingHeader />
<main className="w-full h-full px-5 py-0">
<Outlet />
</main>
</div>
<Footer />
</div>
</div>
</>
);
};
export default LandingLayout;

View File

@@ -11,8 +11,9 @@ const Layout = () => {
const { configs } = useParams<{ configs: string }>(); const { configs } = useParams<{ configs: string }>();
const dispatch = useDispatch(); const dispatch = useDispatch();
useEffect(() => { useEffect(() => {
if (configs === "1" || configs === "2" || configs === "3") if (configs === "1" || configs === "2" || configs === "3") {
dispatch(setConfigId(configs)); dispatch(setConfigId(configs));
}
if (configs) if (configs)
setTimeout(() => { setTimeout(() => {
const element = document.getElementById("configs"); const element = document.getElementById("configs");

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 ( return (
<> <>
<Helmet> <Helmet>
<title>درباره ما</title> <title>پرشین پینگ | درباره ما </title>
<meta <meta
name="description" name="description"
content="بهترین خدمات پینگ برای بازی‌های آنلاین با پرشین پینگ" content="درباره پرشین پینگ - تیم ما و ماموریت ما در ارائه بهترین پینگ برای بازی‌های آنلاین ."
/> />
<meta <meta
name="keywords" name="keywords"
content="پرشین پینگ, خدمات پینگ, بازی آنلاین, کاهش پینگ , درباره ما" content="پرشین پینگ, خدمات پینگ, بازی آنلاین, کاهش پینگ , درباره ما"
/> />
<meta name="robots" content="index, follow" />
</Helmet> </Helmet>
<div className="relative w-full h-full py-2"> <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 axios.get("/profile");
}, },
}); });
return ( return (
<> <>
{!mutation.isPending && ( {!mutation.isPending && (

View File

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

View File

@@ -9,37 +9,44 @@ import toast from "react-hot-toast";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import { setCategoryId } from "../../../../redux/slices/categoryId"; import { setCategoryId } from "../../../../redux/slices/categoryId";
import { useQuery } from "@tanstack/react-query";
import useAxios from "../../../../hooks/useAxios";
import LoaderSpaceConfig from "./LoaderSpaceConfig";
const ConfigItem = ({ const ConfigItem = ({
id,
dateBuy, dateBuy,
configName, configName,
isDisabled, isDisabled,
isShowTraffic, isShowTraffic,
textCopy, textCopy,
maxTraffic,
traffic,
type, type,
categoryId, categoryId,
useMaxTraffic
}: ConfigItemProps) => { }: ConfigItemProps) => {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [isOpenDropDown, setIsOpenDropDown] = useState(false); const [isOpenDropDown, setIsOpenDropDown] = useState(false);
const [configId, setConfigId] = useState("");
const dispatch = useDispatch(); const dispatch = useDispatch();
const navigate = useNavigate(); const navigate = useNavigate();
const [spaceConfig, setSpaceConfig] = useState({
maxTraffic: 0,
traffic: 0,
});
const axios = useAxios();
const handleToggle = () => { 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) => { const copyToClipboard = async (textToCopy: string) => {
try { try {
await navigator.clipboard.writeText(textToCopy); await navigator.clipboard.writeText(textToCopy);
toast.success("متن با موفقیت کپی شد!"); toast.success("متن با موفقیت کپی شد!");
} catch (err) { } catch (err) {
try { toast.error(`Failed to copy: , ${err}`);
await navigator.clipboard.writeText(copyText); setIsOpen(true);
toast.success("متن با موفقیت کپی شد!");
} catch (err) {
toast.error(`Failed to copy: , ${err}`);
}
} }
}; };
@@ -57,6 +64,25 @@ const ConfigItem = ({
} }
}, [textCopy]); }, [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 ( return (
<> <>
<ModalConfigDetails <ModalConfigDetails
@@ -67,24 +93,29 @@ const ConfigItem = ({
nameConfig={configName} nameConfig={configName}
isShowTraffic={isShowTraffic} isShowTraffic={isShowTraffic}
textCopy={textCopy} textCopy={textCopy}
maxTraffic={maxTraffic} maxTraffic={spaceConfig.maxTraffic}
traffic={traffic} traffic={spaceConfig.traffic}
type={type} type={type}
username={username} username={username}
password={password} password={password}
categoryId={categoryId} categoryId={categoryId}
isLoadSpaceConfig={
queryUpdateConfig.isLoading || queryUpdateConfig.isFetching
}
error={queryUpdateConfig?.error ? queryUpdateConfig?.error : null}
useMaxTraffic={useMaxTraffic}
/> />
<div className="relative w-full h-full rounded-md"> <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="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> غیر کانفیگ <span className="text-secondTheme">{configName}</span> غیر
فعال است .{" "} فعال است .{" "}
<Button <Button
extra="cursor-pointer !px-1 !py-0 rounded-md bg-white" extra="cursor-pointer !px-1 !py-0 rounded-md bg-white"
onClick={() => setIsOpen(true)} onClick={() => setIsOpen(true)}
> >
برای تمدید کلیک کنید مشاهده
</Button> </Button>
</div> </div>
</div> </div>
@@ -101,16 +132,6 @@ const ConfigItem = ({
<div className="max-md:hidden flex flex-row-reverse gap-2 justify-end items-center"> <div className="max-md:hidden flex flex-row-reverse gap-2 justify-end items-center">
{type === "gaming" ? ( {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 <Button
onClick={() => { onClick={() => {
setCopyText(password); setCopyText(password);
@@ -121,6 +142,16 @@ const ConfigItem = ({
کپی پسورد کپی پسورد
<IoCopy /> <IoCopy />
</Button> </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 <Button
@@ -145,7 +176,7 @@ const ConfigItem = ({
> >
آموزش آموزش
</Button> </Button>
{isShowTraffic && ( {isShowTraffic && !useMaxTraffic && (
<Dropdown isOpen={isOpenDropDown} setIsOpen={setIsOpenDropDown}> <Dropdown isOpen={isOpenDropDown} setIsOpen={setIsOpenDropDown}>
<Button <Button
id="dropdownDefaultButton" id="dropdownDefaultButton"
@@ -157,7 +188,21 @@ const ConfigItem = ({
حجم حجم
</Button> </Button>
<DropdownItem widthTailwind="w-[20rem] left-0"> <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> </DropdownItem>
</Dropdown> </Dropdown>
)} )}
@@ -165,7 +210,10 @@ const ConfigItem = ({
<div className="md:hidden flex flex-row-reverse gap-2 justify-end items-center"> <div className="md:hidden flex flex-row-reverse gap-2 justify-end items-center">
<Button <Button
extra="!m-0 !px-2 !py-1 shadow-md" extra="!m-0 !px-2 !py-1 shadow-md"
onClick={() => setIsOpen(true)} onClick={() => {
setConfigId(id);
setIsOpen(true);
}}
> >
مشاهده جزئیات مشاهده جزئیات
</Button> </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 { useNavigate } from "react-router-dom";
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import { setCategoryId } from "../../../../redux/slices/categoryId"; import { setCategoryId } from "../../../../redux/slices/categoryId";
import Input from "../../../../components/input";
import LoaderSpaceConfig from "./LoaderSpaceConfig";
import { AxiosError } from "axios";
const ModalConfigDetails = ({ const ModalConfigDetails = ({
isOpen, isOpen,
@@ -23,6 +26,9 @@ const ModalConfigDetails = ({
username, username,
password, password,
categoryId, categoryId,
isLoadSpaceConfig,
error,
useMaxTraffic,
}: { }: {
isOpen: boolean; isOpen: boolean;
setIsOpen: Dispatch<SetStateAction<boolean>>; setIsOpen: Dispatch<SetStateAction<boolean>>;
@@ -37,10 +43,14 @@ const ModalConfigDetails = ({
username: string; username: string;
password: string; password: string;
categoryId: number; categoryId: number;
isLoadSpaceConfig: boolean;
error: AxiosError | any;
useMaxTraffic: boolean;
}) => { }) => {
const navigate = useNavigate(); const navigate = useNavigate();
const dispatch = useDispatch(); const dispatch = useDispatch();
const [copyText, setCopyText] = useState<string>(""); const [_, setCopyText] = useState<string>("");
const [isCopyError, setIsCopyError] = useState(false);
const copyToClipboard = async (textToCopy: string) => { const copyToClipboard = async (textToCopy: string) => {
try { try {
@@ -48,12 +58,8 @@ const ModalConfigDetails = ({
toast.success("متن با موفقیت کپی شد!"); toast.success("متن با موفقیت کپی شد!");
} catch (err) { } catch (err) {
try { setIsCopyError(true);
await navigator.clipboard.writeText(copyText); toast.error(`Failed to copy: , ${err}`);
toast.success("متن با موفقیت کپی شد!");
} catch (err) {
toast.error(`Failed to copy: , ${err}`);
}
} }
}; };
return ( return (
@@ -68,48 +74,95 @@ const ModalConfigDetails = ({
تاریخ خرید : {dateBuy} تاریخ خرید : {dateBuy}
</h1> </h1>
<div className="w-full h-full flex flex-row-reverse gap-2 flex-wrap justify-center items-center"> <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"> <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> </div>
) : ( ) : (
<> <>
{type === "gaming" ? ( {type === "gaming" ? (
<> <>
<Button {isCopyError ? (
onClick={() => { <div className="w-full h-full flex flex-col gap-2">
setCopyText(username); <h1 className="bg-red-600 rounded-md p-1">
copyToClipboard(username); کاربر گرامی کپی خودکار موفقیت آمیز نبود لطفا به صورت
}} دستی از زیر انتخاب کرده و کپی کنید
extra="!m-0 !px-2 !py-1.5 flex flex-row-reverse justify-center items-center gap-1 shadow-md shadow-white" </h1>
> <Input
کپی یوزرنیم type="text"
<IoCopy /> value={`نام کاربری : ${username}`}
</Button> disabled={true}
<Button />
onClick={() => { <Input
setCopyText(password); type="text"
copyToClipboard(password); value={`رمز عبور : ${password}`}
}} disabled={true}
extra="!m-0 !px-2 !py-1.5 flex flex-row-reverse justify-center items-center gap-1 shadow-md shadow-white" />
> </div>
کپی پسورد ) : (
<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>
<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={() => { {isCopyError ? (
setCopyText(textCopy); <>
copyToClipboard(textCopy); <div className="w-full h-full flex flex-col gap-2">
}} <h1 className="bg-red-600 rounded-md p-1">
extra="!m-0 !px-2 !py-1.5 flex flex-row-reverse justify-center items-center gap-1 shadow-md shadow-white" کاربر گرامی کپی خودکار موفقیت آمیز نبود لطفا به صورت
> دستی از زیر انتخاب کرده و کپی کنید
کپی </h1>
<IoCopy /> <textarea
</Button> 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 <Button
onClick={() => { onClick={() => {
@@ -127,7 +180,18 @@ const ModalConfigDetails = ({
</div> </div>
{!isDisabled && isShowTraffic && ( {!isDisabled && isShowTraffic && (
<div className="w-full h-full"> <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>
)} )}
</div> </div>

View File

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

View File

@@ -9,15 +9,16 @@ const Shop = () => {
return ( return (
<> <>
<Helmet> <Helmet>
<title>فروشگاه</title> <title>پرشین پینگ | فروشگاه </title>
<meta <meta
name="description" name="description"
content="بهترین خدمات پینگ برای بازی‌های آنلاین با پرشین پینگ" content="پرشین پینگ - بهترین خدمات پینگ برای بازی‌های آنلاین با پرشین پینگ"
/> />
<meta <meta
name="keywords" name="keywords"
content="پرشین پینگ, خدمات پینگ, بازی آنلاین, کاهش پینگ و فروشگاه" content="پرشین پینگ, خدمات پینگ, بازی آنلاین, کاهش پینگ و فروشگاه"
/> />
<meta name="robots" content="index, follow" />
</Helmet> </Helmet>
<div className="relative w-full h-full py-2"> <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; errorMessage = (err.response.data as { alert: string }).alert;
} }
toast.error(`خطایی رخ داد : ${errorMessage}`)
// dispatch(setIsPaymentGateway(false));
// navigate("/noactive-payment");
return errorMessage; return errorMessage;
}, },
}); });
@@ -157,7 +160,7 @@ const ModalBuy = ({ isOpen, setIsOpen, configId }: ModalBuyProps) => {
<MuiModal <MuiModal
isOpenModal={isOpen} isOpenModal={isOpen}
setIsOpenModal={setIsOpen} setIsOpenModal={setIsOpen}
submitText="خرید" submitText={data?.data?.result?.max_config === 0 ? undefined : "خرید"}
submitOnClick={submitHandler} submitOnClick={submitHandler}
disabled={isLoading || isFetching} disabled={isLoading || isFetching}
nameService={ nameService={
@@ -212,66 +215,76 @@ const ModalBuy = ({ isOpen, setIsOpen, configId }: ModalBuyProps) => {
)} )}
</span> </span>
</h1> </h1>
<h3 className="text-xs md:text-sm text-gray-400"> {data?.data?.result?.max_config === 0 ? (
در صورت نداشتن کد تخفیف پرداخت رو بزنید <>
</h3> <Alert type="info" extra="mt-5"> موجودی کانفیگ به اتمام رسیده </Alert>
<form </>
className="flex flex-col gap-3 justify-center items-center" ) : (
onSubmit={formik.handleSubmit} <>
> <h3 className="text-xs md:text-sm text-gray-400">
<div className="w-full h-full flex justify-center items-center gap-2"> در صورت نداشتن کد تخفیف پرداخت رو بزنید
<Input </h3>
type="text" <form
extra="max-md:!p-1 md:!p-2" className="flex flex-col gap-3 justify-center items-center"
{...formik.getFieldProps("discount")} onSubmit={formik.handleSubmit}
/>
<Button
extra="md:!py-1 disabled:!bg-gray-300"
onClick={discountHandler}
disabled={formik.values.discount === ""}
> >
اعمال <div className="w-full h-full flex justify-center items-center gap-2">
</Button> <Input
</div> type="text"
<div className="w-2/3 h-full flex justify-center items-center gap-1"> extra="max-md:!p-1 md:!p-2"
<Button {...formik.getFieldProps("discount")}
extra="!px-2 max-md:!py-1.5 md:!py-1 disabled:!bg-gray-300" />
onClick={() => { <Button
if (formik.values.count > 1) { extra="md:!py-1 disabled:!bg-gray-300"
chnageCountHandler("dec"); onClick={discountHandler}
} disabled={formik.values.discount === ""}
}} >
disabled={formik.values.count === 1} اعمال
> </Button>
<BiMinus /> </div>
</Button> <div className="w-2/3 h-full flex justify-center items-center gap-1">
<Input <Button
type="text" extra="!px-2 max-md:!py-1.5 md:!py-1 disabled:!bg-gray-300"
extra="max-md:py-0 !p-1 !text-center" onClick={() => {
{...formik.getFieldProps("count")} if (formik.values.count > 1) {
/> chnageCountHandler("dec");
<Button }
extra="!px-2 max-md:!py-1.5 md:!py-1 disabled:!bg-gray-300" }}
onClick={() => { disabled={formik.values.count === 1}
if ( >
formik.values.count.toString() < <BiMinus />
data?.data?.result?.max_config </Button>
) <Input
chnageCountHandler("inc"); type="text"
}} extra="max-md:py-0 !p-1 !text-center"
disabled={ {...formik.getFieldProps("count")}
formik.values.count.toString() === />
data?.data?.result?.max_config <Button
} extra="!px-2 max-md:!py-1.5 md:!py-1 disabled:!bg-gray-300"
> onClick={() => {
<BiPlus /> if (
</Button> formik.values.count.toString() <
</div> data?.data?.result?.max_config
</form> )
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 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"> <div className="w-full h-full bg-gray-900/50 rounded-md shadow flex justify-between items-center p-3">
<p>حجم</p> <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>
<div className="w-full h-full bg-gray-900/50 rounded-md shadow flex justify-between items-center p-3"> <div className="w-full h-full bg-gray-900/50 rounded-md shadow flex justify-between items-center p-3">
<p>محدودیت کاربر</p> <p>محدودیت کاربر</p>

View File

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

View File

@@ -90,7 +90,12 @@ const Learn = ({ activeTutorial }: LearnProps) => {
{/* Render learning items */} {/* Render learning items */}
{data?.data?.result?.learning.map( {data?.data?.result?.learning.map(
(i: { id: string; title: string; medias: string[] }) => ( (i: {
id: string;
title: string;
medias: string[];
url_file: string;
}) => (
<div <div
key={i.id} key={i.id}
className="relative w-full h-full flex flex-col justify-center items-center" className="relative w-full h-full flex flex-col justify-center items-center"
@@ -125,6 +130,14 @@ const Learn = ({ activeTutorial }: LearnProps) => {
); );
})} })}
</div> </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> </div>
) )
)} )}

View File

@@ -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<boolean>) => {
state.isPaymentGateway = action.payload;
},
},
});
export const { setIsPaymentGateway } = isPaymentGatewaySlice.actions;
export default isPaymentGatewaySlice.reducer;

View File

@@ -16,6 +16,7 @@ import {
import tokenReducer from "./slices/token"; import tokenReducer from "./slices/token";
import configId from "./slices/configId"; import configId from "./slices/configId";
import categoryId from "./slices/categoryId"; import categoryId from "./slices/categoryId";
import isPaymentGateway from "./slices/isPaymentGateway";
// Encryption settings // Encryption settings
const secretKey = "token-encrypt-api"; const secretKey = "token-encrypt-api";
@@ -47,6 +48,7 @@ const store = configureStore({
token: persistedTokenReducer, token: persistedTokenReducer,
configIdState: configId, configIdState: configId,
categoryIdState: categoryId, categoryIdState: categoryId,
isPaymentGatewayState: isPaymentGateway,
}, },
middleware: (getDefaultMiddleware) => middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({ getDefaultMiddleware({

View File

@@ -1,8 +1,8 @@
const router = [ const router = [
{ id: 1, name: "فروشگاه", path: "/" }, { id: 1, name: "فروشگاه", path: "/" },
{ id: 2, name: "آموزش", path: "tutorial" }, { id: 2, name: "آموزش", path: "/tutorial" },
{ id: 3, name: "قوانین و مقررات", path: "rule" }, { id: 3, name: "قوانین و مقررات", path: "/rule" },
{ id: 4, name: "درباره ما", path: "about" }, { id: 4, name: "درباره ما", path: "/about" },
]; ];
export default router; export default router;

View File

@@ -119,15 +119,15 @@ export interface MuiModalProps {
} }
export interface ConfigItemProps { export interface ConfigItemProps {
id: string;
dateBuy: string; dateBuy: string;
configName: string; configName: string;
isDisabled: boolean; isDisabled: boolean;
isShowTraffic: boolean; isShowTraffic: boolean;
textCopy: string; textCopy: string;
maxTraffic: number | "unlimited";
traffic: number;
type: string; type: string;
categoryId: number; categoryId: number;
useMaxTraffic: boolean;
} }
// نوع Item برای آیتم‌های داخل Dropdown // نوع Item برای آیتم‌های داخل Dropdown
@@ -203,6 +203,8 @@ type Config = {
traffic: number; traffic: number;
type: string; type: string;
category_id: number; category_id: number;
is_expired: boolean;
use_max_traffic: boolean;
}; };
// تعریف تایپ داده‌های برگشتی // تعریف تایپ داده‌های برگشتی
@@ -215,6 +217,7 @@ type ProfileResponseData = {
}; };
status: boolean; status: boolean;
alert: string; alert: string;
"";
}; };
// تایپ خطا // تایپ خطا