done
12
.eslintrc.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
module.exports = {
|
||||
// ...
|
||||
rules: {
|
||||
quotes: ["error", "single"],
|
||||
// we want to force semicolons
|
||||
semi: ["error", "always"],
|
||||
// we use 2 spaces to indent our code
|
||||
indent: ["error", 2],
|
||||
// we want to avoid extraneous spaces
|
||||
"no-multi-spaces": ["error"],
|
||||
},
|
||||
};
|
||||
20
.eslintrc.json
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es2021": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:react-hooks/recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 12,
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
}
|
||||
},
|
||||
"plugins": ["react", "react-hooks"],
|
||||
"rules": {}
|
||||
}
|
||||
24
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
pnpm-lock.yaml
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
package-lock.json
|
||||
20
.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"cSpell.words": [
|
||||
"aldeen",
|
||||
"antd",
|
||||
"Datepicker",
|
||||
"formik",
|
||||
"Karim",
|
||||
"queryqlent",
|
||||
"szhsin",
|
||||
"Viewelement",
|
||||
"zustand"
|
||||
],
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnPaste": false,
|
||||
"prettier.useTabs": false,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
},
|
||||
"eslint.validate": ["javascript"]
|
||||
}
|
||||
60
README.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
### Directory Descriptions:
|
||||
|
||||
- **public/**: Contains static assets like HTML files and images.
|
||||
- **src/**: The main source code directory.
|
||||
|
||||
- **assets/**: Static assets like images, fonts, etc.
|
||||
- **components/**: Reusable UI components.
|
||||
- **types/**: TypeScript type definitions.
|
||||
- **enums/**: Enumerations or constants.
|
||||
- **pages/**: Components representing different pages.
|
||||
- **hooks/**: Custom React hooks.
|
||||
- **lib/**: Utility functions or helper modules.
|
||||
- **Redux/**: Redux-related code (actions, reducers, etc.) if used.
|
||||
- **styles/**: Global styles or shared styles.
|
||||
- **translate/**: Files related to localization and translation.
|
||||
- **layout/**: Components or files related to the overall layout structure.
|
||||
- **Layout.js**: Example layout component.
|
||||
- **Routes.tsx**: File for defining your application routes.
|
||||
- **App.js**: The main component and entry point.
|
||||
- **index.js**: Entry point for rendering the React app.
|
||||
|
||||
- **.gitignore**: Specifies files or directories to be ignored by version control.
|
||||
- **package.json**: Metadata about the project, dependencies, and scripts.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Node.js and npm installed
|
||||
- v20.10.0
|
||||
|
||||
### Installation
|
||||
|
||||
1. Clone the repository:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/KarimAldeen/Start-React-ts.git
|
||||
```
|
||||
|
||||
```bash
|
||||
cd Start-React-ts
|
||||
```
|
||||
|
||||
2. Install dependencies:
|
||||
|
||||
```bash
|
||||
pnpm i
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
Start the development server:
|
||||
|
||||
```bash
|
||||
|
||||
pnpm start
|
||||
|
||||
```
|
||||
|
||||
# ecommerce_dm
|
||||
110
db.json
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
{
|
||||
"example": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "ibrahim",
|
||||
"email": "ibrahim@gmail.com"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "gregr",
|
||||
"email": "ibrahimgmail.com"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "mhmad",
|
||||
"email": "mhmad@gmial.com"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "soso",
|
||||
"email": "soso@gmail.com"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "few",
|
||||
"email": "jfpwrej"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "sos",
|
||||
"email": "fdwf"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "sos",
|
||||
"email": "fdwf"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "sos",
|
||||
"email": "fdwf"
|
||||
}
|
||||
],
|
||||
"test2": [
|
||||
{
|
||||
"id": 1,
|
||||
"email": "admin@adamin.com"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"email": "admin@adamin.com"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"email": "admin@adamin.com"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"email": "admin@adamin.com"
|
||||
}
|
||||
],
|
||||
"users": [
|
||||
{
|
||||
"id": 1,
|
||||
"email": "admin@adamin.com",
|
||||
"password": "password",
|
||||
"token": "token"
|
||||
}
|
||||
],
|
||||
"activities": [
|
||||
{
|
||||
"id": 1,
|
||||
"image": "/public/Activities/data-display/Rectangle 103.png",
|
||||
"title": "nunc id cursus metus aliquam eleifend mi",
|
||||
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ultrices tincidunt arcu non sodales neque sodales ut etiam sit.",
|
||||
"location": "Consectetur adipiscing elit, sed do",
|
||||
"time": "25 JAN 2024 - 30 JAN 2024"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"image": "/public/Activities/data-display/Rectangle 103.png",
|
||||
"title": "nunc id cursus metus aliquam eleifend mi",
|
||||
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ultrices tincidunt arcu non sodales neque sodales ut etiam sit.",
|
||||
"location": "Consectetur adipiscing elit, sed do",
|
||||
"time": "25 JAN 2024 - 30 JAN 2024"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"image": "/public/Activities/data-display/Rectangle 103.png",
|
||||
"title": "nunc id cursus metus aliquam eleifend mi",
|
||||
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ultrices tincidunt arcu non sodales neque sodales ut etiam sit.",
|
||||
"location": "Consectetur adipiscing elit, sed do",
|
||||
"time": "25 JAN 2024 - 30 JAN 2024"
|
||||
}
|
||||
],
|
||||
"activities/popular": [
|
||||
{
|
||||
"first": "25 JAN 2024",
|
||||
"second": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
|
||||
},
|
||||
{
|
||||
"first": "25 JAN 2024",
|
||||
"second": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
|
||||
},
|
||||
{
|
||||
"first": "25 JAN 2024",
|
||||
"second": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
|
||||
}
|
||||
]
|
||||
}
|
||||
12
eslint.config.mjs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import globals from "globals";
|
||||
import pluginJs from "@eslint/js";
|
||||
import tseslint from "typescript-eslint";
|
||||
import pluginReactConfig from "eslint-plugin-react/configs/recommended.js";
|
||||
import { fixupConfigRules } from "@eslint/compat";
|
||||
|
||||
export default [
|
||||
{ languageOptions: { globals: globals.browser } },
|
||||
pluginJs.configs.recommended,
|
||||
...tseslint.configs.recommended,
|
||||
...fixupConfigRules(pluginReactConfig),
|
||||
];
|
||||
36
index.html
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<link rel="android-chrome" href="./App/Logo.svg" />
|
||||
<link rel="android-chrome" href="./App/Logo.svg" />
|
||||
<link rel="canonical" href="https://karimalden.vercel.app/" />
|
||||
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="./App/Logo.svg" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="./App/Logo.svg" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="./App/Logo.svg" />
|
||||
<link rel="manifest" href="./site.webmanifest" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Landing Page About My Work and Includ My Cv As Front End Developer Use Reactjs In Syria"
|
||||
/>
|
||||
|
||||
<meta property="og:title" content="My LandingPage" />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="Landing Page About My Work and Includ My Cv As Front End Developer Use Reactjs In Syria"
|
||||
/>
|
||||
<meta property="og:image" content="./App/Logo.svg" />
|
||||
<meta property="og:url" content="https://karimalden.vercel.app" />
|
||||
<meta property="og:type" content="website" />
|
||||
<script type="module" src="/src/index.tsx"></script>
|
||||
|
||||
<title>React-Start-App</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
87
package.json
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
{
|
||||
"name": "my-app",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "^5.3.7",
|
||||
"@reduxjs/toolkit": "^2.2.5",
|
||||
"@types/node": "^16.18.98",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/react-helmet": "^6.1.11",
|
||||
"antd": "^5.18.0",
|
||||
"axios": "^1.7.2",
|
||||
"bootstrap": "^5.3.3",
|
||||
"chart.js": "^4.4.3",
|
||||
"dayjs": "^1.11.11",
|
||||
"firebase": "^10.12.2",
|
||||
"formik": "^2.4.6",
|
||||
"i18next": "^23.11.5",
|
||||
"json-server": "^0.17.4",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"prettier": "^3.3.1",
|
||||
"react": "^18.3.1",
|
||||
"react-bootstrap": "^2.10.2",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-i18next": "^13.5.0",
|
||||
"react-icons": "^4.12.0",
|
||||
"react-player": "^2.16.0",
|
||||
"react-query": "^3.39.3",
|
||||
"react-redux": "^9.1.2",
|
||||
"react-router-dom": "^6.23.1",
|
||||
"react-toastify": "^10.0.5",
|
||||
"reactstrap": "^9.2.2",
|
||||
"sass": "^1.77.4",
|
||||
"socket.io-client": "^4.7.5",
|
||||
"swiper": "^11.1.4",
|
||||
"typescript": "^4.9.5",
|
||||
"yup": "^1.4.0",
|
||||
"zustand": "^4.5.2"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "vite --port=3000",
|
||||
"build": "vite build",
|
||||
"format": "prettier --write .",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject",
|
||||
"g:api": "node src/Extensions/FileGenerator/generateApi.js",
|
||||
"g:column": "node src/Extensions/FileGenerator/generateColumn.js",
|
||||
"g:formutil": "node src/Extensions/FileGenerator/generateformUtils.js",
|
||||
"g:page": "node src/Extensions/FileGenerator/generatePage.js",
|
||||
"g:dashboard": "node src/Extensions/FileGenerator/generateDashboard.js ",
|
||||
"g:modal:add": "node src/Extensions/FileGenerator/generateEditModal.js ",
|
||||
"g:model:edit": "node src/Extensions/FileGenerator/generateEditModal.js "
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/compat": "^1.0.3",
|
||||
"@eslint/js": "^9.4.0",
|
||||
"@types/lodash": "^4.17.4",
|
||||
"@vitejs/plugin-react": "^4.3.0",
|
||||
"eslint": "^9.4.0",
|
||||
"eslint-plugin-react": "^7.34.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"globals": "^15.3.0",
|
||||
"typescript-eslint": "^7.12.0",
|
||||
"vite": "^5.2.12"
|
||||
}
|
||||
}
|
||||
BIN
public/About/AboutUS.png
Normal file
|
After Width: | Height: | Size: 640 KiB |
BIN
public/About/Hands.png
Normal file
|
After Width: | Height: | Size: 430 KiB |
BIN
public/About/Laptop.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
public/About/Media.png
Normal file
|
After Width: | Height: | Size: 790 KiB |
4
public/About/line.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="1085" height="2453" viewBox="0 0 1085 2453" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M834 66.7636C789.104 36.4148 653.663 -22.7961 536.215 11.2354C398.097 51.2557 379.485 137.299 183.084 152.307C5.46983 165.879 -38.9711 362.12 35.6606 440.954C92.9647 501.485 114 500 140.473 532" stroke="#E88917" stroke-width="2" stroke-dasharray="8 8"/>
|
||||
<path d="M146 536C219 594 847.141 563.856 883.134 693.454C919.127 823.052 704.168 883.752 594.689 925.715C406.725 964.262 61.1909 1064.49 90.7852 1311.19C120.38 1557.89 610.019 1648.85 851.14 1663.48C953.12 1682.51 1102.59 1793.76 1082.1 2048.47C1065.04 2260.38 996.779 2225.27 693.67 2310.98C670.341 2322.7 546.198 2359.49 574.193 2452" stroke="#E88917" stroke-width="2" stroke-dasharray="8 8"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 771 B |
BIN
public/Activities/data-display/2 25.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
public/Activities/data-display/Rectangle 103.png
Normal file
|
After Width: | Height: | Size: 456 KiB |
1
public/Activities/iconsSearch.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="50px" height="50px"><path d="M 21 3 C 11.621094 3 4 10.621094 4 20 C 4 29.378906 11.621094 37 21 37 C 24.710938 37 28.140625 35.804688 30.9375 33.78125 L 44.09375 46.90625 L 46.90625 44.09375 L 33.90625 31.0625 C 36.460938 28.085938 38 24.222656 38 20 C 38 10.621094 30.378906 3 21 3 Z M 21 5 C 29.296875 5 36 11.703125 36 20 C 36 28.296875 29.296875 35 21 35 C 12.703125 35 6 28.296875 6 20 C 6 11.703125 12.703125 5 21 5 Z"/></svg>
|
||||
|
After Width: | Height: | Size: 501 B |
BIN
public/Activities/main.png
Normal file
|
After Width: | Height: | Size: 363 KiB |
BIN
public/Activities/mediaIcons/Group.png
Normal file
|
After Width: | Height: | Size: 729 B |
BIN
public/Activities/mediaIcons/insta.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
public/Activities/mediaIcons/teleg.png
Normal file
|
After Width: | Height: | Size: 951 B |
BIN
public/Activities/mediaIcons/whats.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
1
public/App/Ar.svg
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
public/App/Logo.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
11
public/App/Logo.svg
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<svg width="72" height="34" viewBox="0 0 72 34" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_2001_4350)">
|
||||
<path d="M34.9514 12.9924C34.4047 16.0388 33.9491 18.929 33.116 21.6629C31.3456 27.5058 27.9089 31.2239 22.7931 32.6143C21.1138 33.0674 19.4215 33.2236 17.7032 33.2236C12.0406 33.2236 6.37794 33.2236 0.71531 33.2392C0.181591 33.2392 -0.0136719 33.1455 -0.0136719 32.4112C0.0123632 26.2091 0.0123632 20.0226 -0.0136719 13.8204C-0.0136719 13.2268 0.103486 13.0393 0.624188 13.0393C2.99338 13.0706 5.34955 13.0706 7.71875 13.0393C8.23945 13.0393 8.40868 13.1643 8.40868 13.8361C8.36962 17.273 8.40868 20.71 8.38264 24.1469C8.38264 24.7562 8.4998 24.9437 9.03352 24.928C12.0276 24.8968 15.0216 24.9437 18.0156 24.8968C20.3848 24.8656 22.5978 24.2407 24.3812 22.1785C25.3835 21.038 25.7871 19.5539 26.1646 18.0229C27.2451 13.5705 28.3255 9.10244 29.432 4.65003C30.3042 1.18183 32.9598 -0.521025 35.7715 0.556928C37.0863 1.05685 37.9715 2.18167 38.6094 3.57207C41.4862 9.75858 44.5454 15.8201 47.1879 22.1629C47.227 22.2566 47.266 22.3347 47.3571 22.5066C47.6045 21.8973 47.8128 21.3505 48.0471 20.8037C50.6246 14.9453 53.3973 9.2118 56.131 3.46271C57.667 0.244478 60.6871 -0.661628 63.1865 1.19745C64.2539 1.9942 64.8788 3.18151 65.2172 4.58753C66.9616 11.8051 68.6799 19.0071 70.4112 26.2247C70.9189 28.3337 71.4136 30.4428 71.9343 32.5362C72.0514 33.0205 72.0775 33.2392 71.5307 33.2392C69.1225 33.1923 66.7142 33.208 64.306 33.2392C63.8894 33.2392 63.7462 33.0517 63.6551 32.6299C62.3794 26.5997 60.8694 20.6475 59.6848 14.6016C59.5936 14.1329 59.5155 13.6642 59.3984 13.0237C59.1771 13.5236 59.0209 13.8673 58.8777 14.2266C56.6907 19.7101 54.2434 25.0218 51.8742 30.3803C50.4293 33.6454 48.3204 34.2703 45.1962 33.3954C44.0897 33.083 43.3347 32.0675 42.814 30.9115C41.33 27.6776 39.8721 24.4125 38.4401 21.1318C37.3206 18.5384 36.11 16.0076 35.1337 13.3205C35.0816 13.258 35.0556 13.1955 34.9514 12.9924Z" fill="red"/>
|
||||
<path d="M24.1476 11.8056C22.0778 9.71216 19.6825 9.16537 17.1051 9.181C11.4685 9.22786 5.83188 9.19662 0.078125 9.19662C0.559774 8.43112 0.989353 7.74373 1.41893 7.05634C2.62956 5.13477 3.85321 3.2132 5.05082 1.27601C5.24609 0.963559 5.44135 0.791711 5.79282 0.807334C10.5182 0.869824 15.2436 0.682354 19.9689 0.932314C22.0387 1.04167 24.0434 1.63533 25.983 2.57268C26.3605 2.76015 26.3345 2.94762 26.2434 3.32256C25.5404 6.11899 24.8635 8.89979 24.1476 11.8056Z" fill="#AFB0B6"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_2001_4350">
|
||||
<rect width="72" height="33.5103" fill="white" transform="translate(0 0.244873)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
BIN
public/Cart/CartProduct.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
public/Contact/ContactImage.png
Normal file
|
After Width: | Height: | Size: 330 KiB |
BIN
public/Faqs/FaqsImage.png
Normal file
|
After Width: | Height: | Size: 818 KiB |
BIN
public/Home/BatteryLife.png
Normal file
|
After Width: | Height: | Size: 435 KiB |
BIN
public/Home/Bose_Headphones.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
public/Home/HeadPhone.png
Normal file
|
After Width: | Height: | Size: 823 KiB |
BIN
public/Home/HeroSection.png
Normal file
|
After Width: | Height: | Size: 2.3 MiB |
BIN
public/Home/HeroShape.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
3
public/Home/HeroShape.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="500" height="695" viewBox="0 0 500 695" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M500 -24H220V-23.9353C194.171 -23.7928 168.277 -10.9011 153.712 17.4919L8.37793 300.812C-2.79264 322.588 -2.79264 348.412 8.37792 370.188L153.712 653.508C168.277 681.901 194.171 694.793 220 694.935V695H500V-24Z" fill="red"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 381 B |
BIN
public/Home/Noise_Cancellation.png
Normal file
|
After Width: | Height: | Size: 950 KiB |
28
public/Home/Noise_Cancellation.svg
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
public/Home/PerfectSound.png
Normal file
|
After Width: | Height: | Size: 528 KiB |
BIN
public/Home/big_transparent_leaf.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/Home/leaf.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
public/Home/p1.png
Normal file
|
After Width: | Height: | Size: 214 KiB |
BIN
public/Home/partner1.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/Home/partner2.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
public/Home/slider-shape.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
public/Home/small_transparent_leaf.png
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
1
public/Layout/Ar.svg
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
public/Layout/Ch.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/Layout/EmptyOrder.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
1
public/Layout/En.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="42.67" height="32" viewBox="0 0 640 480"><defs><clipPath id="flagUm4x30"><path fill-opacity=".7" d="M0 0h682.7v512H0z"/></clipPath></defs><g fill-rule="evenodd" clip-path="url(#flagUm4x30)" transform="scale(.9375)"><g stroke-width="1pt"><path fill="#bd3d44" d="M0 0h972.8v39.4H0zm0 78.8h972.8v39.4H0zm0 78.7h972.8V197H0zm0 78.8h972.8v39.4H0zm0 78.8h972.8v39.4H0zm0 78.7h972.8v39.4H0zm0 78.8h972.8V512H0z"/><path fill="#fff" d="M0 39.4h972.8v39.4H0zm0 78.8h972.8v39.3H0zm0 78.7h972.8v39.4H0zm0 78.8h972.8v39.4H0zm0 78.8h972.8v39.4H0zm0 78.7h972.8v39.4H0z"/></g><path fill="#192f5d" d="M0 0h389.1v275.7H0z"/><path fill="#fff" d="M32.4 11.8L36 22.7h11.4l-9.2 6.7l3.5 11l-9.3-6.8l-9.2 6.7l3.5-10.9l-9.3-6.7H29zm64.9 0l3.5 10.9h11.5l-9.3 6.7l3.5 11l-9.2-6.8l-9.3 6.7l3.5-10.9l-9.2-6.7h11.4zm64.8 0l3.6 10.9H177l-9.2 6.7l3.5 11l-9.3-6.8l-9.2 6.7l3.5-10.9l-9.3-6.7h11.5zm64.9 0l3.5 10.9H242l-9.3 6.7l3.6 11l-9.3-6.8l-9.3 6.7l3.6-10.9l-9.3-6.7h11.4zm64.8 0l3.6 10.9h11.4l-9.2 6.7l3.5 11l-9.3-6.8l-9.2 6.7l3.5-10.9l-9.2-6.7h11.4zm64.9 0l3.5 10.9h11.5l-9.3 6.7l3.6 11l-9.3-6.8l-9.3 6.7l3.6-10.9l-9.3-6.7h11.5zM64.9 39.4l3.5 10.9h11.5L70.6 57L74 67.9l-9-6.7l-9.3 6.7L59 57l-9-6.7h11.4zm64.8 0l3.6 10.9h11.4l-9.3 6.7l3.6 10.9l-9.3-6.7l-9.3 6.7L124 57l-9.3-6.7h11.5zm64.9 0l3.5 10.9h11.5l-9.3 6.7l3.5 10.9l-9.2-6.7l-9.3 6.7l3.5-10.9l-9.2-6.7H191zm64.8 0l3.6 10.9h11.4l-9.3 6.7l3.6 10.9l-9.3-6.7l-9.2 6.7l3.5-10.9l-9.3-6.7H256zm64.9 0l3.5 10.9h11.5L330 57l3.5 10.9l-9.2-6.7l-9.3 6.7l3.5-10.9l-9.2-6.7h11.4zM32.4 66.9L36 78h11.4l-9.2 6.7l3.5 10.9l-9.3-6.8l-9.2 6.8l3.5-11l-9.3-6.7H29zm64.9 0l3.5 11h11.5l-9.3 6.7l3.5 10.9l-9.2-6.8l-9.3 6.8l3.5-11l-9.2-6.7h11.4zm64.8 0l3.6 11H177l-9.2 6.7l3.5 10.9l-9.3-6.8l-9.2 6.8l3.5-11l-9.3-6.7h11.5zm64.9 0l3.5 11H242l-9.3 6.7l3.6 10.9l-9.3-6.8l-9.3 6.8l3.6-11l-9.3-6.7h11.4zm64.8 0l3.6 11h11.4l-9.2 6.7l3.5 10.9l-9.3-6.8l-9.2 6.8l3.5-11l-9.2-6.7h11.4zm64.9 0l3.5 11h11.5l-9.3 6.7l3.6 10.9l-9.3-6.8l-9.3 6.8l3.6-11l-9.3-6.7h11.5zM64.9 94.5l3.5 10.9h11.5l-9.3 6.7l3.5 11l-9.2-6.8l-9.3 6.7l3.5-10.9l-9.2-6.7h11.4zm64.8 0l3.6 10.9h11.4l-9.3 6.7l3.6 11l-9.3-6.8l-9.3 6.7l3.6-10.9l-9.3-6.7h11.5zm64.9 0l3.5 10.9h11.5l-9.3 6.7l3.5 11l-9.2-6.8l-9.3 6.7l3.5-10.9l-9.2-6.7H191zm64.8 0l3.6 10.9h11.4l-9.2 6.7l3.5 11l-9.3-6.8l-9.2 6.7l3.5-10.9l-9.3-6.7H256zm64.9 0l3.5 10.9h11.5l-9.3 6.7l3.5 11l-9.2-6.8l-9.3 6.7l3.5-10.9l-9.2-6.7h11.4zM32.4 122.1L36 133h11.4l-9.2 6.7l3.5 11l-9.3-6.8l-9.2 6.7l3.5-10.9l-9.3-6.7H29zm64.9 0l3.5 10.9h11.5l-9.3 6.7l3.5 10.9l-9.2-6.7l-9.3 6.7l3.5-10.9l-9.2-6.7h11.4zm64.8 0l3.6 10.9H177l-9.2 6.7l3.5 11l-9.3-6.8l-9.2 6.7l3.5-10.9l-9.3-6.7h11.5zm64.9 0l3.5 10.9H242l-9.3 6.7l3.6 11l-9.3-6.8l-9.3 6.7l3.6-10.9l-9.3-6.7h11.4zm64.8 0l3.6 10.9h11.4l-9.2 6.7l3.5 11l-9.3-6.8l-9.2 6.7l3.5-10.9l-9.2-6.7h11.4zm64.9 0l3.5 10.9h11.5l-9.3 6.7l3.6 11l-9.3-6.8l-9.3 6.7l3.6-10.9l-9.3-6.7h11.5zM64.9 149.7l3.5 10.9h11.5l-9.3 6.7l3.5 10.9l-9.2-6.8l-9.3 6.8l3.5-11l-9.2-6.7h11.4zm64.8 0l3.6 10.9h11.4l-9.3 6.7l3.6 10.9l-9.3-6.8l-9.3 6.8l3.6-11l-9.3-6.7h11.5zm64.9 0l3.5 10.9h11.5l-9.3 6.7l3.5 10.9l-9.2-6.8l-9.3 6.8l3.5-11l-9.2-6.7H191zm64.8 0l3.6 10.9h11.4l-9.2 6.7l3.5 10.9l-9.3-6.8l-9.2 6.8l3.5-11l-9.3-6.7H256zm64.9 0l3.5 10.9h11.5l-9.3 6.7l3.5 10.9l-9.2-6.8l-9.3 6.8l3.5-11l-9.2-6.7h11.4zM32.4 177.2l3.6 11h11.4l-9.2 6.7l3.5 10.8l-9.3-6.7l-9.2 6.7l3.5-10.9l-9.3-6.7H29zm64.9 0l3.5 11h11.5l-9.3 6.7l3.6 10.8l-9.3-6.7l-9.3 6.7l3.6-10.9l-9.3-6.7h11.4zm64.8 0l3.6 11H177l-9.2 6.7l3.5 10.8l-9.3-6.7l-9.2 6.7l3.5-10.9l-9.3-6.7h11.5zm64.9 0l3.5 11H242l-9.3 6.7l3.6 10.8l-9.3-6.7l-9.3 6.7l3.6-10.9l-9.3-6.7h11.4zm64.8 0l3.6 11h11.4l-9.2 6.7l3.5 10.8l-9.3-6.7l-9.2 6.7l3.5-10.9l-9.2-6.7h11.4zm64.9 0l3.5 11h11.5l-9.3 6.7l3.6 10.8l-9.3-6.7l-9.3 6.7l3.6-10.9l-9.3-6.7h11.5zM64.9 204.8l3.5 10.9h11.5l-9.3 6.7l3.5 11l-9.2-6.8l-9.3 6.7l3.5-10.9l-9.2-6.7h11.4zm64.8 0l3.6 10.9h11.4l-9.3 6.7l3.6 11l-9.3-6.8l-9.3 6.7l3.6-10.9l-9.3-6.7h11.5zm64.9 0l3.5 10.9h11.5l-9.3 6.7l3.5 11l-9.2-6.8l-9.3 6.7l3.5-10.9l-9.2-6.7H191zm64.8 0l3.6 10.9h11.4l-9.2 6.7l3.5 11l-9.3-6.8l-9.2 6.7l3.5-10.9l-9.3-6.7H256zm64.9 0l3.5 10.9h11.5l-9.3 6.7l3.5 11l-9.2-6.8l-9.3 6.7l3.5-10.9l-9.2-6.7h11.4zM32.4 232.4l3.6 10.9h11.4l-9.2 6.7l3.5 10.9l-9.3-6.7l-9.2 6.7l3.5-11l-9.3-6.7H29zm64.9 0l3.5 10.9h11.5L103 250l3.6 10.9l-9.3-6.7l-9.3 6.7l3.6-11l-9.3-6.7h11.4zm64.8 0l3.6 10.9H177l-9 6.7l3.5 10.9l-9.3-6.7l-9.2 6.7l3.5-11l-9.3-6.7h11.5zm64.9 0l3.5 10.9H242l-9.3 6.7l3.6 10.9l-9.3-6.7l-9.3 6.7l3.6-11l-9.3-6.7h11.4zm64.8 0l3.6 10.9h11.4l-9.2 6.7l3.5 10.9l-9.3-6.7l-9.2 6.7l3.5-11l-9.2-6.7h11.4zm64.9 0l3.5 10.9h11.5l-9.3 6.7l3.6 10.9l-9.3-6.7l-9.3 6.7l3.6-11l-9.3-6.7h11.5z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 4.5 KiB |
BIN
public/Layout/Footer.jpg
Normal file
|
After Width: | Height: | Size: 67 KiB |
BIN
public/Layout/Footer/1.png
Normal file
|
After Width: | Height: | Size: 849 B |
BIN
public/Layout/Footer/2.png
Normal file
|
After Width: | Height: | Size: 674 B |
BIN
public/Layout/Footer/3.png
Normal file
|
After Width: | Height: | Size: 822 B |
BIN
public/Layout/Footer/4.png
Normal file
|
After Width: | Height: | Size: 644 B |
27
public/Layout/KarimLogo.svg
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg class="Logo" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1367 766.99">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-2 {
|
||||
fill:white;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: transparent;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_1-2" data-name="Layer 1-2">
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path class="cls-2" d="M540.42,301c0-7.67,0-15.33,.96-22.04,0-1.92,.96-1.92,1.92-2.87,33.54-15.33,54.62-42.17,69-75.71,4.79-11.5,7.67-22.04,8.62-34.5,.96-7.67,0-15.33-2.87-23-4.79-10.54-16.29-15.33-28.75-12.46-16.29,3.83-26.83,15.33-36.42,28.75-11.5,17.25-16.29,37.37-20.12,56.54-6.71,31.62-8.62,63.25-10.54,94.87-1.92,26.83-3.83,53.67-7.67,80.5-.96,4.79-1.92,9.58-2.87,14.37-.96,4.79,0,4.79,3.83,3.83,16.29-3.83,31.62-8.62,46-16.29,31.62-15.33,59.42-35.46,84.33-58.46,45.04-43.12,81.46-92,105.41-149.5,13.42-31.62,21.08-65.17,18.21-99.66,0-3.83,0-8.62-.96-12.46-.96-4.79,.96-6.71,4.79-8.62,8.62-3.83,18.21-4.79,27.79-4.79,6.71,0,13.42,.96,21.08,2.87,14.37,2.87,24.92,12.46,32.58,23.96,.96,.96,1.92,2.87,.96,3.83s-2.87,0-3.83,0c-5.75-1.92-11.5-3.83-18.21-2.87-13.42,.96-22.04,8.62-24.92,23-2.87,10.54-2.87,22.04-2.87,33.54,.96,20.12,3.83,40.25,3.83,60.37,0,5.75-1.92,11.5-4.79,17.25-43.12,71.87-98.71,130.33-172.5,171.54-39.29,22.04-79.54,37.37-123.62,47.92-3.83,.96-5.75,1.92-6.71,5.75-14.37,56.54-39.29,107.33-77.62,151.41-25.87,30.67-56.54,54.62-93.92,69.96-18.21,7.67-37.37,11.5-57.5,6.71-26.83-6.71-42.17-24.92-49.83-50.79-14.37-48.87,8.62-104.46,53.67-132.25,17.25-10.54,35.46-18.21,56.54-17.25,5.75,0,10.54,.96,16.29,1.92,4.79,.96,6.71,3.83,6.71,7.67,.96,13.42-4.79,24.92-14.37,33.54-3.83,3.83-7.67,3.83-12.46,0-4.79-3.83-9.58-7.67-14.37-9.58-18.21-9.58-35.46-5.75-48.87,9.58-13.42,15.33-20.12,33.54-24.92,52.71-3.83,17.25-4.79,34.5-3.83,51.75,.96,10.54,2.87,21.08,8.62,30.67,6.71,10.54,16.29,13.42,27.79,10.54,10.54-2.87,20.12-9.58,27.79-18.21,31.62-31.62,56.54-68.04,73.79-110.21,22.04-55.58,39.29-113.08,47.92-172.5,4.79-33.54,10.54-67.08,20.12-99.66,12.46-42.17,28.75-82.42,56.54-116.91,17.25-21.08,36.42-39.29,63.25-46.96,23-6.71,44.08-3.83,61.33,14.37,10.54,10.54,14.37,23.96,15.33,38.33,1.92,25.87-6.71,48.87-18.21,71.87-18.21,35.46-46,61.33-82.42,77.62q1.92,0,.96,0h0Z"/>
|
||||
<path class="cls-2" d="M1056.95,437.08c-2.87-2.87-6.71-5.75-9.58-8.62s-3.83-2.87-5.75,.96c-10.54,24.92-22.04,49.83-34.5,74.75-11.5,21.08-23,42.17-39.29,59.42-5.75,6.71-12.46,12.46-20.12,16.29-15.33,7.67-29.71,1.92-36.42-13.42-3.83-7.67-3.83-15.33-3.83-23.96,0-21.08,5.75-41.21,12.46-60.37,7.67-21.08,15.33-41.21,29.71-58.46,9.58-11.5,21.08-22.04,36.42-25.87,6.71-1.92,13.42-.96,19.17,0,1.92,0,2.87,.96,3.83-1.92,9.58-23.96,19.17-48.87,26.83-73.79-3.83,3.83-7.67,8.62-11.5,12.46-9.58,10.54-21.08,21.08-33.54,27.79-27.79,17.25-56.54,13.42-80.5-9.58-14.37-13.42-23-30.67-29.71-48.87-1.92-4.79-3.83-9.58-6.71-15.33-.96,8.62-.96,16.29-2.87,24.92-6.71,46-15.33,92-40.25,132.25-15.33,25.87-37.37,45.04-67.08,53.67-.96,0-1.92,0-2.87,.96-.96,0-1.92,.96-1.92-.96,32.58-10.54,52.71-34.5,66.12-65.17,8.62-20.12,13.42-41.21,17.25-63.25,5.75-38.33,4.79-76.67,4.79-115,0-12.46-1.92-24.92,0-36.42,.96-8.62,4.79-15.33,13.42-19.17,5.75-2.87,10.54-1.92,16.29,.96,7.67,5.75,12.46,13.42,16.29,21.08,9.58,17.25,15.33,36.42,23,54.62,4.79,12.46,10.54,24.92,18.21,36.42,12.46,18.21,24.92,20.12,42.17,6.71,17.25-13.42,30.67-30.67,42.17-48.87,27.79-41.21,50.79-86.25,70.92-132.25,5.75-13.42,11.5-26.83,18.21-39.29,4.79-8.62,12.46-12.46,22.04-11.5,8.62,.96,14.37,6.71,16.29,15.33,1.92,6.71,.96,12.46-.96,19.17-12.46,43.12-26.83,86.25-40.25,128.41-18.21,55.58-37.37,111.16-59.42,164.83-.96,2.87-.96,3.83,.96,5.75,3.83,3.83,6.71,7.67,10.54,12.46q.96,2.87,0,2.87h0Z"/>
|
||||
<path class="cls-2" d="M561.5,456.25c1.92,3.83,.96,8.62,.96,12.46-.96,44.08,4.79,87.21,22.04,127.46,4.79,12.46,11.5,23,21.08,32.58,17.25,18.21,40.25,23,63.25,12.46,20.12-9.58,35.46-23.96,50.79-40.25,2.87-2.87,5.75-5.75,7.67-9.58,1.92-2.87,4.79-2.87,7.67-1.92,16.29,5.75,28.75,15.33,37.37,29.71,2.87,4.79,2.87,9.58-.96,14.37-15.33,20.12-34.5,35.46-59.42,41.21-22.04,4.79-43.12,.96-63.25-9.58-27.79-14.37-48.87-36.42-66.12-62.29-19.17-29.71-31.62-62.29-38.33-96.79-1.92-8.62-1.92-17.25-2.87-25.87,0-1.92,0-2.87,.96-3.83,5.75-6.71,12.46-13.42,19.17-20.12h0Z"/>
|
||||
<path class="cls-2" d="M844.21,140.96c0-6.71,4.79-11.5,10.54-11.5s11.5,5.75,11.5,11.5-4.79,11.5-11.5,11.5c-5.75,0-10.54-4.79-10.54-11.5h0Z"/>
|
||||
</g>
|
||||
<path class="cls-3" d="M935.25,547.29c-.96-4.79-1.92-8.62-1.92-12.46,.96-32.58,6.71-64.21,21.08-93.91,6.71-12.46,14.37-23.96,27.79-31.62,5.75-2.87,12.46-4.79,19.17-3.83,2.87,0,2.87,.96,1.92,2.87-17.25,41.21-33.54,83.37-55.58,121.71-2.88,6.71-7.67,11.5-12.46,17.25h0Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.6 KiB |
54
public/Layout/KarimLogo.tsx
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
import React from "react";
|
||||
|
||||
const KarimLogo = () => {
|
||||
return (
|
||||
<>
|
||||
<svg
|
||||
className="KarimLogo"
|
||||
id="Layer_1"
|
||||
data-name="Layer 1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 1367 766.99"
|
||||
>
|
||||
<defs>
|
||||
<style
|
||||
dangerouslySetInnerHTML={{
|
||||
__html:
|
||||
"\n .cls-2 {\n fill:white;\n }\n\n .cls-3 {\n fill: transparent;\n }\n ",
|
||||
}}
|
||||
/>
|
||||
</defs>
|
||||
<g id="Layer_1-2" data-name="Layer 1-2">
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path
|
||||
className="cls-2"
|
||||
d="M540.42,301c0-7.67,0-15.33,.96-22.04,0-1.92,.96-1.92,1.92-2.87,33.54-15.33,54.62-42.17,69-75.71,4.79-11.5,7.67-22.04,8.62-34.5,.96-7.67,0-15.33-2.87-23-4.79-10.54-16.29-15.33-28.75-12.46-16.29,3.83-26.83,15.33-36.42,28.75-11.5,17.25-16.29,37.37-20.12,56.54-6.71,31.62-8.62,63.25-10.54,94.87-1.92,26.83-3.83,53.67-7.67,80.5-.96,4.79-1.92,9.58-2.87,14.37-.96,4.79,0,4.79,3.83,3.83,16.29-3.83,31.62-8.62,46-16.29,31.62-15.33,59.42-35.46,84.33-58.46,45.04-43.12,81.46-92,105.41-149.5,13.42-31.62,21.08-65.17,18.21-99.66,0-3.83,0-8.62-.96-12.46-.96-4.79,.96-6.71,4.79-8.62,8.62-3.83,18.21-4.79,27.79-4.79,6.71,0,13.42,.96,21.08,2.87,14.37,2.87,24.92,12.46,32.58,23.96,.96,.96,1.92,2.87,.96,3.83s-2.87,0-3.83,0c-5.75-1.92-11.5-3.83-18.21-2.87-13.42,.96-22.04,8.62-24.92,23-2.87,10.54-2.87,22.04-2.87,33.54,.96,20.12,3.83,40.25,3.83,60.37,0,5.75-1.92,11.5-4.79,17.25-43.12,71.87-98.71,130.33-172.5,171.54-39.29,22.04-79.54,37.37-123.62,47.92-3.83,.96-5.75,1.92-6.71,5.75-14.37,56.54-39.29,107.33-77.62,151.41-25.87,30.67-56.54,54.62-93.92,69.96-18.21,7.67-37.37,11.5-57.5,6.71-26.83-6.71-42.17-24.92-49.83-50.79-14.37-48.87,8.62-104.46,53.67-132.25,17.25-10.54,35.46-18.21,56.54-17.25,5.75,0,10.54,.96,16.29,1.92,4.79,.96,6.71,3.83,6.71,7.67,.96,13.42-4.79,24.92-14.37,33.54-3.83,3.83-7.67,3.83-12.46,0-4.79-3.83-9.58-7.67-14.37-9.58-18.21-9.58-35.46-5.75-48.87,9.58-13.42,15.33-20.12,33.54-24.92,52.71-3.83,17.25-4.79,34.5-3.83,51.75,.96,10.54,2.87,21.08,8.62,30.67,6.71,10.54,16.29,13.42,27.79,10.54,10.54-2.87,20.12-9.58,27.79-18.21,31.62-31.62,56.54-68.04,73.79-110.21,22.04-55.58,39.29-113.08,47.92-172.5,4.79-33.54,10.54-67.08,20.12-99.66,12.46-42.17,28.75-82.42,56.54-116.91,17.25-21.08,36.42-39.29,63.25-46.96,23-6.71,44.08-3.83,61.33,14.37,10.54,10.54,14.37,23.96,15.33,38.33,1.92,25.87-6.71,48.87-18.21,71.87-18.21,35.46-46,61.33-82.42,77.62q1.92,0,.96,0h0Z"
|
||||
/>
|
||||
<path
|
||||
className="cls-2"
|
||||
d="M1056.95,437.08c-2.87-2.87-6.71-5.75-9.58-8.62s-3.83-2.87-5.75,.96c-10.54,24.92-22.04,49.83-34.5,74.75-11.5,21.08-23,42.17-39.29,59.42-5.75,6.71-12.46,12.46-20.12,16.29-15.33,7.67-29.71,1.92-36.42-13.42-3.83-7.67-3.83-15.33-3.83-23.96,0-21.08,5.75-41.21,12.46-60.37,7.67-21.08,15.33-41.21,29.71-58.46,9.58-11.5,21.08-22.04,36.42-25.87,6.71-1.92,13.42-.96,19.17,0,1.92,0,2.87,.96,3.83-1.92,9.58-23.96,19.17-48.87,26.83-73.79-3.83,3.83-7.67,8.62-11.5,12.46-9.58,10.54-21.08,21.08-33.54,27.79-27.79,17.25-56.54,13.42-80.5-9.58-14.37-13.42-23-30.67-29.71-48.87-1.92-4.79-3.83-9.58-6.71-15.33-.96,8.62-.96,16.29-2.87,24.92-6.71,46-15.33,92-40.25,132.25-15.33,25.87-37.37,45.04-67.08,53.67-.96,0-1.92,0-2.87,.96-.96,0-1.92,.96-1.92-.96,32.58-10.54,52.71-34.5,66.12-65.17,8.62-20.12,13.42-41.21,17.25-63.25,5.75-38.33,4.79-76.67,4.79-115,0-12.46-1.92-24.92,0-36.42,.96-8.62,4.79-15.33,13.42-19.17,5.75-2.87,10.54-1.92,16.29,.96,7.67,5.75,12.46,13.42,16.29,21.08,9.58,17.25,15.33,36.42,23,54.62,4.79,12.46,10.54,24.92,18.21,36.42,12.46,18.21,24.92,20.12,42.17,6.71,17.25-13.42,30.67-30.67,42.17-48.87,27.79-41.21,50.79-86.25,70.92-132.25,5.75-13.42,11.5-26.83,18.21-39.29,4.79-8.62,12.46-12.46,22.04-11.5,8.62,.96,14.37,6.71,16.29,15.33,1.92,6.71,.96,12.46-.96,19.17-12.46,43.12-26.83,86.25-40.25,128.41-18.21,55.58-37.37,111.16-59.42,164.83-.96,2.87-.96,3.83,.96,5.75,3.83,3.83,6.71,7.67,10.54,12.46q.96,2.87,0,2.87h0Z"
|
||||
/>
|
||||
<path
|
||||
className="cls-2"
|
||||
d="M561.5,456.25c1.92,3.83,.96,8.62,.96,12.46-.96,44.08,4.79,87.21,22.04,127.46,4.79,12.46,11.5,23,21.08,32.58,17.25,18.21,40.25,23,63.25,12.46,20.12-9.58,35.46-23.96,50.79-40.25,2.87-2.87,5.75-5.75,7.67-9.58,1.92-2.87,4.79-2.87,7.67-1.92,16.29,5.75,28.75,15.33,37.37,29.71,2.87,4.79,2.87,9.58-.96,14.37-15.33,20.12-34.5,35.46-59.42,41.21-22.04,4.79-43.12,.96-63.25-9.58-27.79-14.37-48.87-36.42-66.12-62.29-19.17-29.71-31.62-62.29-38.33-96.79-1.92-8.62-1.92-17.25-2.87-25.87,0-1.92,0-2.87,.96-3.83,5.75-6.71,12.46-13.42,19.17-20.12h0Z"
|
||||
/>
|
||||
<path
|
||||
className="cls-2"
|
||||
d="M844.21,140.96c0-6.71,4.79-11.5,10.54-11.5s11.5,5.75,11.5,11.5-4.79,11.5-11.5,11.5c-5.75,0-10.54-4.79-10.54-11.5h0Z"
|
||||
/>
|
||||
</g>
|
||||
<path
|
||||
className="cls-3"
|
||||
d="M935.25,547.29c-.96-4.79-1.92-8.62-1.92-12.46,.96-32.58,6.71-64.21,21.08-93.91,6.71-12.46,14.37-23.96,27.79-31.62,5.75-2.87,12.46-4.79,19.17-3.83,2.87,0,2.87,.96,1.92,2.87-17.25,41.21-33.54,83.37-55.58,121.71-2.88,6.71-7.67,11.5-12.46,17.25h0Z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default KarimLogo;
|
||||
BIN
public/Layout/LoginBg.jpg
Normal file
|
After Width: | Height: | Size: 12 KiB |
1
public/Layout/dark.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 64 64"><path fill="currentColor" d="M43.139 2a29.885 29.885 0 0 1 5.121 16.756c0 16.701-13.686 30.24-30.57 30.24a30.656 30.656 0 0 1-15.689-4.285C7.209 54.963 17.93 62 30.318 62C47.816 62 62 47.969 62 30.66C62 17.867 54.246 6.871 43.139 2z"/></svg>
|
||||
|
After Width: | Height: | Size: 324 B |
1
public/Layout/light.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 512 512"><path fill="currentColor" d="M256 160c-52.9 0-96 43.1-96 96s43.1 96 96 96s96-43.1 96-96s-43.1-96-96-96zm246.4 80.5l-94.7-47.3l33.5-100.4c4.5-13.6-8.4-26.5-21.9-21.9l-100.4 33.5l-47.4-94.8c-6.4-12.8-24.6-12.8-31 0l-47.3 94.7L92.7 70.8c-13.6-4.5-26.5 8.4-21.9 21.9l33.5 100.4l-94.7 47.4c-12.8 6.4-12.8 24.6 0 31l94.7 47.3l-33.5 100.5c-4.5 13.6 8.4 26.5 21.9 21.9l100.4-33.5l47.3 94.7c6.4 12.8 24.6 12.8 31 0l47.3-94.7l100.4 33.5c13.6 4.5 26.5-8.4 21.9-21.9l-33.5-100.4l94.7-47.3c13-6.5 13-24.7.2-31.1zm-155.9 106c-49.9 49.9-131.1 49.9-181 0c-49.9-49.9-49.9-131.1 0-181c49.9-49.9 131.1-49.9 181 0c49.9 49.9 49.9 131.1 0 181z"/></svg>
|
||||
|
After Width: | Height: | Size: 715 B |
29
public/firebase-messaging-sw.js
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
importScripts("https://www.gstatic.com/firebasejs/8.2.0/firebase-app.js");
|
||||
importScripts("https://www.gstatic.com/firebasejs/8.2.0/firebase-messaging.js");
|
||||
|
||||
// Initialize the Firebase app in the service worker by passing the generated config
|
||||
const firebaseConfig = {
|
||||
apiKey: "AIzaSyCcg92Eqrw7TzL8fBQVklVKXwuT3hu0GIQ",
|
||||
authDomain: "dm-store-678d4.firebaseapp.com",
|
||||
projectId: "dm-store-678d4",
|
||||
storageBucket: "dm-store-678d4.appspot.com",
|
||||
messagingSenderId: "91725694575",
|
||||
appId: "1:91725694575:web:6ce7f7d0dfdf807c376f9a",
|
||||
measurementId: "G-TZRGSK472N"
|
||||
};
|
||||
|
||||
firebase.initializeApp(firebaseConfig);
|
||||
|
||||
// Retrieve firebase messaging
|
||||
const messaging = firebase.messaging();
|
||||
|
||||
messaging.onBackgroundMessage(function (payload) {
|
||||
console.log("Received background message ", payload);
|
||||
|
||||
const notificationTitle = payload.notification.title;
|
||||
const notificationOptions = {
|
||||
body: payload.notification.body,
|
||||
};
|
||||
|
||||
self.registration.showNotification(notificationTitle, notificationOptions);
|
||||
});
|
||||
3
public/icon/percent.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M19.5289 8.87L18.0089 7.35001C17.7489 7.09 17.5389 6.58001 17.5389 6.22001V4.06C17.5389 3.18 16.8189 2.46 15.9389 2.46H13.7889C13.4289 2.46 12.9189 2.25 12.6589 1.99L11.1389 0.470005C10.5189 -0.149995 9.49891 -0.149995 8.87891 0.470005L7.33891 1.99C7.08891 2.25 6.57891 2.46 6.20891 2.46H4.05891C3.17891 2.46 2.45891 3.18 2.45891 4.06V6.21C2.45891 6.57 2.24891 7.08 1.98891 7.34L0.468906 8.86C-0.151094 9.48 -0.151094 10.5 0.468906 11.12L1.98891 12.64C2.24891 12.9 2.45891 13.41 2.45891 13.77V15.92C2.45891 16.8 3.17891 17.52 4.05891 17.52H6.20891C6.56891 17.52 7.07891 17.73 7.33891 17.99L8.85891 19.51C9.47891 20.13 10.4989 20.13 11.1189 19.51L12.6389 17.99C12.8989 17.73 13.4089 17.52 13.7689 17.52H15.9189C16.7989 17.52 17.5189 16.8 17.5189 15.92V13.77C17.5189 13.41 17.7289 12.9 17.9889 12.64L19.5089 11.12C20.1589 10.51 20.1589 9.49 19.5289 8.87ZM5.99891 7C5.99891 6.45 6.44891 6 6.99891 6C7.54891 6 7.99891 6.45 7.99891 7C7.99891 7.55 7.55891 8 6.99891 8C6.44891 8 5.99891 7.55 5.99891 7ZM7.52891 13.53C7.37891 13.68 7.18891 13.75 6.99891 13.75C6.80891 13.75 6.61891 13.68 6.46891 13.53C6.17891 13.24 6.17891 12.76 6.46891 12.47L12.4689 6.47001C12.7589 6.18001 13.2389 6.18001 13.5289 6.47001C13.8189 6.76 13.8189 7.24 13.5289 7.53L7.52891 13.53ZM12.9989 14C12.4389 14 11.9889 13.55 11.9889 13C11.9889 12.45 12.4389 12 12.9889 12C13.5389 12 13.9889 12.45 13.9889 13C13.9889 13.55 13.5489 14 12.9989 14Z" fill="#F45E0C"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
36
public/index.html
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<link rel="android-chrome" href="./App/Logo.svg" />
|
||||
<link rel="android-chrome" href="./App/Logo.svg" />
|
||||
<link rel="canonical" href="https://karimalden.vercel.app/" />
|
||||
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="./App/Logo.svg" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="./App/Logo.svg" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="./App/Logo.svg" />
|
||||
<link rel="manifest" href="./site.webmanifest" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Landing Page About My Work and Includ My Cv As Front End Developer Use Reactjs In Syria"
|
||||
/>
|
||||
|
||||
<meta property="og:title" content="My LandingPage" />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="Landing Page About My Work and Includ My Cv As Front End Developer Use Reactjs In Syria"
|
||||
/>
|
||||
<meta property="og:image" content="./App/Logo.svg" />
|
||||
<meta property="og:url" content="https://karimalden.vercel.app" />
|
||||
<meta property="og:type" content="website" />
|
||||
<script type="module" src="/src/index.tsx"></script>
|
||||
|
||||
<title>React-Start-App</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
3
public/robots.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
||||
27
public/site.webmanifest
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"name": "ReactStart-App",
|
||||
"short_name": "RS",
|
||||
"description": "A social networking platform with automated content moderation and context-based authentication system.",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#ffffff",
|
||||
"theme_color": "#000000",
|
||||
"icons": [
|
||||
{
|
||||
"src": "./App/Logo.svg",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "./App/Logo.svg",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "./App/Logo.svg",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
]
|
||||
}
|
||||
57
src/App.tsx
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import { Suspense, useEffect } from "react";
|
||||
import { Route, Routes } from "react-router-dom";
|
||||
import Layout from "./Layout/Ui/Layout";
|
||||
import { routes } from "./Routes";
|
||||
import { Spin } from "antd";
|
||||
import { useGuest } from "./api/auth";
|
||||
import useAuthState from "./state/AuthState";
|
||||
import { requestPermission } from "./utils/firebase/firebase";
|
||||
|
||||
const App = () => {
|
||||
const { data, mutate } = useGuest();
|
||||
const { Guest, setGuest } = useAuthState();
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
//@ts-ignore
|
||||
const guest = data?.token;
|
||||
setGuest(guest);
|
||||
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
useEffect(() => {
|
||||
const fn_firebase = (async () => {
|
||||
const token = await requestPermission()
|
||||
if (!Guest) {
|
||||
mutate({ fcm_token: token });
|
||||
}
|
||||
})
|
||||
fn_firebase()
|
||||
}, [Guest])
|
||||
|
||||
if (!Guest) {
|
||||
return <Spin />;
|
||||
}
|
||||
return (
|
||||
<Routes>
|
||||
{routes?.map((route: any) => (
|
||||
<Route
|
||||
key={route.path}
|
||||
path={route.path}
|
||||
element={
|
||||
<Suspense fallback={<Spin />}>
|
||||
{route.withLayout ? (
|
||||
<Layout>{route.element}</Layout>
|
||||
) : (
|
||||
route.element
|
||||
)}
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</Routes>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
39
src/Components/Auth/AuthTabs.tsx
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import React from 'react';
|
||||
import { Tabs } from 'antd';
|
||||
import type { TabsProps } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import RegisterForm from '../../Pages/Auth/Register';
|
||||
import LoginForm from '../../Pages/Auth/LoginForm';
|
||||
import VerifyForm from '../../Pages/Auth/VerifyForm';
|
||||
|
||||
const AuthTabs = ({setOpen}:any) => {
|
||||
|
||||
const {t} = useTranslation();
|
||||
|
||||
const items: TabsProps['items'] = [
|
||||
{
|
||||
key: '1',
|
||||
label: t('Login'),
|
||||
children: <LoginForm setOpen={setOpen} />,
|
||||
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
label: t('Create Account'),
|
||||
children: <RegisterForm/>,
|
||||
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
label: t('Verify'),
|
||||
children: <VerifyForm/>,
|
||||
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Tabs className='auth_tab' defaultActiveKey="1" items={items} />
|
||||
)
|
||||
}
|
||||
|
||||
export default AuthTabs
|
||||
105
src/Components/Cart/CardItem.tsx
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
import {
|
||||
CloseOutlined,
|
||||
MinusCircleOutlined,
|
||||
PlusCircleFilled,
|
||||
} from "@ant-design/icons";
|
||||
import React, { useState } from "react";
|
||||
import { Card, Skeleton, Button, Tooltip, Popconfirm } from "antd";
|
||||
import useLoadingState from "../../Hooks/useLoadingState";
|
||||
import { TProduct } from "../../types/Cart";
|
||||
import { FaRegTrashAlt, FaTruck, FaPlus } from "react-icons/fa";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { MdOutlineVerified } from "react-icons/md";
|
||||
import { FiMinus } from "react-icons/fi";
|
||||
import CustomImage from "../../ui/CustomImage";
|
||||
import { Product } from "../../types/item";
|
||||
import { useCartState } from "../../state/CartState";
|
||||
import { languageObject } from "../../utils/languageObject";
|
||||
import { Currency } from "../../Layout/app/Const";
|
||||
|
||||
interface CartItemProps {
|
||||
data: Product;
|
||||
}
|
||||
|
||||
const CardItem: React.FC<CartItemProps> = ({ data }) => {
|
||||
const [loading, resetLoading] = useLoadingState(true, 2000);
|
||||
const { t } = useTranslation();
|
||||
const { setCart, deleteFromCart, removeFromCart } = useCartState();
|
||||
|
||||
const addToCart = () => {
|
||||
setCart(data);
|
||||
};
|
||||
|
||||
const DeleteFromCart = () => {
|
||||
deleteFromCart(data?.id);
|
||||
};
|
||||
const RemoveFromCart = () => {
|
||||
removeFromCart(data?.id);
|
||||
};
|
||||
|
||||
const price = (data?.quantity ?? 1) * data?.price;
|
||||
|
||||
return (
|
||||
<Skeleton
|
||||
key={data?.id}
|
||||
loading={loading}
|
||||
active
|
||||
avatar
|
||||
style={{ width: "100%", marginTop: 22 }}
|
||||
>
|
||||
<Card
|
||||
className="CardItem"
|
||||
style={{ width: "100%", marginTop: 16 }}
|
||||
loading={loading}
|
||||
>
|
||||
<span className="Card_Img">
|
||||
<CustomImage alt="" src={data?.main_photo} />
|
||||
</span>
|
||||
|
||||
<span className="Card_Info">
|
||||
<h5>{languageObject(data?.name)}</h5>
|
||||
<h6>
|
||||
<FaTruck /> {t("Free Delivery")}
|
||||
</h6>
|
||||
<h6>
|
||||
<MdOutlineVerified /> {t("Guaranteed")}
|
||||
</h6>
|
||||
|
||||
<div className="card_price">
|
||||
<p>
|
||||
{price} {Currency}{" "}
|
||||
</p>
|
||||
|
||||
<div className="count_section">
|
||||
<FaRegTrashAlt
|
||||
onClick={() => {
|
||||
RemoveFromCart();
|
||||
}}
|
||||
className="trashIcon"
|
||||
/>
|
||||
<div className="card_counter">
|
||||
<span
|
||||
onClick={() => {
|
||||
DeleteFromCart();
|
||||
}}
|
||||
>
|
||||
<FiMinus />
|
||||
</span>
|
||||
<span className="Counter">{data?.quantity}</span>
|
||||
<span
|
||||
onClick={() => {
|
||||
addToCart();
|
||||
}}
|
||||
>
|
||||
<FaPlus />{" "}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</Card>
|
||||
</Skeleton>
|
||||
);
|
||||
};
|
||||
|
||||
export default CardItem;
|
||||
12
src/Components/Cart/Cart.tsx
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import CartWithDrawer from '../HOC/CartWithDrawer'
|
||||
|
||||
const ViewCart = () => {
|
||||
|
||||
return (
|
||||
<div className='ViewCart'>
|
||||
<CartWithDrawer/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ViewCart
|
||||
47
src/Components/Categories/BrandFilter.tsx
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import React from "react";
|
||||
import { Checkbox } from "antd";
|
||||
import type { CheckboxProps } from "antd";
|
||||
import { useFilterStateState } from "../../state/Filter";
|
||||
import { useGetCategories } from "../../api/Categories";
|
||||
import { Category } from "../../types/item";
|
||||
import { languageObject } from "../../utils/languageObject";
|
||||
|
||||
const BrandFilter = () => {
|
||||
const { setFilter, Filter } = useFilterStateState();
|
||||
const onChange =
|
||||
(Category: Category): CheckboxProps["onChange"] =>
|
||||
(e) => {
|
||||
const checked = e.target.checked;
|
||||
|
||||
if (checked) {
|
||||
setFilter([...Filter, { name:Category?.name,id:Category?.id,type:"category", index: Filter.length }]);
|
||||
} else {
|
||||
const newArray = Filter?.filter((item: any) => item.name !== Category?.name);
|
||||
setFilter(newArray);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
const {data:categories_data} = useGetCategories({
|
||||
parent_id:''
|
||||
})
|
||||
const categories = categories_data?.categories as Category[] || [] ;
|
||||
|
||||
return (
|
||||
<div className="CheckboxFilter">
|
||||
{categories?.map((brand) => (
|
||||
<Checkbox
|
||||
checked={Filter.some((item: any) => item.name === brand?.name)}
|
||||
key={brand?.id}
|
||||
onChange={onChange(brand)}
|
||||
|
||||
>
|
||||
{languageObject(brand?.name)}
|
||||
</Checkbox>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BrandFilter;
|
||||
49
src/Components/Categories/Connectivity.tsx
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
import React from "react";
|
||||
import { Checkbox } from "antd";
|
||||
import type { CheckboxProps } from "antd";
|
||||
import { useFilterStateState } from "../../state/Filter";
|
||||
import { useGetCategories } from "../../api/Categories";
|
||||
import { Category } from "../../types/item";
|
||||
import { languageObject } from "../../utils/languageObject";
|
||||
import { useGetBaseSubCategory } from "../../api/baseSubCategory";
|
||||
|
||||
const BrandFilter = () => {
|
||||
const { setFilter, Filter } = useFilterStateState();
|
||||
const onChange =
|
||||
(Category: Category): CheckboxProps["onChange"] =>
|
||||
(e) => {
|
||||
const checked = e.target.checked;
|
||||
console.log(Category);
|
||||
console.log(languageObject(Category?.name));
|
||||
|
||||
if (checked) {
|
||||
|
||||
setFilter([...Filter, { name:languageObject(Category?.name),id:Category?.id,type:"sub_category", index: Filter.length }]);
|
||||
} else {
|
||||
const newArray = Filter?.filter((item: any) => item.name !== languageObject(Category?.name));
|
||||
setFilter(newArray);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
const {data:categories_data} = useGetBaseSubCategory()
|
||||
const categories = categories_data?.[0] as Category[] || [] ;
|
||||
|
||||
return (
|
||||
<div className="CheckboxFilter">
|
||||
{categories?.map((brand) => (
|
||||
<Checkbox
|
||||
checked={Filter.some((item: any) => languageObject(item?.name) === languageObject(brand?.name))}
|
||||
key={brand?.id}
|
||||
onChange={onChange(brand)}
|
||||
|
||||
>
|
||||
{languageObject(brand?.name)}
|
||||
</Checkbox>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BrandFilter;
|
||||
43
src/Components/Categories/WearingStyle.tsx
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
import React from "react";
|
||||
import { Checkbox } from "antd";
|
||||
import type { CheckboxProps } from "antd";
|
||||
import { useFilterStateState } from "../../state/Filter";
|
||||
|
||||
const WearingStyleFilter = () => {
|
||||
const { setFilter, Filter } = useFilterStateState();
|
||||
const onChange =
|
||||
(name: string): CheckboxProps["onChange"] =>
|
||||
(e) => {
|
||||
const checked = e.target.checked;
|
||||
|
||||
if (checked) {
|
||||
setFilter([...Filter, { name, index: Filter.length }]);
|
||||
} else {
|
||||
const newArray = Filter?.filter((item: any) => item.name !== name);
|
||||
setFilter(newArray);
|
||||
}
|
||||
};
|
||||
|
||||
const array_of_filter = [
|
||||
"WearingStyle1",
|
||||
"WearingStyle2",
|
||||
"WearingStyle3",
|
||||
"WearingStyle4",
|
||||
"WearingStyle5",
|
||||
];
|
||||
return (
|
||||
<div className="CheckboxFilter">
|
||||
{array_of_filter?.map((WearingStyle) => (
|
||||
<Checkbox
|
||||
checked={Filter.some((item: any) => item.name === WearingStyle)}
|
||||
key={WearingStyle}
|
||||
onChange={onChange(WearingStyle)}
|
||||
>
|
||||
{WearingStyle}
|
||||
</Checkbox>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default WearingStyleFilter;
|
||||
14
src/Components/Core/Media/Media.tsx
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { mediaData } from "../../../data/MediaData";
|
||||
|
||||
export default function Media() {
|
||||
return (
|
||||
<div className="Media">
|
||||
<h3>WE ARE SOCIAL</h3>
|
||||
<div className="media_box">
|
||||
{mediaData.map((item, index) => {
|
||||
return <img key={index} src={item.icons} alt="icon" />;
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
22
src/Components/Core/Search/SearchComponent.tsx
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
//@ts-ignore
|
||||
import searchIcons from "../../../../public/Activities/iconsSearch.svg";
|
||||
import useSearchQueryWithoutConfirm from "../../../Hooks/useSearchQueryWithoutConfirm";
|
||||
export default function SearchComponent() {
|
||||
const { inputValue, setInputValue } = useSearchQueryWithoutConfirm({
|
||||
queryParams: "search",
|
||||
});
|
||||
return (
|
||||
<div className="SearchComponent">
|
||||
<p>SEARCH</p>
|
||||
<input
|
||||
onChange={(e) => setInputValue(e.target.value)}
|
||||
value={inputValue}
|
||||
type="text"
|
||||
placeholder="Enter Your Keyword"
|
||||
style={{
|
||||
backgroundImage: `url(${searchIcons})`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
54
src/Components/HOC/AuthWithDrawer.tsx
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
import React, { useState } from 'react';
|
||||
import type { DrawerProps } from 'antd';
|
||||
import { Button, Drawer, Space } from 'antd';
|
||||
import { BsArrowLeft } from 'react-icons/bs';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import AuthTabs from '../Auth/AuthTabs';
|
||||
import useAuthState from '../../state/AuthState';
|
||||
import { FaUser } from 'react-icons/fa';
|
||||
import { LuUser2 } from "react-icons/lu";
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import SettingDrawer from './SettingDrawer';
|
||||
|
||||
|
||||
const WithDrawer: React.FC = () => {
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const [placement, setPlacement] = useState<DrawerProps['placement']>('right');
|
||||
const {t} = useTranslation();
|
||||
const {isAuthenticated} = useAuthState()
|
||||
const navigate = useNavigate()
|
||||
|
||||
return (
|
||||
<>
|
||||
<Space>
|
||||
{isAuthenticated?
|
||||
<div className='icon_navbar setting_drawer_container' ><SettingDrawer/> </div>
|
||||
:
|
||||
<Button onClick={()=>setOpen(true)} icon={t("Login / Sign Up")} className='MenuButton' type='primary' />
|
||||
}
|
||||
</Space>
|
||||
<Drawer
|
||||
title={""}
|
||||
placement={placement}
|
||||
closable={false}
|
||||
onClose={() => setOpen(false)}
|
||||
open={open}
|
||||
key={placement}
|
||||
width={600}
|
||||
className='AuthAithDrawer'
|
||||
style={{maxHeight:"90%"}}
|
||||
>
|
||||
<div className="auth_first_section">
|
||||
<span onClick={()=>setOpen(false)}><BsArrowLeft/> {t("Back")}</span>
|
||||
</div>
|
||||
<div className='auth_header'>
|
||||
<AuthTabs setOpen={setOpen} />
|
||||
</div>
|
||||
</Drawer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default WithDrawer;
|
||||
|
||||
108
src/Components/HOC/CartWithDrawer.tsx
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
import React, { useState, ReactNode, useEffect } from "react";
|
||||
import type { DrawerProps } from "antd";
|
||||
import { Badge, Button, Drawer, Space } from "antd";
|
||||
import CardItem from "../Cart/CardItem";
|
||||
import { BsArrowLeft, BsCart } from "react-icons/bs";
|
||||
import { Link } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useCartState } from "../../state/CartState";
|
||||
import { Currency } from "../../Layout/app/Const";
|
||||
import useAuthState from "../../state/AuthState";
|
||||
import { LocalStorageEnum } from "../../api/utils/LocalStorage";
|
||||
import { useAddOrder } from "../../api/order";
|
||||
import { toast } from "react-toastify";
|
||||
import { BiBasket } from "react-icons/bi";
|
||||
|
||||
const CartWithDrawer = () => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [placement, setPlacement] = useState<DrawerProps["placement"]>("right");
|
||||
const { t } = useTranslation();
|
||||
const { Cart, calculateTotalPrice, calculateTotalQuantity, removeCart } =
|
||||
useCartState();
|
||||
const { user } = useAuthState();
|
||||
const { mutate, isLoading, isSuccess } = useAddOrder();
|
||||
const products = Cart?.map((item: any) => ({
|
||||
quantity: item?.quantity,
|
||||
id: item?.id,
|
||||
}));
|
||||
|
||||
const addOrder = () => {
|
||||
mutate({
|
||||
email: user?.email,
|
||||
products: products,
|
||||
form: ["adding orders"],
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isSuccess) {
|
||||
|
||||
removeCart();
|
||||
toast.success("order added success");
|
||||
setOpen(false);
|
||||
}
|
||||
}, [isSuccess]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Space>
|
||||
<Badge className="Badge_Button" count={calculateTotalQuantity()}>
|
||||
<div onClick={() => setOpen(true)} className="icon_navbar">
|
||||
<BiBasket />
|
||||
</div>
|
||||
</Badge>
|
||||
</Space>
|
||||
|
||||
<Drawer
|
||||
title={""}
|
||||
placement={placement}
|
||||
closable={false}
|
||||
onClose={() => setOpen(false)}
|
||||
open={open}
|
||||
key={placement}
|
||||
width={550}
|
||||
style={{maxHeight:"90%"}}
|
||||
>
|
||||
<div className="cart_first_section">
|
||||
<span>{t("Cart")}</span>
|
||||
<span onClick={() => setOpen(false)}>
|
||||
<BsArrowLeft /> {t("Back To Shopping")}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="Drawer_Body">
|
||||
<div className="Card_Items">
|
||||
{Cart.map((item: any, index: number) => (
|
||||
<CardItem key={index} data={item} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
{Cart?.length > 0 ? (
|
||||
<div className="ViewCart_Button">
|
||||
<p>
|
||||
{t("Grand Total")}
|
||||
<br />
|
||||
<span>
|
||||
{" "}
|
||||
{calculateTotalPrice()} {Currency}{" "}
|
||||
</span>
|
||||
</p>
|
||||
<Button
|
||||
className="cart_checkout_button"
|
||||
onClick={() => addOrder()}
|
||||
type="primary"
|
||||
block
|
||||
>
|
||||
{t("Checkout")}
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<div></div>
|
||||
)}
|
||||
</div>
|
||||
</Drawer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default CartWithDrawer;
|
||||
26
src/Components/HOC/ChangeMode.tsx
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import React, { memo, useCallback } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TChangeMode, TModeIcon } from "../../types/ChangeMode";
|
||||
|
||||
|
||||
export const ChangeModeHelper = ({ ChangeModeFunction, ChangeFunctionAttr }:TChangeMode) => {
|
||||
const handleClick = useCallback(() => {
|
||||
ChangeModeFunction(ChangeFunctionAttr);
|
||||
}, [ChangeModeFunction, ChangeFunctionAttr]);
|
||||
|
||||
return handleClick;
|
||||
};
|
||||
|
||||
export const ChangeModeComp = ({onClickFunction, src, modeText,icon, isImage = true}:TModeIcon) =>{
|
||||
const { t } = useTranslation();
|
||||
const ModeContainer = memo(() => (
|
||||
<div className="MenuChange" onClick={onClickFunction}>
|
||||
{isImage
|
||||
? <img alt='ModeImage' src={src} width={20} height={20} />
|
||||
: icon
|
||||
}
|
||||
{t(modeText)}
|
||||
</div>
|
||||
));
|
||||
return <ModeContainer />;
|
||||
}
|
||||
56
src/Components/HOC/SearchWithDrawer.tsx
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import React, { useState, ReactNode } from 'react';
|
||||
import type { DrawerProps } from 'antd';
|
||||
import { Badge, Button, Drawer, Space } from 'antd';
|
||||
import CardItem from '../Cart/CardItem';
|
||||
import { BsArrowLeft, BsCart, BsSearch } from 'react-icons/bs';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { ShoppingCartOutlined } from '@ant-design/icons';
|
||||
import { useCartData } from '../../Redux/DispatchData';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { TiDeleteOutline } from "react-icons/ti";
|
||||
import SearchButton from '../Utils/Search/SearchButton';
|
||||
import { GoClock } from "react-icons/go";
|
||||
import { FiDelete } from "react-icons/fi";
|
||||
import { RiSearch2Line, RiSearchLine } from "react-icons/ri";
|
||||
|
||||
|
||||
|
||||
const SearchWithDrawer = () => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [placement, setPlacement] = useState<DrawerProps['placement']>('right');
|
||||
const { DataCart,count} = useCartData()
|
||||
const {t} = useTranslation();
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<Space>
|
||||
<div onClick={()=>setOpen(true)} className="icon_navbar">
|
||||
<RiSearchLine />
|
||||
</div>
|
||||
</Space>
|
||||
|
||||
<Drawer
|
||||
title={""}
|
||||
placement={placement}
|
||||
closable={false}
|
||||
onClose={() => setOpen(false)}
|
||||
open={open}
|
||||
key={placement}
|
||||
width ={700}
|
||||
style={{maxHeight:"40%"}}
|
||||
>
|
||||
<div className="search_first_section">
|
||||
<SearchButton/>
|
||||
<span className='delete_icon' onClick={()=>setOpen(false)}><TiDeleteOutline/></span>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</Drawer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SearchWithDrawer;
|
||||
|
||||
73
src/Components/HOC/SettingDrawer.tsx
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
import React, { useState } from 'react';
|
||||
import type { DrawerProps } from 'antd';
|
||||
import { Drawer, Space } from 'antd';
|
||||
import { BsArrowLeft } from 'react-icons/bs';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaShoppingBag } from 'react-icons/fa';
|
||||
import { LuUser2 } from "react-icons/lu";
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { CgProfile } from 'react-icons/cg';
|
||||
import SettingDrawerSingleTab from '../Setting/SettingDrawerSingleTab';
|
||||
import { IoMdHeartEmpty } from 'react-icons/io';
|
||||
import { CiLogout } from 'react-icons/ci';
|
||||
import { LocalStorageEnum } from '../../api/utils/LocalStorage';
|
||||
import useAuthState from '../../state/AuthState';
|
||||
|
||||
|
||||
const SettingDrawer: React.FC = () => {
|
||||
|
||||
const {t} = useTranslation();
|
||||
const SettingDrawerData = [
|
||||
{ tabName: "Orders", icon: FaShoppingBag },
|
||||
{ tabName: "Wish List", icon: IoMdHeartEmpty },
|
||||
];
|
||||
|
||||
const {logout} = useAuthState()
|
||||
const [open, setOpen] = useState(false);
|
||||
const [placement, setPlacement] = useState<DrawerProps['placement']>('right');
|
||||
const User = JSON.parse(localStorage.getItem(LocalStorageEnum.USER_KEY) ?? "");
|
||||
|
||||
return (
|
||||
<>
|
||||
<Space>
|
||||
<div className='icon_navbar'onClick={()=>setOpen(true)}><LuUser2 /></div>
|
||||
|
||||
</Space>
|
||||
<Drawer
|
||||
title={""}
|
||||
placement={placement}
|
||||
closable={false}
|
||||
onClose={() => setOpen(false)}
|
||||
open={open}
|
||||
key={placement}
|
||||
width={270}
|
||||
style={{maxHeight:"44%"}}
|
||||
>
|
||||
<div className="setting_drawer_first_section">
|
||||
<p>{t("Profile")}</p>
|
||||
<span onClick={()=>setOpen(false)}><BsArrowLeft/> {t("Back")}</span>
|
||||
</div>
|
||||
<div className='setting_drawer_body'>
|
||||
<div className='setting_drawer_tab'>
|
||||
<CgProfile/>
|
||||
<div>
|
||||
<h4>{User?.name}</h4>
|
||||
<h4>{User?.email}</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='setting_drawer_tabs'>
|
||||
{SettingDrawerData.map((data, index) => (
|
||||
<SettingDrawerSingleTab onCLick={() => setOpen(false)} key={index} Icon={data.icon} tabName={data.tabName} />
|
||||
))}
|
||||
<SettingDrawerSingleTab onCLick={logout} link='/' Icon={CiLogout} tabName={"Logout"} />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</Drawer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SettingDrawer;
|
||||
|
||||
28
src/Components/HOC/WithFormik.tsx
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import { Form, Formik } from "formik";
|
||||
import React from "react";
|
||||
import * as Yup from "yup";
|
||||
|
||||
const WithFormik = ({ children }: any) => {
|
||||
const getInitialValues = () => {
|
||||
return { name: "" };
|
||||
};
|
||||
const getValidationSchema = () => {
|
||||
return Yup.object().shape({});
|
||||
};
|
||||
const handleSubmit = () => {};
|
||||
return (
|
||||
<div className="WithFormik">
|
||||
{
|
||||
<Formik
|
||||
onSubmit={handleSubmit}
|
||||
initialValues={getInitialValues}
|
||||
validationSchema={getValidationSchema}
|
||||
>
|
||||
{(formik) => <Form>{children}</Form>}
|
||||
</Formik>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default WithFormik;
|
||||
32
src/Components/HOC/withVisibale.tsx
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
// This is your Layout Component
|
||||
const Visibale = ({ children, ...props }: any) => {
|
||||
const ref = useRef<any>();
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const observer = new IntersectionObserver(([entry]) => {
|
||||
if (isVisible === false) {
|
||||
setIsVisible(entry.isIntersecting);
|
||||
}
|
||||
});
|
||||
if (ref.current) {
|
||||
observer.observe(ref.current);
|
||||
}
|
||||
return () => {
|
||||
if (ref.current) {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
observer.unobserve(ref.current);
|
||||
}
|
||||
};
|
||||
}, [isVisible]); // Empty array ensures effect is only run on mount and unmount
|
||||
|
||||
return (
|
||||
<div ref={ref} {...props}>
|
||||
{isVisible && children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Visibale;
|
||||
18
src/Components/Home/BatteryLife.tsx
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const BatteryLife = () => {
|
||||
const {t} = useTranslation();
|
||||
return (
|
||||
<div className="BatteryLife">
|
||||
<div>
|
||||
<h1>{t("Up to 20 hours battery life")}</h1>
|
||||
<p>{t("Enjoy up to 20 hours of listening, enough time to pore through this entire playlist. So you can keep the music — or the quiet — going all day long. And when it finally runs down, a quick 15-minute charge gives you another 2.5 hours")}.
|
||||
</p>
|
||||
</div>
|
||||
<img src="/Home/BatteryLife.png" alt="" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BatteryLife;
|
||||
25
src/Components/Home/BestSale.tsx
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import { useNavigate } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import ProductSwiper from "./ProductSwiper";
|
||||
|
||||
const Products = () => {
|
||||
const {t} = useTranslation();
|
||||
|
||||
const navigate = useNavigate();
|
||||
const handelSeeAll = () => {
|
||||
navigate(`/categories?type=best_sale`);
|
||||
};
|
||||
return (
|
||||
<div className="Products">
|
||||
<header>
|
||||
<h1>{t("Best Sale")}</h1>
|
||||
<h5 className="pointer" onClick={handelSeeAll}> {t("View all")} </h5>
|
||||
</header>
|
||||
<main className="ProductCards">
|
||||
<ProductSwiper/>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Products;
|
||||
22
src/Components/Home/BoseHeadphones.tsx
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { GoArrowUpRight } from "react-icons/go";
|
||||
|
||||
const BoseHeadphones = () => {
|
||||
const {t} = useTranslation();
|
||||
return (
|
||||
<div className="BoseHeadphones">
|
||||
<img src="/Home/Bose_Headphones.png" alt="" />
|
||||
<div>
|
||||
<h6>{t("Bose Headphones")}</h6>
|
||||
<h1>{t("Smarter than your average headphones")}</h1>
|
||||
<button className="button">
|
||||
{t("Shop now")}
|
||||
<GoArrowUpRight />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BoseHeadphones;
|
||||
67
src/Components/Home/CategoriesSlider.tsx
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
// import Swiper core and required modules
|
||||
import { Navigation, A11y } from "swiper/modules";
|
||||
|
||||
import { Swiper, SwiperSlide } from "swiper/react";
|
||||
|
||||
// Import Swiper styles
|
||||
import "swiper/css";
|
||||
import "swiper/css/navigation";
|
||||
import "swiper/css/pagination";
|
||||
import "swiper/css/scrollbar";
|
||||
import { useGetCategories } from "../../api/Categories";
|
||||
import { Category } from "../../types/item";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { addBaseUrlToSrc } from "../../utils/addBaseUrlToSrc";
|
||||
|
||||
const CategoriesSlider = () => {
|
||||
const { data } = useGetCategories();
|
||||
const categories = (data?.categories as Category[]) || ([] as []);
|
||||
const navigate = useNavigate();
|
||||
const handelNavigate = (data: Category) => {
|
||||
navigate(`/categories?category=${data?.id}`);
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div className="CategoriesSlider">
|
||||
<Swiper
|
||||
modules={[Navigation, A11y]}
|
||||
spaceBetween={20}
|
||||
slidesPerView={5}
|
||||
navigation
|
||||
breakpoints={{
|
||||
320: {
|
||||
slidesPerView: 1,
|
||||
},
|
||||
480: {
|
||||
slidesPerView: 2,
|
||||
},
|
||||
640: {
|
||||
slidesPerView: 3,
|
||||
},
|
||||
768: {
|
||||
slidesPerView: 3,
|
||||
},
|
||||
1024: {
|
||||
slidesPerView: 4,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{categories?.map((item: Category, index: number) => {
|
||||
return (
|
||||
<SwiperSlide key={index}>
|
||||
<div className="CategoriesSlider_image">
|
||||
<img
|
||||
onClick={() => handelNavigate(item)}
|
||||
src={addBaseUrlToSrc(item?.photo)}
|
||||
alt={`category ${index + 1}`}
|
||||
/>
|
||||
</div>
|
||||
</SwiperSlide>
|
||||
);
|
||||
})}
|
||||
</Swiper>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
export default CategoriesSlider;
|
||||
23
src/Components/Home/HeroSection.tsx
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const HeroSection = () => {
|
||||
const [t] = useTranslation();
|
||||
return (
|
||||
<div className="HeroSection">
|
||||
<div>
|
||||
<h1>{t("Quite Comfort 35 wireless headphones II")}</h1>
|
||||
|
||||
<div>
|
||||
{/* <h3> $229.50 </h3> */}
|
||||
<button className="button">{t("Buy Now")}</button>
|
||||
</div>
|
||||
</div>
|
||||
<span>
|
||||
<img src="/Home/p1.png" alt="" />
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default HeroSection;
|
||||
11
src/Components/Home/NoiseCancellation.tsx
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import React from "react";
|
||||
|
||||
const NoiseCancellation = () => {
|
||||
return (
|
||||
<div className="NoiseCancellation">
|
||||
<img src="/Home/Noise_Cancellation.svg" alt="" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default NoiseCancellation;
|
||||
18
src/Components/Home/OnSaleCard.tsx
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import React from "react";
|
||||
|
||||
const OnSaleCard = () => {
|
||||
return (
|
||||
<div className="OnSaleCard">
|
||||
<img src="/Home/p1.png" alt="" />
|
||||
<h4>Apple Airphone Pro2</h4>
|
||||
<div>
|
||||
{" "}
|
||||
<p>$49.00</p>
|
||||
<p> $34.30 </p>{" "}
|
||||
</div>
|
||||
<span>30%</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default OnSaleCard;
|
||||
17
src/Components/Home/OnSaleSlider.tsx
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import React from "react";
|
||||
import OnSaleCard from "./OnSaleCard";
|
||||
|
||||
const OnSaleSlider = () => {
|
||||
return (
|
||||
<div className="OnSaleSlider">
|
||||
<OnSaleCard />
|
||||
<OnSaleCard />
|
||||
<OnSaleCard />
|
||||
<OnSaleCard />
|
||||
<OnSaleCard />
|
||||
<OnSaleCard />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default OnSaleSlider;
|
||||
19
src/Components/Home/PerfectSound.tsx
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const PerfectSound = () => {
|
||||
const {t} = useTranslation();
|
||||
return (
|
||||
<div className="PerfectSound">
|
||||
<div>
|
||||
<h1>{t("Perfect sound immersive world")}</h1>
|
||||
<p>
|
||||
{t("QuietComfort 35 wireless headphones II are engineered with renowned noise cancellation. With the Google Assistant and Amazon Alexa built-in, you have instant access to millions of songs, playlists and more—hands free")}.
|
||||
</p>
|
||||
</div>
|
||||
<img src="/Home/PerfectSound.png" alt="" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PerfectSound;
|
||||
17
src/Components/Home/PremiumDesign.tsx
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const PremiumDesign = () => {
|
||||
const {t} = useTranslation();
|
||||
return (
|
||||
<div className="PremiumDesign">
|
||||
<h1>{t("Premium Design")}</h1>
|
||||
<p>
|
||||
{t("When you want to take your music anywhere, you need headphones built to keep up. With impact-resistant materials, glass-filled nylon, and corrosion-resistant stainless steel, they’re engineered to survive life on the go")}.
|
||||
</p>
|
||||
<img src="/Home/HeadPhone.png" alt="" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PremiumDesign;
|
||||
120
src/Components/Home/ProductCard.tsx
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
import React, { useEffect } from "react";
|
||||
import { FaHeart, FaStar } from "react-icons/fa";
|
||||
import { Currency } from "../../Layout/app/Const";
|
||||
import { FaCartPlus } from "react-icons/fa6";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import CustomImage from "../../ui/CustomImage";
|
||||
import { languageObject } from "../../utils/languageObject";
|
||||
import { Product } from "../../types/item";
|
||||
import { useAddFavorite, useDeleteFavorite } from "../../api/Favorite";
|
||||
import useAuthState from "../../state/AuthState";
|
||||
import { toast } from "react-toastify";
|
||||
import { useCartState } from "../../state/CartState";
|
||||
import { useQueryClient } from "react-query";
|
||||
|
||||
const ProductCard = ({ item }: { item: Product }) => {
|
||||
const [t] = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const { isAuthenticated } = useAuthState();
|
||||
// console.log(item);
|
||||
|
||||
const handel_click = (id: number) => {
|
||||
console.log(id);
|
||||
|
||||
navigate(`/product/${id}`);
|
||||
};
|
||||
|
||||
const { mutate: addToFavorite, isSuccess: Add } = useAddFavorite();
|
||||
const { mutate: deleteToFavorite, isSuccess: Delete } = useDeleteFavorite();
|
||||
const price = Number(item?.price);
|
||||
const discountAmount = 10;
|
||||
const oldPrice = (Number(price) / 0.9).toFixed(2);
|
||||
|
||||
const min = 4.5;
|
||||
const max = 5;
|
||||
const randomRate = (Math.random() * (max - min) + min)?.toFixed(1);
|
||||
|
||||
const { Cart, setCart } = useCartState();
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const handelChangeFavorite = (item: Product) => {
|
||||
if (!isAuthenticated) {
|
||||
toast.error("sorry you need to be authenticated");
|
||||
return;
|
||||
}
|
||||
|
||||
if (item?.favorite) {
|
||||
|
||||
deleteToFavorite({
|
||||
id: item?.id,
|
||||
});
|
||||
} else {
|
||||
addToFavorite({
|
||||
id: item?.id,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (Add) {
|
||||
toast.success("added success");
|
||||
queryClient.invalidateQueries("mainProduct");
|
||||
}
|
||||
}, [Add]);
|
||||
useEffect(() => {
|
||||
if (Delete) {
|
||||
toast.success("removed success");
|
||||
queryClient.invalidateQueries("mainProduct");
|
||||
}
|
||||
}, [Delete]);
|
||||
|
||||
const handelAddToCart = (item: Product) => {
|
||||
if (!isAuthenticated) {
|
||||
|
||||
toast.error("sorry you need to be authenticated");
|
||||
return;
|
||||
}
|
||||
setCart(item);
|
||||
|
||||
|
||||
toast.success(`${languageObject(item?.name)}` + " added to cart");
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div className="ProductCard">
|
||||
<CustomImage src={item?.main_photo} onClick={() => handel_click(item?.base_product_id)} />
|
||||
<h4>{languageObject(item?.name)}</h4>
|
||||
<p>
|
||||
{" "}
|
||||
{Currency} {oldPrice}{" "}
|
||||
</p>
|
||||
<div>
|
||||
<p>
|
||||
{" "}
|
||||
{Currency} {price}
|
||||
</p>
|
||||
<p>
|
||||
{" "}
|
||||
{randomRate} <FaStar />
|
||||
</p>
|
||||
</div>
|
||||
<span>{discountAmount}%</span>
|
||||
|
||||
<article>
|
||||
<button className="button" onClick={() => handelAddToCart(item)}>
|
||||
<FaCartPlus />
|
||||
{t("add to cart")}
|
||||
</button>
|
||||
<FaHeart
|
||||
onClick={() => handelChangeFavorite(item)}
|
||||
className={item?.favorite ? "" : "not_favorite"}
|
||||
/>
|
||||
</article>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductCard;
|
||||
58
src/Components/Home/ProductSwiper.tsx
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
import React, { useRef, useState } from 'react';
|
||||
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||
import 'swiper/css';
|
||||
import 'swiper/css/free-mode';
|
||||
import 'swiper/css/pagination';
|
||||
import ProductCard from './ProductCard';
|
||||
import { Product } from '../../types/item';
|
||||
import { useGetBaseProduct } from '../../api/baseProduct';
|
||||
import { A11y, Autoplay, Navigation, Pagination, Scrollbar } from 'swiper/modules';
|
||||
import { Spin } from 'antd';
|
||||
|
||||
|
||||
|
||||
const ProductSwiper = () => {
|
||||
const language = localStorage.getItem('language') ;
|
||||
console.log(language);
|
||||
|
||||
const [swiperDirection, setSwiperDirection] = useState(language === "ar" ? "rtl" : "ltr");
|
||||
const swiperRef = useRef<any>(null);
|
||||
|
||||
const { data, isLoading } = useGetBaseProduct({
|
||||
mostOrderd: "asc",
|
||||
});
|
||||
const BaseProducts = (data?.products as Product[]) || ([] as []);
|
||||
|
||||
return (
|
||||
<div className='productSwiper'>
|
||||
<Swiper
|
||||
dir={swiperDirection}
|
||||
slidesPerView={5}
|
||||
spaceBetween={50}
|
||||
breakpoints={{
|
||||
0: { slidesPerView: 1 },
|
||||
400: { slidesPerView: 2 },
|
||||
600: { slidesPerView: 2 },
|
||||
900: { slidesPerView: 4 },
|
||||
1200: { slidesPerView: 4 },
|
||||
1500: { slidesPerView: 4 },
|
||||
}}
|
||||
modules={[Navigation, Pagination, Scrollbar, A11y, Autoplay]}
|
||||
pagination={{ clickable: true }}
|
||||
className="mySwiper"
|
||||
onSwiper={(swiper:any) => (swiperRef.current = swiper)} // Store swiper instance
|
||||
>
|
||||
{
|
||||
isLoading ? <Spin/> :
|
||||
BaseProducts?.map((item:Product, index:number) => (
|
||||
<SwiperSlide key={index}>
|
||||
<ProductCard key={index} item={item} />
|
||||
</SwiperSlide>
|
||||
))
|
||||
}
|
||||
</Swiper>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ProductSwiper;
|
||||
26
src/Components/Home/Products.tsx
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import { useNavigate } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import ProductSwiper from "./ProductSwiper";
|
||||
|
||||
const Products = () => {
|
||||
const {t} = useTranslation();
|
||||
|
||||
const navigate = useNavigate();
|
||||
const handelSeeAll = () => {
|
||||
navigate(`/categories?type=new_product`);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="Products">
|
||||
<header>
|
||||
<h1>{t("New Products")}</h1>
|
||||
<h5 className="pointer" onClick={handelSeeAll}> {t("View all")} </h5>
|
||||
</header>
|
||||
<main className="ProductCards">
|
||||
<ProductSwiper/>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Products;
|
||||
31
src/Components/Home/ProductsOnSale.tsx
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import React from "react";
|
||||
import OnSaleSlider from "./OnSaleSlider";
|
||||
import { IoIosArrowBack } from "react-icons/io";
|
||||
import { IoIosArrowForward } from "react-icons/io";
|
||||
|
||||
const ProductsOnSale = () => {
|
||||
return (
|
||||
<div className="ProductsOnSale">
|
||||
<span>
|
||||
<span>
|
||||
<h3>Products On Sale</h3>
|
||||
<p> Shop Now! </p>
|
||||
</span>
|
||||
<button>View all </button>
|
||||
</span>
|
||||
|
||||
<OnSaleSlider />
|
||||
<div className="pagination">
|
||||
<div>
|
||||
{" "}
|
||||
<IoIosArrowBack />{" "}
|
||||
</div>
|
||||
<div>
|
||||
<IoIosArrowForward />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductsOnSale;
|
||||
19
src/Components/Setting/SettingDrawerSingleTab.tsx
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import React from 'react'
|
||||
import { CgProfile } from 'react-icons/cg'
|
||||
import { IconBaseProps } from 'react-icons/lib'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
const SettingDrawerSingleTab = ({tabName, Icon,onCLick, link = "/settings"}:{tabName:string, Icon:any,onCLick:any, link?:string}) => {
|
||||
return (
|
||||
<Link to={link}>
|
||||
<div onClick={onCLick} className='setting_drawer_tab without_primary'>
|
||||
<Icon/>
|
||||
<div>
|
||||
<h4>{tabName}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
export default SettingDrawerSingleTab
|
||||
16
src/Components/Setting/SettingTabHeader.tsx
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
const SettingTabHeader = ({title,text}:{title:string ,text:string}) => {
|
||||
|
||||
const {t} = useTranslation();
|
||||
|
||||
return (
|
||||
<div className='SettingTabHeader'>
|
||||
<h4>{t(title)}</h4>
|
||||
<p>{t(text)}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SettingTabHeader
|
||||
95
src/Components/Setting/SettingTabs.tsx
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
import React, { useState } from 'react';
|
||||
import type { TabsProps } from 'antd';
|
||||
import { Tabs } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { CgProfile } from "react-icons/cg";
|
||||
import { IoCartOutline } from "react-icons/io5";
|
||||
import { IoMdHeartEmpty } from "react-icons/io";
|
||||
import { GrShieldSecurity,GrContactInfo } from "react-icons/gr";
|
||||
import { CiLogout } from "react-icons/ci";
|
||||
import ContactTab from './Tabs/ContactTab';
|
||||
import ChangePasswordTab from './Tabs/ChangePasswordTab';
|
||||
import OrderTab from './Tabs/OrderTab';
|
||||
import WishlistTab from './Tabs/WishlistTab';
|
||||
import { useWindowResize } from '../../Hooks/useWindowResize';
|
||||
import useAuthState from '../../state/AuthState';
|
||||
import { LocalStorageEnum } from '../../api/utils/LocalStorage';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
type TabPosition = 'left' | 'right' | 'top' | 'bottom';
|
||||
|
||||
const SettingTabs: React.FC = () => {
|
||||
const {windowWidth} = useWindowResize()
|
||||
|
||||
const [tabPosition, setTabPosition] = useState<TabPosition>(windowWidth < 800 ? 'top' : 'left');
|
||||
const {t} = useTranslation();
|
||||
const {logout} = useAuthState()
|
||||
|
||||
const name = JSON.parse(localStorage.getItem(LocalStorageEnum?.USER_KEY) ?? '')?.name
|
||||
const handleLogout = () =>{
|
||||
logout()
|
||||
toast.success(t("you logged out successfully"))
|
||||
}
|
||||
const items: TabsProps['items'] = [
|
||||
{
|
||||
key: '1',
|
||||
label: name,
|
||||
icon: <CgProfile/>,
|
||||
disabled: true,
|
||||
},
|
||||
// {
|
||||
// key: '2',
|
||||
// label: t('Personal Data'),
|
||||
// children: <PersonalDataTabs/>,
|
||||
// icon: <TbUserEdit/>
|
||||
// },
|
||||
{
|
||||
key: '3',
|
||||
label: t('Orders'),
|
||||
children: <OrderTab/>,
|
||||
icon: <IoCartOutline/>
|
||||
},
|
||||
{
|
||||
key: '4',
|
||||
label: t('Wishlist'),
|
||||
children: <WishlistTab/>,
|
||||
icon: <IoMdHeartEmpty />
|
||||
},
|
||||
{
|
||||
key: '5',
|
||||
label: t('Security and access'),
|
||||
children: <ChangePasswordTab/>,
|
||||
icon: <GrShieldSecurity/>
|
||||
|
||||
},
|
||||
{
|
||||
key: '6',
|
||||
label: t('Contact Us'),
|
||||
children: <ContactTab className='contact_tab'/>,
|
||||
icon: <GrContactInfo/>
|
||||
|
||||
},
|
||||
{
|
||||
key: '7',
|
||||
label: <Link to={"/"}><span onClick={handleLogout}>{t('Logout')}</span></Link>,
|
||||
icon: <CiLogout/>
|
||||
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tabs
|
||||
tabPosition={tabPosition}
|
||||
addIcon
|
||||
items={items}
|
||||
className='tabs'
|
||||
defaultActiveKey='2'
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SettingTabs;
|
||||
51
src/Components/Setting/Tabs/ChangePasswordTab.tsx
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import React from 'react'
|
||||
import { Formik, Form, Field } from 'formik';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaKey } from "react-icons/fa";
|
||||
import { Input } from 'antd';
|
||||
import SettingTabHeader from '../SettingTabHeader';
|
||||
import { Button } from 'react-bootstrap';
|
||||
import { useChangePassword } from '../../../api/auth';
|
||||
|
||||
|
||||
const ChangePasswordTab = () => {
|
||||
const [t] = useTranslation();
|
||||
|
||||
const {mutate} = useChangePassword()
|
||||
const handelSubmit = (values: any) => {
|
||||
mutate({ ...values });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='ChangePasswordTab'>
|
||||
<SettingTabHeader title='Security settings' text='Change password and phone number'/>
|
||||
<Formik
|
||||
initialValues={{ password: null }}
|
||||
onSubmit={handelSubmit}
|
||||
>
|
||||
<Form className='personl_data_form'>
|
||||
<div className='form-outline mb-4 feild_container'>
|
||||
<Field
|
||||
placeholder={t('Change Password')}
|
||||
as={Input}
|
||||
type='text'
|
||||
id='password'
|
||||
name='password'
|
||||
prefix={<FaKey />}
|
||||
className='form-control form-control-lg personl_data_feild'
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Button className='w-100 personl_data_form_button' type="submit">
|
||||
{t('Submit')}
|
||||
</Button>
|
||||
|
||||
</Form>
|
||||
|
||||
</Formik>
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
export default ChangePasswordTab
|
||||
125
src/Components/Setting/Tabs/ContactTab.tsx
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import { FaInstagram, FaLinkedinIn, FaTwitter } from "react-icons/fa6";
|
||||
import { Button, Form } from 'react-bootstrap';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { toast } from 'react-toastify';
|
||||
import { IoMailOutline,IoEarthOutline } from "react-icons/io5";
|
||||
import { FiPhone } from "react-icons/fi";
|
||||
import { FaFacebookF } from "react-icons/fa";
|
||||
import { useAddSupportMessage } from '../../../api/supportMessages';
|
||||
|
||||
const ContactTab = ({className=""}: {className?: string }) => {
|
||||
const form = useRef<any>(null);
|
||||
const { t } = useTranslation();
|
||||
const {mutate,isSuccess,isLoading} = useAddSupportMessage()
|
||||
|
||||
const SoicalInfo: { icon: any; text: string }[] = [
|
||||
{
|
||||
icon: <IoMailOutline/>,
|
||||
text: "info@yourdomain.com",
|
||||
},
|
||||
{
|
||||
icon: <FiPhone/> ,
|
||||
text: "+1 (378) 400-1234",
|
||||
},
|
||||
{
|
||||
icon: <IoEarthOutline/>,
|
||||
text: "www.yourdomain.com",
|
||||
},
|
||||
];
|
||||
|
||||
const SoicalIcons: { icon: any; }[] = [
|
||||
{
|
||||
icon: <FaFacebookF/>,
|
||||
},
|
||||
{
|
||||
icon: <FaTwitter /> ,
|
||||
},
|
||||
{
|
||||
icon: <FaLinkedinIn />,
|
||||
},
|
||||
{
|
||||
icon: <FaInstagram />,
|
||||
},
|
||||
];
|
||||
|
||||
const [Name , setName] = useState('')
|
||||
const [Email , setEmail] = useState('')
|
||||
const [Message , setMessage] = useState('')
|
||||
|
||||
const sendEmail = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
|
||||
|
||||
|
||||
if(!Name || !Email || !Message ){
|
||||
toast.error(t("please_fill_all_input"))
|
||||
}else{
|
||||
}
|
||||
mutate({
|
||||
name:Name,
|
||||
email:Email,
|
||||
message:Message
|
||||
})
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if(isSuccess){
|
||||
setMessage('')
|
||||
setName('')
|
||||
setEmail('')
|
||||
toast.success(t("Send Successfully"))
|
||||
|
||||
}
|
||||
}, [isSuccess])
|
||||
|
||||
|
||||
return (
|
||||
<div className={`${className} contact_last_section`}>
|
||||
<div className='left'>
|
||||
<div className='social_info'>
|
||||
{
|
||||
SoicalInfo.map((item)=>(
|
||||
<div className='Single_info'>
|
||||
<span>{item.icon}</span>
|
||||
<p>{item.text}</p>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<div className='icons'>
|
||||
{
|
||||
SoicalIcons.map((item)=>(
|
||||
<span>{item.icon}</span>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='right'>
|
||||
<Form ref={form} onSubmit={sendEmail} className='contact_form'>
|
||||
<Form.Group controlId="formName">
|
||||
<Form.Control type="text" name="to_name" placeholder={t('* Your Name')} value={Name} onChange={(e)=>setName(e.target.value)} required autoFocus />
|
||||
</Form.Group>
|
||||
<Form.Group controlId="formEmail">
|
||||
<Form.Control type="email" name="from_name" placeholder={t('* Email')} value={Email} onChange={(e)=>setEmail(e.target.value)} required/>
|
||||
</Form.Group>
|
||||
<Form.Group controlId="formMessage">
|
||||
<Form.Control as="textarea" rows={6} name="message" placeholder={t('Message')}value={Message} onChange={(e)=>setMessage(e.target.value)} required />
|
||||
</Form.Group>
|
||||
<div className='button_container'>
|
||||
<Button disabled={isLoading} className='mt-4 w-100 button' type="submit">
|
||||
{t('Submit')}
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ContactTab
|
||||