feat: overhaul upload page styling

This commit is contained in:
2026-03-03 17:18:09 +00:00
parent 5310568631
commit b6de100a17

View File

@@ -1,56 +1,132 @@
import axios from 'axios' import axios from "axios";
import './../App.css' import { useState } from "react";
import { useState } from 'react' import { useNavigate } from "react-router-dom";
import { useNavigate } from 'react-router-dom'
import StatsStyling from "../styles/stats_styling"; import StatsStyling from "../styles/stats_styling";
const styles = StatsStyling; const styles = StatsStyling;
const API_BASE_URL = "http://localhost:5000";
const UploadPage = () => { const UploadPage = () => {
let postFile: File | undefined; const [postFile, setPostFile] = useState<File | null>(null);
let topicBucketFile: File | undefined; const [topicBucketFile, setTopicBucketFile] = useState<File | null>(null);
const [returnMessage, setReturnMessage] = useState('') const [returnMessage, setReturnMessage] = useState("");
const navigate = useNavigate() const [isSubmitting, setIsSubmitting] = useState(false);
const [hasError, setHasError] = useState(false);
const navigate = useNavigate();
const uploadFiles = async () => { const uploadFiles = async () => {
if (!postFile || !topicBucketFile) { if (!postFile || !topicBucketFile) {
alert('Please upload all files before uploading.') setHasError(true);
return setReturnMessage("Please upload both files before continuing.");
return;
} }
const formData = new FormData() const formData = new FormData();
formData.append('posts', postFile) formData.append("posts", postFile);
formData.append('topics', topicBucketFile) formData.append("topics", topicBucketFile);
try { try {
const response = await axios.post('http://localhost:5000/upload', formData, { setIsSubmitting(true);
headers: { setHasError(false);
'Content-Type': 'multipart/form-data', setReturnMessage("");
},
})
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 (
<div style={{...styles.container, ...styles.grid, margin: "0"}}>
<div style={{ ...styles.card }}>
<h2 style={{color: "black" }}>Posts File</h2>
<input style={{color: "black" }} type="file" onChange={(e) => postFile = e.target.files?.[0]}></input>
</div>
<div style={{ ...styles.card }}>
<h2 style={{color: "black" }}>Topic Buckets File</h2>
<input style={{color: "black" }} type="file" onChange={(e) => topicBucketFile = e.target.files?.[0]}></input>
</div>
<button onClick={uploadFiles}>Upload</button>
<p>{returnMessage}</p> 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 (
<div style={styles.page}>
<div style={{ ...styles.container, maxWidth: 1100 }}>
<div style={{ ...styles.card, ...styles.headerBar }}>
<div>
<h1 style={{ margin: 0, color: "#111827", fontSize: 28 }}>Upload Dataset</h1>
<p style={{ margin: "8px 0 0", color: "#6b7280", fontSize: 14 }}>
Add your posts and topic map files to generate fresh analytics.
</p>
</div> </div>
) <button
} type="button"
style={{ ...styles.buttonPrimary, opacity: isSubmitting ? 0.75 : 1 }}
onClick={uploadFiles}
disabled={isSubmitting}
>
{isSubmitting ? "Uploading..." : "Upload and Analyze"}
</button>
</div>
<div
style={{
...styles.grid,
marginTop: 14,
gridTemplateColumns: "repeat(auto-fit, minmax(280px, 1fr))",
}}
>
<div style={{ ...styles.card, gridColumn: "auto" }}>
<h2 style={{ ...styles.sectionTitle, color: "#111827" }}>Posts File (.jsonl)</h2>
<p style={styles.sectionSubtitle}>Upload the raw post records export.</p>
<input
style={{ ...styles.input, width: "80%", maxWidth: "100%" }}
type="file"
accept=".jsonl"
onChange={(event) => setPostFile(event.target.files?.[0] ?? null)}
/>
<p style={{ margin: "10px 0 0", fontSize: 13, color: "#374151" }}>
{postFile ? `Selected: ${postFile.name}` : "No file selected"}
</p>
</div>
<div style={{ ...styles.card, gridColumn: "auto" }}>
<h2 style={{ ...styles.sectionTitle, color: "#111827" }}>Topics File (.json)</h2>
<p style={styles.sectionSubtitle}>Upload your topic bucket mapping file.</p>
<input
style={{ ...styles.input, width: "80%", maxWidth: "100%" }}
type="file"
accept=".json"
onChange={(event) => setTopicBucketFile(event.target.files?.[0] ?? null)}
/>
<p style={{ margin: "10px 0 0", fontSize: 13, color: "#374151" }}>
{topicBucketFile ? `Selected: ${topicBucketFile.name}` : "No file selected"}
</p>
</div>
</div>
<div
style={{
...styles.card,
marginTop: 14,
borderColor: hasError ? "rgba(185, 28, 28, 0.28)" : "rgba(0,0,0,0.06)",
background: hasError ? "#fff5f5" : "#ffffff",
color: hasError ? "#991b1b" : "#374151",
fontSize: 14,
}}
>
{returnMessage || "After upload, your dataset is queued for processing and you'll land on stats."}
</div>
</div>
</div>
);
};
export default UploadPage; export default UploadPage;