CourseInsights / frontend / src / App.tsx
App.tsx
Raw
import { useState, useEffect } from "react";
import {Button, Card, Col, Container, Row} from "react-bootstrap";
import "bootstrap/dist/css/bootstrap.min.css";
import AddDatasetForm from "./components/AddDatasetForm";
import Datasets from "./components/Datasets.tsx";
import InsightsChoices from './components/InsightsChoices';

//const port = 4321;
export const SERVER_URL = `https://course-finder-81589cd639c6.herokuapp.com`; //`http://localhost:${port}`; //https://course-finder-81589cd639c6.herokuapp.com // http://a60d3cd90eaea494986e1650a8c0373a-1620953403.us-east-1.elb.amazonaws.com

const App = () => {
	const [theme, setTheme] = useState<string>(localStorage.getItem("theme") || "light");
	const [selectedId, setSelectedId] = useState<string>("");

	const [removed, setRemove] = useState<string|null>(null);


	const [rows, setRows] = useState<{
		id:string;
		Selected:boolean;
		showOptions:boolean;
		kind: string;
		numRows:number;
	}[]>([]);

	const [AddDatasetFormState, setAddDatasetFormState] = useState<{
		inputText:string;
		file: File | null;
		selectedOption: string;
	}>({
		inputText: "",
		file: null,
		selectedOption: "Sections",
	});

	const onSubmitAddDataset = (e: any) => {
		e.preventDefault();

		const requestOptions = {
			method: "PUT",
			body: AddDatasetFormState.file,
			headers: {'Content-Type': 'application/x-zip-compressed'},
		}

		const ENDPOINT_URL = `/dataset/${AddDatasetFormState.inputText}/sections`;

		fetch(`${SERVER_URL}${ENDPOINT_URL}`, requestOptions)
			.then(async (res) => {
				if (!res.ok) {
					// If not a 200 response, reject with error message
					const ans = await res.json();
					throw new Error(`Failed to add: ${ans.error}`);
				}
				return res.json();
			})
			.then((data) => {
				console.log("Received data:", data);
				alert("Add dataset executed successfully!");
				onSubmitListDataset(e);
			})
			.catch((error) => {
				console.error("Error:", error);
				alert("Failed to add dataset. Please try again.");
			});
	}

	const onSubmitListDataset = (e?: any) => {
		if (e) e.preventDefault();

		const requestOptions = {
			method: "GET",
		}

		const ENDPOINT_URL = `/datasets`;

		fetch(`${SERVER_URL}${ENDPOINT_URL}`, requestOptions)
			.then(async (res) => {
				if (!res.ok) {
					const ans = await res.json();
					throw new Error(`Failed to list: ${ans.error}`);
				}
				return res.json();
			})
			.then((data) => {
				console.log("Received data:", data);
				//alert("List dataset executed successfully!");
				const rows:{
					id:string;
					Selected:boolean;
					showOptions:boolean;
					kind: string;
					numRows:number;
				}[] = [];
				data.result.forEach((dataset: {id:string , kind: string, numRows:number}) => {
					const newrow:{
						id:string;
						Selected:boolean;
						showOptions:boolean;
						kind: string;
						numRows:number;
					} = {id: dataset.id,Selected: false,showOptions: false , kind:dataset.kind, numRows: dataset.numRows
					};
					rows.push(newrow);
				});
				setRows(rows);
			})
			.catch((error) => {
				console.error("Error:", error);
				alert("Failed to list dataset. Please try again.");
			});
	}

	const onSubmitRemoveDataset = (e: any) => {
		e.preventDefault();
		setSelectedId("");

		const requestOptions = {
			method: "DELETE",
		}

		const ENDPOINT_URL = `/dataset/${removed}`;

		fetch(`${SERVER_URL}${ENDPOINT_URL}`, requestOptions)
			.then(async (res) => {
				if (!res.ok) {
					const ans = await res.json();
					throw new Error(`Failed to remove: ${ans.error}`);
				}
				return res.json();
			})
			.then((data) => {
				console.log("Received data:", data);
				//alert("Remove dataset executed successfully!");
				setSelectedId("");
				onSubmitListDataset(e);
			})
			.catch((error) => {
				console.error("Error:", error);
				alert("Failed to remove dataset. Please try again.");
			});
	}



	useEffect(() => {
		document.body.setAttribute("data-bs-theme", theme);
		localStorage.setItem("theme", theme);
	}, [theme]);


	const toggleTheme = ():void => {
		setTheme(theme === "light" ? "dark" : "light");
	};

	useEffect(() => {
		onSubmitListDataset();
	}, []);

	return (
		<Container fluid className="mt-4 position-relative">
			<Button
				variant="primary"
				className="position-fixed end-0 m-3 me-3 mb-3"
				onClick={toggleTheme}
				style={{ width: "50px", height: "50px", borderRadius: "25%", top: "0px" }}
			>
				<img
				src={`${import.meta.env.BASE_URL}${theme === "dark" ? "sun-fill.svg" : "moon-fill.svg"}`}
				alt="Toggle Theme"
				style={{ width: "100%", height: "100%" }}
				/>
			</Button>
			
			<Row>
				<Col>
					<h1 className="text-center mb-4 fw-bold">Course Insights</h1>
				</Col>
			</Row>

			<Row className="gx-1 d-flex ms-auto " style={{ width: '100%' }}> 
				<Col xs={4} className="d-flex flex-column">
					{/* Fix resposiveness */}
					<Card className="p-3 shadow-sm w-100" style={{ minHeight: "30vh" }}>
						<AddDatasetForm
						Submit={onSubmitAddDataset}
						DatasetForm={AddDatasetFormState}
						setForm={setAddDatasetFormState}
						/>
					</Card>

					{/* Fix resposiveness */}
					<Card className="p-3 shadow-sm w-100 mt-3" style={{ minHeight: "46.7vh", overflowY: "auto" }}>
						<Datasets onRemove={() => onSubmitRemoveDataset({ preventDefault: () => {} })} rows={rows} setRows={setRows} setRemove={setRemove} setSelectedId={setSelectedId}/>
					</Card>
				</Col>

				{/* Fix resposiveness */}
				<Col xs={8} className="d-flex flex-column gap-4 ps-3" style={{ height: "700px", maxWidth: "1400px"}}>
					<InsightsChoices datasetId={selectedId} orderDir={"DOWN"} />
				</Col>
			</Row>
		</Container>
	);
};
export default App;