capacitor dwld options

This commit is contained in:
Tamilselvan 2026-03-27 01:18:00 +05:30
parent 8c80629ca4
commit 452c030713
11 changed files with 3958 additions and 3797 deletions

10
capacitor.config.json Normal file
View File

@ -0,0 +1,10 @@
{
"appId": "com.example.app",
"appName": "PozoApp",
"webDir": "dist",
"plugins": {
"StatusBar": {
"overlay": false
}
}
}

View File

@ -12,10 +12,14 @@
}, },
"dependencies": { "dependencies": {
"@ant-design/plots": "^2.6.8", "@ant-design/plots": "^2.6.8",
"@capacitor-community/file-opener": "^8.0.0",
"@capacitor-community/speech-recognition": "^7.0.1", "@capacitor-community/speech-recognition": "^7.0.1",
"@capacitor-mlkit/barcode-scanning": "^8.0.1", "@capacitor-mlkit/barcode-scanning": "^8.0.1",
"@capacitor/android": "^8.3.0",
"@capacitor/app": "^8.0.1", "@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/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0", "@dnd-kit/sortable": "^10.0.0",
"@emotion/react": "^11.11.4", "@emotion/react": "^11.11.4",
@ -27,6 +31,7 @@
"@tanstack/react-query-devtools": "^5.91.1", "@tanstack/react-query-devtools": "^5.91.1",
"@tanstack/react-virtual": "^3.13.18", "@tanstack/react-virtual": "^3.13.18",
"@types/node": "^25.5.0", "@types/node": "^25.5.0",
"@vitejs/plugin-legacy": "^8.0.1",
"@zxing/library": "^0.21.3", "@zxing/library": "^0.21.3",
"antd": "^5.17.4", "antd": "^5.17.4",
"antd-img-crop": "^4.22.0", "antd-img-crop": "^4.22.0",
@ -92,7 +97,7 @@
"eslint-plugin-react-refresh": "^0.4.7", "eslint-plugin-react-refresh": "^0.4.7",
"prettier": "^3.5.3", "prettier": "^3.5.3",
"rollup-plugin-obfuscator": "^1.1.0", "rollup-plugin-obfuscator": "^1.1.0",
"sass": "^1.77.2", "sass": "^1.98.0",
"terser": "^5.31.3", "terser": "^5.31.3",
"vite": "^8.0.0", "vite": "^8.0.0",
"vite-plugin-obfuscator": "^1.0.5", "vite-plugin-obfuscator": "^1.0.5",

View File

@ -16,6 +16,7 @@ import { RadioGrpButton } from '../../Components/Forms/RadioGroup.jsx';
import { AiFillDelete } from 'react-icons/ai'; import { AiFillDelete } from 'react-icons/ai';
import upldimg from '../../Images/upldimg.png'; import upldimg from '../../Images/upldimg.png';
import { FiDelete, FiDownload } from 'react-icons/fi'; import { FiDelete, FiDownload } from 'react-icons/fi';
import { downloadFile } from '../../utils/downloadFile.js';
const allowedExcelTypes = [ const allowedExcelTypes = [
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx
'application/vnd.ms-excel', // .xls 'application/vnd.ms-excel', // .xls
@ -328,10 +329,17 @@ const ConfigExcel = ({ handleSubmit, CategoryNames, SubCatData }) => {
window.navigator.msSaveOrOpenBlob(blob, filename); window.navigator.msSaveOrOpenBlob(blob, filename);
} else { } else {
// For other browsers // For other browsers
const downloadLink = document.createElement('a'); downloadFile(
downloadLink.href = window.URL.createObjectURL(blob); buffer,
downloadLink.download = filename; "CategoryDatas.xlsx",
downloadLink.click(); "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); window.navigator.msSaveOrOpenBlob(blob, filename);
} else { } else {
// For other browsers // For other browsers
const downloadLink = document.createElement('a');
downloadLink.href = window.URL.createObjectURL(blob); downloadFile(
downloadLink.download = filename; buffer,
downloadLink.click(); "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); window.navigator.msSaveOrOpenBlob(blob, filename);
} else { } else {
// For other browsers // For other browsers
const downloadLink = document.createElement('a'); downloadFile(
downloadLink.href = window.URL.createObjectURL(blob); buffer,
downloadLink.download = filename; "BrandDatas.xlsx",
downloadLink.click(); "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, ...record,
...values, ...values,
}); });
} catch (errInfo) {} } catch (errInfo) { }
}; };
let childNode = children; let childNode = children;

File diff suppressed because it is too large Load Diff

View File

@ -29,6 +29,7 @@ import { DefaultModal } from '../../Components/Modal/DefaultModal.jsx';
import Buttons from '../../Components/Forms/Buttons.jsx'; import Buttons from '../../Components/Forms/Buttons.jsx';
import { getPurchaseSupplierAndWareHouseData } from '../../Features/PurchaseOrder/PurchaseOrder.js'; import { getPurchaseSupplierAndWareHouseData } from '../../Features/PurchaseOrder/PurchaseOrder.js';
import { Messages } from '../../Components/Notifications/Messages.jsx'; import { Messages } from '../../Components/Notifications/Messages.jsx';
import { downloadFile } from '../../utils/downloadFile.js';
// Constants // Constants
const ALLOWED_EXCEL_TYPES = [ const ALLOWED_EXCEL_TYPES = [
@ -522,15 +523,19 @@ const PurchaseExcel = ({ handleSubmit }) => {
// Step 7: Export file // Step 7: Export file
const buffer = await workbook.xlsx.writeBuffer(); const buffer = await workbook.xlsx.writeBuffer();
const blob = new Blob([buffer], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
});
const filename = `PurchaseOrder_${supplierDisplayName}.xlsx`; const filename = `PurchaseOrder_${supplierDisplayName}.xlsx`;
const link = document.createElement('a');
link.href = URL.createObjectURL(blob); downloadFile(
link.download = filename; buffer,
link.click(); filename,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
(success) => {
if (!success) {
setMessageType('error');
setMessageData('Failed to download the file. Please try again.');
}
}
);
setSupplierProducts([]); setSupplierProducts([]);
setSelectedSupplierData(null); setSelectedSupplierData(null);

View File

@ -19,6 +19,7 @@ import {
import QRCodeLib from 'qrcode'; import QRCodeLib from 'qrcode';
import { LuDownload } from 'react-icons/lu'; import { LuDownload } from 'react-icons/lu';
import { BsFileEarmarkPdf } from 'react-icons/bs'; import { BsFileEarmarkPdf } from 'react-icons/bs';
import { downloadFile } from '../../../utils/downloadFile';
const subDirectory = import.meta.env.ENV_MAIN_BASE_URL || '/'; const subDirectory = import.meta.env.ENV_MAIN_BASE_URL || '/';
@ -312,7 +313,19 @@ const MenuQRCode = () => {
if (openPreview) { if (openPreview) {
setIsPreviewModalOpen(true); setIsPreviewModalOpen(true);
} else { } 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) { } catch (err) {
console.error('PDF generation failed', err); console.error('PDF generation failed', err);
@ -323,17 +336,21 @@ const MenuQRCode = () => {
const downloadPreviewPdf = () => { const downloadPreviewPdf = () => {
if (!pdfPreviewUrl) return; if (!pdfPreviewUrl) return;
fetch(pdfPreviewUrl) fetch(pdfPreviewUrl)
.then((r) => r.blob()) .then((r) => r.arrayBuffer()) // ✅ arrayBuffer instead of blob
.then((blob) => { .then((buffer) => {
const url = URL.createObjectURL(blob); downloadFile(
const a = document.createElement('a'); buffer,
a.href = url; "menu-qr.pdf",
a.download = 'menu-qr.pdf'; "application/pdf",
document.body.appendChild(a); (success) => {
a.click(); if (!success) {
a.remove(); setMessageType('error');
URL.revokeObjectURL(url); setMessageData('Failed to download the file. Please try again.');
}
}
);
}); });
}; };

View File

@ -37,6 +37,7 @@ import {
import { Messages } from '../../Components/Notifications/Messages.jsx'; import { Messages } from '../../Components/Notifications/Messages.jsx';
import { getPurchaseSupplierAndWareHouseData } from '../../Features/PurchaseOrder/PurchaseOrder.js'; import { getPurchaseSupplierAndWareHouseData } from '../../Features/PurchaseOrder/PurchaseOrder.js';
import { getSupplaierIdwithTypeBasedProducts } from '../../Features/SupplierProductMapping/SupplierProductMapping.js'; import { getSupplaierIdwithTypeBasedProducts } from '../../Features/SupplierProductMapping/SupplierProductMapping.js';
import { downloadFile } from '../../utils/downloadFile.js';
const allowedExcelTypes = [ const allowedExcelTypes = [
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx
@ -478,8 +479,8 @@ const StockExcel = ({
: c.key === 'Quantity' : c.key === 'Quantity'
? 10 ? 10
: c.key === 'Supplier' || : c.key === 'Supplier' ||
c.key === 'InvoiceDeliveryChallan' || c.key === 'InvoiceDeliveryChallan' ||
c.key === 'SupplierInvoiceNumber' c.key === 'SupplierInvoiceNumber'
? 30 ? 30
: 20, : 20,
})); }));
@ -1007,14 +1008,19 @@ const StockExcel = ({
}); });
const buffer = await workbook.xlsx.writeBuffer(); 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 filename = `PurchaseEntry_${supplierDisplayName}_${Date.now()}.xlsx`;
const link = document.createElement('a');
link.href = URL.createObjectURL(blob); downloadFile(
link.download = filename; buffer,
link.click(); filename,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
(success) => {
if (!success) {
setMessageType('error');
setMessageData('Failed to download the file. Please try again.');
}
}
);
setSupplierProducts([]); setSupplierProducts([]);
setSelectedSupplierData(null); setSelectedSupplierData(null);
@ -1332,7 +1338,7 @@ const StockExcel = ({
...record, ...record,
...values, ...values,
}); });
} catch (errInfo) {} } catch (errInfo) { }
}; };
let childNode = children; let childNode = children;

View File

@ -60,6 +60,7 @@ import {
getCommonAppPreference, getCommonAppPreference,
} from '../../Features/BrachLogin/BranchLogin.js'; } from '../../Features/BrachLogin/BranchLogin.js';
import { IoClose } from 'react-icons/io5'; import { IoClose } from 'react-icons/io5';
import { downloadFile } from '../../utils/downloadFile.js';
const StockPriceUpdate = () => { const StockPriceUpdate = () => {
const { SadminuserAccess } = useAuth(); const { SadminuserAccess } = useAuth();
@ -179,53 +180,53 @@ const StockPriceUpdate = () => {
}, },
...(hasFieldExists('Stock') ...(hasFieldExists('Stock')
? [ ? [
{ {
title: 'Stock', title: 'Stock',
dataIndex: 'Stock', dataIndex: 'Stock',
key: 'Stock', key: 'Stock',
width: 80, width: 80,
}, },
] ]
: []), : []),
...(hasFieldExists('Stock Date') ...(hasFieldExists('Stock Date')
? [ ? [
{ {
title: 'Stock Date', title: 'Stock Date',
dataIndex: 'StockDate', dataIndex: 'StockDate',
key: 'StockDate', key: 'StockDate',
width: 80, width: 80,
}, },
] ]
: []), : []),
...(hasFieldExists('Old MRP') ...(hasFieldExists('Old MRP')
? [ ? [
{ {
title: 'Old MRP', title: 'Old MRP',
dataIndex: 'OldMRP', dataIndex: 'OldMRP',
key: 'OldMRP', key: 'OldMRP',
width: 100, width: 100,
}, },
] ]
: []), : []),
...(hasFieldExists('Old SP') ...(hasFieldExists('Old SP')
? [ ? [
{ {
title: 'Old SP', title: 'Old SP',
dataIndex: 'OldSP', dataIndex: 'OldSP',
key: 'OldSP', key: 'OldSP',
width: 100, width: 100,
}, },
] ]
: []), : []),
...(hasFieldExists('Old Wholesale Price') ...(hasFieldExists('Old Wholesale Price')
? [ ? [
{ {
title: 'Old Wholesale Price', title: 'Old Wholesale Price',
dataIndex: 'OldWholeSalePrice', dataIndex: 'OldWholeSalePrice',
key: 'OldWholeSalePrice', key: 'OldWholeSalePrice',
width: 140, width: 140,
}, },
] ]
: []), : []),
// ✅ EDITABLE // ✅ EDITABLE
@ -322,7 +323,7 @@ const StockPriceUpdate = () => {
); );
excelDataRef.current excelDataRef.current
?.validateFields([`NewSellPrice${record.localId}`]) ?.validateFields([`NewSellPrice${record.localId}`])
.catch(() => {}); .catch(() => { });
} }
}} }}
/> />
@ -331,40 +332,40 @@ const StockPriceUpdate = () => {
}, },
...(hasFieldExists('New Wholesale Price') ...(hasFieldExists('New Wholesale Price')
? [ ? [
{ {
title: 'New Wholesale Price', title: 'New Wholesale Price',
dataIndex: 'NewWholeSalePrice', dataIndex: 'NewWholeSalePrice',
key: 'NewWholeSalePrice', key: 'NewWholeSalePrice',
width: 160, width: 160,
render: (value, record, index) => ( render: (value, record, index) => (
<Form.Item name={`NewWholeSalePrice${record?.localId}`}> <Form.Item name={`NewWholeSalePrice${record?.localId}`}>
<Input <Input
onChange={(e) => onChange={(e) =>
handlePriceChange( handlePriceChange(
index, index,
'NewWholeSalePrice', 'NewWholeSalePrice',
e.target.value, e.target.value,
record.localId 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" e.target.value =
inputMode="decimal" parts.length > 2
onInput={(e) => { ? `${parts[0]}.${parts.slice(1).join('')}`
let cleanedValue = e.target.value.replace(/[^0-9.]/g, ''); : cleanedValue;
const parts = cleanedValue.split('.'); }}
if (cleanedValue.startsWith('.')) { />
cleanedValue = '0' + cleanedValue; </Form.Item>
} ),
e.target.value = },
parts.length > 2 ]
? `${parts[0]}.${parts.slice(1).join('')}`
: cleanedValue;
}}
/>
</Form.Item>
),
},
]
: []), : []),
{ {
title: 'Action', title: 'Action',
@ -1092,79 +1093,79 @@ const StockPriceUpdate = () => {
}, },
...(hasField('Stock Date') ...(hasField('Stock Date')
? [ ? [
{ {
title: 'stock Date', title: 'stock Date',
dataIndex: 'InwardDate', dataIndex: 'InwardDate',
key: 'InwardDate', key: 'InwardDate',
align: 'center', align: 'center',
width: 120, width: 120,
render: (InwardDate) => render: (InwardDate) =>
InwardDate !== null ? ExtractDateFormate(InwardDate) : '-', InwardDate !== null ? ExtractDateFormate(InwardDate) : '-',
}, },
] ]
: []), : []),
...(hasField('Expiry Date') ...(hasField('Expiry Date')
? [ ? [
{ {
title: 'Exp date', title: 'Exp date',
dataIndex: 'ExpDate', dataIndex: 'ExpDate',
key: 'ExpDate', key: 'ExpDate',
align: 'center', align: 'center',
width: 100, width: 100,
render: (ExpDate) => render: (ExpDate) =>
ExpDate !== null ? ExtractDateFormate(ExpDate) : '-', ExpDate !== null ? ExtractDateFormate(ExpDate) : '-',
}, },
] ]
: []), : []),
...(hasField('Stock') ...(hasField('Stock')
? [ ? [
{ {
title: 'stock', title: 'stock',
dataIndex: 'BalanceQty', dataIndex: 'BalanceQty',
key: 'BalanceQty', key: 'BalanceQty',
align: 'right', align: 'right',
width: '60px', width: '60px',
render: (BalanceQty) => (BalanceQty !== null ? BalanceQty : '-'), render: (BalanceQty) => (BalanceQty !== null ? BalanceQty : '-'),
}, },
] ]
: []), : []),
...(hasField('Old MRP') ...(hasField('Old MRP')
? [ ? [
{ {
title: 'Old MRP', title: 'Old MRP',
dataIndex: 'MRP', dataIndex: 'MRP',
key: 'MRP', key: 'MRP',
align: 'right', align: 'right',
width: '70px', width: '70px',
render: (MRP) => (safeRound(MRP) !== null ? safeRound(MRP) : '-'), render: (MRP) => (safeRound(MRP) !== null ? safeRound(MRP) : '-'),
}, },
] ]
: []), : []),
...(hasField('Old SP') ...(hasField('Old SP')
? [ ? [
{ {
title: 'Old SP', title: 'Old SP',
dataIndex: 'SellPrice', dataIndex: 'SellPrice',
key: 'SellPrice', key: 'SellPrice',
align: 'right', align: 'right',
width: '70px', width: '70px',
render: (SellPrice) => render: (SellPrice) =>
safeRound(SellPrice) !== null ? safeRound(SellPrice) : '-', safeRound(SellPrice) !== null ? safeRound(SellPrice) : '-',
}, },
] ]
: []), : []),
...(hasField('Old Wholesale Price') ...(hasField('Old Wholesale Price')
? [ ? [
{ {
title: 'Old Wholesale Price', title: 'Old Wholesale Price',
dataIndex: 'WhSalePrice', dataIndex: 'WhSalePrice',
key: 'WhSalePrice', key: 'WhSalePrice',
align: 'right', align: 'right',
width: '120px', width: '120px',
render: (WhSalePrice) => render: (WhSalePrice) =>
safeRound(WhSalePrice) !== null ? safeRound(WhSalePrice) : '-', safeRound(WhSalePrice) !== null ? safeRound(WhSalePrice) : '-',
}, },
] ]
: []), : []),
{ {
title: 'New MRP', title: 'New MRP',
@ -1188,19 +1189,19 @@ const StockPriceUpdate = () => {
}, },
...(hasField('New Wholesale Price') ...(hasField('New Wholesale Price')
? [ ? [
{ {
title: 'New Wholesale Price', title: 'New Wholesale Price',
dataIndex: 'CurrentWhAmt', dataIndex: 'CurrentWhAmt',
key: 'CurrentWhAmt', key: 'CurrentWhAmt',
align: 'center', align: 'center',
with: '4rem', with: '4rem',
editable: true, editable: true,
render: (text, record) => ( render: (text, record) => (
<p>{text ? text : 'Enter Wholesale Price'}</p> <p>{text ? text : 'Enter Wholesale Price'}</p>
), ),
width: 120, width: 120,
}, },
] ]
: []), : []),
]; ];
@ -1481,9 +1482,9 @@ const StockPriceUpdate = () => {
isStockVariantBased === 'Yes' isStockVariantBased === 'Yes'
? BulkProductData || [] ? BulkProductData || []
: (BulkProductData || [])?.filter( : (BulkProductData || [])?.filter(
(item, index, self) => (item, index, self) =>
index === self.findIndex((p) => p.ProdId === item.ProdId) index === self.findIndex((p) => p.ProdId === item.ProdId)
); );
if (!uniqueBulkProductData?.length) { if (!uniqueBulkProductData?.length) {
setMessageType('error'); setMessageType('error');
@ -1596,9 +1597,9 @@ const StockPriceUpdate = () => {
cell.border = isHiddenCol cell.border = isHiddenCol
? undefined ? undefined
: { : {
right: { style: 'thin', color: { argb: 'FF000000' } }, right: { style: 'thin', color: { argb: 'FF000000' } },
bottom: { style: 'thin', color: { argb: 'FF000000' } }, bottom: { style: 'thin', color: { argb: 'FF000000' } },
}; };
}); });
/* ---------------- ADD DATA ---------------- */ /* ---------------- ADD DATA ---------------- */
@ -1713,14 +1714,19 @@ const StockPriceUpdate = () => {
/* ---------------- DOWNLOAD ---------------- */ /* ---------------- DOWNLOAD ---------------- */
const buffer = await workbook.xlsx.writeBuffer(); const buffer = await workbook.xlsx.writeBuffer();
const blob = new Blob([buffer], { downloadFile(
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', buffer,
}); "PriceChange_Data.xlsx",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
const link = document.createElement('a'); (success) => {
link.href = URL.createObjectURL(blob); if (success) {
link.download = 'PriceChange_Data.xlsx'; console.log("Template downloaded successfully!");
link.click(); } else {
setMessageType('error');
setMessageData('Failed to download the template. Please try again.');
}
}
)
setExportLoading(false); setExportLoading(false);
}; };
@ -1780,7 +1786,7 @@ const StockPriceUpdate = () => {
Number(current.MRP) !== Number(uploaded.NewMRP) || Number(current.MRP) !== Number(uploaded.NewMRP) ||
Number(current.SellPrice) !== Number(uploaded.NewSellPrice) || Number(current.SellPrice) !== Number(uploaded.NewSellPrice) ||
Number(current.WhSalePrice || 0) !== Number(current.WhSalePrice || 0) !==
Number(uploaded.NewWholeSalePrice || 0); Number(uploaded.NewWholeSalePrice || 0);
return { return {
...uploaded, ...uploaded,
@ -2297,17 +2303,17 @@ const StockPriceUpdate = () => {
<div> <div>
{(RadioSelection == 'Bulk' || {(RadioSelection == 'Bulk' ||
(RadioSelection == 'Single' && StockDetails.length > 0)) && ( (RadioSelection == 'Single' && StockDetails.length > 0)) && (
<div className="samplereportTableButton"> <div className="samplereportTableButton">
<Buttons <Buttons
buttonText="Submit" buttonText="Submit"
color="901D77" color="901D77"
palcement={'right'} palcement={'right'}
handleSubmit={HandlePutData} handleSubmit={HandlePutData}
icon={<ArrowRightOutlined />} icon={<ArrowRightOutlined />}
disabled={addnewAccess} disabled={addnewAccess}
></Buttons> ></Buttons>
</div> </div>
)} )}
</div> </div>
</div> </div>
{RadioSelection == 'Single' && ( {RadioSelection == 'Single' && (
@ -2325,10 +2331,10 @@ const StockPriceUpdate = () => {
StockDetails?.length < 11 StockDetails?.length < 11
? false ? false
: { : {
current: page, current: page,
pageSize: pageSize, pageSize: pageSize,
onChange: handlePageChange, onChange: handlePageChange,
} }
} }
onChange={handleChange} onChange={handleChange}
></Table> ></Table>
@ -2395,7 +2401,7 @@ const StockPriceUpdate = () => {
<div <div
className={`export-excel-div ${exportLoading ? 'is-loading' : ''}`} className={`export-excel-div ${exportLoading ? 'is-loading' : ''}`}
onClick={ onClick={
exportLoading ? () => {} : () => showPriceChangeModal() exportLoading ? () => { } : () => showPriceChangeModal()
} }
> >
<div> <div>

View File

@ -7,6 +7,7 @@ import { RiFileExcel2Fill } from 'react-icons/ri';
import { Messages } from '../../Components/Notifications/Messages.jsx'; import { Messages } from '../../Components/Notifications/Messages.jsx';
import { getSession } from '../../Services/Others.js'; import { getSession } from '../../Services/Others.js';
import './OpeningStockExcel.scss'; import './OpeningStockExcel.scss';
import { downloadFile } from '../../utils/downloadFile.js';
const TEMPLATE_HEADERS = [ const TEMPLATE_HEADERS = [
{ key: 'ProdName', header: 'Product Name' }, { key: 'ProdName', header: 'Product Name' },
@ -203,15 +204,20 @@ const OpeningStockExcel = ({ products = [], onApply, onCancel }) => {
} }
const buffer = await workbook.xlsx.writeBuffer(); const buffer = await workbook.xlsx.writeBuffer();
const blob = new Blob([buffer], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
});
const link = document.createElement('a'); downloadFile(
link.href = URL.createObjectURL(blob); buffer,
link.download = 'opening_stock_template.xlsx'; "opening_stock_template.xlsx",
link.click(); "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
URL.revokeObjectURL(link.href); (success) => {
if (success) {
console.log("Template downloaded successfully!");
} else {
setMessageType('error');
setMessageData('Failed to download the template. Please try again.');
}
}
)
} catch (error) { } catch (error) {
console.error('Template download failed:', error); console.error('Template download failed:', error);
setMessageType('error'); setMessageType('error');
@ -562,8 +568,8 @@ const OpeningStockExcel = ({ products = [], onApply, onCancel }) => {
: '', : '',
TotalPcs: TotalPcs:
row.OnePcsAvailable === 'Y' && row.OnePcsAvailable === 'Y' &&
row.TotalPiece !== undefined && row.TotalPiece !== undefined &&
row.TotalPiece !== null row.TotalPiece !== null
? row.TotalPiece.toString() ? row.TotalPiece.toString()
: 0, : 0,
InwardDetails: [], InwardDetails: [],

62
src/utils/downloadFile.js Normal file
View File

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

View File

@ -7,7 +7,7 @@ export default defineConfig(({ mode }) => {
return { return {
plugins: [react()], plugins: [react()],
base: isProd ? "/apps/retail/" : "/", base: isProd ? "/apps/retail/" : "/", //for capcitor base: isProd ? "/" : "/",
envDir: "src", envDir: "src",
envPrefix: "ENV_", envPrefix: "ENV_",