Skip to content

Commit

Permalink
Merge pull request #17 from hotungkhanh/kan-54/frontend-comment
Browse files Browse the repository at this point in the history
kan-54/frontend-comment
  • Loading branch information
NguyenDonLam authored Sep 22, 2024
2 parents 6cc4dd0 + de74e95 commit 38db9a1
Show file tree
Hide file tree
Showing 23 changed files with 194 additions and 15 deletions.
5 changes: 5 additions & 0 deletions frontend/src/components/BackButton.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import { Button } from '@mui/material';

/**
* React component for a back button with outlined style.
* Displays a button with an arrow icon and text 'Back'.
* @returns JSX element representing the back button
*/
export default function BackButton() {
return (
<Button
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/components/DisplayFile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ interface DisplayFileProps {
fileChosen: File | null;
}

/**
* Renders the file chosen for display.
*
* @param {DisplayFileProps} fileChosen - The file object to be displayed.
* @returns The component displaying the chosen file or an empty
* Box if no file is chosen.
*/
export default function DisplayFile({fileChosen}: DisplayFileProps) {
if (fileChosen === null) {
return <Box/>;
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { Box } from "@mui/material";

/**
* React component for rendering a fixed position footer.
*
* @param children - The content to be displayed inside the footer.
* @returns JSX element representing the styled footer component.
*/
export default function Footer({ children } : { children?: React.ReactNode }) {
const footerStyle = {
backgroundColor: "#f05a22",
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { Box } from "@mui/material";
import VIT_Logo from '../assets/logo.png';

/**
* React component for rendering the header section.
* @returns JSX element representing the header with a logo.
*/
export default function Header() {
const headerStyle = {
backgroundColor: "#F5F5f5",
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/components/NextButton.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
import { Button } from '@mui/material';

/**
* Component for rendering a button with an arrow icon indicating next action.
* @returns JSX element representing the NextButton component
*/
export default function NextButton() {
return (
<Button
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/components/ProceedButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ interface ProceedButtonProps {
fileChosen: File | null;
}

/**
* Functional component for rendering a Proceed Button based on whether a file
* is chosen or not.
*
* @param {ProceedButtonProps} fileChosen - Props object containing the fileChosen
* boolean value
* @returns A Button component that allows the user to proceed
* to a specific route when clicked
*/
export default function ProceedButton({ fileChosen }: ProceedButtonProps) {
const navigate = useNavigate();
if (fileChosen === null) {
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ interface SidebarProps {
}
const drawerWidth = 240;

/**
* Renders a sidebar component with navigation links to Campus, Building, Room,
* Course, and Unit.
*
* @param {SidebarProps} props - The properties passed to Sidebar component
* @param {number} props.marginTop - The top margin of the sidebar.
* @param {number} props.width - The width of the sidebar.
* @returns Sidebar component with navigation links.
*/
export default function Sidebar({ marginTop, width }: SidebarProps) {
return (
<Drawer
Expand Down
10 changes: 10 additions & 0 deletions frontend/src/components/Spreadsheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ interface SpreadsheetProps {
columns?: jspreadsheet.Column[]
}

/**
* Component for rendering a spreadsheet with customisable headers and storage
* functionality.
*
* @param {SpreadsheetProps} props - The properties passed to Spreadsheet component
* @param {SpreadsheetProps.headers} props.headers - Array of header names for the spreadsheet columns.
* @param {SpreadsheetProps.storageKey} props.storageKey - Key for storing and retrieving spreadsheet data
* in storage (i.e. indexedDB).
* @return Div containing a spreadsheet and button to add row.
*/
export default function Spreadsheet({ headers, storageKey, ...other }: SpreadsheetProps) {
const jRef = useRef<null | JspreadsheetInstanceElement>(null);

Expand Down
7 changes: 7 additions & 0 deletions frontend/src/components/UploadButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ const VisuallyHiddenInput = styled("input")({
width: 1,
});

/**
* Functional component for an upload button that allows users to select and
* upload a file.
*
* @param {InputFileUploadProps.setFileChosen} setFileChosen - Callback function to set the chosen file.
* @returns Upload button component with file selection and upload functionality.
*/
export default function UploadButton ({ setFileChosen }: InputFileUploadProps) {

// Handler for file selection
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/components/UploadPopUp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ import { Button } from "@mui/material";
import ProceedButton from "./ProceedButton.tsx";
import DisplayFile from "./DisplayFile.tsx";

/**
* UploadPopUp component for displaying a modal with file upload functionality.
* Manages the state of the modal being open or closed and the file chosen
* for upload.
*
* @returns A button to open a modal with file display, upload button, and proceed button.
*/
export default function UploadPopUp() {
const [open, setOpen] = useState(false);
const [fileChosen, setFileChosen] = useState<File | null>(null);
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/pages/Download.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { Link } from "react-router-dom";

/**
* Renders the Download page component.
* Displays a heading for downloading generated timetables and a link to go
* back to the timetable modification page.
* @returns JSX element representing the Download page
* TODO: TO BE IMPLEMENTED
*/
export default function Download() {
return (
<>
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/pages/Enrolment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ import UploadPopUp from "../components/UploadPopUp.tsx";
import Header from "../components/Header.tsx";
import Footer from "../components/Footer.tsx";
import Photo from "../assets/frontpage.jpg";

/**
* Renders the Starter Page component with specific time and tabler styles.
* Includes a description box with time and tabler elements, lorem ipsum text,
* and an UploadPopUp component.
* Utilizes the Header and Footer components for layout consistency.
* TODO: replace lorem ipsum with actual texts, replace better quality img
*/
export default function StarterPage() {
const timeStyle = {
color: "#f05a22",
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/pages/SemesterInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import '../styles/seminfo.css';
import NextButton from "../components/NextButton.tsx";
import BackButton from "../components/BackButton.tsx";

/**
* Renders the SemesterInfo component with a header, sidebar, spreadsheet,
* and navigation buttons.
*
* @returns JSX element representing the SemesterInfo component
*/
export default function SemesterInfo() {
return (
<div>
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/pages/SendData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ import { getTimetableProblem } from "../scripts/handleInput";
import { useState } from "react";
import { fetchTimetableSolution } from "../scripts/api";

/**
* Page for containing UI elements that allow user to send input data to backend.
* Temporarily has a display for backend's response to confirm successful sending
* (will remove and replace with display page in next sprint).
*
* @returns button for sending timetable problem and temporary display for timetable solution.
* TODO: change button and UI elements to fit with VIT themes.
*/
export default function SendData() {

const [isGenerated, setIsGenerated] = useState("");
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/pages/TimetableMod.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { Link } from "react-router-dom";

/**
* Renders the TimetableMod component to display and modify the generated
* timetable.
* Allows users to navigate back to the campus information page and proceed to
* the download page.
* @returns JSX element containing the page content with navigation links
*/
export default function TimetableMod() {
return (
<>
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/pages/spreadsheets/Building.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import Spreadsheet from '../../components/Spreadsheet.tsx'
import { DB_BUILDINGS } from '../../scripts/persistence.ts';

/**
*
* @returns Spreadsheet input page for buildings information.
*/
export default function Building() {

return (
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/pages/spreadsheets/Room.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import Spreadsheet from '../../components/Spreadsheet.tsx'
import { DB_ROOMS } from '../../scripts/persistence.ts';

/**
*
* @returns Spreadsheet input page for rooms information.
*/
export default function Room() {

return (
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/pages/spreadsheets/Unit.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import Spreadsheet from '../../components/Spreadsheet.tsx'
import { DB_UNITS } from '../../scripts/persistence.ts';

/**
*
* @returns Spreadsheet input page for units information.
*/
export default function Unit() {

return (
Expand Down
7 changes: 6 additions & 1 deletion frontend/src/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ import Download from './pages/Download.tsx'
import Enrolment from './pages/Enrolment.tsx'
import SendData from './pages/SendData.tsx'


/**
* Defines the routes configuration for the application.
* Each route specifies a path and the corresponding component to render.
*
* An array of route objects, each containing path and element information.
*/
const routes = [
{
path: "/",
Expand Down
12 changes: 11 additions & 1 deletion frontend/src/scripts/api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
/* Timetable solver backend endpoint URL */
const API_URL = 'http://localhost:8080/timetabling';

/* =========================================== Defining types =========================================== */

export type TimetableProblem = TimetableBase & {
units: Unit[],
}
Expand Down Expand Up @@ -42,8 +45,15 @@ export type Weekday = "MONDAY" | "TUESDAY" | "WEDNESDAY" | "THURSDAY" | "FRIDAY"

export type Time = string;

/* ====================================================================================================== */


// API function(s)
/**
* Sends the timetabling problem to backend for solving. Return the solution received.
*
* @param problem A TimetableProblem is a list of units with no allocated time and room.
* @returns A TimetableSolution with all units allocated a time and a room.
*/
export async function fetchTimetableSolution(problem: TimetableProblem): Promise<TimetableSolution | null> {
try {
const response = await fetch(API_URL, {
Expand Down
32 changes: 26 additions & 6 deletions frontend/src/scripts/handleInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ import { CellValue } from 'jspreadsheet-ce';
import { TimetableProblem, Unit, Room } from './api';
import { DB_UNITS, storeSpreadsheetData } from './persistence';

/*
* Return true if file is an Excel file
*/
/**
* Function to validate uploaded enrolment data file.
*
* @param file enrolment data Excel file
* @returns true if uploaded file is an Excel file
*/
function isExcelFile(file: File) {
const fileExtension = file.name.split('.').pop();
if (fileExtension === undefined || !['xlsx', 'xls'].includes(fileExtension)) {
Expand All @@ -15,9 +18,12 @@ function isExcelFile(file: File) {
return true;
}

/*
* Return true if enrolment data header file matches expected format
*/
/**
* Function to validate uploaded enrolment data file.
*
* @param inputHeader header row of enrolment data Excel file
* @returns true if header row matches expected format for parsing.
*/
function validateEnrolmentHeader(inputHeader: Row) {
const header = ['StudentID', 'Student Name', 'Personal Email', 'University Email',
'Student Type', 'Offer Type', 'Course Name', 'Campus', 'Original COE Start Date',
Expand All @@ -32,6 +38,12 @@ function validateEnrolmentHeader(inputHeader: Row) {
}
}

/**
* Extract list of units from enrolment data and prefill spreadsheet input page.
*
* @param enrolmentExcel enrolment data Excel file
* @returns enrolment data Excel file
*/
export async function getUnitsList(enrolmentExcel: File) {
if (!isExcelFile(enrolmentExcel)) {
throw new Error(
Expand All @@ -58,6 +70,14 @@ export async function getUnitsList(enrolmentExcel: File) {
return enrolmentExcel;
}

/**
* Parse user input to create the timetabling problem.
*
* @param enrolmentExcel enrolment data Excel file
* @param roomSpreadsheet information of all rooms (spreadsheet input from user)
* @param unitSpreadsheet information of all units (spreadsheet input from user)
* @returns a TimetableProblem, which includes all available rooms, start times and unallocated units
*/
export async function getTimetableProblem(enrolmentExcel: File, roomSpreadsheet: Record<string, CellValue>[], unitSpreadsheet: Record<string, CellValue>[]) {
if (!isExcelFile(enrolmentExcel)) {
throw new Error(
Expand Down
Loading

0 comments on commit 38db9a1

Please sign in to comment.