diff --git a/apps/app/pages/testings-csv.tsx b/apps/app/pages/testings-csv.tsx new file mode 100644 index 000000000..4323910e3 --- /dev/null +++ b/apps/app/pages/testings-csv.tsx @@ -0,0 +1,402 @@ +import { useEffect, useState, useRef } from "react"; + +import { useDropzone } from "react-dropzone"; + +// icons +import { ChevronUpIcon, ChevronDownIcon } from "@heroicons/react/20/solid"; +import { FolderPlusIcon, CheckIcon, XMarkIcon } from "@heroicons/react/24/outline"; + +import { Input, Spinner } from "components/ui"; + +const DUMMY_CSV = `id,name,age,active +1,"John - Test",20,TRUE +2,,30,TRUE +3,Jim,40,FALSE +4,Joe,50,FALSE +5,Jane,50,TRUE +6,Jill,70,TRUE +7,Joy,80,TRUE +8,Joyce,90,FALSE +9,Joyce,100,TRUE +10,Joyce,110,TRUE +11,Joyce,120,TRUE +12,,130,FALSE +13,Joyce,140,TRUE +14,Joyce,150,TRUE +15,,160,TRUE +16,Joyce,170,FALSE +17,Joyce,180,TRUE +18,,190,TRUE +19,,200,FALSE +20,Joyce,210,FALSE +21,Joyce,220,TRUE +22,Joe,230,TRUE +23,,240,FALSE`; + +const csvOrExcelToJson = (csv: string) => { + const lines = csv.split(/\r\n|\n/); + + const result = []; + + const headers = lines[0].split(/,|;|\t|\|/); + + for (let i = 1; i < lines.length; i++) { + const obj: any = {}; + const currentLine = lines[i].split(/,|;|\t|\|/); + + for (let j = 0; j < headers.length; j++) { + if (currentLine[j]?.toUpperCase() === "TRUE" || currentLine[j]?.toUpperCase() === "FALSE") { + obj[headers[j]] = currentLine[j] === "TRUE"; + } else if ( + !isNaN(Number(currentLine[j])) && + currentLine[j] !== "" && + currentLine[j] !== null && + currentLine[j] !== undefined + ) { + obj[headers[j]] = Number(currentLine[j]); + } else { + obj[headers[j]] = currentLine[j] || null; + } + } + + result.push(obj); + } + + return result; +}; + +const Testings = () => { + const invalidItems = useRef([]); + + const [data, setData] = useState(null); + const [editIndex, setEditIndex] = useState(null); + const [searchInput, setSearchInput] = useState(""); + + const [csvInput, setCsvInput] = useState(null); + + const { getRootProps, getInputProps, isDragActive } = useDropzone({ + onDrop: (acceptedFiles) => { + setCsvInput(acceptedFiles[0]); + }, + }); + + useEffect(() => { + if (csvInput) { + const reader = new FileReader(); + reader.onload = () => { + const csvData = csvOrExcelToJson(reader.result as string); + + setData( + csvData.map((item) => ({ + ...item, + isInValid: Object.values(item).some((value) => value === null), + })) + ); + }; + reader.readAsText(csvInput); + } + }, [csvInput]); + + if (csvInput === null) + return ( +
+ +
+ ); + + // useEffect(() => { + // const data = csvOrExcelToJson(DUMMY_CSV).map((item) => ({ + // ...item, + // isInValid: Object.values(item).some((value) => value === null), + // })); + + // setData(data); + // }, []); + + const filterData = + searchInput && searchInput.length > 0 + ? data?.filter((item: any) => item?.name?.toLowerCase().includes(searchInput.toLowerCase())) + : data; + + if (!data) + return ( +
+ +
+ ); + + const jumpToInvalid = (direction: "up" | "down" = "down") => { + const tableContainer = document.getElementById("table-container") as HTMLElement; + + const currentScrollPosition = tableContainer.scrollTop; + + const currentId = invalidItems.current.find( + (item) => item.offsetTop > currentScrollPosition + )?.id; + + const invalidItem = invalidItems.current.find((item) => item.id === currentId); + + if (!invalidItem) return; + + const index = invalidItems.current.indexOf(invalidItem); + + const nextInvalidItem = + direction === "down" ? invalidItems.current[index + 1] : invalidItems.current[index - 1]; + + if (!nextInvalidItem) return; + + const nextInvalidItemId = nextInvalidItem.id; + + const nextInvalidItemElement = document.getElementById(nextInvalidItemId) as HTMLElement; + + if (!nextInvalidItemElement) return; + + nextInvalidItemElement.scrollIntoView({ + behavior: "smooth", + block: "center", + inline: "center", + }); + + nextInvalidItemElement.classList.add("animate-pulse"); + nextInvalidItemElement.classList.add("bg-gray-200"); + setTimeout(() => { + nextInvalidItemElement.classList.remove("animate-pulse"); + nextInvalidItemElement.classList.remove("bg-gray-200"); + }, 1000); + }; + + if (!filterData) return ; + + return ( +
+
+
+
+ setSearchInput(e.target.value)} + /> +
+ +
+
+ + + + {Object.keys(data[0]).map( + (key, index) => + key !== "isInValid" && ( + + ) + )} + + + + + {filterData.map((row: any, index: number) => ( + { + if (row.isInValid && el) invalidItems.current.push(el); + }} + key={index} + > + {Object.keys(row).map( + (key, jIndex) => + key !== "isInValid" && ( + + ) + )} + + + ))} + +
+ {key} + + Edit +
+ {editIndex === index && key !== "id" ? ( + typeof row[key] === "boolean" ? ( +
+ { + const value = e.target.checked; + setData((prev: any[]) => + prev.map((item, i) => + i === index ? { ...item, [key]: value } : item + ) + ); + }} + /> +
+ ) : ( + { + const value = e.target.value; + const isInValid = key === "name" ? value === "" : false; + setData((prev: any[]) => + prev.map((item, i) => + i === index ? { ...item, [key]: value, isInValid } : item + ) + ); + + if (!isInValid) { + const invalidItem = invalidItems.current.find( + (item) => parseInt(item.id) === parseInt(row.id) + ); + if (invalidItem) { + invalidItems.current.splice( + invalidItems.current.indexOf(invalidItem), + 1 + ); + } + } + }} + /> + ) + ) : typeof row[key] === "boolean" ? ( + row[key] ? ( + + ) : ( + + ) + ) : ( + row[key] ?? "-" + )} +
+ +
+
+
+ + +
+
+
+
+

+ Total Invalid:{" "} + {data.filter((item: any) => item.isInValid).length} +

+

+ Total Count: {data.length} +

+
+
+
+
+
+ ); +}; + +export default Testings; + +// const handleDownload = (fileType: "csv" | "xlsx") => { +// const csv = convertToCSVOrExcel(data, fileType); + +// const blob = new Blob([csv], { +// type: +// fileType === "csv" +// ? "text/csv;charset=utf-8;" +// : "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;", +// }); + +// const link = document.createElement("a"); +// const url = URL.createObjectURL(blob); +// link.setAttribute("href", url); +// link.setAttribute("download", `data.${fileType}`); +// link.style.visibility = "hidden"; +// document.body.appendChild(link); +// link.click(); +// document.body.removeChild(link); + +// URL.revokeObjectURL(url); +// }; + +// const convertToCSVOrExcel = (data: any, fileType: "csv" | "xlsx" = "csv") => { +// const headers = Object.keys(data[0]); + +// const divider = fileType === "csv" ? "," : "\t"; + +// let csv = headers.join(divider); + +// csv += "\r\n"; + +// for (const item of data) { +// csv += Object.values(item).join(divider); +// csv += "\r\n"; +// } + +// return csv; +// };