subhasmitalmg-react-spreadsheet-import
Version:
React spreadsheet import for xlsx and csv files with column matching and validation steps
155 lines (152 loc) • 8.38 kB
JavaScript
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
import { useState, useMemo, useCallback, useEffect } from 'react';
import { useStyleConfig, ModalBody, Box, Heading, Button, Switch } from '@chakra-ui/react';
import { ContinueButton } from '../../components/ContinueButton.js';
import { useRsi } from '../../hooks/useRsi.js';
import { addErrorsAndRunHooks } from './utils/dataMutations.js';
import { generateColumns } from './components/columns.js';
import { Table } from '../../components/Table.js';
import { SubmitDataAlert } from '../../components/Alerts/SubmitDataAlert.js';
import { SubmitSuccessAlert } from '../../components/Alerts/SubmitSuccessAlert.js';
import { NoDataPresentAlert } from '../../components/Alerts/NoDataPresentAlert.js';
const ValidationStep = ({ initialData, file }) => {
const { translations, fields, onClose, onSubmit, onDownload, rowHook, tableHook } = useRsi(); //SPO-4200
const styles = useStyleConfig("ValidationStep");
const [data, setData] = useState(useMemo(() => addErrorsAndRunHooks(initialData, fields, rowHook, tableHook),
// eslint-disable-next-line react-hooks/exhaustive-deps
[]));
const [selectedRows, setSelectedRows] = useState(new Set());
const [filterByErrors, setFilterByErrors] = useState(false);
const [showSubmitAlert, setShowSubmitAlert] = useState(false);
const [showSuccessSubmitAlert, setSuccessShowSubmitAlert] = useState(false); //SPO-4200
const [showNoDataPresentAlert, setNoDataPresentAlert] = useState(false); //SPO-4200
// const [showNoofErrorAlert, setNoofErrorAlert] = useState(false)
const updateData = useCallback((rows) => {
setData(addErrorsAndRunHooks(rows, fields, rowHook, tableHook));
}, [setData, rowHook, tableHook, fields]);
const deleteSelectedRows = () => {
if (selectedRows.size) {
const newData = data.filter((value) => !selectedRows.has(value.__index));
updateData(newData);
setSelectedRows(new Set());
}
};
const updateRow = useCallback((rows, changedData) => {
const changes = changedData?.indexes.reduce((acc, index) => {
// when data is filtered val !== actual index in data
const realIndex = data.findIndex((value) => value.__index === rows[index].__index);
acc[realIndex] = rows[index];
return acc;
}, {});
const newData = Object.assign([], data, changes);
updateData(newData);
}, [data, updateData]);
const columns = useMemo(() => generateColumns(fields), [fields]);
const tableData = useMemo(() => {
if (filterByErrors) {
return data.filter((value) => {
if (value?.__errors) {
return Object.values(value.__errors)?.filter((err) => err.level === "error").length;
}
return false;
});
}
return data;
}, [data, filterByErrors]);
const rowKeyGetter = useCallback((row) => row.__index, []);
const submitData = async () => {
const calculatedData = data.reduce((acc, value) => {
const { __index, __errors, ...values } = value;
if (__errors) {
for (const key in __errors) {
if (__errors[key].level === "error") {
acc.invalidData.push(values);
return acc;
}
}
}
acc.validData.push(values);
return acc;
}, { validData: [], invalidData: [], all: data });
onSubmit(calculatedData, file);
setShowSubmitAlert(false);
setSuccessShowSubmitAlert(true); //SPO-4200
setTimeout(() => {
onClose();
}, 10000);
};
//SPO-4200
// const onClose = async () => {
// setSuccessShowSubmitAlert(true)
// console.log("hiting")
// }
//SPO-4200
//SPO-3976 download csv
const downloadData = async () => {
const calculatedData = data.reduce((acc, value) => {
const { __index, __errors, ...values } = value;
if (__errors) {
for (const key in __errors) {
if (__errors[key].level === "error") {
acc.invalidData.push(values);
return acc;
}
}
}
acc.validData.push(values);
// console.log(acc.invalidData.length)
return acc;
}, { validData: [], invalidData: [], all: data });
onDownload(calculatedData, file);
// setNoofErrorAlert(true)
// onClose()
};
//SPO-3976 download csv
const onContinue = () => {
const invalidData = data.find((value) => {
if (value?.__errors) {
return !!Object.values(value.__errors)?.filter((err) => err.level === "error").length;
}
return false;
});
const validData = data.filter((value) => !value?.__errors).length;
if (!invalidData) {
submitData();
}
else if (!validData) {
setNoDataPresentAlert(true); //SPO-4200
}
else {
setShowSubmitAlert(true);
}
};
const [noOfErrors, setNoOfErrors] = useState(0);
const [noOfAllRows, setAllRows] = useState(0);
const updateNoOfErrors = () => {
const calculatedData = data.reduce((acc, value) => {
const { __index, __errors, ...values } = value;
if (__errors) {
for (const key in __errors) {
if (__errors[key].level === "error") {
acc.invalidData.push(values);
return acc;
}
}
}
acc.validData.push(values);
// console.log(acc.invalidData.length)
return acc;
}, { validData: [], invalidData: [], all: data });
setNoOfErrors(calculatedData.invalidData.length);
setAllRows(calculatedData.all.length);
};
useEffect(() => {
updateNoOfErrors();
});
return (jsxs(Fragment, { children: [jsx(SubmitDataAlert, { isOpen: showSubmitAlert, onClose: () => setShowSubmitAlert(false), onConfirm: submitData }), jsx(SubmitSuccessAlert, { isOpen: showSuccessSubmitAlert, onClose: () => setSuccessShowSubmitAlert(false) }), jsx(NoDataPresentAlert, { isOpen: showNoDataPresentAlert, onClose: () => setNoDataPresentAlert(false) }), jsxs(ModalBody, { pb: 0, children: [jsxs(Box, { display: "flex", justifyContent: "space-between", alignItems: "center", mb: "2rem", flexWrap: "wrap", gap: "8px", children: [jsx(Heading, { sx: styles.heading, children: translations.validationStep.title }), jsxs(Box, { display: "flex", gap: "16px", alignItems: "center", flexWrap: "wrap", children: [noOfErrors > 0 && (jsxs(Box, { children: [jsx(Box, { as: "span", color: "red", children: `${noOfErrors}`.trim() }), "/", `${noOfAllRows}`, " ", `${translations.validationStep.noOfErrorRows}`, " ", jsx(Button, { variant: "outline", size: "sm", onClick: downloadData, children: translations.validationStep.downloadButtonTitle })] })), jsx(Button, { variant: "outline", size: "sm", onClick: deleteSelectedRows, children: translations.validationStep.discardButtonTitle }), jsx(Switch, { display: "flex", alignItems: "center", isChecked: filterByErrors, onChange: () => setFilterByErrors(!filterByErrors), children: translations.validationStep.filterSwitchTitle })] })] }), jsx(Table, { rowKeyGetter: rowKeyGetter, rows: tableData, onRowsChange: updateRow, columns: columns, selectedRows: selectedRows, onSelectedRowsChange: setSelectedRows, components: {
noRowsFallback: (jsx(Box, { display: "flex", justifyContent: "center", gridColumn: "1/-1", mt: "32px", children: filterByErrors
? translations.validationStep.noRowsMessageWhenFiltered
: translations.validationStep.noRowsMessage })),
} })] }), jsx(ContinueButton, { onContinue: onContinue, title: translations.validationStep.nextButtonTitle })] }));
};
export { ValidationStep };