make routes dynamic and some fixes

This commit is contained in:
Moaz Dawalibi 2024-10-22 10:10:16 +03:00
parent 2bd688097b
commit 9ce29bc333
16 changed files with 5022 additions and 48 deletions

4842
bundle-analysis.html Normal file

File diff suppressed because one or more lines are too long

View File

@ -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":""
} }
} }

View File

@ -4,9 +4,9 @@
<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" />
<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
View File

@ -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": {}
} }
} }
} }

View File

@ -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",

View File

@ -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>
); );

View File

@ -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;

View File

@ -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;

View File

@ -6,4 +6,5 @@ export enum RoutesEnums {
NOTE = '/#note', NOTE = '/#note',
CONTACT = '/#contact_us', CONTACT = '/#contact_us',
PRIVACY = '/privacy', PRIVACY = '/privacy',
DOWNLOAD = '/download',
} }

View 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

View 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 })),
}));

View File

@ -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;

View File

@ -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
View File

@ -0,0 +1,5 @@
export interface RouteConfig {
path: string;
Component: React.LazyExoticComponent<React.FC> | React.FC;
withLayout: boolean;
}

View 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';
}
};

View 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
};