From 8a698e79a5be573eb44ccbfaf3824c951b03bbf9 Mon Sep 17 00:00:00 2001 From: peckz Date: Fri, 25 Apr 2025 09:50:36 +0200 Subject: [PATCH] feat: allow CSV file upload --- pages/utilities/csv-to-json.tsx | 134 +++++++++++++++++++++++++++++--- 1 file changed, 124 insertions(+), 10 deletions(-) diff --git a/pages/utilities/csv-to-json.tsx b/pages/utilities/csv-to-json.tsx index db91927..b155460 100644 --- a/pages/utilities/csv-to-json.tsx +++ b/pages/utilities/csv-to-json.tsx @@ -1,4 +1,4 @@ -import { useCallback, useState } from "react"; +import { useCallback, useState, useRef } from "react"; import { Textarea } from "@/components/ds/TextareaComponent"; import PageHeader from "@/components/PageHeader"; import { Card } from "@/components/ds/CardComponent"; @@ -12,12 +12,16 @@ import CallToActionGrid from "@/components/CallToActionGrid"; import CsvToJsonSEO from "@/components/seo/CsvToJsonSEO"; import Meta from "@/components/Meta"; import { convertCSVtoJSON } from "@/components/utils/csv-to-json.utils"; +import { cn } from "@/lib/utils"; +import { UploadIcon } from "lucide-react"; export default function CSVtoJSON() { const [input, setInput] = useState(""); const [output, setOutput] = useState(""); const { buttonText, handleCopy } = useCopyToClipboard(); const [lowercase, setLowercase] = useState(false); + const [isDragging, setIsDragging] = useState(false); + const fileInputRef = useRef(null); const handleChange = useCallback( (event: React.ChangeEvent) => { @@ -59,11 +63,82 @@ export default function CSVtoJSON() { }); }, [input]); + const processFile = useCallback( + (file: File) => { + if (!file.type.startsWith("text/") && !file.name.endsWith(".csv")) { + setOutput("Please upload a CSV file"); + return; + } + + const reader = new FileReader(); + reader.onload = (e) => { + const content = e.target?.result as string; + setInput(content); + + try { + const json = convertCSVtoJSON(content, lowercase); + setOutput(json); + } catch (errorMessage: unknown) { + setOutput(errorMessage as string); + } + }; + reader.readAsText(file); + }, + [lowercase] + ); + + const handleDragOver = useCallback((e: React.DragEvent) => { + e.preventDefault(); + setIsDragging(true); + }, []); + + const handleDragLeave = useCallback((e: React.DragEvent) => { + e.preventDefault(); + setIsDragging(false); + }, []); + + const handlePaste = useCallback( + (e: React.ClipboardEvent) => { + const file = e.clipboardData.files?.[0]; + if (file) { + processFile(file); + } + }, + [processFile] + ); + + const handleDrop = useCallback( + (e: React.DragEvent) => { + e.preventDefault(); + setIsDragging(false); + + const file = e.dataTransfer.files?.[0]; + if (file) { + processFile(file); + } + }, + [processFile] + ); + + const handleFileInputChange = useCallback( + (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (file) { + processFile(file); + } + }, + [processFile] + ); + + const triggerFileInput = useCallback(() => { + fileInputRef.current?.click(); + }, []); + return (
@@ -78,14 +153,53 @@ export default function CSVtoJSON() {
- -