Initial commit
This commit is contained in:
commit
3d8437ecf6
|
|
@ -0,0 +1,20 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
env: { browser: true, es2020: true },
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:react/jsx-runtime",
|
||||
"plugin:react-hooks/recommended",
|
||||
],
|
||||
ignorePatterns: ["dist", ".eslintrc.cjs"],
|
||||
parserOptions: { ecmaVersion: "latest", sourceType: "module" },
|
||||
settings: { react: { version: "18.2" } },
|
||||
plugins: ["react-refresh"],
|
||||
rules: {
|
||||
"react-refresh/only-export-components": [
|
||||
"warn",
|
||||
{ allowConstantExport: true },
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/fav.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
rel="preload"
|
||||
as="font"
|
||||
href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,400;0,500;0,600;0,700;1,200&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&family=Manrope:wght@200;300;400;500;600;700;800&family=Montserrat:wght@400;500;600;700&family=Poppins:ital,wght@1,200&display=swap"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Arimo:ital,wght@0,400..700;1,400..700&family=Crimson+Pro:ital,wght@0,200..900;1,200..900&family=Dhurjati&family=Diplomata+SC&family=Inconsolata:wght@200..900&family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&family=Lexend+Zetta:wght@200;300;400;500;700&family=Libre+Franklin:ital,wght@0,100..900;1,100..900&family=Podkova:wght@400..800&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Roboto+Slab:wght@200;300;400;500;600;700&family=VT323&family=Cute+Font&family=Kumar+One&family=Lemon&family=Lily+Script+One&family=M+PLUS+Rounded+1c&family=Maiden+Orange&family=Kode+Mono:wght@400..700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Fredoka:wght@300..700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Freeman&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Concert+One&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Calistoga&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Calistoga&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<!-- <link href="https://vjs.zencdn.net/8.3.0/video-js.css" rel="stylesheet" /> -->
|
||||
<!-- <link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet"> -->
|
||||
|
||||
<title>Pozo Retail Software</title>
|
||||
<!-- mohan -->
|
||||
<!-- <script>
|
||||
// Disable right-click menu and common hotkeys
|
||||
document.addEventListener("contextmenu", (event) => event.preventDefault());
|
||||
document.addEventListener("keydown", (event) => {
|
||||
if (
|
||||
(event.ctrlKey && event.shiftKey && ["I", "J", "C"].includes(event.key.toUpperCase())) ||
|
||||
(event.ctrlKey && ["U", "S"].includes(event.key.toUpperCase())) ||
|
||||
event.key === "F12"
|
||||
) {
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
</script> -->
|
||||
<!-- <script src="https://cdn.jsdelivr.net/npm/eruda"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/eruda-network"></script>
|
||||
<script>
|
||||
(function () {
|
||||
// Always enable Eruda
|
||||
eruda.init();
|
||||
eruda.add(erudaNetwork);
|
||||
eruda.show();
|
||||
|
||||
console.log("✅ Eruda Debug Console Loaded (Always On)");
|
||||
|
||||
// Axios interceptor for API logs
|
||||
setTimeout(() => {
|
||||
if (window.axios) {
|
||||
axios.interceptors.request.use((config) => {
|
||||
console.log(
|
||||
"[API Request]",
|
||||
config.method?.toUpperCase(),
|
||||
config.url,
|
||||
config.data
|
||||
);
|
||||
return config;
|
||||
});
|
||||
axios.interceptors.response.use(
|
||||
(response) => {
|
||||
console.log(
|
||||
"[API Response]",
|
||||
response.config.url,
|
||||
response.status,
|
||||
response.data
|
||||
);
|
||||
return response;
|
||||
},
|
||||
(error) => {
|
||||
console.error(
|
||||
"[API Error]",
|
||||
error.config?.url,
|
||||
error.message
|
||||
);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
console.log("✅ Axios interceptors attached");
|
||||
} else {
|
||||
console.warn("⚠️ Axios not found on window");
|
||||
}
|
||||
}, 2000);
|
||||
})();
|
||||
</script> -->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
<script
|
||||
type="module"
|
||||
href="@import url('https://fonts.googleapis.com/css2?family=Calistoga&display=swap')"
|
||||
></script>
|
||||
<!-- <script src="https://vjs.zencdn.net/8.3.0/video.min.js"></script> -->
|
||||
<!-- <script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script> -->
|
||||
</body>
|
||||
|
||||
<!-- <iframe id="ifmcontentstoprint" style="
|
||||
height: 0px;
|
||||
width: 0px;
|
||||
position: absolute;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
/* font-family: 'Poppins', sans-serif; */
|
||||
"></iframe> -->
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,98 @@
|
|||
{
|
||||
"name": "retail-application",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "node --max-old-space-size=4096 node_modules/vite/bin/vite.js build",
|
||||
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
|
||||
"preview": "vite preview",
|
||||
"format": "prettier --write ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/plots": "^1.2.6",
|
||||
"@autocomplete/material-ui": "0.0.17",
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/styled": "^11.11.5",
|
||||
"@material-ui/lab": "^4.0.0-alpha.61",
|
||||
"@mui/material": "^5.15.18",
|
||||
"@reduxjs/toolkit": "^1.9.5",
|
||||
"@tanstack/react-query": "^5.90.11",
|
||||
"@tanstack/react-query-devtools": "^5.91.1",
|
||||
"antd": "^5.17.4",
|
||||
"antd-img-crop": "^4.22.0",
|
||||
"aos": "^2.3.4",
|
||||
"axios": "^1.7.2",
|
||||
"browser-image-compression": "^2.0.2",
|
||||
"classnames": "^2.5.1",
|
||||
"cropperjs": "^1.6.2",
|
||||
"crypto-js": "^4.1.1",
|
||||
"date-fns": "^4.1.0",
|
||||
"devtools-detect": "^4.0.2",
|
||||
"exceljs": "^4.3.0",
|
||||
"google-maps-react": "^2.0.6",
|
||||
"highcharts": "^11.4.3",
|
||||
"highcharts-react-official": "^3.2.1",
|
||||
"history": "^5.3.0",
|
||||
"html2canvas": "^1.4.1",
|
||||
"html2pdf": "^0.0.11",
|
||||
"html2pdf.js": "^0.10.3",
|
||||
"html5-qrcode": "^2.3.8",
|
||||
"jquery": "^3.7.1",
|
||||
"js-cookie": "^3.0.5",
|
||||
"jsbarcode": "^3.11.6",
|
||||
"jspdf": "^2.5.1",
|
||||
"lucide-react": "^0.536.0",
|
||||
"material-ui": "^0.20.2",
|
||||
"moment": "^2.30.1",
|
||||
"mui-autocomplete": "^2.0.1",
|
||||
"number-to-words": "^1.2.4",
|
||||
"pdf-lib": "^1.17.1",
|
||||
"qrcode": "^1.5.3",
|
||||
"qrcode.react": "^4.2.0",
|
||||
"react": "^18.3.1",
|
||||
"react-beautiful-dnd": "^13.1.1",
|
||||
"react-color": "^2.19.3",
|
||||
"react-countup": "^6.5.3",
|
||||
"react-device-detect": "^2.2.3",
|
||||
"react-devtools": "^5.2.0",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-icons": "^4.12.0",
|
||||
"react-image-crop": "^11.0.10",
|
||||
"react-qr-code": "^2.0.13",
|
||||
"react-redux": "^8.1.2",
|
||||
"react-router-dom": "^6.23.1",
|
||||
"react-select": "^5.8.0",
|
||||
"react-signature-canvas": "^1.0.7",
|
||||
"react-speech-recognition": "^3.10.0",
|
||||
"react-timer-hook": "^3.0.7",
|
||||
"react-transition-group": "^4.4.5",
|
||||
"recharts": "^3.5.0",
|
||||
"string-similarity": "^4.0.4",
|
||||
"tesseract.js": "^6.0.0",
|
||||
"universal-cookie": "^6.1.3",
|
||||
"webfontloader": "^1.6.28",
|
||||
"xlsx": "^0.18.5",
|
||||
"zustand": "^5.0.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@vitejs/plugin-react": "^4.3.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-react": "^7.34.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"eslint-plugin-react-refresh": "^0.4.7",
|
||||
"prettier": "^3.5.3",
|
||||
"rollup-plugin-obfuscator": "^1.1.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"sass": "^1.77.2",
|
||||
"terser": "^5.31.3",
|
||||
"vite": "^4.5.3",
|
||||
"vite-plugin-obfuscator": "^1.0.5",
|
||||
"vite-plugin-remove-console": "^2.2.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<system.webServer>
|
||||
<rewrite>
|
||||
<rules>
|
||||
<rule name="React Routes" stopProcessing="true">
|
||||
<match url=".*" />
|
||||
<conditions logicalGrouping="MatchAll">
|
||||
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
|
||||
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
|
||||
</conditions>
|
||||
<action type="Rewrite" url="/" />
|
||||
</rule>
|
||||
</rules>
|
||||
</rewrite>
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
Binary file not shown.
|
|
@ -0,0 +1,31 @@
|
|||
ENV_BASE_URL='/'
|
||||
ENV_COMMON_BASE_URL='http://192.168.1.16:3000/'
|
||||
# ENV_API_URL='http://192.168.1.25:8001'
|
||||
# ENV_API_URL='http://api.pozo.co.in/Retailapi_UnderTest'
|
||||
# ENV_API_URL='https://api.pozo.dev/pozo-retail-api'
|
||||
# ENV_API_URL_COMMON='https://api.pozo.dev/pozo-common-api'
|
||||
# ENV_API_URL_TOKEN='https://api.pozo.dev/JwtToken'
|
||||
ENV_API_URL='http://192.168.1.37:8012'
|
||||
ENV_API_URL_COMMON='http://192.168.1.37:8013'
|
||||
ENV_API_URL_TOKEN='http://192.168.1.37:8001'
|
||||
ENV_API_URL_OCR='http://192.168.1.37:8070'
|
||||
# ENV_API_URL='https://api.pozo.app/pozo-retail-api'
|
||||
# ENV_API_URL_COMMON='https://api.pozo.app/pozo-common-api'
|
||||
# ENV_API_URL_TOKEN='https://api.pozo.app/JwtToken'
|
||||
# ENV_API_URL='https://www.pozo.dev/pozo-retail-api'
|
||||
# ENV_API_URL_COMMON='https://www.pozo.dev/pozo-common-api'
|
||||
# ENV_API_URL_TOKEN='https://www.pozo.dev/JwtToken'
|
||||
ENV_IMAGE_UPLOAD_API_URL="http://192.168.1.38/"
|
||||
ENV_SECRET_KEY="3a939a2eed2cca4b64cd47f51b23b135b2b9b765273f695d47682ea803c8429d"
|
||||
ENV_URL_SECRET_KEY="f2ef79b8b2d4fc1cc569726a5a753552257b4ff2872d6a71cf3119bce3f07c1b"
|
||||
ENV_MAIN_BASE_URL='http://192.168.1.22:3015/'
|
||||
ENV_SIGNALR_SERVER_URL='https://api.pozo.dev/'
|
||||
ENV_IFSC_API_URL = "https://ifsc.razorpay.com"
|
||||
ENV_PAYMENT_DEVICE_URL='https://pozo.dev/PaymentDevice/PaymentDevice/api/upload-transaction'
|
||||
ENV_PAYMENT_STATUS_GET_URL='https://pozo.dev/PaymentDevice/PaymentDevice/api/get-transaction-status'
|
||||
ENV_ANDROID_PRINTER= 'https://pozo.dev/downloads/resources/POZO%20Printer.apk'
|
||||
ENV_ANDROID_KIOSK= 'https://pozo.app/downloads/resources/POZO%20KIOSK.apk'
|
||||
ENV_ANDROID_HANDHELD= 'https://pozo.dev/downloads/resources/Handheld.apk'
|
||||
ENV_ANDROID_BILLING= 'https://pozo.dev/downloads/resources/PozoBillingApp.apk'
|
||||
ENV_EMAIL_API='http://192.168.1.37:8014'
|
||||
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
#221 server
|
||||
|
||||
# ENV_BASE_URL='/apps/retail/'
|
||||
# ENV_COMMON_BASE_URL='http://pozo.co.in'
|
||||
# ENV_API_URL='http://api.pozo.co.in/Retailapi_UnderTest'
|
||||
# ENV_API_URL_COMMON='http://api.pozo.co.in/Pozocommonapi_UnderTest'
|
||||
# # ENV_API_URL='http://api.pozo.co.in/Retailapi/'
|
||||
# # ENV_API_URL_COMMON='http://api.pozo.co.in/Pozocommonapi'
|
||||
# ENV_IMAGE_UPLOAD_API_URL="https://api.pozo.app/pozo-common-image-api/"
|
||||
# ENV_SECRET_KEY="3a939a2eed2cca4b64cd47f51b23b135b2b9b765273f695d47682ea803c8429d"
|
||||
# ENV_URL_SECRET_KEY="f2ef79b8b2d4fc1cc569726a5a753552257b4ff2872d6a71cf3119bce3f07c1b"
|
||||
# ENV_MAIN_BASE_URL='http://pozo.co.in/apps/retail/'
|
||||
# ENV_CUSTOM_PAYMENT_URL='https://pozo.app/CustomPaymentGateway/CustomPaymentGateway'
|
||||
# ENV_IFSC_API_URL = "https://ifsc.razorpay.com"
|
||||
# ENV_ANDROID_HANDHELD= 'https://pozo.app/downloads/resources/Handheld.apk'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# live Server (173 server)
|
||||
|
||||
ENV_BASE_URL='/apps/retail/'
|
||||
ENV_COMMON_BASE_URL='https://pozo.app'
|
||||
ENV_API_URL='https://api.pozo.app/pozo-retail-api'
|
||||
ENV_API_URL_COMMON='https://api.pozo.app/pozo-common-api'
|
||||
ENV_API_URL_TOKEN='https://api.pozo.app/JwtToken'
|
||||
ENV_API_URL_OCR='http://192.168.1.37:8070'
|
||||
ENV_IMAGE_UPLOAD_API_URL="https://api.pozo.app/pozo-common-image-api/"
|
||||
ENV_SECRET_KEY="3a939a2eed2cca4b64cd47f51b23b135b2b9b765273f695d47682ea803c8429d"
|
||||
ENV_URL_SECRET_KEY="f2ef79b8b2d4fc1cc569726a5a753552257b4ff2872d6a71cf3119bce3f07c1b"
|
||||
ENV_MAIN_BASE_URL='https://pozo.app/apps/retail/'
|
||||
ENV_CUSTOM_PAYMENT_URL='https://pozo.app/CustomPaymentGateway/CustomPaymentGateway'
|
||||
ENV_IFSC_API_URL = "https://ifsc.razorpay.com"
|
||||
ENV_PAYMENT_DEVICE_URL='https://pozo.app/PaymentDevice/PaymentDevice/api/upload-transaction'
|
||||
ENV_PAYMENT_STATUS_GET_URL='https://pozo.app/PaymentDevice/PaymentDevice/api/get-transaction-status'
|
||||
ENV_ANDROID_PRINTER= 'https://pozo.app/downloads/resources/POZO%20Printer.apk'
|
||||
ENV_ANDROID_KIOSK= 'https://pozo.app/downloads/resources/POZO%20KIOSK.apk'
|
||||
ENV_ANDROID_HANDHELD= 'https://pozo.app/downloads/resources/Handheld.apk'
|
||||
ENV_ANDROID_BILLING= 'https://pozo.app/downloads/resources/PozoApp.apk'
|
||||
ENV_EMAIL_API='https://api.pozo.app/pozo-sms-email-template-api'
|
||||
ENV_SIGNALR_SERVER_URL='https://api.pozo.app/'
|
||||
|
||||
#(172 server)
|
||||
|
||||
# ENV_BASE_URL='/apps/retail/'
|
||||
# ENV_COMMON_BASE_URL='https://pozo.dev'
|
||||
# ENV_API_URL='https://api.pozo.dev/pozo-retail-api'
|
||||
# ENV_API_URL_COMMON='https://api.pozo.dev/pozo-common-api'
|
||||
# ENV_API_URL_TOKEN='https://api.pozo.dev/JwtToken'
|
||||
# ENV_API_URL_OCR='https://api.pozo.dev/pozo-scantext-api'
|
||||
# ENV_IMAGE_UPLOAD_API_URL="https://api.pozo.dev/pozo-common-image-api"
|
||||
# ENV_SECRET_KEY="3a939a2eed2cca4b64cd47f51b23b135b2b9b765273f695d47682ea803c8429d"
|
||||
# ENV_URL_SECRET_KEY="f2ef79b8b2d4fc1cc569726a5a753552257b4ff2872d6a71cf3119bce3f07c1b"
|
||||
# ENV_MAIN_BASE_URL='https://pozo.dev/apps/retail/'
|
||||
# ENV_SIGNALR_SERVER_URL='https://api.pozo.dev/'
|
||||
# ENV_CUSTOM_PAYMENT_URL='https://pozo.app/CustomPaymentGateway/CustomPaymentGateway'
|
||||
# ENV_IFSC_API_URL = "https://ifsc.razorpay.com"
|
||||
# ENV_PAYMENT_DEVICE_URL='https://pozo.dev/PaymentDevice/PaymentDevice/api/upload-transaction'
|
||||
# ENV_PAYMENT_STATUS_GET_URL='https://pozo.dev/PaymentDevice/PaymentDevice/api/get-transaction-status'
|
||||
# # ENV_PAYMENT_DEVICE_URL='https://www.plutuscloudserviceuat.in:8201/API/CloudBasedIntegration/V1/UploadBilledTransaction'
|
||||
# # ENV_PAYMENT_STATUS_GET_URL='https://www.plutuscloudserviceuat.in:8201/API/CloudBasedIntegration/V1/GetCloudBasedTxnStatus'
|
||||
# ENV_ANDROID_PRINTER= 'https://pozo.dev/downloads/resources/POZO%20Printer.apk'
|
||||
# ENV_ANDROID_KIOSK= 'https://pozo.dev/downloads/resources/POZO%20KIOSK.apk'
|
||||
# ENV_ANDROID_HANDHELD= 'https://pozo.dev/downloads/resources/Handheld.apk'
|
||||
# ENV_ANDROID_BILLING= 'https://pozo.dev/downloads/resources/PozoApp.apk'
|
||||
# ENV_EMAIL_API='https://api.pozo.dev/pozo-sms-email-template-api'
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
|
|
@ -0,0 +1,265 @@
|
|||
// AppRoutes.jsx
|
||||
import React, { useEffect, useState, useRef, } from 'react';
|
||||
import { Routes, Route } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import ProtectedRoutes from './ProtectedRoutes';
|
||||
import SelfBooking from './Pages/SelfBooking/SelfBooking.jsx'
|
||||
import { isMobile, isIOS } from "react-device-detect";
|
||||
// const { routesConfig }=lazy(()=>import('./routesConfig'));
|
||||
import { routesConfig } from './routesConfig';
|
||||
import {
|
||||
ChangeAppExpDateData,
|
||||
changeHeightforExpDate,
|
||||
getAppSubscriptionDate,
|
||||
GlobalItemCard,
|
||||
} from './Features/BookingScreen/BookingData/BookingData.js';
|
||||
import {
|
||||
checkSession,
|
||||
GenerateLogout,
|
||||
} from './Features/BrachLogin/BranchLogin.js';
|
||||
import {
|
||||
clearSession,
|
||||
getSession,
|
||||
TokendecryptedValuesFun,
|
||||
} from './Services/Others.js';
|
||||
import devtools from 'devtools-detect';
|
||||
import KisokSelBooking from './Pages/SelfBooking/KisokSelBooking.jsx';
|
||||
import IndividualBooking from './Pages/SelfBooking/IndividualBooking.jsx';
|
||||
const commonSubDir = import.meta.env.ENV_COMMON_BASE_URL;
|
||||
const subDirectory = import.meta.env.ENV_BASE_URL;
|
||||
import "../ownLib/my-ui-lib.css"
|
||||
import CustomerMenuPage from './Pages/Reports/MenuQRCode/CustomerMenuPage.jsx';
|
||||
import WeightScaleApp from './Pages/BookingScreen/WeightscaleApp.jsx';
|
||||
const AppRoutes = () => {
|
||||
const navigate = useNavigate();
|
||||
const dispatch = useDispatch();
|
||||
const ItemCard = useSelector(GlobalItemCard);
|
||||
const [remainingDays, setRemainingDays] = useState(null);
|
||||
const prevRemainingDays = useRef(null);
|
||||
const [sessionData, setSessionData] = useState(null);
|
||||
const [devToolsOpen, setDevToolsOpen] = useState(false);
|
||||
useEffect(() => {
|
||||
const handlePopState = (e) => {
|
||||
const SessionId = getSession('SessionId');
|
||||
if (!SessionId) {
|
||||
alert(
|
||||
'Session invalid and Unauthorized action detected. Redirecting to login...'
|
||||
);
|
||||
clearSession();
|
||||
window.location.replace(`${commonSubDir}`);
|
||||
} else {
|
||||
window.history.go(1);
|
||||
}
|
||||
};
|
||||
|
||||
// Add event listener on mount
|
||||
window.addEventListener('popstate', handlePopState);
|
||||
|
||||
// Clean up the event listener on unmount
|
||||
return () => {
|
||||
window.removeEventListener('popstate', handlePopState);
|
||||
};
|
||||
}, []);
|
||||
|
||||
//cmd it start
|
||||
// useEffect(() => {
|
||||
// sessionCheckFun()
|
||||
// }, [navigate, ItemCard]);
|
||||
|
||||
//cmd it End
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const loadSessionData = () => {
|
||||
const CompId = getSession('CompId');
|
||||
const AppId = getSession('AppId');
|
||||
const BranchId = getSession('BranchId');
|
||||
const UserType = getSession('UserType');
|
||||
console.log('loadSessionData:', CompId, AppId, BranchId, UserType);
|
||||
|
||||
if (CompId && AppId && BranchId) {
|
||||
setSessionData({ CompId, AppId, BranchId, UserType });
|
||||
return true; // Indicate that session data is available
|
||||
}
|
||||
return false; // Indicate that session data is not yet available
|
||||
};
|
||||
|
||||
if (!loadSessionData()) {
|
||||
const interval = setInterval(() => {
|
||||
if (loadSessionData()) {
|
||||
clearInterval(interval); // Stop checking once data is available
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
return () => clearInterval(interval); // Cleanup interval on unmount
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchExpDate = async () => {
|
||||
if (!sessionData) {
|
||||
console.log('Session data not available, skipping API call...');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { CompId, AppId, BranchId, UserType } = sessionData;
|
||||
const data = { CompId, BranchId, AppId };
|
||||
|
||||
let res = await dispatch(getAppSubscriptionDate(data)).unwrap();
|
||||
|
||||
if (res?.data?.statusCode === 1 && res?.data?.data?.length > 0) {
|
||||
const expData = res?.data?.data?.[0];
|
||||
|
||||
if (prevRemainingDays.current !== expData.RemainingDays) {
|
||||
prevRemainingDays.current = expData.RemainingDays;
|
||||
setRemainingDays(expData.RemainingDays);
|
||||
dispatch(ChangeAppExpDateData(expData));
|
||||
dispatch(changeHeightforExpDate(expData.RemainingDays));
|
||||
|
||||
if (
|
||||
expData.RemainingDays < 1 &&
|
||||
expData.RemainingHours < 1 &&
|
||||
expData.RemainingMinutes < 1 &&
|
||||
expData.RemainingSeconds < 1
|
||||
) {
|
||||
if (
|
||||
UserType !== 'Super Admin' ||
|
||||
UserType !== 'Super Admin User'
|
||||
) {
|
||||
console.log('Subscription expired, logging out...');
|
||||
alert(
|
||||
'Subscription expired, logging out. Redirecting to login...'
|
||||
);
|
||||
Logout();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log('No subscription data found, logging out...');
|
||||
alert(
|
||||
'No subscription data found, logging out. Redirecting to login...'
|
||||
);
|
||||
Logout();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching subscription data:', error);
|
||||
}
|
||||
};
|
||||
|
||||
if (remainingDays === null) {
|
||||
fetchExpDate();
|
||||
}
|
||||
|
||||
const interval = setInterval(fetchExpDate, 60 * 60 * 1000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, [sessionData, remainingDays]);
|
||||
|
||||
const Logout = async () => {
|
||||
const UserId = getSession('UserId');
|
||||
const status = 'N';
|
||||
try {
|
||||
const res = await dispatch(GenerateLogout({ UserId, status })).unwrap();
|
||||
if (res?.data?.statusCode === 1) {
|
||||
sessionStorage.clear();
|
||||
window.location.replace(`${commonSubDir}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Logout failed:', error);
|
||||
}
|
||||
};
|
||||
// mohan
|
||||
// useEffect(() => {
|
||||
// if (isMobile || isIOS) {
|
||||
// console.log("📱 Mobile/iOS device → skipping DevTools detection");
|
||||
// return;
|
||||
// }
|
||||
// const checkDevTools = setInterval(() => {
|
||||
// if (devtools.isOpen && !devToolsOpen) {
|
||||
// setDevToolsOpen(true);
|
||||
// document.body.innerHTML =
|
||||
// "<h1 style='color: red; text-align: center;'>Close Inspect to continue using the application.</h1>";
|
||||
// }
|
||||
// else if (!devtools.isOpen && devToolsOpen) {
|
||||
// setDevToolsOpen(false);
|
||||
|
||||
// setTimeout(() => {
|
||||
// window.location.reload();
|
||||
// }, 100);
|
||||
|
||||
// clearInterval(checkDevTools);
|
||||
// }
|
||||
|
||||
// if (!devtools.isOpen) {
|
||||
// let before = performance.now();
|
||||
|
||||
// let after = performance.now();
|
||||
|
||||
// let executionDelay = after - before;
|
||||
|
||||
// if (executionDelay > 100) {
|
||||
// setDevToolsOpen(true);
|
||||
// document.body.innerHTML =
|
||||
// "<h1 style='color: red; text-align: center;'>Close Inspect to continue using the application.</h1>";
|
||||
// } else {
|
||||
// setDevToolsOpen(false);
|
||||
// }
|
||||
// }
|
||||
// }, 1000);
|
||||
|
||||
// return () => clearInterval(checkDevTools);
|
||||
// }, [devToolsOpen]);
|
||||
|
||||
const sessionCheckFun = async () => {
|
||||
const UserId = getSession('UserId');
|
||||
const sessionId = getSession('SessionId');
|
||||
const IsLogout = getSession('Mode');
|
||||
let encryptedLoginType = TokendecryptedValuesFun(
|
||||
sessionStorage.getItem('LoginType')
|
||||
);
|
||||
if (encryptedLoginType != 'Kiosk') {
|
||||
const res = await dispatch(checkSession({ UserId, sessionId })).unwrap();
|
||||
if (res?.data?.statusCode === 1) {
|
||||
if (res?.data?.response === 'False') {
|
||||
if (IsLogout !== 'Logout') {
|
||||
alert('Session invalid. Redirecting to login...');
|
||||
}
|
||||
clearSession();
|
||||
window.location.replace(commonSubDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Routes>
|
||||
<Route
|
||||
path={`${subDirectory}selfBooking/:SelfBookingId`}
|
||||
element={<SelfBooking />}
|
||||
/>
|
||||
<Route
|
||||
path={`${subDirectory}MenuQRCode`}
|
||||
element={<CustomerMenuPage />}
|
||||
/>
|
||||
<Route
|
||||
path={`${subDirectory}weightscaleapp`}
|
||||
element={<WeightScaleApp />}
|
||||
/>
|
||||
<Route path={`${subDirectory}kioskSelfBooking`} element={<KisokSelBooking />} />
|
||||
|
||||
<Route
|
||||
path= {`${subDirectory}kiosk-individual-self-booking`}
|
||||
element={<IndividualBooking />}
|
||||
/>
|
||||
<Route
|
||||
path="/*"
|
||||
element={<ProtectedRoutes routesConfig={routesConfig} />}
|
||||
/>
|
||||
</Routes>
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
export default AppRoutes;
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
// AuthContext.jsx
|
||||
import React, { createContext, useContext, useState, useEffect } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { getSession } from './Services/Others';
|
||||
import {
|
||||
getEmpAccesData,
|
||||
getSAdminUserAccesData,
|
||||
PricingAppPricingName,
|
||||
} from './Features/BrachLogin/BranchLogin.js';
|
||||
import { changePricingAppPricingName } from './Features/ThemeChange/ThemeChange.js';
|
||||
import { FeatureAddon } from './Features/BookingScreen/BookingData/BookingData.js';
|
||||
|
||||
export const AuthContext = createContext();
|
||||
|
||||
export const useAuth = () => useContext(AuthContext);
|
||||
|
||||
export const AuthProvider = ({ children }) => {
|
||||
const AppId = getSession('AppId');
|
||||
const CompId = getSession('CompId');
|
||||
const BranchId = getSession('BranchId');
|
||||
const UserId = getSession('UserId');
|
||||
const UserType = getSession('UserType');
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const [Access, setAccess] = useState([]);
|
||||
const [SadminuserAccess, setSadminuserAccess] = useState([]);
|
||||
const [FeatureAddonData, setFeatureAddonData] = useState([]);
|
||||
const [ProORAdvance, setProORAdvance] = useState(false);
|
||||
const [Advance, setAdvance] = useState(false);
|
||||
const [freeProductsCount, setFreeProductsCount] = useState(0);
|
||||
|
||||
let featureaddDetails = FeatureAddonData?.FeatureDtls || [];
|
||||
|
||||
useEffect(() => {
|
||||
getPricingName();
|
||||
if (UserType !== 'Super Admin' && UserType !== 'Super Admin User') {
|
||||
getFeatureAddonData();
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (UserType === 'Employee') {
|
||||
getEmpAccess();
|
||||
}
|
||||
if (UserType === 'Super Admin User') {
|
||||
getSadminUserAccess();
|
||||
}
|
||||
}, [UserType]);
|
||||
|
||||
const getPricingName = async () => {
|
||||
if (!AppId || !UserId) return;
|
||||
const data = {
|
||||
appId: AppId,
|
||||
userId: UserId,
|
||||
};
|
||||
try {
|
||||
const response = await dispatch(PricingAppPricingName(data)).unwrap();
|
||||
const responseData = response?.data;
|
||||
if (responseData?.statusCode !== 1) return setAdvance(false);
|
||||
const pricingData = responseData?.data;
|
||||
await dispatch(changePricingAppPricingName(pricingData));
|
||||
const hasAdvance = pricingData.some(
|
||||
(item) => item.PricingName === 'Premium'
|
||||
);
|
||||
setAdvance(hasAdvance);
|
||||
const hasProOrAdvance =
|
||||
hasAdvance || pricingData.some((item) => item.PricingName === 'Customized');
|
||||
setProORAdvance(hasProOrAdvance);
|
||||
} catch (error) {
|
||||
console.error('Error fetching pricing name:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const getEmpAccess = async () => {
|
||||
let data = {
|
||||
UserId: UserId,
|
||||
AppId: AppId,
|
||||
CompId: CompId,
|
||||
BranchId: BranchId,
|
||||
};
|
||||
const response = await dispatch(getEmpAccesData(data)).unwrap();
|
||||
if (response?.data?.statusCode === 1) {
|
||||
setAccess(response?.data?.data?.[0]?.EmpAccessDetails);
|
||||
}
|
||||
};
|
||||
const getSadminUserAccess = async () => {
|
||||
let data = {
|
||||
UserId: UserId,
|
||||
AppId: AppId,
|
||||
};
|
||||
const response = await dispatch(getSAdminUserAccesData(data)).unwrap();
|
||||
if (response?.data?.statusCode === 1) {
|
||||
setSadminuserAccess(response?.data?.data?.[0]?.AppMenuAccessDetails);
|
||||
}
|
||||
};
|
||||
const getFeatureAddonData = async () => {
|
||||
let featureAddon = await dispatch(
|
||||
FeatureAddon({ AppId: AppId, UserId: UserId })
|
||||
).unwrap();
|
||||
if (featureAddon?.data?.statusCode === 1) {
|
||||
await setFeatureAddonData(
|
||||
featureAddon?.data?.data?.[0]?.FeatAddonHdr?.[0]
|
||||
);
|
||||
} else {
|
||||
await setFeatureAddonData([]);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<AuthContext.Provider
|
||||
value={{
|
||||
UserType,
|
||||
Access,
|
||||
SadminuserAccess,
|
||||
Advance,
|
||||
ProORAdvance,
|
||||
featureaddDetails,
|
||||
freeProductsCount,
|
||||
setFreeProductsCount,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
};
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { Select } from 'antd';
|
||||
import { FiTrash2 } from 'react-icons/fi';
|
||||
import { uomDataSelector } from '../../Features/ProductPage/ProductPage';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { ApplicationPreferences } from '../../Features/BrachLogin/BranchLogin';
|
||||
import './AddProduct.scss';
|
||||
|
||||
export default function AddProduct({ products, setProducts }) {
|
||||
|
||||
const UomData = useSelector(uomDataSelector);
|
||||
const ApplicationPreferenceData = useSelector(ApplicationPreferences);
|
||||
const UomTypePreference = ApplicationPreferenceData?.find(
|
||||
(preference) => preference?.PreferredCatName === 'Product Uom'
|
||||
)?.PreferenceCatDetails;
|
||||
console.log(UomData,"UomData",UomTypePreference)
|
||||
const UomPreference = UomData?.filter((item) =>
|
||||
UomTypePreference?.some?.(
|
||||
(e) =>
|
||||
e?.PreferredSubCatName?.toLowerCase() ==
|
||||
item?.ConfigName?.toLowerCase() && e?.PreferredStatus == 'Y'
|
||||
)
|
||||
);
|
||||
const defaultUomId = UomPreference?.find((cat) => cat?.ConfigName?.toLowerCase() === 'pcs')?.ConfigId || '';
|
||||
const defaultUomName = UomPreference?.find((cat) => cat?.ConfigName?.toLowerCase() === 'pcs')?.ConfigName || '';
|
||||
useEffect(() => {
|
||||
if (defaultUomId) {
|
||||
setProducts((prev) => prev.map((p) => ({ ...p, UOM: p.UOM || defaultUomId, size: p.size || '1' , UOMName: p.UOMName || defaultUomName })));
|
||||
}
|
||||
}, [defaultUomId]);
|
||||
|
||||
const handleInputChange = (id, field, value, displayValue) => {
|
||||
setProducts(products.map(product => {
|
||||
if (product.id !== id) return product;
|
||||
if (field === 'UOM') {
|
||||
return { ...product, UOM: value, UOMName: displayValue || product.UOMName };
|
||||
}
|
||||
return { ...product, [field]: value };
|
||||
}));
|
||||
};
|
||||
|
||||
const addRow = () => {
|
||||
const newId = products.length > 0 ? Math.max(...products.map(p => p.id)) + 1 : 1;
|
||||
setProducts([{ id: newId, name: '', price: '', code: '', size: '1', UOM: defaultUomId || '' , UOMName: defaultUomName || ''}, ...products]);
|
||||
};
|
||||
|
||||
const deleteRow = (id) => {
|
||||
if (products.length > 1) {
|
||||
setProducts(products.filter(product => product.id !== id));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="add-product__container">
|
||||
<div className="add-product__header">
|
||||
<button className="add-product__add-btn" onClick={addRow}>+ Add Row</button>
|
||||
</div>
|
||||
|
||||
<div className="add-product__table-wrapper">
|
||||
<table className="add-product__table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Price</th>
|
||||
<th>Code</th>
|
||||
<th>Size</th>
|
||||
<th>UOM</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{products.map((product) => (
|
||||
<tr key={product.id}>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
value={product.name}
|
||||
onChange={(e) => handleInputChange(product.id, 'name', e.target.value)}
|
||||
placeholder=" product name"
|
||||
className="add-product__input-field"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="number"
|
||||
value={product.price}
|
||||
onChange={(e) => handleInputChange(product.id, 'price', e.target.value)}
|
||||
placeholder="$0.00"
|
||||
className="add-product__input-field"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
value={product.code}
|
||||
onChange={(e) => handleInputChange(product.id, 'code', e.target.value)}
|
||||
placeholder="PRD-000"
|
||||
className="add-product__input-field add-product__input-field--code"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="number"
|
||||
value={product.size}
|
||||
onChange={(e) => handleInputChange(product.id, 'size', e.target.value)}
|
||||
placeholder="Enter size"
|
||||
className="add-product__input-field"
|
||||
/>
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
<Select
|
||||
// size="small"
|
||||
value={product.UOM}
|
||||
onChange={(val, option) => handleInputChange(product.id, 'UOM', val, option?.label)}
|
||||
options={UomPreference?.map((cat) => ({ label: cat.ConfigName, value: cat.ConfigId }))}
|
||||
// placeholder="Select Category"
|
||||
style={{ width: '100%' }}
|
||||
// allowClear
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
className="add-product__delete-btn"
|
||||
onClick={() => deleteRow(product.id)}
|
||||
disabled={products.length === 1}
|
||||
aria-label="Delete row"
|
||||
title="Delete"
|
||||
>
|
||||
<FiTrash2 />
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,228 @@
|
|||
.add-product {
|
||||
&__container {
|
||||
padding: 6px;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 1.5rem;
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 1.875rem;
|
||||
font-weight: bold;
|
||||
color: #1f2937;
|
||||
margin: 0;
|
||||
font-family: "Poppins", sans-serif;
|
||||
}
|
||||
|
||||
&__add-btn {
|
||||
background-color: #333;
|
||||
color: white;
|
||||
padding: 0.625rem 1.25rem;
|
||||
border: none;
|
||||
border-radius: 0.375rem;
|
||||
font-weight: 400;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
font-family: "Poppins", sans-serif;
|
||||
|
||||
&:hover {
|
||||
background-color: #1f2937;
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
}
|
||||
|
||||
&__table-wrapper {
|
||||
max-height: 60vh;
|
||||
overflow: auto;
|
||||
border-radius: 0.5rem;
|
||||
scrollbar-width: thin;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: rgba(107, 114, 128, 0.35);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: rgba(107, 114, 128, 0.35) transparent;
|
||||
}
|
||||
|
||||
&__table {
|
||||
width: 100%;
|
||||
background-color: white;
|
||||
border-collapse: collapse;
|
||||
|
||||
.ant-select-selection-item {
|
||||
padding-top: unset !important;
|
||||
}
|
||||
|
||||
.ant-select-selector {
|
||||
height: 40px !important;
|
||||
}
|
||||
|
||||
input {
|
||||
height: 40px !important;
|
||||
font-weight: 400 !important;
|
||||
}
|
||||
|
||||
thead {
|
||||
background-color: #f1f5f9 !important;
|
||||
color: #111827;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
|
||||
tr th {
|
||||
padding: 8px 8px;
|
||||
text-align: left;
|
||||
font-weight: 500;
|
||||
font-size: 0.75rem;
|
||||
text-transform: uppercase;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 2;
|
||||
font-family: "Poppins", sans-serif;
|
||||
}
|
||||
}
|
||||
|
||||
tbody {
|
||||
color: #374151;
|
||||
font-family: "Poppins", sans-serif;
|
||||
|
||||
tr {
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
transition: background-color 0.2s ease;
|
||||
|
||||
&:nth-child(even) {
|
||||
background-color: #f9fafb;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #f3f4f6;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 8px 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__input-field {
|
||||
width: 100%;
|
||||
padding: 0.5rem;
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
transition: border-color 0.2s ease, box-shadow 0.2s ease;
|
||||
font-family: "Poppins", sans-serif;
|
||||
font-weight: 400 !important;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: #6b7280;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
&--code {
|
||||
font-family: "Poppins", sans-serif;
|
||||
}
|
||||
}
|
||||
|
||||
&__delete-btn {
|
||||
background-color: #ffdcdc;
|
||||
color: #ee3333;
|
||||
width: 2rem !important;
|
||||
height: 2rem;
|
||||
padding: 0.35rem 0.5rem;
|
||||
border: none;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease, transform 0.08s ease;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
line-height: 1;
|
||||
font-family: "Poppins", sans-serif;
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
background-color: #ffb3b3;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background-color: #d1d5db;
|
||||
cursor: not-allowed;
|
||||
opacity: 0.9;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
&:active:not(:disabled) {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
&__container {
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
&__header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
&__table {
|
||||
|
||||
thead tr th,
|
||||
tbody tr td {
|
||||
padding: 0.5rem;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
}
|
||||
|
||||
&__input-field {
|
||||
padding: 0.375rem;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.add-product__delete-btn {
|
||||
width: 50px !important;
|
||||
text-align: center !important;
|
||||
}
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
import { Calendar as CalendarLibrary} from"../../../ownLib/my-ui-lib"
|
||||
const Calendar = CalendarLibrary
|
||||
export default Calendar;
|
||||
// import { useState } from 'react';
|
||||
// import {
|
||||
// format,
|
||||
// startOfWeek,
|
||||
// addDays,
|
||||
// isSameDay,
|
||||
// setMonth,
|
||||
// setYear,
|
||||
// getWeeksInMonth,
|
||||
// startOfMonth,
|
||||
// differenceInCalendarWeeks,
|
||||
// addWeeks,
|
||||
// subWeeks
|
||||
// } from 'date-fns';
|
||||
// import './Calendar.scss';
|
||||
// import { HiDotsHorizontal } from "react-icons/hi";
|
||||
// import { FiChevronLeft, FiChevronRight } from 'react-icons/fi';
|
||||
|
||||
// const Calendar = () => {
|
||||
// // To match the image, set the date to Saturday, May 3, 2025
|
||||
// const initialDate = new Date('2025-06-29T12:00:00');
|
||||
// const [currentDate, setCurrentDate] = useState(initialDate);
|
||||
// const [showYearPicker, setShowYearPicker] = useState(false);
|
||||
|
||||
// const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
||||
|
||||
// const handleMonthClick = (monthIndex) => {
|
||||
// const newDate = setMonth(currentDate, monthIndex);
|
||||
// setCurrentDate(newDate);
|
||||
// };
|
||||
|
||||
// const handleDayClick = (day) => {
|
||||
// setCurrentDate(day);
|
||||
// };
|
||||
|
||||
// const toggleYearPicker = () => {
|
||||
// setShowYearPicker(!showYearPicker);
|
||||
// };
|
||||
|
||||
// const handleYearChange = (year) => {
|
||||
// const newDate = setYear(currentDate, year);
|
||||
// setCurrentDate(newDate);
|
||||
// setShowYearPicker(false);
|
||||
// };
|
||||
|
||||
// const handlePrevWeek = () => {
|
||||
// setCurrentDate(subWeeks(currentDate, 1));
|
||||
// };
|
||||
|
||||
// const handleNextWeek = () => {
|
||||
// setCurrentDate(addWeeks(currentDate, 1));
|
||||
// };
|
||||
|
||||
// const renderDays = () => {
|
||||
// const weekStart = startOfWeek(currentDate, { weekStartsOn: 0 }); // Sunday
|
||||
// const days = [];
|
||||
// for (let i = 0; i < 5; i++) {
|
||||
// days.push(addDays(weekStart, i));
|
||||
// }
|
||||
|
||||
// // Hardcoded event dots to match UI
|
||||
// const eventDays = {
|
||||
// '29': ['yellow', 'orange'],
|
||||
// '30': ['yellow'],
|
||||
// };
|
||||
|
||||
// return days.map((day) => (
|
||||
// <div
|
||||
// key={day}
|
||||
// className={`calendar-day-item ${isSameDay(day, currentDate) ? 'active' : ''}`}
|
||||
// onClick={() => handleDayClick(day)}
|
||||
// >
|
||||
// <div className="event-dots-container">
|
||||
// {(eventDays[format(day, 'd')] || []).map((color, index) => (
|
||||
// <div key={index} className={`event-dot ${color}`}></div>
|
||||
// ))}
|
||||
// </div>
|
||||
// <div className={`day-number ${isSameDay(day, currentDate) ? 'active' : ''}`} >
|
||||
// {format(day, 'd')}</div>
|
||||
// <div
|
||||
// // className="day-name"
|
||||
// className={`day-name ${isSameDay(day, currentDate) ? 'active' : ''}`}
|
||||
// >{format(day, 'EEE')}</div>
|
||||
// </div>
|
||||
// ));
|
||||
// };
|
||||
|
||||
// const renderPagination = () => {
|
||||
// const monthStart = startOfMonth(currentDate);
|
||||
// const totalWeeks = getWeeksInMonth(currentDate, { weekStartsOn: 0 });
|
||||
// const currentWeek = differenceInCalendarWeeks(currentDate, monthStart, { weekStartsOn: 0 });
|
||||
|
||||
// return Array.from({ length: totalWeeks }, (_, i) => (
|
||||
// <span key={i} className={`pagination-dot ${i === currentWeek ? 'active-dot' : ''}`}></span>
|
||||
// ));
|
||||
// };
|
||||
|
||||
// const renderYearPicker = () => {
|
||||
// const currentYear = currentDate.getFullYear();
|
||||
// const years = Array.from({ length: 10 }, (_, i) => currentYear - 5 + i);
|
||||
// return (
|
||||
// <div className="year-picker">
|
||||
// {years.map(year => (
|
||||
// <div
|
||||
// key={year}
|
||||
// className={`year-item ${year === currentYear ? 'active' : ''}`}
|
||||
// onClick={() => handleYearChange(year)}
|
||||
// >
|
||||
// {year}
|
||||
// </div>
|
||||
// ))}
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
|
||||
// return (
|
||||
// <div className="calendar-widget-wrapper">
|
||||
// <div className="calendar-header">
|
||||
// <div className="calendar-title-main">Calendar for Bills & Events</div>
|
||||
// <div className="calendar-event-notes">
|
||||
// Pending bills due tomorrow<br />
|
||||
// Scheduled delivery/purchase<br />
|
||||
// Staff birthdays/notes
|
||||
// </div>
|
||||
// </div>
|
||||
// <div className="calendar-body-content">
|
||||
// {showYearPicker ? (
|
||||
// renderYearPicker()
|
||||
// ) : (
|
||||
// <>
|
||||
// <div className="calendar-controls">
|
||||
// <div className="calendar-year-display">{format(currentDate, 'yyyy')}</div>
|
||||
// <button className="calendar-more-btn" onClick={toggleYearPicker}><HiDotsHorizontal /></button>
|
||||
// </div>
|
||||
// <div className="calendar-months-nav">
|
||||
// {months.slice(0, 6).map((month, index) => (
|
||||
// <button
|
||||
// key={month}
|
||||
// className={`month-nav-btn ${currentDate.getMonth() === index ? 'active' : ''}`}
|
||||
// onClick={() => handleMonthClick(index)}
|
||||
// >
|
||||
// {month}
|
||||
// </button>
|
||||
// ))}
|
||||
// </div>
|
||||
// <div className="calendar-week-view">
|
||||
// <button className="week-nav-btn prev" onClick={handlePrevWeek}>
|
||||
// <FiChevronLeft />
|
||||
// </button>
|
||||
// <div className="calendar-days-grid">{renderDays()}</div>
|
||||
// <button className="week-nav-btn next" onClick={handleNextWeek}>
|
||||
// <FiChevronRight />
|
||||
// </button>
|
||||
// </div>
|
||||
// {/* <div className="calendar-pagination-dots">
|
||||
// {renderPagination()}
|
||||
// </div> */}
|
||||
// </>
|
||||
// )}
|
||||
// </div>
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
|
||||
// export default Calendar;
|
||||
|
|
@ -0,0 +1,451 @@
|
|||
.calendar-widget-wrapper {
|
||||
border-radius: 12px;
|
||||
padding: 18px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-family: 'Poppins', sans-serif;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1.2;
|
||||
/* Makes it slightly wider than other widgets */
|
||||
}
|
||||
|
||||
.calendar-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.calendar-title-main {
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.calendar-event-notes {
|
||||
font-size: 12px;
|
||||
color: #888;
|
||||
text-align: right;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.calendar-body-content {
|
||||
background: #ffffff;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
|
||||
border-radius: 10px;
|
||||
padding: 16px;
|
||||
flex-grow: 1;
|
||||
position: relative;
|
||||
height: 37vh;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.calendar-controls {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.calendar-year-display {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.calendar-more-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 24px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.calendar-months-nav {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #e6eaf0;
|
||||
}
|
||||
|
||||
.month-nav-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 15px;
|
||||
color: #888;
|
||||
font-weight: 500;
|
||||
padding: 4px 8px;
|
||||
border-radius: 6px;
|
||||
|
||||
&.active {
|
||||
background: #e3f2fd;
|
||||
color: #1976d2;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.calendar-days-grid {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
.calendar-day-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 8px 4px;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
min-height: 70px;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
|
||||
transition: all 0.2s ease-in-out;
|
||||
border: 1px solid #EEEEEE;;
|
||||
|
||||
&.active {
|
||||
background: #1976d2;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.event-dots-container {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
display: flex;
|
||||
gap: 3px;
|
||||
}
|
||||
|
||||
.event-dot {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
border-radius: 50%;
|
||||
|
||||
&.yellow {
|
||||
background: #ffca28;
|
||||
}
|
||||
|
||||
&.orange {
|
||||
background: #ff9800;
|
||||
}
|
||||
}
|
||||
|
||||
.day-number {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
&.active{
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.day-name {
|
||||
font-size: 12px;
|
||||
color: #888;
|
||||
&.active{
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.calendar-pagination-dots {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
margin-top: 16px;
|
||||
|
||||
.pagination-dot {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background: #d0d0d0;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&.active-dot {
|
||||
background: #1976d2;
|
||||
width: 18px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
|
||||
.modal {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 2rem;
|
||||
width: 90%;
|
||||
max-width: 400px;
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
|
||||
|
||||
h3 {
|
||||
margin: 0 0 1.5rem 0;
|
||||
color: #2d3748;
|
||||
}
|
||||
|
||||
.event-input {
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
border: 2px solid #e2e8f0;
|
||||
border-radius: 6px;
|
||||
font-size: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
transition: border-color 0.2s ease;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: #667eea;
|
||||
}
|
||||
}
|
||||
|
||||
.event-type-select {
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
border: 2px solid #e2e8f0;
|
||||
border-radius: 6px;
|
||||
font-size: 1rem;
|
||||
margin-bottom: 1.5rem;
|
||||
background: white;
|
||||
cursor: pointer;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: #667eea;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-actions {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
justify-content: flex-end;
|
||||
|
||||
.cancel-btn {
|
||||
padding: 0.75rem 1.5rem;
|
||||
border: 2px solid #e2e8f0;
|
||||
background: white;
|
||||
color: #4a5568;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
border-color: #cbd5e0;
|
||||
background: #f7fafc;
|
||||
}
|
||||
}
|
||||
|
||||
.save-btn {
|
||||
padding: 0.75rem 1.5rem;
|
||||
background: #667eea;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
transition: background-color 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
background: #5a67d8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.year-picker {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.year-item {
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
color: #888;
|
||||
cursor: pointer;
|
||||
padding: 4px 16px;
|
||||
border-radius: 6px;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
background: #e3f2fd;
|
||||
color: #1976d2;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: #1976d2;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.calendar-week-view {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-top: 16px;
|
||||
justify-content: space-between;
|
||||
|
||||
}
|
||||
|
||||
.week-nav-btn {
|
||||
background: #f0f2f5;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
color: #555;
|
||||
font-size: 20px;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
background: #e4e6e9;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
}
|
||||
|
||||
// Responsive design
|
||||
@media (max-width: 768px) {
|
||||
.calendar-container {
|
||||
margin: 1rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.calendar-header {
|
||||
.header-top {
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
align-items: stretch;
|
||||
|
||||
.header-controls {
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.calendar-title {
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
}
|
||||
|
||||
.calendar-body {
|
||||
.year-header {
|
||||
.year {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.month-navigation {
|
||||
.month-tab {
|
||||
padding: 0.625rem 0.75rem;
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
}
|
||||
|
||||
.week-view {
|
||||
gap: 0.375rem;
|
||||
|
||||
.day-card {
|
||||
padding: 0.75rem 0.5rem;
|
||||
min-height: 70px;
|
||||
|
||||
.date-number {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.day-name {
|
||||
font-size: 0.6875rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.month-view {
|
||||
.month-grid {
|
||||
gap: 0.25rem;
|
||||
|
||||
.month-day {
|
||||
min-height: 60px;
|
||||
padding: 0.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.navigation-controls {
|
||||
.current-period {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.calendar-header {
|
||||
.calendar-title {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.calendar-legend {
|
||||
.legend-item {
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.calendar-body {
|
||||
.year-header {
|
||||
.year {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
.week-view {
|
||||
.day-card {
|
||||
padding: 0.5rem 0.25rem;
|
||||
min-height: 60px;
|
||||
|
||||
.date-number {
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
|
||||
.day-name {
|
||||
font-size: 0.625rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.month-view {
|
||||
.month-grid {
|
||||
.month-day {
|
||||
min-height: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
import React, { useState, useRef, useEffect } from "react";
|
||||
import { FiCalendar } from "react-icons/fi";
|
||||
import { MdKeyboardArrowDown } from "react-icons/md";
|
||||
|
||||
const RANGE_OPTIONS = [
|
||||
{ label: 'Today', value: 'today' },
|
||||
{ label: 'This Week', value: 'week' },
|
||||
{ label: 'This Month', value: 'month' },
|
||||
{ label: 'This Year', value: 'year' },
|
||||
];
|
||||
|
||||
const CalendarDropdown = ({ value, onChange }) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const ref = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
function handleClickOutside(event) {
|
||||
if (ref.current && !ref.current.contains(event.target)) {
|
||||
setOpen(false);
|
||||
}
|
||||
}
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => document.removeEventListener('mousedown', handleClickOutside);
|
||||
}, []);
|
||||
|
||||
const selected = RANGE_OPTIONS.find(opt => opt.value === value) || RANGE_OPTIONS[0];
|
||||
|
||||
return (
|
||||
<div ref={ref} style={{ position: 'relative' }}>
|
||||
<button
|
||||
className="calendar-btn"
|
||||
onClick={() => setOpen(o => !o)}
|
||||
type="button"
|
||||
>
|
||||
<FiCalendar style={{ marginRight: 4 }} />
|
||||
{selected.label}
|
||||
<MdKeyboardArrowDown style={{ marginLeft: 2 }} />
|
||||
</button>
|
||||
{open && (
|
||||
<div className="calendar-dropdown">
|
||||
{RANGE_OPTIONS.map(option => (
|
||||
<div
|
||||
key={option.value}
|
||||
className={`calendar-dropdown-item${selected.value === option.value ? ' selectedd' : ''}`}
|
||||
onClick={() => {
|
||||
onChange(option.value);
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
{option.label}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CalendarDropdown;
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
import React from 'react';
|
||||
import { Column } from '@ant-design/plots';
|
||||
|
||||
const DemoColumn = () => {
|
||||
const data = [
|
||||
{
|
||||
type: '家具家电',
|
||||
sales: 38,
|
||||
},
|
||||
{
|
||||
type: '粮油副食',
|
||||
sales: 52,
|
||||
},
|
||||
{
|
||||
type: '生鲜水果',
|
||||
sales: 61,
|
||||
},
|
||||
{
|
||||
type: '美容洗护',
|
||||
sales: 145,
|
||||
},
|
||||
{
|
||||
type: '母婴用品',
|
||||
sales: 48,
|
||||
},
|
||||
{
|
||||
type: '进口食品',
|
||||
sales: 38,
|
||||
},
|
||||
{
|
||||
type: '食品饮料',
|
||||
sales: 38,
|
||||
},
|
||||
{
|
||||
type: '家庭清洁',
|
||||
sales: 38,
|
||||
},
|
||||
];
|
||||
const config = {
|
||||
data,
|
||||
xField: 'type',
|
||||
yField: 'sales',
|
||||
label: {
|
||||
position: 'middle',
|
||||
style: {
|
||||
fill: '#FFFFFF',
|
||||
opacity: 0.6,
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
label: {
|
||||
autoHide: true,
|
||||
autoRotate: false,
|
||||
},
|
||||
},
|
||||
meta: {
|
||||
type: {
|
||||
alias: '类别',
|
||||
},
|
||||
sales: {
|
||||
alias: '销售额',
|
||||
},
|
||||
},
|
||||
};
|
||||
return React.createElement(Column, config);
|
||||
};
|
||||
|
||||
export default DemoColumn;
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import React from 'react';
|
||||
import { Liquid } from '@ant-design/plots';
|
||||
|
||||
const DemoLiquid = () => {
|
||||
const config = {
|
||||
percent: 0.25,
|
||||
shape: 'rect',
|
||||
outline: {
|
||||
border: 2,
|
||||
distance: 4,
|
||||
},
|
||||
wave: {
|
||||
length: 128,
|
||||
},
|
||||
};
|
||||
|
||||
return React.createElement(Liquid, config);
|
||||
};
|
||||
|
||||
export default DemoLiquid;
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
import { Drawer } from 'antd';
|
||||
|
||||
export const Drawers = ({ open, placement, title, children, onClose }) => {
|
||||
return (
|
||||
<>
|
||||
<Drawer
|
||||
title={title}
|
||||
placement={placement}
|
||||
onClose={onClose}
|
||||
open={open}
|
||||
key={placement}
|
||||
>
|
||||
{children}
|
||||
</Drawer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// import { Button } from 'antd';
|
||||
// import './main.scss';
|
||||
// import { forwardRef } from 'react'; //Add for shifayath
|
||||
import { Buttons as ButtonLibrary } from '../../../ownLib/my-ui-lib.js';
|
||||
const Buttons = ButtonLibrary
|
||||
// forwardRef(
|
||||
// ({ buttonText, handleSubmit, icon, disabled, htmlType, prefix }, ref) => (
|
||||
// <Button
|
||||
// ref={ref}
|
||||
// type="primary"
|
||||
// className="primary_Button"
|
||||
// onClick={handleSubmit}
|
||||
// htmlType={htmlType ? 'submit' : ''}
|
||||
// disabled={disabled ? disabled : false}
|
||||
// >
|
||||
// {prefix}
|
||||
// {buttonText}
|
||||
// {icon}
|
||||
// </Button>
|
||||
// )
|
||||
// );
|
||||
|
||||
export default Buttons;
|
||||
// const Buttons = forwardRef(
|
||||
// ({ buttonText, handleSubmit, icon, disabled, htmlType, prefix }, ref) => (
|
||||
// <Button
|
||||
// ref={ref}
|
||||
// type="primary"
|
||||
// className="primary_Button"
|
||||
// onClick={handleSubmit}
|
||||
// htmlType={htmlType ? 'submit' : ''}
|
||||
// disabled={disabled ? disabled : false}
|
||||
// >
|
||||
// {prefix}
|
||||
// {buttonText}
|
||||
// {icon}
|
||||
// </Button>
|
||||
// )
|
||||
// );
|
||||
|
||||
// export default Buttons;
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
// import { Checkbox, Divider } from 'antd';
|
||||
// import { useState } from 'react';
|
||||
import { CheckBoxGroup as CheckboxGroupLibrary } from '../../../ownLib/my-ui-lib.js';
|
||||
|
||||
export const CheckBoxGroup = CheckboxGroupLibrary
|
||||
|
||||
// export const CheckBoxGroup = ({
|
||||
// fieldState,
|
||||
// fieldApi,
|
||||
// faClass,
|
||||
// style,
|
||||
// ListOfCheckBox,
|
||||
// defaultCheckedList,
|
||||
// ...props
|
||||
// }) => {
|
||||
// const plainOptions = ListOfCheckBox;
|
||||
// const {
|
||||
// field,
|
||||
// onBlur,
|
||||
// initialValue,
|
||||
// forwardedRef,
|
||||
// className,
|
||||
// content,
|
||||
// ...rest
|
||||
// } = props.props;
|
||||
// const [checkedList, setCheckedList] = useState(defaultCheckedList);
|
||||
// const [indeterminate, setIndeterminate] = useState(true);
|
||||
// const [checkAll, setCheckAll] = useState(false);
|
||||
// const onChange = (list) => {
|
||||
// setCheckedList(list);
|
||||
// setIndeterminate(!!list?.length && list?.length < plainOptions?.length);
|
||||
// setCheckAll(list?.length === plainOptions?.length);
|
||||
// };
|
||||
// const onCheckAllChange = (e) => {
|
||||
// setCheckedList(e.target.checked ? plainOptions : []);
|
||||
// setIndeterminate(false);
|
||||
// setCheckAll(e.target.checked);
|
||||
// };
|
||||
// return (
|
||||
// <>
|
||||
// <Checkbox
|
||||
// indeterminate={indeterminate}
|
||||
// onChange={onCheckAllChange}
|
||||
// checked={checkAll}
|
||||
// >
|
||||
// Check all
|
||||
// </Checkbox>
|
||||
// <Divider />
|
||||
// <CheckboxGroup
|
||||
// options={plainOptions}
|
||||
// value={checkedList}
|
||||
// onChange={onChange}
|
||||
// />
|
||||
// </>
|
||||
// );
|
||||
// };
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
import React from 'react';
|
||||
|
||||
const ColorPicker = ({ value, onChange, style, placeholder = "Select a color" }) => {
|
||||
const handleColorChange = (e) => {
|
||||
onChange(e.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '8px', ...style }}>
|
||||
<input
|
||||
type="color"
|
||||
value={value || '#000000'}
|
||||
onChange={handleColorChange}
|
||||
style={{
|
||||
width: '40px',
|
||||
height: '40px',
|
||||
border: 'none',
|
||||
borderRadius: '8px',
|
||||
cursor: 'pointer',
|
||||
boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
|
||||
}}
|
||||
/>
|
||||
<span style={{ fontSize: '14px', color: '#666' }}>
|
||||
{value || '#000000'}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ColorPicker;
|
||||
|
|
@ -0,0 +1,522 @@
|
|||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import { Upload, Modal } from 'antd';
|
||||
import { uploadImage } from '../../Features/upload/upload';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import ImageCropper from '../../Components/Forms/Cropper2.jsx';
|
||||
import ShapeCropper from './ShapeCropper.jsx';
|
||||
import { PiCropBold } from 'react-icons/pi';
|
||||
import { FiPenTool } from 'react-icons/fi';
|
||||
import { DefaultModal } from '../../Components/Modal/DefaultModal.jsx';
|
||||
import '../../Styles/Product/Product.scss';
|
||||
import { Messages } from '../Notifications/Messages.jsx';
|
||||
const allowedTypes = [
|
||||
'image/jpeg',
|
||||
'image/png',
|
||||
'image/webp',
|
||||
'image/svg+xml',
|
||||
'image/gif',
|
||||
'image/avif',
|
||||
];
|
||||
const CropUpload = ({
|
||||
updateImageUrl,
|
||||
ImageLink,
|
||||
onlineImage,
|
||||
isProductList = {},
|
||||
handleClose = () => {}
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
const [messageType, setMessageType] = useState(null);
|
||||
const [messageData, setMessageData] = useState(null);
|
||||
const [fileList, setFileList] = useState([]);
|
||||
const [previewVisible, setPreviewVisible] = useState(false);
|
||||
const [previewImage, setPreviewImage] = useState('');
|
||||
const [editImageOpen, setEditImageOpen] = useState(false);
|
||||
const [croppedImage, setCroppedImage] = useState(null);
|
||||
const [shapedImage, setShapedImage] = useState(false);
|
||||
const [cropImage, setCropImage] = useState(false);
|
||||
const [shapedData, setShapedData] = useState(null);
|
||||
const [resizedImageUrl, setResizedImageUrl] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
if (ImageLink != '' && ImageLink != null) {
|
||||
updateImageUrl(ImageLink);
|
||||
setFileList([
|
||||
{
|
||||
uid: `${Date.now()}-${Math.random()}`, // Ensures uniqueness
|
||||
name: `image${Date.now()}-${Math.random()}.png`,
|
||||
status: 'done',
|
||||
url: ImageLink,
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
updateImageUrl();
|
||||
// setFileList([]);
|
||||
// handleRemove()
|
||||
}
|
||||
}, [ImageLink]);
|
||||
|
||||
useEffect(() => {
|
||||
if (ImageLink != '' && ImageLink != null) {
|
||||
if (Object.keys(isProductList)?.length > 0) {
|
||||
const { isProductListPutapi } = isProductList;
|
||||
if (isProductListPutapi) {
|
||||
setFileList([
|
||||
{
|
||||
uid: `${Date.now()}-${Math.random()}`, // Ensures uniqueness
|
||||
name: `image${Date.now()}-${Math.random()}.png`,
|
||||
status: 'done',
|
||||
url: ImageLink,
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
setFileList([]);
|
||||
}
|
||||
} else {
|
||||
// setFileList([]);
|
||||
}
|
||||
} else {
|
||||
// setFileList([]);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (onlineImage !== '' && onlineImage != null && onlineImage != undefined) {
|
||||
setEditImageOpen(true);
|
||||
handleResizeImage(onlineImage);
|
||||
} else {
|
||||
setShapedImage(false);
|
||||
setCropImage(false);
|
||||
}
|
||||
}, [onlineImage]);
|
||||
|
||||
useEffect(() => {
|
||||
if (fileList.length > 0) {
|
||||
const imageUrl = fileList?.[0]?.url;
|
||||
if (imageUrl !== '' && imageUrl !== null && imageUrl !== undefined) {
|
||||
handleResizeImage(imageUrl);
|
||||
} else {
|
||||
setShapedImage(false);
|
||||
setCropImage(false);
|
||||
}
|
||||
}
|
||||
}, [fileList]);
|
||||
|
||||
const handleResizeImage = async (imageUrl) => {
|
||||
try {
|
||||
const resizedImageUrl = await resizeImage(imageUrl, 300, 150);
|
||||
setResizedImageUrl(resizedImageUrl);
|
||||
} catch (error) {
|
||||
console.error('Error resizing image:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const SetDefault = async () => {
|
||||
setEditImageOpen(false);
|
||||
setCroppedImage(null);
|
||||
setShapedData(null);
|
||||
setShapedImage(false);
|
||||
setCropImage(false);
|
||||
updateImageUrl(
|
||||
onlineImage !== '' && onlineImage != null
|
||||
? onlineImage
|
||||
: fileList?.[0]?.['url'] != '' && fileList?.[0]?.['url'] != null
|
||||
? fileList?.[0]?.['url']
|
||||
: ''
|
||||
);
|
||||
if (Object.keys(isProductList)?.length > 0) {
|
||||
const { isProductListPutapi, record, imagePutFunction } = isProductList;
|
||||
if (isProductListPutapi) {
|
||||
imagePutFunction(
|
||||
onlineImage !== '' && onlineImage != null
|
||||
? onlineImage
|
||||
: fileList?.[0]?.['url'] != '' && fileList?.[0]?.['url'] != null
|
||||
? fileList?.[0]?.['url']
|
||||
: '',
|
||||
record
|
||||
);
|
||||
handleClose();
|
||||
setMessageData("Image updated successfully");
|
||||
setMessageType("success");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleEditImageCancle = () => {
|
||||
setCroppedImage(null);
|
||||
setShapedData(null);
|
||||
setEditImageOpen(false);
|
||||
updateImageUrl('');
|
||||
setFileList([]);
|
||||
setShapedImage(false);
|
||||
setCropImage(false);
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
const base64 = croppedImage;
|
||||
const byteCharacters = atob(base64?.split(',')[1]);
|
||||
const byteNumbers = new Array(byteCharacters.length);
|
||||
for (let i = 0; i < byteCharacters.length; i++) {
|
||||
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
||||
}
|
||||
const byteArray = new Uint8Array(byteNumbers);
|
||||
const blob = new Blob([byteArray], { type: 'image/png' });
|
||||
const file = new File([blob], 'cropped_image.png', { type: 'image/png' });
|
||||
try {
|
||||
await handleUpload({
|
||||
file,
|
||||
onSuccess: () => console.log('Upload successful'),
|
||||
onError: () => console.error('Upload failed'),
|
||||
});
|
||||
setEditImageOpen(false);
|
||||
await setCroppedImage(null);
|
||||
setShapedImage(false);
|
||||
setCropImage(false);
|
||||
handleClose();
|
||||
setMessageData("Image updated successfully");
|
||||
setMessageType("success");
|
||||
} catch (error) {
|
||||
console.error('Error in handleUpload:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleShapeSubmit = async () => {
|
||||
const base64 = shapedData[0];
|
||||
const byteCharacters = atob(base64?.split(',')[1]);
|
||||
const byteNumbers = new Array(byteCharacters.length);
|
||||
for (let i = 0; i < byteCharacters.length; i++) {
|
||||
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
||||
}
|
||||
const byteArray = new Uint8Array(byteNumbers);
|
||||
const blob = new Blob([byteArray], { type: 'image/png' });
|
||||
const file = new File([blob], 'cropped_image.png', { type: 'image/png' });
|
||||
try {
|
||||
await handleUpload({
|
||||
file,
|
||||
onSuccess: () => console.log('Upload successful'),
|
||||
onError: () => console.error('Upload failed'),
|
||||
});
|
||||
setEditImageOpen(false);
|
||||
await setShapedData(null);
|
||||
setShapedImage(false);
|
||||
setCropImage(false);
|
||||
handleClose();
|
||||
setMessageData("Image updated successfully");
|
||||
setMessageType("success");
|
||||
} catch (error) {
|
||||
console.error('Error in handleUpload:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancel = () => setPreviewVisible(false);
|
||||
|
||||
const onChange = async ({ fileList: newFileList }) => {
|
||||
setFileList(newFileList);
|
||||
|
||||
if (Object.keys(isProductList)?.length > 0) {
|
||||
const { isProductListPutapi } = isProductList;
|
||||
if (isProductListPutapi && newFileList?.[0]?.originFileObj) {
|
||||
const file = newFileList[0].originFileObj;
|
||||
try {
|
||||
const res = await dispatch(uploadImage(file)).unwrap();
|
||||
if (res?.data?.status) {
|
||||
updateImageUrl(res?.data?.image);
|
||||
if (res?.data?.image) {
|
||||
setFileList([
|
||||
{
|
||||
uid: `${Date.now()}-${Math.random()}`, // Ensures uniqueness
|
||||
name: `image${Date.now()}-${Math.random()}.png`,
|
||||
status: 'done',
|
||||
url: res?.data?.image,
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Image upload failed:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newFileList?.length > 0) {
|
||||
setEditImageOpen(true);
|
||||
}
|
||||
};
|
||||
const onPreview = async (file) => {
|
||||
let src = file.url;
|
||||
if (!src) {
|
||||
src = await new Promise((resolve) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file.originFileObj);
|
||||
reader.onload = () => resolve(reader.result);
|
||||
});
|
||||
}
|
||||
setPreviewImage(src);
|
||||
setPreviewVisible(true);
|
||||
};
|
||||
|
||||
const handleCrop = (croppedData) => {
|
||||
setCroppedImage(croppedData);
|
||||
};
|
||||
|
||||
const handleShape = (shapedData) => {
|
||||
setShapedData(shapedData);
|
||||
};
|
||||
|
||||
const handleUpload = async ({ file, onSuccess, onError }) => {
|
||||
try {
|
||||
if (!file) {
|
||||
console.error('File object is null or undefined.');
|
||||
onError();
|
||||
return;
|
||||
}
|
||||
|
||||
const data = await dispatch(uploadImage(file)).unwrap();
|
||||
|
||||
if (data?.data?.status) {
|
||||
if (Object.keys(isProductList)?.length > 0) {
|
||||
const { isProductListPutapi, record, imagePutFunction } =
|
||||
isProductList;
|
||||
if (isProductListPutapi) {
|
||||
imagePutFunction(data?.data?.image, record);
|
||||
setFileList([{ url: data?.data?.image }]);
|
||||
onSuccess(); // Trigger onSuccess to indicate a successful upload
|
||||
setCroppedImage(null);
|
||||
setShapedData(null);
|
||||
} else {
|
||||
updateImageUrl(data?.data?.image);
|
||||
setFileList([{ url: data?.data?.image }]);
|
||||
onSuccess(); // Trigger onSuccess to indicate a successful upload
|
||||
setCroppedImage(null);
|
||||
setShapedData(null);
|
||||
}
|
||||
} else {
|
||||
updateImageUrl(data?.data?.image);
|
||||
setFileList([{ url: data?.data?.image }]);
|
||||
onSuccess(); // Trigger onSuccess to indicate a successful upload
|
||||
setCroppedImage(null);
|
||||
setShapedData(null);
|
||||
}
|
||||
} else {
|
||||
console.error('API request was not successful:', data?.data?.error);
|
||||
onError(); // Trigger onError to indicate a failed upload
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error calling API:', error);
|
||||
onError(); // Trigger onError in case of an error
|
||||
}
|
||||
};
|
||||
const handleRemove = () => {
|
||||
if (Object.keys(isProductList)?.length > 0) {
|
||||
const { isProductListPutapi, record, imagePutFunction } = isProductList;
|
||||
if (isProductListPutapi) {
|
||||
imagePutFunction('', record);
|
||||
}
|
||||
}
|
||||
updateImageUrl('');
|
||||
setEditImageOpen(false);
|
||||
setShapedImage(false);
|
||||
setCropImage(false);
|
||||
};
|
||||
|
||||
const handleShapeCrop = () => {
|
||||
setShapedImage(true);
|
||||
setCropImage(false);
|
||||
setCroppedImage(null);
|
||||
};
|
||||
|
||||
const handleCropTool = () => {
|
||||
setCropImage(true);
|
||||
setShapedImage(false);
|
||||
setShapedData(null);
|
||||
};
|
||||
|
||||
function resizeImage(imageUrl, width, height) {
|
||||
if (!imageUrl) {
|
||||
// Handle the case where imageUrl is null or undefined
|
||||
console.error('Image URL is null or undefined.');
|
||||
return Promise.reject('Image URL is null or undefined.');
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image();
|
||||
img.crossOrigin = 'anonymous'; // Set crossOrigin to handle cross-origin images
|
||||
img.onload = function () {
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
ctx.drawImage(img, 0, 0, width, height);
|
||||
const resizedImageUrl = canvas.toDataURL();
|
||||
resolve(resizedImageUrl);
|
||||
};
|
||||
img.onerror = function (error) {
|
||||
reject(error);
|
||||
};
|
||||
img.src = imageUrl;
|
||||
});
|
||||
}
|
||||
|
||||
const beforeUpload = (file) => {
|
||||
const isAllowed = allowedTypes.includes(file.type);
|
||||
if (!isAllowed) {
|
||||
Modal.error({
|
||||
title: 'Invalid File Type',
|
||||
content:
|
||||
'Only JPG, JPEG, PNG, WEBP, SVG, GIF, and AVIF files are allowed.',
|
||||
});
|
||||
}
|
||||
return isAllowed || Upload.LIST_IGNORE; // prevents adding to fileList if invalid
|
||||
};
|
||||
|
||||
const onComplete = useCallback(() => {
|
||||
setMessageData(null);
|
||||
setMessageType(null);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Messages
|
||||
messageType={messageType}
|
||||
messageData={messageData}
|
||||
onComplete={onComplete}
|
||||
/>
|
||||
<div
|
||||
className={
|
||||
Object.keys(isProductList)?.length > 0
|
||||
? fileList.length > 0
|
||||
? 'cropUploadFieldSmall'
|
||||
: 'cropUploadFieldSmallNoData'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
<Upload
|
||||
action="https://run.mocky.io/v3/435e224c-44fb-4773-9faf-380c5e6a2188"
|
||||
listType="picture-card"
|
||||
fileList={fileList}
|
||||
customRequest={handleUpload} // Use customRequest to handle the upload process manually
|
||||
onChange={onChange}
|
||||
onPreview={onPreview}
|
||||
onRemove={handleRemove}
|
||||
beforeUpload={beforeUpload}
|
||||
>
|
||||
{fileList.length < 1 && '+ Upload'}
|
||||
</Upload>
|
||||
</div>
|
||||
<Modal visible={previewVisible} onCancel={handleCancel} footer={null}>
|
||||
<img alt="Preview" style={{ width: '100%' }} src={previewImage} />
|
||||
</Modal>
|
||||
<DefaultModal
|
||||
title="Edit Image"
|
||||
width={800}
|
||||
open={editImageOpen}
|
||||
footer={
|
||||
(cropImage && croppedImage === null) ||
|
||||
(shapedImage && shapedData === null)
|
||||
? false
|
||||
: true
|
||||
}
|
||||
buttonText="SUBMIT"
|
||||
children={
|
||||
<>
|
||||
<div className="shape-crop">
|
||||
{!croppedImage && !cropImage && !shapedImage && (
|
||||
<div>
|
||||
<img
|
||||
src={
|
||||
onlineImage !== '' && onlineImage != null
|
||||
? onlineImage
|
||||
: fileList?.[0]?.['url'] != '' &&
|
||||
fileList?.[0]?.['url'] != null
|
||||
? fileList?.[0]?.['url']
|
||||
: ''
|
||||
}
|
||||
style={{ width: '200px', height: '100px' }}
|
||||
alt="Edit Image"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="shape-crop-div">
|
||||
<div
|
||||
className="crop-button"
|
||||
style={{ backgroundColor: cropImage && '#52c41a' }}
|
||||
onClick={() => handleCropTool()}
|
||||
>
|
||||
<div>
|
||||
<PiCropBold className="crop-icon" />
|
||||
</div>
|
||||
<div>Crop Tool</div>
|
||||
</div>
|
||||
<div
|
||||
className="crop-button"
|
||||
style={{ backgroundColor: shapedImage && '#52c41a' }}
|
||||
onClick={() => handleShapeCrop()}
|
||||
>
|
||||
<div>
|
||||
<FiPenTool className="crop-icon" />
|
||||
</div>
|
||||
<div>Pen Tool</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{cropImage && (
|
||||
<ImageCropper
|
||||
imageUrl={
|
||||
onlineImage !== '' && onlineImage != null
|
||||
? onlineImage
|
||||
: fileList?.[0]?.['url'] != '' &&
|
||||
fileList?.[0]?.['url'] != null
|
||||
? fileList?.[0]?.['url']
|
||||
: ''
|
||||
}
|
||||
onCrop={handleCrop}
|
||||
/>
|
||||
)}
|
||||
|
||||
{croppedImage && cropImage && (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
flexDirection: 'column',
|
||||
gap: '2rem',
|
||||
}}
|
||||
>
|
||||
<h4 style={{ marginLeft: '-33rem' }}>
|
||||
Cropped Image Preview
|
||||
</h4>
|
||||
<img
|
||||
src={croppedImage}
|
||||
alt="Cropped Image"
|
||||
style={{ width: '200px', height: '100px' }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{shapedImage && (
|
||||
<ShapeCropper
|
||||
imageUrl={
|
||||
resizedImageUrl !== '' && resizedImageUrl !== null
|
||||
? resizedImageUrl
|
||||
: ''
|
||||
}
|
||||
onShape={handleShape}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
handleSubmit={
|
||||
croppedImage == null && shapedData == null
|
||||
? SetDefault
|
||||
: croppedImage != null
|
||||
? handleSubmit
|
||||
: handleShapeSubmit
|
||||
}
|
||||
handleCancel={handleEditImageCancle}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default CropUpload;
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
import React, { useRef, useEffect, useState } from 'react';
|
||||
import Cropper from 'cropperjs';
|
||||
import 'cropperjs/dist/cropper.css';
|
||||
import { Button, Slider } from 'antd';
|
||||
|
||||
const ImageCropper = ({ imageUrl, onCrop }) => {
|
||||
const imageRef = useRef(null);
|
||||
const [cropper, setCropper] = useState(null);
|
||||
const [rotation, setRotation] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
if (imageRef.current && imageUrl) {
|
||||
if (cropper) {
|
||||
cropper.replace(imageUrl);
|
||||
} else {
|
||||
const newCropper = new Cropper(imageRef.current, {});
|
||||
setCropper(newCropper);
|
||||
}
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (cropper) {
|
||||
cropper.destroy();
|
||||
}
|
||||
};
|
||||
}, [imageUrl]); // Watch for changes in imageUrl
|
||||
|
||||
useEffect(() => {
|
||||
if (cropper) {
|
||||
cropper.rotateTo(rotation);
|
||||
}
|
||||
}, [rotation]); // Watch for changes in rotation
|
||||
|
||||
const handleCrop = () => {
|
||||
if (cropper) {
|
||||
const croppedData = cropper.getCroppedCanvas().toDataURL();
|
||||
onCrop(croppedData);
|
||||
}
|
||||
};
|
||||
|
||||
const handleRotationChange = (value) => {
|
||||
setRotation(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
flexDirection: 'column',
|
||||
gap: '2rem',
|
||||
}}
|
||||
>
|
||||
<img
|
||||
ref={imageRef}
|
||||
src={imageUrl}
|
||||
alt="Crop Preview"
|
||||
style={{ width: '300px', height: '150px' }}
|
||||
/>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>
|
||||
<Button danger onClick={handleCrop}>
|
||||
Crop Image
|
||||
</Button>
|
||||
<span>Rotation: {rotation}°</span>
|
||||
<Slider
|
||||
min={0}
|
||||
max={360}
|
||||
step={1}
|
||||
value={rotation}
|
||||
onChange={handleRotationChange}
|
||||
style={{ width: '200px' }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ImageCropper;
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
import {DatePic as DatePicLibrary} from"../../../ownLib/my-ui-lib"
|
||||
export const DatePic = DatePicLibrary
|
||||
|
||||
// import { DatePicker, Space } from 'antd';
|
||||
// export const DatePic = ({ fieldState, ...props }) => {
|
||||
// const { value } = fieldState;
|
||||
// const {
|
||||
// required,
|
||||
// field,
|
||||
// onChange,
|
||||
// onBlur,
|
||||
// canSelectPast,
|
||||
// initialValue,
|
||||
// forwardedRef,
|
||||
// min,
|
||||
// className,
|
||||
// content,
|
||||
// faClass,
|
||||
// icon,
|
||||
// ...rest
|
||||
// } = props;
|
||||
|
||||
// const disabledDate = (current) => {
|
||||
// var date = new Date();
|
||||
// date.setDate(date.getDate() + 1);
|
||||
// return current.valueOf() <= date.setDate(date.getDate() - 2);
|
||||
// };
|
||||
|
||||
// return (
|
||||
// <Space direction="vertical">
|
||||
// <DatePicker
|
||||
// {...rest}
|
||||
// id={field}
|
||||
// type="date"
|
||||
// ref={forwardedRef}
|
||||
// required={required}
|
||||
// value={value}
|
||||
// disabledDate={canSelectPast ? '' : disabledDate}
|
||||
// format="DD-MM-YYYY"
|
||||
// onChange={onChange}
|
||||
// inputReadOnly={true}
|
||||
// />
|
||||
// </Space>
|
||||
// );
|
||||
// };
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
|
||||
import {DatePicEmpMaster} from"../../../ownLib/my-ui-lib"
|
||||
export const DatePic = DatePicEmpMaster
|
||||
|
||||
// import { DatePicker, Space } from 'antd';
|
||||
// import dayjs from 'dayjs';
|
||||
// import customParseFormat from 'dayjs/plugin/customParseFormat';
|
||||
// import FloatLabel from './FloatLabel/index.jsx';
|
||||
|
||||
// dayjs.extend(customParseFormat);
|
||||
|
||||
// export const DatePic = ({
|
||||
// onChange,
|
||||
// label,
|
||||
// isOnChange,
|
||||
// canSelectPast,
|
||||
// valueData,
|
||||
// }) => {
|
||||
// const disabledDate = (current) => {
|
||||
// const today = dayjs().startOf('day');
|
||||
// if (canSelectPast === undefined) {
|
||||
// return false;
|
||||
// } else if (canSelectPast) {
|
||||
// return current && current > today;
|
||||
// } else {
|
||||
// return current && current < today;
|
||||
// }
|
||||
// };
|
||||
|
||||
// return (
|
||||
// <Space direction="vertical">
|
||||
// <FloatLabel label={label} isOnChange={isOnChange}>
|
||||
// <DatePicker
|
||||
// style={{ height: '49px' }}
|
||||
// format="DD-MM-YYYY"
|
||||
// value={
|
||||
// valueData != undefined
|
||||
// ? dayjs(valueData, 'YYYY-MM-DDTHH:mm:ss')
|
||||
// : ''
|
||||
// }
|
||||
// disabledDate={disabledDate}
|
||||
// onChange={onChange}
|
||||
// inputReadOnly={true}
|
||||
// />
|
||||
// </FloatLabel>
|
||||
// </Space>
|
||||
// );
|
||||
// };
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
|
||||
import {DatePicProd as DatePicProdLibrary}from"../../../ownLib/my-ui-lib"
|
||||
export const DatePicProd = DatePicProdLibrary
|
||||
|
||||
// import { DatePicker, Space } from 'antd';
|
||||
// import dayjs from 'dayjs';
|
||||
// import customParseFormat from 'dayjs/plugin/customParseFormat';
|
||||
|
||||
// dayjs.extend(customParseFormat);
|
||||
|
||||
// export const DatePicProd = ({
|
||||
// onChange,
|
||||
// canSelectPast,
|
||||
// valueData,
|
||||
// disabled,
|
||||
// cancelFuture,
|
||||
// minDate,
|
||||
// dontallowfeature,
|
||||
// }) => {
|
||||
// const disabledDate = (current) => {
|
||||
// var date = new Date();
|
||||
// date.setDate(date.getDate() + 1);
|
||||
// return current.valueOf() <= date.setDate(date.getDate() - 2);
|
||||
// };
|
||||
|
||||
// const disabledFutureDate = (current) => {
|
||||
// // Can not select days before today and today
|
||||
// return current && current > dayjs().endOf('day');
|
||||
// };
|
||||
// const disabledMinDate = (current) => {
|
||||
// if (minDate) {
|
||||
// return (
|
||||
// current &&
|
||||
// current < dayjs(minDate, 'YYYY-MM-DDTHH:mm:ss').startOf('day')
|
||||
// );
|
||||
// }
|
||||
// return false;
|
||||
// };
|
||||
|
||||
// return (
|
||||
// <Space direction="vertical">
|
||||
// <DatePicker
|
||||
// format="DD-MM-YYYY"
|
||||
// value={valueData ? dayjs(valueData, 'YYYY-MM-DDTHH:mm:ss') : ''}
|
||||
// disabledDate={(current) => {
|
||||
// if (dontallowfeature) {
|
||||
// return current && current > dayjs().endOf('day');
|
||||
// } else if (canSelectPast) {
|
||||
// if (cancelFuture) {
|
||||
// return disabledFutureDate(current) || disabledMinDate(current);
|
||||
// }
|
||||
// return disabledMinDate(current);
|
||||
// }
|
||||
// return disabledDate(current) || disabledMinDate(current);
|
||||
// }}
|
||||
// disabled={disabled}
|
||||
// onChange={onChange}
|
||||
// inputReadOnly={true}
|
||||
// />
|
||||
// </Space>
|
||||
// );
|
||||
// };
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
import { Select } from 'antd';
|
||||
import classnames from 'classnames';
|
||||
import FloatLabel from './FloatLabel/index';
|
||||
import React, { forwardRef, useEffect, useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import {
|
||||
changeDropDownStatus,
|
||||
GlobalfocusStatusCust,
|
||||
} from '../../Features/BookingScreen/BookingData/BookingData';
|
||||
import { validateSafeInput } from '../../Services/Others';
|
||||
|
||||
export const DropDowns = forwardRef((props, ref) => {
|
||||
const {
|
||||
options,
|
||||
onChangeFunction,
|
||||
isOnchanges,
|
||||
className,
|
||||
defaultValue,
|
||||
disabled,
|
||||
alphabetfilter,
|
||||
label,
|
||||
valueData,
|
||||
labelChange,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
const [isOnChangeState, setIsOnChangeState] = useState(isOnchanges);
|
||||
const dispatch = useDispatch();
|
||||
const selectStatuscust = useSelector(GlobalfocusStatusCust);
|
||||
|
||||
useEffect(() => {
|
||||
setIsOnChangeState(isOnchanges);
|
||||
}, [isOnchanges]);
|
||||
|
||||
const handleMouseEnter = () => {
|
||||
dispatch(changeDropDownStatus(true));
|
||||
};
|
||||
|
||||
const handleChangeStatus = () => {
|
||||
dispatch(changeDropDownStatus(false));
|
||||
setIsOnChangeState(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<div onMouseEnter={handleMouseEnter}>
|
||||
<FloatLabel
|
||||
ref={ref}
|
||||
label={label}
|
||||
value={valueData ?? ''}
|
||||
isOnChange={valueData != null ? true : isOnChangeState}
|
||||
>
|
||||
<Select
|
||||
{...rest}
|
||||
showSearch
|
||||
style={{ width: 250 }}
|
||||
defaultValue={defaultValue ?? null}
|
||||
optionFilterProp="children"
|
||||
filterOption={
|
||||
props.filterOption !== undefined
|
||||
? props.filterOption
|
||||
: !labelChange
|
||||
? (input, option) =>
|
||||
(option?.label ?? '')
|
||||
?.toLowerCase()
|
||||
?.includes(input?.toLowerCase())
|
||||
: null
|
||||
}
|
||||
filterSort={
|
||||
!labelChange
|
||||
? (a, b) =>
|
||||
alphabetfilter === 'No'
|
||||
? parseInt(a.value, 10) - parseInt(b.value, 10)
|
||||
: (a?.label ?? '')
|
||||
?.toLowerCase()
|
||||
?.localeCompare((b?.label ?? '')?.toLowerCase())
|
||||
: null
|
||||
}
|
||||
value={valueData}
|
||||
onChange={(e, option) => {
|
||||
onChangeFunction(e, option);
|
||||
handleChangeStatus();
|
||||
}}
|
||||
options={options}
|
||||
className={classnames(className)}
|
||||
disabled={disabled}
|
||||
// getPopupContainer={(triggerNode) => triggerNode.parentNode}
|
||||
getPopupContainer={(triggerNode) => document.body}
|
||||
/>
|
||||
</FloatLabel>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
// export const DropDowns = forwardRef(({ options, onChangeFunction, isOnchanges, className, defaultValue, disabled, numberOpt, alphabetfilter, ...props },ref) => {
|
||||
// const [inpValue, setInputValue] = useState('')
|
||||
// const [isOnchange, setisOnchange] = useState(isOnchanges)
|
||||
// const dispatch = useDispatch();
|
||||
// const selectStatuscust = useSelector(GlobalfocusStatusCust);
|
||||
|
||||
// useEffect(() => {
|
||||
// setisOnchange(isOnchanges)
|
||||
// }, [isOnchanges])
|
||||
|
||||
// const changeStatus = () => {
|
||||
// dispatch(changeDropDownStatus(false))
|
||||
// setisOnchange(true)
|
||||
// }
|
||||
|
||||
// const {
|
||||
// field,
|
||||
// onChange,
|
||||
// label,
|
||||
// onBlur,
|
||||
// forwardedRef,
|
||||
// required,
|
||||
// valueData,
|
||||
// labelChange,
|
||||
// ...rest
|
||||
// } = props;
|
||||
// const MouseFunction = async (e) => {
|
||||
|
||||
// dispatch(changeDropDownStatus(e))
|
||||
// }
|
||||
|
||||
// const openMenuClick = async () => {
|
||||
// // await dispatch(changefocusStatusCustMouse(true));
|
||||
|
||||
// }
|
||||
|
||||
// // const HandleClick = async (e) => {
|
||||
// // MouseFunction(false)
|
||||
// // if (!e) {
|
||||
// // dispatch(changefocusStatusCust(!selectStatuscust));
|
||||
// // }
|
||||
// // };
|
||||
|
||||
// return (
|
||||
// <div onMouseEnter={() => MouseFunction(true)}
|
||||
// // onMouseLeave={() => MouseFunction(false)}
|
||||
// // last i commet this one
|
||||
|
||||
// onClick={() => openMenuClick()}>
|
||||
// <FloatLabel
|
||||
// label={label}
|
||||
// value={inpValue}
|
||||
// isOnChange={valueData != null ? true : isOnchange}
|
||||
// >
|
||||
|
||||
// <Select
|
||||
// showSearch
|
||||
// ref={ref}
|
||||
// style={{
|
||||
// width: 250
|
||||
// }}
|
||||
// defaultValue={defaultValue ? defaultValue : null}
|
||||
// optionFilterProp="children"
|
||||
// filterOption={
|
||||
// !labelChange
|
||||
// ? (input, option) =>
|
||||
// (option?.label ?? '')
|
||||
// .toLowerCase()
|
||||
// .includes(input?.toLowerCase())
|
||||
// : null
|
||||
// }
|
||||
// filterSort={
|
||||
// !labelChange
|
||||
// ? (optionA, optionB) => {
|
||||
// if (alphabetfilter === "No") {
|
||||
// return parseInt(optionA.value, 10) - parseInt(optionB.value, 10);
|
||||
|
||||
// } else {
|
||||
// return (optionA?.label ?? '')
|
||||
// ?.toLowerCase()
|
||||
// ?.localeCompare((optionB?.label ?? '').toLowerCase());
|
||||
// }
|
||||
// }
|
||||
// : null
|
||||
// }
|
||||
// value={valueData}
|
||||
// onChange={(e) => {
|
||||
// onChangeFunction(e);
|
||||
// changeStatus();
|
||||
// }}
|
||||
// onSelect={(e) => changeStatus(e)}
|
||||
// options={options}
|
||||
// className={classnames(` ${className}`)}
|
||||
// disabled={disabled ? true : false}
|
||||
// // onMenuClose={() => HandleClick(false)}
|
||||
// />
|
||||
// </FloatLabel>
|
||||
// </div>
|
||||
|
||||
// )
|
||||
// });
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
import { Select } from 'antd';
|
||||
import classnames from 'classnames';
|
||||
import FloatLabel from './FloatLabel/index';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import {
|
||||
changeDropDownStatus,
|
||||
GlobalfocusStatusCust,
|
||||
} from '../../Features/BookingScreen/BookingData/BookingData';
|
||||
|
||||
export const DropDowns1 = ({
|
||||
options,
|
||||
onChangeFunction,
|
||||
isOnchanges,
|
||||
className,
|
||||
defaultValue,
|
||||
disabled,
|
||||
numberOpt,
|
||||
alphabetfilter,
|
||||
labelChange,
|
||||
valueData,
|
||||
label,
|
||||
...props
|
||||
}) => {
|
||||
const [inpValue, setInputValue] = useState('');
|
||||
const [isOnchange, setisOnchange] = useState(isOnchanges);
|
||||
const dispatch = useDispatch();
|
||||
const selectStatuscust = useSelector(GlobalfocusStatusCust);
|
||||
|
||||
useEffect(() => {
|
||||
setisOnchange(isOnchanges);
|
||||
}, [isOnchanges]);
|
||||
|
||||
const changeStatus = () => {
|
||||
dispatch(changeDropDownStatus(false));
|
||||
setisOnchange(true);
|
||||
};
|
||||
|
||||
const MouseFunction = (e) => {
|
||||
dispatch(changeDropDownStatus(e));
|
||||
};
|
||||
|
||||
const openMenuClick = () => {
|
||||
// You can add logic here if needed
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
onMouseEnter={() => MouseFunction(true)}
|
||||
// onMouseLeave={() => MouseFunction(false)} // uncomment if needed
|
||||
onClick={() => openMenuClick()}
|
||||
>
|
||||
<FloatLabel
|
||||
label={label}
|
||||
value={inpValue}
|
||||
isOnChange={valueData != null ? true : isOnchange}
|
||||
>
|
||||
<Select
|
||||
showSearch
|
||||
style={{ width: 250 }}
|
||||
defaultValue={defaultValue ?? null}
|
||||
optionFilterProp="children"
|
||||
filterOption={
|
||||
!labelChange
|
||||
? (input, option) => {
|
||||
// Use searchLabel if available, else empty string (to avoid errors)
|
||||
const target = option?.searchLabel ?? '';
|
||||
return target?.toLowerCase().includes(input?.toLowerCase());
|
||||
}
|
||||
: null
|
||||
}
|
||||
filterSort={
|
||||
!labelChange
|
||||
? (optionA, optionB) => {
|
||||
if (alphabetfilter === 'No') {
|
||||
return (
|
||||
parseInt(optionA.value, 10) - parseInt(optionB.value, 10)
|
||||
);
|
||||
} else {
|
||||
const a = optionA?.searchLabel ?? '';
|
||||
const b = optionB?.searchLabel ?? '';
|
||||
return a?.toLowerCase()?.localeCompare(b?.toLowerCase());
|
||||
}
|
||||
}
|
||||
: null
|
||||
}
|
||||
value={valueData}
|
||||
onChange={(e) => {
|
||||
onChangeFunction(e);
|
||||
changeStatus();
|
||||
}}
|
||||
onSelect={(e) => changeStatus(e)}
|
||||
options={options}
|
||||
className={classnames(className)}
|
||||
disabled={!!disabled}
|
||||
{...props}
|
||||
/>
|
||||
</FloatLabel>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
|
||||
import { FilterButton as FilterButtonLibrary } from "../../../ownLib/my-ui-lib"
|
||||
export const FilterButton = FilterButtonLibrary
|
||||
|
||||
export default FilterButton;
|
||||
// import { Select } from 'antd';
|
||||
// import classnames from 'classnames';
|
||||
// import FloatLabel from './FloatLabel/index';
|
||||
// import React, { useState } from 'react';
|
||||
|
||||
// export const FilterButton = ({
|
||||
// options,
|
||||
// onChangeFunction,
|
||||
// isOnchanges,
|
||||
// className,
|
||||
// defaultValue,
|
||||
// disabled,
|
||||
// onSearch,
|
||||
// onSearchChange,
|
||||
// ...props
|
||||
// }) => {
|
||||
// const [inpValue, setInputValue] = useState('');
|
||||
// const [isOnchange, setisOnchange] = useState(isOnchanges);
|
||||
|
||||
// const changeStatus = async () => {
|
||||
// await setisOnchange(true);
|
||||
// };
|
||||
|
||||
// const {
|
||||
// field,
|
||||
// onChange,
|
||||
// label,
|
||||
// onBlur,
|
||||
// forwardedRef,
|
||||
// required,
|
||||
// valueData,
|
||||
// ...rest
|
||||
// } = props;
|
||||
|
||||
// return (
|
||||
// <FloatLabel label={label} value={inpValue} isOnChange={isOnchange}>
|
||||
// <Select
|
||||
// showSearch
|
||||
// style={{
|
||||
// width: 220,
|
||||
// }}
|
||||
// defaultValue={defaultValue ? defaultValue : null}
|
||||
// optionFilterProp="children"
|
||||
// filterOption={(input, option) => (option?.label ?? '')?.includes(input)}
|
||||
// filterSort={(optionA, optionB) =>
|
||||
// (optionA?.label ?? '')
|
||||
// ?.toLowerCase()
|
||||
// ?.localeCompare((optionB?.label ?? '')?.toLowerCase())
|
||||
// }
|
||||
// value={valueData}
|
||||
// onChange={(e) => onChangeFunction(e)}
|
||||
// onSelect={(e) => changeStatus(e)}
|
||||
// options={options}
|
||||
// className={classnames(` ${className}`)}
|
||||
// disabled={disabled ? true : false}
|
||||
// />
|
||||
// </FloatLabel>
|
||||
// );
|
||||
// };
|
||||
|
||||
// export default FilterButton;
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
.float-label {
|
||||
position: relative;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 14px !important;
|
||||
font-weight: normal;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
left: 12px;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
top: 14px;
|
||||
transition: 0.2s ease all;
|
||||
}
|
||||
|
||||
.label-float {
|
||||
font-size: 12px !important;
|
||||
top: 2px;
|
||||
left: 12px;
|
||||
font-style: normal;
|
||||
color: #007eb5;
|
||||
z-index: 23;
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// import React, { useState } from 'react';
|
||||
// import './index.css';
|
||||
import { FloatLabel as FloatLabelLibrary } from '../../../../ownLib/my-ui-lib.js';
|
||||
|
||||
const FloatLabel = FloatLabelLibrary
|
||||
|
||||
export default FloatLabel;
|
||||
// const FloatLabel = (props) => {
|
||||
// const [focus, setFocus] = useState(false);
|
||||
// const { children, label, value, isOnChange } = props;
|
||||
|
||||
// const labelClass =
|
||||
// focus || (value && value?.length !== 0) || isOnChange
|
||||
// ? 'label label-float'
|
||||
// : 'label';
|
||||
|
||||
// return (
|
||||
// <div
|
||||
// className="float-label"
|
||||
// onBlur={() => setFocus(false)}
|
||||
// onFocus={() => setFocus(true)}
|
||||
// >
|
||||
// {children}
|
||||
// <label className={labelClass}>{label}</label>
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
|
||||
// export default FloatLabel;
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
// import React, {useState } from "react";
|
||||
// import { Input} from "antd";
|
||||
// import FloatLabel from "./FloatLabel/index.jsx";
|
||||
// import "./main.scss";
|
||||
|
||||
// export const InputField = ({...props}) => {
|
||||
// const [inpValue , setInputValue] = useState('')
|
||||
// const {
|
||||
// onChange,
|
||||
// isOnChange,
|
||||
// onBlur,
|
||||
// onKeyUp,
|
||||
// label,
|
||||
// disable=false,
|
||||
// ...rest
|
||||
// } = props;
|
||||
|
||||
// return (
|
||||
// <div className="example">
|
||||
// <FloatLabel
|
||||
// label={label}
|
||||
// value = {inpValue}
|
||||
// isOnChange= {isOnChange}
|
||||
// >
|
||||
// <Input
|
||||
// disabled={disable}
|
||||
// {...rest}
|
||||
// onChange={(e) => {
|
||||
// setInputValue(e?.target?.value)
|
||||
// if (onChange) {
|
||||
// onChange(e);
|
||||
// }
|
||||
|
||||
// }}
|
||||
// onBlur={(e) => {
|
||||
// if (onBlur) {
|
||||
// onBlur(e);
|
||||
// }
|
||||
// }}
|
||||
// onKeyUp={(e) => {
|
||||
// if (onKeyUp) {
|
||||
// onKeyUp(e);
|
||||
// }
|
||||
// }}
|
||||
// autoComplete="Off"
|
||||
// />
|
||||
// </FloatLabel>
|
||||
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
|
||||
// import React, {
|
||||
// forwardRef,
|
||||
// useImperativeHandle,
|
||||
// useRef,
|
||||
// useState,
|
||||
// } from 'react';
|
||||
// import { Input } from 'antd';
|
||||
// import FloatLabel from './FloatLabel/index.jsx';
|
||||
// import './main.scss';
|
||||
|
||||
import { InputField as InputFieldLibrary } from '../../../ownLib/my-ui-lib.js';
|
||||
|
||||
|
||||
export const InputField = InputFieldLibrary
|
||||
|
||||
// export const InputField = forwardRef((props, outerRef) => {
|
||||
// const [inpValue, setInputValue] = useState('');
|
||||
// const inputRef = useRef(null);
|
||||
// const wrapperRef = useRef(null);
|
||||
// const {
|
||||
// onChange,
|
||||
// isOnChange,
|
||||
// onBlur,
|
||||
// onKeyUp,
|
||||
// label,
|
||||
// disable = false,
|
||||
// ...rest
|
||||
// } = props;
|
||||
// useImperativeHandle(outerRef, () => wrapperRef.current);
|
||||
|
||||
// return (
|
||||
// <div className="example" ref={wrapperRef}>
|
||||
// <FloatLabel label={label} value={inpValue} isOnChange={isOnChange}>
|
||||
// <Input
|
||||
// ref={inputRef}
|
||||
// disabled={disable}
|
||||
// {...rest}
|
||||
// onChange={(e) => {
|
||||
// setInputValue(e?.target?.value);
|
||||
// if (onChange) {
|
||||
// onChange(e);
|
||||
// }
|
||||
// }}
|
||||
// onBlur={(e) => {
|
||||
// if (onBlur) {
|
||||
// onBlur(e);
|
||||
// }
|
||||
// }}
|
||||
// onKeyUp={(e) => {
|
||||
// if (onKeyUp) {
|
||||
// onKeyUp(e);
|
||||
// }
|
||||
// }}
|
||||
// autoComplete="Off"
|
||||
// />
|
||||
// </FloatLabel>
|
||||
// </div>
|
||||
// );
|
||||
// });
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
.ant-radio-wrapper .ant-radio-checked .ant-radio-inner {
|
||||
border-color: #000000;
|
||||
background-color: #000000;
|
||||
}
|
||||
|
||||
.ant-radio-wrapper .ant-radio-inner {
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
inset-block-start: 0;
|
||||
inset-inline-start: 0;
|
||||
display: block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color: #ffffff;
|
||||
border-color: #000000;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-radius: 50%;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
import {RadioGrpButton as RadioGrpButtonLibrary} from "../../../ownLib/my-ui-lib"
|
||||
export const RadioGrpButton = RadioGrpButtonLibrary
|
||||
// import { Radio } from 'antd';
|
||||
// import { useEffect, useState } from 'react';
|
||||
// import './RadioBtn.scss';
|
||||
// export const RadioGrpButton = ({ fieldState, style, ...props }) => {
|
||||
// const {
|
||||
// field,
|
||||
// onBlur,
|
||||
// initialValue,
|
||||
// forwardedRef,
|
||||
// onClickFunction,
|
||||
// className,
|
||||
// onSelectFuntion,
|
||||
// content,
|
||||
// Header,
|
||||
// defaultSelect,
|
||||
// disabled,
|
||||
// ...rest
|
||||
// } = props;
|
||||
|
||||
// const [value, setValue] = useState(defaultSelect);
|
||||
// const onChange = (e) => {
|
||||
// setValue(e?.target?.value);
|
||||
// if (onSelectFuntion) {
|
||||
// onSelectFuntion(e?.target?.value);
|
||||
// }
|
||||
// };
|
||||
|
||||
// const onClickfun = (e) => {
|
||||
// if (onClickFunction) {
|
||||
// onClickFunction(e?.target?.value);
|
||||
// }
|
||||
// };
|
||||
// useEffect(() => {
|
||||
// setValue(defaultSelect);
|
||||
// }, [props]);
|
||||
// return (
|
||||
// <div>
|
||||
// <p style={{ paddingBottom: '10px', fontWeight: '500' }}>{Header}</p>
|
||||
|
||||
// <Radio.Group onChange={onChange} value={value}>
|
||||
// {content?.map((key, index) => (
|
||||
// <Radio
|
||||
// value={key.value}
|
||||
// key={index}
|
||||
// onClick={(e) => onClickfun(e)}
|
||||
// disabled={disabled ? disabled : false}
|
||||
// >
|
||||
// {key.label}
|
||||
// </Radio>
|
||||
// ))}
|
||||
// </Radio.Group>
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import { Radio } from 'antd';
|
||||
|
||||
export const RadioButton = ({ faClass, style, ...props }) => {
|
||||
const { onChange, onBlur, ...rest } = props;
|
||||
|
||||
return (
|
||||
<Radio
|
||||
{...rest}
|
||||
name={props.props.name}
|
||||
value={props.props.value}
|
||||
onChange={(e) => {
|
||||
if (onChange) {
|
||||
onChange(e);
|
||||
}
|
||||
}}
|
||||
onBlur={(e) => {
|
||||
if (onBlur) {
|
||||
onBlur(e);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{props.props.label}
|
||||
</Radio>
|
||||
);
|
||||
};
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
import {ScannerInputField as ScannerInputFieldLibrary} from "../../../ownLib/my-ui-lib"
|
||||
|
||||
export const ScannerInputField = ScannerInputFieldLibrary
|
||||
// import React, { useState } from 'react';
|
||||
// import { Input } from 'antd';
|
||||
// import FloatLabel from './FloatLabel/index.jsx';
|
||||
// import './main.scss';
|
||||
|
||||
// export const ScannerInputField = ({ ...props }) => {
|
||||
// const [inpValue, setInputValue] = useState('');
|
||||
|
||||
// const {
|
||||
// onChange,
|
||||
// isOnChange,
|
||||
|
||||
// label,
|
||||
|
||||
// valueData,
|
||||
// ...rest
|
||||
// } = props;
|
||||
|
||||
// return (
|
||||
// <div className="example">
|
||||
// <FloatLabel label={label} value={inpValue} isOnChange={isOnChange}>
|
||||
// <Input
|
||||
// {...rest}
|
||||
// onChange={(e) => {
|
||||
// setInputValue(e?.target?.value);
|
||||
// if (onChange) {
|
||||
// onChange(e);
|
||||
// }
|
||||
// }}
|
||||
// />
|
||||
// </FloatLabel>
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import {Search as SearchLibrary} from "../../../ownLib/my-ui-lib"
|
||||
|
||||
export const Search = SearchLibrary
|
||||
|
||||
|
||||
export default Search;
|
||||
// import { Input } from 'antd';
|
||||
// import { SearchOutlined } from '@ant-design/icons';
|
||||
// import './main.scss';
|
||||
// import React from 'react';
|
||||
|
||||
// export const Search = React.forwardRef(({ placeholder, onSearch, onSearchChange, value }, ref) => {
|
||||
|
||||
// return (
|
||||
// <Input
|
||||
// ref={ref}
|
||||
// maxLength={50}
|
||||
// value={value}
|
||||
// className="searchDiv"
|
||||
// placeholder={placeholder}
|
||||
// prefix={<SearchOutlined style={{ color: '#999' }} />}
|
||||
// onPressEnter={onSearch}
|
||||
// onChange={onSearchChange}
|
||||
// />
|
||||
// )
|
||||
// })
|
||||
|
||||
// export default Search;
|
||||
|
|
@ -0,0 +1,249 @@
|
|||
import {ShapeCropper as ShapeCropperLibrary} from "../../../ownLib/my-ui-lib"
|
||||
|
||||
const ShapeCropper=ShapeCropperLibrary
|
||||
|
||||
export default ShapeCropper;
|
||||
// import React, { useEffect, useRef, useState, useCallback } from 'react';
|
||||
// import { ReloadOutlined, EyeOutlined, DeleteFilled } from '@ant-design/icons';
|
||||
// import { Messages } from '../../Components/Notifications/Messages';
|
||||
// import TooltipWrapper from '../../Components/Tooltip/Tooltip';
|
||||
// import { isMobile } from 'react-device-detect';
|
||||
|
||||
// const ShapeCropper = ({ imageUrl, onShape }) => {
|
||||
// const canvasRef = useRef(null);
|
||||
// const imgRef = useRef(null);
|
||||
|
||||
// const [messageType, setMessageType] = useState(null);
|
||||
// const [messageData, setMessageData] = useState(null);
|
||||
// const [points, setPoints] = useState([]);
|
||||
// const [imageLoaded, setImageLoaded] = useState(false);
|
||||
// const [clippedImages, setClippedImages] = useState([]);
|
||||
// const [definingClippingPath, setDefiningClippingPath] = useState(false);
|
||||
// const [isPreview, setIsPreview] = useState(false);
|
||||
|
||||
// useEffect(() => {
|
||||
// setPoints([]);
|
||||
// setClippedImages([]);
|
||||
// setDefiningClippingPath(true);
|
||||
// setImageLoaded(false);
|
||||
|
||||
// const canvas = canvasRef.current;
|
||||
// const ctx = canvas.getContext('2d');
|
||||
|
||||
// const img = new Image();
|
||||
// img.crossOrigin = 'anonymous';
|
||||
// img.onload = () => {
|
||||
// imgRef.current = img;
|
||||
|
||||
// canvas.width = img.width;
|
||||
// canvas.height = img.height;
|
||||
// ctx.drawImage(img, 0, 0);
|
||||
// setImageLoaded(true);
|
||||
// };
|
||||
// img.src = imageUrl;
|
||||
|
||||
// return () => {
|
||||
// ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
// setPoints([]);
|
||||
// setClippedImages([]);
|
||||
// setImageLoaded(false);
|
||||
// setDefiningClippingPath(true);
|
||||
// };
|
||||
// }, [imageUrl]);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (imageLoaded && definingClippingPath) {
|
||||
// const canvas = canvasRef.current;
|
||||
// const ctx = canvas.getContext('2d');
|
||||
// ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
// ctx.drawImage(imgRef.current, 0, 0);
|
||||
// drawClippingPath(ctx);
|
||||
// }
|
||||
// }, [imageLoaded, definingClippingPath, points]);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (clippedImages.length > 0) {
|
||||
// onShape(clippedImages);
|
||||
// }
|
||||
// }, [clippedImages]);
|
||||
|
||||
// const onComplete = useCallback(() => {
|
||||
// setMessageData(null);
|
||||
// setMessageType(null);
|
||||
// }, []);
|
||||
// const handleMouseDown = (e) => {
|
||||
// e.preventDefault();
|
||||
// e.stopPropagation();
|
||||
|
||||
// const rect = canvasRef.current.getBoundingClientRect();
|
||||
// const mx = e.clientX - rect.left;
|
||||
// const my = e.clientY - rect.top;
|
||||
|
||||
// if (
|
||||
// points.length > 1 &&
|
||||
// Math.abs(mx - points[0].x) < 10 &&
|
||||
// Math.abs(my - points[0].y) < 10
|
||||
// ) {
|
||||
// clipIt();
|
||||
// setDefiningClippingPath(false);
|
||||
// } else {
|
||||
// setPoints([...points, { x: mx, y: my }]);
|
||||
// }
|
||||
// };
|
||||
|
||||
// const drawClippingPath = (ctx) => {
|
||||
// ctx.strokeStyle = '#ff4d4f';
|
||||
// ctx.beginPath();
|
||||
// if (points.length > 0) {
|
||||
// ctx.moveTo(points[0].x, points[0].y);
|
||||
// for (let i = 1; i < points.length; i++) {
|
||||
// ctx.lineTo(points[i].x, points[i].y);
|
||||
// }
|
||||
// ctx.lineTo(points[0].x, points[0].y);
|
||||
// }
|
||||
// ctx.stroke();
|
||||
// if (points.length > 0) {
|
||||
// ctx.beginPath();
|
||||
// ctx.arc(points[0].x, points[0].y, 10, 0, Math.PI * 2);
|
||||
// ctx.stroke();
|
||||
// }
|
||||
// };
|
||||
|
||||
// const clipIt = () => {
|
||||
// const canvas = canvasRef.current;
|
||||
// const ctx = canvas.getContext('2d');
|
||||
|
||||
// const minX = Math.min(...points.map((point) => point.x));
|
||||
// const minY = Math.min(...points.map((point) => point.y));
|
||||
// const maxX = Math.max(...points.map((point) => point.x));
|
||||
// const maxY = Math.max(...points.map((point) => point.y));
|
||||
// const width = maxX - minX;
|
||||
// const height = maxY - minY;
|
||||
|
||||
// const clippedCanvas = document.createElement('canvas');
|
||||
// clippedCanvas.width = width;
|
||||
// clippedCanvas.height = height;
|
||||
// const clippedCtx = clippedCanvas.getContext('2d');
|
||||
|
||||
// clippedCtx.drawImage(
|
||||
// imgRef.current,
|
||||
// minX,
|
||||
// minY,
|
||||
// width,
|
||||
// height,
|
||||
// 0,
|
||||
// 0,
|
||||
// width,
|
||||
// height
|
||||
// );
|
||||
|
||||
// setMessageType('success');
|
||||
// setMessageData('Image Cropped Successfully');
|
||||
// setClippedImages((prevImages) => [
|
||||
// ...prevImages,
|
||||
// clippedCanvas.toDataURL(),
|
||||
// ]);
|
||||
|
||||
// setPoints([]);
|
||||
// };
|
||||
|
||||
// const setReset = () => {
|
||||
// if (points?.length > 0) {
|
||||
// setPoints([]);
|
||||
// onShape(null);
|
||||
// const canvas = canvasRef.current;
|
||||
// const ctx = canvas.getContext('2d');
|
||||
// ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
// } else {
|
||||
// setMessageType('error');
|
||||
// setMessageData('No Clipping Region');
|
||||
// }
|
||||
// };
|
||||
|
||||
// const setPreview = () => {
|
||||
// if (clippedImages?.length > 0) {
|
||||
// setIsPreview(!isPreview);
|
||||
// } else {
|
||||
// setMessageType('error');
|
||||
// setMessageData('No Image Found To Preview');
|
||||
// }
|
||||
// };
|
||||
|
||||
// const setRemove = () => {
|
||||
// if (clippedImages?.length > 0) {
|
||||
// setClippedImages([]);
|
||||
// setPoints([]);
|
||||
// setIsPreview(false);
|
||||
// setDefiningClippingPath(true);
|
||||
// onShape(null);
|
||||
// } else {
|
||||
// setMessageType('error');
|
||||
// setMessageData('No Image Found To Remove');
|
||||
// }
|
||||
// };
|
||||
|
||||
// return (
|
||||
// <div className="shape-crop">
|
||||
// <Messages
|
||||
// messageType={messageType}
|
||||
// messageData={messageData}
|
||||
// onComplete={onComplete}
|
||||
// />
|
||||
// <h4>
|
||||
// Click to outline clipping region. Click back in starting circle to
|
||||
// complete the clip.
|
||||
// </h4>
|
||||
// <div className="shape-crop-subdiv">
|
||||
// <div>
|
||||
// <canvas
|
||||
// ref={canvasRef}
|
||||
// width={300}
|
||||
// height={150}
|
||||
// style={{ border: '1px solid black' }}
|
||||
// onMouseDown={handleMouseDown}
|
||||
// ></canvas>
|
||||
// </div>
|
||||
// <div>
|
||||
// {isPreview &&
|
||||
// clippedImages?.map((image, index) => (
|
||||
// <img
|
||||
// key={index}
|
||||
// src={image}
|
||||
// alt={`Clipped image ${index}`}
|
||||
// style={{ width: '200px', height: '100px' }}
|
||||
// />
|
||||
// ))}
|
||||
// </div>
|
||||
// </div>
|
||||
|
||||
// <div className="shape-crop-subdiv">
|
||||
// <div>
|
||||
// <TooltipWrapper title={'Reset'} isMobile={isMobile}>
|
||||
// <ReloadOutlined
|
||||
// className="shape-reset"
|
||||
// onClick={() => setReset()}
|
||||
// />
|
||||
// </TooltipWrapper>
|
||||
// </div>
|
||||
// <div>
|
||||
// <TooltipWrapper title={'Preview'} isMobile={isMobile}>
|
||||
// <EyeOutlined
|
||||
// className="shape-preview"
|
||||
// onClick={() => setPreview()}
|
||||
// />
|
||||
// </TooltipWrapper>
|
||||
// </div>
|
||||
// <div>
|
||||
// <TooltipWrapper title={'Remove'} isMobile={isMobile}>
|
||||
// <DeleteFilled
|
||||
// className="shape-delete"
|
||||
// onClick={() => setRemove()}
|
||||
// />
|
||||
// </TooltipWrapper>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
|
||||
// export default ShapeCropper;
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
// import { Switch } from 'antd';
|
||||
|
||||
import { Toggle as ToggleLibrary } from '../../../ownLib/my-ui-lib';
|
||||
|
||||
export const Toggle = ToggleLibrary
|
||||
|
||||
// export const Toggle = ({ defaultChecked, functionName }) => {
|
||||
// return <Switch defaultChecked={defaultChecked} onChange={functionName} />;
|
||||
// };
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
import {TextAreaInput as TextAreaInputLibrary } from "../../../ownLib/my-ui-lib"
|
||||
|
||||
export const TextAreaInput = TextAreaInputLibrary
|
||||
|
||||
|
||||
export default TextAreaInput;
|
||||
// import React, { useEffect, useState } from 'react';
|
||||
// import { Input } from 'antd';
|
||||
|
||||
// import FloatLabel from './FloatLabel/index.jsx';
|
||||
|
||||
// import './main.scss';
|
||||
|
||||
// export const TextAreaInput = ({ ...props }) => {
|
||||
// const [inpValue, setInputValue] = useState(props?.defaultValue || '');
|
||||
// const { TextArea } = Input;
|
||||
|
||||
// useEffect(() => {
|
||||
// setInputValue(props?.defaultValue);
|
||||
// }, [props?.defaultValue]);
|
||||
|
||||
// const { onChange, isOnChange, onBlur, label,width = false, ...rest } = props;
|
||||
|
||||
// return (
|
||||
// <div className={width? "" : "example"} style={{ width: width ? '100%' : 'auto' }}>
|
||||
// <FloatLabel label={label} value={inpValue} isOnChange={isOnChange}>
|
||||
// <TextArea
|
||||
// {...rest}
|
||||
// onChange={(e) => {
|
||||
// setInputValue(e?.target?.value);
|
||||
// if (onChange) {
|
||||
// onChange(e);
|
||||
// }
|
||||
// }}
|
||||
// onBlur={(e) => {
|
||||
// if (onBlur) {
|
||||
// onBlur(e);
|
||||
// }
|
||||
// }}
|
||||
// />
|
||||
// </FloatLabel>
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
|
||||
// export default TextAreaInput;
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import { TimePickers as TimePickerLibrary } from "../../../ownLib/my-ui-lib"
|
||||
|
||||
export const TimePickers = TimePickerLibrary
|
||||
|
||||
export default TimePickers;
|
||||
// import { TimePicker } from 'antd';
|
||||
// import dayjs from 'dayjs';
|
||||
// import customParseFormat from 'dayjs/plugin/customParseFormat';
|
||||
// import FloatLabel from './FloatLabel/index.jsx';
|
||||
// import './main.scss';
|
||||
|
||||
// dayjs.extend(customParseFormat);
|
||||
|
||||
// export const TimePickers = ({ label, isOnChange, onChange, valueData }) => (
|
||||
// <div className="example">
|
||||
// <FloatLabel label={label} isOnChange={isOnChange}>
|
||||
// <TimePicker
|
||||
// className="TimePickerDiv"
|
||||
// use12Hours
|
||||
// format="h:mm a"
|
||||
// onChange={onChange}
|
||||
// value={valueData != undefined ? dayjs(valueData, 'HH:mm:ss') : ''}
|
||||
// inputReadOnly={true}
|
||||
// />
|
||||
// </FloatLabel>
|
||||
// </div>
|
||||
// );
|
||||
// export default TimePickers;
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
|
||||
import { TimePickersProduct as TimePickersProductLibrary} from "../../../ownLib/my-ui-lib"
|
||||
|
||||
export const TimePickers =TimePickersProductLibrary
|
||||
export default TimePickers;
|
||||
// import { TimePicker } from 'antd';
|
||||
|
||||
// import dayjs from 'dayjs';
|
||||
// import customParseFormat from 'dayjs/plugin/customParseFormat';
|
||||
|
||||
// dayjs.extend(customParseFormat);
|
||||
|
||||
// export const TimePickers = ({ onChange, valueData }) => (
|
||||
// <div>
|
||||
// <TimePicker
|
||||
// use12Hours
|
||||
// format="h:mm a"
|
||||
// onChange={onChange}
|
||||
// value={valueData != undefined ? dayjs(valueData, 'HH:mm:ss') : ''}
|
||||
// inputReadOnly={true}
|
||||
// />
|
||||
// </div>
|
||||
// );
|
||||
// export default TimePickers;
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { Modal, Upload } from 'antd';
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { uploadImage } from '../../Features/upload/upload';
|
||||
const allowedTypes = [
|
||||
'image/jpeg',
|
||||
'image/png',
|
||||
'image/webp',
|
||||
'image/svg+xml',
|
||||
'image/gif',
|
||||
'image/avif',
|
||||
];
|
||||
const getBase64 = (file) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.onload = () => resolve(reader.result);
|
||||
reader.onerror = (error) => reject(error);
|
||||
});
|
||||
|
||||
const App = ({ singleImage, updateImageUrl, ImageLink = '', listType }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [previewOpen, setPreviewOpen] = useState(false);
|
||||
const [previewImage, setPreviewImage] = useState('');
|
||||
const [previewTitle, setPreviewTitle] = useState('');
|
||||
const [fileList, setFileList] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
// Inside Imageupload.jsx
|
||||
const safeLink = typeof ImageLink === 'string' ? ImageLink : '';
|
||||
if (safeLink != '' && safeLink != null) {
|
||||
setFileList([{ url: safeLink }]);
|
||||
} else {
|
||||
setFileList([]);
|
||||
}
|
||||
}, [ImageLink]);
|
||||
|
||||
const handleCancel = () => setPreviewOpen(false);
|
||||
|
||||
const handlePreview = async (file) => {
|
||||
if (!file.url && !file.preview) {
|
||||
file.preview = await getBase64(file.originFileObj);
|
||||
}
|
||||
setPreviewImage(file.url || file.preview);
|
||||
setPreviewOpen(true);
|
||||
setPreviewTitle(
|
||||
file.name || file.url.substring(file.url.lastIndexOf('/') + 1)
|
||||
);
|
||||
};
|
||||
|
||||
const handleRemove = () => {
|
||||
updateImageUrl('');
|
||||
};
|
||||
|
||||
const handleChange = async ({ fileList: newFileList }) => {
|
||||
if (newFileList?.length > 0) {
|
||||
let data = await dispatch(
|
||||
uploadImage(newFileList[0].originFileObj)
|
||||
).unwrap();
|
||||
if (data?.data?.status) {
|
||||
updateImageUrl(data?.data?.image);
|
||||
setFileList([{ url: data?.data?.image }]);
|
||||
}
|
||||
} else {
|
||||
updateImageUrl('');
|
||||
setFileList(newFileList);
|
||||
}
|
||||
};
|
||||
|
||||
const beforeUpload = (file) => {
|
||||
const isAllowed = allowedTypes.includes(file.type);
|
||||
if (!isAllowed) {
|
||||
Modal.error({
|
||||
title: 'Invalid File Type',
|
||||
content:
|
||||
'Only JPG, JPEG, PNG, WEBP, SVG, GIF, and AVIF files are allowed.',
|
||||
});
|
||||
}
|
||||
return isAllowed || Upload.LIST_IGNORE; // prevents adding to fileList if invalid
|
||||
};
|
||||
|
||||
const uploadButton = (
|
||||
<div>
|
||||
<PlusOutlined />
|
||||
<div
|
||||
style={{
|
||||
marginTop: 8,
|
||||
}}
|
||||
className="uploadText"
|
||||
>
|
||||
Upload
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Upload
|
||||
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
|
||||
listType={listType ? listType : 'picture-circle'}
|
||||
fileList={fileList}
|
||||
onPreview={handlePreview}
|
||||
onChange={handleChange}
|
||||
onRemove={handleRemove}
|
||||
beforeUpload={beforeUpload}
|
||||
>
|
||||
{singleImage && fileList?.length == 0
|
||||
? uploadButton
|
||||
: !singleImage && fileList?.length <= 8
|
||||
? uploadButton
|
||||
: null}
|
||||
</Upload>
|
||||
<Modal
|
||||
open={previewOpen}
|
||||
title={''}
|
||||
footer={null}
|
||||
onCancel={handleCancel}
|
||||
>
|
||||
<img
|
||||
alt="example"
|
||||
style={{
|
||||
width: '100%',
|
||||
}}
|
||||
src={previewImage}
|
||||
/>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default App;
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { uploadImage } from '../../Features/upload/upload';
|
||||
import videoBg from '../../Images/TemplateImages/videobg.svg';
|
||||
import './VideoUpload.scss';
|
||||
|
||||
export default function VideoInput({ updateVideoUrl, videoUrl }) {
|
||||
const inputRef = useRef();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const [source, setSource] = useState();
|
||||
|
||||
useEffect(() => {
|
||||
if (videoUrl) {
|
||||
setSource(videoUrl);
|
||||
} else {
|
||||
if (inputRef?.current) {
|
||||
inputRef?.current?.value = null;
|
||||
}
|
||||
setSource();
|
||||
}
|
||||
}, [videoUrl]);
|
||||
|
||||
const handleFileChange = async (event) => {
|
||||
let file = event.target.files[0];
|
||||
if (event.target.files?.length > 0) {
|
||||
let data = await dispatch(uploadImage(file)).unwrap();
|
||||
if (data?.data?.status) {
|
||||
updateVideoUrl(data?.data?.image);
|
||||
setSource(data?.data?.image);
|
||||
}
|
||||
} else {
|
||||
updateVideoUrl('');
|
||||
setSource('');
|
||||
}
|
||||
};
|
||||
|
||||
const handleChoose = (event) => {
|
||||
inputRef?.current?.click();
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<input
|
||||
ref={inputRef}
|
||||
className="VideoInput_input"
|
||||
type="file"
|
||||
onChange={handleFileChange}
|
||||
accept=".mov,.mp4"
|
||||
/>
|
||||
{!source && (
|
||||
<button
|
||||
type="button"
|
||||
style={{ backgroundColor: '#cfcfcf', borderColor: '#cfcfcf' }}
|
||||
onClick={handleChoose}
|
||||
>
|
||||
<img src={videoBg} style={{ width: '150px', height: '85px' }}></img>
|
||||
</button>
|
||||
)}
|
||||
{source && <video className="VideoInput_video" controls src={source} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
.VideoInput_input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.VideoInput_video {
|
||||
display: block;
|
||||
margin: 0;
|
||||
height: 85px;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.VideoInput_footer {
|
||||
background: #eee;
|
||||
width: 100%;
|
||||
min-height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
|
||||
import {InputFieldCustom as InputFieldCustomLibrary} from "../../../ownLib/my-ui-lib"
|
||||
export const InputFieldCustom = InputFieldCustomLibrary
|
||||
|
||||
// import React, { useState } from 'react';
|
||||
// import { Input } from 'antd';
|
||||
// import FloatLabel from './FloatLabel/index.jsx';
|
||||
// import './main.scss';
|
||||
|
||||
// export const InputFieldCustom = ({ ...props }) => {
|
||||
// const [inpValue, setInputValue] = useState('');
|
||||
// const { onChange, isOnChange, onBlur, label, ...rest } = props;
|
||||
|
||||
// return (
|
||||
// <div
|
||||
// className={'CustomInputField'}
|
||||
// style={{ marginLeft: '-40px', width: '70px', fontSize: '14px' }}
|
||||
// >
|
||||
// <FloatLabel
|
||||
// label={label}
|
||||
// value={inpValue}
|
||||
// isOnChange={isOnChange}
|
||||
// style={{ width: '12px !important' }}
|
||||
// >
|
||||
// <Input
|
||||
// {...rest}
|
||||
// onChange={(e) => {
|
||||
// setInputValue(e?.target?.value);
|
||||
// if (onChange) {
|
||||
// onChange(e);
|
||||
// }
|
||||
// }}
|
||||
// onBlur={(e) => {
|
||||
// if (onBlur) {
|
||||
// onBlur(e);
|
||||
// }
|
||||
// }}
|
||||
// autoComplete="Off"
|
||||
// />
|
||||
// </FloatLabel>
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
|
|
@ -0,0 +1,983 @@
|
|||
.example {
|
||||
width: var(--INPUT_FIELD_WIDTH);
|
||||
}
|
||||
|
||||
.ant-input {
|
||||
padding: 18px 14px 6px 11px;
|
||||
font-size: 16px;
|
||||
font-weight: 490;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.ant-input:hover {
|
||||
padding: 18px 14px 6px 11px;
|
||||
font-size: 16px;
|
||||
border: var(--DEFAULT_SELECTED_COLOR) solid 1px;
|
||||
}
|
||||
|
||||
.ant-input:focus {
|
||||
padding: 18px 14px 6px 11px;
|
||||
font-size: 16px;
|
||||
border: var(--DEFAULT_SELECTED_COLOR) solid 1px;
|
||||
}
|
||||
|
||||
.ant-select .ant-select-selector {
|
||||
padding: 16px 10px 4px 11px;
|
||||
}
|
||||
|
||||
.ant-select-single:not(.ant-select-customize-input) .ant-select-selector {
|
||||
padding: 8px 10px 4px 11px;
|
||||
height: 53px;
|
||||
font-size: 16px;
|
||||
padding: 10px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.ant-select .ant-select-selector {
|
||||
padding: 16px 10px 4px 11px;
|
||||
}
|
||||
|
||||
.ant-select-single:not(.ant-select-customize-input) .ant-select-selector {
|
||||
padding: 8px 10px 4px 11px;
|
||||
height: 48px;
|
||||
font-size: 16px;
|
||||
padding: 10px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.ant-select-single .ant-select-selector .ant-select-selection-search {
|
||||
top: 16px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
:where(.css-dev-only-do-not-override-1fviqcj).ant-select-dropdown
|
||||
.ant-select-item-option-selected:not(.ant-select-item-option-disabled) {
|
||||
color: rgba(255, 255, 255, 0.88);
|
||||
font-weight: 600;
|
||||
background-color: var(--PRIMARY_BUTTON_BG_COLOR);
|
||||
}
|
||||
|
||||
.primary_Button {
|
||||
width: 170px;
|
||||
height: 42px;
|
||||
background-color: var(--PRIMARY_BUTTON_BG_COLOR) !important;
|
||||
color: #fff;
|
||||
font-family: var(--HEADING_FONT_FAMILY);
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
letter-spacing: 0.5px;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.primary_Button {
|
||||
border: 1px solid;
|
||||
overflow: hidden;
|
||||
|
||||
span {
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
&:after {
|
||||
background: #fff;
|
||||
content: '';
|
||||
height: 155px;
|
||||
left: -75px;
|
||||
opacity: 0.2;
|
||||
position: absolute;
|
||||
top: -50px;
|
||||
transform: rotate(35deg);
|
||||
transition: all 550ms cubic-bezier(0.19, 1, 0.22, 1);
|
||||
width: 50px;
|
||||
z-index: -10;
|
||||
}
|
||||
}
|
||||
|
||||
.primary_Button:hover {
|
||||
&:after {
|
||||
left: 120%;
|
||||
transition: all 550ms cubic-bezier(0.19, 1, 0.22, 1);
|
||||
}
|
||||
}
|
||||
|
||||
.primary_Button:focus {
|
||||
border: 1.8px solid var(--PRIMARY_BUTTON_BG_COLOR);
|
||||
background-color: #ffffff !important;
|
||||
color: #901d77;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.primary_Button:focus:hover {
|
||||
border: 1.8px solid var(--PRIMARY_BUTTON_BG_COLOR);
|
||||
background-color: white !important;
|
||||
color: var(--PRIMARY_BUTTON_BG_COLOR);
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.secondary_Button {
|
||||
width: 170px;
|
||||
height: 42px;
|
||||
background-color: black !important;
|
||||
color: #fff;
|
||||
font-family: var(--HEADING_FONT_FAMILY);
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
letter-spacing: 0.5px;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.secondary_Button {
|
||||
border: 1px solid;
|
||||
overflow: hidden;
|
||||
|
||||
span {
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
&:after {
|
||||
background: #fff;
|
||||
content: '';
|
||||
height: 155px;
|
||||
left: -75px;
|
||||
opacity: 0.2;
|
||||
position: absolute;
|
||||
top: -50px;
|
||||
transform: rotate(35deg);
|
||||
transition: all 550ms cubic-bezier(0.19, 1, 0.22, 1);
|
||||
width: 50px;
|
||||
z-index: -10;
|
||||
}
|
||||
}
|
||||
|
||||
.secondary_Button:hover {
|
||||
&:after {
|
||||
left: 120%;
|
||||
transition: all 550ms cubic-bezier(0.19, 1, 0.22, 1);
|
||||
}
|
||||
}
|
||||
|
||||
.secondary_Button:focus {
|
||||
border: 1.8px solid var(--PRIMARY_BUTTON_BG_COLOR);
|
||||
background-color: #ffffff !important;
|
||||
color: #901d77;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.secondary_Button:focus:hover {
|
||||
border: 1.8px solid var(--PRIMARY_BUTTON_BG_COLOR);
|
||||
background-color: white !important;
|
||||
color: var(--PRIMARY_BUTTON_BG_COLOR);
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tertiary_Button {
|
||||
width: 180px;
|
||||
height: 42px;
|
||||
background-color: var(--THIRD_BUTTON_BG_COLOR) !important;
|
||||
color: #ffffff;
|
||||
font-family: var(--HEADING_FONT_FAMILY);
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 14;
|
||||
line-height: 18px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
letter-spacing: 0.5px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 2;
|
||||
// left: 200px;
|
||||
}
|
||||
|
||||
.tertiary_Button {
|
||||
overflow: hidden;
|
||||
|
||||
span {
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
height: 155px;
|
||||
left: -15px;
|
||||
opacity: 0.2;
|
||||
position: absolute;
|
||||
top: -50px;
|
||||
transform: rotate(35deg);
|
||||
transition: all 550ms cubic-bezier(0.19, 1, 0.22, 1);
|
||||
width: 50px;
|
||||
z-index: -10;
|
||||
}
|
||||
}
|
||||
|
||||
.tertiary_Button:hover {
|
||||
background-color: #000000 !important;
|
||||
border-color: #fff !important;
|
||||
font-weight: 500;
|
||||
|
||||
&:after {
|
||||
left: 120%;
|
||||
transition: all 550ms cubic-bezier(0.19, 1, 0.22, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// .tertiary_Button{
|
||||
// width: 100px;
|
||||
// height:30px;
|
||||
// background-color: var(--THIRD_BUTTON_BG_COLOR) !important;
|
||||
// color:#fff;
|
||||
// font-family: var( --HEADING_FONT_FAMILY );
|
||||
// font-style: normal;
|
||||
// font-weight: 400;
|
||||
// font-size: 14;
|
||||
// line-height: 18px;
|
||||
// border-radius:8px;
|
||||
// display: flex;
|
||||
// letter-spacing: 0.5px;
|
||||
// justify-content:center;
|
||||
// align-items: center;
|
||||
// z-index:2;
|
||||
// left: 450px;
|
||||
// }
|
||||
|
||||
// .tertiary_Button {
|
||||
// border: 1px solid;
|
||||
// overflow: hidden;
|
||||
|
||||
// span {
|
||||
// z-index: 20;
|
||||
// }
|
||||
|
||||
// &:after {
|
||||
// content: "";
|
||||
// height: 155px;
|
||||
// left: -15px;
|
||||
// opacity: .2;
|
||||
// position: absolute;
|
||||
// top: -50px;
|
||||
// transform: rotate(35deg);
|
||||
// transition: all 550ms cubic-bezier(0.19, 1, 0.22, 1);
|
||||
// width: 50px;
|
||||
// z-index: -10;
|
||||
// }
|
||||
// }
|
||||
|
||||
// .tertiary_Button:hover {
|
||||
// &:after {
|
||||
// left: 120%;
|
||||
// transition: all 550ms cubic-bezier(0.19, 1, 0.22, 1);
|
||||
// }
|
||||
// }
|
||||
|
||||
Button:disabled,
|
||||
Button[disabled] {
|
||||
width: 170px;
|
||||
height: 45px;
|
||||
background-color: grey;
|
||||
color: #fff;
|
||||
font-family: var(--HEADING_FONT_FAMILY);
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
letter-spacing: 0.5px;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.primary_Button {
|
||||
background-color: var(--ERROR_COLOR);
|
||||
color: white;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.ant-btn-primary:disabled,
|
||||
.ant-btn-primary:disabled {
|
||||
width: 170px;
|
||||
height: 45px;
|
||||
background-color: grey !important;
|
||||
color: #fff;
|
||||
font-family: var(--HEADING_FONT_FAMILY);
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
letter-spacing: 0.5px;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.ant-btn-primary:disabled {
|
||||
height: 25px;
|
||||
background-color: white !important;
|
||||
color: #fff;
|
||||
font-family: var(--HEADING_FONT_FAMILY);
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-size: 10px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
letter-spacing: 0.5px;
|
||||
justify-content: center;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.ant-btn-primary:disabled {
|
||||
background-color: var(--ERROR_COLOR);
|
||||
color: #858585;
|
||||
}
|
||||
|
||||
.ant-picker-dropdown
|
||||
.ant-picker-cell-in-view.ant-picker-cell-today
|
||||
.ant-picker-cell-inner::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-end: 0;
|
||||
bottom: 0;
|
||||
inset-inline-start: 0;
|
||||
z-index: 1;
|
||||
border: 1px solid var(--PRIMARY_BUTTON_BG_COLOR);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.ant-picker-dropdown
|
||||
.ant-picker-cell-in-view.ant-picker-cell-selected
|
||||
.ant-picker-cell-inner,
|
||||
:where(.css-dev-only-do-not-override-1fviqcj).ant-picker-dropdown
|
||||
.ant-picker-cell-in-view.ant-picker-cell-range-start
|
||||
.ant-picker-cell-inner,
|
||||
:where(.css-dev-only-do-not-override-1fviqcj).ant-picker-dropdown
|
||||
.ant-picker-cell-in-view.ant-picker-cell-range-end
|
||||
.ant-picker-cell-inner {
|
||||
color: #fff;
|
||||
background: #901d77;
|
||||
}
|
||||
|
||||
.ant-picker-dropdown .ant-picker-today-btn {
|
||||
color: var(--DEFAULT_SELECTED_COLOR);
|
||||
}
|
||||
|
||||
.ant-checkbox .ant-checkbox-inner {
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
display: block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
direction: ltr;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #000;
|
||||
border-radius: 4px;
|
||||
border-collapse: separate;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.ant-checkbox-checked .ant-checkbox-inner {
|
||||
background-color: #000;
|
||||
border-color: #000;
|
||||
}
|
||||
|
||||
.ant-pagination .ant-pagination-item-active {
|
||||
font-weight: 600;
|
||||
background-color: #ffffff;
|
||||
border-color: #000000;
|
||||
}
|
||||
|
||||
.ant-pagination .ant-pagination-item-active a {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.ant-table-wrapper .ant-table-thead > tr > th,
|
||||
.ant-table-wrapper .ant-table-thead > tr > td {
|
||||
position: relative;
|
||||
font-weight: 600;
|
||||
text-align: start;
|
||||
font-size: 12px;
|
||||
color: rgb(118, 118, 118);
|
||||
background: #fafafa;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.ant-checkbox-wrapper:not(.ant-checkbox-wrapper-disabled):hover
|
||||
.ant-checkbox-checked:not(.ant-checkbox-disabled)
|
||||
.ant-checkbox-inner {
|
||||
background-color: #000000;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.ant-checkbox-wrapper:not(.ant-checkbox-wrapper-disabled):hover
|
||||
.ant-checkbox-inner,
|
||||
:where(.css-dev-only-do-not-override-1fviqcj).ant-checkbox:not(
|
||||
.ant-checkbox-disabled
|
||||
):hover
|
||||
.ant-checkbox-inner {
|
||||
border-color: #000000;
|
||||
}
|
||||
|
||||
.ant-switch.ant-switch-checked {
|
||||
background: var(--SELECTED_COLOR);
|
||||
}
|
||||
|
||||
.ant-switch.ant-switch-checked:hover:not(.ant-switch-disabled) {
|
||||
background: var(--SELECTED_COLOR);
|
||||
}
|
||||
|
||||
.ant-table-wrapper .ant-table-thead > tr > th,
|
||||
.ant-table-wrapper .ant-table-thead > tr > td {
|
||||
position: relative;
|
||||
color: rgba(64, 64, 64, 0.88);
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
text-align: start;
|
||||
background: none;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
font-family: var(--HEADING_FONT_FAMILY);
|
||||
transition: background 0.2s ease;
|
||||
transition-duration: 0.6s;
|
||||
}
|
||||
|
||||
.ant-table-wrapper .ant-table {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: rgb(14 14 14 / 88%);
|
||||
font-size: 14px;
|
||||
line-height: 1.5714285714285714;
|
||||
list-style: none;
|
||||
font-family: var(--HEADING_FONT_FAMILY);
|
||||
background: none;
|
||||
background-color: rgba(255, 255, 255, 0.036);
|
||||
border-radius: 5px;
|
||||
transition-duration: 0.6s;
|
||||
}
|
||||
|
||||
.ant-table-wrapper table {
|
||||
width: 100%;
|
||||
text-align: start;
|
||||
border-radius: 8px 8px 0 0;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
.ant-table-wrapper .ant-table:hover {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: rgb(14 14 14 / 88%);
|
||||
font-size: 14px;
|
||||
line-height: 1.5714285714;
|
||||
list-style: none;
|
||||
border-radius: 8px 8px 0 0;
|
||||
transition-duration: 0.6s;
|
||||
}
|
||||
|
||||
.ant-table-cell-row-hover {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
transition-duration: 0.6s;
|
||||
}
|
||||
|
||||
.ant-table-wrapper .ant-table-pagination-right {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.ant-pagination .ant-pagination-item {
|
||||
display: inline-block;
|
||||
min-width: 32px;
|
||||
height: 32px;
|
||||
margin-inline-end: 8px;
|
||||
font-family:
|
||||
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue',
|
||||
Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
|
||||
'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
list-style: none;
|
||||
background-color: white;
|
||||
border-radius: 6px;
|
||||
outline: 0;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.ant-menu .ant-menu-item .ant-menu-item-icon,
|
||||
.ant-menu .ant-menu-submenu-title .ant-menu-item-icon,
|
||||
:where(.css-dev-only-do-not-override-1fviqcj).ant-menu .ant-menu-item .anticon,
|
||||
:where(.css-dev-only-do-not-override-1fviqcj).ant-menu
|
||||
.ant-menu-submenu-title
|
||||
.anticon {
|
||||
min-width: 14px;
|
||||
font-size: 20px;
|
||||
position: relative;
|
||||
top: 13px;
|
||||
transition:
|
||||
font-size 0.2s cubic-bezier(0.215, 0.61, 0.355, 1),
|
||||
margin 0.3s cubic-bezier(0.645, 0.045, 0.355, 1),
|
||||
color 0.3s;
|
||||
}
|
||||
|
||||
:where(.css-2i2tap).ant-menu-vertical
|
||||
> .ant-menu-submenu
|
||||
> .ant-menu-submenu-title {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
:where(.css-zg0ahe).ant-menu-vertical
|
||||
> .ant-menu-submenu
|
||||
> .ant-menu-submenu-title {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ant-menu-light,
|
||||
.ant-menu-light > .ant-menu {
|
||||
color: rgba(0, 0, 0, 0.88);
|
||||
background: none;
|
||||
//dhana
|
||||
// padding: 1vw 0vh;
|
||||
//
|
||||
}
|
||||
|
||||
.ant-form-item .ant-form-item-explain-error {
|
||||
color: var(--ERROR_COLOR);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ant-table-cell {
|
||||
background: #fafafa7a;
|
||||
//vicky
|
||||
padding: 1px 8px !important;
|
||||
}
|
||||
|
||||
.ant-input-affix-wrapper > input.ant-input {
|
||||
font-size: inherit;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
outline: none;
|
||||
transition-duration: 0.6s;
|
||||
}
|
||||
|
||||
.ant-input-affix-wrapper:not(.ant-input-affix-wrapper-disabled):hover {
|
||||
border-color: #4096ff;
|
||||
border-inline-end-width: 1px;
|
||||
background-color: none;
|
||||
z-index: 0;
|
||||
transition-duration: 0.6s;
|
||||
}
|
||||
|
||||
.ant-input-affix-wrapper {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
color: rgba(0, 0, 0, 0.88);
|
||||
height: 50px;
|
||||
line-height: 1.5714285714285714;
|
||||
background-color: #ffffff;
|
||||
background-image: none;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #acacac;
|
||||
border-radius: 6px;
|
||||
font-size: 16px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.ant-input-affix-wrapper > input.ant-input {
|
||||
font-size: inherit;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.ant-input-affix-wrapper > input.ant-input {
|
||||
font-size: inherit;
|
||||
border: none;
|
||||
padding: 23px 2px;
|
||||
padding-top: 1rem;
|
||||
border-radius: 0;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.ant-upload-drag-icon {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.ant-upload-text {
|
||||
font-family: var(--HEADING_FONT_FAMILY);
|
||||
}
|
||||
|
||||
.ant-upload-hint {
|
||||
font-family: var(--PARA_FONT_FAMILY);
|
||||
}
|
||||
|
||||
.ant-upload-wrapper .ant-upload-drag p.ant-upload-drag-icon .anticon {
|
||||
color: #6a6a6a;
|
||||
font-size: 48px;
|
||||
}
|
||||
|
||||
.ant-table table {
|
||||
border-spacing: 0 10px;
|
||||
transition-duration: 0.6s;
|
||||
}
|
||||
|
||||
.ant-table-wrapper .ant-table-tbody > tr.ant-table-row > td,
|
||||
.ant-table-wrapper
|
||||
.ant-table-tbody
|
||||
> tr
|
||||
> th.ant-table-cell-row
|
||||
> td.ant-table-cell-row {
|
||||
background: #ffffff8e;
|
||||
box-shadow: rgba(100, 100, 111, 0.018) 0px 7px 29px 0px;
|
||||
}
|
||||
|
||||
.ant-table-wrapper .ant-table-tbody > tr.ant-table-row:hover > td,
|
||||
.ant-table-wrapper
|
||||
.ant-table-tbody
|
||||
> tr
|
||||
> th.ant-table-cell-row-hover
|
||||
> td.ant-table-cell-row-hover {
|
||||
background: rgb(224, 223, 223);
|
||||
font-size: 15px;
|
||||
transition-duration: 0.6s;
|
||||
// transform: translateY(-8px);
|
||||
}
|
||||
|
||||
.ant-modal .ant-modal-content {
|
||||
position: relative;
|
||||
background-color: #ffffff;
|
||||
background-clip: padding-box;
|
||||
border: 0;
|
||||
font-family: var(--HEADING_FONT_FAMILY);
|
||||
border-radius: 8px;
|
||||
box-shadow:
|
||||
0 6px 16px 0 rgba(0, 0, 0, 0.08),
|
||||
0 3px 6px -4px rgba(0, 0, 0, 0.12),
|
||||
0 9px 28px 8px rgba(0, 0, 0, 0.05);
|
||||
pointer-events: auto;
|
||||
padding: 24px 24px;
|
||||
color: #000;
|
||||
max-height: 98vh;
|
||||
overflow: auto;
|
||||
}
|
||||
.ant-modal-title {
|
||||
font-size: 24px !important;
|
||||
text-wrap: wrap;
|
||||
font-family: 'Gilroy', sans-serif;
|
||||
}
|
||||
|
||||
.ant-modal-footer {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.ant-modal-root .ant-modal-mask {
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.ant-pagination .ant-pagination-next {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
outline: 1;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.ant-pagination .ant-pagination-prev,
|
||||
.ant-pagination .ant-pagination-next {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.ant-pagination .ant-pagination-item {
|
||||
min-width: 32px;
|
||||
height: 32px;
|
||||
margin-inline-end: 8px;
|
||||
font-family:
|
||||
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue',
|
||||
Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
|
||||
'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
list-style: none;
|
||||
background-color: white;
|
||||
border-radius: 6px;
|
||||
outline: 0;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.ant-pagination
|
||||
.ant-pagination-jump-next
|
||||
.ant-pagination-item-container
|
||||
.ant-pagination-item-ellipsis {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-end: 0;
|
||||
bottom: 0;
|
||||
inset-inline-start: 0;
|
||||
margin: auto;
|
||||
color: rgba(0, 0, 0, 0.25);
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
letter-spacing: 2px;
|
||||
text-align: center;
|
||||
text-indent: 0.13em;
|
||||
opacity: 1;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.ant-pagination
|
||||
.ant-pagination-jump-next
|
||||
.ant-pagination-item-container
|
||||
.ant-pagination-item-link-icon {
|
||||
color: var(--ERROR_COLOR);
|
||||
font-size: 12px;
|
||||
opacity: 0;
|
||||
transition: all 0.2s;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ant-select-single.ant-select-show-arrow .ant-select-selection-item,
|
||||
.ant-select-single.ant-select-show-arrow .ant-select-selection-placeholder {
|
||||
padding-inline-end: 18px;
|
||||
text-align: initial;
|
||||
}
|
||||
|
||||
.ant-select-single.ant-select-show-arrow .ant-select-selection-item,
|
||||
.ant-select-single.ant-select-show-arrow .ant-select-selection-placeholder {
|
||||
padding-inline-end: 59px;
|
||||
text-align: initial;
|
||||
font-size: 14px;
|
||||
color: #626262;
|
||||
font-weight: 400;
|
||||
font-family: 'Poppins', sans-serif;
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
.ant-select .ant-select-arrow {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: rgba(0, 0, 0, 0.517);
|
||||
font-style: normal;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
text-transform: none;
|
||||
vertical-align: -0.125em;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
inset-inline-start: auto;
|
||||
inset-inline-end: 11px;
|
||||
height: 110p;
|
||||
margin-top: -6px;
|
||||
font-size: 16px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.ant-select:not(.ant-select-customize-input)
|
||||
.ant-select-selector
|
||||
.ant-select-selection-search-input {
|
||||
padding: 0;
|
||||
border: none;
|
||||
height: 20px;
|
||||
font-size: 16px;
|
||||
position: relative;
|
||||
bottom: 0.5rem;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.ant-table-wrapper .ant-table-column-sorter {
|
||||
margin-inline-start: 4px;
|
||||
color: rgba(0, 0, 0, 0.29);
|
||||
font-size: 0;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.ant-input:disabled {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.ant-form-item-row
|
||||
.ant-form-item-control
|
||||
.ant-form-item-control-input
|
||||
.ant-form-item-control-input-content
|
||||
.ant-input-textarea-affix-wrapper {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.ant-input-search-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ant-input-search {
|
||||
width: var(--INPUT_FIELD_WIDTH) !important;
|
||||
}
|
||||
|
||||
.searchDiv .ant-input {
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: 0.25rem !important;
|
||||
width: 100%;
|
||||
height: 45px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.radio-buttons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.download-link {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #1292ee;
|
||||
cursor: pointer;
|
||||
|
||||
button {
|
||||
border: none;
|
||||
background-color: #dadadaff;
|
||||
padding: 10px 16px;
|
||||
width: max-content;
|
||||
cursor: pointer;
|
||||
gap: 4px;
|
||||
align-items: flex-start;
|
||||
display: flex;
|
||||
border-radius: 8px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
span {
|
||||
font-family: 'Poppins';
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
.configMsrMainDiv {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
column-gap: 1rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.configMsrSubDiv {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 1rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.configMsrSubDiv .ant-form-item .ant-form-item-explain-error {
|
||||
position: relative;
|
||||
left: 1rem;
|
||||
top: 1rem;
|
||||
}
|
||||
|
||||
.shape-crop {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.shape-crop-subdiv {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
gap: 2.5rem;
|
||||
}
|
||||
|
||||
.shape-crop-div {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.shape-reset {
|
||||
font-size: 25px;
|
||||
color: var(--SELECTED_COLOR);
|
||||
}
|
||||
|
||||
.shape-preview {
|
||||
font-size: 25px;
|
||||
color: var(--DEFAULT_SELECTED_COLOR);
|
||||
}
|
||||
|
||||
.shape-delete {
|
||||
font-size: 25px;
|
||||
color: var(--ERROR_COLOR);
|
||||
}
|
||||
|
||||
.crop-icon {
|
||||
font-size: 20px;
|
||||
// color: var(--DEFAULT_SELECTED_COLOR);
|
||||
}
|
||||
|
||||
.crop-button {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 0.5rem;
|
||||
width: 110px;
|
||||
background-color: var(--DEFAULT_SELECTED_COLOR);
|
||||
font-size: 14px;
|
||||
color: white;
|
||||
border-radius: 5px;
|
||||
padding: 6px 2px 1px 10px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.viewerExcelupload {
|
||||
.ant-table-wrapper .ant-table-pagination.ant-pagination {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
z-index: 10;
|
||||
background: white;
|
||||
padding-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.formSearch {
|
||||
.ant-input-affix-wrapper {
|
||||
height: 42px !important;
|
||||
}
|
||||
|
||||
.searchDiv .ant-input {
|
||||
height: unset !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// writed by sree lowStock animated
|
||||
|
||||
.stock-alert-animation {
|
||||
// position: relative;
|
||||
animation: blink 1s infinite;
|
||||
cursor: pointer;
|
||||
}
|
||||
@keyframes blink {
|
||||
0% { opacity: 1; }
|
||||
50% { opacity: 0; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import { TertiaryButton as TertiaryButtonLibrary } from "../../../ownLib/my-ui-lib"
|
||||
const TertiaryButton = TertiaryButtonLibrary
|
||||
|
||||
export default TertiaryButton;
|
||||
|
||||
// import { Button } from 'antd';
|
||||
// import './main.scss';
|
||||
|
||||
// const TertiaryButton = ({
|
||||
// buttonText,
|
||||
// handleSubmit,
|
||||
// icon,
|
||||
// htmlType,
|
||||
// disabled,
|
||||
// }) => (
|
||||
// <Button
|
||||
// type="primary"
|
||||
// className="tertiary_Button"
|
||||
// onClick={handleSubmit}
|
||||
// htmlType={htmlType ? 'submit' : ''}
|
||||
// disabled={disabled ? disabled : false}
|
||||
// >
|
||||
// {buttonText}
|
||||
// {icon}
|
||||
// </Button>
|
||||
// );
|
||||
|
||||
// export default TertiaryButton;
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
// import React from 'react';
|
||||
// import './Loader.scss';
|
||||
// import {Loader as LoaderLibrary} from "../../../ownLib/my-ui-lib"
|
||||
// const Loader = LoaderLibrary
|
||||
|
||||
// export default Loader;
|
||||
|
||||
// import React from 'react';
|
||||
// import './Loader.scss';
|
||||
|
||||
// const Loader = () => {
|
||||
// const text = 'POZO';
|
||||
// return (
|
||||
// <div className="modern-loader-wrapper">
|
||||
// <div className="modern-balls-loader">
|
||||
// {text.split('').map((char, i) => (
|
||||
// <span className="modern-ball" key={i} style={{ animationDelay: `${i * 0.18}s` }}>{char}</span>
|
||||
// ))}
|
||||
// </div>
|
||||
// <div className="modern-progress-bar">
|
||||
// <div className="modern-progress-fill"></div>
|
||||
// </div>
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
|
||||
// export default Loader;
|
||||
|
||||
import React from 'react';
|
||||
import './Loader.scss';
|
||||
|
||||
const Loader = () => {
|
||||
return (
|
||||
<div className="LoaderMainPozo">
|
||||
<div className="card11">
|
||||
<div className="loader11">
|
||||
<p>Loading</p>
|
||||
<div className="words">
|
||||
<span className="word">PozoApp</span>
|
||||
<span className="word">BillingApp</span>
|
||||
<span className="word">PozoApp</span>
|
||||
<span className="word">BillingApp</span>
|
||||
<span className="word">PozoApp</span>
|
||||
</div>
|
||||
<p></p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="progress-container11">
|
||||
<div className="progress-bar11">
|
||||
<div className="progress-fill11"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Loader;
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
.LoaderMainPozo {
|
||||
display: flex;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
.card11 {
|
||||
background-color: var(--bg-color);
|
||||
border-radius: 1.25rem;
|
||||
}
|
||||
.loader11 {
|
||||
color: rgb(66, 66, 66);
|
||||
font-family: "Gilroy", sans-serif;
|
||||
font-weight: 400;
|
||||
font-size: 25px;
|
||||
-webkit-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
height: 40px;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
border-radius: 8px;
|
||||
letter-spacing: -0.5px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.words {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
letter-spacing: -0.3px;
|
||||
}
|
||||
.words::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(var(--bg-color) 10%, transparent 30%, transparent 70%, var(--bg-color) 90%);
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.word {
|
||||
display: block;
|
||||
height: 100%;
|
||||
padding-left: 6px;
|
||||
color: #52c41a;
|
||||
animation: spin_4991 4s infinite;
|
||||
}
|
||||
|
||||
@keyframes spin_4991 {
|
||||
10% {
|
||||
-webkit-transform: translateY(-102%);
|
||||
transform: translateY(-102%);
|
||||
}
|
||||
|
||||
25% {
|
||||
-webkit-transform: translateY(-100%);
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
||||
50% {
|
||||
-webkit-transform: translateY(-200%);
|
||||
transform: translateY(-200%);
|
||||
}
|
||||
|
||||
75% {
|
||||
-webkit-transform: translateY(-300%);
|
||||
transform: translateY(-300%);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: translateY(-400%);
|
||||
transform: translateY(-400%);
|
||||
}
|
||||
}
|
||||
.progress-container11 {
|
||||
width: 200px;
|
||||
margin: 4px auto;
|
||||
}
|
||||
|
||||
.progress-bar11 {
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
background: rgb(136 131 131 / 20%);
|
||||
border-radius: 3px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress-fill11 {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #52c41a, #52c41a);
|
||||
border-radius: 3px;
|
||||
animation: progress 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes progress {
|
||||
0% {
|
||||
width: 0%;
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
50% {
|
||||
width: 100%;
|
||||
transform: translateX(0%);
|
||||
}
|
||||
100% {
|
||||
width: 100%;
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
import * as React from 'react';
|
||||
import './style.css';
|
||||
import loadgif from '../../Images/spin3.gif';
|
||||
|
||||
const styles = {
|
||||
text: {
|
||||
marginTop: 52,
|
||||
color: '#888',
|
||||
marginLeft: 6,
|
||||
},
|
||||
spinner: {
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.5)',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
top: 0,
|
||||
left: 0,
|
||||
zIndex: 99999999999999999,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
};
|
||||
|
||||
export const Loader = ({
|
||||
loading,
|
||||
text = 'Loading..',
|
||||
fullPage,
|
||||
containerStyle,
|
||||
textStyle,
|
||||
}) => {
|
||||
if (!loading) {
|
||||
return null;
|
||||
}
|
||||
const mergedContainerStyle = {
|
||||
...styles.spinner,
|
||||
...containerStyle,
|
||||
position: fullPage ? 'fixed' : 'absolute',
|
||||
};
|
||||
return (
|
||||
<div style={mergedContainerStyle}>
|
||||
<div>
|
||||
<img src={loadgif} className="loadgif" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
@keyframes react-overlay-loader-spinner {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.react-overlay-loader-spinner:before {
|
||||
content: '';
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-top: -30px;
|
||||
margin-left: -20px;
|
||||
border-radius: 50%;
|
||||
border: 3px solid #eee;
|
||||
border-top-color: #07d;
|
||||
animation: react-overlay-loader-spinner 0.8s linear infinite;
|
||||
}
|
||||
|
||||
.loadgif {
|
||||
width: 570px;
|
||||
height: 320px;
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Map, Marker, GoogleApiWrapper } from 'google-maps-react';
|
||||
|
||||
class MapView extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
fields: props.prevlca ? { location: props.prevlca } : { location: {} },
|
||||
currentLocation: props.prevlca ? props.prevlca : false,
|
||||
};
|
||||
}
|
||||
async componentDidMount() {
|
||||
if (Object.keys(this.state.fields.location)?.length === 0) {
|
||||
const { lat, lng } = await this.getcurrentLocation();
|
||||
this.setState((prev) => ({
|
||||
fields: {
|
||||
...prev.fields,
|
||||
location: {
|
||||
lat,
|
||||
lng,
|
||||
},
|
||||
},
|
||||
currentLocation: {
|
||||
lat,
|
||||
lng,
|
||||
},
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
getcurrentLocation() {
|
||||
if (navigator && navigator.geolocation) {
|
||||
return new Promise((resolve, reject) => {
|
||||
navigator.geolocation.getCurrentPosition((pos) => {
|
||||
const coords = pos.coords;
|
||||
resolve({
|
||||
lat: coords.latitude,
|
||||
lng: coords.longitude,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
return {
|
||||
lat: 0.0,
|
||||
lng: 0,
|
||||
};
|
||||
}
|
||||
addMarker = (location, map) => {
|
||||
this.setState({
|
||||
fields: { location: { lat: location.lat(), lng: location.lng() } },
|
||||
});
|
||||
map.panTo(location);
|
||||
this.props.onMarkerClick(location);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { lat = 0, lng = 0 } = this.state.fields.location;
|
||||
// var bounds = new this.props.google.maps.LatLngBounds();
|
||||
return (
|
||||
<div>
|
||||
<Map
|
||||
google={this.props.google}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
}}
|
||||
initialCenter={{ lat: lat || 0, lng: lng || 0 }}
|
||||
center={{ lat: lat || 0, lng: lng || 0 }}
|
||||
zoom={14}
|
||||
mapTypeId="roadmap"
|
||||
onClick={(t, map, c) => {
|
||||
this.addMarker(c.latLng, map);
|
||||
}}
|
||||
// bounds={bounds}
|
||||
>
|
||||
<Marker
|
||||
tooltip={true}
|
||||
name="Your Position"
|
||||
position={this.state.fields.location}
|
||||
onClick={this.props.onMarkerClick}
|
||||
/>
|
||||
</Map>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default GoogleApiWrapper({
|
||||
apiKey: 'AIzaSyB6w_WDy6psJ5HPX15Me1-o6CkS5jTYWnE',
|
||||
})(MapView);
|
||||
|
|
@ -0,0 +1,432 @@
|
|||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import { AppstoreOutlined, MailOutlined, SettingOutlined, } from '@ant-design/icons';
|
||||
import { FaCaretRight } from "react-icons/fa";
|
||||
|
||||
import './PozoMenu.scss';
|
||||
|
||||
const PozoMenu = ({ items = [], mode = "vertical", style = {}, onClick, collapse = false, selectedKey: propSelectedKey, isBottomMenu = false }) => {
|
||||
const [openKeys, setOpenKeys] = useState([]);
|
||||
const [selectedKey, setSelectedKey] = useState('');
|
||||
const [dropdownPositions, setDropdownPositions] = useState({});
|
||||
console.log(dropdownPositions, "dropdownPositions")
|
||||
const [isMobile, setIsMobile] = useState(window.innerWidth <= 768);
|
||||
const menuRef = useRef();
|
||||
|
||||
// Update selected key when prop changes
|
||||
useEffect(() => {
|
||||
if (propSelectedKey !== undefined) {
|
||||
setSelectedKey(propSelectedKey);
|
||||
}
|
||||
}, [propSelectedKey]);
|
||||
|
||||
// Close dropdown when clicking outside, window resize, or scroll
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event) => {
|
||||
if (menuRef.current && !menuRef.current.contains(event.target)) {
|
||||
setOpenKeys([]);
|
||||
setDropdownPositions({});
|
||||
}
|
||||
};
|
||||
|
||||
const handleResize = () => {
|
||||
// Update mobile detection
|
||||
setIsMobile(window.innerWidth <= 768);
|
||||
|
||||
// Recalculate positions on window resize
|
||||
if (openKeys.length > 0) {
|
||||
setOpenKeys([]);
|
||||
setDropdownPositions({});
|
||||
}
|
||||
};
|
||||
|
||||
const handleScroll = () => {
|
||||
// 🎯 FIXED: Recalculate positions on scroll to maintain proper positioning
|
||||
if (openKeys.length > 0) {
|
||||
// Find all currently open menu elements and recalculate their positions
|
||||
const newPositions = {};
|
||||
openKeys.forEach(key => {
|
||||
const element = document.querySelector(`[data-menu-key="${key}"]`);
|
||||
if (element) {
|
||||
const level = key.split('-').length - 1;
|
||||
newPositions[key] = calculatePosition(element, level);
|
||||
}
|
||||
});
|
||||
setDropdownPositions(prev => ({ ...prev, ...newPositions }));
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
window.addEventListener('resize', handleResize);
|
||||
window.addEventListener('scroll', handleScroll, true); // Capture scroll events
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
window.removeEventListener('resize', handleResize);
|
||||
window.removeEventListener('scroll', handleScroll, true);
|
||||
};
|
||||
}, [openKeys]);
|
||||
|
||||
// 🎯 FIXED: Smart positioning calculation - exactly like your image behavior
|
||||
const calculatePosition = (element, level = 0) => {
|
||||
const rect = element.getBoundingClientRect();
|
||||
const viewportWidth = window.innerWidth;
|
||||
const viewportHeight = window.innerHeight;
|
||||
const scrollX = window.pageXOffset || document.documentElement.scrollLeft;
|
||||
const scrollY = window.pageYOffset || document.documentElement.scrollTop;
|
||||
|
||||
// Dynamic dropdown dimensions - responsive
|
||||
const dropdownWidth = isMobile
|
||||
? Math.min(280, viewportWidth - 20)
|
||||
: (level > 0 ? 220 : 250);
|
||||
const dropdownHeight = Math.min(
|
||||
isMobile ? viewportHeight * 0.5 : 400,
|
||||
viewportHeight * 0.6
|
||||
);
|
||||
const gap = isMobile ? 2 : 4;
|
||||
const edgePadding = isMobile ? 10 : 8;
|
||||
|
||||
// Calculate available space on both sides
|
||||
const spaceRight = viewportWidth - rect.right;
|
||||
const spaceLeft = rect.left;
|
||||
const spaceNeeded = dropdownWidth + gap + edgePadding;
|
||||
|
||||
let position = {
|
||||
top: rect.top + scrollY,
|
||||
left: rect.right + gap + scrollX,
|
||||
direction: 'right',
|
||||
verticalDirection: 'down'
|
||||
};
|
||||
|
||||
// 🎯 FIXED: HORIZONTAL POSITIONING - Exactly like your images
|
||||
if (level === 0) {
|
||||
console.log('🎯 Space Analysis:', {
|
||||
spaceRight,
|
||||
spaceLeft,
|
||||
spaceNeeded,
|
||||
elementPosition: { left: rect.left, right: rect.right }
|
||||
});
|
||||
|
||||
if (spaceRight >= spaceNeeded) {
|
||||
// Image 1: Enough space on right - open to RIGHT
|
||||
position.left = rect.right + gap + scrollX;
|
||||
position.direction = 'right';
|
||||
console.log('✅ Opening RIGHT - space available');
|
||||
} else if (spaceLeft >= spaceNeeded) {
|
||||
// Image 2: No space on right, space on left - open to LEFT
|
||||
position.left = rect.left - dropdownWidth - gap + scrollX;
|
||||
position.direction = 'left';
|
||||
console.log('✅ Opening LEFT - no space on right');
|
||||
} else {
|
||||
// Edge case: Limited space on both sides
|
||||
if (spaceRight >= spaceLeft) {
|
||||
position.left = viewportWidth - dropdownWidth - edgePadding + scrollX;
|
||||
position.direction = 'right-edge';
|
||||
} else {
|
||||
position.left = edgePadding + scrollX;
|
||||
position.direction = 'left-edge';
|
||||
}
|
||||
console.log('⚠️ Edge positioning applied');
|
||||
}
|
||||
} else {
|
||||
// Nested menu positioning
|
||||
const parentKeys = Object.keys(dropdownPositions);
|
||||
const parentDirection = parentKeys.length > 0
|
||||
? dropdownPositions[parentKeys[level - 1]]?.direction || 'right'
|
||||
: 'right';
|
||||
|
||||
if (parentDirection.includes('right')) {
|
||||
if (spaceRight >= spaceNeeded) {
|
||||
position.left = rect.right + gap + scrollX;
|
||||
position.direction = 'right';
|
||||
} else {
|
||||
position.left = rect.left - dropdownWidth - gap + scrollX;
|
||||
position.direction = 'left';
|
||||
}
|
||||
} else {
|
||||
if (spaceLeft >= spaceNeeded) {
|
||||
position.left = rect.left - dropdownWidth - gap + scrollX;
|
||||
position.direction = 'left';
|
||||
} else {
|
||||
position.left = rect.right + gap + scrollX;
|
||||
position.direction = 'right';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 🎯 FIXED: VERTICAL POSITIONING
|
||||
const spaceBelow = viewportHeight - rect.bottom;
|
||||
const spaceAbove = rect.top;
|
||||
|
||||
if (isBottomMenu && level === 0) {
|
||||
if (spaceAbove >= dropdownHeight + edgePadding) {
|
||||
position.top = rect.top - dropdownHeight - gap + scrollY;
|
||||
position.verticalDirection = 'up';
|
||||
} else {
|
||||
position.top = rect.bottom + gap + scrollY;
|
||||
position.verticalDirection = 'down';
|
||||
}
|
||||
} else {
|
||||
if (spaceBelow >= dropdownHeight + edgePadding) {
|
||||
position.top = rect.top + scrollY;
|
||||
position.verticalDirection = 'down';
|
||||
} else if (spaceAbove >= dropdownHeight + edgePadding) {
|
||||
position.top = rect.bottom - dropdownHeight + scrollY;
|
||||
position.verticalDirection = 'up';
|
||||
} else {
|
||||
position.top = Math.max(edgePadding, (viewportHeight - dropdownHeight) / 2) + scrollY;
|
||||
position.verticalDirection = 'center';
|
||||
}
|
||||
}
|
||||
|
||||
// 🎯 FIXED: Final boundary checks
|
||||
position.left = Math.max(
|
||||
edgePadding + scrollX,
|
||||
Math.min(position.left, viewportWidth - dropdownWidth - edgePadding + scrollX)
|
||||
);
|
||||
|
||||
position.top = Math.max(
|
||||
edgePadding + scrollY,
|
||||
Math.min(position.top, viewportHeight - dropdownHeight - edgePadding + scrollY)
|
||||
);
|
||||
|
||||
// Store dimensions for reference
|
||||
position.width = dropdownWidth;
|
||||
position.height = dropdownHeight;
|
||||
|
||||
console.log('🎯 FIXED Position:', {
|
||||
clicked: { top: rect.top, left: rect.left, right: rect.right, bottom: rect.bottom },
|
||||
spaces: { right: spaceRight, left: spaceLeft, above: spaceAbove, below: spaceBelow },
|
||||
calculated: position,
|
||||
direction: position.direction
|
||||
});
|
||||
|
||||
return position;
|
||||
};
|
||||
|
||||
// Handle menu item click
|
||||
const handleMenuClick = (item, event, parentKeys = []) => {
|
||||
event.stopPropagation();
|
||||
|
||||
if (item.children && item.children.length > 0) {
|
||||
// Has children - toggle submenu
|
||||
const itemKey = item.key;
|
||||
const isOpen = openKeys.includes(itemKey);
|
||||
|
||||
if (isOpen) {
|
||||
// Close this submenu and all its children
|
||||
setOpenKeys(prev => prev.filter(key => {
|
||||
// Keep only keys that are not this item or its descendants
|
||||
return !key.startsWith(itemKey) && key !== itemKey;
|
||||
}));
|
||||
setDropdownPositions(prev => {
|
||||
const newPos = { ...prev };
|
||||
Object.keys(newPos).forEach(key => {
|
||||
if (key.startsWith(itemKey) || key === itemKey) {
|
||||
delete newPos[key];
|
||||
}
|
||||
});
|
||||
return newPos;
|
||||
});
|
||||
} else {
|
||||
// Close all submenus at the same level or deeper
|
||||
const currentPath = [...parentKeys, itemKey];
|
||||
const newOpenKeys = openKeys.filter(key => {
|
||||
// Keep only parent keys in the current path
|
||||
return currentPath.some(pathKey => key === pathKey) ||
|
||||
currentPath.every((pathKey, index) => {
|
||||
const keyParts = key.split('-');
|
||||
const pathParts = pathKey.split('-');
|
||||
return index < keyParts.length && keyParts[index] === pathParts[index];
|
||||
});
|
||||
});
|
||||
|
||||
// Add current item to open keys
|
||||
newOpenKeys.push(itemKey);
|
||||
|
||||
// Calculate position and add to dropdown positions
|
||||
const position = calculatePosition(event.currentTarget, parentKeys.length);
|
||||
console.log('🎯 Setting position for', itemKey, ':', position);
|
||||
|
||||
setDropdownPositions(prev => {
|
||||
// Remove positions for closed items
|
||||
const newPos = {};
|
||||
newOpenKeys.forEach(key => {
|
||||
if (prev[key]) newPos[key] = prev[key];
|
||||
});
|
||||
newPos[itemKey] = position;
|
||||
console.log('🎯 Updated dropdown positions:', newPos);
|
||||
return newPos;
|
||||
});
|
||||
|
||||
setOpenKeys(newOpenKeys);
|
||||
}
|
||||
} else {
|
||||
// No children - select item and close all dropdowns
|
||||
setSelectedKey(item.key);
|
||||
setOpenKeys([]);
|
||||
setDropdownPositions({});
|
||||
|
||||
// Trigger onClick callback if provided
|
||||
if (onClick) {
|
||||
onClick({
|
||||
key: item.key,
|
||||
keyPath: [...parentKeys, item.key],
|
||||
item: item,
|
||||
domEvent: event
|
||||
});
|
||||
}
|
||||
|
||||
console.log('Menu item clicked:', {
|
||||
key: item.key,
|
||||
keyPath: [...parentKeys, item.key],
|
||||
label: item.label
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Check if item is selected
|
||||
const isSelected = (key) => selectedKey === key;
|
||||
|
||||
// Check if item is open
|
||||
const isOpen = (key) => openKeys.includes(key);
|
||||
|
||||
// Check if item is in active path (has selected child)
|
||||
const isInActivePath = (item, parentKeys = []) => {
|
||||
if (!item.children) return false;
|
||||
|
||||
const checkChildren = (children, currentPath) => {
|
||||
return children.some(child => {
|
||||
const childPath = [...currentPath, child.key];
|
||||
if (child.key === selectedKey) return true;
|
||||
if (child.children) {
|
||||
return checkChildren(child.children, childPath);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
return checkChildren(item.children, [...parentKeys, item.key]);
|
||||
};
|
||||
|
||||
const menuRefs = useRef({});
|
||||
const submenuRefs = useRef({});
|
||||
const [positions, setPositions] = useState({});
|
||||
|
||||
const renderMenuItems = (items, parentKeys = [], level = 0) => {
|
||||
return items.map((item) => {
|
||||
if (!item) return null;
|
||||
|
||||
const hasChildren = item.children && item.children.length > 0;
|
||||
const isItemSelected = isSelected(item.key);
|
||||
const isItemOpen = isOpen(item.key);
|
||||
const isItemInActivePath = isInActivePath(item, parentKeys);
|
||||
const currentKeys = [...parentKeys, item.key];
|
||||
|
||||
return (
|
||||
<div
|
||||
key={item.key}
|
||||
className="pozo-menu-item-wrapper"
|
||||
ref={(el) => {
|
||||
if (el) menuRefs.current[item.key] = el;
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={`pozo-menu-item ${isItemSelected ? 'selected' : ''} ${isItemOpen ? 'open' : ''} ${isItemInActivePath ? 'active-path' : ''} ${hasChildren ? 'has-children' : ''} ${item.type === 'group' ? 'group-item' : ''}`}
|
||||
onClick={(e) => handleMenuClick(item, e, parentKeys)}
|
||||
data-menu-key={item.key}
|
||||
style={{ justifyContent: "flex-start" }}
|
||||
>
|
||||
{item.icon && (
|
||||
<span className="pozo-menu-icon" style={{ fontSize: collapse ? "1.3rem" : "" }}>
|
||||
{item.icon}
|
||||
</span>
|
||||
)}
|
||||
|
||||
{!collapse && <span className="pozo-menu-label">{item.label}</span>}
|
||||
|
||||
{hasChildren && !collapse && (
|
||||
// <span className="pozo-menu-arrow"><FaCaretRight /></span>
|
||||
<span className={`${isItemOpen ? "open " : ""}pozo-menu-arrow`}>
|
||||
<FaCaretRight />
|
||||
</span>
|
||||
|
||||
)}
|
||||
</div>
|
||||
|
||||
{hasChildren && isItemOpen && !collapse && (
|
||||
<div
|
||||
ref={(el) => {
|
||||
if (el) submenuRefs.current[item.key] = el;
|
||||
}}
|
||||
className={`pozo-dropdown-submenu ${level > 0 ? 'nested-submenu' : ''}`}
|
||||
style={{
|
||||
position: 'fixed',
|
||||
top: (() => {
|
||||
const defaultTop = positions[item.key]?.top || 0;
|
||||
const submenuHeight =
|
||||
submenuRefs.current[item.key]?.getBoundingClientRect()?.height || 0;
|
||||
const screenHeight = window.innerHeight;
|
||||
|
||||
// ✅ If submenu would overflow screen bottom, adjust top
|
||||
if (defaultTop + submenuHeight > screenHeight) {
|
||||
return Math.max(
|
||||
8, // padding from top
|
||||
screenHeight - submenuHeight - 8
|
||||
);
|
||||
}
|
||||
return defaultTop;
|
||||
})(),
|
||||
left: positions[item.key]?.left + 5 || 0,
|
||||
// width: 220,
|
||||
width: 200,
|
||||
maxHeight: 400,
|
||||
zIndex: 1000 + level
|
||||
}}
|
||||
>
|
||||
<div className="pozo-submenu-content">
|
||||
{renderMenuItems(item.children, currentKeys, level + 1)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
// ✅ Compute positions after render
|
||||
useEffect(() => {
|
||||
const updated = {};
|
||||
for (const [key, el] of Object.entries(menuRefs.current)) {
|
||||
if (el && typeof el.getBoundingClientRect === "function") {
|
||||
const rect = el.getBoundingClientRect();
|
||||
updated[key] = {
|
||||
top: rect.top + window.scrollY,
|
||||
left: rect.right + window.scrollX
|
||||
};
|
||||
}
|
||||
}
|
||||
Object.entries(submenuRefs.current).forEach(([key, el]) => {
|
||||
if (el) {
|
||||
const height = el.getBoundingClientRect().height;
|
||||
console.log(`Total submenu height for ${key}:`, height);
|
||||
}
|
||||
});
|
||||
setPositions(updated);
|
||||
}, [items, openKeys]);
|
||||
|
||||
|
||||
console.log(submenuRefs, "menuRef")
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`pozo-menu pozo-menu-${mode}`}
|
||||
style={style}
|
||||
>
|
||||
<div className="pozo-menu-content" ref={menuRef}>
|
||||
{renderMenuItems(items)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PozoMenu;
|
||||
|
|
@ -0,0 +1,452 @@
|
|||
// PozoMenu Component Styles - Integrated with SideMenuPozo
|
||||
.pozo-menu {
|
||||
font-family: "Poppins", sans-serif !important;
|
||||
background: transparent;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
// overflow: hidden;
|
||||
overflow: auto;
|
||||
user-select: none;
|
||||
|
||||
@media (max-width: 500px) {
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
&.pozo-menu-vertical {
|
||||
width: 100% !important;
|
||||
min-height: auto;
|
||||
}
|
||||
|
||||
&.pozo-menu-horizontal {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
|
||||
.pozo-menu-content {
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.1rem;
|
||||
}
|
||||
|
||||
.pozo-menu-item-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.pozo-menu-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 8px 8px;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
background 0.2s,
|
||||
color 0.2s;
|
||||
border-radius: 8px;
|
||||
margin: 1px 3px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
position: relative;
|
||||
min-height: 38px;
|
||||
font-family: "Poppins", sans-serif !important;
|
||||
|
||||
&:hover:not(.selected):not(.active-path) {
|
||||
background: #394588;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background: #050d36 !important;
|
||||
color: #ffffff !important;
|
||||
border-right: 3px solid #ffffff;
|
||||
font-weight: 600;
|
||||
border-radius: 6px;
|
||||
border: none !important;
|
||||
|
||||
.pozo-menu-icon {
|
||||
color: #23bbff !important;
|
||||
}
|
||||
|
||||
.pozo-menu-label {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.pozo-menu-arrow {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.open {
|
||||
background: #050d36 !important;
|
||||
color: #23bbff;
|
||||
font-weight: 600;
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
&.active-path {
|
||||
background: #050d36 !important;
|
||||
color: #ffffff !important;
|
||||
font-weight: 600;
|
||||
border-radius: 6px 4px 4px 6px;
|
||||
border-right: 2px solid #23bbff !important;
|
||||
|
||||
.pozo-menu-icon {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.pozo-menu-label {
|
||||
color: #ffffff !important;
|
||||
font-weight: 500 !important;
|
||||
}
|
||||
|
||||
.pozo-menu-arrow {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.has-children {
|
||||
&:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.group-item {
|
||||
font-weight: 600;
|
||||
color: #666;
|
||||
font-size: 12px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
padding: 8px 16px;
|
||||
background: #fafafa;
|
||||
margin: 4px 8px;
|
||||
|
||||
&:hover {
|
||||
background: #fafafa;
|
||||
color: #666;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pozo-menu-icon {
|
||||
margin-right: 0.3rem;
|
||||
font-size: 1.3rem;
|
||||
min-width: 24px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@media (max-width: 500px) {
|
||||
font-size: 1rem !important;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.pozo-menu-label {
|
||||
flex: 1;
|
||||
color: #ffffff;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
word-break: break-word;
|
||||
line-height: 1.2;
|
||||
font-family: "Poppins", sans-serif !important;
|
||||
}
|
||||
|
||||
.pozo-menu-arrow {
|
||||
margin-left: auto;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: transform 0.2s ease;
|
||||
color: #999;
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.open.pozo-menu-arrow {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
// Dropdown Submenu Styles - SideMenuPozo Style
|
||||
.pozo-dropdown-submenu {
|
||||
position: fixed !important;
|
||||
background: #23378a;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
border: none;
|
||||
min-width: 200px;
|
||||
max-width: 300px;
|
||||
max-height: 54vh;
|
||||
overflow-y: auto;
|
||||
animation: dropdownFadeIn 0.2s ease;
|
||||
scrollbar-width: thin;
|
||||
z-index: 1050 !important;
|
||||
|
||||
// Ensure no transform interference
|
||||
transform: none !important;
|
||||
margin: 0 !important;
|
||||
|
||||
&.nested-submenu {
|
||||
background: #23378a;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
padding: 0.2rem 0 0.5rem 0;
|
||||
width: 200px;
|
||||
z-index: 10001 !important;
|
||||
margin-left: -3px !important;
|
||||
@media (max-width: 768px) {
|
||||
background-color: #040716;
|
||||
}
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #c1c1c1;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb:hover {
|
||||
background: #a8a8a8;
|
||||
}
|
||||
}
|
||||
|
||||
.pozo-submenu-content {
|
||||
padding: 0.2rem 0 0.5rem 0;
|
||||
|
||||
.pozo-menu-item {
|
||||
margin: 1px 8px;
|
||||
padding: 0.5rem 0.7rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
border-radius: 6px;
|
||||
background: transparent;
|
||||
transition:
|
||||
background 0.18s,
|
||||
color 0.18s;
|
||||
|
||||
&:hover:not(.selected):not(.active-path) {
|
||||
background: #394588;
|
||||
color: #182147;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background: #050d36 !important;
|
||||
color: #ffffff !important;
|
||||
font-weight: 600;
|
||||
border-radius: 6px;
|
||||
border-left: 3px solid #ffffff;
|
||||
|
||||
.pozo-menu-icon {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.pozo-menu-label {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.pozo-menu-arrow {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.active-path {
|
||||
background: #050d36 !important;
|
||||
color: #ffffff !important;
|
||||
font-weight: 600;
|
||||
border-radius: 6px;
|
||||
|
||||
.pozo-menu-icon {
|
||||
color: #23bbff !important;
|
||||
}
|
||||
|
||||
.pozo-menu-label {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.pozo-menu-arrow {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.group-item {
|
||||
background: transparent;
|
||||
border-bottom: none;
|
||||
margin: 0;
|
||||
border-radius: 6px;
|
||||
|
||||
&:hover {
|
||||
background: transparent;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Inline Submenu Styles
|
||||
.pozo-inline-submenu {
|
||||
background: #fafafa;
|
||||
border-left: 2px solid #e8e8e8;
|
||||
margin-left: 20px;
|
||||
border-radius: 0 6px 6px 0;
|
||||
|
||||
.pozo-menu-item {
|
||||
margin: 1px 4px;
|
||||
padding: 8px 12px;
|
||||
font-size: 13px;
|
||||
background: transparent;
|
||||
|
||||
&:hover {
|
||||
background: #f0f8ff;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background: #e6f7ff;
|
||||
border-left: 2px solid #1890ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Animation
|
||||
@keyframes dropdownFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Bottom menu positioning
|
||||
.bottom-menu {
|
||||
.pozo-dropdown-submenu {
|
||||
// Remove transform for bottom menu - use calculated position
|
||||
transform: none !important;
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
// Responsive Design
|
||||
@media (max-width: 900px) {
|
||||
// .pozo-dropdown-submenu {
|
||||
// // left: 70px !important;
|
||||
// // min-width: 180px;
|
||||
// // max-width: calc(100vw - 80px);
|
||||
// }
|
||||
|
||||
// .pozo-dropdown-submenu.nested-submenu {
|
||||
// // left: 70px !important;
|
||||
// }
|
||||
|
||||
.bottom-menu .pozo-dropdown-submenu {
|
||||
left: 70px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.pozo-menu {
|
||||
&.pozo-menu-vertical {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.pozo-dropdown-submenu {
|
||||
// min-width: 160px;
|
||||
// max-width: calc(50vw - 20px);
|
||||
// left: 30% !important;
|
||||
// right: 10px !important;
|
||||
position: unset !important;
|
||||
width: 100% !important;
|
||||
min-width: unset !important;
|
||||
max-width: unset !important;
|
||||
background-color: #050d36c4;
|
||||
// border-top: 1px solid #23bbff;
|
||||
margin-top: 2px !important;
|
||||
}
|
||||
|
||||
.pozo-menu-item {
|
||||
padding: 10px 8px;
|
||||
font-size: 15px;
|
||||
margin: 1px 3px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 500px) {
|
||||
.pozo-menu-item {
|
||||
// padding: 8px 8px;
|
||||
padding: 6px 4px 6px 6px;
|
||||
font-size: 15px;
|
||||
}
|
||||
.pozo-menu-label {
|
||||
font-size: 11px !important;
|
||||
margin-top: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
// Dark Theme Support
|
||||
.pozo-menu.dark-theme {
|
||||
background: #001529;
|
||||
color: #fff;
|
||||
|
||||
.pozo-menu-item {
|
||||
color: #ffffffd9;
|
||||
|
||||
&:hover {
|
||||
background: #1890ff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background: #1890ff;
|
||||
color: #fff;
|
||||
border-left-color: #fff;
|
||||
}
|
||||
|
||||
&.group-item {
|
||||
background: #002140;
|
||||
color: rgba(255, 255, 255, 0.65);
|
||||
}
|
||||
}
|
||||
|
||||
.pozo-dropdown-submenu {
|
||||
background: #001529;
|
||||
border-color: #303030;
|
||||
}
|
||||
|
||||
.pozo-inline-submenu {
|
||||
background: #002140;
|
||||
border-left-color: #303030;
|
||||
}
|
||||
}
|
||||
|
||||
// High Contrast Mode
|
||||
@media (prefers-contrast: high) {
|
||||
.pozo-menu-item {
|
||||
border: 1px solid transparent;
|
||||
|
||||
&:hover {
|
||||
border-color: #1890ff;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
border-color: #1890ff;
|
||||
border-width: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,275 @@
|
|||
import { useContext, useEffect, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { Menu } from 'antd';
|
||||
import {
|
||||
changePreviewComponents,
|
||||
changeSelectedPrintdummyData,
|
||||
getTemplate,
|
||||
} from '../../Features/ThemeChange/ThemeChange';
|
||||
import {
|
||||
changeBookingType,
|
||||
changeOrderCardDetails,
|
||||
changeReorderHoldDetails,
|
||||
changeProductCategorie,
|
||||
changeCustomerID,
|
||||
changeSelectedCustId,
|
||||
changeSelectedOption,
|
||||
ChangeOverAllDiscSales,
|
||||
ChangeOverAllDiscEstimate,
|
||||
changeSummeryTotalAmount,
|
||||
changeSearchedData,
|
||||
changeBtoBQuickProductTransfer,
|
||||
changeTipAmount,
|
||||
changeCommonPaymentOptions,
|
||||
GlobalDineinDefault,
|
||||
} from '../../Features/BookingScreen/BookingData/BookingData';
|
||||
import {
|
||||
changeWholeSaleAuctionSelectedData,
|
||||
changeWholeSaleGradeListData,
|
||||
} from '../../Features/WholeSale/WholesaleData';
|
||||
import { GiHamburgerMenu } from 'react-icons/gi';
|
||||
import './sideMenu.scss';
|
||||
import { getSession } from '../../Services/Others';
|
||||
import { ChangeTotalAmount } from '../../Features/ExteraCharges/ExtraCharges';
|
||||
import * as Offer from '../../Features/Offer/Offer';
|
||||
import { AuthContext } from '../../AuthContext';
|
||||
import { useSelector } from 'react-redux';
|
||||
const subDirectory = import.meta.env.BASE_URL;
|
||||
|
||||
export const getItem = (label, key, icon, children, ariaExpanded = false) => {
|
||||
return {
|
||||
key,
|
||||
icon,
|
||||
children,
|
||||
label,
|
||||
};
|
||||
};
|
||||
|
||||
export const getsubItem = (
|
||||
label,
|
||||
key,
|
||||
icon,
|
||||
children,
|
||||
ariaExpanded = false
|
||||
) => {
|
||||
return {
|
||||
key,
|
||||
icon,
|
||||
children,
|
||||
label,
|
||||
};
|
||||
};
|
||||
|
||||
const SideMenu = ({ mode, theme, items }) => {
|
||||
const { freeProductsCount, setFreeProductsCount } = useContext(AuthContext);
|
||||
const [collapsed, setCollapsed] = useState(true);
|
||||
const [width, setWidth] = useState(window.innerWidth);
|
||||
const [openKeys, setOpenKeys] = useState([]);
|
||||
const [clickedKeys, setClickedKeys] = useState([]);
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
const CompId = getSession('CompId');
|
||||
const BranchId = getSession('BranchId');
|
||||
const AppId = getSession('AppId');
|
||||
const DineinDefault = useSelector(GlobalDineinDefault);
|
||||
|
||||
const handleMouseEnter = (e) => {
|
||||
const key = e.key;
|
||||
if (!openKeys.includes(key)) {
|
||||
setOpenKeys((prev) => [...prev, key]);
|
||||
}
|
||||
};
|
||||
|
||||
const handleMouseLeave = (e) => {
|
||||
const key = e.key;
|
||||
// Only remove the key if it wasn't clicked
|
||||
if (!clickedKeys.includes(key)) {
|
||||
setOpenKeys((prev) => prev.filter((k) => k !== key));
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubMenuClick = ({ key }) => {
|
||||
// Toggle clicked state
|
||||
setClickedKeys((prev) => {
|
||||
if (prev.includes(key)) {
|
||||
// If already clicked, remove it and close the menu
|
||||
setOpenKeys((openKeys) => openKeys.filter((k) => k !== key));
|
||||
return prev.filter((k) => k !== key);
|
||||
}
|
||||
// If not clicked, add it and keep menu open
|
||||
return [...prev, key];
|
||||
});
|
||||
};
|
||||
|
||||
const handleMenuItemClick = (e) => {
|
||||
if(DineinDefault&& e.key == `${subDirectory}sales` ){
|
||||
navigatefun(`${subDirectory}sales/dine-in`);
|
||||
// setOpenKeys([]);
|
||||
}else{
|
||||
navigatefun(e.key);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const handleClickOutside = (e) => {
|
||||
if (!e.target.closest('.ant-menu')) {
|
||||
setOpenKeys([]);
|
||||
setClickedKeys([]);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener('click', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('click', handleClickOutside);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const navigatefun = async (e) => {
|
||||
try {
|
||||
dispatch(changePreviewComponents({}));
|
||||
dispatch(changeSelectedPrintdummyData(false));
|
||||
dispatch(changeWholeSaleGradeListData([]));
|
||||
dispatch(changeWholeSaleAuctionSelectedData([]));
|
||||
dispatch(changeCommonPaymentOptions([]));
|
||||
dispatch(
|
||||
changeBtoBQuickProductTransfer({
|
||||
action: false,
|
||||
selectedProducts: [],
|
||||
})
|
||||
);
|
||||
if (e == `${subDirectory}sales/dine-in`) {
|
||||
dispatch(changeTipAmount(0));
|
||||
dispatch(changeBookingType('Dine In'));
|
||||
dispatch(changeOrderCardDetails([]));
|
||||
dispatch(changeReorderHoldDetails({}));
|
||||
dispatch(changeProductCategorie(null));
|
||||
dispatch(changeCustomerID(null));
|
||||
dispatch(changeSelectedCustId(null));
|
||||
dispatch(changeSelectedOption(null));
|
||||
dispatch(ChangeOverAllDiscSales(0));
|
||||
dispatch(ChangeOverAllDiscEstimate(0));
|
||||
dispatch(Offer.changeSalesWiseOfferAmount(0));
|
||||
dispatch(Offer.changeOverallOfferAmount(0));
|
||||
dispatch(changeSummeryTotalAmount(0));
|
||||
dispatch(Offer.changeOrderOfferDetail([]));
|
||||
// await dispatch(Offer.changeFreeProductCount(0));
|
||||
setFreeProductsCount(0);
|
||||
|
||||
dispatch(Offer.changeloyaltyPointsDiscountAmount(0));
|
||||
dispatch(ChangeTotalAmount([]));
|
||||
}
|
||||
if (e == `${subDirectory}sales`) {
|
||||
// await dispatch(getTemplate({ CompId, BranchId, AppId })).unwrap();
|
||||
dispatch(changeTipAmount(0));
|
||||
dispatch(changeSearchedData(''));
|
||||
dispatch(changeBookingType('TakeAway'));
|
||||
dispatch(changeOrderCardDetails([]));
|
||||
dispatch(changeReorderHoldDetails({}));
|
||||
dispatch(changeProductCategorie(null));
|
||||
dispatch(changeCustomerID(null));
|
||||
dispatch(changeSelectedCustId(null));
|
||||
dispatch(changeSelectedOption(null));
|
||||
dispatch(ChangeOverAllDiscSales(0));
|
||||
dispatch(ChangeOverAllDiscEstimate(0));
|
||||
dispatch(Offer.changeSalesWiseOfferAmount(0));
|
||||
dispatch(Offer.changeOverallOfferAmount(0));
|
||||
dispatch(changeSummeryTotalAmount(0));
|
||||
dispatch(Offer.changeOrderOfferDetail([]));
|
||||
// dispatch(Offer.changeFreeProductCount(0));
|
||||
setFreeProductsCount(0);
|
||||
dispatch(Offer.changeloyaltyPointsDiscountAmount(0));
|
||||
dispatch(Offer.changeCoupenCodeAmount(0));
|
||||
dispatch(ChangeTotalAmount([]));
|
||||
}
|
||||
|
||||
if (e == `${subDirectory}saleslayouts/print-selection`) {
|
||||
dispatch(changeSelectedPrintdummyData(true));
|
||||
}
|
||||
// if(e==`${subDirectory}kiosksales`){
|
||||
// const elem = document.documentElement;
|
||||
// if (elem.requestFullscreen) {
|
||||
// elem.requestFullscreen();
|
||||
// } else if (elem.mozRequestFullScreen) { // Firefox
|
||||
// elem.mozRequestFullScreen();
|
||||
// } else if (elem.webkitRequestFullscreen) { // Chrome, Safari and Opera
|
||||
// elem.webkitRequestFullscreen();
|
||||
// } else if (elem.msRequestFullscreen) { // IE/Edge
|
||||
// elem.msRequestFullscreen();
|
||||
// }
|
||||
// }else{
|
||||
// if (document.exitFullscreen) {
|
||||
// document.exitFullscreen();
|
||||
// } else if (document.mozCancelFullScreen) { // Firefox
|
||||
// document.mozCancelFullScreen();
|
||||
// } else if (document.webkitExitFullscreen) { // Chrome, Safari and Opera
|
||||
// document.webkitExitFullscreen();
|
||||
// } else if (document.msExitFullscreen) { // IE/Edge
|
||||
// document.msExitFullscreen();
|
||||
// }
|
||||
// }
|
||||
|
||||
navigate(e);
|
||||
} catch (error) {
|
||||
console.error('Navigation failed:', error);
|
||||
}
|
||||
};
|
||||
const toggleCollapsed = () => {
|
||||
setCollapsed(!collapsed);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
function handleResize() {
|
||||
setWidth(window.innerWidth);
|
||||
}
|
||||
window.addEventListener('resize', handleResize);
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
}, [width]);
|
||||
|
||||
useEffect(() => {
|
||||
width < 768 && setCollapsed(true);
|
||||
width > 768 && setCollapsed(false);
|
||||
}, [width < 768]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div style={{ display: 'flex', justifyContent: 'center' }}>
|
||||
<button
|
||||
onClick={toggleCollapsed}
|
||||
style={{
|
||||
position: 'fixed',
|
||||
top: '5px',
|
||||
border: 'none',
|
||||
}}
|
||||
>
|
||||
{collapsed ? (
|
||||
<GiHamburgerMenu />
|
||||
) : (
|
||||
<GiHamburgerMenu style={{ fontSize: '20px' }} />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
<div style={{ display: 'flex', justifyContent: 'center' }}>
|
||||
{/* <img className="sidebarlogo" src={Logo} style={{width:"2rem",}} alt="" /> */}
|
||||
<p className="sidebarlogo">POZO</p>
|
||||
</div>
|
||||
<Menu
|
||||
className={collapsed ? 'sideMenuantd2' : 'sideMenuantd'}
|
||||
defaultSelectedKeys={['1']}
|
||||
openKeys={openKeys}
|
||||
onOpenChange={setOpenKeys}
|
||||
onClick={handleMenuItemClick}
|
||||
onTitleClick={handleSubMenuClick}
|
||||
inlineCollapsed={collapsed}
|
||||
mode={mode}
|
||||
theme={theme}
|
||||
items={items}
|
||||
onMouseEnter={(e) => handleMouseEnter(e)}
|
||||
onMouseLeave={(e) => handleMouseLeave(e)}
|
||||
triggerSubMenuAction="click"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default SideMenu;
|
||||
|
|
@ -0,0 +1,444 @@
|
|||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { useNavigate, useLocation } from 'react-router-dom';
|
||||
import { useSelector } from 'react-redux';
|
||||
import {
|
||||
FaBars, FaThLarge, FaHome, FaCog, FaChartBar, FaFileAlt,
|
||||
FaMobileAlt, FaSignOutAlt, FaSignInAlt, FaArrowRight,
|
||||
FaCaretRight
|
||||
} from 'react-icons/fa';
|
||||
import { MdSettings, MdOutlineReport, MdOutlineHome, MdOutlineKeyboardArrowDown, MdOutlineKeyboardArrowRight, } from 'react-icons/md';
|
||||
import { BiLogOut, BiLogIn } from 'react-icons/bi';
|
||||
import { AiOutlineAppstore, AiOutlineSetting, AiOutlineBarChart, AiOutlineFileText } from 'react-icons/ai';
|
||||
import { GiHamburgerMenu } from 'react-icons/gi';
|
||||
import './SideMenuPozo.scss';
|
||||
import { FaCaretDown } from "react-icons/fa";
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useContext } from 'react';
|
||||
import { AuthContext } from '../../AuthContext';
|
||||
import PozoMenu from './PozoMenu';
|
||||
import { getSession } from '../../Services/Others';
|
||||
import {
|
||||
changePreviewComponents,
|
||||
changeSelectedPrintdummyData,
|
||||
getTemplate,
|
||||
} from '../../Features/ThemeChange/ThemeChange';
|
||||
import {
|
||||
changeBookingType,
|
||||
changeOrderCardDetails,
|
||||
changeReorderHoldDetails,
|
||||
changeProductCategorie,
|
||||
changeCustomerID,
|
||||
changeSelectedCustId,
|
||||
changeSelectedOption,
|
||||
ChangeOverAllDiscSales,
|
||||
ChangeOverAllDiscEstimate,
|
||||
changeSummeryTotalAmount,
|
||||
changeSearchedData,
|
||||
changeBtoBQuickProductTransfer,
|
||||
changeTipAmount,
|
||||
GlobalDineinDefault,
|
||||
} from '../../Features/BookingScreen/BookingData/BookingData';
|
||||
import {
|
||||
changeWholeSaleAuctionSelectedData,
|
||||
changeWholeSaleGradeListData,
|
||||
} from '../../Features/WholeSale/WholesaleData';
|
||||
import { ChangeTotalAmount } from '../../Features/ExteraCharges/ExtraCharges';
|
||||
import * as Offer from '../../Features/Offer/Offer';
|
||||
import { FiMenu } from 'react-icons/fi';
|
||||
import POZOMIND from "../../Images/PozomindWLogo.png";
|
||||
import { ChangeFullFreeProductList, changeFullOfferAppliedProducts, changeLoyaltyConsumedQuantities } from '../../Features/Offer/Offernew/BookingOffernew';
|
||||
|
||||
const subDirectory = import.meta.env.BASE_URL;
|
||||
|
||||
// Filter functions (copied from AppPage.jsx)
|
||||
function filterMenuItems(menu, configList) {
|
||||
if (!Array.isArray(menu)) return [];
|
||||
return menu.filter((item) => {
|
||||
if (!item) return false;
|
||||
if (item.label === "Sign Out") return true;
|
||||
// For nested children, filter recursively
|
||||
let filteredChildren = item.children ? filterMenuItems(item.children, configList) : undefined;
|
||||
// Employee access: ConfigName
|
||||
const config = configList?.find(
|
||||
(config) => config.ConfigName === item.label && config.ReadAccess === 'Y'
|
||||
);
|
||||
// If this item or any of its children are accessible, include it
|
||||
return (config || (filteredChildren && filteredChildren.length > 0));
|
||||
}).map(item => ({
|
||||
...item,
|
||||
children: item.children ? filterMenuItems(item.children, configList) : undefined
|
||||
}));
|
||||
}
|
||||
|
||||
function filterSadminUserMenuItems(menu, configList) {
|
||||
if (!Array.isArray(menu)) return [];
|
||||
return menu.filter((item) => {
|
||||
if (!item) return false;
|
||||
if (item.label === "Sign Out") return true;
|
||||
|
||||
let filteredChildren = item.children ? filterSadminUserMenuItems(item.children, configList) : undefined;
|
||||
// Super admin user access: MenuName
|
||||
const config = configList?.find(
|
||||
(config) => config.MenuName === item.label && config.ReadAccess === 'Y'
|
||||
);
|
||||
return (config || (filteredChildren && filteredChildren.length > 0));
|
||||
}).map(item => ({
|
||||
...item,
|
||||
children: item.children ? filterSadminUserMenuItems(item.children, configList) : undefined
|
||||
}));
|
||||
}
|
||||
|
||||
// Capitalize helper
|
||||
function capitalizeWords(str) {
|
||||
if (typeof str !== 'string') return '';
|
||||
return str.replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase());
|
||||
}
|
||||
|
||||
// Recursively capitalize all menu item labels, filtering out falsy items and items without a label
|
||||
function capitalizeMenuLabels(items) {
|
||||
return (items || [])
|
||||
.filter(item => item && typeof item.label === 'string' && item.label.trim() !== '')
|
||||
.map(item => ({
|
||||
...item,
|
||||
label: capitalizeWords(item.label),
|
||||
children: item.children ? capitalizeMenuLabels(item.children) : undefined
|
||||
}));
|
||||
}
|
||||
|
||||
const SideMenuPozo = ({ items = [] }) => {
|
||||
const { freeProductsCount, setFreeProductsCount, UserType, Access, SadminuserAccess } = useContext(AuthContext);
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const [openKeys, setOpenKeys] = useState([]);
|
||||
const [collapsed, setCollapsed] = useState(window.innerWidth < 768);
|
||||
const [dropdownPosition, setDropdownPosition] = useState({});
|
||||
const menuRef = useRef();
|
||||
const CompId = getSession('CompId');
|
||||
const BranchId = getSession('BranchId');
|
||||
const AppId = getSession('AppId');
|
||||
const DineinDefault = useSelector(GlobalDineinDefault);
|
||||
const [collapse, setCollapse] = useState(false);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
setCollapse(window.innerWidth < 768);
|
||||
};
|
||||
window.addEventListener('resize', handleResize);
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
setCollapsed(window.innerWidth < 768);
|
||||
};
|
||||
window.addEventListener('resize', handleResize);
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (e) => {
|
||||
if (menuRef.current && !menuRef.current.contains(e.target)) {
|
||||
setOpenKeys([]);
|
||||
setDropdownPosition({});
|
||||
}
|
||||
};
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => document.removeEventListener('mousedown', handleClickOutside);
|
||||
}, []);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event) => {
|
||||
if (window.innerWidth < 768) {
|
||||
if (menuRef.current && !menuRef.current.contains(event.target)) {
|
||||
setCollapse(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener("mousedown", handleClickOutside);
|
||||
return () => document.removeEventListener("mousedown", handleClickOutside);
|
||||
}, []);
|
||||
|
||||
// Debug current pathname
|
||||
useEffect(() => {
|
||||
console.log('Current pathname:', location.pathname);
|
||||
}, [location.pathname]);
|
||||
|
||||
const isSelected = (key) => location.pathname === key;
|
||||
const isOpen = (key) => openKeys.includes(key);
|
||||
|
||||
// Check if any child of this item is selected (for parent menu highlighting)
|
||||
const hasSelectedChild = (item) => {
|
||||
if (!item.children) return false;
|
||||
return item.children.some(child => {
|
||||
if (child.children) {
|
||||
return hasSelectedChild(child);
|
||||
}
|
||||
return location.pathname === child.key;
|
||||
});
|
||||
};
|
||||
|
||||
// Check if a dropdown item is currently selected
|
||||
const isDropdownItemSelected = (item) => {
|
||||
return location.pathname === item.key;
|
||||
};
|
||||
|
||||
const navigatefun = async (e) => {
|
||||
dispatch(changePreviewComponents({}));
|
||||
dispatch(changeSelectedPrintdummyData(false));
|
||||
dispatch(changeWholeSaleGradeListData([]));
|
||||
dispatch(changeWholeSaleAuctionSelectedData([]));
|
||||
dispatch(
|
||||
changeBtoBQuickProductTransfer({
|
||||
action: false,
|
||||
selectedProducts: [],
|
||||
})
|
||||
);
|
||||
if (e == `${subDirectory}sales/dine-in`) {
|
||||
dispatch(changeTipAmount(0));
|
||||
dispatch(changeBookingType('Dine In'));
|
||||
dispatch(changeOrderCardDetails([]));
|
||||
dispatch(changeReorderHoldDetails({}));
|
||||
dispatch(changeProductCategorie(null));
|
||||
dispatch(changeCustomerID(null));
|
||||
dispatch(changeSelectedCustId(null));
|
||||
dispatch(changeSelectedOption(null));
|
||||
dispatch(ChangeOverAllDiscSales(0));
|
||||
dispatch(ChangeOverAllDiscEstimate(0));
|
||||
dispatch(Offer.changeSalesWiseOfferAmount(0));
|
||||
dispatch(Offer.changeOverallOfferAmount(0));
|
||||
dispatch(changeSummeryTotalAmount(0));
|
||||
dispatch(Offer.changeOrderOfferDetail([]));
|
||||
setFreeProductsCount(0);
|
||||
dispatch(Offer.changeloyaltyPointsDiscountAmount(0));
|
||||
dispatch(ChangeTotalAmount([]));
|
||||
dispatch(ChangeFullFreeProductList([]));
|
||||
dispatch(changeFullOfferAppliedProducts([]));
|
||||
dispatch(changeLoyaltyConsumedQuantities({}))
|
||||
}
|
||||
if (e == `${subDirectory}sales`) {
|
||||
dispatch(changeTipAmount(0));
|
||||
dispatch(changeSearchedData(''));
|
||||
dispatch(changeBookingType('TakeAway'));
|
||||
dispatch(changeOrderCardDetails([]));
|
||||
dispatch(changeReorderHoldDetails({}));
|
||||
dispatch(changeProductCategorie(null));
|
||||
dispatch(changeCustomerID(null));
|
||||
dispatch(changeSelectedCustId(null));
|
||||
dispatch(changeSelectedOption(null));
|
||||
dispatch(ChangeOverAllDiscSales(0));
|
||||
dispatch(ChangeOverAllDiscEstimate(0));
|
||||
dispatch(Offer.changeSalesWiseOfferAmount(0));
|
||||
dispatch(Offer.changeOverallOfferAmount(0));
|
||||
dispatch(changeSummeryTotalAmount(0));
|
||||
dispatch(Offer.changeOrderOfferDetail([]));
|
||||
setFreeProductsCount(0);
|
||||
dispatch(Offer.changeloyaltyPointsDiscountAmount(0));
|
||||
dispatch(Offer.changeCoupenCodeAmount(0));
|
||||
dispatch(ChangeFullFreeProductList([]));
|
||||
dispatch(changeFullOfferAppliedProducts([]));
|
||||
dispatch(ChangeTotalAmount([]));
|
||||
dispatch(changeLoyaltyConsumedQuantities({}))
|
||||
}
|
||||
if (e == `${subDirectory}saleslayouts/print-selection`) {
|
||||
dispatch(changeSelectedPrintdummyData(true));
|
||||
}
|
||||
navigate(e);
|
||||
};
|
||||
|
||||
const handleMenuClick = (item, parentKeys = [], event, level = 0) => {
|
||||
if (item.children) {
|
||||
if (openKeys.includes(item.key)) {
|
||||
setOpenKeys(openKeys.filter(k => k !== item.key));
|
||||
const newPositions = { ...dropdownPosition };
|
||||
delete newPositions[item.key];
|
||||
setDropdownPosition(newPositions);
|
||||
} else {
|
||||
// For top level (level 0), close all other open menus
|
||||
// For nested levels, keep parent chain but close siblings
|
||||
let newOpenKeys;
|
||||
if (level === 0) {
|
||||
// Close all other top-level menus
|
||||
newOpenKeys = [];
|
||||
} else {
|
||||
// Keep only the parent chain, remove siblings
|
||||
newOpenKeys = openKeys.filter(key => {
|
||||
// Keep if it's in the parent chain
|
||||
return parentKeys.includes(key);
|
||||
});
|
||||
}
|
||||
|
||||
// Calculate position for dropdown
|
||||
const rect = event.currentTarget.getBoundingClientRect();
|
||||
let position;
|
||||
|
||||
if (level === 0) {
|
||||
position = {
|
||||
top: rect.top,
|
||||
left: collapsed ? rect.right + 1 : 10
|
||||
};
|
||||
} else {
|
||||
position = {
|
||||
top: rect.top,
|
||||
left: rect.right + 1
|
||||
};
|
||||
}
|
||||
|
||||
setDropdownPosition(prev => ({ ...prev, [item.key]: position }));
|
||||
setOpenKeys([...newOpenKeys, item.key]);
|
||||
}
|
||||
} else {
|
||||
if (DineinDefault && item.key == `${subDirectory}sales`) {
|
||||
navigatefun(`${subDirectory}sales/dine-in`);
|
||||
setOpenKeys([]);
|
||||
}
|
||||
else {
|
||||
navigatefun(item.key);
|
||||
setOpenKeys([]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
console.log(items, Access, "Employee items")
|
||||
// Filter menu items based on access
|
||||
let filteredMenuItems = (items || []).filter(Boolean);
|
||||
if (UserType === 'Employee' && Array.isArray(Access) && Access.length > 0) {
|
||||
filteredMenuItems = filterMenuItems(filteredMenuItems, Access);
|
||||
} else if (UserType === 'Super Admin User' && Array.isArray(SadminuserAccess) && SadminuserAccess.length > 0) {
|
||||
filteredMenuItems = filterSadminUserMenuItems(filteredMenuItems, SadminuserAccess);
|
||||
}
|
||||
|
||||
// Capitalize all labels, filter out items without a label
|
||||
const menuItemsWithCapitalizedLabels = capitalizeMenuLabels(filteredMenuItems);
|
||||
const bottomKeys = ['Support', 'Settings', 'Download', 'Sign Out'];
|
||||
const bottomMenuItems = menuItemsWithCapitalizedLabels.filter(item =>
|
||||
bottomKeys.includes(item.label)
|
||||
);
|
||||
const mainMenuItems = menuItemsWithCapitalizedLabels.filter(item =>
|
||||
!bottomKeys.includes(item.label)
|
||||
);
|
||||
// Recursive render for menu and submenus
|
||||
const renderMenuItems = (items, parentKeys = [], level = 0) => (
|
||||
<div className={`side-menu-list${level > 0 ? ' nested-list' : ''}`}>
|
||||
{(items || []).filter(Boolean).map((item) => (
|
||||
<div key={item.key}>
|
||||
<div
|
||||
className={`${level > 0 ? 'dropdown-submenu-item' : 'menu-item'}${isSelected(item.key) || (level === 0 && hasSelectedChild(item)) ? ' selecteded' : ''}${isOpen(item.key) ? ' open' : ''}${item.children ? ' has-children' : ''}`}
|
||||
onClick={(e) => { e.stopPropagation(); handleMenuClick(item, parentKeys, e, level); }}
|
||||
// style={{ paddingLeft: `${level * 10 + 1}px` }}
|
||||
>
|
||||
{item.icon && level === 0 && <span className='menu-icon' style={{
|
||||
fontSize: collapse ? "1.5rem" : ""
|
||||
}}>{item.icon}</span>}
|
||||
{!collapse && <span className='menu-label'>{item.label}</span>}
|
||||
{!collapse && <span className='menu-labelDot'>{isDropdownItemSelected(item) ? '●' : ''}</span>}
|
||||
{item.children && !collapse && (
|
||||
<span className='menu-arrow'>
|
||||
{level === 0 ? <FaCaretRight size={14} /> : <MdOutlineKeyboardArrowRight />}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{item.children && isOpen(item.key) && !collapse && (
|
||||
<div
|
||||
className={`dropdown-submenu${level > 0 ? ' nested' : ''}`}
|
||||
|
||||
>
|
||||
{renderMenuItems(item.children, [...parentKeys, item.key], level + 1)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
// Custom onClick handler for PozoMenu
|
||||
const handlePozoMenuClick = (e) => {
|
||||
console.log('PozoMenu clicked:', e);
|
||||
navigatefun(e.key);
|
||||
};
|
||||
|
||||
// Get current selected key based on location
|
||||
const getCurrentSelectedKey = () => {
|
||||
return location.pathname;
|
||||
};
|
||||
|
||||
const isMobile = /Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
|
||||
const isAndroid = /Android/i.test(navigator.userAgent);
|
||||
|
||||
|
||||
return (
|
||||
<div className={`SideMenuPozo-Master${collapse ? ' collapsed' : ''}`} ref={menuRef}
|
||||
style={{ height: isMobile ? "88%" : "" }}
|
||||
>
|
||||
<div style={{
|
||||
width: "100%", display: "flex", flexDirection: "column", gap: "10px",
|
||||
height: "68vh", overflow: "auto"
|
||||
}}>
|
||||
<div className="paypreLogoDiv">
|
||||
<div className="shopNameNav" style={{ width: "100%" }}>
|
||||
<div style={{
|
||||
display: "flex", flexDirection: "row",
|
||||
alignItems: "center", gap: "4px", padding: "0px 10px", justifyContent: "space-between"
|
||||
}}>
|
||||
<FiMenu
|
||||
size={26}
|
||||
onClick={() => setCollapse((prev) => !prev)}
|
||||
style={{ cursor: 'pointer' }}
|
||||
/>
|
||||
{collapse ? "" :
|
||||
// <img src={POZOMIND} alt="PozoMindLogo" width="80px" height={"45px"} className='PozoMindLogo' />
|
||||
<div>
|
||||
PozoApp
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
{/* <div> */}
|
||||
{/* <div>{branchName}</div> */}
|
||||
<p>{/* {'Palacode'} , {'Tamilnadu'} , {'India'} */}</p>
|
||||
{/* </div> */}
|
||||
</div>
|
||||
</div>
|
||||
{/* Top Menu using PozoMenu */}
|
||||
<div className='top-menu'>
|
||||
<PozoMenu
|
||||
items={mainMenuItems}
|
||||
mode="vertical"
|
||||
collapse={collapse}
|
||||
selectedKey={getCurrentSelectedKey()}
|
||||
style={{
|
||||
width: collapse ? '60px' : '200px',
|
||||
background: 'transparent',
|
||||
boxShadow: 'none'
|
||||
}}
|
||||
onClick={handlePozoMenuClick}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/* Bottom Menu using PozoMenu */}
|
||||
<div className='bottom-menu' style={{
|
||||
height: isMobile ? "30vh" : ""
|
||||
}}>
|
||||
<PozoMenu
|
||||
items={bottomMenuItems}
|
||||
mode="vertical"
|
||||
collapse={collapse}
|
||||
selectedKey={getCurrentSelectedKey()}
|
||||
isBottomMenu={true}
|
||||
style={{
|
||||
width: collapse ? '60px' : '200px',
|
||||
background: 'transparent',
|
||||
boxShadow: 'none'
|
||||
}}
|
||||
onClick={handlePozoMenuClick}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SideMenuPozo;
|
||||
|
|
@ -0,0 +1,408 @@
|
|||
.SideMenuPozo-Master {
|
||||
// width: 12vw;
|
||||
// width: 200px;
|
||||
width: 160px;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
background-color: #23378a;
|
||||
padding: 0rem 3px 0 0px;
|
||||
transition: width 0.2s;
|
||||
font-family: 'Poppins', sans-serif !important;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
|
||||
@media (max-width: 500px) {
|
||||
width: 150px;
|
||||
overflow: auto;
|
||||
// padding-bottom: 3rem;
|
||||
// position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100vh !important;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.SideMenuPozo-Master.collapsed {
|
||||
width: 45px;
|
||||
min-width: 45px;
|
||||
position: unset;
|
||||
|
||||
@media (max-width: 500px) {
|
||||
width: 9vw;
|
||||
}
|
||||
}
|
||||
|
||||
.side-menu-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.hamburger-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #fff;
|
||||
font-size: 1.5rem;
|
||||
cursor: pointer;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.side-menu-logo {
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
font-size: 1.2rem;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.side-menu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
color: #fff;
|
||||
padding: 10px 8px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
transition:
|
||||
background 0.2s,
|
||||
color 0.2s;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: 38px;
|
||||
font-family: 'Poppins', sans-serif !important;
|
||||
|
||||
@media (max-width: 500px) {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-item.selecteded,
|
||||
.menu-item.open {
|
||||
// background: #25306a;
|
||||
background: #050d36;
|
||||
color: #23bbff;
|
||||
border-right: 2px solid #23bbff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.menu-item:hover {
|
||||
background: #394588;
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
margin-right: 0.3rem;
|
||||
font-size: 1.3rem;
|
||||
min-width: 24px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.menu-label {
|
||||
flex: 1;
|
||||
color: #ffffff;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
word-break: break-word;
|
||||
max-width: 140px;
|
||||
line-height: 1.2;
|
||||
font-family: 'Poppins', sans-serif !important;
|
||||
|
||||
@media (max-width: 500px) {
|
||||
font-size: 8px !important;
|
||||
margin-top: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.side-menu-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 95vh; // Full screen height
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.side-menu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.top-menu {
|
||||
// flex: 1 1 auto;
|
||||
overflow: hidden; // Prevent scroll
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.bottom-menu {
|
||||
flex-shrink: 0;
|
||||
padding: 10px 0;
|
||||
width: 100%;
|
||||
// height: 32vh;
|
||||
max-height: 30vh;
|
||||
overflow: auto;
|
||||
// padding-bottom: 5rem;
|
||||
}
|
||||
|
||||
.menu-arrow {
|
||||
margin-left: auto;
|
||||
font-size: 1.2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.submenu {
|
||||
margin-left: 2.2rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.3rem;
|
||||
}
|
||||
|
||||
.submenu-item {
|
||||
color: #fff;
|
||||
padding: 0.5rem 0.7rem;
|
||||
border-radius: 6px;
|
||||
font-size: 0.95rem;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.submenu-item:hover {
|
||||
background: #2e397a;
|
||||
}
|
||||
|
||||
.floating-submenu {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.floating-submenu-item {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.reports-parent {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
// Dropdown submenu styles
|
||||
.dropdown-submenu {
|
||||
// position: fixed;
|
||||
position: absolute;
|
||||
margin-top: -2rem;
|
||||
width: 200px;
|
||||
background: #23378a;
|
||||
color: #fff;
|
||||
border-radius: 12px 12px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
// padding: 0.2rem 0 0.5rem 0;
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.2rem;
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
transition:
|
||||
max-height 0.2s ease,
|
||||
opacity 0.2s;
|
||||
animation: dropdown-fade-in 0.2s;
|
||||
// max-height: 350px;
|
||||
// overflow: auto;
|
||||
// left: 202px;
|
||||
left: 12.7rem;
|
||||
top: auto;
|
||||
bottom: auto;
|
||||
}
|
||||
|
||||
@keyframes dropdown-fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-submenu.nested {
|
||||
background: #23378a;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
padding: 0.2rem 0 0.5rem 0;
|
||||
// position: fixed !important;
|
||||
width: 200px;
|
||||
z-index: 10000;
|
||||
left: 12.7rem;
|
||||
}
|
||||
|
||||
.side-menu-list.nested-list {
|
||||
padding-left: 0;
|
||||
height: max-content;
|
||||
max-height: 54vh;
|
||||
overflow: auto;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
.side-menu-list {
|
||||
margin: 3px 3px;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.1rem;
|
||||
}
|
||||
|
||||
.dropdown-submenu-item {
|
||||
color: #fff;
|
||||
padding: 0.5rem 0.7rem;
|
||||
border-radius: 6px;
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
transition:
|
||||
background 0.18s,
|
||||
color 0.18s;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.dropdown-submenu-item:hover {
|
||||
background: #394588;
|
||||
color: #182147;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.dropdown-submenu-item .open {
|
||||
background: #050d36;
|
||||
color: #182147;
|
||||
font-weight: 600;
|
||||
border-radius: 10px;
|
||||
border-left: 3px solid #23bbff;
|
||||
}
|
||||
|
||||
.dropdown-submenu-item.selecteded {
|
||||
background: #050d36;
|
||||
color: #182147;
|
||||
font-weight: 600;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.dropdown-submenu-item.selecteded {
|
||||
border-left: 3px solid #394588;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
// .dropdown-submenu-item.selecteded::after {
|
||||
// content: '';
|
||||
// position: absolute;
|
||||
// right: 8px;
|
||||
// top: 50%;
|
||||
// transform: translateY(-50%);
|
||||
// width: 6px;
|
||||
// height: 6px;
|
||||
// background: #23bbff;
|
||||
// border-radius: 50%;
|
||||
// }
|
||||
|
||||
.menu-item.has-children {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.dropdown-submenu {
|
||||
left: 70px;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-menu {
|
||||
.side-menu-list.nested-list {
|
||||
max-height: 85vh;
|
||||
}
|
||||
|
||||
.dropdown-submenu {
|
||||
bottom: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-labelDot {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
color: #23bbff;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.menu-item.open.has-children,
|
||||
.dropdown-submenu-item.open.has-children {
|
||||
background-color: #050d36 !important;
|
||||
border-right: 2px solid #23bbff;
|
||||
}
|
||||
|
||||
.menu-item.selecteded,
|
||||
.dropdown-submenu-item.selecteded {
|
||||
background-color: #050d36 !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.shopNameNav {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
text-transform: capitalize;
|
||||
gap: 0;
|
||||
gap: 10px;
|
||||
|
||||
div {
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
|
||||
@media (max-width: 499px) {
|
||||
font-size: 14px !important;
|
||||
|
||||
svg {
|
||||
width: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div:nth-child(2) {
|
||||
font-size: 22px;
|
||||
font-weight: 500;
|
||||
display: unset;
|
||||
font-family: "Poppins";
|
||||
letter-spacing: -1.2px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 10px;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.3px;
|
||||
|
||||
@media (max-width: 499px) {
|
||||
font-size: 7px !important;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
padding-right: 1rem;
|
||||
|
||||
@media (max-width: 499px) {
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
.ant-menu-title-content {
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
// shifayath
|
||||
// align-items: center;
|
||||
//
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ant-menu-vertical > .ant-menu-submenu > .ant-menu-submenu-title {
|
||||
height: 57px;
|
||||
line-height: 35px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
// align-items: center;
|
||||
row-gap: 0.5rem;
|
||||
}
|
||||
|
||||
@media (max-width: 500px) {
|
||||
.sideNaveParent {
|
||||
// width: 16vw;
|
||||
position: relative;
|
||||
z-index: 100;
|
||||
}
|
||||
}
|
||||
|
||||
.sideNaveParent .ant-menu-submenu > .ant-menu-submenu-title {
|
||||
height: 57px;
|
||||
line-height: 35px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
row-gap: 0.5rem;
|
||||
padding-inline-end: 15px;
|
||||
}
|
||||
|
||||
.ant-menu-vertical > .ant-menu-submenu > .ant-menu-submenu-title:hover {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--PRIMARY_BUTTON_BG_COLOR) !important;
|
||||
}
|
||||
|
||||
:where(.css-dev-only-do-not-override-2i2tap).ant-menu-vertical
|
||||
> .ant-menu-submenu
|
||||
> .ant-menu-submenu-title {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
:where(.css-2i2tap).ant-menu-vertical
|
||||
> .ant-menu-submenu
|
||||
> .ant-menu-submenu-title {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ant-menu-vertical > .ant-menu-item {
|
||||
// line-height: 35px;
|
||||
line-height: 30px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
// height: 70px;
|
||||
// height: 57px;
|
||||
height: 50px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
row-gap: 0.5rem;
|
||||
margin-inline: 0px;
|
||||
margin-block: 0px;
|
||||
}
|
||||
|
||||
.ant-menu-vertical > .ant-menu-item:hover {
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: var(--PRIMARY_BUTTON_BG_COLOR) !important;
|
||||
}
|
||||
|
||||
.ant-menu-light .ant-menu-submenu-selected > .ant-menu-submenu-title,
|
||||
.ant-menu-light
|
||||
> .ant-menu
|
||||
.ant-menu-submenu-selected
|
||||
> .ant-menu-submenu-title {
|
||||
color: var(--PRIMARY_BUTTON_BG_COLOR) !important;
|
||||
}
|
||||
|
||||
.ant-menu-light .ant-menu-item-selected,
|
||||
.ant-menu-light > .ant-menu .ant-menu-item-selected {
|
||||
color: var(--PRIMARY_BUTTON_BG_COLOR) !important;
|
||||
}
|
||||
|
||||
.ant-menu-light .ant-menu-item-selected,
|
||||
.ant-menu-light > .ant-menu .ant-menu-item-selected {
|
||||
color: var(--PRIMARY_BUTTON_BG_COLOR) !important;
|
||||
}
|
||||
|
||||
.ant-menu-light .ant-menu-item-selected,
|
||||
.ant-menu-light > .ant-menu .ant-menu-item-selected {
|
||||
background-color: #f4eaf2;
|
||||
}
|
||||
|
||||
.ant-menu .ant-menu-item .ant-menu-item-icon svg {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.sideNaveParent .ant-menu .ant-menu-submenu-arrow {
|
||||
top: 40%;
|
||||
}
|
||||
|
||||
.ant-menu .ant-menu-submenu-title .ant-menu-item-icon svg {
|
||||
font-size: 25px;
|
||||
// align-items: center;
|
||||
}
|
||||
|
||||
.ant-menu .ant-menu-item .ant-menu-item-icon + span {
|
||||
margin-inline-start: 0px;
|
||||
}
|
||||
|
||||
.ant-menu-light,
|
||||
.ant-menu-light > .ant-menu {
|
||||
color: rgba(92, 92, 92, 0.88);
|
||||
background: none;
|
||||
padding: 2px;
|
||||
top: 1rem;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.menuLogos {
|
||||
fill: #ff4d4f;
|
||||
background: #ff4d4f;
|
||||
}
|
||||
.ant-menu-submenu {
|
||||
// max-height: 60vh !important;
|
||||
// june 26
|
||||
max-height: 56vh !important;
|
||||
overflow: auto !important;
|
||||
}
|
||||
|
||||
.sideMenuantd {
|
||||
width: 9vw !important;
|
||||
height: 100%;
|
||||
padding: 0px;
|
||||
padding-inline: 0px;
|
||||
padding-inline-end: 0px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
.sideMenuantd2 {
|
||||
width: 5vw !important;
|
||||
height: 100%;
|
||||
padding: 0px;
|
||||
padding-inline: 0px;
|
||||
padding-inline-end: 0px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
.sidebarlogo {
|
||||
// margin-bottom: 1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.sideMenuantd {
|
||||
width: 25vw !important;
|
||||
height: 100%;
|
||||
padding: 0px;
|
||||
padding-inline: 0px;
|
||||
padding-inline-end: 0px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
.sideMenuantd2 {
|
||||
width: 10vw !important;
|
||||
// width: 5rem !important;
|
||||
height: 100%;
|
||||
padding: 0px;
|
||||
padding-inline: 0px;
|
||||
padding-inline-end: 0px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
.sidebarlogo {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 499px) {
|
||||
.sideMenuantd2 {
|
||||
width: 3rem !important;
|
||||
// width: 5rem !important;
|
||||
height: 100%;
|
||||
padding: 0px;
|
||||
padding-inline: 0px;
|
||||
padding-inline-end: 0px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
import React from 'react';
|
||||
import { Layout, Menu, theme } from 'antd';
|
||||
const { Sider } = Layout;
|
||||
|
||||
export const SideMenu = ({ items }) => {
|
||||
items?.map((icon, index) => ({
|
||||
key: String(index + 1),
|
||||
icon: React.createElement(
|
||||
'img',
|
||||
{ src: icon['menuicon'], height: '200px', width: '300px' },
|
||||
null
|
||||
),
|
||||
|
||||
label: icon['menuname'],
|
||||
}));
|
||||
|
||||
return (
|
||||
<Layout hasSider>
|
||||
<Sider
|
||||
style={{
|
||||
overflow: 'auto',
|
||||
height: '100vh',
|
||||
position: 'fixed',
|
||||
left: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
backgroundColor: '#dbe8f5',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
height: 32,
|
||||
margin: 16,
|
||||
}}
|
||||
/>
|
||||
<Menu
|
||||
theme="white"
|
||||
style={{ color: 'black' }}
|
||||
mode="inline"
|
||||
defaultSelectedKeys={['4']}
|
||||
items={items}
|
||||
/>
|
||||
</Sider>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
import {DefaultModal as DefaultModalLibrary} from "../../../ownLib/my-ui-lib"
|
||||
export const DefaultModal = DefaultModalLibrary
|
||||
// import { useEffect } from 'react';
|
||||
// import { Modal } from 'antd';
|
||||
// import Buttons from '../Forms/Buttons';
|
||||
// import { ArrowRightOutlined, CloseOutlined } from '@ant-design/icons';
|
||||
|
||||
// export const DefaultModal = ({
|
||||
// open,
|
||||
// title,
|
||||
// handleCancel,
|
||||
// children,
|
||||
// footer,
|
||||
// handleSubmit,
|
||||
// width,
|
||||
// destroyOnClose,
|
||||
// buttonText,
|
||||
// maskTransitionName,
|
||||
// transitionName,
|
||||
// className,
|
||||
// }) => {
|
||||
// // Close modal on pressing 'Escape'
|
||||
// useEffect(() => {
|
||||
// const handleKeyDown = (event) => {
|
||||
// if (event.key === 'Escape' && open) {
|
||||
// handleCancel();
|
||||
// }
|
||||
// };
|
||||
// window.addEventListener('keydown', handleKeyDown);
|
||||
// return () => window.removeEventListener('keydown', handleKeyDown);
|
||||
// }, [open, handleCancel]);
|
||||
|
||||
// return (
|
||||
// <>
|
||||
// <Modal
|
||||
// destroyOnClose={destroyOnClose ? destroyOnClose : false}
|
||||
// open={open}
|
||||
// title={title}
|
||||
// top={0}
|
||||
// width={width ? width : 700}
|
||||
// maskTransitionName={maskTransitionName}
|
||||
// transitionName={transitionName}
|
||||
// className={className}
|
||||
// centered
|
||||
// closeIcon={<CloseOutlined onClick={handleCancel} />}
|
||||
// onCancel={handleCancel} // Handles default close (mask clicks, close icon)
|
||||
// footer={
|
||||
// footer
|
||||
// ? [
|
||||
// <Buttons
|
||||
// buttonText={buttonText ? buttonText : 'SUBMIT'}
|
||||
// color="901D77"
|
||||
// icon={<ArrowRightOutlined />}
|
||||
// handleSubmit={handleSubmit}
|
||||
// >
|
||||
// {buttonText}
|
||||
// </Buttons>,
|
||||
// ]
|
||||
// : footer
|
||||
// }
|
||||
// maskClosable={true} // Ensures clicking outside closes the modal
|
||||
// >
|
||||
// {children}
|
||||
// </Modal>
|
||||
// </>
|
||||
// );
|
||||
// };
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Modal, Button } from 'antd';
|
||||
import { ImportOutlined, ExportOutlined } from '@ant-design/icons';
|
||||
import * as XLSX from 'xlsx';
|
||||
import { saveAs } from 'file-saver';
|
||||
|
||||
const [excelData, setExcelData] = useState(null);
|
||||
const [excelFile, setExcelFile] = useState(null);
|
||||
const [excelFileError, setExcelFileError] = useState(null);
|
||||
|
||||
const handleFile = (e) => {
|
||||
let selectedFile = e.target.files[0];
|
||||
if (selectedFile) {
|
||||
if (selectedFile && fileType.includes(selectedFile.type)) {
|
||||
let reader = new FileReader();
|
||||
reader.readAsArrayBuffer(selectedFile);
|
||||
reader.onload = (e) => {
|
||||
setExcelFileError(null);
|
||||
setExcelFile(e.target.result);
|
||||
};
|
||||
} else {
|
||||
setExcelFileError('Please select only excel file types');
|
||||
setExcelFile(null);
|
||||
}
|
||||
} else {
|
||||
console.log('Please select a file');
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
if (excelFile !== null) {
|
||||
const workbook = XLSX.read(excelFile, { type: 'buffer' });
|
||||
const worksheetName = workbook.SheetNames[0];
|
||||
const worksheet = workbook.Sheets[worksheetName];
|
||||
const data = XLSX.utils.sheet_to_json(worksheet);
|
||||
setExcelData(data);
|
||||
} else {
|
||||
setExcelData(null);
|
||||
}
|
||||
};
|
||||
|
||||
const handleExport = () => {
|
||||
if (excelData !== null) {
|
||||
const worksheet = XLSX.utils.json_to_sheet(excelData);
|
||||
const workbook = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
|
||||
const excelBuffer = XLSX.write(workbook, {
|
||||
bookType: 'xlsx',
|
||||
type: 'array',
|
||||
});
|
||||
const excelData = new Blob([excelBuffer], {
|
||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
});
|
||||
saveAs(excelData, 'exported_data.xlsx');
|
||||
}
|
||||
};
|
||||
|
||||
const Modals = ({ open, title, handleCancel, children, footer }) => {
|
||||
return (
|
||||
<Modal
|
||||
visible={open}
|
||||
title={title}
|
||||
onCancel={handleCancel}
|
||||
footer={
|
||||
footer
|
||||
? [
|
||||
<Button key="submit" type="primary" onClick={handleSubmit}>
|
||||
Submit
|
||||
</Button>,
|
||||
<Button key="cancel" onClick={handleCancel}>
|
||||
Cancel
|
||||
</Button>,
|
||||
]
|
||||
: footer
|
||||
}
|
||||
>
|
||||
{children}
|
||||
<div>
|
||||
<h4>Import Excel</h4>
|
||||
<input type="file" onChange={handleFile} />
|
||||
{excelFileError && <div className="error">{excelFileError}</div>}
|
||||
<Button type="primary" icon={<ImportOutlined />} onClick={handleSubmit}>
|
||||
Import
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<h4>Export Excel</h4>
|
||||
<Button type="primary" icon={<ExportOutlined />} onClick={handleExport}>
|
||||
Export
|
||||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default Modals;
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
import React from 'react';
|
||||
import { DefaultModal } from './DefaultModal';
|
||||
import StockReceived from '../../Pages/StockTransfer/StockReceived';
|
||||
import Buttons from '../Forms/Buttons';
|
||||
import { BiPlus } from 'react-icons/bi';
|
||||
import { ArrowRightOutlined } from '@ant-design/icons';
|
||||
|
||||
const ProductDetailsModal = ({
|
||||
open,
|
||||
onClose,
|
||||
productDetails,
|
||||
headerData,
|
||||
onDataChange,
|
||||
onSubmit
|
||||
}) => {
|
||||
return (
|
||||
<DefaultModal
|
||||
open={open}
|
||||
title="Product Details"
|
||||
handleCancel={onClose}
|
||||
width={800}
|
||||
footer={false}
|
||||
>
|
||||
<div style={{ overflowX: 'auto' }}>
|
||||
{headerData && (
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
gap: '20px',
|
||||
marginBottom: '15px',
|
||||
padding: '10px',
|
||||
backgroundColor: '#f5f5f5',
|
||||
borderRadius: '4px'
|
||||
}}>
|
||||
<div><strong>Dispatch Id:</strong> <span style={{fontSize:"12px"}}> {headerData.Dispatch_Id} </span> </div>
|
||||
<div><strong>Date & Time:</strong> <span style={{fontSize:"12px"}}> {headerData.dateTime} </span></div>
|
||||
<div><strong>From Branch:</strong> <span style={{fontSize:"12px"}}> {headerData.fromBranch} </span> </div>
|
||||
{/* <div><strong>dispatched By</strong> {headerData.Created_By}</div> */}
|
||||
</div>
|
||||
)}
|
||||
<StockReceived
|
||||
productDetails={productDetails}
|
||||
onDataChange={onDataChange}
|
||||
editable={true}
|
||||
/>
|
||||
|
||||
<div style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
paddingTop: "10px",
|
||||
flexDirection: "row-reverse"
|
||||
}}>
|
||||
<Buttons
|
||||
buttonText={'SUBMIT'}
|
||||
handleSubmit={onSubmit}
|
||||
color="901D77"
|
||||
icon={<ArrowRightOutlined />}
|
||||
>
|
||||
OPEN
|
||||
</Buttons>
|
||||
</div>
|
||||
</div>
|
||||
</DefaultModal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductDetailsModal;
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
.ReceivedStocksModalMaster {
|
||||
overflow: auto;
|
||||
scrollbar-width: thin;
|
||||
max-height: 70vh;
|
||||
width: 100%;
|
||||
.ant-modal .ant-modal-content {
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
background-clip: padding-box;
|
||||
border: 0;
|
||||
font-family: var(--HEADING_FONT_FAMILY);
|
||||
border-radius: 8px;
|
||||
box-shadow:
|
||||
0 6px 16px #00000014,
|
||||
0 3px 6px -4px #0000001f,
|
||||
0 9px 28px 8px #0000000d;
|
||||
pointer-events: auto;
|
||||
padding: 35px;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
.receive-stocks-modal {
|
||||
.ant-modal-content {
|
||||
padding: 24px !important;
|
||||
}
|
||||
table {
|
||||
border-spacing: unset !important;
|
||||
.ant-table-cell {
|
||||
font-size: 13px;
|
||||
font-family: 'Poppins', sans-serif;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-table
|
||||
.ant-table-container
|
||||
.ant-table-content
|
||||
table
|
||||
tbody
|
||||
tr:nth-child(odd):hover
|
||||
td {
|
||||
background-color: #cecece49 !important;
|
||||
font-weight: 400 !important;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
import React from 'react';
|
||||
import { DefaultModal } from './DefaultModal';
|
||||
import { Tables } from '../Tables/Table';
|
||||
import "./ReceivedStockModel.scss"
|
||||
const ReceivedStocksModal = ({
|
||||
open,
|
||||
onClose,
|
||||
columns,
|
||||
tableData,
|
||||
handlePageChange,
|
||||
customTable = false
|
||||
}) => {
|
||||
const renderCell = (column, row, index) => {
|
||||
if (column.render) {
|
||||
return column.render(row[column.dataIndex], row, index);
|
||||
}
|
||||
return row[column.dataIndex];
|
||||
};
|
||||
|
||||
return (
|
||||
<DefaultModal
|
||||
open={open}
|
||||
title="Receive Stocks"
|
||||
handleCancel={onClose}
|
||||
handleSubmit={onClose}
|
||||
width={900}
|
||||
footer={false}
|
||||
className={'receive-stocks-modal'}
|
||||
>
|
||||
<>
|
||||
|
||||
{!customTable && <div style={{overflowX:"auto"}}>
|
||||
|
||||
<Tables
|
||||
columns={columns}
|
||||
data={tableData}
|
||||
dataSource={tableData}
|
||||
pagination={handlePageChange}
|
||||
/>
|
||||
</div>}
|
||||
{
|
||||
customTable &&
|
||||
<div className="ReceivedStocksModalMaster" >
|
||||
<table style={{ width: "100%" }}>
|
||||
<thead>
|
||||
<tr>
|
||||
{columns.map((column) => (
|
||||
<th key={column.key} style={{ textAlign: column.align, width: column.width, backgroundColor: '#f0f8ff', fontFamily: "poppins", fontWeight: "450" }}>
|
||||
{column.title?.toUpperCase()}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{tableData.map((row, index) => (
|
||||
<tr key={row.key || index} style={{ fontSize: "13px" }}>
|
||||
{columns.map((column) => (
|
||||
<td key={column.key} style={{ textAlign: column.align, width: column.width }}>
|
||||
{renderCell(column, row, index)}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
</>
|
||||
|
||||
</DefaultModal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ReceivedStocksModal;
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
import {Messages as MessagesLibrary} from "../../../ownLib/my-ui-lib"
|
||||
export const Messages = MessagesLibrary
|
||||
|
||||
// import { useEffect } from 'react';
|
||||
// import { message } from 'antd';
|
||||
|
||||
// export const Messages = ({
|
||||
// messageType,
|
||||
// messageData,
|
||||
// duration,
|
||||
// onComplete,
|
||||
// }) => {
|
||||
// const [messageApi, contextHolder] = message.useMessage();
|
||||
|
||||
// useEffect(() => {
|
||||
// if (messageType)
|
||||
// messageApi
|
||||
// .open({
|
||||
// type: messageType,
|
||||
// content: messageData,
|
||||
// duration: duration ? duration : 3,
|
||||
// })
|
||||
// .then(() => {
|
||||
// if (onComplete) {
|
||||
// onComplete();
|
||||
// }
|
||||
// });
|
||||
// }, [messageType]);
|
||||
|
||||
// return <>{contextHolder}</>;
|
||||
// };
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
import React from "react";
|
||||
import { FiSend, FiCamera, FiPlus, FiUpload } from "react-icons/fi";
|
||||
import "./pedalOCR.scss";
|
||||
|
||||
const ActionButtons = ({ onOCR, onReset, onAdd, inputMethod }) => {
|
||||
const isCamera = inputMethod === 'camera';
|
||||
const handleLeftClick = onAdd || onReset;
|
||||
|
||||
return (
|
||||
<div className="action-buttons">
|
||||
<button onClick={handleLeftClick} className="action-buttons__btn action-buttons__btn--clear">
|
||||
{isCamera ? <FiCamera className="action-buttons__icon" /> : <FiUpload className="action-buttons__icon" />}
|
||||
<span className="action-buttons__text action-buttons__text--mobile">
|
||||
{isCamera ? 'Scan More' : 'Upload More'}
|
||||
</span>
|
||||
<span className="action-buttons__text action-buttons__text--desktop">
|
||||
{isCamera ? 'Scan More Images' : 'Upload More Images'}
|
||||
</span>
|
||||
</button>
|
||||
<button onClick={onOCR} className="action-buttons__btn action-buttons__btn--process">
|
||||
<FiSend className="action-buttons__icon" />
|
||||
<span className="action-buttons__text action-buttons__text--mobile">Process</span>
|
||||
<span className="action-buttons__text action-buttons__text--desktop">Process Images</span>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ActionButtons;
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
import React, { useState, useEffect, forwardRef, useImperativeHandle } from "react";
|
||||
import { FiCamera, FiImage, FiUpload } from "react-icons/fi";
|
||||
|
||||
const CameraInput = forwardRef(({ fileRef, onFileSelect }, ref) => {
|
||||
const [isMobile, setIsMobile] = useState(false);
|
||||
const cameraRef = React.useRef(null);
|
||||
const fileUploadRef = React.useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const checkMobile = () => {
|
||||
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
||||
};
|
||||
setIsMobile(checkMobile());
|
||||
}, []);
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
openAny: () => {
|
||||
if (isMobile) {
|
||||
cameraRef.current && cameraRef.current.click();
|
||||
} else {
|
||||
fileRef && fileRef.current && fileRef.current.click();
|
||||
}
|
||||
},
|
||||
openCamera: () => cameraRef.current && cameraRef.current.click(),
|
||||
openUpload: () => fileUploadRef.current && fileUploadRef.current.click(),
|
||||
openFileRef: () => fileRef && fileRef.current && fileRef.current.click(),
|
||||
}));
|
||||
|
||||
const buttonStyle = {
|
||||
padding: "12px 24px",
|
||||
fontSize: 14,
|
||||
fontWeight: 500,
|
||||
cursor: "pointer",
|
||||
marginTop: 10,
|
||||
backgroundColor: "#1890ff",
|
||||
color: "#fff",
|
||||
border: "none",
|
||||
borderRadius: 8,
|
||||
boxShadow: "0 2px 8px rgba(24, 144, 255, 0.3)",
|
||||
transition: "all 0.3s ease",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
gap: 8,
|
||||
width: "100%",
|
||||
maxWidth: 280,
|
||||
margin: "10px auto"
|
||||
};
|
||||
|
||||
if (isMobile) {
|
||||
return (
|
||||
<>
|
||||
<input
|
||||
ref={cameraRef}
|
||||
type="file"
|
||||
accept="image/*"
|
||||
capture="environment"
|
||||
multiple
|
||||
hidden
|
||||
onChange={onFileSelect}
|
||||
/>
|
||||
<input
|
||||
ref={fileUploadRef}
|
||||
type="file"
|
||||
accept="image/*"
|
||||
multiple
|
||||
hidden
|
||||
onChange={onFileSelect}
|
||||
/>
|
||||
<div style={{ display: "flex", flexDirection: "row", gap: 8, padding: "0 8px" }}>
|
||||
<button
|
||||
onClick={() => cameraRef.current.click()}
|
||||
style={{
|
||||
...buttonStyle,
|
||||
backgroundColor: "#52c41a",
|
||||
fontSize: 12,
|
||||
padding: "10px 12px",
|
||||
whiteSpace: "nowrap",
|
||||
flex: 1
|
||||
}}
|
||||
onMouseOver={(e) => {
|
||||
e.target.style.backgroundColor = "#389e0d";
|
||||
e.target.style.transform = "translateY(-2px)";
|
||||
}}
|
||||
onMouseOut={(e) => {
|
||||
e.target.style.backgroundColor = "#52c41a";
|
||||
e.target.style.transform = "translateY(0)";
|
||||
}}
|
||||
>
|
||||
<FiCamera size={16} />
|
||||
<span>Camera</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => fileUploadRef.current.click()}
|
||||
style={{
|
||||
...buttonStyle,
|
||||
fontSize: 12,
|
||||
padding: "10px 12px",
|
||||
whiteSpace: "nowrap",
|
||||
flex: 1
|
||||
}}
|
||||
onMouseOver={(e) => {
|
||||
e.target.style.backgroundColor = "#096dd9";
|
||||
e.target.style.transform = "translateY(-2px)";
|
||||
}}
|
||||
onMouseOut={(e) => {
|
||||
e.target.style.backgroundColor = "#1890ff";
|
||||
e.target.style.transform = "translateY(0)";
|
||||
}}
|
||||
>
|
||||
<FiUpload size={16} />
|
||||
<span>Gallery</span>
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<input
|
||||
ref={fileRef}
|
||||
type="file"
|
||||
accept="image/*"
|
||||
capture="environment"
|
||||
multiple
|
||||
hidden
|
||||
onChange={onFileSelect}
|
||||
/>
|
||||
<button
|
||||
onClick={() => fileRef.current.click()}
|
||||
style={buttonStyle}
|
||||
onMouseOver={(e) => {
|
||||
e.target.style.backgroundColor = "#096dd9";
|
||||
e.target.style.transform = "translateY(-2px)";
|
||||
}}
|
||||
onMouseOut={(e) => {
|
||||
e.target.style.backgroundColor = "#1890ff";
|
||||
e.target.style.transform = "translateY(0)";
|
||||
}}
|
||||
>
|
||||
{/* <FiCamera size={20} /> */}
|
||||
<span style={{ fontFamily: "Poppins", fontWeight: "400" }}>Add Images</span>
|
||||
<FiImage size={18} />
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
export default CameraInput;
|
||||
|
|
@ -0,0 +1,222 @@
|
|||
import React, { useState, useRef, useEffect } from "react";
|
||||
import ReactCrop from "react-image-crop";
|
||||
import "react-image-crop/dist/ReactCrop.css";
|
||||
import { FiX, FiScissors } from "react-icons/fi";
|
||||
|
||||
const ResizableCropper = ({ imageSrc, onCropComplete, onCancel, onNext, currentIndex, total }) => {
|
||||
const [crop, setCrop] = useState({ unit: "%", width: 80, height: 100, aspect: 4 / 5 });
|
||||
const [completedCrop, setCompletedCrop] = useState(null);
|
||||
const [screenSize, setScreenSize] = useState('desktop');
|
||||
const imgRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const updateScreenSize = () => {
|
||||
const width = window.innerWidth;
|
||||
if (width <= 480) setScreenSize('mobile');
|
||||
else if (width <= 768) setScreenSize('tablet');
|
||||
else if (width <= 1024) setScreenSize('laptop');
|
||||
else setScreenSize('desktop');
|
||||
};
|
||||
|
||||
updateScreenSize();
|
||||
window.addEventListener('resize', updateScreenSize);
|
||||
return () => window.removeEventListener('resize', updateScreenSize);
|
||||
}, []);
|
||||
|
||||
// Convert crop to base64 image
|
||||
const getCroppedImage = () => {
|
||||
if (!imgRef.current || !completedCrop?.width || !completedCrop?.height) return null;
|
||||
|
||||
const canvas = document.createElement("canvas");
|
||||
const scaleX = imgRef.current.naturalWidth / imgRef.current.width;
|
||||
const scaleY = imgRef.current.naturalHeight / imgRef.current.height;
|
||||
|
||||
canvas.width = completedCrop.width * scaleX;
|
||||
canvas.height = completedCrop.height * scaleY;
|
||||
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.drawImage(
|
||||
imgRef.current,
|
||||
completedCrop.x * scaleX,
|
||||
completedCrop.y * scaleY,
|
||||
completedCrop.width * scaleX,
|
||||
completedCrop.height * scaleY,
|
||||
0,
|
||||
0,
|
||||
completedCrop.width * scaleX,
|
||||
completedCrop.height * scaleY
|
||||
);
|
||||
|
||||
return canvas.toDataURL("image/jpeg");
|
||||
};
|
||||
|
||||
const handleNext = () => {
|
||||
const cropped = getCroppedImage();
|
||||
if (cropped) onCropComplete(cropped);
|
||||
if (onNext) onNext();
|
||||
};
|
||||
|
||||
const getResponsiveStyles = () => {
|
||||
switch (screenSize) {
|
||||
case 'mobile':
|
||||
return {
|
||||
containerPadding: "12px",
|
||||
imagePadding: 8,
|
||||
maxHeight: "250px",
|
||||
buttonPadding: "14px 20px",
|
||||
fontSize: 13,
|
||||
iconSize: 16,
|
||||
gap: 8,
|
||||
direction: 'row',
|
||||
borderRadius: 8
|
||||
};
|
||||
case 'tablet':
|
||||
return {
|
||||
containerPadding: "16px",
|
||||
imagePadding: 12,
|
||||
maxHeight: "320px",
|
||||
buttonPadding: "12px 18px",
|
||||
fontSize: 13,
|
||||
iconSize: 16,
|
||||
gap: 10,
|
||||
direction: 'row',
|
||||
borderRadius: 10
|
||||
};
|
||||
case 'laptop':
|
||||
return {
|
||||
containerPadding: "18px",
|
||||
imagePadding: 14,
|
||||
maxHeight: "380px",
|
||||
buttonPadding: "12px 20px",
|
||||
fontSize: 14,
|
||||
iconSize: 16,
|
||||
gap: 12,
|
||||
direction: 'row',
|
||||
borderRadius: 12
|
||||
};
|
||||
default:
|
||||
return {
|
||||
containerPadding: "20px",
|
||||
imagePadding: 16,
|
||||
maxHeight: "400px",
|
||||
buttonPadding: "12px 20px",
|
||||
fontSize: 14,
|
||||
iconSize: 16,
|
||||
gap: 12,
|
||||
direction: 'row',
|
||||
borderRadius: 12
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const styles = getResponsiveStyles();
|
||||
|
||||
const buttonStyle = {
|
||||
padding: styles.buttonPadding,
|
||||
border: "none",
|
||||
borderRadius: 8,
|
||||
cursor: "pointer",
|
||||
fontSize: styles.fontSize,
|
||||
fontWeight: 500,
|
||||
transition: "all 0.3s ease",
|
||||
boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 6,
|
||||
width: screenSize === 'mobile' ? '100%' : 'auto',
|
||||
justifyContent: 'center',
|
||||
minHeight: screenSize === 'mobile' ? '48px' : 'auto'
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
textAlign: "center",
|
||||
marginTop: screenSize === 'mobile' ? 12 : 20,
|
||||
padding: styles.containerPadding,
|
||||
backgroundColor: "#f8f9fa",
|
||||
borderRadius: styles.borderRadius,
|
||||
margin: screenSize === 'mobile' ? '12px 8px' : '20px auto',
|
||||
maxWidth: screenSize === 'mobile' ? '100%' : '500px'
|
||||
}}>
|
||||
{/* {screenSize !== 'mobile' && (
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<h3 style={{ margin: 0, color: "#333", fontSize: screenSize === 'tablet' ? 16 : 18 }}>
|
||||
Crop Image {currentIndex + 1} of {total}
|
||||
</h3>
|
||||
</div>
|
||||
)} */}
|
||||
|
||||
<div style={{
|
||||
backgroundColor: "#fff",
|
||||
padding: styles.imagePadding,
|
||||
borderRadius: 8,
|
||||
boxShadow: "0 2px 8px rgba(0,0,0,0.1)",
|
||||
overflow: 'hidden'
|
||||
}}>
|
||||
{screenSize === 'mobile' && (
|
||||
<div style={{ marginBottom: 8, fontSize: 12, color: "#666" }}>
|
||||
Image {currentIndex + 1} of {total}
|
||||
</div>
|
||||
)}
|
||||
<ReactCrop
|
||||
crop={crop}
|
||||
onChange={(newCrop) => setCrop(newCrop)}
|
||||
onComplete={(newCrop) => setCompletedCrop(newCrop)}
|
||||
keepSelection={true}
|
||||
>
|
||||
<img
|
||||
ref={imgRef}
|
||||
src={imageSrc}
|
||||
alt="Preview"
|
||||
style={{
|
||||
maxWidth: "100%",
|
||||
maxHeight: styles.maxHeight,
|
||||
borderRadius: 4,
|
||||
touchAction: 'none'
|
||||
}}
|
||||
/>
|
||||
</ReactCrop>
|
||||
</div>
|
||||
|
||||
<div style={{
|
||||
marginTop: screenSize === 'mobile' ? 16 : 20,
|
||||
display: "flex",
|
||||
flexDirection: styles.direction,
|
||||
justifyContent: "center",
|
||||
gap: styles.gap,
|
||||
padding: screenSize === 'mobile' ? '0 4px' : '0'
|
||||
}}>
|
||||
<button
|
||||
onClick={onCancel}
|
||||
style={{
|
||||
...buttonStyle,
|
||||
backgroundColor: "#6c757d",
|
||||
color: "#fff",
|
||||
fontFamily: "Poppins"
|
||||
}}
|
||||
onMouseOver={(e) => e.target.style.backgroundColor = "#5a6268"}
|
||||
onMouseOut={(e) => e.target.style.backgroundColor = "#6c757d"}
|
||||
>
|
||||
<FiX size={styles.iconSize} />
|
||||
{screenSize === 'mobile' ? 'Cancel' : 'Cancel All'}
|
||||
</button>
|
||||
<button
|
||||
onClick={handleNext}
|
||||
style={{
|
||||
...buttonStyle,
|
||||
backgroundColor: "#1890ff",
|
||||
color: "#fff",
|
||||
fontFamily: "Poppins"
|
||||
}}
|
||||
onMouseOver={(e) => e.target.style.backgroundColor = "#096dd9"}
|
||||
onMouseOut={(e) => e.target.style.backgroundColor = "#1890ff"}
|
||||
>
|
||||
<FiScissors size={styles.iconSize} />
|
||||
{screenSize === 'mobile' ? 'Crop' : 'Crop '}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ResizableCropper;
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
import React, { useState, useRef, useEffect } from "react";
|
||||
import CameraInput from "./CameraInput";
|
||||
import ResizableCropper from "./CropperArea";
|
||||
import ThumbnailsList from "./ThumbnailsList";
|
||||
import ActionButtons from "./ActionButtons";
|
||||
import TipsSection from "./TipsSection";
|
||||
import "./pedalOCR.scss";
|
||||
|
||||
const MultiCameraCropOCR = ({ showTips, handleProcessMultipleOCR }) => {
|
||||
const fileRef = useRef(null);
|
||||
const cameraInputRef = useRef(null);
|
||||
const [isMobile, setIsMobile] = useState(false);
|
||||
const [images, setImages] = useState([]);
|
||||
const [currentIndex, setCurrentIndex] = useState(null);
|
||||
const [finalImages, setFinalImages] = useState([]);
|
||||
console.log(finalImages, "finalImages")
|
||||
// const [showTips, setShowTips] = useState(false);
|
||||
|
||||
const onFileSelect = (e) => {
|
||||
const files = Array.from(e.target.files);
|
||||
const newImages = files.map((file, idx) => {
|
||||
const id = Date.now() + idx;
|
||||
const reader = new FileReader();
|
||||
return new Promise((resolve) => {
|
||||
reader.onload = () => resolve({ id, src: reader.result });
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
});
|
||||
|
||||
Promise.all(newImages).then((imgs) => {
|
||||
setImages((prev) => [...prev, ...imgs]);
|
||||
setCurrentIndex((prev) => (prev === null ? 0 : prev));
|
||||
});
|
||||
};
|
||||
|
||||
const handleCropComplete = (croppedImage) => {
|
||||
setFinalImages((prev) => [...prev, croppedImage]);
|
||||
};
|
||||
|
||||
const handleRemoveImage = (index) => {
|
||||
setFinalImages((prev) => prev.filter((_, i) => i !== index));
|
||||
};
|
||||
|
||||
const handleRecropImage = (index) => {
|
||||
const imageToRecrop = finalImages[index];
|
||||
setFinalImages((prev) => prev.filter((_, i) => i !== index));
|
||||
// Add back to images for re-cropping
|
||||
const newImage = { id: Date.now(), src: imageToRecrop };
|
||||
setImages((prev) => [...prev, newImage]);
|
||||
setCurrentIndex(images.length);
|
||||
};
|
||||
|
||||
const handleSendToOCR = async () => {
|
||||
if (!finalImages.length) return;
|
||||
|
||||
const formDataArray = finalImages.map(base64 => {
|
||||
const byteString = atob(base64.split(',')[1]);
|
||||
const ab = new ArrayBuffer(byteString.length);
|
||||
const ia = new Uint8Array(ab);
|
||||
for (let i = 0; i < byteString.length; i++) {
|
||||
ia[i] = byteString.charCodeAt(i);
|
||||
}
|
||||
const blob = new Blob([ab], { type: 'image/jpeg' });
|
||||
const formData = new FormData();
|
||||
formData.append('image', blob, 'cropped.jpg');
|
||||
return formData;
|
||||
});
|
||||
|
||||
console.log(formDataArray, "formDataArray")
|
||||
handleProcessMultipleOCR(formDataArray)
|
||||
resetAll()
|
||||
};
|
||||
|
||||
const resetAll = () => {
|
||||
setImages([]);
|
||||
setFinalImages([]);
|
||||
setCurrentIndex(null);
|
||||
};
|
||||
|
||||
const handleAddMore = () => {
|
||||
if (cameraInputRef.current && cameraInputRef.current.openAny) {
|
||||
cameraInputRef.current.openAny();
|
||||
} else if (fileRef.current) {
|
||||
fileRef.current.click();
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const checkMobile = () => /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
||||
setIsMobile(checkMobile());
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="multi-camera-crop-ocr">
|
||||
<div>
|
||||
{showTips && <TipsSection />}
|
||||
</div>
|
||||
|
||||
{currentIndex !== null && images[currentIndex] && (
|
||||
<ResizableCropper
|
||||
imageSrc={images[currentIndex].src}
|
||||
currentIndex={currentIndex}
|
||||
total={images.length}
|
||||
onCropComplete={handleCropComplete}
|
||||
onCancel={resetAll}
|
||||
onNext={() => {
|
||||
if (currentIndex + 1 < images.length) {
|
||||
setCurrentIndex(currentIndex + 1);
|
||||
} else {
|
||||
setCurrentIndex(null);
|
||||
setImages([]);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{currentIndex === null && (
|
||||
<>
|
||||
<CameraInput ref={cameraInputRef} fileRef={fileRef} onFileSelect={onFileSelect} />
|
||||
|
||||
</>
|
||||
)}
|
||||
|
||||
{finalImages.length > 0 && currentIndex === null && (
|
||||
<>
|
||||
<h4>Cropped Images ({finalImages.length}):</h4>
|
||||
<ThumbnailsList
|
||||
images={finalImages}
|
||||
onRemove={handleRemoveImage}
|
||||
onRecrop={handleRecropImage}
|
||||
/>
|
||||
<ActionButtons onOCR={handleSendToOCR} onAdd={handleAddMore} inputMethod={isMobile ? 'camera' : 'upload'} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MultiCameraCropOCR;
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
import React from 'react';
|
||||
import './pedalOCR.scss';
|
||||
|
||||
const OCRLoader = ({ isVisible, imageCount }) => {
|
||||
if (!isVisible) return null;
|
||||
|
||||
return (
|
||||
<div className="ocr-loader">
|
||||
<div className="ocr-loader__content">
|
||||
<div className="ocr-loader__spinner"></div>
|
||||
|
||||
<h3 className="ocr-loader__title">
|
||||
🔍 Processing Images
|
||||
</h3>
|
||||
|
||||
<p className="ocr-loader__text">
|
||||
Analyzing {imageCount} image{imageCount > 1 ? 's' : ''}...
|
||||
</p>
|
||||
|
||||
<div className="ocr-loader__dots">
|
||||
{[1, 2, 3].map((dot) => (
|
||||
<div key={dot} className={`ocr-loader__dot ocr-loader__dot--${dot}`} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default OCRLoader;
|
||||
|
|
@ -0,0 +1,312 @@
|
|||
.tips-section {
|
||||
margin-bottom: 20px;
|
||||
background-color: #f6ffed;
|
||||
padding: 16px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #b7eb8f;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.tips-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.tips-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
margin: 0;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.tips-content {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.tip-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 8px;
|
||||
font-size: 13px;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.tip-verify {
|
||||
color: #ff4d4f;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tips-section-mobile {
|
||||
margin-bottom: 12px;
|
||||
background-color: #f6ffed;
|
||||
padding: 8px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #b7eb8f;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.tips-header-mobile {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
margin-bottom: 6px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tips-title-mobile {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.tips-grid-mobile {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 4px;
|
||||
font-size: 10px;
|
||||
|
||||
span {
|
||||
font-family: "Poppins";
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
.tips-verify-mobile {
|
||||
color: #ff4d4f;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
// ActionButtons Styles
|
||||
.action-buttons {
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
|
||||
@media (max-width: 480px) {
|
||||
flex-direction: row;
|
||||
gap: 8px;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
gap: 12px;
|
||||
padding: 0 6px;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
gap: 14px;
|
||||
padding: 0 7px;
|
||||
}
|
||||
}
|
||||
|
||||
.action-buttons__btn {
|
||||
padding: 12px 24px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-family: "Poppins";
|
||||
|
||||
@media (max-width: 480px) {
|
||||
padding: 10px 16px;
|
||||
font-size: 12px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
padding: 11px 20px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
padding: 12px 22px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
&--process {
|
||||
background-color: #1890ff;
|
||||
|
||||
&:hover {
|
||||
background-color: #096dd9;
|
||||
}
|
||||
}
|
||||
|
||||
&--clear {
|
||||
background-color: #6c757d;
|
||||
|
||||
&:hover {
|
||||
background-color: #5a6268;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.action-buttons__icon {
|
||||
margin-right: 6px;
|
||||
font-size: 16px;
|
||||
|
||||
@media (max-width: 480px) {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.action-buttons__text {
|
||||
&--mobile {
|
||||
display: none;
|
||||
|
||||
@media (max-width: 480px) {
|
||||
display: inline;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
&--desktop {
|
||||
display: inline;
|
||||
|
||||
@media (max-width: 480px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MultiCameraCropOCR Styles
|
||||
.multi-camera-crop-ocr {
|
||||
max-width: 500px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.multi-camera-crop-ocr__scanning-message {
|
||||
margin-top: 16px;
|
||||
padding: 12px;
|
||||
background-color: #f0f8ff;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: #1890ff;
|
||||
}
|
||||
// Global Poppins font for all PedalOCR components
|
||||
.tips-section,
|
||||
.tips-header,
|
||||
.tips-title,
|
||||
.tips-content,
|
||||
.tip-item,
|
||||
.tip-verify,
|
||||
.tips-section-mobile,
|
||||
.tips-header-mobile,
|
||||
.tips-title-mobile,
|
||||
.tips-grid-mobile,
|
||||
.tips-verify-mobile,
|
||||
.action-buttons,
|
||||
.action-buttons__btn,
|
||||
.action-buttons__text,
|
||||
.multi-camera-crop-ocr,
|
||||
.multi-camera-crop-ocr__scanning-message {
|
||||
font-family: "Poppins", sans-serif;
|
||||
}
|
||||
// OCRLoader Styles
|
||||
.ocr-loader {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
font-family: "Poppins", sans-serif;
|
||||
|
||||
&__content {
|
||||
background-color: #fff;
|
||||
padding: 32px;
|
||||
border-radius: 12px;
|
||||
text-align: center;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
&__spinner {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border: 4px solid #f3f3f3;
|
||||
border-top: 4px solid #1890ff;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
margin: 0 auto 20px;
|
||||
}
|
||||
|
||||
&__title {
|
||||
margin: 0 0 8px 0;
|
||||
color: #333;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
font-family: "Poppins", sans-serif;
|
||||
}
|
||||
|
||||
&__text {
|
||||
margin: 0 0 16px 0;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
font-family: "Poppins", sans-serif;
|
||||
}
|
||||
|
||||
&__dots {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
&__dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background-color: #1890ff;
|
||||
border-radius: 50%;
|
||||
animation: pulse 1.4s ease-in-out infinite both;
|
||||
|
||||
&--1 {
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
&--2 {
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
&--3 {
|
||||
animation-delay: 0.6s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 80%, 100% {
|
||||
transform: scale(0.8);
|
||||
opacity: 0.5;
|
||||
}
|
||||
40% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import React from "react";
|
||||
|
||||
const PreviewImage = ({ finalImage, onOCR, onReset }) => (
|
||||
<div style={{ marginTop: 20, textAlign: "center" }}>
|
||||
<img src={finalImage} alt="Cropped" style={{ width: "100%", borderRadius: 8 }} />
|
||||
<div style={{ marginTop: 10 }}>
|
||||
<button
|
||||
onClick={onOCR}
|
||||
style={{ padding: "10px 20px", backgroundColor: "#1890ff", color: "#fff", border: "none", borderRadius: 5, cursor: "pointer", marginRight: 10 }}
|
||||
>
|
||||
🔍 Send to OCR
|
||||
</button>
|
||||
<button
|
||||
onClick={onReset}
|
||||
style={{ padding: "10px 20px", backgroundColor: "#f5f5f5", border: "1px solid #ccc", borderRadius: 5, cursor: "pointer" }}
|
||||
>
|
||||
🔄 Reset
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default PreviewImage;
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
import React from "react";
|
||||
|
||||
const ThumbnailsList = ({ images, onRemove, onRecrop }) => (
|
||||
<div style={{ display: "flex", flexWrap: "wrap", gap: 10, marginTop: 10, }}>
|
||||
{images.map((img, idx) => (
|
||||
<div key={idx} style={{ position: "relative", cursor: "pointer" ,width:120 , height:120}}>
|
||||
<img
|
||||
src={img}
|
||||
alt={`Cropped ${idx}`}
|
||||
style={{ width: "100%", height: "100%", objectFit: "cover", borderRadius: 5 }}
|
||||
onClick={() => onRecrop && onRecrop(idx)}
|
||||
/>
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onRemove && onRemove(idx);
|
||||
}}
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: -5,
|
||||
right: -5,
|
||||
background: "red",
|
||||
color: "white",
|
||||
border: "none",
|
||||
borderRadius: "50%",
|
||||
width: 20,
|
||||
height: 20,
|
||||
fontSize: 12,
|
||||
cursor: "pointer"
|
||||
}}
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
export default ThumbnailsList;
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { FiInfo, FiImage, FiEyeOff, FiFileText, FiCheck } from "react-icons/fi";
|
||||
import "./PedalOCR.scss"
|
||||
|
||||
const TipsSection = () => {
|
||||
const [isMobile, setIsMobile] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const checkMobile = () => {
|
||||
return window.innerWidth <= 768 || /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
||||
};
|
||||
setIsMobile(checkMobile());
|
||||
|
||||
const handleResize = () => setIsMobile(checkMobile());
|
||||
window.addEventListener('resize', handleResize);
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
}, []);
|
||||
|
||||
if (isMobile) {
|
||||
return (
|
||||
<div className="tips-section-mobile">
|
||||
<div className="tips-header-mobile">
|
||||
<FiInfo size={12} color="#1890ff" />
|
||||
<span className="tips-title-mobile">Quick Tips</span>
|
||||
</div>
|
||||
<div className="tips-grid-mobile">
|
||||
<span>• Clear images</span>
|
||||
<span>• No blur/glare</span>
|
||||
<span>• Flat document</span>
|
||||
<span>• JPG, PNG only</span>
|
||||
<span className="tips-verify-mobile">• Verify before adding</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="tips-section">
|
||||
<div className="tips-header">
|
||||
<FiInfo size={16} color="#1890ff" />
|
||||
<h4 className="tips-title">Tips for Best Results</h4>
|
||||
</div>
|
||||
|
||||
<div className="tips-content">
|
||||
<div className="tip-item">
|
||||
<FiImage size={14} color="#52c41a" />
|
||||
<span>Upload clear, high-quality images</span>
|
||||
</div>
|
||||
<div className="tip-item">
|
||||
<FiEyeOff size={14} color="#52c41a" />
|
||||
<span>Avoid blur, shadows, and glare</span>
|
||||
</div>
|
||||
<div className="tip-item">
|
||||
<FiFileText size={14} color="#52c41a" />
|
||||
<span>Keep the document flat</span>
|
||||
</div>
|
||||
<div className="tip-item">
|
||||
<FiCheck size={14} color="#52c41a" />
|
||||
<span>Supported formats: JPG, PNG</span>
|
||||
</div>
|
||||
<div className="tip-item tip-verify">
|
||||
<FiInfo size={14} color="#ff4d4f" />
|
||||
<span>Verify results before adding to products</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TipsSection;
|
||||
|
|
@ -0,0 +1,187 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import { FiTrash2 } from 'react-icons/fi';
|
||||
|
||||
const ScannedProductTable = ({ data, editable, onDataChange }) => {
|
||||
const handleCellEdit = (categoryIndex, productIndex, field, value) => {
|
||||
|
||||
if (!editable || !onDataChange) return;
|
||||
|
||||
const newData = [...data];
|
||||
if (field === 'Category') {
|
||||
newData[categoryIndex].Category = value;
|
||||
} else {
|
||||
newData[categoryIndex].Products[productIndex][field] = value;
|
||||
}
|
||||
onDataChange(newData);
|
||||
};
|
||||
|
||||
const allProducts = useMemo(() =>
|
||||
data?.flatMap((category, categoryIndex) =>
|
||||
category.Products?.map((product, productIndex) => ({
|
||||
...product,
|
||||
categoryIndex,
|
||||
productIndex,
|
||||
categoryName: category.Category,
|
||||
uniqueId: `${categoryIndex}-${productIndex}`
|
||||
})) || []
|
||||
) || [], [data]
|
||||
);
|
||||
|
||||
const tableStyle = {
|
||||
width: '100%',
|
||||
borderCollapse: 'collapse',
|
||||
backgroundColor: '#fff',
|
||||
borderRadius: '8px',
|
||||
overflow: 'hidden',
|
||||
boxShadow: '0 2px 8px rgba(0,0,0,0.1)'
|
||||
};
|
||||
|
||||
const headerStyle = {
|
||||
backgroundColor: '#f8f9fa',
|
||||
border: '1px solid #e9ecef',
|
||||
padding: '12px 8px',
|
||||
fontWeight: 600,
|
||||
fontSize: '14px',
|
||||
color: '#0b0b0bff',
|
||||
textAlign: 'left'
|
||||
};
|
||||
|
||||
const cellStyle = {
|
||||
border: '1px solid #e9ecef',
|
||||
padding: '4px',
|
||||
backgroundColor: '#fff',
|
||||
transition: 'background-color 0.2s ease'
|
||||
};
|
||||
|
||||
const inputStyle = {
|
||||
width: '100%',
|
||||
border: '1px solid transparent',
|
||||
outline: 'none',
|
||||
padding: '8px',
|
||||
fontSize: '14px',
|
||||
backgroundColor: 'transparent',
|
||||
borderRadius: '4px',
|
||||
transition: 'all 0.2s ease'
|
||||
};
|
||||
|
||||
const editableInputStyle = {
|
||||
...inputStyle,
|
||||
backgroundColor: '#f8f9ff',
|
||||
border: '1px solid #d6e3ff',
|
||||
cursor: 'text'
|
||||
};
|
||||
|
||||
const handleDeleteProduct = (categoryIndex, productIndex) => {
|
||||
if (!editable || !onDataChange) return;
|
||||
const newData = [...data];
|
||||
newData[categoryIndex].Products.splice(productIndex, 1);
|
||||
onDataChange(newData);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
|
||||
<table style={tableStyle}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style={headerStyle}>Category</th>
|
||||
<th style={headerStyle}>Product</th>
|
||||
<th style={headerStyle}>MRP</th>
|
||||
<th style={headerStyle}>No of Units</th>
|
||||
<th style={headerStyle}>UOM</th>
|
||||
<th style={headerStyle}>Delete</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{allProducts.map((product) => (
|
||||
<tr key={product.uniqueId} style={{ ':hover': { backgroundColor: '#f8f9fa' } }}>
|
||||
<td style={cellStyle}>
|
||||
{editable ? (
|
||||
<input
|
||||
value={product.categoryName || ''}
|
||||
onChange={(e) => handleCellEdit(product.categoryIndex, product.productIndex, 'Category', e.target.value)}
|
||||
style={editableInputStyle}
|
||||
placeholder="Enter category"
|
||||
/>
|
||||
) : (
|
||||
<span style={{ padding: '8px', display: 'block' }}>{product.categoryName}</span>
|
||||
)}
|
||||
</td>
|
||||
<td style={cellStyle}>
|
||||
{editable ? (
|
||||
<input
|
||||
value={product.Product}
|
||||
onChange={(e) => handleCellEdit(product.categoryIndex, product.productIndex, 'Product', e.target.value)}
|
||||
style={editableInputStyle}
|
||||
placeholder="Enter product name"
|
||||
/>
|
||||
) : (
|
||||
<span style={{ padding: '8px', display: 'block' }}>{product.Product}</span>
|
||||
)}
|
||||
</td>
|
||||
<td style={cellStyle}>
|
||||
{editable ? (
|
||||
<input
|
||||
type="number"
|
||||
value={product.MRP}
|
||||
onChange={(e) => handleCellEdit(product.categoryIndex, product.productIndex, 'MRP', e.target.value)}
|
||||
style={editableInputStyle}
|
||||
placeholder="0.00"
|
||||
/>
|
||||
) : (
|
||||
<span style={{ padding: '8px', display: 'block', fontWeight: 500, color: '#28a745' }}>₹{product.MRP}</span>
|
||||
)}
|
||||
</td>
|
||||
<td style={cellStyle}>
|
||||
{editable ? (
|
||||
<input
|
||||
type="number"
|
||||
value={product.NoOfUnits}
|
||||
onChange={(e) => handleCellEdit(product.categoryIndex, product.productIndex, 'NoOfUnits', parseInt(e.target.value))}
|
||||
min="1"
|
||||
style={editableInputStyle}
|
||||
placeholder="1"
|
||||
/>
|
||||
) : (
|
||||
<span style={{ padding: '8px', display: 'block' }}>{product.NoOfUnits}</span>
|
||||
)}
|
||||
</td>
|
||||
<td style={cellStyle}>
|
||||
{editable ? (
|
||||
<input
|
||||
value={product.UOM}
|
||||
onChange={(e) => handleCellEdit(product.categoryIndex, product.productIndex, 'UOM', e.target.value)}
|
||||
style={editableInputStyle}
|
||||
placeholder="PCS"
|
||||
/>
|
||||
) : (
|
||||
<span style={{ padding: '8px', display: 'block' }}>{product.UOM}</span>
|
||||
)}
|
||||
</td>
|
||||
<td style={cellStyle}>
|
||||
{editable ? (
|
||||
<button
|
||||
onClick={() => handleDeleteProduct(product.categoryIndex, product.productIndex)}
|
||||
title="Delete"
|
||||
style={{
|
||||
background: 'transparent',
|
||||
border: 'none',
|
||||
cursor: 'pointer',
|
||||
color: '#e53935',
|
||||
padding: '8px',
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center'
|
||||
}}
|
||||
>
|
||||
<FiTrash2 />
|
||||
</button>
|
||||
) : null}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ScannedProductTable;
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import {ReprintTables as ReprintTablesLibrary } from "../../../ownLib/my-ui-lib"
|
||||
|
||||
export const ReprintTables = ReprintTablesLibrary
|
||||
// import { Table } from 'antd';
|
||||
|
||||
// export const ReprintTables = ({ columns, data, onChange, pagination }) => {
|
||||
// return (
|
||||
// <>
|
||||
// <Table
|
||||
// columns={columns}
|
||||
// dataSource={data}
|
||||
// onChange={onChange}
|
||||
// pagination={
|
||||
// pagination
|
||||
// ? false
|
||||
// : {
|
||||
// defaultPageSize: 10,
|
||||
// showSizeChanger: false,
|
||||
// hideOnSinglePage: true,
|
||||
// }
|
||||
// }
|
||||
// />
|
||||
// </>
|
||||
// );
|
||||
// };
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
import { Tables as TableLibrary } from "../../../ownLib/my-ui-lib"
|
||||
|
||||
export const Tables = TableLibrary
|
||||
|
||||
// import { Table } from 'antd';
|
||||
|
||||
// export const Tables = ({
|
||||
// columns,
|
||||
// data,
|
||||
// onChange,
|
||||
// pagination,
|
||||
// rowSelection,
|
||||
// rowClassName,
|
||||
// summary,
|
||||
// }) => {
|
||||
// return (
|
||||
// <>
|
||||
// <Table
|
||||
// columns={columns}
|
||||
// dataSource={data}
|
||||
// onChange={onChange}
|
||||
// summary={summary ? summary : null}
|
||||
// rowSelection={rowSelection ? rowSelection : null}
|
||||
// pagination={
|
||||
// pagination
|
||||
// ? {
|
||||
// onChange: pagination,
|
||||
// defaultPageSize: 10,
|
||||
// showSizeChanger: false,
|
||||
// hideOnSinglePage: true,
|
||||
// }
|
||||
// : false
|
||||
// }
|
||||
// rowClassName={rowClassName}
|
||||
// // pagination={
|
||||
// // pagination
|
||||
// // ? pagination
|
||||
// // : {
|
||||
// // defaultPageSize: 10,
|
||||
// // showSizeChanger: false,
|
||||
// // hideOnSinglePage: true,
|
||||
// // }
|
||||
// // }
|
||||
// />
|
||||
// </>
|
||||
// );
|
||||
// };
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
import {TooltipWrapper as TooltipWrapperLibrary} from "../../../ownLib/my-ui-lib"
|
||||
|
||||
const TooltipWrapper = TooltipWrapperLibrary
|
||||
|
||||
export default TooltipWrapper;
|
||||
// import React from 'react';
|
||||
// import { Tooltip } from 'antd';
|
||||
|
||||
// const TooltipWrapper = ({ children, title, isMobile, placement, onClick }) => {
|
||||
// if (isMobile) {
|
||||
// return children; // If isMobile is true, just render the children without a Tooltip
|
||||
// }
|
||||
|
||||
// return (
|
||||
// <Tooltip title={title} placement={placement} onClick={onClick}>
|
||||
// {children}
|
||||
// </Tooltip>
|
||||
// ); // Otherwise, wrap the children in Tooltip
|
||||
// };
|
||||
|
||||
// export default TooltipWrapper;
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
import React, { Component } from 'react';
|
||||
import { isMobile } from 'react-device-detect';
|
||||
import { FaWeight } from 'react-icons/fa';
|
||||
|
||||
class WeightScale extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
Finalresult: '',
|
||||
result: '',
|
||||
amtPerGram: 0,
|
||||
finalData: [],
|
||||
portValdata: null,
|
||||
};
|
||||
}
|
||||
|
||||
// this.myfun
|
||||
componentDidMount = async () => {
|
||||
this.portfun(this.props.portval);
|
||||
|
||||
if (this.props.WeightScale === false) {
|
||||
await port.close({ baudRate: 9600 });
|
||||
port.close(() => {
|
||||
connected = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
portfun = async (e) => {
|
||||
if (e === null) {
|
||||
const port = await navigator.serial.requestPort();
|
||||
if (port) {
|
||||
await this.props.setportfun(port);
|
||||
await this.myfun(port);
|
||||
} else {
|
||||
console.log('portnot closed', port);
|
||||
}
|
||||
} else {
|
||||
this.props.setportfun(e);
|
||||
this.myfun(e);
|
||||
}
|
||||
};
|
||||
|
||||
isFloat = (value) => {
|
||||
const numericValue = parseFloat(value);
|
||||
return !Number.isNaN(numericValue) && !Number.isInteger(numericValue);
|
||||
};
|
||||
|
||||
myfun = async (port) => {
|
||||
// const port = await navigator.serial.requestPort();
|
||||
if (port.readable === null) {
|
||||
await port.open({ baudRate: 9600 });
|
||||
}
|
||||
|
||||
while (port.readable) {
|
||||
if (!port.readable.locked) {
|
||||
const reader = port.readable.getReader();
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
const { value, done } = await reader.read();
|
||||
|
||||
if (done) {
|
||||
reader.releaseLock();
|
||||
break;
|
||||
}
|
||||
if (value) {
|
||||
await this.setState({
|
||||
result: await new TextDecoder('utf-8').decode(value),
|
||||
});
|
||||
if (
|
||||
this.isFloat(new TextDecoder('utf-8').decode(value)) === true
|
||||
) {
|
||||
await this.props.testfun(
|
||||
new TextDecoder('utf-8').decode(value)
|
||||
);
|
||||
}
|
||||
|
||||
if (this.props.portclose === false) {
|
||||
reader.cancel();
|
||||
await port.close({ baudRate: 9600 });
|
||||
port.close(() => {
|
||||
connected = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.message === 'The device has been lost.') {
|
||||
this.props.msg({ type: 'error', msg: 'Weight Scale disconnect' });
|
||||
// Optionally, you can attempt to reopen the port or take other actions
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
openport = async () => {
|
||||
const port = await navigator.serial.requestPort();
|
||||
if (port) {
|
||||
this.props.setportfun(port);
|
||||
}
|
||||
|
||||
if (port.readable === null) {
|
||||
await port.open({ baudRate: 9600 });
|
||||
}
|
||||
|
||||
while (port.readable) {
|
||||
if (!port.readable.locked) {
|
||||
const reader = port.readable.getReader();
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
const { value, done } = await reader.read();
|
||||
|
||||
if (done) {
|
||||
reader.releaseLock();
|
||||
break;
|
||||
}
|
||||
if (value) {
|
||||
await this.setState({
|
||||
result: await new TextDecoder('utf-8').decode(value),
|
||||
});
|
||||
|
||||
if (
|
||||
this.isFloat(new TextDecoder('utf-8').decode(value)) === true
|
||||
) {
|
||||
await this.props.testfun(
|
||||
new TextDecoder('utf-8').decode(value)
|
||||
);
|
||||
}
|
||||
|
||||
if (this.props.portclose === false) {
|
||||
reader.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
componentDidUpdate = async () => {
|
||||
if (this.props.portclose === true) this.portfun(this.props.portval);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={{ display: 'inline' }}>
|
||||
{/* <FaWeight
|
||||
style={{fontSize: "22px", cursor: "pointer", margin: "0px 0px 5px 16px",color: "black"}}
|
||||
onClick={()=>this.openport()}
|
||||
/> */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default WeightScale;
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
|
||||
import { axiosRetailInstanceData } from '../AuthenicationToken/AuthenticationToken';
|
||||
|
||||
export const getEmpAccess = createAsyncThunk(
|
||||
'Home/getEmpAccess',
|
||||
async (data) => {
|
||||
if (
|
||||
data?.CompId != null &&
|
||||
data?.CompId != undefined &&
|
||||
data?.BranchId != null &&
|
||||
data?.BranchId != undefined &&
|
||||
data?.EmpId != null &&
|
||||
data?.EmpId != undefined &&
|
||||
data?.AppId != null &&
|
||||
data?.AppId != undefined
|
||||
) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/empAccess?CompId=${data?.CompId}&BranchId=${data?.BranchId}&EmpId=${data?.EmpId}&AppId=${data?.AppId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const initialState = {
|
||||
breadCrumb: [],
|
||||
RedirectStatus: false,
|
||||
EmpAccessDetail:[]
|
||||
};
|
||||
|
||||
const centerPageSlice = createSlice({
|
||||
name: 'centerPage',
|
||||
initialState,
|
||||
|
||||
reducers: {
|
||||
changeBreadCrumb: (state, action) => {
|
||||
const { items } = action?.payload;
|
||||
state.breadCrumb = items;
|
||||
},
|
||||
emptyBreadCrumb: (state, action) => {
|
||||
state.breadCrumb = [];
|
||||
},
|
||||
ChangeRedirectStatus: (state, action) => {
|
||||
state.RedirectStatus = action?.payload;
|
||||
},
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
builder.addCase(getEmpAccess.fulfilled, (state, action) => {
|
||||
if (action?.payload?.data?.statusCode === 1) {
|
||||
state.EmpAccessDetail = action?.payload?.data?.data[0]?.EmpAccessDetails;
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
export const { changeBreadCrumb, emptyBreadCrumb, ChangeRedirectStatus } =
|
||||
centerPageSlice.actions;
|
||||
|
||||
export const breadCrumbSelector = (state) => state.centerPage?.breadCrumb;
|
||||
export const GlobalRedirectStatus = (state) => state.centerPage?.RedirectStatus;
|
||||
export const GlobalEmpAccessDetail = (state)=>state.centerPage?.EmpAccessDetail
|
||||
export default centerPageSlice.reducer;
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
import axios from 'axios';
|
||||
import {
|
||||
getSession,
|
||||
clearSession,
|
||||
TokendecryptedValuesFun,
|
||||
} from '../../Services/Others';
|
||||
|
||||
const apiUrl = import.meta.env.ENV_API_URL;
|
||||
const apiCommonUrl = import.meta.env.ENV_API_URL_COMMON;
|
||||
const subDirectory = import.meta.env.ENV_COMMON_BASE_URL;
|
||||
const EmailApiUrl = import.meta.env.ENV_EMAIL_API;
|
||||
const apiRetailOcr = import.meta.env.ENV_API_URL_OCR
|
||||
|
||||
const axiosRetailInstance = axios.create({
|
||||
baseURL: apiUrl,
|
||||
});
|
||||
|
||||
const axiosCommonInstance = axios.create({
|
||||
baseURL: apiCommonUrl,
|
||||
});
|
||||
const axiosEmail_SMS = axios.create({
|
||||
baseURL: EmailApiUrl,
|
||||
});
|
||||
const axiosRetailOcr = axios.create({
|
||||
baseURL: apiRetailOcr,
|
||||
});
|
||||
|
||||
const getToken = () => {
|
||||
return new Promise((resolve) => {
|
||||
let token = sessionStorage.getItem('auth');
|
||||
|
||||
if (token) {
|
||||
resolve(token);
|
||||
} else {
|
||||
const tokenInterval = setInterval(() => {
|
||||
token = sessionStorage.getItem('auth');
|
||||
if (token) {
|
||||
clearInterval(tokenInterval);
|
||||
resolve(token);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const addAuthHeader = async (config) => {
|
||||
const token = await getToken();
|
||||
if (token) {
|
||||
config.headers['Authorization'] = `Bearer ${token}`;
|
||||
console.log(config, 'Request config after adding token');
|
||||
} else {
|
||||
console.warn('Token is still not available.');
|
||||
}
|
||||
let encryptedMobileno = sessionStorage.getItem('MobileNo');
|
||||
let encryptedUserId = sessionStorage.getItem('UserId');
|
||||
let encryptedLoginType = TokendecryptedValuesFun(
|
||||
sessionStorage.getItem('LoginType')
|
||||
);
|
||||
console.log(
|
||||
'encryptedLoginType',
|
||||
encryptedLoginType,
|
||||
TokendecryptedValuesFun(encryptedMobileno)
|
||||
);
|
||||
|
||||
// let Mobileno = encryptedUserId && encryptedLoginType != "Kiosk" ? TokendecryptedValuesFun(encryptedMobileno) : '1000000001';
|
||||
let Mobileno = encryptedUserId
|
||||
? TokendecryptedValuesFun(encryptedMobileno)
|
||||
: '1000000001';
|
||||
|
||||
console.warn('Mobileno is still not available.');
|
||||
config.headers['Mobileno'] = Mobileno;
|
||||
return config;
|
||||
};
|
||||
|
||||
axiosRetailInstance.interceptors.request.use(addAuthHeader, (error) => {
|
||||
console.error('Error in request interceptor:', error);
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
axiosCommonInstance.interceptors.request.use(addAuthHeader, (error) => {
|
||||
console.error('Error in request interceptor:', error);
|
||||
return Promise.reject(error);
|
||||
});
|
||||
axiosEmail_SMS.interceptors.request.use(addAuthHeader, (error) => {
|
||||
console.error('Error in request interceptor:', error);
|
||||
return Promise.reject(error);
|
||||
});
|
||||
axiosRetailOcr.interceptors.request.use(
|
||||
(config) => {
|
||||
// no auth header needed
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error in request interceptor:', error);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
function showNotification(message) {
|
||||
const notification = document.createElement('div');
|
||||
notification.innerText = message;
|
||||
notification.style.cssText = `
|
||||
position: fixed;
|
||||
top: 10%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background-color: #f03e3e;
|
||||
color: white;
|
||||
padding: 15px 30px;
|
||||
border-radius: 8px;
|
||||
font-family: Arial, sans-serif;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||
z-index: 1000;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
`;
|
||||
|
||||
document.body.appendChild(notification);
|
||||
|
||||
// Show the notification
|
||||
setTimeout(() => {
|
||||
notification.style.opacity = 1;
|
||||
}, 10);
|
||||
|
||||
// Remove the notification after 3 seconds
|
||||
setTimeout(() => {
|
||||
notification.style.opacity = 0;
|
||||
setTimeout(() => notification.remove(), 300);
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
const responseErrorHandler = async (error) => {
|
||||
if (error.response && error.response.status === 401) {
|
||||
showNotification(
|
||||
'Your session has expired. Please log in again to continue.'
|
||||
);
|
||||
|
||||
setTimeout(() => {
|
||||
if (getSession('UserId')) {
|
||||
const Generate = 'N';
|
||||
fetch(`${apiCommonUrl}/Logout`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: sessionStorage.getItem('auth')
|
||||
? sessionStorage.getItem('auth')
|
||||
: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
|
||||
Mobileno: getSession('MobileNo')
|
||||
? getSession('MobileNo')
|
||||
: '1000000001',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
UserId: getSession('UserId'),
|
||||
Generate: Generate,
|
||||
RequestMode: 'DW',
|
||||
}),
|
||||
})
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`Error: ${response.status}`);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then((data) => {
|
||||
if (data?.statusCode === 1) {
|
||||
clearSession();
|
||||
window.location.href = `${subDirectory}`;
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
}
|
||||
// else {
|
||||
// clearSession();
|
||||
// window.location.href = `${subDirectory}`;
|
||||
// }
|
||||
}, 2000);
|
||||
}
|
||||
// else {
|
||||
// alert("An error occurred. Please try again later.");
|
||||
// }
|
||||
return Promise.reject(error);
|
||||
};
|
||||
|
||||
axiosCommonInstance.interceptors.response.use(
|
||||
(response) => response, // On success, just return the response
|
||||
// responseErrorHandler // Handle errors
|
||||
);
|
||||
|
||||
axiosRetailInstance.interceptors.response.use(
|
||||
(response) => response, // On success, just return the response
|
||||
// responseErrorHandler // Handle errors
|
||||
);
|
||||
|
||||
export const axiosRetailInstanceData = axiosRetailInstance;
|
||||
export const axiosCommonInstanceData = axiosCommonInstance;
|
||||
export const axiosEmail_SMSData = axiosEmail_SMS;
|
||||
export const axiosRetailOcrData = axiosRetailOcr;
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
import { createAsyncThunk } from '@reduxjs/toolkit';
|
||||
import { axiosRetailInstanceData } from '../AuthenicationToken/AuthenticationToken';
|
||||
|
||||
export const getBarcodeSessionsIDs = createAsyncThunk(
|
||||
'barcode/getBarcodeSessionsIDs',
|
||||
async () => {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/ConfigMaster?typeName=Barcode Size`
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const getBarcodeComponent = createAsyncThunk(
|
||||
'barcode/getBarcodeComponent',
|
||||
async () => {
|
||||
return await axiosRetailInstanceData.get(`/BarcodeComponent`);
|
||||
}
|
||||
);
|
||||
|
||||
export const getBarcodeComponentsBasedOnSessionId = createAsyncThunk(
|
||||
'barcode/getBarcodeComponent',
|
||||
async (sessionId) => {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/BarcodeComponent?sessionId=${sessionId}&activeStatus=A`
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const putBarcodeComponent = createAsyncThunk(
|
||||
'barcode/putBarcodeComponent',
|
||||
async (putData) => {
|
||||
return await axiosRetailInstanceData.put('/BarcodeComponent', putData);
|
||||
}
|
||||
);
|
||||
|
||||
export const postBarcodeComponent = createAsyncThunk(
|
||||
'barcode/postBarcodeComponent',
|
||||
async (postData) => {
|
||||
return await axiosRetailInstanceData.post('/BarcodeComponent', postData);
|
||||
}
|
||||
);
|
||||
|
||||
export const deleteBarcodeComponent = createAsyncThunk(
|
||||
'barcode/deleteBarcodeComponent',
|
||||
async ({ componentId, updatedBy, activeStatus }) => {
|
||||
return await axiosRetailInstanceData.delete(
|
||||
`/BarcodeComponent?componentId=${componentId}&updatedBy=${updatedBy}&activeStatus=${activeStatus}`
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const getBarcodeTemplate = createAsyncThunk(
|
||||
'barcode/getBarcodeComponent',
|
||||
async ({ compId, appId, branchId }) => {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/BarcodeTemplate?compId=${compId}&appId=${appId}&branchId=${branchId}`
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const putBarcodeTemplate = createAsyncThunk(
|
||||
'barcode/putBarcodeComponent',
|
||||
async (putData) => {
|
||||
return await axiosRetailInstanceData.put('/BarcodeTemplate', putData);
|
||||
}
|
||||
);
|
||||
|
||||
export const postBarcodeTemplate = createAsyncThunk(
|
||||
'barcode/postBarcodeComponent',
|
||||
async (postData) => {
|
||||
return await axiosRetailInstanceData.post('/BarcodeTemplate', postData);
|
||||
}
|
||||
);
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
|
||||
import { create } from 'zustand';
|
||||
|
||||
// Utility: format date as YYYY-MM-DD
|
||||
const formatDate = (date) => {
|
||||
const d = new Date(date);
|
||||
const year = d.getFullYear();
|
||||
const month = String(d.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(d.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
};
|
||||
|
||||
// Utility: get today's and tomorrow's date
|
||||
const today = new Date();
|
||||
const tomorrow = new Date();
|
||||
tomorrow.setDate(today.getDate() + 1);
|
||||
|
||||
export const useDateStore = create((set) => ({
|
||||
selectedDate: [formatDate(today), formatDate(today)], // initial 2 dates
|
||||
isBulk: false,
|
||||
setSelectedDate: (dates) => {
|
||||
// Always store as an array in YYYY-MM-DD format
|
||||
const formattedDates = (Array.isArray(dates) ? dates : [dates]).map(formatDate);
|
||||
console.log(formattedDates, "dates useDateStore");
|
||||
set({ selectedDate: formattedDates });
|
||||
},
|
||||
invoiceDate: formatDate(today), // single date instead of array
|
||||
|
||||
setInvoiceDate: (date) => {
|
||||
// Store as single date in YYYY-MM-DD format
|
||||
const formattedDate = formatDate(date);
|
||||
console.log(formattedDate, "date useDateStore");
|
||||
set({ invoiceDate: formattedDate });
|
||||
},
|
||||
clearInvoiceDate: () => {
|
||||
// Reset to today's date in YYYY-MM-DD format
|
||||
const t1 = formatDate(new Date());
|
||||
set({ invoiceDate: t1 });
|
||||
},
|
||||
clearDates: () => {
|
||||
// Reset to current + next day in YYYY-MM-DD format
|
||||
const t1 = formatDate(new Date());
|
||||
set({ selectedDate: [t1, t1] });
|
||||
},
|
||||
|
||||
setIsBulk: (value) => set({ isBulk: value }),
|
||||
}));
|
||||
|
|
@ -0,0 +1,523 @@
|
|||
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
|
||||
import axios from 'axios';
|
||||
import {
|
||||
axiosRetailInstanceData,
|
||||
axiosCommonInstanceData,
|
||||
} from '../../AuthenicationToken/AuthenticationToken';
|
||||
import { getSession } from '../../../Services/Others';
|
||||
import { getSelfBooking } from '../../TableBooking/TableBooking';
|
||||
const Paymentdevice_POST_URL = import.meta.env.ENV_PAYMENT_DEVICE_URL;
|
||||
const Paymentdevice_GET_URL = import.meta.env.ENV_PAYMENT_STATUS_GET_URL;
|
||||
const apiCommonUrl = import.meta.env.ENV_API_URL_COMMON;
|
||||
|
||||
export const getProductCategories = createAsyncThunk(
|
||||
'KioskBookingData/getLayoutCategories',
|
||||
async ({ CompId, BranchId, AppId }) => {
|
||||
if (
|
||||
CompId != null &&
|
||||
CompId != undefined &&
|
||||
BranchId != null &&
|
||||
BranchId != undefined &&
|
||||
AppId != null &&
|
||||
AppId != undefined
|
||||
) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/productCat?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const getPaymentVerfication = createAsyncThunk(
|
||||
'KioskBookingData/getLayoutCategories',
|
||||
async (OrderId) => {
|
||||
if (
|
||||
OrderId != null &&
|
||||
OrderId != undefined
|
||||
) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/PaymentPageStatus?orderId=${OrderId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
export const getCustomerBooking = createAsyncThunk(
|
||||
'self/CustomerBookings',
|
||||
({ AppId, CompId, BranchId, CustId, FromDate, ToDate }) => {
|
||||
if (CompId != null && CompId != undefined && BranchId != null && BranchId != undefined && AppId != null && AppId != undefined && CustId != null && CustId != undefined && FromDate != null && FromDate != undefined && ToDate != null && ToDate != undefined) {
|
||||
return axiosRetailInstanceData.get(`/CustomerBookings?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}&CustId=${CustId}&fromDate=${FromDate}&toDate=${ToDate}`);
|
||||
}
|
||||
else if (CompId != null && CompId != undefined && BranchId != null && BranchId != undefined && AppId != null && AppId != undefined && CustId != null && CustId != undefined) {
|
||||
return axiosRetailInstanceData.get(`/CustomerBookings?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}&CustId=${CustId}`);
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
// get /CustomerMembership
|
||||
export const getCustomerMembership = createAsyncThunk(
|
||||
'self/CustomerMembership',
|
||||
({ AppId, CompId, BranchId, CustId }) => {
|
||||
if (CompId != null && CompId != undefined && BranchId != null && BranchId != undefined && AppId != null && AppId != undefined && CustId != null && CustId != undefined) {
|
||||
return axiosRetailInstanceData.get(`/CustomerMembership?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}&CustId=${CustId}`);
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
export const getProductCardListKiosk = createAsyncThunk(
|
||||
'KioskBookingData/getProductCardListKiosk',
|
||||
async ({ CompId, BranchId, AppId, ProdCat, ProdSubCat, Search, Dates,fromDate,toDate }) => {
|
||||
|
||||
if (
|
||||
CompId != null &&
|
||||
CompId != undefined &&
|
||||
BranchId != null &&
|
||||
BranchId != undefined &&
|
||||
AppId != null &&
|
||||
AppId != undefined &&
|
||||
ProdCat != null &&
|
||||
ProdCat != undefined && Search != null && Search != undefined && Search != ""
|
||||
) {
|
||||
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/productCardList?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}&ProdName=${encodeURIComponent(Search)}`
|
||||
);
|
||||
}
|
||||
else if (
|
||||
CompId != null &&
|
||||
CompId != undefined &&
|
||||
BranchId != null &&
|
||||
BranchId != undefined &&
|
||||
AppId != null &&
|
||||
AppId != undefined &&
|
||||
ProdSubCat != null &&
|
||||
ProdSubCat != undefined &&
|
||||
fromDate != null &&
|
||||
fromDate != undefined &&
|
||||
toDate != null &&
|
||||
toDate != undefined
|
||||
) {
|
||||
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/productCardList?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}&ProdSubCat=${ProdSubCat}&fromDate=${fromDate}&toDate=${toDate}`
|
||||
);
|
||||
}
|
||||
else if (
|
||||
CompId != null &&
|
||||
CompId != undefined &&
|
||||
BranchId != null &&
|
||||
BranchId != undefined &&
|
||||
AppId != null &&
|
||||
AppId != undefined &&
|
||||
ProdSubCat != null &&
|
||||
ProdSubCat != undefined &&
|
||||
Dates != null && Dates != undefined
|
||||
) {
|
||||
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/productCardList?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}&ProdSubCat=${ProdSubCat}&date=${Dates}`
|
||||
);
|
||||
}
|
||||
else if (
|
||||
CompId != null &&
|
||||
CompId != undefined &&
|
||||
BranchId != null &&
|
||||
BranchId != undefined &&
|
||||
AppId != null &&
|
||||
AppId != undefined &&
|
||||
ProdSubCat != null &&
|
||||
ProdSubCat != undefined
|
||||
|
||||
) {
|
||||
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/productCardList?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}&ProdSubCat=${ProdSubCat}`
|
||||
);
|
||||
}
|
||||
else {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/ProductCardList?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}&prodCat=${ProdCat}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
export const PostKioskBookingData = createAsyncThunk(
|
||||
'BookingData/PostKioskBookingdata',
|
||||
async (postData) => {
|
||||
return await axiosRetailInstanceData.post(`/KioskBooking`, postData);
|
||||
}
|
||||
);
|
||||
export const PostSelfBookingCustomer = createAsyncThunk(
|
||||
'BookingData/PostKioskBookingdata',
|
||||
async (postData) => {
|
||||
return await axiosRetailInstanceData.post(`/CustomerSelfBooking`, postData);
|
||||
}
|
||||
);
|
||||
export const PutKioskBookingData = createAsyncThunk(
|
||||
'BookingData/PutKioskBookingdata',
|
||||
async (putData) => {
|
||||
return await axiosRetailInstanceData.put(`/KioskBooking`, putData);
|
||||
}
|
||||
);
|
||||
|
||||
export const PutBookingPaymentStatusChange = createAsyncThunk(
|
||||
'BookingData/PutBookingPaymentStatusChange',
|
||||
async (putData) => {
|
||||
return await axiosRetailInstanceData.put(`/BookingPaymentStatus`, putData);
|
||||
}
|
||||
);
|
||||
// http://192.168.1.37:8001/ProductCardList?request.compId=1&request.branchId=1&request.appId=2&request.prodCat=224
|
||||
|
||||
export const getCompanyData = createAsyncThunk(
|
||||
'appAccess/getCompanyData',
|
||||
async ({ CompId }) => {
|
||||
if (CompId != null && CompId != undefined) {
|
||||
return await axios.get(`${apiCommonUrl}/company?CompId=${CompId}`);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const getPaymentGatewayConfig = createAsyncThunk(
|
||||
'getPaymentGatewayConfig',
|
||||
async ({ CompId, AppId, BranchId }) => {
|
||||
if (
|
||||
CompId != null &&
|
||||
CompId != undefined &&
|
||||
BranchId != null &&
|
||||
BranchId != undefined &&
|
||||
AppId != null &&
|
||||
AppId != undefined
|
||||
) {
|
||||
return await axiosCommonInstanceData.get(
|
||||
`/PaymentGatewayConfig?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const getPaymentGatewayDetails = createAsyncThunk(
|
||||
'getPaymentGatewayDetails',
|
||||
async ({ CompId, AppId, BranchId, DetailType }) => {
|
||||
if (
|
||||
CompId != null &&
|
||||
CompId != undefined &&
|
||||
BranchId != null &&
|
||||
BranchId != undefined &&
|
||||
AppId != null &&
|
||||
AppId != undefined
|
||||
) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/upi?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}&detailType=${DetailType}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const getAllApplications = createAsyncThunk(
|
||||
'application/getApplicationData',
|
||||
async ({ AppId }) => {
|
||||
if (AppId != null && AppId != undefined) {
|
||||
return axios.get(`${apiCommonUrl}/application?AppId=${AppId}`);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const getDeviceAccess = createAsyncThunk(
|
||||
'agetDeviceAccess',
|
||||
async ({ DeviceAddress }) => {
|
||||
if (DeviceAddress != null && DeviceAddress != undefined) {
|
||||
return axiosCommonInstanceData.get(
|
||||
`/DeviceInfo?DeviceAddress=${DeviceAddress}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const getPaymentOptionsData = createAsyncThunk(
|
||||
'getPaymentOptionsData',
|
||||
({ AppId, CompId, BranchId }) => {
|
||||
const UserType = getSession('UserType');
|
||||
if (
|
||||
CompId != null &&
|
||||
CompId != undefined &&
|
||||
BranchId != null &&
|
||||
BranchId != undefined &&
|
||||
AppId != null &&
|
||||
AppId != undefined &&
|
||||
UserType !== 'Super Admin' &&
|
||||
UserType !== 'Super Admin User'
|
||||
) {
|
||||
return axiosRetailInstanceData.get(
|
||||
`/paymentOptions?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const getPaymentDeviceAccessData = createAsyncThunk(
|
||||
'getPaymentDeviceAccessData',
|
||||
({ AppId, CompId, BranchId, UserId }) => {
|
||||
if (
|
||||
CompId != null &&
|
||||
CompId != undefined &&
|
||||
BranchId != null &&
|
||||
BranchId != undefined &&
|
||||
AppId != null &&
|
||||
AppId != undefined &&
|
||||
UserId != null &&
|
||||
UserId != undefined
|
||||
) {
|
||||
return axiosRetailInstanceData.get(
|
||||
`/PaymentDeviceAccess?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}&UserId=${UserId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const getPaymentGatewayAccessData = createAsyncThunk(
|
||||
'getPaymentGatewayAccessData',
|
||||
({ AppId, CompId, BranchId, ActiveStatus }) => {
|
||||
if (
|
||||
CompId != null &&
|
||||
CompId != undefined &&
|
||||
BranchId != null &&
|
||||
BranchId != undefined &&
|
||||
AppId != null &&
|
||||
AppId != undefined
|
||||
) {
|
||||
return axiosCommonInstanceData.get(
|
||||
`/PaymentGatewayConfig?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}&ActiveStatus=${ActiveStatus}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const postPaymentDevice = createAsyncThunk(
|
||||
'postPaymentDevice',
|
||||
async (data, { rejectWithValue }) => {
|
||||
try {
|
||||
const response = await axios.post(`${Paymentdevice_POST_URL}`, data, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json', // Set the Content-Type header
|
||||
// Add any other headers here if needed
|
||||
},
|
||||
});
|
||||
console.log('Response Data:', response?.data); // Log the response data
|
||||
return response?.data;
|
||||
} catch (error) {
|
||||
console.error('Request Error:', error);
|
||||
return rejectWithValue(error.response?.data || error.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const getPaymentDeviceResponse = createAsyncThunk(
|
||||
'getPaymentDeviceResponse',
|
||||
async (data, { rejectWithValue }) => {
|
||||
try {
|
||||
const response = await axios.post(`${Paymentdevice_GET_URL}`, data, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json', // Set the Content-Type header
|
||||
},
|
||||
});
|
||||
console.log('Response Data:', response?.data); // Log the response data
|
||||
return response?.data;
|
||||
} catch (error) {
|
||||
console.error('Request Error:', error);
|
||||
return rejectWithValue(error.response?.data || error.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const initialState = {
|
||||
BookingType: 'TakeAway',
|
||||
ProdCat: null,
|
||||
ProdSubCat: null,
|
||||
CategorieData: [],
|
||||
ProductCardList: [],
|
||||
KioskOrderDetails: [],
|
||||
OrderbtnClicked: false,
|
||||
OrderId: null,
|
||||
SalesId: null,
|
||||
KioskBookingTypeBoth: false,
|
||||
PaymentgatewayRedirect: false,
|
||||
PGFailedTransId: null,
|
||||
PGFailedAmt: null,
|
||||
MergeData: [], // Add merge data to global state
|
||||
LastBuyProducts: [],
|
||||
changeAddlastPrds: false,
|
||||
MembershipDetail: [],
|
||||
OrderOfferDetails: [],
|
||||
selfBookingCustomerDtls: null,
|
||||
MembershipNumber: null
|
||||
};
|
||||
|
||||
const KioskBookingData = createSlice({
|
||||
name: 'KioskBookingData',
|
||||
initialState,
|
||||
reducers: {
|
||||
|
||||
changeSelfBookingCustomerDtls: (state, action) => {
|
||||
state.selfBookingCustomerDtls = action?.payload
|
||||
},
|
||||
changeOrderOfferDetail: (state, action) => {
|
||||
state.OrderOfferDetails = action?.payload;
|
||||
},
|
||||
changeAddlastPrds: (state, action) => {
|
||||
state.changeAddlastPrds = action?.payload;
|
||||
},
|
||||
changeMembershipDetail: (state, action) => {
|
||||
state.MembershipDetail = action?.payload;
|
||||
},
|
||||
changeAllLastBuyProducts: (state, action) => {
|
||||
state.LastBuyProducts = action?.payload
|
||||
},
|
||||
changeProductCategorie: (state, action) => {
|
||||
state.ProdCat = action?.payload;
|
||||
},
|
||||
changeProductSubCategorie: (state, action) => {
|
||||
state.ProdSubCat = action?.payload;
|
||||
},
|
||||
changeBookingType: (state, action) => {
|
||||
state.BookingType = action?.payload;
|
||||
},
|
||||
changeCategorieData: (state, action) => {
|
||||
state.CategorieData = action?.payload;
|
||||
},
|
||||
changeProductCardListData: (state, action) => {
|
||||
state.ProductCardList = action?.payload;
|
||||
},
|
||||
changePaymentgatewayRedirect: (state, action) => {
|
||||
state.PaymentgatewayRedirect = action?.payload;
|
||||
},
|
||||
changeAllGlbStatustData: (state, action) => {
|
||||
(state.BookingType = 'TakeAway'),
|
||||
(state.KioskOrderDetails = []),
|
||||
(state.OrderbtnClicked = false),
|
||||
(state.OrderId = null),
|
||||
(state.ProdCat = null),
|
||||
state.CategorieData;
|
||||
// cart clear
|
||||
},
|
||||
changeKioskOrderDetails: (state, action) => {
|
||||
state.KioskOrderDetails = action?.payload;
|
||||
const result =
|
||||
action?.payload?.some(
|
||||
(product) => product.BookingTypeName === 'TakeAway'
|
||||
) &&
|
||||
action?.payload?.some(
|
||||
(product) => product.BookingTypeName === 'Dine In'
|
||||
);
|
||||
state.KioskBookingTypeBoth = result ? true : false;
|
||||
},
|
||||
changeOrderbtnClicked: (state, action) => {
|
||||
state.OrderbtnClicked = action?.payload;
|
||||
},
|
||||
changeOrderId: (state, action) => {
|
||||
state.OrderId = action?.payload;
|
||||
},
|
||||
changeSalesId: (state, action) => {
|
||||
state.SalesId = action?.payload;
|
||||
},
|
||||
changePGFailedTransId: (state, action) => {
|
||||
state.PGFailedTransId = action?.payload;
|
||||
},
|
||||
changePGFailedAmt: (state, action) => {
|
||||
state.PGFailedAmt = action?.payload;
|
||||
},
|
||||
changeMergeData: (state, action) => {
|
||||
state.MergeData = action?.payload;
|
||||
},
|
||||
changeMembershipNumber: (state, action) => {
|
||||
state.MembershipNumber = action?.payload;
|
||||
}
|
||||
},
|
||||
|
||||
extraReducers: (builder) => {
|
||||
builder.addCase(getProductCategories.fulfilled, (state, action) => {
|
||||
if (action?.payload?.data?.statusCode == 1) {
|
||||
state.CategorieData = action?.payload?.data?.data;
|
||||
// state.ProdCat = action?.payload?.data?.data[0].ProdCat;
|
||||
} else {
|
||||
state.CategorieData = action?.payload?.data?.data;
|
||||
// state.ProdCat = null;
|
||||
}
|
||||
}),
|
||||
builder.addCase(getProductCardListKiosk.fulfilled, (state, action) => {
|
||||
if (action?.payload?.data?.statusCode == 1) {
|
||||
state.ProductCardList = action?.payload?.data?.data;
|
||||
} else {
|
||||
state.ProductCardList = [];
|
||||
}
|
||||
});
|
||||
builder.addCase(getSelfBooking.fulfilled, (state, action) => {
|
||||
if (action?.payload?.data?.statusCode == 1) {
|
||||
state.KioskOrderDetails =
|
||||
action?.payload?.data?.data?.[0]?.productDetails?.map((item) => ({
|
||||
...item,
|
||||
disabled: true,
|
||||
}));
|
||||
state.OrderId = action?.payload?.data?.data?.[0]?.OrderId;
|
||||
state.SalesId = action?.payload?.data?.data?.[0]?.SalesId;
|
||||
} else {
|
||||
state.KioskOrderDetails = [];
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export const {
|
||||
changeSelfBookingCustomerDtls,
|
||||
changeProductCategorie,
|
||||
changeProductSubCategorie,
|
||||
changeBookingType,
|
||||
changeCategorieData,
|
||||
changeProductCardListData,
|
||||
changeAllGlbStatustData,
|
||||
changeKioskOrderDetails,
|
||||
changeOrderbtnClicked,
|
||||
changeOrderId,
|
||||
changePaymentgatewayRedirect,
|
||||
changePGFailedTransId,
|
||||
changePGFailedAmt,
|
||||
changeSalesId,
|
||||
changeMergeData,
|
||||
changeAllLastBuyProducts, changeAddlastPrds,
|
||||
changeMembershipDetail, changeOrderOfferDetail, changeMembershipNumber
|
||||
} = KioskBookingData.actions;
|
||||
|
||||
export const GlobalBookingTypeKiosk = (state) =>
|
||||
state?.KioskBookingData?.BookingType;
|
||||
export const GlobalProductCategorieKiosk = (state) =>
|
||||
state?.KioskBookingData?.ProdCat;
|
||||
export const GlobalProductSubCategorieKiosk = (state) =>
|
||||
state?.KioskBookingData?.ProdSubCat;
|
||||
export const GlobalCategorieDataKiosk = (state) =>
|
||||
state?.KioskBookingData?.CategorieData;
|
||||
export const GlobalProductCardListKiosk = (state) =>
|
||||
state?.KioskBookingData?.ProductCardList;
|
||||
export const GlobalKioskOrderDetails = (state) =>
|
||||
state?.KioskBookingData?.KioskOrderDetails;
|
||||
export const GlobalOrderbtnClicked = (state) =>
|
||||
state?.KioskBookingData?.OrderbtnClicked;
|
||||
export const GlobalOrderId = (state) => state?.KioskBookingData?.OrderId;
|
||||
export const GlobalSalesId = (state) => state?.KioskBookingData?.SalesId;
|
||||
export const GlobalKioskBookingTypeBoth = (state) =>
|
||||
state?.KioskBookingData?.KioskBookingTypeBoth;
|
||||
export const GlobalPaymentgatewayRedirect = (state) =>
|
||||
state?.KioskBookingData?.PaymentgatewayRedirect;
|
||||
export const GlobalPGFailedTransId = (state) =>
|
||||
state?.KioskBookingData?.PGFailedTransId;
|
||||
export const GlobalPGFailedAmt = (state) =>
|
||||
state?.KioskBookingData?.PGFailedAmt;
|
||||
export const GlobalMergeData = (state) => state?.KioskBookingData?.MergeData;
|
||||
export const GlobalLastBuyProducts = (state) => state?.KioskBookingData?.LastBuyProducts;
|
||||
export const GlobalChangeAddlastPrds = (state) => state?.KioskBookingData?.changeAddlastPrds;
|
||||
export const GlobalMembershipDetail = (state) => state?.KioskBookingData?.MembershipDetail;
|
||||
export const GlobalOrderOfferDetails = (state) => state?.KioskBookingData?.OrderOfferDetails;
|
||||
export const GlobalSelfBookingCustomerDtls = (state) => state?.KioskBookingData?.selfBookingCustomerDtls;
|
||||
export const GlobalMembershipNumber = (state) => state?.KioskBookingData?.MembershipNumber;
|
||||
|
||||
export default KioskBookingData.reducer;
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
|
||||
import { axiosRetailInstanceData } from '../../AuthenicationToken/AuthenticationToken';
|
||||
|
||||
export const getAddCustomerDetails = createAsyncThunk(
|
||||
'addCustomer/getAddCustomerDetails',
|
||||
async (data) => {
|
||||
if (
|
||||
data?.MobileNo != null &&
|
||||
data?.MobileNo != undefined &&
|
||||
data?.AppId != null &&
|
||||
data?.AppId != undefined &&
|
||||
data?.CompId != null &&
|
||||
data?.CompId != undefined &&
|
||||
data?.BranchId != null &&
|
||||
data?.BranchId != undefined
|
||||
) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/customer?MobileNo=${data?.MobileNo}&AppId=${data?.AppId}&CompId=${data?.CompId}&BranchId=${data?.BranchId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const postAddCustomerDetails = createAsyncThunk(
|
||||
'addCustomer/postAddCustomerDetails',
|
||||
async (postData) => {
|
||||
return await axiosRetailInstanceData.post(`/customer`, postData);
|
||||
}
|
||||
);
|
||||
|
||||
export const postRePrintReason = createAsyncThunk(
|
||||
'rePrint/postRePrintReason',
|
||||
async (postData) => {
|
||||
return await axiosRetailInstanceData.post(`/rePrint`, postData);
|
||||
}
|
||||
);
|
||||
export const postDefaultReprintReason = createAsyncThunk(
|
||||
'rePrint/postDefaultReprintReason',
|
||||
async (postData) => {
|
||||
return await axiosRetailInstanceData.post(`/DefaultStatusReprint`, postData);
|
||||
}
|
||||
);
|
||||
export const getRePrintDefault = createAsyncThunk(
|
||||
'rePrint/getRePrintDefault',
|
||||
async (data) => {
|
||||
return await axiosRetailInstanceData.get(`/ReprintHistoryStatus?compId=${data.CompId}&branchId=${data.BranchId}&appId=${data.AppId}&Type=${data?.Type ? data?.Type : 'Reprint'}`);
|
||||
}
|
||||
);
|
||||
|
||||
export const getDefaultPaymentOptions = createAsyncThunk(
|
||||
'rePrint/getDefaultPaymentOptions',
|
||||
async (data) => {
|
||||
return await axiosRetailInstanceData.get(`/ReprintHistoryStatus?compId=${data.CompId}&branchId=${data.BranchId}&appId=${data.AppId}&Type=PaymentOptions`);
|
||||
}
|
||||
);
|
||||
|
||||
export const getRePrintReason = createAsyncThunk(
|
||||
'rePrint/getRePrintReason',
|
||||
async (data) => {
|
||||
if (
|
||||
data?.orderFromDate != null &&
|
||||
data?.orderFromDate != undefined &&
|
||||
data?.orderToDate != null &&
|
||||
data?.orderToDate != undefined &&
|
||||
data?.appId != null &&
|
||||
data?.appId != undefined &&
|
||||
data?.compId != null &&
|
||||
data?.compId != undefined &&
|
||||
data?.branchId != null &&
|
||||
data?.branchId != undefined
|
||||
) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/ReprintHistory?compId=${data.compId}&branchId=${data.branchId}&appId=${data.appId}&fromDate=${data.orderFromDate}&toDate=${data.orderToDate}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const ReprintDetails = createAsyncThunk(
|
||||
"addCustomer/ReprintDetails",
|
||||
async (data) => {
|
||||
const { AppId, CompId, BranchId, OrderFromDate, OrderToDate, OrderId } = data || {};
|
||||
if (OrderId && !OrderFromDate && !OrderToDate) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/reprint?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}&OrderId=${OrderId}&pageNumber=${data.PageNumber}`
|
||||
);
|
||||
}
|
||||
if (OrderFromDate && OrderToDate) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/reprint?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}&orderFromDate=${OrderFromDate}&orderToDate=${OrderToDate} &pageNumber=${data.PageNumber}`
|
||||
);
|
||||
} else {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/reprint?CompId=${CompId}&BranchId=${BranchId}&AppId=${AppId}&pageNumber=${data.PageNumber}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
|
||||
const initialState = {
|
||||
AddCustomerDetails: [],
|
||||
refreshTrigger: 0,
|
||||
};
|
||||
|
||||
const addCustomer = createSlice({
|
||||
name: 'addCustomer',
|
||||
initialState,
|
||||
reducers: {
|
||||
changeCustomerdetails: (state, action) => {
|
||||
state.AddCustomerDetails = action?.payload;
|
||||
},
|
||||
triggerCustomerRefresh: (state) => {
|
||||
state.refreshTrigger += 1;
|
||||
},
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
builder.addCase(getAddCustomerDetails.fulfilled, (state, action) => {
|
||||
if (action?.payload?.status) {
|
||||
state.AddCustomerDetails = action?.payload?.data?.data;
|
||||
} else {
|
||||
state.AddCustomerDetails = [];
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
export const { changeCustomerdetails, triggerCustomerRefresh } = addCustomer.actions;
|
||||
|
||||
export const GlobalAddCustomerDetails = (state) =>
|
||||
state.addCustomer?.AddCustomerDetails;
|
||||
|
||||
export const GlobalCustomerRefreshTrigger = (state) =>
|
||||
state.addCustomer?.refreshTrigger;
|
||||
|
||||
export default addCustomer.reducer;
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
import axios from 'axios';
|
||||
import { createAsyncThunk } from '@reduxjs/toolkit';
|
||||
import { axiosRetailInstanceData } from '../../AuthenicationToken/AuthenticationToken';
|
||||
|
||||
export const getSalesInvoices = createAsyncThunk(
|
||||
'ListOfInvoices/getSalesInvoices',
|
||||
async (data) => {
|
||||
if (
|
||||
data?.CompId != null &&
|
||||
data?.CompId != undefined &&
|
||||
data?.BranchId != null &&
|
||||
data?.BranchId != undefined &&
|
||||
data?.AppId != null &&
|
||||
data?.AppId != undefined
|
||||
) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/reprint?CompId=${data?.CompId}&BranchId=${data?.BranchId}&AppId=${data?.AppId}&orderFromDate=${data?.orderFromDate}&orderToDate=${data?.orderToDate}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
|
||||
import { axiosRetailInstanceData } from '../../AuthenicationToken/AuthenticationToken';
|
||||
|
||||
export const gettinghold = createAsyncThunk('gettinghold', async (data) => {
|
||||
if (
|
||||
data?.AppId != null &&
|
||||
data?.AppId != undefined &&
|
||||
data?.CompId != null &&
|
||||
data?.CompId != undefined &&
|
||||
data?.BranchId != null &&
|
||||
data?.BranchId != undefined
|
||||
) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/hold?CompId=${data?.CompId}&BranchId=${data?.BranchId}&AppId=${data?.AppId}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export const puttinghold = createAsyncThunk('puttinghold', async (putData) => {
|
||||
return await axiosRetailInstanceData.put(`/hold`, putData);
|
||||
});
|
||||
|
||||
const initialState = {
|
||||
holddata: [],
|
||||
};
|
||||
|
||||
const HoldOption = createSlice({
|
||||
name: 'HoldOption',
|
||||
initialState,
|
||||
reducers: {
|
||||
changeholddata: (state, action) => {
|
||||
state.holddata = action?.payload;
|
||||
},
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
builder.addCase(gettinghold.fulfilled, (state, action) => {
|
||||
if (action?.payload?.status) {
|
||||
state.holddata = action?.payload?.data?.data;
|
||||
} else {
|
||||
state.holddata = [];
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export const { changeholddata } = HoldOption.actions;
|
||||
|
||||
export const globalholddata = (state) => state?.HoldOption?.holddata;
|
||||
|
||||
export default HoldOption.reducer;
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
|
||||
import { axiosRetailInstanceData } from '../../AuthenicationToken/AuthenticationToken';
|
||||
|
||||
export const PreOrderBookingData = createAsyncThunk(
|
||||
'PreOrder/PreOrderBookingData',
|
||||
async (postData) => {
|
||||
return await axiosRetailInstanceData.post(`/PreOrder`, postData);
|
||||
}
|
||||
);
|
||||
|
||||
export const PreOrderGet = createAsyncThunk(
|
||||
'PreOrder/PreOrderBookingData',
|
||||
async (data) => {
|
||||
if (
|
||||
data?.compId != null &&
|
||||
data?.compId != undefined &&
|
||||
data?.branchId != null &&
|
||||
data?.branchId != undefined &&
|
||||
data?.appId != null &&
|
||||
data?.appId != undefined &&
|
||||
data?.deliveryStatus != null &&
|
||||
data?.deliveryStatus != undefined
|
||||
) {
|
||||
if (data?.toDate && data?.fromDate) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/PreOrder?compId=${data?.compId}&branchId=${data?.branchId}&appId=${data?.appId}&deliveryStatus=${data?.deliveryStatus}&fromDate=${data?.fromDate}&toDate=${data?.toDate}`
|
||||
);
|
||||
} else {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/PreOrder?compId=${data?.compId}&branchId=${data?.branchId}&appId=${data?.appId}&deliveryStatus=${data?.deliveryStatus}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
export const PreOrderBookingDataCancel= createAsyncThunk(
|
||||
'PreOrder/PreOrderBookingDataCancel',
|
||||
async (Data) => {
|
||||
return await axiosRetailInstanceData.post(`/PreOrderCancel`, Data);
|
||||
}
|
||||
);
|
||||
|
||||
export const PreOrderBookingDataPut = createAsyncThunk(
|
||||
'PreOrder/PreOrderBookingDataPut',
|
||||
async (putData) => {
|
||||
return await axiosRetailInstanceData.put(`/PreOrder`, putData);
|
||||
}
|
||||
);
|
||||
|
||||
const initialState = {
|
||||
preOrder: false,
|
||||
PreOrderList: [],
|
||||
PreOrderAdditem: null,
|
||||
PreOrderCusName: null,
|
||||
PreOrderCusMobNo: null,
|
||||
PreOrderDate: null,
|
||||
PreOrderTime: null,
|
||||
PreOrderAdvance: 0,
|
||||
PreOrderMessage: null,
|
||||
PreOrderAdd1: null,
|
||||
PreOrderAdd2: null,
|
||||
PreOrderzip: null,
|
||||
PreOrderCity: null,
|
||||
PreOrderDistrict: null,
|
||||
PreOrderState: null,
|
||||
PreOrderReferenceMessage: null,
|
||||
PreOrderSelectedPaymentOption: null,
|
||||
PreOrderSelectedUPIOption: null,
|
||||
PreOrderListedit: [],
|
||||
PreOrderPendingCount: null,
|
||||
};
|
||||
|
||||
const PreOrder = createSlice({
|
||||
name: 'PreOrder',
|
||||
initialState,
|
||||
reducers: {
|
||||
changepreOrder: (state, action) => {
|
||||
state.preOrder = action?.payload;
|
||||
},
|
||||
changePreOrderMessage: (state, action) => {
|
||||
state.PreOrderMessage = action?.payload;
|
||||
},
|
||||
changePreOrderAdd1: (state, action) => {
|
||||
state.PreOrderAdd1 = action?.payload;
|
||||
},
|
||||
changePreOrderAdd2: (state, action) => {
|
||||
state.PreOrderAdd2 = action?.payload;
|
||||
},
|
||||
changePreOrderzip: (state, action) => {
|
||||
state.PreOrderzip = action?.payload;
|
||||
},
|
||||
changePreOrderCity: (state, action) => {
|
||||
state.PreOrderCity = action?.payload;
|
||||
},
|
||||
changePreOrderDistrict: (state, action) => {
|
||||
state.PreOrderDistrict = action?.payload;
|
||||
},
|
||||
changePreOrderState: (state, action) => {
|
||||
state.PreOrderState = action?.payload;
|
||||
},
|
||||
changePreOrderReferenceMessage: (state, action) => {
|
||||
state.PreOrderReferenceMessage = action?.payload;
|
||||
},
|
||||
changePreOrderSelectedPaymentOption: (state, action) => {
|
||||
state.PreOrderSelectedPaymentOption = action?.payload;
|
||||
},
|
||||
changePreOrderSelectedUPIOptione: (state, action) => {
|
||||
state.PreOrderSelectedUPIOption = action?.payload;
|
||||
},
|
||||
changepreOrderListedit: (state, action) => {
|
||||
state.PreOrderListedit = action?.payload;
|
||||
},
|
||||
changePreOrderPendingCount: (state, action) => {
|
||||
state.PreOrderPendingCount = action?.payload;
|
||||
},
|
||||
|
||||
changePreOrderAdvance: (state, action) => {
|
||||
state.PreOrderAdvance = action?.payload;
|
||||
},
|
||||
changePreOrderDate: (state, action) => {
|
||||
state.PreOrderDate = action?.payload;
|
||||
},
|
||||
changePreOrderTime: (state, action) => {
|
||||
state.PreOrderTime = action?.payload;
|
||||
},
|
||||
changePreOrderCusName: (state, action) => {
|
||||
state.PreOrderCusName = action?.payload;
|
||||
},
|
||||
changePreOrderCusMob: (state, action) => {
|
||||
state.PreOrderCusMobNo = action?.payload;
|
||||
},
|
||||
changePreOrderAdditem: (state, action) => {
|
||||
state.PreOrderAdditem = action?.payload;
|
||||
},
|
||||
changepreOrderList: (state, action) => {
|
||||
state.PreOrderList = action?.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
export const {
|
||||
changepreOrder,
|
||||
changepreOrderList,
|
||||
changePreOrderAdditem,
|
||||
changePreOrderCusName,
|
||||
changePreOrderCusMob,
|
||||
changePreOrderDate,
|
||||
changePreOrderTime,
|
||||
changePreOrderAdvance,
|
||||
changePreOrderMessage,
|
||||
changePreOrderAdd1,
|
||||
changePreOrderAdd2,
|
||||
changePreOrderzip,
|
||||
changePreOrderCity,
|
||||
changePreOrderDistrict,
|
||||
changePreOrderState,
|
||||
changePreOrderReferenceMessage,
|
||||
changePreOrderSelectedPaymentOption,
|
||||
changePreOrderSelectedUPIOptione,
|
||||
changepreOrderListedit,
|
||||
changePreOrderPendingCount,
|
||||
} = PreOrder.actions;
|
||||
|
||||
export const GlobalpreOrderOpen = (state) => state?.PreOrder?.preOrder;
|
||||
export const GlobalPreOrderMessage = (state) =>
|
||||
state?.PreOrder?.PreOrderMessage;
|
||||
export const GlobalPreOrderListedit = (state) =>
|
||||
state?.PreOrder?.PreOrderListedit;
|
||||
export const GlobalPreOrderPendingCount = (state) =>
|
||||
state?.PreOrder?.PreOrderPendingCount;
|
||||
export const GlobalPreOrderSelectedPaymentOption = (state) =>
|
||||
state?.PreOrder?.PreOrderSelectedPaymentOption;
|
||||
export const GlobaPreOrderSelectedUPIOptione = (state) =>
|
||||
state?.PreOrder?.PreOrderSelectedUPIOption;
|
||||
export const GlobalPreOrderReferenceMessage = (state) =>
|
||||
state?.PreOrder?.PreOrderReferenceMessage;
|
||||
export const GlobalPreOrderAdd1 = (state) => state?.PreOrder?.PreOrderAdd1;
|
||||
export const GlobalPreOrderAdd2 = (state) => state?.PreOrder?.PreOrderAdd2;
|
||||
export const GlobalPreOrderzip = (state) => state?.PreOrder?.PreOrderzip;
|
||||
export const GlobalPreOrderCity = (state) => state?.PreOrder?.PreOrderCity;
|
||||
export const GlobalPreOrderDistrict = (state) =>
|
||||
state?.PreOrder?.PreOrderDistrict;
|
||||
export const GlobalPreOrderState = (state) => state?.PreOrder?.PreOrderState;
|
||||
export const GlobalPreOrderAdvance = (state) =>
|
||||
state?.PreOrder?.PreOrderAdvance;
|
||||
export const GlobalPreOrderDate = (state) => state?.PreOrder?.PreOrderDate;
|
||||
export const GlobalPreOrderTime = (state) => state?.PreOrder?.PreOrderTime;
|
||||
export const GlobalPreOrderCusName = (state) =>
|
||||
state?.PreOrder?.PreOrderCusName;
|
||||
export const GlobalPreOrderCusMobNo = (state) =>
|
||||
state?.PreOrder?.PreOrderCusMobNo;
|
||||
export const GlobalPreOrderAdditem = (state) =>
|
||||
state?.PreOrder?.PreOrderAdditem;
|
||||
export const GlobalPreOrderList = (state) => state?.PreOrder?.PreOrderList;
|
||||
|
||||
export default PreOrder.reducer;
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
|
||||
import {
|
||||
axiosRetailInstanceData,
|
||||
axiosCommonInstanceData,
|
||||
} from '../../AuthenicationToken/AuthenticationToken';
|
||||
import { getSession } from '../../../Services/Others';
|
||||
|
||||
export const getccavenuePaymentDetails = createAsyncThunk(
|
||||
'getccavenuePaymentDetails1',
|
||||
async () => {
|
||||
return await axiosCommonInstanceData.get(
|
||||
`/ccavenuePaymentDetails?activeStatus=A`
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const getPaymentUpiDetails = createAsyncThunk(
|
||||
'getPaymentUpiDeatils1',
|
||||
async () => {
|
||||
return await axiosCommonInstanceData.get(
|
||||
`/paymentUpiDetails?activeStatus=A&type=I`
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const postInvoice = createAsyncThunk('postInvoice', async (postData) => {
|
||||
return await axiosCommonInstanceData.post(`/userAppMap`, postData);
|
||||
});
|
||||
export const getPricingType = createAsyncThunk(
|
||||
'getPricingType/getPricingType',
|
||||
async (PricingId) => {
|
||||
if (PricingId) {
|
||||
return await axiosCommonInstanceData.get(
|
||||
`/pricingType?PricingId=${PricingId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const getUserDetails = createAsyncThunk(
|
||||
'getUserDetail/getUserDetails',
|
||||
async (UserId) => {
|
||||
if (UserId) {
|
||||
return await axiosCommonInstanceData.get(`/user?UserId=${UserId}`);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const getPurchasedAppDetails = createAsyncThunk(
|
||||
'getPurchasedAppDetails',
|
||||
async ({ UserId, AppId }) => {
|
||||
return await axiosCommonInstanceData.get(
|
||||
`/UserAppMap?AppId=${AppId}&UserId=${UserId}`
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const CheckPaymentStatus = createAsyncThunk(
|
||||
'SendPaymentLink/SendPaymentLink',
|
||||
async (BookingId) => {
|
||||
if (BookingId) {
|
||||
return await axiosCommonInstanceData.get(
|
||||
`/userAppMap?UniqueId=${BookingId}&PaymentStatus=S`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const getPaymentValidation = createAsyncThunk(
|
||||
'getPaymentValidation',
|
||||
async (data) => {
|
||||
const UserType = getSession('UserType');
|
||||
if (UserType !== 'Super Admin' && UserType !== 'Super Admin User') {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/PaymentOptions?compId=${data?.CompId}&appId=${data?.AppId}&branchId=${data?.BranchId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const initialState = {};
|
||||
|
||||
const Pricing = createSlice({
|
||||
name: 'BookingData',
|
||||
initialState,
|
||||
});
|
||||
export default Pricing.reducer;
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
|
||||
import {
|
||||
axiosRetailInstanceData,
|
||||
axiosCommonInstanceData,
|
||||
} from '../AuthenicationToken/AuthenticationToken';
|
||||
|
||||
export const getRetailPaymentClosing = createAsyncThunk(
|
||||
'RetailBookingClose/getRetailPaymentClosing',
|
||||
async (data) => {
|
||||
console.log(data, 'datadata');
|
||||
if (
|
||||
data?.AppId != null &&
|
||||
data?.AppId != undefined &&
|
||||
data?.CompId != null &&
|
||||
data?.CompId != undefined &&
|
||||
data?.BranchId != null &&
|
||||
data?.BranchId != undefined &&
|
||||
data?.UserId != null &&
|
||||
data?.UserId != undefined
|
||||
) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/BookingClosingBalance?CompId=${data?.CompId}&BranchId=${data?.BranchId}&AppId=${data?.AppId}&UserId=${data?.UserId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
export const PostBookingClose = createAsyncThunk(
|
||||
'RetailBookingClose/PostBookingClose',
|
||||
async (postData) => {
|
||||
return await axiosRetailInstanceData.post(`/BookingClose`, postData);
|
||||
}
|
||||
);
|
||||
export const PutBookingClose = createAsyncThunk(
|
||||
'RetailBookingClose/PutBookingClose',
|
||||
async (putData) => {
|
||||
return await axiosRetailInstanceData.put(`/BookingClose`, putData);
|
||||
}
|
||||
);
|
||||
|
|
@ -0,0 +1,275 @@
|
|||
import axios from 'axios';
|
||||
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
|
||||
import {
|
||||
axiosRetailInstanceData,
|
||||
axiosCommonInstanceData,
|
||||
} from '../AuthenicationToken/AuthenticationToken';
|
||||
import { getSession } from '../../Services/Others';
|
||||
const apiCommonUrl = import.meta.env.ENV_API_URL_COMMON;
|
||||
|
||||
export const GenerateLogout = createAsyncThunk(
|
||||
'signInPage/GenerateLogout',
|
||||
async ({ UserId, status }) => {
|
||||
if (UserId) {
|
||||
return await axiosCommonInstanceData.put(`/Logout`, {
|
||||
UserId: UserId,
|
||||
Generate: status,
|
||||
RequestMode: 'DW',
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
export const checkSession = createAsyncThunk(
|
||||
'signInPage/checkSession',
|
||||
async ({ UserId, sessionId }) => {
|
||||
if (UserId) {
|
||||
return await axiosCommonInstanceData.get(
|
||||
`/UserSessionId?UserId=${UserId}&sessionId=${sessionId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
export const PublicQrCodepost = createAsyncThunk(
|
||||
'BranchLogin/PublicQrCodepost',
|
||||
async (postData) => {
|
||||
return await axiosCommonInstanceData.get(
|
||||
`/URLshortener?referenceNo=${postData}`
|
||||
);
|
||||
}
|
||||
);
|
||||
export const getCompBranchData = createAsyncThunk(
|
||||
'BranchData/getBranchData',
|
||||
async ({ CompId, AppId, UserId }) => {
|
||||
if (
|
||||
UserId != null &&
|
||||
UserId != undefined &&
|
||||
AppId != null &&
|
||||
AppId != undefined &&
|
||||
CompId != null &&
|
||||
CompId != undefined
|
||||
) {
|
||||
return await axiosCommonInstanceData.get(
|
||||
`/Branch?UserId=${UserId}&AppId=${AppId}&CompId=${CompId}`
|
||||
);
|
||||
} else if (
|
||||
CompId != null &&
|
||||
CompId != undefined &&
|
||||
AppId != null &&
|
||||
AppId != undefined
|
||||
) {
|
||||
return await axiosCommonInstanceData.get(
|
||||
`/Branch?CompId=${CompId}&AppId=${AppId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
export const getBranchDetail = createAsyncThunk(
|
||||
'BranchData/getBranchDetail',
|
||||
async (data) => {
|
||||
if (data?.BrId != null && data?.BrId != undefined) {
|
||||
return await axiosCommonInstanceData.get(`/Branch?BrId=${data?.BrId}`);
|
||||
}
|
||||
}
|
||||
);
|
||||
export const getAllBranchDetail = createAsyncThunk(
|
||||
'BranchData/getAllBranchDetail',
|
||||
async (data) => {
|
||||
if (data?.AppId != null && data?.AppId != undefined) {
|
||||
return await axiosCommonInstanceData.get(`/Branch?appId=${data?.AppId}`);
|
||||
}
|
||||
}
|
||||
);
|
||||
export const getEmpAccesData = createAsyncThunk(
|
||||
'EmpAccesData/getEmpAccesData',
|
||||
async (data) => {
|
||||
if (
|
||||
data?.AppId != null &&
|
||||
data?.AppId != undefined &&
|
||||
data?.UserId != null &&
|
||||
data?.UserId != undefined &&
|
||||
data?.CompId != null &&
|
||||
data?.CompId != undefined &&
|
||||
data?.BranchId != null &&
|
||||
data?.BranchId != undefined
|
||||
) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/EmpAccess?empId=${data?.UserId}&AppId=${data?.AppId}&CompId=${data?.CompId}&branchId=${data?.BranchId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
export const PricingAppPricingName = createAsyncThunk(
|
||||
'BranchData/PricingAppPricingName',
|
||||
async (data) => {
|
||||
if (
|
||||
data?.appId != null &&
|
||||
data?.appId != undefined &&
|
||||
data?.compId != null &&
|
||||
data?.compId != undefined &&
|
||||
data?.branchId != null &&
|
||||
data?.branchId != undefined
|
||||
) {
|
||||
return await axios.get(
|
||||
`${apiCommonUrl}/PricingAppFeatMap?appId=${data?.appId}&compId=${data?.compId}&branchId=${data?.branchId}`
|
||||
);
|
||||
} else if (
|
||||
data?.appId != null &&
|
||||
data?.appId != undefined &&
|
||||
data?.userId != null &&
|
||||
data?.userId != undefined
|
||||
) {
|
||||
return await axios.get(
|
||||
`${apiCommonUrl}/PricingAppFeatMap?appId=${data?.appId}&userId=${data?.userId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const getSAdminUserAccesData = createAsyncThunk(
|
||||
'Sadmindata/getSAdminUserAccesData',
|
||||
async (data) => {
|
||||
if (
|
||||
data?.AppId != null &&
|
||||
data?.AppId != undefined &&
|
||||
data?.UserId != null &&
|
||||
data?.UserId != undefined
|
||||
) {
|
||||
return await axiosCommonInstanceData.get(
|
||||
`/AppMenuAccess?UserId=${data?.UserId}&AppId=${data?.AppId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const getApplicationDetails = createAsyncThunk(
|
||||
'BranchData/getApplicationDetails',
|
||||
async ({ AppId }) => {
|
||||
if (AppId) {
|
||||
return await axios.get(`${apiCommonUrl}/application?AppId=${AppId}`);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const PostLoginSuser = createAsyncThunk(
|
||||
'BranchData/PostLoginSuser',
|
||||
async (postData) => {
|
||||
return await axiosCommonInstanceData.post(
|
||||
`/SuperAdminUserBranchSignIn`,
|
||||
postData
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const PUTLoginuser = createAsyncThunk(
|
||||
'BranchData/PostLoginSuser',
|
||||
async (putData) => {
|
||||
return await axiosCommonInstanceData.put(
|
||||
`/SuperAdminUserBranchSignIn`,
|
||||
putData
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const putSadminUserExit = createAsyncThunk(
|
||||
'BranchData/putSadminUserExit',
|
||||
async (putData) => {
|
||||
return await axiosCommonInstanceData.put(
|
||||
`/SuperAdminUserBranchSignInEmp`,
|
||||
putData
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const getLoginuser = createAsyncThunk(
|
||||
'BranchData/getLoginuser',
|
||||
async (getdata) => {
|
||||
return await axiosCommonInstanceData.get(
|
||||
`/SuperAdminUserBranchSignIn?userId=${getdata.UserId}&sessionId=${getdata.sessionId}&branchId=${getdata.BranchId}`
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const getCommonAppPreference = createAsyncThunk(
|
||||
'/getAppPreference',
|
||||
async (AppId) => {
|
||||
if (
|
||||
AppId != null &&
|
||||
AppId != undefined
|
||||
){
|
||||
return await axiosCommonInstanceData.get(
|
||||
`/ApplicationPreferenceMapping?AppId=${AppId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const initialState = {
|
||||
SelectedBrachId: null,
|
||||
CompBranchData: null,
|
||||
SadminUserPin: [],
|
||||
SadminUserData: [],
|
||||
AppPreferences: [],
|
||||
isWarehouse:false,
|
||||
};
|
||||
|
||||
const BranchLogin = createSlice({
|
||||
name: 'BranchLogin',
|
||||
initialState,
|
||||
reducers: {
|
||||
changeSelectedBranchId: (state, action) => {
|
||||
state.SelectedBrachId = action?.payload;
|
||||
},
|
||||
changeWarehouse:(state,action)=>{
|
||||
state.isWarehouse=action?.payload
|
||||
|
||||
}
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
builder.addCase(getCompBranchData.fulfilled, (state, action) => {
|
||||
if (action?.payload?.status) {
|
||||
state.CompBranchData = action?.payload?.data?.data;
|
||||
}
|
||||
});
|
||||
builder.addCase(checkSession.fulfilled, (state, action) => {
|
||||
if (action?.payload?.status) {
|
||||
if (action?.payload?.data?.data?.length > 0) {
|
||||
state.SadminUserPin = action?.payload?.data?.data?.filter(
|
||||
(item) =>
|
||||
item?.AppId == getSession('AppId') &&
|
||||
item?.CompId == getSession('CompId') &&
|
||||
item?.BranchId == getSession('BranchId')
|
||||
);
|
||||
state.SadminUserData = action?.payload?.data?.data;
|
||||
} else {
|
||||
state.SadminUserPin = [];
|
||||
}
|
||||
}
|
||||
});
|
||||
builder.addCase(getCommonAppPreference.fulfilled, (state, action) => {
|
||||
if (action?.payload?.status === 200) {
|
||||
const { data: result } = action?.payload;
|
||||
if (result?.data?.length > 0) {
|
||||
state.AppPreferences = result?.data?.[0]?.PreferenceDetails;
|
||||
} else {
|
||||
state.AppPreferences = [];
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
export const { changeSelectedBranchId ,changeWarehouse} = BranchLogin.actions;
|
||||
export const GlobalSelectedBranchId = (state) =>
|
||||
state?.BranchLogin?.SelectedBrachId;
|
||||
export const GlobalCompBranchData = (state) =>
|
||||
state?.BranchLogin?.CompBranchData;
|
||||
export const GLobalSadminUserPin = (state) => state?.BranchLogin?.SadminUserPin;
|
||||
export const GLobalSadminUserData = (state) =>
|
||||
state?.BranchLogin?.SadminUserData;
|
||||
export const ApplicationPreferences = (state) =>
|
||||
state?.BranchLogin?.AppPreferences;
|
||||
export const globalBranchType = (state) =>
|
||||
state?.BranchLogin?.isWarehouse;
|
||||
|
||||
|
||||
|
||||
export default BranchLogin.reducer;
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
import { createAsyncThunk } from '@reduxjs/toolkit';
|
||||
import { axiosRetailInstanceData } from '../AuthenicationToken/AuthenticationToken';
|
||||
|
||||
export const getProdListBasedOnCat = createAsyncThunk(
|
||||
'CancelApplicableProd/getProdListBasedOnCat',
|
||||
async (data) => {
|
||||
if (
|
||||
data?.CompId != null &&
|
||||
data?.CompId != undefined &&
|
||||
data?.BranchId != null &&
|
||||
data?.BranchId != undefined &&
|
||||
data?.AppId != null &&
|
||||
data?.AppId != undefined &&
|
||||
data?.ProdCat != null &&
|
||||
data?.ProdCat != undefined &&
|
||||
data?.type != null &&
|
||||
data?.type != undefined
|
||||
) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/productCardList?CompId=${data?.CompId}&BranchId=${data?.BranchId}&AppId=${data?.AppId}&ProdCat=${data?.ProdCat}&Type=${data?.type}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const putCancelAppProd = createAsyncThunk(
|
||||
'CancelApplicableProd/putCancelAppProd',
|
||||
async (putData) => {
|
||||
return await axiosRetailInstanceData.put(
|
||||
`/CancelApplicableProducts`,
|
||||
putData
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const getSalesReturn = createAsyncThunk(
|
||||
'CancelApplicableProd/getProdListBasedOnCat',
|
||||
async (data) => {
|
||||
const { CompId, BranchId, AppId } = data;
|
||||
if (
|
||||
CompId != null &&
|
||||
CompId != undefined &&
|
||||
BranchId != null &&
|
||||
BranchId != undefined &&
|
||||
AppId != null &&
|
||||
AppId != undefined
|
||||
) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/SalesReturn?appId=${AppId}&compId=${CompId}&branchId=${BranchId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
export const getRescheduledSlot = createAsyncThunk(
|
||||
'RescheduledSlot/getRescheduledSlot',
|
||||
async (data) => {
|
||||
const { CompId, BranchId, AppId } = data;
|
||||
if (
|
||||
CompId != null &&
|
||||
CompId != undefined &&
|
||||
BranchId != null &&
|
||||
BranchId != undefined &&
|
||||
AppId != null &&
|
||||
AppId != undefined
|
||||
) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/Sales/RescheduledSlotGet?appId=${AppId}&compId=${CompId}&branchId=${BranchId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const postSalesReturn = createAsyncThunk(
|
||||
'CancelApplicableProd/postSalesReturn',
|
||||
async (postData) => {
|
||||
return await axiosRetailInstanceData.post(
|
||||
`/SalesReturn`,
|
||||
postData
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const postRescheduleSlot = createAsyncThunk(
|
||||
'RescheduleSlot/SlotReschedule',
|
||||
async (postData) => {
|
||||
return await axiosRetailInstanceData.post(
|
||||
`/SlotReschedule`,
|
||||
postData
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const getProductReturnPolicy = createAsyncThunk(
|
||||
'CancelApplicableProd/getProductReturnPolicy',
|
||||
async (data) => {
|
||||
const { CompId, BranchId, AppId, SalesId } = data;
|
||||
if (
|
||||
CompId != null &&
|
||||
CompId != undefined &&
|
||||
BranchId != null &&
|
||||
BranchId != undefined &&
|
||||
AppId != null &&
|
||||
AppId != undefined &&
|
||||
SalesId != null &&
|
||||
SalesId != undefined
|
||||
) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`ReturnExchangePolicyMapping/Eligibility?appId=${AppId}&compId=${CompId}&branchId=${BranchId}&salesId=${SalesId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
import { createAsyncThunk } from '@reduxjs/toolkit';
|
||||
import { axiosRetailInstanceData } from '../AuthenicationToken/AuthenticationToken';
|
||||
|
||||
export const productname = createAsyncThunk('productname', async (data) => {
|
||||
if (
|
||||
data?.CompId != null &&
|
||||
data?.CompId != undefined &&
|
||||
data?.BranchId != null &&
|
||||
data?.BranchId != undefined &&
|
||||
data?.AppId != null &&
|
||||
data?.AppId != undefined
|
||||
) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/Offer/ProductDtl?CompId=${data?.CompId}&BranchId=${data?.BranchId}&AppId=${data?.AppId}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export const getCombolist = createAsyncThunk('getCombo', async (data) => {
|
||||
if (
|
||||
data?.CompId != null &&
|
||||
data?.CompId != undefined &&
|
||||
data?.BranchId != null &&
|
||||
data?.BranchId != undefined &&
|
||||
data?.AppId != null &&
|
||||
data?.AppId != undefined &&
|
||||
data?.ActiveStatus != null &&
|
||||
data?.ActiveStatus != undefined
|
||||
) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/comboHdr?CompId=${data?.CompId}&BranchId=${data?.BranchId}&AppId=${data?.AppId}&ActiveStatus=${data?.ActiveStatus}`
|
||||
);
|
||||
} else {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/comboHdr?CompId=${data?.CompId}&BranchId=${data?.BranchId}&AppId=${data?.AppId}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export const getCombo = createAsyncThunk('getCombo', async (data) => {
|
||||
if (
|
||||
data?.CompId != null &&
|
||||
data?.CompId != undefined &&
|
||||
data?.BranchId != null &&
|
||||
data?.BranchId != undefined &&
|
||||
data?.AppId != null &&
|
||||
data?.AppId != undefined
|
||||
) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/comboHdr?CompId=${data?.CompId}&BranchId=${data?.BranchId}&AppId=${data?.AppId}&type=${data?.type}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export const getComboProddata = createAsyncThunk('getCombo', async (data) => {
|
||||
if (
|
||||
data?.CompId != null &&
|
||||
data?.CompId != undefined &&
|
||||
data?.BranchId != null &&
|
||||
data?.BranchId != undefined &&
|
||||
data?.AppId != null &&
|
||||
data?.AppId != undefined
|
||||
) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/comboHdr?CompId=${data?.CompId}&BranchId=${data?.BranchId}&AppId=${data?.AppId}&comboId=${data?.comboId}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export const productqrqty = createAsyncThunk('productqrqty', async (data) => {
|
||||
if (data?.ProdId != null && data?.ProdId != undefined) {
|
||||
return await axiosRetailInstanceData.get(`/product?ProdId=${data?.ProdId}`);
|
||||
}
|
||||
});
|
||||
|
||||
export const postCombo = createAsyncThunk(
|
||||
'postCombo/postCombo',
|
||||
async (postData) => {
|
||||
return await axiosRetailInstanceData.post(`/comboHdr`, postData);
|
||||
}
|
||||
);
|
||||
|
||||
export const putCombo = createAsyncThunk(
|
||||
'putCombo/putCombo',
|
||||
async (putData) => {
|
||||
return await axiosRetailInstanceData.put(`/comboHdr`, putData);
|
||||
}
|
||||
);
|
||||
|
||||
export const deleteCombo = createAsyncThunk(
|
||||
'deleteCombo/deleteCombo',
|
||||
async (putData) => {
|
||||
return await axiosRetailInstanceData.put(`/DeleteCombo`, putData);
|
||||
}
|
||||
);
|
||||
|
||||
export const getProdvaraiantdata = createAsyncThunk(
|
||||
'product/getProdcataloguedata',
|
||||
async (data) => {
|
||||
if (
|
||||
data?.CompId != null &&
|
||||
data?.CompId != undefined &&
|
||||
data?.BranchId != null &&
|
||||
data?.BranchId != undefined &&
|
||||
data?.AppId != null &&
|
||||
data?.AppId != undefined &&
|
||||
data?.prodName != null &&
|
||||
data?.prodName != undefined
|
||||
) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/ProductCardList?CompId=${data?.CompId}&BranchId=${data?.BranchId}&AppId=${data?.AppId} &prodName=${encodeURIComponent(data?.prodName)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const getPurProdvaraiantdata = createAsyncThunk(
|
||||
'PurchaseOrder/getPurProdvaraiantdata',
|
||||
async (data) => {
|
||||
if (
|
||||
data?.CompId !== null &&
|
||||
data?.CompId !== undefined &&
|
||||
data?.BranchId !== null &&
|
||||
data?.BranchId !== undefined &&
|
||||
data?.AppId !== null &&
|
||||
data?.AppId !== undefined &&
|
||||
data?.prodName !== null &&
|
||||
data?.prodName !== undefined
|
||||
) {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/ProductCardList?CompId=${data?.CompId}&BranchId=${data?.BranchId}&AppId=${data?.AppId}&prodName=${encodeURIComponent(data?.prodName)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const getProdInwarddata = createAsyncThunk(
|
||||
'getProdInwarddata',
|
||||
async (data) => {
|
||||
return await axiosRetailInstanceData.get(
|
||||
`/InwardDtl?CompId=${data?.CompId}&BranchId=${data?.BranchId}&AppId=${data?.AppId}&prodId=${data?.prodId}`
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const putComboStockdel = createAsyncThunk(
|
||||
'putComboStockdel/putComboStockdel',
|
||||
async (putData) => {
|
||||
return await axiosRetailInstanceData.put(`/ComboStock`, putData);
|
||||
}
|
||||
);
|
||||
|
||||
export const putComboPriceoffer = createAsyncThunk(
|
||||
'putComboPriceoffer/putComboPriceoffer',
|
||||
async (putData) => {
|
||||
return await axiosRetailInstanceData.put(`/ComboHdr`, putData);
|
||||
}
|
||||
);
|
||||
|
||||
export const putComboName = createAsyncThunk(
|
||||
'putComboName',
|
||||
async (putData) => {
|
||||
return await axiosRetailInstanceData.put(`/ComboNameChange`, putData);
|
||||
}
|
||||
);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue