make routes dynamic and some fixes
This commit is contained in:
parent
2bd688097b
commit
9ce29bc333
4842
bundle-analysis.html
Normal file
4842
bundle-analysis.html
Normal file
File diff suppressed because one or more lines are too long
11
data.json
11
data.json
|
|
@ -6,7 +6,8 @@
|
||||||
"link4": "لقطة الشاشة",
|
"link4": "لقطة الشاشة",
|
||||||
"link5": "ملاحظة",
|
"link5": "ملاحظة",
|
||||||
"link6": "اتصل بنا",
|
"link6": "اتصل بنا",
|
||||||
"link7":"الخصوصية"
|
"link7":"الخصوصية",
|
||||||
|
"link8":"تحميل"
|
||||||
},
|
},
|
||||||
"Home": {
|
"Home": {
|
||||||
"title": "احصل على تنزيل مجاني لتطبيق",
|
"title": "احصل على تنزيل مجاني لتطبيق",
|
||||||
|
|
@ -183,8 +184,8 @@
|
||||||
"privacy": "© زاكر 2024.جميع الحقوق محفوظة"
|
"privacy": "© زاكر 2024.جميع الحقوق محفوظة"
|
||||||
},
|
},
|
||||||
"Links": {
|
"Links": {
|
||||||
"google_play_link": "/",
|
"google_play_link": "https://play.google.com/store",
|
||||||
"apple_store_link": "/",
|
"apple_store_link": "https://apps.apple.com",
|
||||||
"facebook": "/",
|
"facebook": "/",
|
||||||
"telegram": "/",
|
"telegram": "/",
|
||||||
"instagram": "/",
|
"instagram": "/",
|
||||||
|
|
@ -205,5 +206,9 @@
|
||||||
"NotFound": {
|
"NotFound": {
|
||||||
"title":"عذرا الصفخة غير موجودة",
|
"title":"عذرا الصفخة غير موجودة",
|
||||||
"description":"ارجع للصفحة الرئيسية"
|
"description":"ارجع للصفحة الرئيسية"
|
||||||
|
},
|
||||||
|
"Download": {
|
||||||
|
"title":"",
|
||||||
|
"description":""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<link rel="manifest" href="/site.webmanifest" />
|
<link rel="manifest" href="/site.webmanifest" />
|
||||||
<link rel="icon" type="image/webp" href="/Setting/LOGO.png" />
|
<link rel="icon" type="image/webp" href="/Setting/LOGO.png" />
|
||||||
<meta name="description" content=" description of your web app" />
|
<meta name="description" content=" description of your web app" />
|
||||||
<title>Website</title>
|
<title>Zaker</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script type="module" src="/src/main.tsx"></script>
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
|
|
||||||
37
package-lock.json
generated
37
package-lock.json
generated
|
|
@ -16,7 +16,8 @@
|
||||||
"react-icons": "^5.3.0",
|
"react-icons": "^5.3.0",
|
||||||
"react-player": "^2.16.0",
|
"react-player": "^2.16.0",
|
||||||
"react-router-dom": "^6.27.0",
|
"react-router-dom": "^6.27.0",
|
||||||
"swiper": "^11.1.14"
|
"swiper": "^11.1.14",
|
||||||
|
"zustand": "^5.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.5.1",
|
"@types/node": "^22.5.1",
|
||||||
|
|
@ -4810,6 +4811,34 @@
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"node_modules/zustand": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-LE+VcmbartOPM+auOjCCLQOsQ05zUTp8RkgwRzefUk+2jISdMMFnxvyTjA4YNWr5ZGXYbVsEMZosttuxUBkojQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.20.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": ">=18.0.0",
|
||||||
|
"immer": ">=9.0.6",
|
||||||
|
"react": ">=18.0.0",
|
||||||
|
"use-sync-external-store": ">=1.2.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"immer": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"use-sync-external-store": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -7978,6 +8007,12 @@
|
||||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
|
},
|
||||||
|
"zustand": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-LE+VcmbartOPM+auOjCCLQOsQ05zUTp8RkgwRzefUk+2jISdMMFnxvyTjA4YNWr5ZGXYbVsEMZosttuxUBkojQ==",
|
||||||
|
"requires": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,8 @@
|
||||||
"react-icons": "^5.3.0",
|
"react-icons": "^5.3.0",
|
||||||
"react-player": "^2.16.0",
|
"react-player": "^2.16.0",
|
||||||
"react-router-dom": "^6.27.0",
|
"react-router-dom": "^6.27.0",
|
||||||
"swiper": "^11.1.14"
|
"swiper": "^11.1.14",
|
||||||
|
"zustand": "^5.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.5.1",
|
"@types/node": "^22.5.1",
|
||||||
|
|
|
||||||
38
src/App.tsx
38
src/App.tsx
|
|
@ -1,44 +1,32 @@
|
||||||
|
import './styles/App/index.scss';
|
||||||
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
|
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
|
||||||
import { lazy, Suspense } from 'react';
|
import { Suspense } from 'react';
|
||||||
import { Spin } from 'antd';
|
import { Spin } from 'antd';
|
||||||
import Layout from './components/layout/Layout';
|
import Layout from './components/layout/Layout';
|
||||||
import './styles/App/index.scss';
|
import { routes } from './Routes';
|
||||||
const PrivacyPage = lazy(() => import("./pages/Privacy/Page"));
|
|
||||||
const Page = lazy(() => import("./pages/Main/Page"));
|
|
||||||
const NotFoundPage = lazy(() => import("./pages/NotFound/NotFound"));
|
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Router>
|
<Router>
|
||||||
<Routes>
|
<Routes>
|
||||||
|
{routes.map((route:any) => (
|
||||||
<Route
|
<Route
|
||||||
path="/"
|
key={route.path}
|
||||||
|
path={route.path}
|
||||||
element={
|
element={
|
||||||
<Suspense fallback={<Spin />}>
|
<Suspense fallback={<Spin />}>
|
||||||
|
{route.withLayout ? (
|
||||||
<Layout>
|
<Layout>
|
||||||
<Page />
|
<route.Component />
|
||||||
</Layout>
|
</Layout>
|
||||||
|
) : (
|
||||||
|
<route.Component />
|
||||||
|
)}
|
||||||
</Suspense>
|
</Suspense>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Route
|
))}
|
||||||
path="/privacy"
|
|
||||||
element={
|
|
||||||
<Suspense fallback={<Spin />}>
|
|
||||||
<Layout>
|
|
||||||
<PrivacyPage />
|
|
||||||
</Layout>
|
|
||||||
</Suspense>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
path="*"
|
|
||||||
element={
|
|
||||||
<Suspense fallback={<Spin />}>
|
|
||||||
<NotFoundPage/>
|
|
||||||
</Suspense>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Routes>
|
</Routes>
|
||||||
</Router>
|
</Router>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,31 @@
|
||||||
import './styles/App/index.scss';
|
import { lazy } from 'react';
|
||||||
import HomePage from './pages/HomePage';
|
import { RouteConfig } from './types/RoutesType';
|
||||||
|
|
||||||
const Routes = () => {
|
const DownloadPage = lazy(() => import("./pages/Download/Download"));
|
||||||
return <HomePage />;
|
const PrivacyPage = lazy(() => import("./pages/Privacy/Page"));
|
||||||
};
|
const Page = lazy(() => import("./pages/Main/Page"));
|
||||||
|
const NotFoundPage = lazy(() => import("./pages/NotFound/NotFound"));
|
||||||
|
|
||||||
|
export const routes: RouteConfig[] = [
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
Component: Page,
|
||||||
|
withLayout: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/privacy',
|
||||||
|
Component: PrivacyPage,
|
||||||
|
withLayout: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/download',
|
||||||
|
Component: DownloadPage,
|
||||||
|
withLayout: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '*',
|
||||||
|
Component: NotFoundPage,
|
||||||
|
withLayout: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
export default Routes;
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ const NavBar: React.FC = () => {
|
||||||
{ path: RoutesEnums.NOTE, label: navBarData.link5 },
|
{ path: RoutesEnums.NOTE, label: navBarData.link5 },
|
||||||
{ path: RoutesEnums.CONTACT, label: navBarData.link6 },
|
{ path: RoutesEnums.CONTACT, label: navBarData.link6 },
|
||||||
{ path: RoutesEnums.PRIVACY, label: navBarData.link7 },
|
{ path: RoutesEnums.PRIVACY, label: navBarData.link7 },
|
||||||
|
{ path: RoutesEnums.DOWNLOAD, label: navBarData.link8 },
|
||||||
];
|
];
|
||||||
const [Open, setOpen] = useState(false);
|
const [Open, setOpen] = useState(false);
|
||||||
const handleToggle = () => {
|
const handleToggle = () => {
|
||||||
|
|
@ -57,7 +58,6 @@ const NavBar: React.FC = () => {
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
setActive(link.path);
|
setActive(link.path);
|
||||||
};
|
};
|
||||||
console.log(link);
|
|
||||||
|
|
||||||
const isActive =
|
const isActive =
|
||||||
Active === '' && link.path === '/#' ? true : Active === link.path;
|
Active === '' && link.path === '/#' ? true : Active === link.path;
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,5 @@ export enum RoutesEnums {
|
||||||
NOTE = '/#note',
|
NOTE = '/#note',
|
||||||
CONTACT = '/#contact_us',
|
CONTACT = '/#contact_us',
|
||||||
PRIVACY = '/privacy',
|
PRIVACY = '/privacy',
|
||||||
|
DOWNLOAD = '/download',
|
||||||
}
|
}
|
||||||
|
|
|
||||||
34
src/pages/Download/Download.tsx
Normal file
34
src/pages/Download/Download.tsx
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import { useDetectDeviceType } from '../../states/DeviceTypeState';
|
||||||
|
import DownloadPage from '../DownloadPage'
|
||||||
|
import { detectDeviceType } from '../../utils/DetectDeviceType';
|
||||||
|
import { Spin } from 'antd';
|
||||||
|
import Layout from '../../components/layout/Layout';
|
||||||
|
import { ExternalRedirect } from '../../utils/ExternalRedirect';
|
||||||
|
|
||||||
|
const Download = () => {
|
||||||
|
const { DeviceType, setDeviceType }: any = useDetectDeviceType();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setDeviceType(detectDeviceType());
|
||||||
|
}, [setDeviceType]);
|
||||||
|
|
||||||
|
if (!DeviceType) {
|
||||||
|
return <Spin />;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className='Download'>
|
||||||
|
{
|
||||||
|
DeviceType === 'desktop' ? (
|
||||||
|
<Layout>
|
||||||
|
<DownloadPage />
|
||||||
|
</Layout>
|
||||||
|
) : (
|
||||||
|
<ExternalRedirect url={DeviceType === 'ios' ? 'https://apps.apple.com' : 'https://play.google.com/store'} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Download
|
||||||
13
src/states/DeviceTypeState.ts
Normal file
13
src/states/DeviceTypeState.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { create } from 'zustand';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
interface ModalState {
|
||||||
|
DeviceType: string;
|
||||||
|
setDeviceType: (value: string) => void;
|
||||||
|
}
|
||||||
|
export const useDetectDeviceType = create<ModalState>((set) => ({
|
||||||
|
DeviceType: "",
|
||||||
|
setDeviceType: (value: string) => set(() => ({ DeviceType: value })),
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
outline: none;
|
outline: none;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
padding: 3vw 1vw;
|
padding: 35px 15px;
|
||||||
background: var(--secondary);
|
background: var(--secondary);
|
||||||
color: var(--white);
|
color: var(--white);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
> img {
|
> img {
|
||||||
width: 600px;
|
width: 600px;
|
||||||
|
height: 500px;
|
||||||
}
|
}
|
||||||
> span {
|
> span {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -96,6 +97,7 @@
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
> img {
|
> img {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
|
height: 250px;
|
||||||
order: 0;
|
order: 0;
|
||||||
}
|
}
|
||||||
> span {
|
> span {
|
||||||
|
|
|
||||||
5
src/types/RoutesType.ts
Normal file
5
src/types/RoutesType.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
export interface RouteConfig {
|
||||||
|
path: string;
|
||||||
|
Component: React.LazyExoticComponent<React.FC> | React.FC;
|
||||||
|
withLayout: boolean;
|
||||||
|
}
|
||||||
16
src/utils/DetectDeviceType.ts
Normal file
16
src/utils/DetectDeviceType.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
export const detectDeviceType = () => {
|
||||||
|
const ua = navigator.userAgent;
|
||||||
|
|
||||||
|
// Check if it's an iOS device
|
||||||
|
const isIOS = /iPad|iPhone|iPod/.test(ua) && !(window as any).MSStream;
|
||||||
|
|
||||||
|
if (/android/i.test(ua)) {
|
||||||
|
return 'android';
|
||||||
|
} else if (isIOS) {
|
||||||
|
return 'ios';
|
||||||
|
} else {
|
||||||
|
return 'desktop';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
9
src/utils/ExternalRedirect.ts
Normal file
9
src/utils/ExternalRedirect.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
|
export const ExternalRedirect = ({ url }: { url: string }) => {
|
||||||
|
useEffect(() => {
|
||||||
|
window.location.href = url;
|
||||||
|
}, [url]);
|
||||||
|
|
||||||
|
return null; // This component renders nothing
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user