diff --git a/README.md b/README.md new file mode 100644 index 0000000..a1f2377 --- /dev/null +++ b/README.md @@ -0,0 +1,2556 @@ +# POZO Retail Web to Andriod by using capcitor package + +A short description of what the project does. + +--- + +## 📦 Prerequisites + +Make sure you have the following installed: + +- Node.js (v20+ recommended) +- npm or yarn + +--- + +## 🔧 Required Changes Before Running the App + +Before running the application, make the following updates: + +### 1️⃣ Update Vite Config +Open the file: + + +// this is ProtecedRoute.jsx make sure need to cmd or add some thng like this before changing react to capcitor +import { useEffect, useState } from 'react'; +import { Routes, Route, useNavigate } from 'react-router-dom'; +import { useDispatch } from 'react-redux'; +import { + getEmpAccesData, + GenerateLogout, + getSAdminUserAccesData, + PricingAppPricingName, + checkSession, + getCompBranchData, + getCommonAppPreference, + changeWarehouse, +} from './Features/BrachLogin/BranchLogin.js'; +import { clearSession, getSession, sessionStore } from './Services/Others'; +import { + FeatureAddon, + GlobalFeatAddOnData, +} from './Features/BookingScreen/BookingData/BookingData.js'; +import { Suspense } from 'react'; +import { gettableData } from './Features/PreferenceMaster/PreferenceMaster.js'; +import { useSelector } from 'react-redux'; +import { useTemplate } from './utils/useTemplate.js'; + +const commonUrl = import.meta.env.ENV_COMMON_BASE_URL; +const subDirectory = import.meta.env.BASE_URL; + +const ProtectedRoutes = ({ routesConfig }) => { + // useTemplate( + // getSession('CompId'), + // getSession('BranchId'), + // getSession('AppId') + // ); + sessionStore('AppId', 2); + sessionStore('BranchId', 791); + sessionStore('AppName', 'Bakery'); + sessionStore('CompId', 657); + sessionStore('MobileNo', '8888888888'); + sessionStore('UserType', 'Admin'); + sessionStore('UserId', 286); + sessionStore('userName', 'Karthiga'); + + sessionStore( + 'auth','eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiODg4ODg4ODg4OCIsIlBhc3N3b3JkIjoiWkB6MTIzNCIsImF1ZCI6WyJodHRwczovL2FwaS5wb3pvLmRldi9wb3pvLXJldGFpbC1hcGkiLCJodHRwczovL2FwaS5wb3pvLmRldi9wb3pvLWNvbW1vbi1hcGkiLCJodHRwczovL2FwaS5wb3pvLmRldi9wb3pvLXNtcy1lbWFpbC10ZW1wbGF0ZS1hcGkiLCJodHRwczovL2FwaS5wb3pvLmRldi9wb3pvLWNvbW1vbi1hcGkiXSwiZXhwIjoxNzc0NjM3OTA5LCJpc3MiOiJodHRwczovL2FwaS5wb3pvLmRldi9Kd3RUb2tlbiJ9.TWDS0cuHGIDW_16EH2RS4z2B-wnuuPmMNd_lre505qY' + ); + const navigate = useNavigate(); + const dispatch = useDispatch(); + const UserType = getSession('UserType'); + const [hasRedirected, setHasRedirected] = useState(false); + const AppId = getSession('AppId'); + const CompId = getSession('CompId'); + const BranchId = getSession('BranchId'); + const UserId = getSession('UserId'); + const sessionId = getSession('SessionId'); + const Warehouse = getSession('Warehouse'); + const [accessCheckComplete, setAccessCheckComplete] = useState(false); + const FeatureAddonData = useSelector(GlobalFeatAddOnData); + useTemplate(657, 791, 2); + + useEffect(() => { + getApplicationPreference(); + }, []); + //sri + // useEffect(() => { + // if (Warehouse) { + // dispatch(changeWarehouse(true)); + // } + // }, [Warehouse]); + const getApplicationPreference = async () => { + await dispatch(getCommonAppPreference(AppId)).unwrap(); + }; + + 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) { + return response?.data?.data?.[0]?.EmpAccessDetails; + } + return null; + }; + + const getSadminUserAccess = async () => { + let data = { + UserId: UserId, + AppId: AppId, + }; + const response = await dispatch(getSAdminUserAccesData(data)).unwrap(); + if (response?.data?.statusCode === 1) { + return response?.data?.data?.[0]?.AppMenuAccessDetails; + } + return null; + }; + + const Dinein = async () => { + if (AppId && CompId && BranchId) { + let DineinData = { + AppId: AppId, + CompId: CompId, + BranchId: BranchId, + UserId: UserId, + }; + const response = await dispatch(gettableData(DineinData)).unwrap(); + if (response?.data?.statusCode === 1) { + const SettingValueData = response?.data?.data + ?.find((e) => e.AppId === AppId) + ?.SettingDtlDetails?.some( + (e) => e.SettingIdName === 'DineIn' && e.SettingValue === 'Y' + ); + const EstimateValueData = response?.data?.data + ?.find((e) => e.AppId === AppId) + ?.SettingDtlDetails?.some( + (e) => e.SettingIdName === 'Estimation' && e.SettingValue === 'Y' + ); + return (SettingValueData, EstimateValueData); + } + } + }; + + const checkAccess = async (empAccess) => { + if (!empAccess) return false; + let DineinData, + EstimateData = await Dinein(); + switch (empAccess) { + case 'Dine In': + case 'KOT': + return !!DineinData; + case 'Estimate': + return !!EstimateData; + default: + return false; // Restrict access if no valid match found + } + }; + + 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; + const pricingData = responseData?.data; + const hasAdvance = pricingData?.some( + (item) => item.PricingName === 'Premium' + ); + const hasProOrAdvance = + hasAdvance || + pricingData.some((item) => item.PricingName === 'Customized'); + return (hasAdvance, hasProOrAdvance); + } catch (error) { + console.error('Error fetching pricing name:', error); + } + }; + + const checkPlanAccess = async (empAccess, featureAddonData) => { + if (!empAccess) return false; + let Advance, + ProORAdvance = await getPricingName(); + switch (empAccess) { + case 'Product Catalogue': + return ( + ProORAdvance || + featureAddonData?.some( + (item) => item?.FeatureAddonName?.toLowerCase() === 'catalog' + ) + ); + case 'Sales Setup': + case 'Print Setup': + return ( + Advance || + featureAddonData?.some( + (item) => + item?.FeatureAddonName?.toLowerCase() === 'customized template' + ) + ); + case 'Kiosk Setup': + case 'Kiosk Sales': + return featureAddonData?.some( + (item) => item?.FeatureAddonName?.toLowerCase() === 'kiosk sales' + ); + default: + return false; // Restrict access if no valid match found + } + }; + + const checkEmpAccess = async (empAccess, currentPath) => { + if (!empAccess) return false; + const Access = await getEmpAccess(); + let accessType; + if (currentPath.endsWith('/new')) { + accessType = 'AddAccess'; + } else if (currentPath.endsWith('/update')) { + accessType = 'UpdateAccess'; + } else { + accessType = 'ReadAccess'; + } + // const config = Access?.find(config => + // config.ConfigName === empAccess && config[accessType] === 'Y' + // ); + const config = Access?.find( + (config) => + (config.ConfigName === empAccess && config[accessType] === 'Y') || + (currentPath.includes('supplier-master') && + (config.ConfigName === 'Supplier' || + config.ConfigName === 'Seller') && + config[accessType] === 'Y') + ); + + return !!config; + }; + + const checkSuperAdminUserAccess = async (empAccess, currentPath) => { + console.log('empAccessData1', empAccess, currentPath); + if (!empAccess) return false; + const Access = await getSadminUserAccess(); + let accessType; + if (currentPath.endsWith('/new')) { + accessType = 'AddAccess'; + } else if (currentPath.endsWith('/update')) { + accessType = 'UpdateAccess'; + } else { + accessType = 'ReadAccess'; + } + console.log('empAccessData2', Access, accessType); + // const config = Access?.find(config => + // config.MenuName === empAccess && config[accessType] === 'Y' + // ); + const config = Access?.find( + (config) => + (config.MenuName === empAccess && config[accessType] === 'Y') || + (currentPath.includes('supplier-master') && + (config.MenuName === 'Supplier' || config.MenuName === 'Seller') && + config[accessType] === 'Y') + ); + console.log('empAccessData3', config); + + return !!config; + }; + + const getEmpAccessFromChildren = (route, currentPath) => { + if (route.path === currentPath) { + return route.empAccess || null; + } + + if (route.children) { + for (const child of route.children) { + const childPath = `${route.path}/${child.path}`; + if (childPath === currentPath) { + return child.empAccess || null; + } + } + } + + return null; + }; + + const getEmpAccessDataFromChildren = (route, currentPath) => { + if (route.path === currentPath) { + return route.access || null; + } + if (route.children) { + for (const child of route.children) { + const childPath = `${route.path}/${child.path}`; + if (childPath === currentPath) { + return child.access || null; + } + } + } + return null; + }; + + const fetchBranchData = async () => { + const response = await dispatch( + getCompBranchData({ CompId: CompId, AppId: AppId }) + ).unwrap(); + if (response?.data?.statusCode === 1) { + if (response?.data?.data?.length == 1) { + navigate(`${subDirectory}`); + } else { + navigate(`${subDirectory}app-page/branch-login`); + } + } + }; + + + const Logout = async () => { + const status = 'N'; // replace with your actual status + const res = await dispatch(GenerateLogout({ UserId, status })).unwrap(); + if (res?.data?.statusCode === 1) { + sessionStorage.clear(); + window.location.replace(`${commonUrl}`); + } + }; + + const renderRoutes = (routes) => { + return routes.map(({ path, component: Component, children }) => { + const fullPath = `${path}`; + + if (!Component) { + console.error(`Component not found for path: ${fullPath}`); + return null; + } + + if (children) { + return ( + }> + {children.map(({ path: childPath, component: ChildComponent }) => { + if (!ChildComponent) { + console.error( + `Child component not found for path: ${childPath}` + ); + return null; + } + return ( + } + /> + ); + })} + + ); + } + + return } />; + }); + }; + + return ( + }> + {renderRoutes(routesConfig)} + + ); +}; + +export default ProtectedRoutes; +/// Routes config +import React from 'react'; +import { lazy } from 'react'; +const CommonMaster = lazy( + () => import('./Pages/CommonMaster/CommonMaster.jsx') +); +const ConfigType = lazy(() => import('./Pages/ConfigType/ConfigTypeForm.jsx')); +const AdminTax = lazy(() => import('./Pages/AdminTax/AdminTaxForm.jsx')); +const ProductForm = lazy(() => import('./Pages/Product/ProductForm.jsx')); +const Sport_ProductForm = lazy( + () => import('./Pages/Product/SportsMaster.jsx') +); +const ShiftMasterList = lazy( + () => import('./Pages/ShiftMaster/ShiftMasterList.jsx') +); +const ShiftMasterForm = lazy( + () => import('./Pages/ShiftMaster/ShiftMasterForm.jsx') +); +const EmployeeMasterList = lazy( + () => import('./Pages/EmpMaster/EmpMasterList.jsx') +); +const EmployeeMasterForm = lazy( + () => import('./Pages/EmpMaster/EmpMasterForm.jsx') +); + +const SupplierMasterList = lazy( + () => import('./Pages/SupplierMaster/SupplierMasterList.jsx') +); +const SupplierMasterForm = lazy( + () => import('./Pages/SupplierMaster/SupplierMasterForm.jsx') +); + +const ComponentMasterForm = lazy( + () => import('./Pages/UiComponentPage/ComponentForm.jsx') +); +const ComponentMasterList = lazy( + () => import('./Pages/UiComponentPage/ComponentList.jsx') +); + +const CustomerForm = lazy( + () => import('./Pages/CustomerMaster/CustMasterForm.jsx') +); +const CustomerMasterList = lazy( + () => import('./Pages/CustomerMaster/CustMasterList.jsx') +); + +const DateWiseReport = lazy( + () => import('./Pages/Reports/DateWiseReport/DateWiseReport.jsx') +); + +const ItemWiseReport = lazy( + () => import('./Pages/Reports/ItemWiseReport/ItemWiseReport.jsx') +); + +const Reprint = lazy( + () => + import('./Pages/BookingScreen/Components/OtherConponents/Reprint/BSReprint.jsx') +); + +const BookingSelectionPage = lazy( + () => import('./Pages/BookingScreen/Components/MainPage/MainPage.jsx') +); + +const PrintSelectionPage = lazy( + () => import('./Pages/BookingScreen/Components/PrintMainPage/MainPage.jsx') +); +const KioskMainPage = lazy( + () => import('./Pages/BookingScreen/Components/Kiosk/KioskMainPage.jsx') +); + +const BookingPage = lazy(() => import('./Pages/BookingScreen/BookingPage.jsx')); + +const StockForm = lazy(() => import('./Pages/StockMaster/StockForm.jsx')); + +const StockList = lazy(() => import('./Pages/StockMaster/StockList.jsx')); + +const DiningMasterList = lazy(() => import('./Pages/Dining/DiningList.jsx')); + +const DiningMasterForm = lazy(() => import('./Pages/Dining/DiningForm.jsx')); + +const TableBooking = lazy( + () => import('./Pages/Tablebooking/TableBooking.jsx') +); + +const ComboMaster = lazy(() => import('./Pages/ComboPack/ComboMaster.jsx')); + +const ComboList = lazy(() => import('./Pages/ComboPack/ComboMasterlist.jsx')); +const EmpAccessForm = lazy(() => import('./Pages/EmpAccess/EmpAccessForm.jsx')); +const EmpAccessList = lazy(() => import('./Pages/EmpAccess/EmpAccessList.jsx')); + +const EmpScreenAccessList = lazy( + () => import('./Pages/EmpScreenAccess/EmpScreenAccessList.jsx') +); +const EmpScreenRightsAccess = lazy( + () => import('./Pages/EmpScreenAccess/EmpScreenRightsAccess.jsx') +); + +const PreferenceList = lazy( + () => import('./Pages/Preference/PreferenceList.jsx') +); + +const PaymentOptions = lazy( + () => import('./Pages/Payment/PaymentOptions/PaymentOptions.jsx') +); +const PaymentDetails = lazy( + () => import('./Pages/Payment/PaymentDetails/PaymentDetailsForm.jsx') +); +const PaymentDetailsList = lazy( + () => import('./Pages/Payment/PaymentDetails/PaymentDetailsList.jsx') +); +const PaymentReceivedRetail = lazy( + () => + import('./Pages/Payment/PaymentReceivedRetail/PaymentReceivedRetail.jsx') +); + +const ExtraChargesList = lazy( + () => import('./Pages/ExtraCharges/ExtraChargesList.jsx') +); + +const BranchLogin = lazy(() => import('./Pages/BranchLogin/BranchLogin.jsx')); +const BackToBranchLogin = lazy( + () => import('./Pages/BranchLogin/BackToBranchLogin.jsx') +); +const Logout = lazy(() => import('./Pages/Logout.jsx')); + +const BacktoLogin = lazy(() => import('./Pages/BranchLogin/BacktoLogin.jsx')); + +const StockPriceUpdate = lazy( + () => import('./Pages/StockPriceUpdate/StockPriceUpdate.jsx') +); + +const ProductCatalogueList = lazy( + () => import('./Pages/ProductCatlogue/ProductcatlogueList.jsx') +); + +const KOT = lazy(() => import('./Pages/Reports/KOT/kot.jsx')); + +const CustomerKOTDisplay = lazy( + () => import('./Pages/Reports/KOT/CustomerKOTDisplay.jsx') +); + +const RedirectApps = lazy(() => import('./Pages/RedirectApps.jsx')); + +const WSTransaction = lazy( + () => import('./Pages/WholeSaleTransaction/WSSalesTransaction.jsx') +); + +const LedgerReport = lazy( + () => import('./Pages/Reports/LedgerReport/LedgerReport.jsx') +); +const PaymentDetailsPage = lazy( + () => + import('./Pages/BookingScreen/Components/BookingFunctionality/PaymentDetailsPage.jsx') +); + +const CreditCustomerPrint = lazy( + () => + import('./Pages/BookingScreen/Components/BookingFunctionality/CreditDownloadpage.jsx') +); + +const Cancellation = lazy( + () => import('./Pages/CancelReschedule/Cancellation.jsx') +); + +const ChangePaymentmode = lazy( + () => import('./Pages/CancelReschedule/ChangePaymentmode.jsx') +); + +const CancellationList = lazy( + () => import('./Pages/CancelReschedule/CancellationList.jsx') +); + +const CancelApplicableProd = lazy( + () => import('./Pages/CancelReschedule/CancelApplicableProd.jsx') +); + +const CancellationListPending = lazy( + () => import('./Pages/CancelReschedule/CancelPendingPayment.jsx') +); + +const AndroidApp = lazy(() => import('./Pages/AndroidApp/AndroidApp.jsx')); + +const EstimateItemWiseReport = lazy( + () => import('./Pages/Reports/Estimate/EstimateItemWiseReport.jsx') +); + +const EstimateDateWiseReport = lazy( + () => import('./Pages/Reports/Estimate/EstimateDateWiseReport.jsx') +); + +const OfferForm = lazy(() => import('./Pages/Offer/Offer/OfferFormNew.jsx')); + +const OfferList = lazy(() => import('./Pages/Offer/Offer/OfferListNew.jsx')); + +const ItemWise = lazy(() => import('./Pages/Offer/ItemOffer/ItemWiseForm.jsx')); +const SalesWiseForm = lazy( + () => import('./Pages/Offer/SalesOffer/SalesWiseForm.jsx') +); +const SalesWiseList = lazy( + () => import('./Pages/Offer/SalesOffer/SalesWiseList.jsx') +); + +const QuantityWise = lazy( + () => import('./Pages/Offer/QuantityOffer/QuantityWiseForm.jsx') +); + +const BuyOneGetOneForm = lazy( + () => import('./Pages/Offer/BuyOneGetOneOffer/BuyOneGetOneForm.jsx') +); + +const LoyaltyPointsList = lazy( + () => import('./Pages/Offer/LoyaltyPoints/LoyaltyPointsList.jsx') +); + +const BundleOfferForm = lazy( + () => import('./Pages/Offer/BundleOffer/BundleOfferForm.jsx') +); +const BundleOfferList = lazy( + () => import('./Pages/Offer/BundleOffer/BundleOfferList.jsx') +); +const CouponWiseOfferlist = lazy( + () => import('./Pages/Offer/CouponOffer/CouponWiseOfferlist.jsx') +); + +const PromocodeList = lazy( + () => import('./Pages/Offer/PromoCode/PromocodeList.jsx') +); + +const OfferCodeList = lazy( + () => import('./Pages/Offer/OfferCode/OfferCodeList.jsx') +); + +const PricingPage = lazy( + () => + import('./Pages/BookingScreen/Components/UtillComponents/PricingPage.jsx') +); + +const PurchaseOrder = lazy( + () => import('./Pages/PurchaseOrder/PurchaseOrder.jsx') +); + +const PurchaseOrderMail = lazy( + () => import('./Pages/PurchaseOrder/PurchaseOrderMail.jsx') +); + +const PurchaseOrderList = lazy( + () => import('./Pages/PurchaseOrder/PurchaseOrderList.jsx') +); + +const StockReceivedList = lazy( + () => import('./Pages/StockTransfer/StockReceivedList.jsx') +); + +const GstInvoiceSetUpForm = lazy( + () => import('./Pages/GstInvoiceSetup/GstInvoiceSetUpForm.jsx') +); + +const gstInvoiceSetUpList = lazy( + () => import('./Pages/GstInvoiceSetup/GstInvoiceSetupList.jsx') +); + +const StockinHand = lazy(() => import('./Pages/StockinHand/StockinHand.jsx')); + +const PurchaseReturn = lazy( + () => import('./Pages/PurchaseReturn/purchaseReturn.jsx') +); + +const PurchaseReturnget = lazy( + () => import('./Pages/PurchaseReturn/PurchaseReturnGet.jsx') +); + +const KioskBookingPage = lazy( + () => import('./Pages/Kiosk/KioskBookingPage.jsx') +); + +const KioskBookingReceipt = lazy( + () => import('./Pages/Kiosk/PaymentGateway/PaymentGatewayReceipt.jsx') +); + +const KioskComponentList = lazy( + () => import('./Pages/KioskComponent/KioskComponentList.jsx') +); + +const CustomerDisplay = lazy( + () => import('./Pages/CustomerDisplay/CustomerDisplay.jsx') +); + +const PurchaseQuotationForm = lazy( + () => import('./Pages/PurchaseQuotation/PurchaseQuotationForm.jsx') +); + +const DeliveryChallanForm = lazy( + () => import('./Pages/DeliveryChallan/Deliverychallan.jsx') +); + +const DeliveryChallanList = lazy( + () => import('./Pages/DeliveryChallan/DeliverychallanList.jsx') +); + +const ComboOfferMaster = lazy( + () => import('./Pages/Offer/ComboOfferPack/ComboOfferForm.jsx') +); + +const PaymentDeviceForm = lazy( + () => import('./Pages/Payment/PaymentDevice/PaymentDeviceForm.jsx') +); +const PaymentFailedDetailsList = lazy( + () => + import('./Pages/Payment/PaymentFailedDetails/PaymentFailedDetailsList.jsx') +); + +const CounterCategoryMappingForm = lazy( + () => import('./Pages/CounterCategoryMapping/CounterCategoryMappingForm.jsx') +); + +const ImageBulkUpload = lazy( + () => import('./Pages/ImageBulkUpload/ImageBulkUpload.jsx') +); + +const WholesaleBookingPage = lazy( + () => import('./Pages/PurchaseScreen/LayoutScreen8/LayoutScreen8.jsx') +); + +const WholeSaleProductList = lazy( + () => import('./Pages/Wholesale/ProductList.jsx') +); + +const ProductEntry = lazy(() => import('./Pages/Wholesale/ProductEntry.jsx')); + +const ProductEntryList = lazy( + () => import('./Pages/Wholesale/ProductEntryList.jsx') +); +const ItemEntry = lazy( + () => import('./Pages/Wholesale/ItemEntry/ItemEntry.jsx') +); + +const WsPreorder = lazy( + () => import('./Pages/Wholesalespreorder/WholesalePreorderList.jsx') +); + +const WsPreorderForm = lazy( + () => import('./Pages/Wholesalespreorder/WholesalePreorderForm.jsx') +); + +const ExtraChrgesList = lazy( + () => import('./Pages/Wholesale/ItemEntry/ExtraChrgesList.jsx') +); + +const SalesBillCancel = lazy( + () => import('./Pages/SalesRemoval/SalesBillCancelList.jsx') +); + +const WholeSaleAbstract = lazy( + () => import('./Pages/WholeSaleAbstract/WholeSaleAbstract.jsx') +); + +const WholeSaleSellerAbstract = lazy( + () => import('./Pages/WholeSaleAbstract/WholeSaleSellerAbstract.jsx') +); + +const PaymentReceived = lazy( + () => import('./Pages/WholeSaleTransaction/PaymentReceived.jsx') +); + +const WholeSaleSalesReport = lazy( + () => import('./Pages/WholeSaleReport/WholeSalesSalesReport.jsx') +); + +const WholeSalePurchaseReport = lazy( + () => import('./Pages/WholeSaleReport/WholeSalePurchaseReport.jsx') +); +const WholeSalePaymentPurchaseReport = lazy( + () => + import('./Pages/WholesalePaymentReport/WholeSalePaymentPurchaseReport.jsx') +); + +const WholeSalePaymentSalesReport = lazy( + () => + import('./Pages/WholesalePaymentReport/WholeSalePaymementSaleReport.jsx') +); + +const SpeechLanguagesList = lazy( + () => import('./Pages/SpeechLanguages/SpeechLanguagesList.jsx') +); + +const LegderList = lazy( + () => import('./Pages/WholeSaleLedger/WholeSaleLedger.jsx') +); + +const SellerMasterTran = lazy( + () => import('./Pages/WholeSaleTransaction/SellerMasterTransaction.jsx') +); + +const TicketForm = lazy(() => import('./Pages/Ticket/TicketForm.jsx')); + +const ThemeCreation = lazy( + () => import('./Pages/BookingScreen/Components/ThemeCreation/ThemeList.jsx') +); + +const ThemeSelection = lazy( + () => + import('./Pages/BookingScreen/Components/ThemeCreation/ThemePreview.jsx') +); + +const BarcodeTemplateSetup = lazy( + () => import('./Pages/BarcodeSetup/BarcodeTemplateSetup.jsx') +); + +const BarcodeComponentList = lazy( + () => import('./Pages/BarcodeComponent/BarcodeComponentList.jsx') +); + +const StoreRecipelist = lazy( + () => import('./Pages/StoreKitchen/StoreRecipe/StoreRecipelist.jsx') +); + +const StoreRecipeform = lazy( + () => import('./Pages/StoreKitchen/StoreRecipe/StoreRecipeform.jsx') +); + +const Storekitchenlist = lazy( + () => import('./Pages/StoreKitchen/StoretoKitchen/StoretoKitchenlist.jsx') +); + +const StoreKitchenform = lazy( + () => import('./Pages/StoreKitchen/StoretoKitchen/Storetokitchenform.jsx') +); +import { getSession, sessionStore } from './Services/Others'; +import axios from 'axios'; +const KitchenFinishlist = lazy( + () => import('./Pages/StoreKitchen/StoreKitchenFinish/KitchenFinishlist.jsx') +); +const KitechenFinishform = lazy( + () => import('./Pages/StoreKitchen/StoreKitchenFinish/KitechenFinishform.jsx') +); + +const FreeProductList = lazy( + () => import('./Pages/FreeProducts/FreeProduct/FreeProductList.jsx') +); + +const FreePurchaseEnteryForm = lazy( + () => + import('./Pages/FreeProducts/FreePurchase/FreePurchaseEntery/FreePurchaseEnteryForm.jsx') +); +const FreePurchaseEnteryList = lazy( + () => + import('./Pages/FreeProducts/FreePurchase/FreePurchaseEntery/FreePurchaseEnteryList.jsx') +); + +const FreePurchaseOrderList = lazy( + () => + import('./Pages/FreeProducts/FreePurchase/FreePurchaseOrder/FreePurchaseOrderList.jsx') +); +const FreePurchaseOrderForm = lazy( + () => + import('./Pages/FreeProducts/FreePurchase/FreePurchaseOrder/FreePurchaseOrderForm.jsx') +); + +const FreePurchaseReturnList = lazy( + () => + import('./Pages/FreeProducts/FreePurchase/FreePurchaseReturn/FreePurchaseReturnList.jsx') +); +const FreePurchaseReturnForm = lazy( + () => + import('./Pages/FreeProducts/FreePurchase/FreePurchaseReturn/FreePurchaseReturnForm.jsx') +); +const CommonForm = lazy( + () => import('./Pages/Offer/LoyaltyPoints/CommonForm.jsx') +); + +const ReprintReasonReportList = lazy( + () => + import('./Pages/Reports/ReprintReasonReport/ReprintReasonReportList.jsx') +); + +const RevenueItemWiseReport = lazy( + () => import('./Pages/Reports/Revenue/RevenueItemWiseReport.jsx') +); + +const LinkUrlCreate = lazy( + () => import('./Pages/paymentpdfPage/LinkUrlCreate.jsx') +); + +const SupplierProductMapping = lazy( + () => import('./Pages/SupplierProductMapping/SupplierProductMapping.jsx') +); + +const RedirectUserProfile = lazy( + () => import('./Pages/RedirectUserProfile.jsx') +); + +const RelieveRequestForm = lazy( + () => import('./Pages/EmpMaster/EmpRelieve.jsx') +); + +const PurchaseQuotationList = lazy( + () => import('./Pages/PurchaseQuotation/PurchaseQuotationList.jsx') +); + +const ExchangeAndReplacementList = lazy( + () => import('./Pages/ExchangeAndReplacement/ExchangeAndReplacementList.jsx') +); +const ExchangeAndReplacementForm = lazy( + () => import('./Pages/ExchangeAndReplacement/ExchangeAndReplacementForm.jsx') +); + +const ExchangeReturnMapForm = lazy( + () => import('./Pages/ExchangeReturnMap/ExchangeReturnMapForm.jsx') +); +const ExchangeReturnMapList = lazy( + () => import('./Pages/ExchangeReturnMap/ExchangeReturnMapList.jsx') +); + +const OtherServicesForm = lazy( + () => import('./Pages/OtherServices/OtherServicesForm.jsx') +); +const OtherServicesList = lazy( + () => import('./Pages/OtherServices/OtherServicesList.jsx') +); +const EmpCommisionOrIncentiveForm = lazy( + () => + import('./Pages/EmpCommissionOrIncentive/EmpCommisionOrIncentiveForm.jsx') +); + +const EmpCommisionOrIncentiveList = lazy( + () => + import('./Pages/EmpCommissionOrIncentive/EmpCommisionOrIncentiveList.jsx') +); + +const SalesBillProductsReturnList = lazy( + () => import('./Pages/CancelReschedule/SalesBillProductReturnList.jsx') +); + +const SalesBillProductsReturn = lazy( + () => import('./Pages/CancelReschedule/SalesBillProductsReturn.jsx') +); + +const DeliveryChallanToInvoiceForm = lazy( + () => + import('./Pages/DeliveryChallanToInvoice/DeliveryChallanToInvoiceForm.jsx') +); + +const DeliveryChallanToInvoiceList = lazy( + () => + import('./Pages/DeliveryChallanToInvoice/DeliveryChallanToInvoiceList.jsx') +); + +const TipAmountSettlementList = lazy( + () => + import('./Pages/Reports/TipAmountSettlement/TipAmountSettlementList.jsx') +); + +const EmployeeSettlement = lazy( + () => import('./Pages/Reports/EmployeeSettlement/EmployeeSettlement.jsx') +); +const Settlement = lazy( + () => import('./Pages/Reports/TipAmountSettlement/Settlement.jsx') +); +const PublicQrCode = lazy(() => import('./Pages/Reports/PublicQrCode.jsx')); + +const TableMapping = lazy( + () => import('./Pages/TableMapping/TableMapping.jsx') +); +const TableMAppingList = lazy( + () => import('./Pages/TableMapping/TableMAppingList.jsx') +); + +const PurchaseOrderReport = lazy( + () => import('./Pages/Reports/PurchaseReport/PurchaseOrderReport.jsx') +); + +const SalesOrder = lazy(() => import('./Pages/SalesOrder/SalesOrder.jsx')); + +const LoyaltyBased = lazy( + () => import('./Pages/Offer/LoyaltyBased/LoyaltyBased.jsx') +); +const LoyaltyBasedList = lazy( + () => import('./Pages/Offer/LoyaltyBased/LoyaltyBasedList.jsx') +); +const CodeBase = lazy(() => import('./Pages/Offer/CodeBase/CodeBase.jsx')); +const CodeBaseList = lazy( + () => import('./Pages/Offer/CodeBase/CodeBaseList.jsx') +); + +const TurboAddForm = lazy(() => import('./Pages/Product/TurboAddForm.jsx')); + +const ProductMaster = lazy(() => import('./Pages/Product/ProductMaster.jsx')); + +const GatewayMasterConfiguration = lazy( + () => + import('./Pages/GatewayMasterConfiguration/GatewayMasterConfiguration.jsx') +); +const GatewayMasterConfigurationList = lazy( + () => + import('./Pages/GatewayMasterConfiguration/GatewayMasterConfigurationList.jsx') +); + +const MembershipForm = lazy( + () => import('./Pages/Membership/MembershipForm.jsx') +); +const MembershipList = lazy( + () => import('./Pages/Membership/MembershipList.jsx') +); +const SlotManagementForm = lazy( + () => import('./Pages/SlotManagement/SlotManagement.jsx') +); +const SlotManagementList = lazy( + () => import('./Pages/SlotManagement/SlotManagementList.jsx') +); + +const BookingReScedule = lazy( + () => import('./Pages/CancelReschedule/BookingReScedule.jsx') +); +const BookingReSceduleList = lazy( + () => import('./Pages/CancelReschedule/BookingReSceduleList.jsx') +); + +const MembershipReport = lazy( + () => import('./Pages/Reports/Membership/MembershipReport.jsx') +); +const OpeningStock = lazy( + () => import('./Pages/openingStock/openingstockForm.jsx') +); +const OpeningStockList = lazy( + () => import('./Pages/openingStock/OpeningStockList.jsx') +); + +const StockAdjustment = lazy( + () => import('./Pages/StockAdjustment/StockAdjustment.jsx') +); +const StockAdjustmentList = lazy( + () => import('./Pages/StockAdjustment/StockAdjustmentList.jsx') +); +const TopSellingProducts = lazy( + () => import('./Pages/DashBoard/TopSellingProductsChart.jsx') +); + +const AutomatedReorder = lazy( + () => import('./Pages/Automated Reorder/AutomatedReorder.jsx') +); +const AutomatedReorderList = lazy( + () => import('./Pages/Automated Reorder/AutomatedReorderList.jsx') +); + +const CustomerPurchaseConfirm = lazy( + () => + import('./Pages/PurchaseOrder/CustomerPurchaseConfirm/CustomerPurchaseConfirm.jsx') +); + +const MenuQRCode = lazy( + () => import('./Pages/Reports/MenuQRCode/MenuQRCode.jsx') +); + +const PurchaseLink = lazy( + () => import('./Pages/PurchaseOrder/CustomerPurchaseConfirm/PurchaseLink.jsx') +); +const RackForm = lazy(() => import('./Pages/Rack/RackForm.jsx')); +const RackList = lazy(() => import('./Pages/Rack/RackList.jsx')); + +const CreateTransfer = lazy( + () => import('./Pages/StockTransfer/CreateTransfer.jsx') +); +const Dispatch = lazy(() => import('./Pages/StockTransfer/Dispatch.jsx')); +const StockTransferList = lazy( + () => import('./Pages/StockTransfer/TransferList.jsx') +); + +const ComboLayout3 = lazy( + () => import('./Pages/BookingScreen/Template/ComboLayout3/ComboLayout3.jsx') +); + +const Productcatlogue = lazy( + () => import('./Pages/ProductCatlogue/Productcatalogue.jsx') +); + +const subDirectory = import.meta.env.BASE_URL; +const apiCommonUrl = import.meta.env.ENV_API_URL_COMMON; + +const initSession = () => { + sessionStore('AppId', 2); + sessionStore('BranchId', 791); + sessionStore('AppName', 'Bakery'); + sessionStore('CompId', 657); + sessionStore('MobileNo', '8888888888'); + sessionStore('UserType', 'Admin'); + sessionStore('UserId', 286); + sessionStore('userName', 'Karthiga'); + + sessionStore( + 'auth','eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiODg4ODg4ODg4OCIsIlBhc3N3b3JkIjoiWkB6MTIzNCIsImF1ZCI6WyJodHRwczovL2FwaS5wb3pvLmRldi9wb3pvLXJldGFpbC1hcGkiLCJodHRwczovL2FwaS5wb3pvLmRldi9wb3pvLWNvbW1vbi1hcGkiLCJodHRwczovL2FwaS5wb3pvLmRldi9wb3pvLXNtcy1lbWFpbC10ZW1wbGF0ZS1hcGkiLCJodHRwczovL2FwaS5wb3pvLmRldi9wb3pvLWNvbW1vbi1hcGkiXSwiZXhwIjoxNzc0NjM3OTA5LCJpc3MiOiJodHRwczovL2FwaS5wb3pvLmRldi9Kd3RUb2tlbiJ9.TWDS0cuHGIDW_16EH2RS4z2B-wnuuPmMNd_lre505qY' + ); +}; + +const getAppType = async () => { + // 🔥 If already stored, don't call API again + const storedType = getSession('AppType'); + if (storedType) { + return storedType === 'Wholesale'; + } + + const AppId = getSession('AppId'); + if (!AppId) return null; + + const response = await axios.get( + `${apiCommonUrl}/application?AppId=${AppId}` + ); + + const subCategoryName = + response?.data?.data?.[0]?.SubCategoryName?.toLowerCase(); + + const isWholesale = subCategoryName === 'wholesale'; + + sessionStore('AppType', isWholesale ? 'Wholesale' : 'Sale'); + + return isWholesale; +}; + +const fetchComponent = async () => { + try { + initSession(); + + const isWholesale = await getAppType(); + if (isWholesale === null) return null; + + return isWholesale + ? import('./Pages/AppPage/WholesaleAppPage.jsx') + : import('./Pages/AppPage/AppPage.jsx'); + } catch (err) { + console.error('API call failed:', err); + return null; + } +}; +const fetchHomeComponent = async () => { + try { + initSession(); + + const isWholesale = await getAppType(); + if (isWholesale === null) return null; + + return isWholesale + ? import('./Pages/DashBoard/WholesaleDashboard.jsx') + : import('./Pages/DashBoard/RetailDashboard.jsx'); + } catch (err) { + console.error('API call failed:', err); + return null; + } +}; + +export const routesConfig = [ + { path: `${subDirectory}customer-display`, component: CustomerDisplay }, + { path: `${subDirectory}PricingPage`, component: PricingPage }, + { + path: `${subDirectory}android-app`, + component: AndroidApp, + empAccess: 'Android App', + }, + { path: `${subDirectory}purchaseordermail`, component: PurchaseOrderMail }, + { + path: `${subDirectory}viewbill`, + component: LinkUrlCreate, + empAccess: 'View Bill', + }, + // writed b=y sree + // { + // path: `${subDirectory}MenuQRCode`, + // component: CustomerMenuPage, + // }, + { + path: `${subDirectory}purchaseconfirm`, + component: CustomerPurchaseConfirm, + }, + { + path: `${subDirectory}viewpurchaseorder`, + component: PurchaseLink, + }, + { + path: `${subDirectory}combolayout3`, + component: ComboLayout3, + }, + + { + path: `${subDirectory}`, + component: React.lazy(() => + fetchComponent().then((module) => ({ default: module.default })) + ), + children: [ + { + path: '/', + component: React.lazy(() => + fetchHomeComponent().then((module) => ({ default: module.default })) + ), + }, + { path: `relieve-request`, component: RelieveRequestForm }, + { path: 'branch-login', component: BranchLogin }, + { path: 'branch-all', component: BackToBranchLogin }, + { path: 'back-to-login', component: BacktoLogin }, + { path: 'logout', component: Logout }, + { path: 'redirect-apps', component: RedirectApps }, + { path: 'redirect-userprofile', component: RedirectUserProfile }, + // { path: 'transaction', component: WSTransaction } + ], + }, + { + path: `${subDirectory}qrprint`, + component: CreditCustomerPrint, + empAccess: 'Public', + }, + { path: `${subDirectory}sales`, component: BookingPage, empAccess: 'Sales' }, + { + path: `${subDirectory}wholesales`, + component: WholesaleBookingPage, + empAccess: 'Whole Sales', + }, + { + path: `${subDirectory}kiosksales`, + component: KioskBookingPage, + empAccess: 'Kiosk Sales', + }, + { + path: `${subDirectory}kiosk-receipt`, + component: KioskBookingReceipt, + empAccess: 'Public', + }, + { + path: `${subDirectory}payment-page`, + component: PaymentDetailsPage, + empAccess: 'Public', + }, + { path: `${subDirectory}reprint`, component: Reprint }, + { + path: `${subDirectory}transaction`, + component: React.lazy(() => + fetchComponent().then((module) => ({ default: module.default })) + ), + children: [ + { path: 'sales', component: WSTransaction, empAccess: 'Sales' }, + { path: 'payment-received', component: PaymentReceived }, + { path: 'seller-payment', component: SellerMasterTran }, + ], + }, + { + path: `${subDirectory}kitchen`, + component: React.lazy(() => + fetchComponent().then((module) => ({ default: module.default })) + ), + children: [ + { path: 'kot', component: KOT, empAccess: 'KOT' }, + { + path: 'kot-display', + component: CustomerKOTDisplay, + empAccess: 'KOT Display', + }, + ], + }, + { + path: `${subDirectory}report`, + component: React.lazy(() => + fetchComponent().then((module) => ({ default: module.default })) + ), + children: [ + { + path: 'PublicQrCode', + component: PublicQrCode, + empAccess: 'SelfBooking QR Code', + }, + { + path: 'MenuQRCode', + component: MenuQRCode, + empAccess: 'MenuQRCode', + }, + // { + // path: 'tipamountsettlementlist', + // component: TipAmountSettlementList, + // empAccess: 'Tips', + // }, + // { + // path: 'EmployeeSettlement', + // component: EmployeeSettlement, + // empAccess: 'Incentive', + // }, + { + path: 'Settlement', + component: Settlement, + empAccess: 'Settlement', + }, + + { + path: 'datewisereport', + component: DateWiseReport, + empAccess: 'Daily Sales', + }, + { + path: 'itemwisereport', + component: ItemWiseReport, + empAccess: 'By Item', + }, + { + path: 'top-selling-products', + component: TopSellingProducts, + empAccess: 'Top Selling Products', + }, + { + path: 'estimateitemwisereport', + component: EstimateItemWiseReport, + empAccess: 'By Item', + }, + { + path: 'estimatedatewisereport', + component: EstimateDateWiseReport, + empAccess: 'Daily Sales', + }, + { path: 'ledgerreport', component: LedgerReport, empAccess: 'Ledger' }, + { path: 'ledger', component: LegderList, empAccess: 'Ledger' }, + { + path: 'stock-in-hand', + component: StockinHand, + empAccess: 'Stock Inhand', + }, + { + path: 'abstract', + component: WholeSaleAbstract, + empAccess: 'Abstract For Sales', + }, + { + path: 'sellerabstract', + component: WholeSaleSellerAbstract, + empAccess: 'Abstract For Purchase', + }, + { + path: 'salesreport', + component: WholeSaleSalesReport, + empAccess: 'Daily Sales', + }, + { + path: 'purchasereport', + component: WholeSalePurchaseReport, + empAccess: 'Purchase', + }, + { + path: 'paymentpurchasereport', + component: WholeSalePaymentPurchaseReport, + empAccess: 'Purchase Payment', + }, + { + path: 'paymentsalesreport', + component: WholeSalePaymentSalesReport, + empAccess: 'Sales Payment', + }, + { + path: 'reprintreasonreport', + component: ReprintReasonReportList, + empAccess: 'Reprint Details', + }, + { + path: 'membership', + component: MembershipReport, + empAccess: 'Membership Report', + }, + { + path: 'revenueitemWisereport', + component: RevenueItemWiseReport, + empAccess: 'Gross Margin', + }, + + { + path: 'PurchaseOrderReport', + component: PurchaseOrderReport, + empAccess: 'Purchase', + }, + ], + }, + { + path: `${subDirectory}setting`, + component: React.lazy(() => + fetchComponent().then((module) => ({ default: module.default })) + ), + children: [ + { + path: 'common-master', + component: CommonMaster, + empAccess: 'Common Master', + }, + { + path: 'other-services', + component: OtherServicesList, + empAccess: 'OtherServices', + }, + { + path: 'other-services/new', + component: (props) => , + empAccess: 'OtherServices', + }, + { + path: 'other-services/update', + component: (props) => , + empAccess: 'OtherServices', + }, + { + path: 'config-type', + component: ConfigType, + access: 'Super Admin', + empAccess: 'Config Type', + }, + { + path: 'languages', + component: SpeechLanguagesList, + access: 'Super Admin', + empAccess: 'Languages', + }, + { + path: 'preference', + component: PreferenceList, + empAccess: 'Preference', + }, + { + path: 'price-change', + component: StockPriceUpdate, + empAccess: 'Price Change', + }, + { + path: 'extra-charges', + component: ExtraChargesList, + empAccess: 'Extra Charges', + }, + { + path: 'Exchange-Return-policy', + component: ExchangeAndReplacementList, + empAccess: 'Exchange / Return', + }, + { + path: 'Exchange-Return-policy/new', + component: (props) => ( + + ), + empAccess: 'Exchange / Return', + }, + { + path: 'exchange-return-mapping', + component: ExchangeReturnMapList, + empAccess: 'Rules Mapping', + }, + { + path: 'exchange-return-mapping/new', + component: (props) => ( + + ), + empAccess: 'Rules Mapping', + }, + + { + path: 'product-catalogue-list', + component: ProductCatalogueList, + empAccess: 'Product Catalogue', + }, + { + path: 'product-catalogue', + component: Productcatlogue, + empAccess: 'Product Catalogue', + }, + { path: 'admin-tax', component: AdminTax, empAccess: 'Tax' }, + { + path: 'create-ticket', + component: TicketForm, + empAccess: 'Create Ticket', + }, + { + path: 'payment-options', + component: PaymentOptions, + empAccess: 'Payment Options', + }, + { + path: 'payment-received-retail', + component: PaymentReceivedRetail, + empAccess: 'Payment Updates', + }, + { + path: 'payment-device-access', + component: PaymentDeviceForm, + empAccess: 'Payment Device Access', + }, + { + path: 'counter-category-mapping', + component: CounterCategoryMappingForm, + empAccess: 'Counter Mapping', + }, + + { + path: 'wholesale-product-master', + component: WholeSaleProductList, + empAccess: 'Product', + }, + { + path: 'product-entry', + component: ProductEntryList, + empAccess: 'Product Entry', + }, + { + path: 'product', + component: ProductMaster, + empAccess: 'Product Entry', + }, + + { + path: 'product-entry/new', + component: (props) => , + empAccess: 'Product Entry', + }, + { + path: 'wholesale-extracharges/new', + component: ItemEntry, + empAccess: 'Extra Charges', + }, + { + path: 'wholesale-extracharges', + component: ExtraChrgesList, + empAccess: 'Extra Charges', + }, + { + path: 'membership-master/list', + component: MembershipList, + empAccess: 'Membership', + }, + { + path: 'membership-master/new', + component: (props) => , + empAccess: 'Membership', + }, + { + path: 'membership-master/update', + component: (props) => , + empAccess: 'Membership', + }, + + { + path: 'opening-stock/new', + component: OpeningStock, + empAccess: 'Opening Stock', + }, + { + path: 'opening-stock', + component: OpeningStockList, + empAccess: 'Opening Stock', + }, + { + path: 'stock-adjustment', + component: StockAdjustment, + empAccess: 'Stock Adjustment', + }, + { + path: 'stock-adjustment-list', + component: StockAdjustmentList, + empAccess: 'Stock Adjustment', + }, + { + path: 'product-master', + component: ProductMaster, + empAccess: 'Add Product', + }, + { + path: 'product-master/combo', + component: ProductMaster, + component: (props) => , + empAccess: 'Add Product', + }, + { + path: 'product-master/new', + component: (props) => , + empAccess: 'Add Product', + }, + { + path: 'products-master/new', + component: (props) => , + empAccess: 'Add Product', + }, + { + path: 'products-master/update', + component: (props) => , + empAccess: 'Add Product', + }, + { + path: 'product-master/update', + component: (props) => , + empAccess: 'Add Product', + }, + { + path: 'product-master/turbo-add', + component: (props) => , + empAccess: 'Add Product', + }, + { + path: 'image-bulk-upload', + component: ImageBulkUpload, + empAccess: 'Image Upload', + }, + { + path: 'rack-master', + component: RackList, + empAccess: 'Add Rack', + }, + { + path: 'rack-master/new', + component: (props) => , + empAccess: 'Add Rack', + }, + { + path: 'rack-master/update', + component: (props) => , + empAccess: 'Add Rack', + }, + { + path: 'slot-management', + component: (props) => , + empAccess: 'Slot Management', + }, + { + path: 'slot-management-list', + component: (props) => , + empAccess: 'Slot Management', + }, + { + path: 'productBased-offer', + component: OfferList, + empAccess: 'Product Based', + }, + + { + path: 'productBased-offer/new', + component: (props) => , + empAccess: 'Product Based', + }, + { + path: 'productBased-offer/update', + component: (props) => , + empAccess: 'Product Based', + }, + { + path: 'code-base', + component: CodeBaseList, + empAccess: 'Code Based', + }, + { + path: 'code-base/new', + component: (props) => , + empAccess: 'Code Based', + }, + { + path: 'code-base/new', + component: (props) => , + empAccess: 'Code Based', + }, + + { path: 'item-wise', component: ItemWise, empAccess: 'Item Wise Offer' }, + { + path: 'quantity-wise', + component: QuantityWise, + empAccess: 'Quantity Wise Offer', + }, + { + path: 'buyone-getone', + component: BuyOneGetOneForm, + empAccess: 'Buy X and Get X or Y', + }, + + { + path: 'sales-wise', + component: SalesWiseList, + empAccess: 'Sales Wise Offer', + }, + { + path: 'sales-wise/new', + component: (props) => , + empAccess: 'Sales Wise Offer', + }, + { + path: 'sales-wise/update', + component: (props) => , + empAccess: 'Sales Wise Offer', + }, + + { + path: 'loyalty-point', + component: LoyaltyPointsList, + empAccess: 'Loyalty Cards', + }, + { + path: 'loyalty-based', + // component: LoyaltyBased, + component: LoyaltyBasedList, + empAccess: 'Loyalty Points', + }, + { + path: 'loyalty-based/new', + component: (props) => , + empAccess: 'Loyalty Points', + }, + { + path: 'loyalty-based/update', + component: (props) => , + empAccess: 'Loyalty Points', + }, + + { + path: 'loyalty-point/new', + component: (props) => ( + + ), + empAccess: 'Loyalty Cards', + }, + { + path: 'loyalty-point/update', + component: (props) => ( + + ), + empAccess: 'Loyalty Cards', + }, + // { path: 'loyalty-point/new', component: (props) => , empAccess: "Loyalty Cards" }, + // { path: 'loyalty-point/update', component: (props) => , empAccess: "Loyalty Cards" }, + + { + path: 'bundle-offer', + component: BundleOfferList, + empAccess: 'Bundle Offer', + }, + { + path: 'bundle-offer/new', + component: (props) => , + empAccess: 'Bundle Offer', + }, + { + path: 'bundle-offer/update', + component: (props) => , + empAccess: 'Bundle Offer', + }, + + { + path: 'coupon', + component: CouponWiseOfferlist, + empAccess: 'Coupon Wise Offer', + }, + { + path: 'coupon/new', + component: (props) => ( + + ), + empAccess: 'Coupon Wise Offer', + }, + { + path: 'coupon/update', + component: (props) => ( + + ), + empAccess: 'Coupon Wise Offer', + }, + // { path: 'coupon/new', component: (props) => , empAccess: "Coupon Wise Offer" }, + // { path: 'coupon/update', component: (props) => , empAccess: "Coupon Wise Offer" }, + + { path: 'promo-code', component: PromocodeList, empAccess: 'Promo Code' }, + { + path: 'promo-code/new', + component: (props) => ( + + ), + empAccess: 'Promo Code', + }, + { + path: 'promo-code/update', + component: (props) => ( + + ), + empAccess: 'Promo Code', + }, + // { path: 'promo-code/new', component: (props) => , empAccess: "Promo Code" }, + // { path: 'promo-code/update', component: (props) => , empAccess: "Promo Code" }, + + { path: 'offer-code', component: OfferCodeList, empAccess: 'Offer Code' }, + { + path: 'offer-code/new', + component: (props) => ( + + ), + empAccess: 'Offer Code', + }, + { + path: 'offer-code/update', + component: (props) => ( + + ), + empAccess: 'Offer Code', + }, + // { path: 'offer-code/new', component: (props) => , empAccess: "Offer Code" }, + // { path: 'offer-code/update', component: (props) => , empAccess: "Offer Code" }, + + { + path: 'customer-master', + component: CustomerMasterList, + empAccess: 'Customer', + }, + { + path: 'customer-master/new', + component: (props) => , + empAccess: 'Customer', + }, + { + path: 'customer-master/update', + component: (props) => , + empAccess: 'Customer', + }, + { + path: 'automated-reorder', + component: AutomatedReorderList, + empAccess: 'Automated Reorder', + }, + { + path: 'automated-reorder/new', + component: (props) => , + empAccess: 'Automated Reorder', + }, + { + path: 'automated-reorder/update', + component: (props) => , + empAccess: 'Automated Reorder', + }, + { + path: 'purchase-entry', + component: StockList, + empAccess: 'Product Receipt', + }, + { + path: 'purchase-entry/new', + component: (props) => , + empAccess: 'Product Receipt', + }, + { + path: 'purchase-entry/update', + component: (props) => , + empAccess: 'Product Receipt', + }, + + { + path: 'receive-stocks', + component: StockReceivedList, + empAccess: 'Purchase Order', + }, + { + path: 'gst-invoice-setup/new', + component: (props) => , + empAccess: 'Gst Invoice Setup', + }, + { + path: 'gst-invoice-setup/update', + component: (props) => ( + + ), + empAccess: 'Gst Invoice Setup', + }, + { + path: 'gst-invoice-setup', + component: gstInvoiceSetUpList, + empAccess: 'Gst Invoice Setup', + }, + { + path: 'purchase-order', + component: PurchaseOrderList, + empAccess: 'Purchase Order', + }, + { + path: 'purchase-order/new', + component: (props) => , + empAccess: 'Purchase Order', + }, + + { + path: 'purchase-return/list', + component: PurchaseReturnget, + empAccess: 'Product Return', + }, + { + path: 'purchaseconfirm', + component: CustomerPurchaseConfirm, + // empAccess: 'View Bill', + }, + { + path: 'purchase-return', + component: PurchaseReturn, + empAccess: 'Product Return', + }, + //free Products + { + path: 'free-product-master', + component: FreeProductList, + empAccess: 'Add Product', + }, + + { + path: 'free-purchase-entry', + component: FreePurchaseEnteryList, + empAccess: 'Purchase Entry', + }, + { + path: 'free-purchase-entry/new', + component: (props) => ( + + ), + empAccess: 'Purchase Entry', + }, + { + path: 'free-purchase-entry/update', + component: (props) => ( + + ), + empAccess: 'Purchase Entry', + }, + + { + path: 'free-purchase-order', + component: FreePurchaseOrderList, + empAccess: 'Purchase Order', + }, + { + path: 'free-purchase-order/new', + component: (props) => ( + + ), + empAccess: 'Purchase Order', + }, + + { + path: 'free-purchase-return', + component: FreePurchaseReturnList, + empAccess: 'Purchase Return', + }, + { + path: 'free-purchase-return/new', + component: FreePurchaseReturnForm, + empAccess: 'Purchase Return', + }, + //free Products + { + path: 'sales-quotation', + component: PurchaseQuotationForm, + empAccess: 'Sales Quotation', + }, + { + path: 'sales-quotation/list', + component: PurchaseQuotationList, + empAccess: 'Sales Quotation', + }, + { + path: 'sales-order', + component: SalesOrder, + empAccess: 'Sales Order', + }, + // { path: 'delivery-challan', + // component: DeliveryChallanList, + // empAccess: 'Delivery Challan' + // }, + { + path: 'delivery-challan/list', + component: DeliveryChallanList, + empAccess: 'Delivery Challan', + }, + { + path: 'delivery-challan', + component: DeliveryChallanForm, + empAccess: 'Delivery Challan', + }, + { + path: 'delivery-challan-to-invoice/list', + component: DeliveryChallanToInvoiceList, + empAccess: 'DC to Invoice', + }, + { + path: 'delivery-challan-to-invoice', + component: DeliveryChallanToInvoiceForm, + empAccess: 'DC to Invoice', + }, + + { path: 'shift-master', component: ShiftMasterList, empAccess: 'Shift' }, + { + path: 'shift-master/new', + component: (props) => , + empAccess: 'Shift', + }, + { + path: 'shift-master/update', + component: (props) => , + empAccess: 'Shift', + }, + + { + path: 'employee-master', + component: EmployeeMasterList, + empAccess: 'Add Employee', + }, + { + path: 'employee-master/new', + component: (props) => , + empAccess: 'Add Employee', + }, + { + path: 'employee-master/update', + component: (props) => , + empAccess: 'Add Employee', + }, + { + path: 'commission-or-incentive-master', + component: EmpCommisionOrIncentiveList, + empAccess: 'Incentive', + }, + { + path: 'commission-or-incentive-master/new', + component: (props) => ( + + ), + empAccess: 'Incentive', + }, + { + path: 'commission-or-incentive-master/update', + component: (props) => ( + + ), + empAccess: 'Incentive', + }, + { + path: 'supplier-master', + component: SupplierMasterList, + empAccess: 'Add Supplier', + }, + { + path: 'supplier-master/new', + component: (props) => , + empAccess: 'Add Supplier', + }, + { + path: 'supplier-master/update', + component: (props) => , + empAccess: 'Add Supplier', + }, + { + path: 'stock-transfer', + component: CreateTransfer, + empAccess: 'Create Transfer', + }, + { + path: 'stock-dispatch', + component: Dispatch, + empAccess: 'Dispatch', + }, + { + path: 'stock-transferlist', + component: StockTransferList, + empAccess: 'Create Transfer', + }, + { + path: 'supplierproductmapping-master', + component: SupplierProductMapping, + empAccess: 'Product Mapping', + }, + // { path: 'supplier-master/new', component: (props) => , empAccess: "Supplier" }, + // { path: 'supplier-master/update', component: (props) => , empAccess: "Supplier" }, + + { + path: 'dinein-master', + component: DiningMasterList, + empAccess: 'Dine In', + }, + { + path: 'dinein-master/new', + component: (props) => , + empAccess: 'Dine In', + }, + { + path: 'dinein-master/edit', + component: (props) => , + empAccess: 'Dine In', + }, + + { + path: 'combo-master', + component: ComboList, + empAccess: 'Add Product', + }, + { + path: 'combo-master/new', + component: (props) => , + empAccess: 'Add Product', + }, + { + path: 'combo-master/update', + component: (props) => , + empAccess: 'Add Product', + }, + + { + path: 'combo-offer-master', + component: ComboOfferMaster, + empAccess: 'Combo Price', + }, + + { + path: 'payment-details', + component: PaymentDetailsList, + empAccess: 'Payment Details', + }, + { + path: 'payment-details/new', + component: (props) => , + empAccess: 'Payment Details', + }, + { + path: 'payment-details/update', + component: (props) => , + empAccess: 'Payment Details', + }, + + { + path: 'payment-failed-details', + component: PaymentFailedDetailsList, + empAccess: 'Payment Failed Details', + }, + { + path: 'TableMapping/update', + component: (props) => , + empAccess: 'Table Mapping', + }, + { + path: 'TableMapping', + component: TableMAppingList, + empAccess: 'Table Mapping', + }, + { + path: 'employee-access', + component: EmpAccessList, + empAccess: 'Employee Access', + }, + { + path: 'employee-access/new', + component: (props) => , + empAccess: 'Employee Access', + }, + { + path: 'employee-access/update', + component: (props) => , + empAccess: 'Employee Access', + }, + { + path: 'employee-screenrights', + component: EmpScreenAccessList, + empAccess: 'Employee Screen Rights', + }, + { + path: 'employee-screenrights/new', + component: (props) => ( + + ), + empAccess: 'Employee Screen Rights', + }, + { + path: 'employee-screenrights/update', + component: (props) => ( + + ), + empAccess: 'Employee Screen Rights', + }, + + { + path: 'cancel-reschedule-rules', + component: CancellationList, + empAccess: 'Cancel / Reschedule', + }, + { + path: 'cancel-reschedule-rules/new', + component: (props) => , + empAccess: 'Cancel / Reschedule', + }, + { + path: 'cancel-reschedule-rules/update', + component: (props) => , + empAccess: 'Cancel / Reschedule', + }, + + { + path: 'cancel-applicable-product', + component: CancelApplicableProd, + empAccess: 'Cancel Applicable Products', + }, + { + path: 'cancel-paymentchange', + component: ChangePaymentmode, + empAccess: 'Payment Mode Change', + }, + { + path: 'cancel-pendingpayment', + component: CancellationListPending, + empAccess: 'Cancel Unpaid Order', + }, + { + path: 'sales-bill-cancel', + component: SalesBillCancel, + empAccess: 'Sales Entry Cancel', + }, + { + path: 'sales-bill-product-return/list', + component: SalesBillProductsReturnList, + empAccess: 'Sales Product Return', + }, + { + path: 'sales-bill-product-return', + component: SalesBillProductsReturn, + empAccess: 'Sales Product Return', + }, + { + path: 'booking-reschedule', + component: BookingReScedule, + empAccess: 'Booking Reschedule', + }, + { + path: 'booking-reschedule/list', + component: BookingReSceduleList, + empAccess: 'Booking Reschedule', + }, + + { + path: 'wholesale-preorder', + component: WsPreorder, + empAccess: 'Preorder', + }, + { + path: 'wholesale-preorder/new', + component: (props) => , + empAccess: 'Preorder', + }, + { + path: 'wholesale-preorder/update', + component: (props) => , + empAccess: 'Preorder', + }, + + { + path: 'custom-product', + component: StoreRecipelist, + empAccess: 'Bill Of Material', + }, + { + path: 'custom-product/new', + component: (props) => , + empAccess: 'Bill Of Material', + }, + { + path: 'custom-product/update', + component: (props) => , + empAccess: 'Bill Of Material', + }, + + { + path: 'store-to-production', + component: Storekitchenlist, + empAccess: 'Material Issue', + }, + { + path: 'store-to-production/new', + component: (props) => , + empAccess: 'Material Issue', + }, + { + path: 'store-to-production/update', + component: (props) => , + empAccess: 'Material Issue', + }, + + { + path: 'ready-for-sale', + component: KitchenFinishlist, + empAccess: 'Finished Goods', + }, + { + path: 'ready-for-sale/new', + component: (props) => , + empAccess: 'Finished Goods', + }, + { + path: 'ready-for-sale/update', + component: (props) => , + empAccess: 'Finished Goods', + }, + + { + path: 'gateway-master-configuration/new', + component: (props) => ( + + ), + empAccess: 'Gateway Master Configuration', + }, + { + path: 'gateway-master-configuration/update', + component: (props) => ( + + ), + empAccess: 'Gateway Master Configuration', + }, + { + path: 'gateway-master-configuration/list', + component: GatewayMasterConfigurationList, + empAccess: 'Gateway Master Configuration', + }, + ], + }, + { + path: `${subDirectory}sales`, + component: React.lazy(() => + fetchComponent().then((module) => ({ default: module.default })) + ), + children: [{ path: 'dine-in', component: TableBooking }], + empAccess: 'Sales Entry', + }, + { + path: `${subDirectory}saleslayouts`, + component: React.lazy(() => + fetchComponent().then((module) => ({ default: module.default })) + ), + children: [ + { + path: 'sales-selection', + component: BookingSelectionPage, + empAccess: 'Sales Screen', + }, + { + path: 'print-selection', + component: PrintSelectionPage, + empAccess: 'Print Forms', + }, + { + path: 'kiosk-selection', + component: KioskMainPage, + empAccess: 'Kiosk Screen', + }, + { + path: `barcode-qr-selection`, + component: BarcodeTemplateSetup, + empAccess: 'Barcode / QR', + }, + { + path: 'kiosk-component', + component: KioskComponentList, + access: 'Super Admin', + empAccess: 'Kiosk Component', + }, + { + path: 'component-master', + component: ComponentMasterList, + access: 'Super Admin', + empAccess: 'Component Master', + }, + { + path: 'barcode-master', + component: BarcodeComponentList, + access: 'Super Admin', + empAccess: 'Barcode Component', + }, + { + path: 'component-master/new', + component: (props) => , + access: 'Super Admin', + empAccess: 'Component Master', + }, + { + path: 'component-master/update', + component: (props) => ( + + ), + access: 'Super Admin', + empAccess: 'Component Master', + }, + { + path: 'theme-creation', + component: ThemeCreation, + access: 'Super Admin', + empAccess: 'Theme Creation', + }, + { + path: 'themeselection/new', + component: (props) => , + access: 'Super Admin', + empAccess: 'Theme Creation', + }, + { + path: 'themeselection/update', + component: (props) => , + access: 'Super Admin', + empAccess: 'Theme Creation', + }, + ], + }, +]; +// this is vite file +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; + +export default defineConfig(({ mode }) => { + const isProd = mode === "production"; + + return { + plugins: [react()], + + base: isProd ? "/apps/retail/" : "/", //for capcitor base: isProd ? "/" : "/", + + envDir: "src", + envPrefix: "ENV_", + + server: { + host: true, // 🔥 auto detect your IP + port: process.env.PORT || 3015, + }, + + build: { + minify: "esbuild", + esbuild: { + drop: isProd ? ["console", "debugger"] : [], + }, + }, + }; +}); +/// android xml file ; + + + + + + + + + + + + + + + + + + + + + + + + +//pathfile android\app\src\main\res\xml\file_paths.xml + + + + + +///package.json + +{ + "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": "^2.6.8", + "@capacitor-community/file-opener": "^8.0.0", + "@capacitor-community/speech-recognition": "^7.0.1", + "@capacitor-mlkit/barcode-scanning": "^8.0.1", + "@capacitor/android": "^8.3.0", + "@capacitor/app": "^8.0.1", + "@capacitor/cli": "^8.3.0", + "@capacitor/core": "^8.3.0", + "@capacitor/filesystem": "^8.1.2", + "@dnd-kit/core": "^6.3.1", + "@dnd-kit/sortable": "^10.0.0", + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", + "@mui/material": "^5.15.18", + "@react-google-maps/api": "^2.20.8", + "@reduxjs/toolkit": "^1.9.5", + "@tanstack/react-query": "^5.90.11", + "@tanstack/react-query-devtools": "^5.91.1", + "@tanstack/react-virtual": "^3.13.18", + "@types/node": "^25.5.0", + "@vitejs/plugin-legacy": "^8.0.1", + "@zxing/library": "^0.21.3", + "antd": "^5.17.4", + "antd-img-crop": "^4.22.0", + "aos": "^2.3.4", + "apexcharts": "^5.10.4", + "axios": "^1.13.6", + "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.4.0", + "file-saver": "^2.0.5", + "history": "^5.3.0", + "html2canvas": "^1.4.1", + "html2pdf": "^0.0.11", + "html5-qrcode": "^2.3.8", + "jquery": "^3.7.1", + "js-cookie": "^3.0.5", + "jsbarcode": "^3.11.6", + "jspdf": "^4.2.1", + "lucide": "^0.577.0", + "lucide-react": "^0.536.0", + "moment": "^2.30.1", + "number-to-words": "^1.2.4", + "pdf-lib": "^1.17.1", + "qr-scanner": "^1.4.2", + "qrcode": "^1.5.3", + "qrcode.react": "^4.2.0", + "react": "^18.3.1", + "react-apexcharts": "^2.1.0", + "react-beautiful-dnd": "^13.1.1", + "react-color": "^2.19.3", + "react-countup": "^6.5.3", + "react-device-detect": "^2.2.3", + "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": "^8.0.1", + "webfontloader": "^1.6.28", + "zustand": "^5.0.8" + }, + "devDependencies": { + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^6.0.1", + "esbuild": "^0.27.4", + "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", + "sass": "^1.98.0", + "terser": "^5.31.3", + "vite": "^8.0.0", + "vite-plugin-obfuscator": "^1.0.5", + "vite-plugin-remove-console": "^2.2.0" + } +} + diff --git a/capacitor.config.json b/capacitor.config.json new file mode 100644 index 0000000..2a7f3c4 --- /dev/null +++ b/capacitor.config.json @@ -0,0 +1,10 @@ +{ + "appId": "com.example.app", + "appName": "PozoApp", + "webDir": "dist", + "plugins": { + "StatusBar": { + "overlay": false + } + } +} \ No newline at end of file diff --git a/package.json b/package.json index b880d73..51320e1 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,14 @@ }, "dependencies": { "@ant-design/plots": "^2.6.8", + "@capacitor-community/file-opener": "^8.0.0", "@capacitor-community/speech-recognition": "^7.0.1", "@capacitor-mlkit/barcode-scanning": "^8.0.1", + "@capacitor/android": "^8.3.0", "@capacitor/app": "^8.0.1", - "@capacitor/core": "^8.1.0", + "@capacitor/cli": "^8.3.0", + "@capacitor/core": "^8.3.0", + "@capacitor/filesystem": "^8.1.2", "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", "@emotion/react": "^11.11.4", @@ -27,6 +31,7 @@ "@tanstack/react-query-devtools": "^5.91.1", "@tanstack/react-virtual": "^3.13.18", "@types/node": "^25.5.0", + "@vitejs/plugin-legacy": "^8.0.1", "@zxing/library": "^0.21.3", "antd": "^5.17.4", "antd-img-crop": "^4.22.0", @@ -92,7 +97,7 @@ "eslint-plugin-react-refresh": "^0.4.7", "prettier": "^3.5.3", "rollup-plugin-obfuscator": "^1.1.0", - "sass": "^1.77.2", + "sass": "^1.98.0", "terser": "^5.31.3", "vite": "^8.0.0", "vite-plugin-obfuscator": "^1.0.5", diff --git a/src/Pages/CommonMaster/ConfigExcelUpload.jsx b/src/Pages/CommonMaster/ConfigExcelUpload.jsx index fefcbd2..5c2a590 100644 --- a/src/Pages/CommonMaster/ConfigExcelUpload.jsx +++ b/src/Pages/CommonMaster/ConfigExcelUpload.jsx @@ -16,6 +16,7 @@ import { RadioGrpButton } from '../../Components/Forms/RadioGroup.jsx'; import { AiFillDelete } from 'react-icons/ai'; import upldimg from '../../Images/upldimg.png'; import { FiDelete, FiDownload } from 'react-icons/fi'; +import { downloadFile } from '../../utils/downloadFile.js'; const allowedExcelTypes = [ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx 'application/vnd.ms-excel', // .xls @@ -328,10 +329,17 @@ const ConfigExcel = ({ handleSubmit, CategoryNames, SubCatData }) => { window.navigator.msSaveOrOpenBlob(blob, filename); } else { // For other browsers - const downloadLink = document.createElement('a'); - downloadLink.href = window.URL.createObjectURL(blob); - downloadLink.download = filename; - downloadLink.click(); + downloadFile( + buffer, + "CategoryDatas.xlsx", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + (success) => { + if (!success) { + console.error("error occured while downloading") + } + } + ); + } } }; @@ -415,10 +423,17 @@ const ConfigExcel = ({ handleSubmit, CategoryNames, SubCatData }) => { window.navigator.msSaveOrOpenBlob(blob, filename); } else { // For other browsers - const downloadLink = document.createElement('a'); - downloadLink.href = window.URL.createObjectURL(blob); - downloadLink.download = filename; - downloadLink.click(); + + downloadFile( + buffer, + "SubcatagoryDatas.xlsx", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + (success) => { + if (!success) { + console.error("Failed to download the file. Please try again.") + } + } + ); } } }; @@ -529,10 +544,17 @@ const ConfigExcel = ({ handleSubmit, CategoryNames, SubCatData }) => { window.navigator.msSaveOrOpenBlob(blob, filename); } else { // For other browsers - const downloadLink = document.createElement('a'); - downloadLink.href = window.URL.createObjectURL(blob); - downloadLink.download = filename; - downloadLink.click(); + downloadFile( + buffer, + "BrandDatas.xlsx", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + (success) => { + if (!success) { + console.error("Failed to download the file. Please try again.") + + } + } + ); } } }; @@ -673,7 +695,7 @@ const ConfigExcel = ({ handleSubmit, CategoryNames, SubCatData }) => { ...record, ...values, }); - } catch (errInfo) {} + } catch (errInfo) { } }; let childNode = children; diff --git a/src/Pages/Product/ExcelUpload.jsx b/src/Pages/Product/ExcelUpload.jsx index b7ab7f0..10ef5e9 100644 --- a/src/Pages/Product/ExcelUpload.jsx +++ b/src/Pages/Product/ExcelUpload.jsx @@ -41,6 +41,7 @@ import Buttons from '../../Components/Forms/Buttons.jsx'; import { IoClose } from 'react-icons/io5'; import { Messages } from '../../Components/Notifications/Messages.jsx'; import useWhyDidYouUpdate from '../../Services/findrerender.js'; +import { downloadFile } from '../../utils/downloadFile.js'; const getApplicationSampleData = (appName) => { const sampleDataMap = { @@ -1227,8 +1228,8 @@ const ProductExcel = ({ allowBlank: true, formulae: [ '"' + - (typeof Unit !== 'undefined' ? Unit.join(',') : 'KGS,PCS,LITER') + - '"', + (typeof Unit !== 'undefined' ? Unit.join(',') : 'KGS,PCS,LITER') + + '"', ], }, sampleValue: sampleData?.uom || 'KGS', @@ -2357,23 +2358,21 @@ const ProductExcel = ({ } }); - // Generate and download the file const buffer = await workbook.xlsx.writeBuffer(); - const blob = new Blob([buffer], { - type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - }); - const filename = 'Product Data.xlsx'; - if (typeof window !== 'undefined') { - if (window.navigator && window.navigator.msSaveOrOpenBlob) { - window.navigator.msSaveOrOpenBlob(blob, filename); - } else { - const downloadLink = document.createElement('a'); - downloadLink.href = window.URL.createObjectURL(blob); - downloadLink.download = filename; - downloadLink.click(); + downloadFile( + buffer, + "Product Data.xlsx", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + (success) => { + if (success) { + console.log("File downloaded and opened successfully!"); + } else { + console.log("Failed to download/open file."); + } } - } + ); + }; const handleFileSubmit = (e) => { @@ -2908,15 +2907,21 @@ const ProductExcel = ({ selectUnlockedCells: true, }); + // const buffer = await workbook.xlsx.writeBuffer(); + // const blob = new Blob([buffer], { + // type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + // }); + // const downloadLink = document.createElement('a'); + // downloadLink.href = window.URL.createObjectURL(blob); + // downloadLink.download = 'Product_Data.xlsx'; + // downloadLink.click(); const buffer = await workbook.xlsx.writeBuffer(); - const blob = new Blob([buffer], { - type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - }); - const downloadLink = document.createElement('a'); - downloadLink.href = window.URL.createObjectURL(blob); - downloadLink.download = 'Product_Data.xlsx'; - downloadLink.click(); + downloadFile( + buffer, + "Product_Data.xlsx", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + ); setLoading(false); } else { setLoading(false); @@ -3228,98 +3233,98 @@ const ProductExcel = ({

- Upload Your Excel -

+ Upload Your Excel +

-
- -
- -
-
+
+
handleExportData()} + className="btn btn--info" + style={{ + background: '#00694aff', + color: '#fff', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + padding: '5px 12px', + borderRadius: '4px', + }} + onClick={handleFieldSetup} > -
- -
-
- Export Excel -
+
+
+
handleExportData()} + > +
+ +
+
+ Export Excel +
+
{message && (
No Data Found
)} -
- - {excelData?.length > 0 && excelData && ( -
- - - -
- )}
-
0 ? 'space-between' : 'flex-end', - gap: '1rem', - }} - > - {excelData?.length > 0 && ( -
-
-

- Modified -
-
-

- Not Modified -
-
- )} - - - + {excelData?.length > 0 && excelData && ( +
+ + + +
+ )} +
+
0 ? 'space-between' : 'flex-end', + gap: '1rem', + }} + > + {excelData?.length > 0 && ( +
+
+

+ Modified +
+
+

+ Not Modified +
+
+ )} + + + +
@@ -3502,7 +3507,7 @@ const ProductExcel = ({
setSelectedImage(item)} > diff --git a/src/Pages/PurchaseOrder/PurchaseOrderBulkUpload.jsx b/src/Pages/PurchaseOrder/PurchaseOrderBulkUpload.jsx index 5767788..ee2700c 100644 --- a/src/Pages/PurchaseOrder/PurchaseOrderBulkUpload.jsx +++ b/src/Pages/PurchaseOrder/PurchaseOrderBulkUpload.jsx @@ -29,6 +29,7 @@ import { DefaultModal } from '../../Components/Modal/DefaultModal.jsx'; import Buttons from '../../Components/Forms/Buttons.jsx'; import { getPurchaseSupplierAndWareHouseData } from '../../Features/PurchaseOrder/PurchaseOrder.js'; import { Messages } from '../../Components/Notifications/Messages.jsx'; +import { downloadFile } from '../../utils/downloadFile.js'; // Constants const ALLOWED_EXCEL_TYPES = [ @@ -522,15 +523,19 @@ const PurchaseExcel = ({ handleSubmit }) => { // Step 7: Export file const buffer = await workbook.xlsx.writeBuffer(); - const blob = new Blob([buffer], { - type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - }); - const filename = `PurchaseOrder_${supplierDisplayName}.xlsx`; - const link = document.createElement('a'); - link.href = URL.createObjectURL(blob); - link.download = filename; - link.click(); + + downloadFile( + buffer, + filename, + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + (success) => { + if (!success) { + setMessageType('error'); + setMessageData('Failed to download the file. Please try again.'); + } + } + ); setSupplierProducts([]); setSelectedSupplierData(null); diff --git a/src/Pages/Reports/MenuQRCode/MenuQRCode.jsx b/src/Pages/Reports/MenuQRCode/MenuQRCode.jsx index 1805311..83e49ef 100644 --- a/src/Pages/Reports/MenuQRCode/MenuQRCode.jsx +++ b/src/Pages/Reports/MenuQRCode/MenuQRCode.jsx @@ -19,6 +19,7 @@ import { import QRCodeLib from 'qrcode'; import { LuDownload } from 'react-icons/lu'; import { BsFileEarmarkPdf } from 'react-icons/bs'; +import { downloadFile } from '../../../utils/downloadFile'; const subDirectory = import.meta.env.ENV_MAIN_BASE_URL || '/'; @@ -312,7 +313,19 @@ const MenuQRCode = () => { if (openPreview) { setIsPreviewModalOpen(true); } else { - pdf.save('menu-qr.pdf'); + // pdf.save('menu-qr.pdf'); + const pdfBuffer = pdf.output('arraybuffer'); // ✅ arraybuffer for downloadFile + downloadFile( + pdfBuffer, + "menu-qr.pdf", + "application/pdf", + (success) => { + if (!success) { + setMessageType('error'); + setMessageData('Failed to download the PDF. Please try again.'); + } + } + ); } } catch (err) { console.error('PDF generation failed', err); @@ -323,17 +336,21 @@ const MenuQRCode = () => { const downloadPreviewPdf = () => { if (!pdfPreviewUrl) return; + fetch(pdfPreviewUrl) - .then((r) => r.blob()) - .then((blob) => { - const url = URL.createObjectURL(blob); - const a = document.createElement('a'); - a.href = url; - a.download = 'menu-qr.pdf'; - document.body.appendChild(a); - a.click(); - a.remove(); - URL.revokeObjectURL(url); + .then((r) => r.arrayBuffer()) // ✅ arrayBuffer instead of blob + .then((buffer) => { + downloadFile( + buffer, + "menu-qr.pdf", + "application/pdf", + (success) => { + if (!success) { + setMessageType('error'); + setMessageData('Failed to download the file. Please try again.'); + } + } + ); }); }; diff --git a/src/Pages/StockMaster/StockBulkUpload.jsx b/src/Pages/StockMaster/StockBulkUpload.jsx index cbb9629..bec8dfe 100644 --- a/src/Pages/StockMaster/StockBulkUpload.jsx +++ b/src/Pages/StockMaster/StockBulkUpload.jsx @@ -37,6 +37,7 @@ import { import { Messages } from '../../Components/Notifications/Messages.jsx'; import { getPurchaseSupplierAndWareHouseData } from '../../Features/PurchaseOrder/PurchaseOrder.js'; import { getSupplaierIdwithTypeBasedProducts } from '../../Features/SupplierProductMapping/SupplierProductMapping.js'; +import { downloadFile } from '../../utils/downloadFile.js'; const allowedExcelTypes = [ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx @@ -478,8 +479,8 @@ const StockExcel = ({ : c.key === 'Quantity' ? 10 : c.key === 'Supplier' || - c.key === 'InvoiceDeliveryChallan' || - c.key === 'SupplierInvoiceNumber' + c.key === 'InvoiceDeliveryChallan' || + c.key === 'SupplierInvoiceNumber' ? 30 : 20, })); @@ -1007,14 +1008,19 @@ const StockExcel = ({ }); const buffer = await workbook.xlsx.writeBuffer(); - const blob = new Blob([buffer], { - type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - }); const filename = `PurchaseEntry_${supplierDisplayName}_${Date.now()}.xlsx`; - const link = document.createElement('a'); - link.href = URL.createObjectURL(blob); - link.download = filename; - link.click(); + + downloadFile( + buffer, + filename, + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + (success) => { + if (!success) { + setMessageType('error'); + setMessageData('Failed to download the file. Please try again.'); + } + } + ); setSupplierProducts([]); setSelectedSupplierData(null); @@ -1332,7 +1338,7 @@ const StockExcel = ({ ...record, ...values, }); - } catch (errInfo) {} + } catch (errInfo) { } }; let childNode = children; diff --git a/src/Pages/StockPriceUpdate/StockPriceUpdate.jsx b/src/Pages/StockPriceUpdate/StockPriceUpdate.jsx index 1888fdd..82b6274 100644 --- a/src/Pages/StockPriceUpdate/StockPriceUpdate.jsx +++ b/src/Pages/StockPriceUpdate/StockPriceUpdate.jsx @@ -60,6 +60,7 @@ import { getCommonAppPreference, } from '../../Features/BrachLogin/BranchLogin.js'; import { IoClose } from 'react-icons/io5'; +import { downloadFile } from '../../utils/downloadFile.js'; const StockPriceUpdate = () => { const { SadminuserAccess } = useAuth(); @@ -179,53 +180,53 @@ const StockPriceUpdate = () => { }, ...(hasFieldExists('Stock') ? [ - { - title: 'Stock', - dataIndex: 'Stock', - key: 'Stock', - width: 80, - }, - ] + { + title: 'Stock', + dataIndex: 'Stock', + key: 'Stock', + width: 80, + }, + ] : []), ...(hasFieldExists('Stock Date') ? [ - { - title: 'Stock Date', - dataIndex: 'StockDate', - key: 'StockDate', - width: 80, - }, - ] + { + title: 'Stock Date', + dataIndex: 'StockDate', + key: 'StockDate', + width: 80, + }, + ] : []), ...(hasFieldExists('Old MRP') ? [ - { - title: 'Old MRP', - dataIndex: 'OldMRP', - key: 'OldMRP', - width: 100, - }, - ] + { + title: 'Old MRP', + dataIndex: 'OldMRP', + key: 'OldMRP', + width: 100, + }, + ] : []), ...(hasFieldExists('Old SP') ? [ - { - title: 'Old SP', - dataIndex: 'OldSP', - key: 'OldSP', - width: 100, - }, - ] + { + title: 'Old SP', + dataIndex: 'OldSP', + key: 'OldSP', + width: 100, + }, + ] : []), ...(hasFieldExists('Old Wholesale Price') ? [ - { - title: 'Old Wholesale Price', - dataIndex: 'OldWholeSalePrice', - key: 'OldWholeSalePrice', - width: 140, - }, - ] + { + title: 'Old Wholesale Price', + dataIndex: 'OldWholeSalePrice', + key: 'OldWholeSalePrice', + width: 140, + }, + ] : []), // ✅ EDITABLE @@ -322,7 +323,7 @@ const StockPriceUpdate = () => { ); excelDataRef.current ?.validateFields([`NewSellPrice${record.localId}`]) - .catch(() => {}); + .catch(() => { }); } }} /> @@ -331,40 +332,40 @@ const StockPriceUpdate = () => { }, ...(hasFieldExists('New Wholesale Price') ? [ - { - title: 'New Wholesale Price', - dataIndex: 'NewWholeSalePrice', - key: 'NewWholeSalePrice', - width: 160, - render: (value, record, index) => ( - - - handlePriceChange( - index, - 'NewWholeSalePrice', - e.target.value, - record.localId - ) + { + title: 'New Wholesale Price', + dataIndex: 'NewWholeSalePrice', + key: 'NewWholeSalePrice', + width: 160, + render: (value, record, index) => ( + + + handlePriceChange( + index, + 'NewWholeSalePrice', + e.target.value, + record.localId + ) + } + placeholder="New Wholesale" + inputMode="decimal" + onInput={(e) => { + let cleanedValue = e.target.value.replace(/[^0-9.]/g, ''); + const parts = cleanedValue.split('.'); + if (cleanedValue.startsWith('.')) { + cleanedValue = '0' + cleanedValue; } - placeholder="New Wholesale" - inputMode="decimal" - onInput={(e) => { - let cleanedValue = e.target.value.replace(/[^0-9.]/g, ''); - const parts = cleanedValue.split('.'); - if (cleanedValue.startsWith('.')) { - cleanedValue = '0' + cleanedValue; - } - e.target.value = - parts.length > 2 - ? `${parts[0]}.${parts.slice(1).join('')}` - : cleanedValue; - }} - /> - - ), - }, - ] + e.target.value = + parts.length > 2 + ? `${parts[0]}.${parts.slice(1).join('')}` + : cleanedValue; + }} + /> + + ), + }, + ] : []), { title: 'Action', @@ -1092,79 +1093,79 @@ const StockPriceUpdate = () => { }, ...(hasField('Stock Date') ? [ - { - title: 'stock Date', - dataIndex: 'InwardDate', - key: 'InwardDate', - align: 'center', - width: 120, - render: (InwardDate) => - InwardDate !== null ? ExtractDateFormate(InwardDate) : '-', - }, - ] + { + title: 'stock Date', + dataIndex: 'InwardDate', + key: 'InwardDate', + align: 'center', + width: 120, + render: (InwardDate) => + InwardDate !== null ? ExtractDateFormate(InwardDate) : '-', + }, + ] : []), ...(hasField('Expiry Date') ? [ - { - title: 'Exp date', - dataIndex: 'ExpDate', - key: 'ExpDate', - align: 'center', - width: 100, - render: (ExpDate) => - ExpDate !== null ? ExtractDateFormate(ExpDate) : '-', - }, - ] + { + title: 'Exp date', + dataIndex: 'ExpDate', + key: 'ExpDate', + align: 'center', + width: 100, + render: (ExpDate) => + ExpDate !== null ? ExtractDateFormate(ExpDate) : '-', + }, + ] : []), ...(hasField('Stock') ? [ - { - title: 'stock', - dataIndex: 'BalanceQty', - key: 'BalanceQty', - align: 'right', - width: '60px', - render: (BalanceQty) => (BalanceQty !== null ? BalanceQty : '-'), - }, - ] + { + title: 'stock', + dataIndex: 'BalanceQty', + key: 'BalanceQty', + align: 'right', + width: '60px', + render: (BalanceQty) => (BalanceQty !== null ? BalanceQty : '-'), + }, + ] : []), ...(hasField('Old MRP') ? [ - { - title: 'Old MRP', - dataIndex: 'MRP', - key: 'MRP', - align: 'right', - width: '70px', - render: (MRP) => (safeRound(MRP) !== null ? safeRound(MRP) : '-'), - }, - ] + { + title: 'Old MRP', + dataIndex: 'MRP', + key: 'MRP', + align: 'right', + width: '70px', + render: (MRP) => (safeRound(MRP) !== null ? safeRound(MRP) : '-'), + }, + ] : []), ...(hasField('Old SP') ? [ - { - title: 'Old SP', - dataIndex: 'SellPrice', - key: 'SellPrice', - align: 'right', - width: '70px', - render: (SellPrice) => - safeRound(SellPrice) !== null ? safeRound(SellPrice) : '-', - }, - ] + { + title: 'Old SP', + dataIndex: 'SellPrice', + key: 'SellPrice', + align: 'right', + width: '70px', + render: (SellPrice) => + safeRound(SellPrice) !== null ? safeRound(SellPrice) : '-', + }, + ] : []), ...(hasField('Old Wholesale Price') ? [ - { - title: 'Old Wholesale Price', - dataIndex: 'WhSalePrice', - key: 'WhSalePrice', - align: 'right', - width: '120px', - render: (WhSalePrice) => - safeRound(WhSalePrice) !== null ? safeRound(WhSalePrice) : '-', - }, - ] + { + title: 'Old Wholesale Price', + dataIndex: 'WhSalePrice', + key: 'WhSalePrice', + align: 'right', + width: '120px', + render: (WhSalePrice) => + safeRound(WhSalePrice) !== null ? safeRound(WhSalePrice) : '-', + }, + ] : []), { title: 'New MRP', @@ -1188,19 +1189,19 @@ const StockPriceUpdate = () => { }, ...(hasField('New Wholesale Price') ? [ - { - title: 'New Wholesale Price', - dataIndex: 'CurrentWhAmt', - key: 'CurrentWhAmt', - align: 'center', - with: '4rem', - editable: true, - render: (text, record) => ( -

{text ? text : 'Enter Wholesale Price'}

- ), - width: 120, - }, - ] + { + title: 'New Wholesale Price', + dataIndex: 'CurrentWhAmt', + key: 'CurrentWhAmt', + align: 'center', + with: '4rem', + editable: true, + render: (text, record) => ( +

{text ? text : 'Enter Wholesale Price'}

+ ), + width: 120, + }, + ] : []), ]; @@ -1481,9 +1482,9 @@ const StockPriceUpdate = () => { isStockVariantBased === 'Yes' ? BulkProductData || [] : (BulkProductData || [])?.filter( - (item, index, self) => - index === self.findIndex((p) => p.ProdId === item.ProdId) - ); + (item, index, self) => + index === self.findIndex((p) => p.ProdId === item.ProdId) + ); if (!uniqueBulkProductData?.length) { setMessageType('error'); @@ -1596,9 +1597,9 @@ const StockPriceUpdate = () => { cell.border = isHiddenCol ? undefined : { - right: { style: 'thin', color: { argb: 'FF000000' } }, - bottom: { style: 'thin', color: { argb: 'FF000000' } }, - }; + right: { style: 'thin', color: { argb: 'FF000000' } }, + bottom: { style: 'thin', color: { argb: 'FF000000' } }, + }; }); /* ---------------- ADD DATA ---------------- */ @@ -1713,14 +1714,19 @@ const StockPriceUpdate = () => { /* ---------------- DOWNLOAD ---------------- */ const buffer = await workbook.xlsx.writeBuffer(); - const blob = new Blob([buffer], { - type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - }); - - const link = document.createElement('a'); - link.href = URL.createObjectURL(blob); - link.download = 'PriceChange_Data.xlsx'; - link.click(); + downloadFile( + buffer, + "PriceChange_Data.xlsx", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + (success) => { + if (success) { + console.log("Template downloaded successfully!"); + } else { + setMessageType('error'); + setMessageData('Failed to download the template. Please try again.'); + } + } + ) setExportLoading(false); }; @@ -1780,7 +1786,7 @@ const StockPriceUpdate = () => { Number(current.MRP) !== Number(uploaded.NewMRP) || Number(current.SellPrice) !== Number(uploaded.NewSellPrice) || Number(current.WhSalePrice || 0) !== - Number(uploaded.NewWholeSalePrice || 0); + Number(uploaded.NewWholeSalePrice || 0); return { ...uploaded, @@ -2297,17 +2303,17 @@ const StockPriceUpdate = () => {
{(RadioSelection == 'Bulk' || (RadioSelection == 'Single' && StockDetails.length > 0)) && ( -
- } - disabled={addnewAccess} - > -
- )} +
+ } + disabled={addnewAccess} + > +
+ )}
{RadioSelection == 'Single' && ( @@ -2325,10 +2331,10 @@ const StockPriceUpdate = () => { StockDetails?.length < 11 ? false : { - current: page, - pageSize: pageSize, - onChange: handlePageChange, - } + current: page, + pageSize: pageSize, + onChange: handlePageChange, + } } onChange={handleChange} > @@ -2395,7 +2401,7 @@ const StockPriceUpdate = () => {
{} : () => showPriceChangeModal() + exportLoading ? () => { } : () => showPriceChangeModal() } >
diff --git a/src/Pages/openingStock/OpeningStockExcel.jsx b/src/Pages/openingStock/OpeningStockExcel.jsx index b8c5e5b..d680b7a 100644 --- a/src/Pages/openingStock/OpeningStockExcel.jsx +++ b/src/Pages/openingStock/OpeningStockExcel.jsx @@ -7,6 +7,7 @@ import { RiFileExcel2Fill } from 'react-icons/ri'; import { Messages } from '../../Components/Notifications/Messages.jsx'; import { getSession } from '../../Services/Others.js'; import './OpeningStockExcel.scss'; +import { downloadFile } from '../../utils/downloadFile.js'; const TEMPLATE_HEADERS = [ { key: 'ProdName', header: 'Product Name' }, @@ -203,15 +204,20 @@ const OpeningStockExcel = ({ products = [], onApply, onCancel }) => { } const buffer = await workbook.xlsx.writeBuffer(); - const blob = new Blob([buffer], { - type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - }); - const link = document.createElement('a'); - link.href = URL.createObjectURL(blob); - link.download = 'opening_stock_template.xlsx'; - link.click(); - URL.revokeObjectURL(link.href); + downloadFile( + buffer, + "opening_stock_template.xlsx", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + (success) => { + if (success) { + console.log("Template downloaded successfully!"); + } else { + setMessageType('error'); + setMessageData('Failed to download the template. Please try again.'); + } + } + ) } catch (error) { console.error('Template download failed:', error); setMessageType('error'); @@ -562,8 +568,8 @@ const OpeningStockExcel = ({ products = [], onApply, onCancel }) => { : '', TotalPcs: row.OnePcsAvailable === 'Y' && - row.TotalPiece !== undefined && - row.TotalPiece !== null + row.TotalPiece !== undefined && + row.TotalPiece !== null ? row.TotalPiece.toString() : 0, InwardDetails: [], diff --git a/src/utils/downloadFile.js b/src/utils/downloadFile.js new file mode 100644 index 0000000..96acce5 --- /dev/null +++ b/src/utils/downloadFile.js @@ -0,0 +1,62 @@ +import { Capacitor } from "@capacitor/core"; +import { Filesystem, Directory } from "@capacitor/filesystem"; +import { FileOpener } from "@capacitor-community/file-opener"; + +/** + * Download and open a file (Excel, PDF, etc.) + * @param {ArrayBuffer | Blob} buffer - File data + * @param {string} filename - File name with extension + * @param {string} mimeType - File MIME type (example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet) + * @param {Function} onSuccess - Optional callback, called with true/false + */ +export const downloadFile = async (buffer, filename, mimeType, onSuccess) => { + try { + const isWeb = Capacitor.getPlatform() === "web"; + + // 🌐 Web download + if (isWeb) { + const blob = buffer instanceof Blob ? buffer : new Blob([buffer], { type: mimeType }); + + const link = document.createElement("a"); + link.href = URL.createObjectURL(blob); + link.download = filename; + link.click(); + + URL.revokeObjectURL(link.href); + onSuccess?.(true); + return; + } + + // 📱 Mobile (Android / iOS) + + // Convert ArrayBuffer → Base64 + let binary = ""; + const bytes = new Uint8Array(buffer); + for (let i = 0; i < bytes.length; i++) { + binary += String.fromCharCode(bytes[i]); + } + const base64Data = btoa(binary); + + // Save file inside app's Documents folder + + const savedFile = await Filesystem.writeFile({ + path: filename, + data: base64Data, + directory: Directory.Data, // ← was Directory.Documents + recursive: true, + }); + + // FileOpener requires removing "file://" + + await FileOpener.open({ + filePath: savedFile.uri, // ← was savedFile.uri.replace("file://", "") + contentType: mimeType, + }); + + onSuccess?.(true); + + } catch (err) { + console.error("File download/open error:", err); + onSuccess?.(false); + } +}; \ No newline at end of file diff --git a/vite.config.js b/vite.config.js index 245c478..8552f81 100644 --- a/vite.config.js +++ b/vite.config.js @@ -7,7 +7,7 @@ export default defineConfig(({ mode }) => { return { plugins: [react()], - base: isProd ? "/apps/retail/" : "/", + base: isProd ? "/apps/retail/" : "/", //for capcitor base: isProd ? "/" : "/", envDir: "src", envPrefix: "ENV_",