From b6de100a1734347950b0d6886c761c975143d493 Mon Sep 17 00:00:00 2001 From: Dylan De Faoite Date: Tue, 3 Mar 2026 17:18:09 +0000 Subject: [PATCH] feat: overhaul upload page styling --- frontend/src/pages/Upload.tsx | 156 +++++++++++++++++++++++++--------- 1 file changed, 116 insertions(+), 40 deletions(-) diff --git a/frontend/src/pages/Upload.tsx b/frontend/src/pages/Upload.tsx index 2218231..74a9b18 100644 --- a/frontend/src/pages/Upload.tsx +++ b/frontend/src/pages/Upload.tsx @@ -1,56 +1,132 @@ -import axios from 'axios' -import './../App.css' -import { useState } from 'react' -import { useNavigate } from 'react-router-dom' +import axios from "axios"; +import { useState } from "react"; +import { useNavigate } from "react-router-dom"; import StatsStyling from "../styles/stats_styling"; const styles = StatsStyling; +const API_BASE_URL = "http://localhost:5000"; const UploadPage = () => { - let postFile: File | undefined; - let topicBucketFile: File | undefined; - const [returnMessage, setReturnMessage] = useState('') - const navigate = useNavigate() + const [postFile, setPostFile] = useState(null); + const [topicBucketFile, setTopicBucketFile] = useState(null); + const [returnMessage, setReturnMessage] = useState(""); + const [isSubmitting, setIsSubmitting] = useState(false); + const [hasError, setHasError] = useState(false); + const navigate = useNavigate(); const uploadFiles = async () => { if (!postFile || !topicBucketFile) { - alert('Please upload all files before uploading.') - return + setHasError(true); + setReturnMessage("Please upload both files before continuing."); + return; } - const formData = new FormData() - formData.append('posts', postFile) - formData.append('topics', topicBucketFile) + const formData = new FormData(); + formData.append("posts", postFile); + formData.append("topics", topicBucketFile); try { - const response = await axios.post('http://localhost:5000/upload', formData, { - headers: { - 'Content-Type': 'multipart/form-data', - }, - }) - console.log('Files uploaded successfully:', response.data) - setReturnMessage(`Upload successful! Posts: ${response.data.posts_count}, Comments: ${response.data.comments_count}`) - navigate('/stats') - } catch (error) { - console.error('Error uploading files:', error) - setReturnMessage('Error uploading files. Error details: ' + error) - } - } - return ( -
-
-

Posts File

- postFile = e.target.files?.[0]}> -
-
-

Topic Buckets File

- topicBucketFile = e.target.files?.[0]}> -
- + setIsSubmitting(true); + setHasError(false); + setReturnMessage(""); -

{returnMessage}

+ const response = await axios.post(`${API_BASE_URL}/upload`, formData, { + headers: { + "Content-Type": "multipart/form-data", + }, + }); + + setReturnMessage( + `Upload queued successfully (dataset #${response.data.dataset_id}). Redirecting to insights...` + ); + + setTimeout(() => { + navigate("/stats"); + }, 400); + } catch (error: unknown) { + setHasError(true); + if (axios.isAxiosError(error)) { + const message = String(error.response?.data?.error || error.message || "Upload failed."); + setReturnMessage(`Upload failed: ${message}`); + } else { + setReturnMessage("Upload failed due to an unexpected error."); + } + } finally { + setIsSubmitting(false); + } + }; + + return ( +
+
+
+
+

Upload Dataset

+

+ Add your posts and topic map files to generate fresh analytics. +

+
+ +
+ +
+
+

Posts File (.jsonl)

+

Upload the raw post records export.

+ setPostFile(event.target.files?.[0] ?? null)} + /> +

+ {postFile ? `Selected: ${postFile.name}` : "No file selected"} +

+
+ +
+

Topics File (.json)

+

Upload your topic bucket mapping file.

+ setTopicBucketFile(event.target.files?.[0] ?? null)} + /> +

+ {topicBucketFile ? `Selected: ${topicBucketFile.name}` : "No file selected"} +

+
+
+ +
+ {returnMessage || "After upload, your dataset is queued for processing and you'll land on stats."} +
+
- ) -} + ); +}; export default UploadPage;