done
23
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
;
|
||||||
|
# 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*
|
||||||
13
.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"aldeen",
|
||||||
|
"currentlanguage",
|
||||||
|
"Datepicker",
|
||||||
|
"formik",
|
||||||
|
"Karim",
|
||||||
|
"queryqlent",
|
||||||
|
"setstyle",
|
||||||
|
"szhsin",
|
||||||
|
"Viewelement"
|
||||||
|
]
|
||||||
|
}
|
||||||
48
db.json
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
{
|
||||||
|
"example":[
|
||||||
|
{
|
||||||
|
"type": "Bernadette O'Reilly",
|
||||||
|
"href": "/Dennis Von",
|
||||||
|
"data": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"count": 48,
|
||||||
|
"id": "10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Jeanette",
|
||||||
|
"href": "/Patsy",
|
||||||
|
"data": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"count": 32613,
|
||||||
|
"id": "12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Marion",
|
||||||
|
"href": "/MissLuis",
|
||||||
|
"data": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"count": 71846,
|
||||||
|
"id": "13"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Jean",
|
||||||
|
"href": "/Georgia",
|
||||||
|
"data": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"count": 8268,
|
||||||
|
"id": "14"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"email": "admin@adamin.com",
|
||||||
|
"password": "password",
|
||||||
|
"token": "token"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
20
index.html
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content="Web site created using create-react-app"
|
||||||
|
/>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
||||||
|
|
||||||
|
<title>React-ts</title>
|
||||||
|
</head>
|
||||||
|
<script type="module" src="/src/index.tsx"></script>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
34650
package-lock.json
generated
Normal file
104
package.json
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
{
|
||||||
|
"name": "my-app",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@ant-design/icons": "^5.2.6",
|
||||||
|
"@emailjs/browser": "^4.3.3",
|
||||||
|
"@reduxjs/toolkit": "^1.9.7",
|
||||||
|
"@szhsin/react-menu": "github:szhsin/react-menu",
|
||||||
|
"@testing-library/jest-dom": "^5.17.0",
|
||||||
|
"@testing-library/react": "^13.4.0",
|
||||||
|
"@testing-library/user-event": "^13.5.0",
|
||||||
|
"@types/jest": "^27.5.2",
|
||||||
|
"@types/node": "^16.18.60",
|
||||||
|
"@types/react": "^18.2.33",
|
||||||
|
"@types/react-dom": "^18.2.14",
|
||||||
|
"@types/react-slick": "^0.23.12",
|
||||||
|
"@wojtekmaj/react-daterange-picker": "^5.4.4",
|
||||||
|
"antd": "^5.11.1",
|
||||||
|
"apexcharts": "^3.44.0",
|
||||||
|
"axios": "^1.6.0",
|
||||||
|
"bootstrap": "^5.3.2",
|
||||||
|
"chart.js": "^4.4.0",
|
||||||
|
"dayjs": "^1.11.10",
|
||||||
|
"formik": "^2.4.5",
|
||||||
|
"i18next": "^23.6.0",
|
||||||
|
"i18next-browser-languagedetector": "^7.1.0",
|
||||||
|
"json-server": "^0.17.4",
|
||||||
|
"mdb-react-ui-kit": "^7.2.0",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-alice-carousel": "^2.8.0",
|
||||||
|
"react-bootstrap": "^2.9.1",
|
||||||
|
"react-bootstrap-sweetalert": "^5.2.0",
|
||||||
|
"react-chartjs-2": "^5.2.0",
|
||||||
|
"react-confirm-alert": "^3.0.6",
|
||||||
|
"react-data-table-component": "^7.5.4",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"react-feather": "^2.0.10",
|
||||||
|
"react-i18next": "^13.3.1",
|
||||||
|
"react-icons": "^4.11.0",
|
||||||
|
"react-id-swiper": "^4.0.0",
|
||||||
|
"react-multi-carousel": "^2.8.4",
|
||||||
|
"react-player": "^2.16.0",
|
||||||
|
"react-query": "^3.39.3",
|
||||||
|
"react-redux": "^8.1.3",
|
||||||
|
"react-responsive-carousel": "^3.2.23",
|
||||||
|
"react-router-dom": "^6.18.0",
|
||||||
|
"react-scripts": "5.0.1",
|
||||||
|
"react-select-country-list": "^2.2.3",
|
||||||
|
"react-slick": "^0.29.0",
|
||||||
|
"react-tabs": "^6.0.2",
|
||||||
|
"react-toastify": "^9.1.3",
|
||||||
|
"react-toggle": "^4.1.3",
|
||||||
|
"react-transition-group": "^4.4.5",
|
||||||
|
"react-verification-code-input": "^1.2.9",
|
||||||
|
"reactstrap": "^9.2.0",
|
||||||
|
"sass": "^1.69.5",
|
||||||
|
"slick-carousel": "^1.8.1",
|
||||||
|
"source-map-explorer": "^2.5.3",
|
||||||
|
"styled-components": "5.3.3",
|
||||||
|
"swiper": "^11.0.5",
|
||||||
|
"typescript": "^4.9.5",
|
||||||
|
"web-vitals": "^2.1.4",
|
||||||
|
"yup": "^1.3.2",
|
||||||
|
"zustand": "^4.4.5"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "vite",
|
||||||
|
"build": "vite build",
|
||||||
|
"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 ",
|
||||||
|
"analyze": "source-map-explorer 'build/static/js/*.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": {
|
||||||
|
"@vitejs/plugin-react": "^4.3.0",
|
||||||
|
"unplugin-auto-import": "^0.17.6",
|
||||||
|
"vite": "^5.2.12"
|
||||||
|
}
|
||||||
|
}
|
||||||
12898
pnpm-lock.yaml
Normal file
BIN
public/About/About.png
Normal file
|
After Width: | Height: | Size: 485 KiB |
104
public/About/about.svg
Normal file
|
After Width: | Height: | Size: 12 MiB |
BIN
public/App/BigGmap.png
Normal file
|
After Width: | Height: | Size: 435 KiB |
BIN
public/App/CheckMark.png
Normal file
|
After Width: | Height: | Size: 600 B |
BIN
public/App/product.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/App/productManual.png
Normal file
|
After Width: | Height: | Size: 556 B |
BIN
public/Document/documentCard.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
public/Home/Gmap.png
Normal file
|
After Width: | Height: | Size: 258 KiB |
BIN
public/Home/checkoutSwiperCard.png
Normal file
|
After Width: | Height: | Size: 116 KiB |
BIN
public/Home/heroImage.png
Normal file
|
After Width: | Height: | Size: 971 KiB |
BIN
public/Home/productReview1.png
Normal file
|
After Width: | Height: | Size: 287 KiB |
BIN
public/Home/productReview2.png
Normal file
|
After Width: | Height: | Size: 148 KiB |
BIN
public/Home/productReview3.png
Normal file
|
After Width: | Height: | Size: 182 KiB |
BIN
public/Home/productReview4.png
Normal file
|
After Width: | Height: | Size: 250 KiB |
BIN
public/Home/settingIcon.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
1
public/Layout/Ar.svg
Normal file
|
After Width: | Height: | Size: 10 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/FooterImage.png
Normal file
|
After Width: | Height: | Size: 624 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 |
BIN
public/Logo/Logo.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
108
public/MainPartnerr.svg
Normal file
|
After Width: | Height: | Size: 87 KiB |
BIN
public/Partner/partner1.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
public/Service/Services.png
Normal file
|
After Width: | Height: | Size: 95 KiB |
BIN
public/Service/ServicesRes.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
136
public/Service/service.svg
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
public/Service/serviceImage.png
Normal file
|
After Width: | Height: | Size: 91 KiB |
141
public/Service/serviceRes.svg
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
public/Team/team1.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
25
public/manifest.json
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"short_name": "React App",
|
||||||
|
"name": "Create React App Sample",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "favicon.ico",
|
||||||
|
"sizes": "64x64 32x32 24x24 16x16",
|
||||||
|
"type": "image/x-icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "logo192.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "192x192"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "logo512.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "512x512"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"start_url": ".",
|
||||||
|
"display": "standalone",
|
||||||
|
"theme_color": "#000000",
|
||||||
|
"background_color": "#ffffff"
|
||||||
|
}
|
||||||
3
public/robots.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# https://www.robotstxt.org/robotstxt.html
|
||||||
|
User-agent: *
|
||||||
|
Disallow:
|
||||||
34
src/App.tsx
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { lazy, Suspense } from 'react';
|
||||||
|
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
|
||||||
|
import LoadingAntd from './Components/Utils/Loading/LoadingAntd';
|
||||||
|
import { routesArray } from './config/RoutesArray';
|
||||||
|
import Layout from './Layout/Layout';
|
||||||
|
|
||||||
|
const App = () => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Suspense fallback={<LoadingAntd />}>
|
||||||
|
<Routes>
|
||||||
|
{routesArray.map(({ path, LayoutClassName, ComponentElement, isLayoutExist }) => (
|
||||||
|
<Route
|
||||||
|
key={path}
|
||||||
|
path={path}
|
||||||
|
element={
|
||||||
|
isLayoutExist ? (
|
||||||
|
<Layout className={LayoutClassName}>
|
||||||
|
<ComponentElement />
|
||||||
|
</Layout>
|
||||||
|
) : (
|
||||||
|
<ComponentElement />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Routes>
|
||||||
|
</Suspense>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default App;
|
||||||
15
src/Components/CheckoutOurNew/All.tsx
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import BaseSingleTab from './BaseSingleTab'
|
||||||
|
import { checkoutItemsLighting } from '../../data/Checkout'
|
||||||
|
|
||||||
|
const All = () => {
|
||||||
|
return (
|
||||||
|
<BaseSingleTab
|
||||||
|
data={checkoutItemsLighting}
|
||||||
|
title='CHECKOUT OUR NEW'
|
||||||
|
sub_title='Our product groups'
|
||||||
|
text='Products and technologies that transcend the times in industrial automation'
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default All
|
||||||
16
src/Components/CheckoutOurNew/Automation.tsx
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { checkoutItemsLighting } from '../../data/Checkout'
|
||||||
|
import BaseSingleTab from './BaseSingleTab'
|
||||||
|
|
||||||
|
const Automation = () => {
|
||||||
|
return (
|
||||||
|
<BaseSingleTab
|
||||||
|
data={checkoutItemsLighting}
|
||||||
|
title='CHECKOUT OUR NEW'
|
||||||
|
sub_title='Industrial Automation Products'
|
||||||
|
text='In the industrial automation sector, which we entered into in 2006, we are among the world-class premium companies that provide energy efficiency.'
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Automation
|
||||||
28
src/Components/CheckoutOurNew/BaseSingleTab.tsx
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
import BaseSwiper from './BaseSwiperForTabs';
|
||||||
|
|
||||||
|
interface BaseSingleTabProps {
|
||||||
|
data:any;
|
||||||
|
title:string,
|
||||||
|
sub_title:string;
|
||||||
|
text:string
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BaseSingleTab = ({data,title,sub_title,text}:BaseSingleTabProps) => {
|
||||||
|
const {t} = useTranslation();
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='checkout_single_tab'>
|
||||||
|
<div className="details">
|
||||||
|
<h1>{t(title)}</h1>
|
||||||
|
<h2>{t(sub_title)}</h2>
|
||||||
|
<p>{t(text)}</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<BaseSwiper data={data} isLoading={false}/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BaseSingleTab
|
||||||
51
src/Components/CheckoutOurNew/BaseSwiperForTabs.tsx
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||||
|
import "swiper/css";
|
||||||
|
import 'swiper/css/free-mode';
|
||||||
|
import "swiper/css/navigation";
|
||||||
|
import "swiper/css/pagination";
|
||||||
|
import "swiper/css/scrollbar";import { A11y, Autoplay, Navigation,Scrollbar } from 'swiper/modules';
|
||||||
|
import Spinner from '../Utils/Loading/Spinner';
|
||||||
|
import TeamCard from '../Ui/TeamCard';
|
||||||
|
import CheckoutCard from './CheckoutCard';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const BaseSwiper = ({data,isLoading}:{data:any,isLoading:boolean}) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='checkout_Swiper'>
|
||||||
|
<Swiper
|
||||||
|
dir={'ltr'}
|
||||||
|
slidesPerView={3}
|
||||||
|
spaceBetween={60}
|
||||||
|
breakpoints={{
|
||||||
|
0: { slidesPerView: 1 },
|
||||||
|
400: { slidesPerView: 1 },
|
||||||
|
600: { slidesPerView: 1 },
|
||||||
|
900: { slidesPerView: 2 },
|
||||||
|
1200: { slidesPerView: 2 },
|
||||||
|
1500: { slidesPerView: 3 },
|
||||||
|
}}
|
||||||
|
navigation
|
||||||
|
autoplay={true}
|
||||||
|
modules={[Navigation, Scrollbar, A11y, Autoplay]}
|
||||||
|
pagination={{ clickable: true }}
|
||||||
|
className="mySwiper"
|
||||||
|
>
|
||||||
|
{
|
||||||
|
isLoading ? <Spinner/> :
|
||||||
|
data?.map((item:any, index:number) => (
|
||||||
|
<SwiperSlide key={index}>
|
||||||
|
<CheckoutCard
|
||||||
|
name={item?.name}
|
||||||
|
src={item?.src}
|
||||||
|
key={index}
|
||||||
|
/>
|
||||||
|
</SwiperSlide>
|
||||||
|
))}
|
||||||
|
</Swiper>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BaseSwiper;
|
||||||
11
src/Components/CheckoutOurNew/CheckoutCard.tsx
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
const CheckoutCard = ({src,name}:{src:string,name:string}) => {
|
||||||
|
return (
|
||||||
|
<div className='checkout_card'>
|
||||||
|
<img src={src} alt={name} />
|
||||||
|
<h4>{name}</h4>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CheckoutCard
|
||||||
27
src/Components/CheckoutOurNew/CheckoutOurNew.tsx
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import CheckoutTabs from './CheckoutTabs'
|
||||||
|
import All from './All';
|
||||||
|
import Lighting from './Lighting';
|
||||||
|
import Automation from './Automation';
|
||||||
|
|
||||||
|
const CheckoutOurNew = () => {
|
||||||
|
const [activeButton, setActiveButton] = useState(0);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='checkout_our_new'>
|
||||||
|
<CheckoutTabs
|
||||||
|
activeButton={activeButton}
|
||||||
|
setActiveButton={setActiveButton}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{activeButton === 0 ? (
|
||||||
|
<All />
|
||||||
|
) : activeButton === 1 ? (
|
||||||
|
<Lighting />
|
||||||
|
) : (
|
||||||
|
<Automation />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CheckoutOurNew
|
||||||
33
src/Components/CheckoutOurNew/CheckoutTabs.tsx
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { useButtonState } from '../../zustand/ButtonState';
|
||||||
|
|
||||||
|
const CheckoutTabs = ({ activeButton, setActiveButton }: any) => {
|
||||||
|
|
||||||
|
const { setActiveTab } = useButtonState((state) => state);
|
||||||
|
|
||||||
|
// Function to handle button click
|
||||||
|
const handleButtonClick = (index: number) => {
|
||||||
|
setActiveButton(index);
|
||||||
|
setActiveTab(index);
|
||||||
|
};
|
||||||
|
const {t} = useTranslation();
|
||||||
|
const buttonLabels = [
|
||||||
|
t("All"),
|
||||||
|
t("lighting"),
|
||||||
|
t("Automation"),
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='checkout_button_tabs'>
|
||||||
|
{buttonLabels.map((label, index) => (
|
||||||
|
<button
|
||||||
|
key={index}
|
||||||
|
className={activeButton === index ? "Activebutton" : "button"}
|
||||||
|
onClick={() => handleButtonClick(index)}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</button>
|
||||||
|
))}</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CheckoutTabs
|
||||||
15
src/Components/CheckoutOurNew/Lighting.tsx
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { checkoutItemsLighting } from '../../data/Checkout';
|
||||||
|
import BaseSingleTab from './BaseSingleTab';
|
||||||
|
|
||||||
|
const Lighting = () => {
|
||||||
|
return (
|
||||||
|
<BaseSingleTab
|
||||||
|
data={checkoutItemsLighting}
|
||||||
|
title='CHECKOUT OUR NEW'
|
||||||
|
sub_title='Latest Professional Lighting'
|
||||||
|
text='We provide a wide range of indoor and outdoor lighting products, project design and supervision services in relation to technical and architectural lighting, and lighting control area.'
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Lighting
|
||||||
43
src/Components/Distributor/CollapsChildren.tsx
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { CiMail } from "react-icons/ci";
|
||||||
|
import { FaPhoneFlip } from "react-icons/fa6";
|
||||||
|
import { SlPrinter } from "react-icons/sl";
|
||||||
|
|
||||||
|
const CollapsChildren = () => {
|
||||||
|
return (
|
||||||
|
<div className='collaps_children'>
|
||||||
|
<h1>EBRU SOFT YAZILIM BİLG. LTD. ŞTİ.</h1>
|
||||||
|
<p>İvedik O.S.B. Melih Gökçek Blv. Eminel İş Mrkz. No:18/46 Yenimahalle/ANKARA</p>
|
||||||
|
|
||||||
|
<FaPhoneFlip/>
|
||||||
|
<p>+90 (216) 314 59 00</p>
|
||||||
|
|
||||||
|
<SlPrinter/>
|
||||||
|
<p>+90 (312) 385 12 76</p>
|
||||||
|
|
||||||
|
<CiMail/>
|
||||||
|
<p>Boutique@Butykotomasion.com</p>
|
||||||
|
|
||||||
|
<CiMail/>
|
||||||
|
<p>Boutique@Butykotomasion.com</p>
|
||||||
|
|
||||||
|
<h1>EBRU SOFT YAZILIM BİLG. LTD. ŞTİ.</h1>
|
||||||
|
<p>İvedik O.S.B. Melih Gökçek Blv. Eminel İş Mrkz. No:18/46 Yenimahalle/ANKARA</p>
|
||||||
|
|
||||||
|
<FaPhoneFlip/>
|
||||||
|
<p>+90 (216) 314 59 00</p>
|
||||||
|
|
||||||
|
<SlPrinter/>
|
||||||
|
<p>+90 (312) 385 12 76</p>
|
||||||
|
|
||||||
|
<CiMail/>
|
||||||
|
<p>Boutique@Butykotomasion.com</p>
|
||||||
|
|
||||||
|
<CiMail/>
|
||||||
|
<p>Boutique@Butykotomasion.com</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CollapsChildren
|
||||||
37
src/Components/Distributor/Distributor.tsx
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { DistributorArray, DistributorArray2 } from '../../data/Distributor'
|
||||||
|
import DistributorWord from '../Ui/DistributorWord'
|
||||||
|
import AnimationButton from '../Ui/AnimationButton'
|
||||||
|
|
||||||
|
const Distributor = () => {
|
||||||
|
const {t} = useTranslation()
|
||||||
|
return (
|
||||||
|
<div className='Distributor'>
|
||||||
|
<div className="left">
|
||||||
|
<h1>{t("Our Distributors")}</h1>
|
||||||
|
<h4>{t("Look at our local distributors")}</h4>
|
||||||
|
<div className='word_container'>
|
||||||
|
<div>
|
||||||
|
{DistributorArray.map((e) =>(
|
||||||
|
<DistributorWord title={e.title}/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{DistributorArray2.map((e) =>(
|
||||||
|
<DistributorWord title={e.title}/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="button_container">
|
||||||
|
<AnimationButton withAnimation={false} link='/' text='See Details'/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="right">
|
||||||
|
<img src="/Home/Gmap.png" alt="googleMap" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Distributor
|
||||||
114
src/Components/Distributor/DistributorCollaps.tsx
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
import type { CollapseProps } from "antd";
|
||||||
|
import { Collapse } from "antd";
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import CollapsChildren from "./CollapsChildren";
|
||||||
|
|
||||||
|
const DistributorCollaps = () => {
|
||||||
|
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [activeKey, setActiveKey] = useState<string[]>(["1"]);
|
||||||
|
|
||||||
|
const onChange = (key: string | string[]) => {
|
||||||
|
if (typeof key === 'string') {
|
||||||
|
setActiveKey([key]);
|
||||||
|
} else {
|
||||||
|
setActiveKey(key);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const items: CollapseProps["items"] = [
|
||||||
|
{
|
||||||
|
style:{background:"transparent"},
|
||||||
|
key: "1",
|
||||||
|
label: t("Ankara"),
|
||||||
|
children: (
|
||||||
|
<p>
|
||||||
|
<CollapsChildren/>
|
||||||
|
</p>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "2",
|
||||||
|
label: t("Gaziantep"),
|
||||||
|
children: (
|
||||||
|
<p>
|
||||||
|
<CollapsChildren/>
|
||||||
|
</p>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "3",
|
||||||
|
label: t("İstanbul"),
|
||||||
|
children: (
|
||||||
|
<p>
|
||||||
|
{/* {t("Sakarya")}. */}
|
||||||
|
</p>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "4",
|
||||||
|
label: t("İzmir"),
|
||||||
|
children: (
|
||||||
|
<p>
|
||||||
|
{/* {t("Sakarya")}. */}
|
||||||
|
</p>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
key: "5",
|
||||||
|
label: t("Kocaeli"),
|
||||||
|
children: (
|
||||||
|
<p>
|
||||||
|
{/* {t("Sakarya")}. */}
|
||||||
|
</p>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "6",
|
||||||
|
label: t("Konya"),
|
||||||
|
children: (
|
||||||
|
<p>
|
||||||
|
{/* {t("Sakarya")}. */}
|
||||||
|
</p>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "7",
|
||||||
|
label: t("Sakarya"),
|
||||||
|
children: (
|
||||||
|
<p>
|
||||||
|
{/* {t("Sakarya")}. */}
|
||||||
|
</p>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Collapse
|
||||||
|
className="distributor_collaps"
|
||||||
|
defaultActiveKey={["1"]}
|
||||||
|
expandIconPosition="right"
|
||||||
|
bordered={false}
|
||||||
|
activeKey={activeKey}
|
||||||
|
onChange={onChange}
|
||||||
|
|
||||||
|
items={items.map(item => ({
|
||||||
|
...item,
|
||||||
|
label: (
|
||||||
|
<span
|
||||||
|
className={classNames({
|
||||||
|
'label-active': activeKey.includes(item.key as string)
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}))}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default DistributorCollaps
|
||||||
78
src/Components/Document/Document.tsx
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { Pagination } from 'antd';
|
||||||
|
import DocumentCard from './DocumentCard';
|
||||||
|
import { useNavigate, useLocation } from 'react-router-dom';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useWindowResize } from '../../Hooks/useWindowResize';
|
||||||
|
import { useGetCertificate } from '../../api/certificate';
|
||||||
|
|
||||||
|
const Document: React.FC = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [isChanging, setIsChanging] = useState(false);
|
||||||
|
const { windowWidth } = useWindowResize();
|
||||||
|
|
||||||
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
|
const [totalItems, setTotalItems] = useState(0);
|
||||||
|
const [perPage, setPerPage] = useState(3);
|
||||||
|
const { data } = useGetCertificate({ page: currentPage, per_page: perPage });
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
|
const handlePageChange = (page: number) => {
|
||||||
|
setIsChanging(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setCurrentPage(page);
|
||||||
|
navigate(`${location.pathname}?page=${page}`);
|
||||||
|
setIsChanging(false);
|
||||||
|
}, 300);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const params = new URLSearchParams(location.search);
|
||||||
|
const pageParam = params.get('page');
|
||||||
|
const page = pageParam ? parseInt(pageParam, 10) : 1;
|
||||||
|
setCurrentPage(page);
|
||||||
|
}, [location.search]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (data?.meta) {
|
||||||
|
setTotalItems(data.meta.total);
|
||||||
|
}
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (windowWidth < 600) {
|
||||||
|
setPerPage(1);
|
||||||
|
} else if (windowWidth < 1300) {
|
||||||
|
setPerPage(2);
|
||||||
|
} else {
|
||||||
|
setPerPage(3);
|
||||||
|
}
|
||||||
|
}, [windowWidth]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='Document'>
|
||||||
|
<h1>{t("Documents")}</h1>
|
||||||
|
<h2>{t("Quality Certificates")}</h2>
|
||||||
|
|
||||||
|
<Pagination
|
||||||
|
current={currentPage}
|
||||||
|
pageSize={perPage}
|
||||||
|
total={totalItems}
|
||||||
|
onChange={handlePageChange}
|
||||||
|
/>
|
||||||
|
<div className={`document-cards ${isChanging ? 'changing' : ''}`}>
|
||||||
|
{data?.data?.map((item: any) => (
|
||||||
|
<DocumentCard
|
||||||
|
key={item.id}
|
||||||
|
name={item?.name}
|
||||||
|
image={item?.image}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Document;
|
||||||
18
src/Components/Document/DocumentCard.tsx
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const DocumentCard = ({name,text,image}:any) => {
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='Document_card'>
|
||||||
|
<div className="image_container">
|
||||||
|
<img src={image} alt="document_card" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1>{name}</h1>
|
||||||
|
{/* <p>{text}</p> */}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DocumentCard
|
||||||
44
src/Components/HOC/SearchWithDrawer.tsx
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { useState } from 'react';
|
||||||
|
import type { DrawerProps } from 'antd';
|
||||||
|
import { Drawer, Space } from 'antd';
|
||||||
|
import { TiDeleteOutline } from "react-icons/ti";
|
||||||
|
import SearchButton from '../Utils/Search/SearchButton';
|
||||||
|
import { RiSearchLine } from "react-icons/ri";
|
||||||
|
import Empty from '../Utils/Search/Empty';
|
||||||
|
|
||||||
|
const SearchWithDrawer = () => {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const [placement, setPlacement] = useState<DrawerProps['placement']>('right');
|
||||||
|
const [noDataFound, setNoDataFound] = useState(false);
|
||||||
|
|
||||||
|
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={720}
|
||||||
|
style={{ maxHeight: "40%" }}
|
||||||
|
>
|
||||||
|
<div className="search_first_section">
|
||||||
|
<SearchButton setOpen={setOpen} setNoDataFound={setNoDataFound} />
|
||||||
|
<span className='delete_icon' onClick={() => setOpen(false)}><TiDeleteOutline /></span>
|
||||||
|
</div>
|
||||||
|
<div className='not_found_section'>
|
||||||
|
{noDataFound ? <Empty />:"" }
|
||||||
|
</div>
|
||||||
|
</Drawer>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SearchWithDrawer;
|
||||||
41
src/Components/Home/ComprehensivePurchase.tsx
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { IoIosArrowForward } from "react-icons/io";
|
||||||
|
|
||||||
|
const ComprehensivePurchase = () => {
|
||||||
|
const {t} = useTranslation();
|
||||||
|
return (
|
||||||
|
<div className='comprehensive_purchase'>
|
||||||
|
<h1>{t("products")}</h1>
|
||||||
|
<h4>{t("Comprehensive purchase of all low voltage and lighting products")}</h4>
|
||||||
|
<div className="first">
|
||||||
|
<div>
|
||||||
|
<Link className='products_link' to={'/products'}><img src="/Home/productReview1.png" alt="" /></Link>
|
||||||
|
<h6>{t("measurement")}</h6>
|
||||||
|
<p>{t("Explore")} <IoIosArrowForward/></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Link className='products_link' to={'/products'}><img src="/Home/productReview2.png" alt="" /></Link>
|
||||||
|
<h6>{t("End")}</h6>
|
||||||
|
<p>{t("Explore")} <IoIosArrowForward/></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="second first">
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Link className='products_link' to={'/products'}><img src="/Home/productReview3.png" alt="" /></Link>
|
||||||
|
<h6>{t("Power & Control")}</h6>
|
||||||
|
<p>{t("Explore")} <IoIosArrowForward/></p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Link className='products_link' to={'/products'}><img src="/Home/productReview4.png" alt="" /></Link>
|
||||||
|
<h6>{t("lighting")}</h6>
|
||||||
|
<p>{t("Explore")} <IoIosArrowForward/></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ComprehensivePurchase
|
||||||
26
src/Components/Home/HeroSection.tsx
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
import React from 'react'
|
||||||
|
import HeroSwiper from './HeroSwiper'
|
||||||
|
import AnimationButton from '../Ui/AnimationButton';
|
||||||
|
|
||||||
|
const HeroSection = () => {
|
||||||
|
const {t} = useTranslation();
|
||||||
|
return (
|
||||||
|
<div className='hero_section'>
|
||||||
|
<HeroSwiper />
|
||||||
|
<div className="hero_details">
|
||||||
|
<h1>{t("Industrial Automation")}</h1>
|
||||||
|
<h4>{t("Industrial Automation & Control Solutions")}</h4>
|
||||||
|
<p>{t("MNS automation and control products and solutions cover a wide range of industrial, infrastructure and construction sectors")}</p>
|
||||||
|
<div className="button_container">
|
||||||
|
<AnimationButton
|
||||||
|
link='/'
|
||||||
|
text='Products'
|
||||||
|
withAnimation={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HeroSection
|
||||||
16
src/Components/Home/HeroSwiper.tsx
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
|
||||||
|
import { Carousel } from 'antd';
|
||||||
|
import { heroArray } from '../../data/Home';
|
||||||
|
|
||||||
|
|
||||||
|
const CarouselApp= () => (
|
||||||
|
<Carousel >
|
||||||
|
{heroArray.map((item:any, index:number) => (
|
||||||
|
<div className='hero_Swiper' key={index}>
|
||||||
|
<img src={item.src} alt="hero_image" />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</Carousel>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default CarouselApp;
|
||||||
43
src/Components/Info/Info.tsx
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
import HeaderLink from '../Ui/HeaderLink'
|
||||||
|
import { InfoProps } from '../../type/InfoProps';
|
||||||
|
import Spinner from '../Utils/Loading/Spinner';
|
||||||
|
import { PrivacyData, TermsData } from '../../data/Info';
|
||||||
|
|
||||||
|
const Info = ({headerText,title,isLoading,text,isHaveText=false,isPrivacy = false}:InfoProps) => {
|
||||||
|
const {t} = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='info'>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{isLoading? <Spinner/> :
|
||||||
|
<div className="info_content">
|
||||||
|
<HeaderLink text={headerText}/>
|
||||||
|
<h1>{t(title)}</h1>
|
||||||
|
{isHaveText?
|
||||||
|
<p>{text}</p>
|
||||||
|
:""
|
||||||
|
}
|
||||||
|
{
|
||||||
|
isPrivacy
|
||||||
|
? PrivacyData.map((item) => (
|
||||||
|
<div className='single_info'>
|
||||||
|
<h2>{item.key}</h2>
|
||||||
|
<p>{item.value}</p>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
: TermsData.map((item) => (
|
||||||
|
<div className='single_info'>
|
||||||
|
<h2>{item.key}</h2>
|
||||||
|
<p>{item.value}</p>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Info
|
||||||
29
src/Components/OurTeam/OurTeam.tsx
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
import React from 'react'
|
||||||
|
import TeamCard from '../Ui/TeamCard';
|
||||||
|
import TeamSwiper from './TeamSwiper';
|
||||||
|
import { teamMembers } from '../../data/Team';
|
||||||
|
import { useGetTeamMember } from '../../api/TeamMember';
|
||||||
|
|
||||||
|
const OurTeam = () => {
|
||||||
|
const {t} = useTranslation();
|
||||||
|
const {data} = useGetTeamMember();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='our_team'>
|
||||||
|
<h1>{t("Documents")}</h1>
|
||||||
|
<h2>{t("Quality Certificates")}</h2>
|
||||||
|
|
||||||
|
<div className='our_team_cards'>
|
||||||
|
{data?.data.map((member:any)=>(
|
||||||
|
<TeamCard
|
||||||
|
name={member.name}
|
||||||
|
position={member.position}
|
||||||
|
image={member.image}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default OurTeam
|
||||||
46
src/Components/OurTeam/TeamSwiper.tsx
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||||
|
import "swiper/css";
|
||||||
|
import 'swiper/css/free-mode';
|
||||||
|
import "swiper/css/navigation";
|
||||||
|
import "swiper/css/pagination";
|
||||||
|
import "swiper/css/scrollbar";import { A11y, Autoplay, Navigation,Scrollbar } from 'swiper/modules';
|
||||||
|
import Spinner from '../Utils/Loading/Spinner';
|
||||||
|
import TeamCard from '../Ui/TeamCard';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const TeamSwiper = ({data,isLoading}:{data:any,isLoading:boolean}) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='team_Swiper'>
|
||||||
|
<Swiper
|
||||||
|
dir={'ltr'}
|
||||||
|
slidesPerView={5}
|
||||||
|
spaceBetween={66}
|
||||||
|
breakpoints={{
|
||||||
|
0: { slidesPerView: 1 },
|
||||||
|
400: { slidesPerView: 1 },
|
||||||
|
600: { slidesPerView: 3 },
|
||||||
|
900: { slidesPerView: 4 },
|
||||||
|
1200: { slidesPerView: 5 },
|
||||||
|
1500: { slidesPerView: 5 },
|
||||||
|
}}
|
||||||
|
navigation
|
||||||
|
autoplay={true}
|
||||||
|
modules={[Navigation, Scrollbar, A11y, Autoplay]}
|
||||||
|
pagination={{ clickable: true }}
|
||||||
|
className="mySwiper"
|
||||||
|
>
|
||||||
|
{
|
||||||
|
isLoading ? <Spinner/> :
|
||||||
|
data?.map((item:any, index:number) => (
|
||||||
|
<SwiperSlide key={index}>
|
||||||
|
|
||||||
|
</SwiperSlide>
|
||||||
|
))}
|
||||||
|
</Swiper>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TeamSwiper;
|
||||||
33
src/Components/Pagination/PaginationOptions.tsx
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { TableProps } from "antd";
|
||||||
|
import { useMemo } from "react";
|
||||||
|
import {
|
||||||
|
IoMdArrowDropdown,
|
||||||
|
IoMdArrowDropleft,
|
||||||
|
IoMdArrowDropright,
|
||||||
|
} from "react-icons/io";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
export const PaginationOptions = (dataWpagination: any) => {
|
||||||
|
return useMemo(() => {
|
||||||
|
if (!dataWpagination || !dataWpagination.data.pagination) return {};
|
||||||
|
|
||||||
|
return {
|
||||||
|
pageSize: dataWpagination?.data?.pagination.per_page,
|
||||||
|
current: dataWpagination?.data?.pagination.current_page,
|
||||||
|
total: dataWpagination?.data?.pagination.total_items,
|
||||||
|
prevIcon: <IoMdArrowDropright color="#A098AE" size={30} />,
|
||||||
|
nextIcon: <IoMdArrowDropleft color="#A098AE" size={30} />,
|
||||||
|
};
|
||||||
|
}, [dataWpagination]);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useTableOnChange = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
return (pagination: any, _filters: any, _sorter: any, _extra: any) => {
|
||||||
|
if (pagination) {
|
||||||
|
// navigate(`?page=${pagination.current}&per_page=${pagination.pageSize}`);
|
||||||
|
navigate(`?page=${pagination.current}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
34
src/Components/Pagination/usePagination.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
|
import { PaginationAntd, PaginationMeta } from "../../type/pagination";
|
||||||
|
|
||||||
|
interface Data {
|
||||||
|
meta: PaginationMeta;
|
||||||
|
}
|
||||||
|
|
||||||
|
const usePagination = (data: Data) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
|
const [pagination, setPagination] = useState<PaginationAntd>({
|
||||||
|
current: data?.meta?.current_page || 1,
|
||||||
|
pageSize: data?.meta?.per_page || 10,
|
||||||
|
total: data?.meta?.total || 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setPagination({
|
||||||
|
current: data?.meta?.current_page || 1,
|
||||||
|
pageSize: data?.meta?.per_page || 10,
|
||||||
|
total: data?.meta?.total || 0,
|
||||||
|
});
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
const handlePageChange = (page: number) => {
|
||||||
|
navigate(`?page=${page}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
return { pagination, handlePageChange };
|
||||||
|
};
|
||||||
|
|
||||||
|
export default usePagination;
|
||||||
21
src/Components/Partner/Partner.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { partnerArray } from '../../data/Partner';
|
||||||
|
|
||||||
|
const Partner = () => {
|
||||||
|
const {t} = useTranslation();
|
||||||
|
return (
|
||||||
|
<div className='partner'>
|
||||||
|
<div className='top'>
|
||||||
|
<img src="/Home/settingIcon.png" alt="setting" />
|
||||||
|
<p>{t("Trusted by 100+ Companies across the globe!")}</p>
|
||||||
|
</div>
|
||||||
|
<div className='image_container'>
|
||||||
|
{partnerArray?.map((item:any)=>(
|
||||||
|
<img src={item.path} alt="logo" />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Partner
|
||||||
47
src/Components/Products/BrandFilter.tsx
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
import React from "react";
|
||||||
|
import { Checkbox } from "antd";
|
||||||
|
import type { CheckboxProps } from "antd";
|
||||||
|
import { useFilterStateState } from "../../zustand/Filter";
|
||||||
|
import { languageObject } from "../Utils/languageObject";
|
||||||
|
import { useGetCategory } from "../../api/category";
|
||||||
|
|
||||||
|
const BrandFilter = ({id}:{id:any}) => {
|
||||||
|
const { setFilter, Filter } = useFilterStateState();
|
||||||
|
|
||||||
|
const onChange =
|
||||||
|
(Category: any): 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 = useGetCategory({
|
||||||
|
parent_id:id
|
||||||
|
})
|
||||||
|
const product = data?.data?.data;
|
||||||
|
console.log(product);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="CheckboxFilter">
|
||||||
|
{product?.map((brand:any) => {
|
||||||
|
console.log(brand?.children);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Checkbox
|
||||||
|
checked={Filter.some((item: any) => item.name === brand?.name)}
|
||||||
|
key={brand?.id}
|
||||||
|
onChange={onChange(brand)}
|
||||||
|
>
|
||||||
|
{languageObject(brand?.name)}
|
||||||
|
</Checkbox>
|
||||||
|
)})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BrandFilter;
|
||||||
24
src/Components/Products/ProductCard.tsx
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import { languageObject } from '../Utils/languageObject';
|
||||||
|
|
||||||
|
const ProductCard = ({data}:any) => {
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const productLink = `/product/${data?.id}`
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="product_card">
|
||||||
|
<div className="image_container">
|
||||||
|
<img
|
||||||
|
onClick={() => navigate(productLink)}
|
||||||
|
src={data?.file}
|
||||||
|
alt={`product ${data.name}`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p className="truncate-text">{languageObject(data?.name)}</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProductCard
|
||||||
39
src/Components/Products/ProductInfo.tsx
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
|
||||||
|
const ProductInfo = ({ data }:{data:any}) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const ProductCollectionArray = data?.collections
|
||||||
|
? data.collections.flatMap((collection:any) => {
|
||||||
|
const { collectionParam, ...rest } = collection;
|
||||||
|
return Object.entries(rest).map(([key, value]) => ({
|
||||||
|
key,
|
||||||
|
value
|
||||||
|
}));
|
||||||
|
})
|
||||||
|
: [];
|
||||||
|
|
||||||
|
const midpoint = Math.ceil(ProductCollectionArray.length / 2);
|
||||||
|
const leftSection = ProductCollectionArray.slice(0, midpoint);
|
||||||
|
const rightSection = ProductCollectionArray.slice(midpoint);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='product_info'>
|
||||||
|
<h1>{t("allocation")}</h1>
|
||||||
|
|
||||||
|
<div className='details'>
|
||||||
|
<div className='left'>
|
||||||
|
{leftSection.map((e:any) => (
|
||||||
|
<span >{t(e.key)} <span>{e.value}</span></span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className='right'>
|
||||||
|
{rightSection.map((e:any) => (
|
||||||
|
<span >{t(e.key)} <span>{e.value}</span></span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProductInfo;
|
||||||
47
src/Components/Products/ProductSwiper.tsx
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||||
|
import "swiper/css";
|
||||||
|
import 'swiper/css/free-mode';
|
||||||
|
import "swiper/css/navigation";
|
||||||
|
import "swiper/css/pagination";
|
||||||
|
import "swiper/css/scrollbar";import { A11y, Autoplay, Navigation,Scrollbar } from 'swiper/modules';
|
||||||
|
import Spinner from '../Utils/Loading/Spinner';
|
||||||
|
import ProductCard from './ProductCard';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const ProductSwiper = ({data,isLoading}:{data:any,isLoading:boolean}) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='similar_Swiper'>
|
||||||
|
<Swiper
|
||||||
|
dir={'ltr'}
|
||||||
|
slidesPerView={3}
|
||||||
|
spaceBetween={66}
|
||||||
|
breakpoints={{
|
||||||
|
0: { slidesPerView: 1 },
|
||||||
|
400: { slidesPerView: 1 },
|
||||||
|
600: { slidesPerView: 2 },
|
||||||
|
1000: { slidesPerView: 2 },
|
||||||
|
1200: { slidesPerView: 3 },
|
||||||
|
1500: { slidesPerView: 4 },
|
||||||
|
}}
|
||||||
|
navigation
|
||||||
|
modules={[Navigation, Scrollbar, A11y, Autoplay]}
|
||||||
|
pagination={{ clickable: true }}
|
||||||
|
className="mySwiper"
|
||||||
|
>
|
||||||
|
{
|
||||||
|
isLoading ? <Spinner/> :
|
||||||
|
data?.data?.map((item:any, index:number) => (
|
||||||
|
<SwiperSlide key={index}>
|
||||||
|
<ProductCard
|
||||||
|
data={item}
|
||||||
|
/>
|
||||||
|
</SwiperSlide>
|
||||||
|
))}
|
||||||
|
</Swiper>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProductSwiper;
|
||||||
54
src/Components/Products/SingleProductSwiper.tsx
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||||
|
import "swiper/css";
|
||||||
|
import 'swiper/css/free-mode';
|
||||||
|
import "swiper/css/navigation";
|
||||||
|
import "swiper/css/pagination";
|
||||||
|
import "swiper/css/scrollbar";import { A11y, Autoplay, Navigation,Scrollbar } from 'swiper/modules';
|
||||||
|
import Spinner from '../Utils/Loading/Spinner';
|
||||||
|
import ProductCard from './ProductCard';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const SingleProductSwiper = ({data,isLoading}:{data:any,isLoading:boolean}) => {
|
||||||
|
const [mainImage, setMainImage] = useState(data?.file);
|
||||||
|
console.log(data?.data?.attachment);
|
||||||
|
|
||||||
|
const handleImageClick = (image:any) => {
|
||||||
|
setMainImage(image);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className='single_product_Swiper'>
|
||||||
|
<Swiper
|
||||||
|
dir={'ltr'}
|
||||||
|
slidesPerView={3}
|
||||||
|
spaceBetween={66}
|
||||||
|
breakpoints={{
|
||||||
|
0: { slidesPerView: 1 },
|
||||||
|
400: { slidesPerView: 2 },
|
||||||
|
600: { slidesPerView: 2 },
|
||||||
|
1000: { slidesPerView: 3 },
|
||||||
|
1200: { slidesPerView: 4 },
|
||||||
|
1500: { slidesPerView: 4 },
|
||||||
|
}}
|
||||||
|
navigation
|
||||||
|
modules={[Navigation, Scrollbar, A11y, Autoplay]}
|
||||||
|
pagination={{ clickable: true }}
|
||||||
|
className="mySwiper"
|
||||||
|
>
|
||||||
|
{
|
||||||
|
isLoading ? <Spinner/> :
|
||||||
|
data?.data?.attachment?.map(({attachment, id}:{attachment:string,id:number}) => {
|
||||||
|
return(
|
||||||
|
<SwiperSlide key={id}>
|
||||||
|
<div key={id} className="image_container" onClick={() => handleImageClick(attachment)}>
|
||||||
|
<img src={attachment} alt={`product_multi_image_${id}`} className='multi_image' />
|
||||||
|
</div>
|
||||||
|
</SwiperSlide>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</Swiper>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SingleProductSwiper;
|
||||||
35
src/Components/Service/Service.tsx
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { ServicesArray } from '../../data/Service';
|
||||||
|
|
||||||
|
const Service = () => {
|
||||||
|
const {t} = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='Service'>
|
||||||
|
<h1>{t("OUR SERVICES")}</h1>
|
||||||
|
<h2>{t("What services do we provide?")}</h2>
|
||||||
|
<picture>
|
||||||
|
<source className="service_image" srcSet="/Service/ServicesRes.png" media="(max-width: 600px)" />
|
||||||
|
<img className="service_image" src="/Service/Services.png" alt="MDN" />
|
||||||
|
</picture>
|
||||||
|
{/* <ServiceImage/> */}
|
||||||
|
{/* <picture>
|
||||||
|
<source className="service_image" srcSet="/Service/serviceRes.svg" media="(max-width: 600px)" />
|
||||||
|
<img className="service_image" src="/Service/service.svg" alt="MDN" />
|
||||||
|
<div className='single_services_container'>
|
||||||
|
{
|
||||||
|
ServicesArray.map((e) =>(
|
||||||
|
<div className='single_service'>
|
||||||
|
<h1>{t(e.title)}</h1>
|
||||||
|
<p>{t(e.text)}</p>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</picture> */}
|
||||||
|
{/* <img src="/Service/service.svg" alt="" /> */}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Service
|
||||||
13
src/Components/Ui/AnimationButton.tsx
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
const AnimationButton = ({text,icon,link,withAnimation= true}:AnimationButtonProps) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='animation_button'>
|
||||||
|
<Link to={link}><p>{text}</p></Link>
|
||||||
|
{
|
||||||
|
withAnimation ? <span>{icon}</span> : <span style={{display:"none"}}>{icon}</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AnimationButton
|
||||||
50
src/Components/Ui/CardItem.tsx
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
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 '../../Layout/NavBar/Types';
|
||||||
|
|
||||||
|
interface CartItemProps {
|
||||||
|
data: TProduct;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CardItem: React.FC<CartItemProps> = ({ data }) => {
|
||||||
|
const [loading, resetLoading] = useLoadingState(true, 2000);
|
||||||
|
const [Counter, setCounter] = useState<number>(data?.count);
|
||||||
|
const [Price, setPrice] = useState<number>(data?.price);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Skeleton loading={loading} active avatar style={{ width: "100%", marginTop: 22 }}>
|
||||||
|
<Card className='CardItem' style={{ width: "100%", marginTop: 16 }} loading={loading}>
|
||||||
|
<span className='Card_Counter'>
|
||||||
|
<Button shape="circle" icon={<PlusCircleFilled />} onClick={() => { setCounter(v => ++v); setPrice(v => 2 * v) }} />
|
||||||
|
<div className='Counter'>{Counter}</div>
|
||||||
|
<Button shape="circle" icon={<MinusCircleOutlined />} onClick={() => { setCounter(v => v > 1 ? --v : v); setPrice(v => Counter > 1 ? v / 2 : v) }} />
|
||||||
|
</span>
|
||||||
|
<span className='Card_Img'>
|
||||||
|
<img alt='' src={data?.img} />
|
||||||
|
</span>
|
||||||
|
<span className='Card_Info'>
|
||||||
|
<h5>{data.name}</h5>
|
||||||
|
<h6>{data.type}</h6>
|
||||||
|
<strong>${Price}.00</strong>
|
||||||
|
</span>
|
||||||
|
<span className='Card_Delete'>
|
||||||
|
<Popconfirm
|
||||||
|
title="Delete the Item"
|
||||||
|
description="Are you sure to delete this Item?"
|
||||||
|
okText="Yes"
|
||||||
|
cancelText="No"
|
||||||
|
>
|
||||||
|
<Tooltip title="Delete" placement="bottom">
|
||||||
|
<Button shape="circle" icon={<CloseOutlined />} danger />
|
||||||
|
</Tooltip>
|
||||||
|
</Popconfirm>
|
||||||
|
</span>
|
||||||
|
</Card>
|
||||||
|
</Skeleton>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export default CardItem;
|
||||||
28
src/Components/Ui/Carousel.tsx
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Carousel } from 'antd';
|
||||||
|
import { TbannerData } from '../../Layout/NavBar/Types';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import { BsArrowUpRight } from 'react-icons/bs';
|
||||||
|
|
||||||
|
type TCarouselApp = {
|
||||||
|
data: TbannerData[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const CarouselApp: React.FC<TCarouselApp> = ({ data }) => (
|
||||||
|
<Carousel >
|
||||||
|
{data.map((item: TbannerData, index: number) => (
|
||||||
|
<div className='banner_Container' key={index}>
|
||||||
|
<img alt='' className='banner1' src={item.imageUrl} />
|
||||||
|
<div className='banner_Info'>
|
||||||
|
<h1 className='underLineText'>{item.title}</h1>
|
||||||
|
<h2>
|
||||||
|
{item.subtitle} <br /> <strong>{item.discount}</strong>
|
||||||
|
</h2>
|
||||||
|
<Link to={item.link}>{item?.btn} <BsArrowUpRight /> </Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</Carousel>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default CarouselApp;
|
||||||
15
src/Components/Ui/ContactInfo.tsx
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import MediaButton from './MediaButton';
|
||||||
|
|
||||||
|
const ContactInfo = ({ title,info}:ContactInfoProps) => {
|
||||||
|
const {t} = useTranslation();
|
||||||
|
return (
|
||||||
|
<div className='single_contact_info'>
|
||||||
|
<div>
|
||||||
|
<h2>{t(title)}</h2>
|
||||||
|
<p>{info}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ContactInfo
|
||||||
30
src/Components/Ui/CustomImage.tsx
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import { IMAGE_BASE_URL } from "../../api/config";
|
||||||
|
|
||||||
|
interface ImageProps extends React.ImgHTMLAttributes<HTMLImageElement> {
|
||||||
|
src: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CustomImage: React.FC<ImageProps> = ({ src, ...props }) => {
|
||||||
|
|
||||||
|
const [imgSrc, setImgSrc] = useState<any>(src);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setImgSrc(src);
|
||||||
|
}, [src,props]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const newImage = (imgSrc?.replace("public", "/storage"))
|
||||||
|
// IMAGE_BASE_URL +
|
||||||
|
|
||||||
|
return (
|
||||||
|
<img
|
||||||
|
src={newImage}
|
||||||
|
{...props}
|
||||||
|
alt="there is no image"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CustomImage;
|
||||||
15
src/Components/Ui/CustomTitle.tsx
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { CustomTitleProps } from '../../type/app';
|
||||||
|
|
||||||
|
|
||||||
|
const CustomTitle = ({title}:CustomTitleProps) => {
|
||||||
|
|
||||||
|
const {t} = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='Custom_Title'>
|
||||||
|
<p>{t(title)}</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CustomTitle
|
||||||
13
src/Components/Ui/DistributorWord.tsx
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const DistributorWord = ({title}:any) => {
|
||||||
|
const {t} = useTranslation();
|
||||||
|
return (
|
||||||
|
<div className='distributor_word'>
|
||||||
|
<img src="/App/CheckMark.png" alt="check" />
|
||||||
|
<span>{t(title)}</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DistributorWord
|
||||||
20
src/Components/Ui/DrawerLink.tsx
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { NavLink } from 'react-router-dom';
|
||||||
|
|
||||||
|
const DrawerLink = ({href,name,icon,closeDrawer}:HedaerLinksProps) => {
|
||||||
|
|
||||||
|
const {t} = useTranslation();
|
||||||
|
const pathname = window.location.pathname;
|
||||||
|
const is_active = pathname === href;
|
||||||
|
const handleClick = () => {
|
||||||
|
closeDrawer();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NavLink to={href} className="nav_link_drawer" onClick={handleClick}>
|
||||||
|
<p className={`drawer_link ${is_active && "active_link" }`}>{icon}{t(name)} </p>
|
||||||
|
</NavLink>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DrawerLink
|
||||||
39
src/Components/Ui/DropDown.tsx
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { DownOutlined } from '@ant-design/icons';
|
||||||
|
import { Dropdown, Menu, Space } from 'antd';
|
||||||
|
|
||||||
|
interface MenuItem {
|
||||||
|
key: string;
|
||||||
|
name: string;
|
||||||
|
href: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DropDownProps {
|
||||||
|
menuItems: MenuItem[];
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DropDown: React.FC<DropDownProps> = ({ menuItems, title }) => {
|
||||||
|
const renderMenuItems = () => {
|
||||||
|
return menuItems.map((item) => (
|
||||||
|
<Menu.Item key={item.key}>
|
||||||
|
<a target="_blank" rel="noopener noreferrer" href={item.href}>
|
||||||
|
{item.name}
|
||||||
|
</a>
|
||||||
|
</Menu.Item>
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
const menu = <Menu>{renderMenuItems()}</Menu>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dropdown overlay={menu} placement="bottomLeft">
|
||||||
|
<Space>
|
||||||
|
<span>{title} </span>
|
||||||
|
<DownOutlined />
|
||||||
|
</Space>
|
||||||
|
</Dropdown>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DropDown;
|
||||||
87
src/Components/Ui/DropdownMenu.tsx
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {Dropdown, Button } from 'antd';
|
||||||
|
import { AppstoreOutlined, DownOutlined } from '@ant-design/icons';
|
||||||
|
import MenuItems from './MenuItems';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const DropdownMenu = () => {
|
||||||
|
const {t} = useTranslation();
|
||||||
|
return (
|
||||||
|
<Dropdown overlay={MenuItems} placement="bottomLeft" className='DropdownMenu'trigger={['click']} >
|
||||||
|
<Button>
|
||||||
|
<AppstoreOutlined />
|
||||||
|
{t("Categories")}
|
||||||
|
<DownOutlined />
|
||||||
|
</Button>
|
||||||
|
</Dropdown>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DropdownMenu;
|
||||||
|
|
||||||
|
|
||||||
|
//////////// you can use this file when you connect with backend just change the response and api endpoint //////////////////
|
||||||
|
|
||||||
|
// import React from 'react';
|
||||||
|
// import { Dropdown, Button, Menu } from 'antd';
|
||||||
|
// import { AppstoreOutlined, DownOutlined, MailOutlined } from '@ant-design/icons';
|
||||||
|
// import { useGetAllCategories } from '../../api/categories';
|
||||||
|
// import { Link, useNavigate } from 'react-router-dom';
|
||||||
|
// import { useTranslation } from 'react-i18next';
|
||||||
|
// import type { MenuProps } from 'antd';
|
||||||
|
|
||||||
|
// const DropdownMenu = () => {
|
||||||
|
// const { data, isError, isLoading } = useGetAllCategories();
|
||||||
|
// const navigate = useNavigate();
|
||||||
|
// const [t] = useTranslation();
|
||||||
|
|
||||||
|
// if (isLoading) {
|
||||||
|
// return <div>Loading...</div>;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (isError || !data?.data?.data) {
|
||||||
|
// return <div>Error loading categories</div>;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// const CategoriesArry = data.data.data.map((item: any) => ({
|
||||||
|
// value: item?.category_translations[0]?.name,
|
||||||
|
// label: item?.id,
|
||||||
|
// }));
|
||||||
|
|
||||||
|
|
||||||
|
// const items: any = CategoriesArry?.map((item: any) => ({
|
||||||
|
// key: item.key,
|
||||||
|
// label: (
|
||||||
|
// <Link rel="noopener noreferrer" to={`/Products?category_id=`+item.label}>
|
||||||
|
// {item.value}
|
||||||
|
// </Link>
|
||||||
|
// ),
|
||||||
|
// icon: item.icon, // You can include the icon if available
|
||||||
|
// disabled: item.disabled,
|
||||||
|
// danger: item.danger,
|
||||||
|
// }));
|
||||||
|
|
||||||
|
// const menu: React.ReactNode = (
|
||||||
|
// <Menu>
|
||||||
|
// {items.map((menuItem: any) => (
|
||||||
|
// <Menu.Item key={menuItem.key} disabled={menuItem.disabled} danger={menuItem.danger}>
|
||||||
|
// {menuItem.label}
|
||||||
|
// </Menu.Item>
|
||||||
|
// ))}
|
||||||
|
// </Menu>
|
||||||
|
// );
|
||||||
|
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <Dropdown menu={{items}} placement="bottomLeft" className="DropdownMenu" trigger={['click']}>
|
||||||
|
// <Button>
|
||||||
|
// <AppstoreOutlined />
|
||||||
|
// {t("Categories")}
|
||||||
|
// <DownOutlined />
|
||||||
|
// </Button>
|
||||||
|
// </Dropdown>
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// export default DropdownMenu;
|
||||||
11
src/Components/Ui/FooterTItleWithSeperator.tsx
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
const FooterTItleWithSeparator = ({ title }: { title: string }) => {
|
||||||
|
const {t} = useTranslation()
|
||||||
|
return (
|
||||||
|
<div className='FooterTItleWithSeparator'>
|
||||||
|
<h1>{t(title)}</h1>
|
||||||
|
<hr />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FooterTItleWithSeparator;
|
||||||
27
src/Components/Ui/HeaderLink.tsx
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { SlArrowRight } from "react-icons/sl";
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import { THeaderLink } from '../../type/app';
|
||||||
|
import { BaseURL } from '../../api/config';
|
||||||
|
|
||||||
|
const HeaderLink = ({text,isMulti,extraText,extraLink}:THeaderLink) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='header_link'>
|
||||||
|
<Link to={"/"} className='first_link'>{t("Home")}</Link>
|
||||||
|
<SlArrowRight className='header_link_svg'/>
|
||||||
|
{
|
||||||
|
isMulti ?
|
||||||
|
<>
|
||||||
|
<Link to={`${extraLink}`} className='first_link'>{ t(extraText || "")}</Link>
|
||||||
|
<SlArrowRight className='header_link_svg'/>
|
||||||
|
</>
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
<span className='page_title_link'>{t(text)}</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HeaderLink
|
||||||
14
src/Components/Ui/MediaButton.tsx
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { IMAGE_BASE_URL } from "../../api/config";
|
||||||
|
|
||||||
|
const MediaButton = ({ img: Image, link, isStatic = true }: any) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link to={link}>
|
||||||
|
<div className='MediaButton'>
|
||||||
|
<span>{isStatic ? <span>{<Image />}</span> : <img src={IMAGE_BASE_URL + Image} alt="ak" width={14} />}</span>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MediaButton;
|
||||||
37
src/Components/Ui/MenuItems.tsx
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Menu } from 'antd';
|
||||||
|
import { MenuItem } from '../../Layout/NavBar/Types';
|
||||||
|
import { menuData } from './MenuItemsData';
|
||||||
|
|
||||||
|
const { SubMenu } = Menu;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const generateMenuItems = (items: MenuItem[]): React.ReactNode => {
|
||||||
|
return items.map((item) => {
|
||||||
|
if (item.children) {
|
||||||
|
return (
|
||||||
|
<SubMenu key={item.key} icon={item.icon} title={item.label}>
|
||||||
|
{generateMenuItems(item.children)}
|
||||||
|
</SubMenu>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<Menu.Item key={item.key}>
|
||||||
|
<a href={`/${item.key}`}>{item.label}</a>
|
||||||
|
</Menu.Item>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const MenuItems: React.FC<{ items: MenuItem[] }> = ({ items }) => {
|
||||||
|
return <Menu mode="vertical">{generateMenuItems(items)}</Menu>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const App = () => {
|
||||||
|
return <MenuItems items={menuData} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default App;
|
||||||
169
src/Components/Ui/MenuItemsData.tsx
Normal file
|
|
@ -0,0 +1,169 @@
|
||||||
|
//// fake data ////
|
||||||
|
|
||||||
|
import { MenuItem } from "../../Layout/NavBar/Types";
|
||||||
|
import { AppstoreOutlined, MailOutlined, SettingOutlined } from '@ant-design/icons';
|
||||||
|
export const menuData: MenuItem[] = [
|
||||||
|
{
|
||||||
|
key: 'sub1',
|
||||||
|
label: 'Moaz',
|
||||||
|
icon: <MailOutlined />,
|
||||||
|
children: [
|
||||||
|
{ key: '1', label: 'Option 1' },
|
||||||
|
{ key: '2', label: 'Option 2' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'sub2',
|
||||||
|
label: 'Navigation Two',
|
||||||
|
icon: <AppstoreOutlined />,
|
||||||
|
children: [
|
||||||
|
{ key: '5', label: 'Option 5' },
|
||||||
|
{ key: '6', label: 'Option 6' },
|
||||||
|
{
|
||||||
|
key: 'sub3',
|
||||||
|
label: 'Submenu',
|
||||||
|
children: [
|
||||||
|
{ key: '7', label: 'Option 7' },
|
||||||
|
{
|
||||||
|
key: 'subsub1',
|
||||||
|
label: 'Sub-Submenu 1',
|
||||||
|
children: [
|
||||||
|
{ key: '8', label: 'Option 8' },
|
||||||
|
{ key: '9', label: 'Option 9' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'sub4',
|
||||||
|
label: 'Navigation Three',
|
||||||
|
icon: <SettingOutlined />,
|
||||||
|
children: [
|
||||||
|
{ key: '9', label: 'Option 9' },
|
||||||
|
{ key: '10', label: 'Option 10' },
|
||||||
|
{ key: '11', label: 'Option 11' },
|
||||||
|
{
|
||||||
|
key: 'subsub2',
|
||||||
|
label: 'Sub-Submenu 2',
|
||||||
|
children: [
|
||||||
|
{ key: '12', label: 'Option 12' },
|
||||||
|
{ key: '13', label: 'Option 13' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'subsub3',
|
||||||
|
label: 'Sub-Submenu 3',
|
||||||
|
children: [
|
||||||
|
{ key: '14', label: 'Option 14' },
|
||||||
|
{ key: '15', label: 'Option 15' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'sub5',
|
||||||
|
label: 'Navigation Four',
|
||||||
|
icon: <SettingOutlined />,
|
||||||
|
children: [
|
||||||
|
{ key: '16', label: 'Option 16' },
|
||||||
|
{ key: '17', label: 'Option 17' },
|
||||||
|
{
|
||||||
|
key: 'subsub4',
|
||||||
|
label: 'Sub-Submenu 4',
|
||||||
|
children: [
|
||||||
|
{ key: '18', label: 'Option 18' },
|
||||||
|
{ key: '19', label: 'Option 19' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'subsub5',
|
||||||
|
label: 'Sub-Submenu 5',
|
||||||
|
children: [
|
||||||
|
{ key: '20', label: 'Option 20' },
|
||||||
|
{ key: '21', label: 'Option 21' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'sub6',
|
||||||
|
label: 'Navigation Five',
|
||||||
|
icon: <SettingOutlined />,
|
||||||
|
children: [
|
||||||
|
{ key: '22', label: 'Option 22' },
|
||||||
|
{ key: '23', label: 'Option 23' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'sub7',
|
||||||
|
label: 'Navigation Six',
|
||||||
|
icon: <SettingOutlined />,
|
||||||
|
children: [
|
||||||
|
{ key: '24', label: 'Option 24' },
|
||||||
|
{ key: '25', label: 'Option 25' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'sub8',
|
||||||
|
label: 'Navigation Seven',
|
||||||
|
icon: <SettingOutlined />,
|
||||||
|
children: [
|
||||||
|
{ key: '26', label: 'Option 26' },
|
||||||
|
{ key: '27', label: 'Option 27' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'sub9',
|
||||||
|
label: 'Navigation Eight',
|
||||||
|
icon: <SettingOutlined />,
|
||||||
|
children: [
|
||||||
|
{ key: '28', label: 'Option 28' },
|
||||||
|
{ key: '29', label: 'Option 29' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'sub10',
|
||||||
|
label: 'Navigation Nine',
|
||||||
|
icon: <SettingOutlined />,
|
||||||
|
children: [
|
||||||
|
{ key: '30', label: 'Option 30' },
|
||||||
|
{ key: '31', label: 'Option 31' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
export const menuItems = [
|
||||||
|
{
|
||||||
|
key: '1',
|
||||||
|
name: '1st menu item',
|
||||||
|
href: 'https://www.antgroup.com',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '2',
|
||||||
|
name: '2nd menu item',
|
||||||
|
href: 'https://www.example.com',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '3',
|
||||||
|
name: '1st menu item',
|
||||||
|
href: 'https://www.antgroup.com',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '4',
|
||||||
|
name: '2nd menu item',
|
||||||
|
href: 'https://www.example.com',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '5',
|
||||||
|
name: '1st menu item',
|
||||||
|
href: 'https://www.antgroup.com',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '6.NavMenus',
|
||||||
|
name: '2nd menu item',
|
||||||
|
href: 'https://www.example.com',
|
||||||
|
},
|
||||||
|
];
|
||||||
13
src/Components/Ui/PreviewButton.tsx
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
const PreviewButton = ({ link }: { link: string }) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
return (
|
||||||
|
<div className='preview_button'>
|
||||||
|
<Link to={link}>
|
||||||
|
<p>{t("Preview")}</p>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PreviewButton;
|
||||||
11
src/Components/Ui/SettingImage.tsx
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const SettingImage = ({isReverse = false}:{isReverse?:boolean}) => {
|
||||||
|
return (
|
||||||
|
<div className={`Setting_image ${isReverse? "rotate":""}`}>
|
||||||
|
<img src="/Home/settingIcon.png" alt="" />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SettingImage
|
||||||
13
src/Components/Ui/SingleLink.tsx
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
const SingleLink = ({name, href}:FooterLinksProps) => {
|
||||||
|
return (
|
||||||
|
<div className='SingleLink'>
|
||||||
|
<Link to={href} className="link">
|
||||||
|
{/* <div><RiArrowRightDoubleLine/></div> */}
|
||||||
|
<h5>{name}</h5>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SingleLink
|
||||||
26
src/Components/Ui/TeamCard.tsx
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { IMAGE_BASE_URL } from '../../api/config';
|
||||||
|
|
||||||
|
interface TeamCardProps {
|
||||||
|
name: string;
|
||||||
|
position: string;
|
||||||
|
image: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TeamCard: React.FC<TeamCardProps> = ({ name, position, image }) => {
|
||||||
|
console.log(image);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='team_card'>
|
||||||
|
<div className='card_image'>
|
||||||
|
<img src={image} alt={`${name}`} />
|
||||||
|
</div>
|
||||||
|
<div className='card_info'>
|
||||||
|
<h3>{name}</h3>
|
||||||
|
<p>{position}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TeamCard;
|
||||||
170
src/Components/Utils/BombBtn/BombBtn.scss
Normal file
|
|
@ -0,0 +1,170 @@
|
||||||
|
.BombBtn{
|
||||||
|
.container-button {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
grid-template-rows: 1fr 1fr;
|
||||||
|
grid-template-areas: "bt-1 bt-2 bt-3"
|
||||||
|
"bt-4 bt-5 bt-6";
|
||||||
|
position: relative;
|
||||||
|
perspective: 800;
|
||||||
|
padding: 0;
|
||||||
|
width: 60px;
|
||||||
|
height: 25px;
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-button:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hover {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bt-1 {
|
||||||
|
grid-area: bt-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bt-2 {
|
||||||
|
grid-area: bt-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bt-3 {
|
||||||
|
grid-area: bt-3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bt-4 {
|
||||||
|
grid-area: bt-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bt-5 {
|
||||||
|
grid-area: bt-5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bt-6 {
|
||||||
|
grid-area: bt-6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bt-1:hover ~ button {
|
||||||
|
transform: rotateX(15deg) rotateY(-15deg) rotateZ(0deg);
|
||||||
|
box-shadow: -2px -2px #18181888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bt-1:hover ~ button::after {
|
||||||
|
animation: shake 0.5s ease-in-out 0.3s;
|
||||||
|
text-shadow: -2px -2px #18181888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bt-3:hover ~ button {
|
||||||
|
transform: rotateX(15deg) rotateY(15deg) rotateZ(0deg);
|
||||||
|
box-shadow: 2px -2px #18181888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bt-3:hover ~ button::after {
|
||||||
|
animation: shake 0.5s ease-in-out 0.3s;
|
||||||
|
text-shadow: 2px -2px #18181888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bt-4:hover ~ button {
|
||||||
|
transform: rotateX(-15deg) rotateY(-15deg) rotateZ(0deg);
|
||||||
|
box-shadow: -2px 2px #18181888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bt-4:hover ~ button::after {
|
||||||
|
animation: shake 0.5s ease-in-out 0.3s;
|
||||||
|
text-shadow: -2px 2px #18181888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bt-6:hover ~ button {
|
||||||
|
transform: rotateX(-15deg) rotateY(15deg) rotateZ(0deg);
|
||||||
|
box-shadow: 2px 2px #18181888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bt-6:hover ~ button::after {
|
||||||
|
animation: shake 0.5s ease-in-out 0.3s;
|
||||||
|
text-shadow: 2px 2px #18181888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hover:hover ~ button::before {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hover:hover ~ button::after {
|
||||||
|
content: attr(data-text);
|
||||||
|
top: -200%;
|
||||||
|
transform: translate(-50%, 0);
|
||||||
|
font-size: 20px;
|
||||||
|
color: var(--secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
position: absolute;
|
||||||
|
padding: 0;
|
||||||
|
width: 60px;
|
||||||
|
height: 25px;
|
||||||
|
background: var(--secondary);
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 900;
|
||||||
|
border: 3px solid var(--secondary);
|
||||||
|
border-radius: 12px;
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
button::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 60px;
|
||||||
|
height: 25px;
|
||||||
|
background-color: var(--secondary);
|
||||||
|
border-radius: 12px;
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
button::after {
|
||||||
|
content: attr(data-text);
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 60px;
|
||||||
|
height: 25px;
|
||||||
|
background-color: transparent;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 900;
|
||||||
|
line-height: 25px;
|
||||||
|
color: var(--primary);
|
||||||
|
border: none;
|
||||||
|
border-radius: 12px;
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes shake {
|
||||||
|
0% {
|
||||||
|
left: 45%;
|
||||||
|
}
|
||||||
|
|
||||||
|
25% {
|
||||||
|
left: 54%;
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
left: 48%;
|
||||||
|
}
|
||||||
|
|
||||||
|
75% {
|
||||||
|
left: 52%;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
left: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/Components/Utils/BombBtn/BombBtn.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import React from 'react'
|
||||||
|
import './BombBtn.scss'
|
||||||
|
|
||||||
|
const BombBtn = () => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='BombBtn'>
|
||||||
|
<div className="container-button" >
|
||||||
|
<div className="hover bt-1" />
|
||||||
|
<div className="hover bt-2" />
|
||||||
|
<div className="hover bt-3" />
|
||||||
|
<div className="hover bt-4" />
|
||||||
|
<div className="hover bt-5" />
|
||||||
|
<div className="hover bt-6" />
|
||||||
|
<button data-text={"15% off"} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BombBtn
|
||||||
47
src/Components/Utils/FileInput/File.tsx
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { Button, Upload, UploadFile } from 'antd'
|
||||||
|
import { UploadOutlined } from '@ant-design/icons';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const File = ({ label,set }: any) => {
|
||||||
|
const {t} = useTranslation();
|
||||||
|
const imageUrl = '';
|
||||||
|
|
||||||
|
const fileList: UploadFile[] = [
|
||||||
|
{
|
||||||
|
uid: '-1',
|
||||||
|
name: '',
|
||||||
|
status: 'done',
|
||||||
|
url: imageUrl,
|
||||||
|
thumbUrl: imageUrl,
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const FilehandleChange = (value:any) => {
|
||||||
|
set(value?.file?.originFileObj)
|
||||||
|
};
|
||||||
|
const customRequest = async ({ onSuccess}: any) => {
|
||||||
|
onSuccess();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="TalabeeField">
|
||||||
|
<label htmlFor={label} className="text" >
|
||||||
|
{(`${label}`)}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<Upload
|
||||||
|
listType="picture"
|
||||||
|
maxCount={1}
|
||||||
|
className='w-100 upload_file'
|
||||||
|
defaultFileList={[...fileList]}
|
||||||
|
onChange={ FilehandleChange}
|
||||||
|
customRequest={customRequest}
|
||||||
|
>
|
||||||
|
<Button className='w-100 partner_image' icon={<UploadOutlined />}>{t("upload_image")}</Button>
|
||||||
|
</Upload>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default File
|
||||||
117
src/Components/Utils/Loading/Loading.scss
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
.Loading{
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
width: 200px;
|
||||||
|
height: 60px;
|
||||||
|
position: relative;
|
||||||
|
left: 40%;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: var(--fifthly);
|
||||||
|
left: 15%;
|
||||||
|
transform-origin: 50%;
|
||||||
|
animation: circle7124 .5s alternate infinite ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes circle7124 {
|
||||||
|
0% {
|
||||||
|
top: 60px;
|
||||||
|
height: 5px;
|
||||||
|
border-radius: 50px 50px 25px 25px;
|
||||||
|
transform: scaleX(1.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
40% {
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
transform: scaleX(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
top: 0%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle:nth-child(2) {
|
||||||
|
left: 45%;
|
||||||
|
animation-delay: .2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle:nth-child(3) {
|
||||||
|
left: auto;
|
||||||
|
right: 15%;
|
||||||
|
animation-delay: .3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow {
|
||||||
|
width: 20px;
|
||||||
|
height: 4px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: var(--fifthly);
|
||||||
|
position: absolute;
|
||||||
|
opacity: .5;
|
||||||
|
top: 62px;
|
||||||
|
transform-origin: 50%;
|
||||||
|
z-index: -1;
|
||||||
|
left: 15%;
|
||||||
|
filter: blur(1px);
|
||||||
|
animation: shadow046 .5s alternate infinite ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes shadow046 {
|
||||||
|
0% {
|
||||||
|
transform: scaleX(1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
40% {
|
||||||
|
transform: scaleX(1);
|
||||||
|
opacity: .7;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: scaleX(.2);
|
||||||
|
opacity: .4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow:nth-child(4) {
|
||||||
|
left: 45%;
|
||||||
|
animation-delay: .2s
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow:nth-child(5) {
|
||||||
|
left: auto;
|
||||||
|
right: 15%;
|
||||||
|
animation-delay: .3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.loading_page{
|
||||||
|
width: 100vw !important;height: 50vh !important;
|
||||||
|
display: flex !important;justify-content: space-between !important;align-items: center !important; flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
:where(.css-dev-only-do-not-override-1ae8k9u).ant-spin .ant-spin-dot-item ,:where(.css-1adbn6x).ant-spin .ant-spin-dot-item{
|
||||||
|
background-color: var(--primary);
|
||||||
|
}
|
||||||
|
:where(.css-dev-only-do-not-override-1ae8k9u).ant-spin, :where(.css-1adbn6x).ant-spin .ant-spin-dot-item{
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.spinner{
|
||||||
|
color: var(--primary);
|
||||||
|
padding-block: 30px;
|
||||||
|
}
|
||||||
19
src/Components/Utils/Loading/Loading.tsx
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
import React from 'react'
|
||||||
|
import './Loading.scss'
|
||||||
|
const Loading = () => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="Loading">
|
||||||
|
<div className="wrapper">
|
||||||
|
<div className="circle"></div>
|
||||||
|
<div className="circle"></div>
|
||||||
|
<div className="circle"></div>
|
||||||
|
<div className="shadow"></div>
|
||||||
|
<div className="shadow"></div>
|
||||||
|
<div className="shadow"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Loading
|
||||||
13
src/Components/Utils/Loading/LoadingAntd.tsx
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { Spin } from 'antd';
|
||||||
|
import './Loading.scss'
|
||||||
|
|
||||||
|
const LoadingAntd = () => {
|
||||||
|
return (
|
||||||
|
<div className='loading_page'>
|
||||||
|
<img src='/Logo/Logo.png' width={100} alt='logo'/>
|
||||||
|
<Spin className='LoadingAntd' size='large' />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LoadingAntd
|
||||||
15
src/Components/Utils/Loading/LoadingButton.tsx
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import React from "react";
|
||||||
|
import { Button, Spinner } from "reactstrap";
|
||||||
|
|
||||||
|
const LoadingButton = ({ className = 'LoadinButton',isLoading = false, ...props }) => {
|
||||||
|
return (
|
||||||
|
<Button className={className} disabled={isLoading} {...props}>
|
||||||
|
{isLoading ? <Spinner style={{ marginRight: "10px" }} size="sm" /> : null}
|
||||||
|
<span >{props.children}</span>
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export { LoadingButton };
|
||||||
8
src/Components/Utils/Loading/Spinner.tsx
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { Spin } from 'antd';
|
||||||
|
|
||||||
|
const Spinner: React.FC = () =>
|
||||||
|
<>
|
||||||
|
<Spin className='LoadingAntd spinner' size='large'/>
|
||||||
|
</>
|
||||||
|
export default Spinner
|
||||||
17
src/Components/Utils/Search/Empty.tsx
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
const Empty = () => {
|
||||||
|
const [t] = useTranslation()
|
||||||
|
return (
|
||||||
|
<div className='Empty'>
|
||||||
|
<img src="/icon/notfound_search.png" alt="" />
|
||||||
|
<h1>{t("There are no suitable products")}</h1>
|
||||||
|
<p>
|
||||||
|
{t("Please try using other keywords to find the product name")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Empty
|
||||||
11
src/Components/Utils/Search/Search.tsx
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
import SearchWithDrawer from '../../HOC/SearchWithDrawer'
|
||||||
|
|
||||||
|
const ViewSearch = () => {
|
||||||
|
return (
|
||||||
|
<div className='ViewSearch'>
|
||||||
|
<SearchWithDrawer />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ViewSearch
|
||||||
85
src/Components/Utils/Search/SearchButton.tsx
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
|
import { Select, Spin } from 'antd';
|
||||||
|
import { useNavigate, useSearchParams } from 'react-router-dom';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { LuSearch } from 'react-icons/lu';
|
||||||
|
// import { Product } from '../../../types/item';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import { useGetProducts } from '../../../api/products';
|
||||||
|
|
||||||
|
interface SearchButtonProps {
|
||||||
|
setOpen: (open: boolean) => void;
|
||||||
|
setNoDataFound: (noData: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SearchButton: React.FC<SearchButtonProps> = ({ setOpen, setNoDataFound }) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [searchParams] = useSearchParams();
|
||||||
|
const [query, setQuery] = useState<string | null>(searchParams.get('search'));
|
||||||
|
|
||||||
|
const { data, isLoading } = useGetProducts({
|
||||||
|
name: query,
|
||||||
|
});
|
||||||
|
|
||||||
|
const BaseProducts = (data?.data as Product[]) || [];
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setNoDataFound(!isLoading && BaseProducts.length < 1);
|
||||||
|
}, [isLoading, BaseProducts, setNoDataFound]);
|
||||||
|
|
||||||
|
const options = BaseProducts.map((product: any) => ({
|
||||||
|
value: product.id,
|
||||||
|
label: product?.name as string,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const debouncedSearchChange = useCallback(
|
||||||
|
_.debounce((value: string) => {
|
||||||
|
console.log(value);
|
||||||
|
|
||||||
|
setQuery(value);
|
||||||
|
navigate(`${window.location.pathname}?search=${value}`, {
|
||||||
|
replace: true,
|
||||||
|
});
|
||||||
|
}, 500), // Adjust the debounce delay (in milliseconds) as needed
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSearchChange = (value: string) => {
|
||||||
|
debouncedSearchChange(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelectChange = (value: number) => {
|
||||||
|
console.log(value);
|
||||||
|
|
||||||
|
const selectedProduct = BaseProducts.find(product => product?.id === value);
|
||||||
|
if (selectedProduct) {
|
||||||
|
setOpen(false);
|
||||||
|
navigate(`/product/${selectedProduct?.id}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const filterOption = (input: string, option?: { label: string }) => {
|
||||||
|
if (!option) return false;
|
||||||
|
return option?.label.toLowerCase().includes(input.toLowerCase());
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
className='InputAutoComplete'
|
||||||
|
suffixIcon={<LuSearch />}
|
||||||
|
placeholder={t('Search..') as string}
|
||||||
|
allowClear
|
||||||
|
showSearch
|
||||||
|
loading={isLoading}
|
||||||
|
onSearch={handleSearchChange}
|
||||||
|
onChange={handleSelectChange}
|
||||||
|
options={options}
|
||||||
|
optionFilterProp="label"
|
||||||
|
filterOption={filterOption}
|
||||||
|
notFoundContent={isLoading ? <Spin /> : null}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SearchButton;
|
||||||
182
src/Components/Utils/SearchBar/SearchBar.scss
Normal file
|
|
@ -0,0 +1,182 @@
|
||||||
|
.SearchBar {
|
||||||
|
.group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
max-width: 190px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
padding: 0 1rem;
|
||||||
|
padding-left: 2.5rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
outline: none;
|
||||||
|
font-weight: 500;
|
||||||
|
background: var(--primary);
|
||||||
|
color: var(--bg);
|
||||||
|
border: none;
|
||||||
|
box-shadow: 2px 2px 7px 0 var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.input::placeholder {
|
||||||
|
color: var(--bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
// background: #000;
|
||||||
|
position: absolute;
|
||||||
|
left: 1rem;
|
||||||
|
fill: var(--bg);
|
||||||
|
width: 1rem;
|
||||||
|
height: 1rem;
|
||||||
|
top: 0 ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.InputAutoComplete{
|
||||||
|
width: 100%;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: 30px !important;
|
||||||
|
box-shadow: 0 4px 10px 0 rgba(0, 0, 0, 0.05);
|
||||||
|
.ant-select-selector{
|
||||||
|
border-radius: 30px !important;
|
||||||
|
border: 1.4px solid var(--white) !important;
|
||||||
|
padding-left: 15px !important;
|
||||||
|
position: relative;
|
||||||
|
span{
|
||||||
|
color: var(--gray) !important;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-select-arrow{
|
||||||
|
@include Flex;
|
||||||
|
font-size: 32px;
|
||||||
|
color: var(--white) !important;
|
||||||
|
background: var(--primary);
|
||||||
|
width: 40px;height: 40px;
|
||||||
|
border-radius: 50%;
|
||||||
|
top: 20%;
|
||||||
|
right: 5px;
|
||||||
|
svg{
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.Drawer_search_Body{
|
||||||
|
width: 90%;
|
||||||
|
margin-inline: auto;
|
||||||
|
.recent_search_text{
|
||||||
|
display: flex; justify-content: space-between;align-items: center;
|
||||||
|
.recent_search_text_container{
|
||||||
|
margin-block: 8px;
|
||||||
|
width: 100%;
|
||||||
|
display: flex; justify-content: space-between;
|
||||||
|
div{
|
||||||
|
display: flex;
|
||||||
|
p{
|
||||||
|
text-transform: capitalize;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
svg{
|
||||||
|
opacity: .6;
|
||||||
|
font-size: 20px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
svg{
|
||||||
|
font-size: 10px;
|
||||||
|
opacity: .6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search_first_section{
|
||||||
|
width: 91%;
|
||||||
|
margin-inline: auto;
|
||||||
|
display: flex;justify-content: space-between;align-items: center;
|
||||||
|
.delete_icon{
|
||||||
|
height: 75px;
|
||||||
|
cursor: pointer;
|
||||||
|
svg{
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.not_found_section{
|
||||||
|
@include Flex;
|
||||||
|
.Empty{
|
||||||
|
@include Flex; flex-direction: column;
|
||||||
|
p,h1{
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ViewSearch{
|
||||||
|
// background: #000;
|
||||||
|
width: 100%;
|
||||||
|
.ant-drawer .ant-drawer-content {
|
||||||
|
height: 50% !important ;width: 100% !important;
|
||||||
|
min-height: 50% !important;
|
||||||
|
display: flex; flex-direction: column;
|
||||||
|
border-radius: 5px 0 0 5px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.search_comp{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media screen and (max-width:1000px) {
|
||||||
|
// .InputAutoComplete{
|
||||||
|
// width: 85%;
|
||||||
|
// height: 42px;
|
||||||
|
// @include Flex;
|
||||||
|
// margin-inline: auto;
|
||||||
|
// border-radius: 10px !important;
|
||||||
|
// margin-bottom: 10px;
|
||||||
|
// box-shadow: rgba(0, 0, 0, 0);
|
||||||
|
// .ant-select-selector{
|
||||||
|
// background: #000 !important;
|
||||||
|
// background: var(--whiteGray) !important;
|
||||||
|
// border-radius: 10px !important;
|
||||||
|
// border: 1.4px solid var(--whiteGray) !important;
|
||||||
|
// padding-left: 15px !important;
|
||||||
|
// span{
|
||||||
|
// color: var(--gray) !important;
|
||||||
|
// font-size: 15px;
|
||||||
|
// font-weight: 500;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// .ant-select-arrow{
|
||||||
|
// @include Flex;
|
||||||
|
// font-size: 32px;
|
||||||
|
// color: var(--gray) !important;
|
||||||
|
// background: transparent;
|
||||||
|
// width: 40px;height: 40px;
|
||||||
|
// border-radius: 50%;
|
||||||
|
// top: 16%;
|
||||||
|
// right: 5px;
|
||||||
|
// svg{
|
||||||
|
// font-size: 20px;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
.not_found_section{
|
||||||
|
.Empty{
|
||||||
|
h1 , p{
|
||||||
|
text-align: center;
|
||||||
|
font-size: 12px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/Components/Utils/SearchBar/SearchBar.tsx
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import React from "react";
|
||||||
|
import "./SearchBar.scss";
|
||||||
|
const SearchBar = () => {
|
||||||
|
return (
|
||||||
|
<div className="SearchBar">
|
||||||
|
<div className="group">
|
||||||
|
<svg className="icon" viewBox="0 0 24 24">
|
||||||
|
<g>
|
||||||
|
<path d="M21.53 20.47l-3.66-3.66C19.195 15.24 20 13.214 20 11c0-4.97-4.03-9-9-9s-9 4.03-9 9 4.03 9 9 9c2.215 0 4.24-.804 5.808-2.13l3.66 3.66c.147.146.34.22.53.22s.385-.073.53-.22c.295-.293.295-.767.002-1.06zM3.5 11c0-4.135 3.365-7.5 7.5-7.5s7.5 3.365 7.5 7.5-3.365 7.5-7.5 7.5-7.5-3.365-7.5-7.5z"></path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
<input placeholder="Search" type="search" className="input" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SearchBar;
|
||||||