From 012d3124ef3a9ebd9fb69dd027fd20e80b3c15dd Mon Sep 17 00:00:00 2001 From: Srinath Date: Mon, 23 Mar 2026 10:55:21 +0530 Subject: [PATCH] Fix issues with date, subcategory, category, and brand --- src/Pages/Product/ExcelUpload.jsx | 270 ++++++++++++++++++++++++------ 1 file changed, 215 insertions(+), 55 deletions(-) diff --git a/src/Pages/Product/ExcelUpload.jsx b/src/Pages/Product/ExcelUpload.jsx index f452a3f..18e7388 100644 --- a/src/Pages/Product/ExcelUpload.jsx +++ b/src/Pages/Product/ExcelUpload.jsx @@ -960,15 +960,28 @@ const ProductExcel = ({ const rows = nonEmptyRows.slice(1); const dateFields = [ - 'Available From', - 'Available To', 'Manufacture Date', 'Expire Date', 'Stock Date', ]; function convertToDisplayFormat(dateString) { + if (!dateString) return ''; + // Handle DD/MM/YY or DD/MM/YYYY (from Excel dateNF format) + const slashParts = String(dateString).split('/'); + if (slashParts.length === 3) { + const [d, m, y] = slashParts; + const fullYear = y.length === 2 ? '20' + y : y; + return `${d.padStart(2,'0')}-${m.padStart(2,'0')}-${fullYear}`; + } + // Handle DD-MM-YYYY already in correct format + const dashParts = String(dateString).split('-'); + if (dashParts.length === 3 && dashParts[2].length === 4) { + return dateString; // already DD-MM-YYYY + } + // Fallback: try native Date parse (YYYY-MM-DD etc) const date = new Date(dateString); + if (isNaN(date.getTime())) return ''; const day = date.getDate().toString().padStart(2, '0'); const month = (date.getMonth() + 1).toString().padStart(2, '0'); const year = date.getFullYear().toString(); @@ -1070,9 +1083,9 @@ const ProductExcel = ({ }; const updateImageUrl = (url, index, key) => { + const newData1 = [...Datas]; newData1[key] = { ...newData1[key], Productimage: url }; - setDatas(newData1); setExcelData(newData1); }; @@ -1087,7 +1100,7 @@ const ProductExcel = ({ if (selectedImageIndex != null && selectedImageIndex != undefined) { try { - if (selectedImage.image !== undefined) { + if (selectedImage?.image !== undefined) { const response = await fetch(selectedImage.image); const datas = await response.blob(); const metadata = { @@ -1305,13 +1318,7 @@ const ProductExcel = ({ validation: { type: 'list', allowBlank: true, - formulae: [ - '"' + - (typeof CategoryNames !== 'undefined' - ? CategoryNames.join(',') - : 'Sample Category') + - '"', - ], + formulae: [`Sheet2!$B$2:$B$${(CategoryNames?.length || 0) + 1}`], }, sampleValue: sampleData?.category || 'Sample Category', headerColor: 'FF2929', @@ -1324,7 +1331,7 @@ const ProductExcel = ({ ...headerStyle, font: { bold: true, color: { argb: '#000000' } }, }, - validation: null, + validation: null, // set dynamically per row below sampleValue: sampleData?.subCategory || 'Sample Sub Category', headerColor: '52c41a', }, @@ -1336,7 +1343,7 @@ const ProductExcel = ({ ...headerStyle, font: { bold: true, color: { argb: '#000000' } }, }, - validation: null, + validation: null, // set dynamically per row below sampleValue: sampleData?.brand || 'Sample Brand', headerColor: '52c41a', }, @@ -1448,20 +1455,8 @@ const ProductExcel = ({ ...headerStyle, font: { bold: true, color: { argb: '#000000' } }, }, - validation: { - type: 'list', - allowBlank: true, - formulae: [ - '"' + - (typeof TaxDatas !== 'undefined' - ? TaxDatas.map((item) => - item.replace(/,/g, '').replace('-', '-').trim() - ).join(',') - : 'NIL - 0%') + - '"', - ], - }, - sampleValue: 'NIL - 0%', + validation: null, // set via Sheet2 range reference below + sampleValue: sampleData?.tax || 'NIL - 0%', headerColor: '52c41a', }, AutoGenerateQr: { @@ -1510,7 +1505,7 @@ const ProductExcel = ({ }, OnePiecePrice: { header: 'OnePiece Price', - key: 'StockAvailable', + key: 'OnePiecePrice', width: 20, style: { ...headerStyle, @@ -1529,7 +1524,7 @@ const ProductExcel = ({ }, AutoGenOnePieceQr: { header: 'Auto Generate One Piece Qrcode', - key: 'StockDate', + key: 'AutoGenOnePieceQr', width: 30, style: { ...headerStyle, @@ -1545,7 +1540,7 @@ const ProductExcel = ({ }, AutoGenOnePieceQrNum: { header: 'Auto Generate One Piece Qrcode Number', - key: 'StockDate', + key: 'AutoGenOnePieceQrNum', width: 40, style: { ...headerStyle, @@ -1629,27 +1624,31 @@ const ProductExcel = ({ }, AvailableFrom: { header: 'Available From', - key: 'AvailableFrom TIME', + key: 'AvailableFrom', width: 20, style: { ...headerStyle, font: { bold: true, color: { argb: '#000000' } }, + numFmt: '@', }, validation: null, - sampleValue: new Date(), + sampleValue: '08:00:00', headerColor: '52c41a', + isTimeField: true, }, AvailableTo: { header: 'Available To', - key: 'AvailableTo TIME', + key: 'AvailableTo', width: 20, style: { ...headerStyle, font: { bold: true, color: { argb: '#000000' } }, + numFmt: '@', }, validation: null, - sampleValue: new Date(), + sampleValue: '22:00:00', headerColor: '52c41a', + isTimeField: true, }, }; @@ -1781,11 +1780,26 @@ const ProductExcel = ({ }; }); - // Add sample data in row 2 - + // Add sample data in row 2 — time fields forced to text format selectedColumns.forEach((config, index) => { - const columnLetter = getExcelColumnLetter(index + 1); // ✅ FIXED - worksheet.getCell(`${columnLetter}2`).value = config.sampleValue; + const columnLetter = getExcelColumnLetter(index + 1); + const cell = worksheet.getCell(`${columnLetter}2`); + if (config.isTimeField) { + cell.numFmt = '@'; + cell.value = String(config.sampleValue); + } else { + cell.value = config.sampleValue; + } + }); + + // Force text format on all data rows for time fields + selectedColumns.forEach((config, index) => { + if (config.isTimeField) { + const columnLetter = getExcelColumnLetter(index + 1); + for (let r = 2; r <= 1002; r++) { + worksheet.getCell(`${columnLetter}${r}`).numFmt = '@'; + } + } }); // Add validation to columns @@ -1812,29 +1826,42 @@ const ProductExcel = ({ } }); +// // Now set protection for all rows +// // First, unlock ALL cells in the worksheet +// for (let rowNum = 1; rowNum <= worksheet.rowCount; rowNum++) { +// const row = worksheet.getRow(rowNum); +// row.eachCell({ includeEmpty: true }, (cell, colNumber) => { +// const config = selectedColumns[colNumber - 1]; +// cell.protection = { locked: config?.locked || false }; +// }); +// } + +// // Then lock ONLY the header row (row 1) and sample row (row 2) +// worksheet.getRow(1).eachCell({ includeEmpty: true }, (cell) => { +// cell.protection = { locked: true }; +// }); + +// worksheet.getRow(2).eachCell({ includeEmpty: true }, (cell) => { +// cell.protection = { locked: true }; +// }); // Add empty rows for data entry for (let i = 1; i <= 1000; i++) { worksheet.addRow({}); } - // Now set protection for all rows - // First, unlock ALL cells in the worksheet - for (let rowNum = 1; rowNum <= worksheet.rowCount; rowNum++) { - const row = worksheet.getRow(rowNum); - row.eachCell({ includeEmpty: true }, (cell, colNumber) => { - const config = selectedColumns[colNumber - 1]; - cell.protection = { locked: config?.locked || false }; - }); + // Explicitly unlock all data-entry cells (rows 3+) for every column + for (let rowNum = 3; rowNum <= worksheet.rowCount; rowNum++) { + for (let colNum = 1; colNum <= selectedColumns.length; colNum++) { + const config = selectedColumns[colNum - 1]; + worksheet.getCell(rowNum, colNum).protection = { locked: config?.locked || false }; + } } - // Then lock ONLY the header row (row 1) and sample row (row 2) - worksheet.getRow(1).eachCell({ includeEmpty: true }, (cell) => { - cell.protection = { locked: true }; - }); - - worksheet.getRow(2).eachCell({ includeEmpty: true }, (cell) => { - cell.protection = { locked: true }; - }); + // Lock header row (row 1) and sample row (row 2) + for (let colNum = 1; colNum <= selectedColumns.length; colNum++) { + worksheet.getCell(1, colNum).protection = { locked: true }; + worksheet.getCell(2, colNum).protection = { locked: true }; + } // Protect the worksheet await worksheet.protect('', { @@ -2158,6 +2185,139 @@ const ProductExcel = ({ }); } + // Write TaxDatas into Sheet2 column N for range-based dropdown (avoids 255-char limit) + if (typeof TaxDatas !== 'undefined' && TaxDatas?.length > 0) { + TaxDatas.forEach((taxItem, idx) => { + worksheet1.getCell(`N${idx + 2}`).value = taxItem.replace(/,/g, '').trim(); + }); + } + + // Apply Tax validation using Sheet2 column N range + const taxColIndex = selectedColumns.findIndex((c) => c.key === 'TaxId') + 1; + if (taxColIndex > 0 && TaxDatas?.length > 0) { + for (let rowNumber = 3; rowNumber <= 1002; rowNumber++) { + worksheet.getCell(rowNumber, taxColIndex).dataValidation = { + type: 'list', + allowBlank: true, + formulae: [`Sheet2!$N$2:$N$${TaxDatas.length + 1}`], + showErrorMessage: false, + }; + } + } + + // ── Dynamic SubCategory dropdown per Category ────────────────────── + // Build a map: categoryName → [subcat names] + const catSubcatMap = {}; + if (CategoryNames && SubCatData && Subcatnumfid) { + CategoryNames.forEach((catName, catIdx) => { + const catId = CategoryId?.[catIdx]; + const subcats = SubCatData.filter( + (_, sIdx) => Subcatnumfid[sIdx] == catId + ); + catSubcatMap[catName] = subcats; + }); + } + + // Write each category's subcats into Sheet2 starting at column O (col 15) + // Row 1 = category name header, rows 2+ = subcat names + const catSubcatStartCol = 15; // column O + const catNameToColLetter = {}; + + if (CategoryNames) { + CategoryNames.forEach((catName, catIdx) => { + const colIndex = catSubcatStartCol + catIdx; + const colLetter = getExcelColumnLetter(colIndex); + catNameToColLetter[catName] = colLetter; + + // Write header (category name) + worksheet1.getCell(`${colLetter}1`).value = catName; + + // Write subcats for this category + const subcats = catSubcatMap[catName] || []; + subcats.forEach((subcat, sIdx) => { + worksheet1.getCell(`${colLetter}${sIdx + 2}`).value = subcat; + }); + + // Define a named range for this category's subcats + const safeName = catName.replace(/[^A-Za-z0-9_]/g, '_'); + const rangeRef = subcats.length > 0 + ? `Sheet2!$${colLetter}$2:$${colLetter}$${subcats.length + 1}` + : `Sheet2!$${colLetter}$2:$${colLetter}$2`; + + workbook.definedNames.add(rangeRef, safeName); + }); + } + + // Find which column index ProdCat and ProdSubCat are in Sheet1 + const catColIndex = selectedColumns.findIndex((c) => c.key === 'ProdCat') + 1; + const subCatColIndex = selectedColumns.findIndex((c) => c.key === 'ProdSubCat') + 1; + + if (catColIndex > 0 && subCatColIndex > 0) { + const catColLetter = getExcelColumnLetter(catColIndex); + + for (let rowNumber = 3; rowNumber <= 1002; rowNumber++) { + const cell = worksheet.getCell(rowNumber, subCatColIndex); + cell.dataValidation = { + type: 'list', + allowBlank: true, + formulae: [`INDIRECT(SUBSTITUTE(${catColLetter}${rowNumber}," ","_"))`], + showErrorMessage: false, + }; + } + } + + // ── Dynamic Brand dropdown per SubCategory ──────────────────────── + // Build a map: subcatName → [brand names] using Allbranddatanumfid (parent subcat ID) + const subcatBrandMap = {}; + if (SubCatData && Allbranddata && Allbranddatanumfid) { + SubCatData.forEach((subcatName, sIdx) => { + const subcatId = SubcatId?.[sIdx]; + const brands = Allbranddata.filter( + (_, bIdx) => Allbranddatanumfid[bIdx] == subcatId + ); + subcatBrandMap[subcatName] = brands; + }); + } + + // Write each subcat's brands into Sheet2 starting after the category columns + const brandStartCol = catSubcatStartCol + (CategoryNames?.length || 0) + 1; + + if (SubCatData) { + SubCatData.forEach((subcatName, sIdx) => { + const colIndex = brandStartCol + sIdx; + const colLetter = getExcelColumnLetter(colIndex); + + worksheet1.getCell(`${colLetter}1`).value = `B_${subcatName}`; + + const brands = subcatBrandMap[subcatName] || []; + brands.forEach((brand, bIdx) => { + worksheet1.getCell(`${colLetter}${bIdx + 2}`).value = brand; + }); + + const safeName = `B_${subcatName.replace(/[^A-Za-z0-9_]/g, '_')}`; + const rangeRef = brands.length > 0 + ? `Sheet2!$${colLetter}$2:$${colLetter}$${brands.length + 1}` + : `Sheet2!$${colLetter}$2:$${colLetter}$2`; + workbook.definedNames.add(rangeRef, safeName); + }); + } + + // Apply INDIRECT brand validation based on selected SubCategory + const brandColIndex = selectedColumns.findIndex((c) => c.key === 'Brand') + 1; + if (subCatColIndex > 0 && brandColIndex > 0) { + const subCatColLetter = getExcelColumnLetter(subCatColIndex); + for (let rowNumber = 3; rowNumber <= 1002; rowNumber++) { + const cell = worksheet.getCell(rowNumber, brandColIndex); + cell.dataValidation = { + type: 'list', + allowBlank: true, + formulae: [`INDIRECT("B_"&SUBSTITUTE(${subCatColLetter}${rowNumber}," ","_"))`], + showErrorMessage: false, + }; + } + } + // ───────────────────────────────────────────────────────────────────── + // Original complex logic for column C (SUBCAT DATAS) worksheet1 .getColumn('C') @@ -2536,7 +2696,7 @@ const ProductExcel = ({
updateImageUrl(url, index)} + updateImageUrl={(url) => updateImageUrl(url, index, record.key)} // ImageLink={record.Productimage || ""} ImageLink={ onlineImage