Task 3: Backend

This commit is contained in:
RobinB27
2025-11-16 14:45:18 +01:00
parent 3a61b72642
commit f65cf176f9
9 changed files with 6492 additions and 34 deletions

View File

@@ -1,9 +1,9 @@
import "./App.css";
import "./css/App.css";
import '@fortawesome/fontawesome-free/css/all.css';
import { readCSV } from './csv';
import { CSV_Data, fileInfo } from './types';
import React, { useState } from "react";
import React, { useState, useRef } from "react";
import Layout from "./Layout";
import CSVCard from "./components/CSVCard";
import InfoCard from "./components/InfoCard";
@@ -18,6 +18,8 @@ function App() {
rowcount: 0
});
const formRef = useRef(null);
// This is triggered in CSVCard
const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>): Promise<void> => {
const file = e.target.files?.[0];
@@ -33,11 +35,22 @@ function App() {
}
setInfo(newFileInfo);
setData(data);
if (formRef.current) {
// Upload to server
const formData = new FormData(formRef.current);
const res = await fetch("/upload", {
method: "POST",
body: formData
});
const result = await res.json();
console.log(result);
}
}
return (
<Layout>
<CSVCard handleChange={handleFileChange}></CSVCard>
<CSVCard handleChange={handleFileChange} formRef={formRef}></CSVCard>
<InfoCard info={info}></InfoCard>
<DataTable data={data}></DataTable>
</Layout>

View File

@@ -1,5 +1,5 @@
import React from "react";
import "./Layout.css";
import "./css/Layout.css";
const Layout = (props: { children: React.ReactNode }) => {
return (

View File

@@ -1,19 +1,20 @@
import React from "react";
import "../Layout.css";
import "../css/Layout.css";
const CSVCard = (props: {
handleChange: (e: React.ChangeEvent<HTMLInputElement>) => void
handleChange: (e: React.ChangeEvent<HTMLInputElement>) => void,
formRef: React.RefObject<HTMLFormElement>
}) => {
return (
<article>
<header>
<h2>Select CSV data</h2>
</header>
<form>
<form ref={props.formRef} action="/upload" method="post" encType="multipart/form-data" >
<label htmlFor="file-input" className="custom-file-upload">
<i className="fa fa-file-csv"></i> Select CSV file to explore
</label>
<input id="file-input" type="file" aria-describedby="fileHelp" accept="text/csv" onChange={props.handleChange}/>
<input id="file-input" type="file" name="dataFile" aria-describedby="fileHelp" accept="text/csv" onChange={props.handleChange}/>
<small>Please upload a CSV file, where the first row is the header.</small>
</form>
</article>

View File

@@ -35,6 +35,11 @@ const DataTable = (props: {data: CSV_Data}) => {
}
return (
<article className="table-container">
<header>
<h2>Data table</h2>
</header>
<div className="table-scroll-wrapper">
<table id="table-content">
<thead>
<tr>
@@ -59,6 +64,8 @@ const DataTable = (props: {data: CSV_Data}) => {
}
</tbody>
</table>
</div>
</article>
)
}

View File

@@ -1,4 +1,3 @@
import "../Layout.css";
import { fileInfo } from "../types";
const InfoCard = (props: {

View File

@@ -1,10 +1,27 @@
import express from "express";
import ViteExpress from "vite-express";
import multer from "multer";
// creates the expres app do not change
const app = express();
// add your routes here
const storage = multer.diskStorage({
destination: "./src/server/uploads",
filename: (_req, file, cb) => {
// Suggested in Multer's readme
const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1E9);
cb(null, file.fieldname + "-" + uniqueSuffix)
}
});
const upload = multer({ storage: storage });
app.post(
"/upload",
upload.single("dataFile"),
(req, res, next) => {
console.log(req, res, next)
}
);
// example route which returns a message
app.get("/hello", async function (_req, res) {

File diff suppressed because it is too large Load Diff