From 76e609068f7c0fd12902e6fca2f7e880f0f30ce6 Mon Sep 17 00:00:00 2001 From: Chris-1010 Date: Tue, 23 Sep 2025 01:04:53 +0100 Subject: [PATCH] Enhance file upload experience with drag-and-drop support and file removal functionality --- app/src/index.css | 2 +- app/src/pages/Home.tsx | 170 ++++++++++++++++++++++++++++++++--------- 2 files changed, 137 insertions(+), 35 deletions(-) diff --git a/app/src/index.css b/app/src/index.css index 444f889..46e26f4 100644 --- a/app/src/index.css +++ b/app/src/index.css @@ -29,7 +29,7 @@ body { display: flex; place-items: center; min-width: 320px; - min-height: 100vh; + height: 98vh; } h1 { diff --git a/app/src/pages/Home.tsx b/app/src/pages/Home.tsx index 153a610..2aaae11 100644 --- a/app/src/pages/Home.tsx +++ b/app/src/pages/Home.tsx @@ -1,39 +1,141 @@ -import { useState } from 'react' -import { useNavigate } from 'react-router-dom' -import { readFiles } from '../model/parser' -import { addStreams } from '../util/db' +import { useState, useRef } from "react"; +import { useNavigate } from "react-router-dom"; +import { readFiles } from "../model/parser"; +import { addStreams } from "../util/db"; const Home = () => { - const [files, setFiles] = useState([]) - const navigate = useNavigate() + const [files, setFiles] = useState([]); + const [dragOver, setDragOver] = useState(false); + const navigate = useNavigate(); + const fileInputRef = useRef(null); - const handleUpload = async () => { - if (files.length === 0) return; - - const streams = await readFiles(files); // your parser - await addStreams(streams); // save to IndexedDB - navigate('/stats'); // go to StatView - }; + const handleFiles = (fileList: FileList | null) => { + if (fileList) { + const jsonFiles = Array.from(fileList).filter((file) => file.type === "application/json" || file.name.endsWith(".json")); + setFiles(jsonFiles); + } + }; - return ( -
-

Upload Spotify files

- { - if (e.target.files) { - setFiles(Array.from(e.target.files)); - } - }} - /> - -
- ) -} + //#region File handling methods + const handleFileSelect = (e: React.ChangeEvent) => { + handleFiles(e.target.files); + }; -export default Home; \ No newline at end of file + const handleDrop = (e: React.DragEvent) => { + e.preventDefault(); + setDragOver(false); + handleFiles(e.dataTransfer.files); + }; + + const handleDragOver = (e: React.DragEvent) => { + e.preventDefault(); + setDragOver(true); + }; + + const handleDragLeave = (e: React.DragEvent) => { + e.preventDefault(); + setDragOver(false); + }; + //#endregion + + const handleUpload = async () => { + if (files.length === 0) return; + + const streams = await readFiles(files); + await addStreams(streams); + navigate("/stats"); + }; + + const openFileDialog = () => { + fileInputRef.current?.click(); + }; + + const removeFile = (index: number) => { + setFiles(files.filter((_, i) => i !== index)); + }; + + return ( +
+

Upload Spotify files

+ + {/* Hidden actual input */} + + + {/* Custom drop zone */} +
+
📁
+

Drop JSON files here or click to browse

+

Multiple .json files accepted

+
+ + {files.length > 0 && ( +
+

{files.length} files selected:

+ {files.map((file, index) => ( +
+ {file.name} + +
+ ))} + +
+ )} +
+ ); +}; + +export default Home;