Untitled

 avatar
unknown
plain_text
9 months ago
7.9 kB
3
Indexable
import React, { useRef, useState } from 'react';
import { SimpleFileUpload, Label, Button, Group, Section, ListItem, List } from '@d-lift/uxcomponents';
import * as XLSX from 'xlsx';

const ExcelUpload = () => {
    const [status, setStatus] = useState('initial');
    const [uploadedFiles, setUploadedFiles] = useState([]);
    const [errors, setErrors] = useState([]);
    const fileInputRef = useRef(null);
    const [selectedFile, setSelectedFile] = useState(null);

    const handleFileChange = (e) => {
        if (Array.isArray(e) && e.length > 0) {
            const newFile = e[0];
            setSelectedFile(newFile);
            handleUpload(newFile);
        } else {
            console.log('No file selected');
        }
    };

    const handleUpload = async (file) => {
        try {
            if (!file) {
                console.error('No file selected');
                setStatus('fail');
                return;
            }

            console.log('Processing file:', file);
            const reader = new FileReader();
            reader.onload = (event) => {
                const data = new Uint8Array(event.target.result);
                const workbook = XLSX.read(data, { type: 'array' });
                const firstSheetName = workbook.SheetNames[0];
                const worksheet = workbook.Sheets[firstSheetName];
                const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });

                const validationResult = validateData(jsonData);
                if (validationResult.isValid) {
                    convertToJSONAndUpload(jsonData);
                } else {
                    setErrors(validationResult.errors);
                    setStatus('fail');
                }
            };
            reader.readAsArrayBuffer(file);

            setUploadedFiles((prevFiles) => [
                ...prevFiles,
                {
                    id: Math.random() * 100 + 1,
                    name: file.name,
                },
            ]);

            setStatus('success');
        } catch (error) {
            console.error(error);
            setStatus('fail');
        }
    };

    const validateData = (data) => {
        let isValid = true;
        let errors = [];

        const headers = data[0];
        const requiredFields = ["RFI Title", "RFI desc", "requesting as", "needed by", "offering"];
        const questionFields = ["response", "respond as"];
        
        // Check mandatory headers
        requiredFields.forEach((field) => {
            if (!headers.includes(field)) {
                isValid = false;
                errors.push(`Missing mandatory field: ${field}`);
            }
        });

        // Validate each row
        data.slice(1).forEach((row, rowIndex) => {
            // Check mandatory fields
            requiredFields.forEach((field) => {
                const fieldIndex = headers.indexOf(field);
                if (row[fieldIndex] === '' || row[fieldIndex] === undefined) {
                    isValid = false;
                    errors.push(`Error in row ${rowIndex + 2}: ${field} is mandatory`);
                }
                if (field === "needed by") {
                    const date = new Date(row[fieldIndex]);
                    if (date < new Date()) {
                        isValid = false;
                        errors.push(`Error in row ${rowIndex + 2}: ${field} date should not be in the past`);
                    }
                }
            });

            // Check questions fields
            let questionSection = false;
            row.forEach((cell, cellIndex) => {
                if (questionFields.includes(headers[cellIndex])) {
                    questionSection = true;
                    if (cell === '' || cell === undefined) {
                        isValid = false;
                        errors.push(`Error in row ${rowIndex + 2}, cell ${cellIndex + 1}: ${headers[cellIndex]} is mandatory`);
                    }
                }
            });
            
            if (questionSection && (row[headers.indexOf("response")] === '' || row[headers.indexOf("response")] === undefined)) {
                isValid = false;
                errors.push(`Error in row ${rowIndex + 2}: response is mandatory for questions`);
            }

            if (questionSection && (row[headers.indexOf("respond as")] === '' || row[headers.indexOf("respond as")] === undefined)) {
                isValid = false;
                errors.push(`Error in row ${rowIndex + 2}: respond as is mandatory for questions`);
            }
        });

        return { isValid, errors };
    };

    const convertToJSONAndUpload = (data) => {
        const jsonData = data.slice(1).map((row, index) => {
            const rowData = {};
            data[0].forEach((header, i) => {
                rowData[header] = row[i];
            });
            return rowData;
        });

        callAPIToInsertData(jsonData);
    };

    const callAPIToInsertData = async (data) => {
        try {
            const response = await fetch('YOUR_API_ENDPOINT', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(data),
            });

            if (response.ok) {
                console.log('Data successfully inserted');
            } else {
                console.error('Failed to insert data');
            }
        } catch (error) {
            console.error('Error during API call:', error);
        }
    };

    return (
        <>
            <div className="ux-rfi-attachment-container ux-rfi-green-border">
                <Label className="mb-0" model="AddAttachments.fileList" labelKey="attachments"></Label>
                <Section className="pt-4">
                    <List>
                        {uploadedFiles.length > 0 ? (
                            uploadedFiles.map((file) => (
                                <ListItem key={file.id} iconKey={null}>
                                    {file.name}
                                </ListItem>
                            ))
                        ) : (
                            <ListItem iconKey={null} labelKey="empty_err"></ListItem>
                        )}
                    </List>
                    {errors.length > 0 && (
                        <Section className="pt-4">
                            <Label className="mb-0" model="AddAttachments.errorList" labelKey="errors"></Label>
                            <List>
                                {errors.map((error, index) => (
                                    <ListItem key={index} iconKey={null}>
                                        {error}
                                    </ListItem>
                                ))}
                            </List>
                        </Section>
                    )}
                    <SimpleFileUpload
                        model="AddAttachments.uploadedFiles"
                        allowDragAndDrop={false}
                        inputDisplayType="custom"
                        ref={fileInputRef}
                        style={{ display: 'none' }}
                        onDropAccepted={handleFileChange}
                        accept=".xls,.xlsx">
                        <Button
                            size="small"
                            click={() => fileInputRef.current && fileInputRef.current.click()}
                            className="ux-rfi-green-button">
                            <Group width="1,10">
                                <i className="fa fa-plus" aria-hidden="true"></i>Add Attachment
                            </Group>
                        </Button>
                    </SimpleFileUpload>
                </Section>
            </div>
        </>
    );
};

export default ExcelUpload;
Editor is loading...
Leave a Comment