Merge pull request 'srinath' (#296) from srinath into main
Reviewed-on: Pozomind/pozo-retail-app#296
This commit is contained in:
commit
a50ea556f1
|
|
@ -12,6 +12,7 @@ import { uploadImage } from "../../../../../Features/upload/upload";
|
||||||
import { SelfBookingEmailSendLink } from "../../../../../Features/ConfigMasterPage/ConfigMasterPage";
|
import { SelfBookingEmailSendLink } from "../../../../../Features/ConfigMasterPage/ConfigMasterPage";
|
||||||
import { Messages } from "../../../../../Components/Notifications/Messages";
|
import { Messages } from "../../../../../Components/Notifications/Messages";
|
||||||
const { RangePicker } = DatePicker;
|
const { RangePicker } = DatePicker;
|
||||||
|
import dayjs from "dayjs";
|
||||||
const uploadApiUrl = import.meta.env.ENV_IMAGE_UPLOAD_API_URL;
|
const uploadApiUrl = import.meta.env.ENV_IMAGE_UPLOAD_API_URL;
|
||||||
|
|
||||||
const ReprintPDFDataShare = ({ printDatas, printerTemplateStyle, SettingDataSelector, open = false, onClose = () => { } }) => {
|
const ReprintPDFDataShare = ({ printDatas, printerTemplateStyle, SettingDataSelector, open = false, onClose = () => { } }) => {
|
||||||
|
|
@ -40,7 +41,9 @@ const ReprintPDFDataShare = ({ printDatas, printerTemplateStyle, SettingDataSele
|
||||||
fetchData(dateStrings);
|
fetchData(dateStrings);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const disabledDate = (current) => {
|
||||||
|
return current && current > dayjs().endOf("day");
|
||||||
|
};
|
||||||
const fetchData = async (dates = dateStrings) => {
|
const fetchData = async (dates = dateStrings) => {
|
||||||
setIsFetching(true);
|
setIsFetching(true);
|
||||||
try {
|
try {
|
||||||
|
|
@ -184,8 +187,9 @@ Thank you for choosing us!`;
|
||||||
<div>
|
<div>
|
||||||
<RangePicker
|
<RangePicker
|
||||||
placeholder={['Start Date', 'End Date']}
|
placeholder={['Start Date', 'End Date']}
|
||||||
format="YYYY-MM-DD"
|
format="DD-MM-YYYY"
|
||||||
onChange={handleDateChange}
|
onChange={handleDateChange}
|
||||||
|
disabledDate={disabledDate}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -606,6 +606,8 @@ const ProductExcel = ({
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [message, setMessage] = useState(false);
|
const [message, setMessage] = useState(false);
|
||||||
const [Datas, setDatas] = useState();
|
const [Datas, setDatas] = useState();
|
||||||
|
console.log(Datas, 'Datas32323232');
|
||||||
|
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
const [MappingOpen, setMappingOpen] = useState(false);
|
const [MappingOpen, setMappingOpen] = useState(false);
|
||||||
const [fieldMapping, setFieldMapping] = useState({});
|
const [fieldMapping, setFieldMapping] = useState({});
|
||||||
|
|
@ -843,6 +845,7 @@ const ProductExcel = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFileUpload = (e) => {
|
const handleFileUpload = (e) => {
|
||||||
|
|
||||||
const file = e.target.files[0];
|
const file = e.target.files[0];
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
|
|
||||||
|
|
@ -957,15 +960,28 @@ const ProductExcel = ({
|
||||||
const rows = nonEmptyRows.slice(1);
|
const rows = nonEmptyRows.slice(1);
|
||||||
|
|
||||||
const dateFields = [
|
const dateFields = [
|
||||||
'Available From',
|
|
||||||
'Available To',
|
|
||||||
'Manufacture Date',
|
'Manufacture Date',
|
||||||
'Expire Date',
|
'Expire Date',
|
||||||
'Stock Date',
|
'Stock Date',
|
||||||
];
|
];
|
||||||
|
|
||||||
function convertToDisplayFormat(dateString) {
|
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);
|
const date = new Date(dateString);
|
||||||
|
if (isNaN(date.getTime())) return '';
|
||||||
const day = date.getDate().toString().padStart(2, '0');
|
const day = date.getDate().toString().padStart(2, '0');
|
||||||
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
||||||
const year = date.getFullYear().toString();
|
const year = date.getFullYear().toString();
|
||||||
|
|
@ -999,6 +1015,12 @@ const ProductExcel = ({
|
||||||
item['Product Varient Name'] === undefined
|
item['Product Varient Name'] === undefined
|
||||||
? 'Variant 1'
|
? 'Variant 1'
|
||||||
: item['Product Varient Name'],
|
: item['Product Varient Name'],
|
||||||
|
'Manufacture Date':
|
||||||
|
item['Manufacture Date'] == 'NaN-NaN-NaN' ? '' : item['Manufacture Date'],
|
||||||
|
'Expire Date':
|
||||||
|
item['Expire Date'] == 'NaN-NaN-NaN' ? '' : item['Expire Date'],
|
||||||
|
'Available From':
|
||||||
|
item['Available From'] == 'NaN-NaN-NaN' ? '' : item['Available From'],
|
||||||
'Available To':
|
'Available To':
|
||||||
item['Available To'] == 'NaN-NaN-NaN' ? '' : item['Available To'],
|
item['Available To'] == 'NaN-NaN-NaN' ? '' : item['Available To'],
|
||||||
ProdId: item['ProdId'] || null,
|
ProdId: item['ProdId'] || null,
|
||||||
|
|
@ -1061,9 +1083,9 @@ const ProductExcel = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateImageUrl = (url, index, key) => {
|
const updateImageUrl = (url, index, key) => {
|
||||||
|
|
||||||
const newData1 = [...Datas];
|
const newData1 = [...Datas];
|
||||||
newData1[key] = { ...newData1[key], Productimage: url };
|
newData1[key] = { ...newData1[key], Productimage: url };
|
||||||
|
|
||||||
setDatas(newData1);
|
setDatas(newData1);
|
||||||
setExcelData(newData1);
|
setExcelData(newData1);
|
||||||
};
|
};
|
||||||
|
|
@ -1078,7 +1100,7 @@ const ProductExcel = ({
|
||||||
|
|
||||||
if (selectedImageIndex != null && selectedImageIndex != undefined) {
|
if (selectedImageIndex != null && selectedImageIndex != undefined) {
|
||||||
try {
|
try {
|
||||||
if (selectedImage.image !== undefined) {
|
if (selectedImage?.image !== undefined) {
|
||||||
const response = await fetch(selectedImage.image);
|
const response = await fetch(selectedImage.image);
|
||||||
const datas = await response.blob();
|
const datas = await response.blob();
|
||||||
const metadata = {
|
const metadata = {
|
||||||
|
|
@ -1296,13 +1318,7 @@ const ProductExcel = ({
|
||||||
validation: {
|
validation: {
|
||||||
type: 'list',
|
type: 'list',
|
||||||
allowBlank: true,
|
allowBlank: true,
|
||||||
formulae: [
|
formulae: [`Sheet2!$B$2:$B$${(CategoryNames?.length || 0) + 1}`],
|
||||||
'"' +
|
|
||||||
(typeof CategoryNames !== 'undefined'
|
|
||||||
? CategoryNames.join(',')
|
|
||||||
: 'Sample Category') +
|
|
||||||
'"',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
sampleValue: sampleData?.category || 'Sample Category',
|
sampleValue: sampleData?.category || 'Sample Category',
|
||||||
headerColor: 'FF2929',
|
headerColor: 'FF2929',
|
||||||
|
|
@ -1315,7 +1331,7 @@ const ProductExcel = ({
|
||||||
...headerStyle,
|
...headerStyle,
|
||||||
font: { bold: true, color: { argb: '#000000' } },
|
font: { bold: true, color: { argb: '#000000' } },
|
||||||
},
|
},
|
||||||
validation: null,
|
validation: null, // set dynamically per row below
|
||||||
sampleValue: sampleData?.subCategory || 'Sample Sub Category',
|
sampleValue: sampleData?.subCategory || 'Sample Sub Category',
|
||||||
headerColor: '52c41a',
|
headerColor: '52c41a',
|
||||||
},
|
},
|
||||||
|
|
@ -1327,7 +1343,7 @@ const ProductExcel = ({
|
||||||
...headerStyle,
|
...headerStyle,
|
||||||
font: { bold: true, color: { argb: '#000000' } },
|
font: { bold: true, color: { argb: '#000000' } },
|
||||||
},
|
},
|
||||||
validation: null,
|
validation: null, // set dynamically per row below
|
||||||
sampleValue: sampleData?.brand || 'Sample Brand',
|
sampleValue: sampleData?.brand || 'Sample Brand',
|
||||||
headerColor: '52c41a',
|
headerColor: '52c41a',
|
||||||
},
|
},
|
||||||
|
|
@ -1439,20 +1455,8 @@ const ProductExcel = ({
|
||||||
...headerStyle,
|
...headerStyle,
|
||||||
font: { bold: true, color: { argb: '#000000' } },
|
font: { bold: true, color: { argb: '#000000' } },
|
||||||
},
|
},
|
||||||
validation: {
|
validation: null, // set via Sheet2 range reference below
|
||||||
type: 'list',
|
sampleValue: sampleData?.tax || 'NIL - 0%',
|
||||||
allowBlank: true,
|
|
||||||
formulae: [
|
|
||||||
'"' +
|
|
||||||
(typeof TaxDatas !== 'undefined'
|
|
||||||
? TaxDatas.map((item) =>
|
|
||||||
item.replace(/,/g, '').replace('-', '-').trim()
|
|
||||||
).join(',')
|
|
||||||
: 'NIL - 0%') +
|
|
||||||
'"',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
sampleValue: 'NIL - 0%',
|
|
||||||
headerColor: '52c41a',
|
headerColor: '52c41a',
|
||||||
},
|
},
|
||||||
AutoGenerateQr: {
|
AutoGenerateQr: {
|
||||||
|
|
@ -1501,7 +1505,7 @@ const ProductExcel = ({
|
||||||
},
|
},
|
||||||
OnePiecePrice: {
|
OnePiecePrice: {
|
||||||
header: 'OnePiece Price',
|
header: 'OnePiece Price',
|
||||||
key: 'StockAvailable',
|
key: 'OnePiecePrice',
|
||||||
width: 20,
|
width: 20,
|
||||||
style: {
|
style: {
|
||||||
...headerStyle,
|
...headerStyle,
|
||||||
|
|
@ -1520,7 +1524,7 @@ const ProductExcel = ({
|
||||||
},
|
},
|
||||||
AutoGenOnePieceQr: {
|
AutoGenOnePieceQr: {
|
||||||
header: 'Auto Generate One Piece Qrcode',
|
header: 'Auto Generate One Piece Qrcode',
|
||||||
key: 'StockDate',
|
key: 'AutoGenOnePieceQr',
|
||||||
width: 30,
|
width: 30,
|
||||||
style: {
|
style: {
|
||||||
...headerStyle,
|
...headerStyle,
|
||||||
|
|
@ -1536,7 +1540,7 @@ const ProductExcel = ({
|
||||||
},
|
},
|
||||||
AutoGenOnePieceQrNum: {
|
AutoGenOnePieceQrNum: {
|
||||||
header: 'Auto Generate One Piece Qrcode Number',
|
header: 'Auto Generate One Piece Qrcode Number',
|
||||||
key: 'StockDate',
|
key: 'AutoGenOnePieceQrNum',
|
||||||
width: 40,
|
width: 40,
|
||||||
style: {
|
style: {
|
||||||
...headerStyle,
|
...headerStyle,
|
||||||
|
|
@ -1620,27 +1624,31 @@ const ProductExcel = ({
|
||||||
},
|
},
|
||||||
AvailableFrom: {
|
AvailableFrom: {
|
||||||
header: 'Available From',
|
header: 'Available From',
|
||||||
key: 'AvailableFrom TIME',
|
key: 'AvailableFrom',
|
||||||
width: 20,
|
width: 20,
|
||||||
style: {
|
style: {
|
||||||
...headerStyle,
|
...headerStyle,
|
||||||
font: { bold: true, color: { argb: '#000000' } },
|
font: { bold: true, color: { argb: '#000000' } },
|
||||||
|
numFmt: '@',
|
||||||
},
|
},
|
||||||
validation: null,
|
validation: null,
|
||||||
sampleValue: new Date(),
|
sampleValue: '08:00:00',
|
||||||
headerColor: '52c41a',
|
headerColor: '52c41a',
|
||||||
|
isTimeField: true,
|
||||||
},
|
},
|
||||||
AvailableTo: {
|
AvailableTo: {
|
||||||
header: 'Available To',
|
header: 'Available To',
|
||||||
key: 'AvailableTo TIME',
|
key: 'AvailableTo',
|
||||||
width: 20,
|
width: 20,
|
||||||
style: {
|
style: {
|
||||||
...headerStyle,
|
...headerStyle,
|
||||||
font: { bold: true, color: { argb: '#000000' } },
|
font: { bold: true, color: { argb: '#000000' } },
|
||||||
|
numFmt: '@',
|
||||||
},
|
},
|
||||||
validation: null,
|
validation: null,
|
||||||
sampleValue: new Date(),
|
sampleValue: '22:00:00',
|
||||||
headerColor: '52c41a',
|
headerColor: '52c41a',
|
||||||
|
isTimeField: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1772,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) => {
|
selectedColumns.forEach((config, index) => {
|
||||||
const columnLetter = getExcelColumnLetter(index + 1); // ✅ FIXED
|
const columnLetter = getExcelColumnLetter(index + 1);
|
||||||
worksheet.getCell(`${columnLetter}2`).value = config.sampleValue;
|
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
|
// Add validation to columns
|
||||||
|
|
@ -1803,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
|
// Add empty rows for data entry
|
||||||
for (let i = 1; i <= 1000; i++) {
|
for (let i = 1; i <= 1000; i++) {
|
||||||
worksheet.addRow({});
|
worksheet.addRow({});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now set protection for all rows
|
// Explicitly unlock all data-entry cells (rows 3+) for every column
|
||||||
// First, unlock ALL cells in the worksheet
|
for (let rowNum = 3; rowNum <= worksheet.rowCount; rowNum++) {
|
||||||
for (let rowNum = 1; rowNum <= worksheet.rowCount; rowNum++) {
|
for (let colNum = 1; colNum <= selectedColumns.length; colNum++) {
|
||||||
const row = worksheet.getRow(rowNum);
|
const config = selectedColumns[colNum - 1];
|
||||||
row.eachCell({ includeEmpty: true }, (cell, colNumber) => {
|
worksheet.getCell(rowNum, colNum).protection = { locked: config?.locked || false };
|
||||||
const config = selectedColumns[colNumber - 1];
|
}
|
||||||
cell.protection = { locked: config?.locked || false };
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then lock ONLY the header row (row 1) and sample row (row 2)
|
// Lock header row (row 1) and sample row (row 2)
|
||||||
worksheet.getRow(1).eachCell({ includeEmpty: true }, (cell) => {
|
for (let colNum = 1; colNum <= selectedColumns.length; colNum++) {
|
||||||
cell.protection = { locked: true };
|
worksheet.getCell(1, colNum).protection = { locked: true };
|
||||||
});
|
worksheet.getCell(2, colNum).protection = { locked: true };
|
||||||
|
}
|
||||||
worksheet.getRow(2).eachCell({ includeEmpty: true }, (cell) => {
|
|
||||||
cell.protection = { locked: true };
|
|
||||||
});
|
|
||||||
|
|
||||||
// Protect the worksheet
|
// Protect the worksheet
|
||||||
await worksheet.protect('', {
|
await worksheet.protect('', {
|
||||||
|
|
@ -2149,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)
|
// Original complex logic for column C (SUBCAT DATAS)
|
||||||
worksheet1
|
worksheet1
|
||||||
.getColumn('C')
|
.getColumn('C')
|
||||||
|
|
@ -2527,7 +2696,7 @@ const ProductExcel = ({
|
||||||
<div className="imgUpldr" style={{ fontSize: '15px' }}>
|
<div className="imgUpldr" style={{ fontSize: '15px' }}>
|
||||||
<Imageupload
|
<Imageupload
|
||||||
singleImage={true}
|
singleImage={true}
|
||||||
updateImageUrl={(url) => updateImageUrl(url, index)}
|
updateImageUrl={(url) => updateImageUrl(url, index, record.key)}
|
||||||
// ImageLink={record.Productimage || ""}
|
// ImageLink={record.Productimage || ""}
|
||||||
ImageLink={
|
ImageLink={
|
||||||
onlineImage
|
onlineImage
|
||||||
|
|
|
||||||
|
|
@ -629,6 +629,10 @@ const ProductForm = ({ formType }) => {
|
||||||
}, [editstate?.Rack, RackData]);
|
}, [editstate?.Rack, RackData]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// Auto-fill "Variant X" only when we are adding a new variant.
|
||||||
|
// When editing, another effect will populate the full data.
|
||||||
|
if (!openVariant || variantEdit) return;
|
||||||
|
|
||||||
let variantAddData11 = [...variantPriceData];
|
let variantAddData11 = [...variantPriceData];
|
||||||
if (variantAddData11?.length > 0) {
|
if (variantAddData11?.length > 0) {
|
||||||
const lastAddProdVariantName11 =
|
const lastAddProdVariantName11 =
|
||||||
|
|
@ -677,7 +681,32 @@ const ProductForm = ({ formType }) => {
|
||||||
ProdVariantName: `Variant ${parseInt(variantAddData11?.length) + parseInt(2)}`,
|
ProdVariantName: `Variant ${parseInt(variantAddData11?.length) + parseInt(2)}`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [openVariant]);
|
}, [openVariant, variantEdit, variantPriceData]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Populate edit values only after the variant form is mounted.
|
||||||
|
if (!openVariant || !variantEdit) return;
|
||||||
|
if (
|
||||||
|
variantEditIndex === undefined ||
|
||||||
|
variantEditIndex === null ||
|
||||||
|
!variantPriceData?.length
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const row = variantPriceData?.[variantEditIndex];
|
||||||
|
if (!row) return;
|
||||||
|
|
||||||
|
formVariantRef?.current?.setFieldsValue({
|
||||||
|
ProdVariantName: row?.ProdVariantName,
|
||||||
|
AmountOfPiece: row?.OnePcsPrice,
|
||||||
|
MRP: row?.MRP,
|
||||||
|
SellPrice: row?.SellPrice,
|
||||||
|
WhSalePrice: row?.WhSalePrice,
|
||||||
|
OfferPrice: row?.OfferPrice,
|
||||||
|
SpecialPrice: row?.SpecialPrice,
|
||||||
|
});
|
||||||
|
}, [openVariant, variantEdit, variantEditIndex, variantPriceData]);
|
||||||
|
|
||||||
const onComplete = useCallback(() => {
|
const onComplete = useCallback(() => {
|
||||||
setMessageData(null);
|
setMessageData(null);
|
||||||
|
|
@ -1573,28 +1602,7 @@ const ProductForm = ({ formType }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const variantActionsFormatter = (row, index) => {
|
const variantActionsFormatter = (row, index) => {
|
||||||
if (StockOpen == 'Y') {
|
setOpenVariant(true);
|
||||||
formVariantRef?.current?.setFieldsValue({
|
|
||||||
ProdVariantName: row?.ProdVariantName,
|
|
||||||
AmountOfPiece: row?.OnePcsPrice,
|
|
||||||
MRP: row?.MRP,
|
|
||||||
SellPrice: row?.SellPrice,
|
|
||||||
WhSalePrice: row?.WhSalePrice,
|
|
||||||
OfferPrice: row?.OfferPrice,
|
|
||||||
SpecialPrice: row?.SpecialPrice,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
formVariantRef?.current?.setFieldsValue({
|
|
||||||
ProdVariantName: row?.ProdVariantName,
|
|
||||||
AmountOfPiece: row?.OnePcsPrice,
|
|
||||||
MRP: row?.MRP,
|
|
||||||
SellPrice: row?.SellPrice,
|
|
||||||
WhSalePrice: row?.WhSalePrice,
|
|
||||||
OfferPrice: row?.OfferPrice,
|
|
||||||
SpecialPrice: row?.SpecialPrice,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setVariantEdit(true);
|
setVariantEdit(true);
|
||||||
setVariantEditIndex(index);
|
setVariantEditIndex(index);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue