diff --git a/frontend/src/components/pages/schedule/SchedulePage.tsx b/frontend/src/components/pages/schedule/SchedulePage.tsx index 3e73bc9..458d372 100644 --- a/frontend/src/components/pages/schedule/SchedulePage.tsx +++ b/frontend/src/components/pages/schedule/SchedulePage.tsx @@ -1,8 +1,37 @@ -import React from "react"; +import React, { useEffect, useState } from "react"; import { Flex, + Input, + Button, + InputGroup, + InputLeftElement, + Tabs, + TabList, + Tab, + Icon, + Checkbox, } from "@chakra-ui/react"; +import { + tasksColumnTypes +} from "./columnKeys"; + +import { + scheduleTasksMockData, + sundayScheduleTasksMockData, + mondayScheduleTasksMockData, + tuesdayScheduleTasksMockData, + wednesdayScheduleTasksMockData, + thursdayScheduleTasksMockData, + fridayScheduleTasksMockData, + saturdayScheduleTasksMockData, +} from "../../../mocks/scheduletasks"; + +import ScheduleTable, { + ColumnInfoTypes, + TableData, +} from "./ScheduleTable"; + import RoomCard from "../home/HomeRoomCard" import { residentsMockData } from "../../../mocks/residents"; @@ -14,8 +43,79 @@ const renderRoomCards = residentsMockData.map(resident => /> ) - const SchedulePage = (): React.ReactElement => { + const enum Dates { + SUNDAY = "SUNDAY", + MONDAY = "MONDAY", + TUESDAY = "TUESDAY", + WEDNESDAY = "WEDNESDAY", + THURSDAY = "THURSDAY", + FRIDAY = "FRIDAY", + SATURDAY = "SATURDAY", + } + + const [taskData, setTaskData] = useState([]); + const [storedTaskData, setStoredTaskData] = useState([]); + const [taskDataColumns, setTaskDataColumns] = useState([]); + const [taskDate, setTaskDate] = useState(Dates.SUNDAY); + const [dailyTaskData, setDailyTaskData] = useState([]); + + useEffect(() => { + setTaskDataColumns(tasksColumnTypes); + setTaskData(scheduleTasksMockData); + if (taskDate === Dates.SUNDAY) { + setDailyTaskData(sundayScheduleTasksMockData); + } + else if (taskDate === Dates.MONDAY) { + setDailyTaskData(mondayScheduleTasksMockData); + } + else if (taskDate === Dates.TUESDAY) { + setDailyTaskData(tuesdayScheduleTasksMockData); + } + else if (taskDate === Dates.WEDNESDAY) { + setDailyTaskData(wednesdayScheduleTasksMockData); + } + else if (taskDate === Dates.THURSDAY) { + setDailyTaskData(thursdayScheduleTasksMockData); + } + else if (taskDate === Dates.FRIDAY) { + setDailyTaskData(fridayScheduleTasksMockData); + } + else if (taskDate === Dates.SATURDAY) { + setDailyTaskData(saturdayScheduleTasksMockData); + } + else { + setDailyTaskData(sundayScheduleTasksMockData); + } + }, []); + + useEffect(() => { + if (taskDate === Dates.SUNDAY) { + setDailyTaskData(sundayScheduleTasksMockData); + } + else if (taskDate === Dates.MONDAY) { + setDailyTaskData(mondayScheduleTasksMockData); + } + else if (taskDate === Dates.TUESDAY) { + setDailyTaskData(tuesdayScheduleTasksMockData); + } + else if (taskDate === Dates.WEDNESDAY) { + setDailyTaskData(wednesdayScheduleTasksMockData); + } + else if (taskDate === Dates.THURSDAY) { + setDailyTaskData(thursdayScheduleTasksMockData); + } + else if (taskDate === Dates.FRIDAY) { + setDailyTaskData(fridayScheduleTasksMockData); + } + else if (taskDate === Dates.SATURDAY) { + setDailyTaskData(saturdayScheduleTasksMockData); + } + else { + setDailyTaskData(sundayScheduleTasksMockData); + } + }, [taskDate]) + return (

Schedule Page

@@ -25,6 +125,88 @@ const SchedulePage = (): React.ReactElement => { > {renderRoomCards}
+ Weekly Tasks + + {}} + isSelectable + /> + + + + + { + setTaskDate(Dates.SUNDAY); + }} + > + Sunday + + { + setTaskDate(Dates.MONDAY); + }} + > + Monday + + { + setTaskDate(Dates.TUESDAY); + }} + > + Tuesday + + { + setTaskDate(Dates.WEDNESDAY); + }} + > + Wednesday + + { + setTaskDate(Dates.THURSDAY); + }} + > + Thursday + + { + setTaskDate(Dates.FRIDAY); + }} + > + Friday + + { + setTaskDate(Dates.SATURDAY); + }} + > + Saturday + + + + Daily Tasks + + {}} + isSelectable + /> + + ); }; diff --git a/frontend/src/components/pages/schedule/ScheduleTable.tsx b/frontend/src/components/pages/schedule/ScheduleTable.tsx new file mode 100644 index 0000000..94dcaa7 --- /dev/null +++ b/frontend/src/components/pages/schedule/ScheduleTable.tsx @@ -0,0 +1,337 @@ +import React, { useState, useEffect } from "react"; +import { + Table, + Thead, + Tbody, + Tr, + Th, + Td, + TableContainer, + Checkbox, + Center, + Box, + Flex, + IconButton, + Icon, +} from "@chakra-ui/react"; +import ModeCommentOutlinedIcon from '@mui/icons-material/ModeCommentOutlined'; +import ChevronLeftOutlinedIcon from "@mui/icons-material/ChevronLeftOutlined"; +import ChevronRightOutlinedIcon from "@mui/icons-material/ChevronRightOutlined"; +import KeyboardArrowUpOutlinedIcon from "@mui/icons-material/KeyboardArrowUpOutlined"; +import KeyboardArrowDownOutlinedIcon from "@mui/icons-material/KeyboardArrowDownOutlined"; + +type TableTypes = string | number | boolean | Date; + +export type ColumnInfoTypes = { header: string; key: string }; + +export interface TableData { + [key: string]: TableTypes; +} + +type Props = { + data: TableData[]; + columnInfo: ColumnInfoTypes[]; + onEdit: (row: unknown) => unknown; + maxResults?: number; + isSelectable?: boolean; +}; + +type SortState = { + [key: string]: number; +}; + +const ScheduleTable = ({ + columnInfo, + data, + onEdit, + maxResults = 10, + isSelectable = false, +}: Props): React.ReactElement => { + const [checked, setChecked] = useState(data.map(() => false)); + const [page, setPage] = useState(1); + const [pageArray, setPageArray] = useState([]); + const [sortingColumn, setSortingColumn] = useState({}); + const [originalData, setOriginalData] = useState(data); + const [sortedData, setSortedData] = useState(data); + + useEffect(() => { + return Math.ceil(data.length / maxResults) >= 5 + ? setPageArray([1, 2, 3, 4, 5]) + : setPageArray( + Array.from( + { length: Math.ceil(data.length / maxResults) }, + (_, i) => i + 1, + ), + ); + }, [data, maxResults]); + + useEffect(() => { + setOriginalData(data); + setSortedData(data); + }, [data]); + + // sorting the columns by ascending and descending order based on column indicated + const sortColumn = (column: string) => { + const newSortingColumn: SortState = {}; + columnInfo.forEach((col) => { + newSortingColumn[col.key] = + col.key === column ? sortingColumn[column] : 0; + }); + + // increment column sorting state + sortingColumn[column] = sortingColumn[column] + ? sortingColumn[column] + 1 + : 1; + + // if at the end, go back to 0 + if (sortingColumn[column] === 3) { + setSortingColumn({ ...sortingColumn, [column]: 0 }); + setSortedData(originalData); + return; + } + setSortingColumn({ + ...newSortingColumn, + [column]: sortingColumn[column], + }); + + // apply sorting based on which sorting state the column's in + const sorted = [...originalData].sort((a, b) => { + if (sortingColumn[column] === 1) { + return a[column] > b[column] ? 1 : -1; + } + if (sortingColumn[column] === 2) { + return a[column] < b[column] ? 1 : -1; + } + return 0; + }); + setSortedData(sorted); + }; + + // constants for pagination UI + const checkedPage = checked.slice((page - 1) * maxResults, page * maxResults); + const allChecked = checkedPage.every(Boolean); + const isIndeterminate = checkedPage.some(Boolean) && !allChecked; + + // pagination functions + const leftPaginate = () => { + if (page > 1) setPage(page - 1); + if (pageArray[0] > 1 && pageArray.length === 5) { + setPageArray(pageArray.map((item) => item - 1)); + } + }; + + const rightPaginate = () => { + if (page < Math.ceil(data.length / maxResults)) setPage(page + 1); + if ( + pageArray[pageArray.length - 1] < Math.ceil(data.length / maxResults) && + pageArray.length === 5 + ) { + setPageArray(pageArray.map((item) => item + 1)); + } + }; + + const numberPaginate = (n: number) => { + setPage(n); + // Sets n as the center of the page array when possible. + if ( + n - 2 >= 1 && + n + 2 <= Math.ceil(data.length / maxResults) && + pageArray.length === 5 + ) { + setPageArray([n - 2, n - 1, n, n + 1, n + 2]); + } + }; + + return ( + + + + + + {isSelectable ? ( + + ) : null} + {columnInfo.map((header, index) => ( + + ))} + + + + {sortedData + .slice((page - 1) * maxResults, page * maxResults) + .map((row, index) => { + return ( + + {isSelectable ? ( + + ) : null} + {columnInfo.map((column, i) => { + const getColor = (status: string) => { + if (status === "Completed") return "#0D8312"; + if (status === "Excused") return "#B07D18"; + if (status === "Incomplete") return "#B21D2F"; + return "black"; + }; + + const getBoxColor = (status: string) => { + if (status === "Completed") return "#CDEECE"; + if (status === "Excused") return "#FFE5B2"; + if (status === "Incomplete") return "#F8D7DB"; + return "black"; + }; + + return column.key === "status" ? ( + + ) : ( + + ); + })} + + + ); + })} + +
+ {null} + + + {header.header} + + { + sortColumn(header.key); + }} + /> + { + sortColumn(header.key); + }} + /> + + + +
+ { + const newChecked = [...checked]; + newChecked[index + (page - 1) * maxResults] = + e.target.checked; + setChecked(newChecked); + }} + /> + + {row[column.key] ? {String(row[column.key])} : ''} + + {row[column.key] ? String(row[column.key]) : ''} onEdit(row)}> + +
+
+ + + + {`Showing ${(page - 1) * maxResults + 1} to ${page * maxResults} of ${ + data.length + } entries`} + + + + } + onClick={() => leftPaginate()} + /> + {pageArray.map((item, index) => { + return ( +
numberPaginate(item)} + key={index} + > + {item} +
+ ); + })} + } + onClick={() => rightPaginate()} + /> +
+
+
+
+ ); +}; + +export default ScheduleTable; diff --git a/frontend/src/components/pages/schedule/columnKeys.ts b/frontend/src/components/pages/schedule/columnKeys.ts new file mode 100644 index 0000000..25bebb2 --- /dev/null +++ b/frontend/src/components/pages/schedule/columnKeys.ts @@ -0,0 +1,22 @@ +import { ColumnInfoTypes } from "../../common/CommonTable"; + +export const tasksColumnTypes: ColumnInfoTypes[] = [ + { + header: " Name", + key: "title", + }, + { + header: "Status", + key: "status", + }, + { + header: "Time", + key: "time", + }, + { + header: "Marillac Bucks", + key: "creditValue", + }, +]; + +export default {}; diff --git a/frontend/src/mocks/scheduletasks.ts b/frontend/src/mocks/scheduletasks.ts new file mode 100644 index 0000000..343bb26 --- /dev/null +++ b/frontend/src/mocks/scheduletasks.ts @@ -0,0 +1,169 @@ +export const scheduleTasksMockData = [ + { + title: "Weekly Review with CM", + status: "Completed", + time: "All day", + creditValue: "$5.00", + }, + { + title: "Skills Session with PM", + status: "Completed", + time: "All day", + creditValue: "$5.00", + }, + { + title: "Housing Plan", + status: "Excused", + time: "All day", + creditValue: "$5.00", + }, +]; + +export const sundayScheduleTasksMockData = [ + { + title: "Weekly Review with CM", + status: "Completed", + time: "All day", + creditValue: "$5.00", + }, + { + title: "Skills Session with PM", + status: "Completed", + time: "All day", + creditValue: "$5.00", + }, + { + title: "Housing Plan", + status: "Excused", + time: "All day", + creditValue: "$5.00", + }, +]; + +export const mondayScheduleTasksMockData = [ + { + title: "Weekly Review with CM", + status: "Excused", + time: "All day", + creditValue: "$10.00", + }, + { + title: "Skills Session with PM", + status: "Completed", + time: "All day", + creditValue: "$5.00", + }, + { + title: "Housing Plan", + status: "Excused", + time: "All day", + creditValue: "$5.00", + }, +]; + +export const tuesdayScheduleTasksMockData = [ + { + title: "Weekly Review with CM", + status: "Completed", + time: "All day", + creditValue: "$5.00", + }, + { + title: "Skills Session with PM", + status: "Completed", + time: "All day", + creditValue: "$5.00", + }, + { + title: "Housing Plan", + status: "Excused", + time: "All day", + creditValue: "$5.00", + }, +]; + +export const wednesdayScheduleTasksMockData = [ + { + title: "Weekly Review with CM", + status: "Completed", + time: "All day", + creditValue: "$5.00", + }, + { + title: "Skills Session with PM", + status: "Completed", + time: "All day", + creditValue: "$5.00", + }, + { + title: "Housing Plan", + status: "Excused", + time: "All day", + creditValue: "$5.00", + }, +]; + +export const thursdayScheduleTasksMockData = [ + { + title: "Weekly Review with CM", + status: "Completed", + time: "All day", + creditValue: "$5.00", + }, + { + title: "Skills Session with PM", + status: "Completed", + time: "All day", + creditValue: "$5.00", + }, + { + title: "Housing Plan", + status: "Excused", + time: "All day", + creditValue: "$5.00", + }, +]; + +export const fridayScheduleTasksMockData = [ + { + title: "Weekly Review with CM", + status: "Completed", + time: "All day", + creditValue: "$5.00", + }, + { + title: "Skills Session with PM", + status: "Completed", + time: "All day", + creditValue: "$5.00", + }, + { + title: "Housing Plan", + status: "Excused", + time: "All day", + creditValue: "$5.00", + }, +]; + +export const saturdayScheduleTasksMockData = [ + { + title: "Weekly Review with CM", + status: "Completed", + time: "All day", + creditValue: "$5.00", + }, + { + title: "Skills Session with PM", + status: "Completed", + time: "All day", + creditValue: "$5.00", + }, + { + title: "Housing Plan", + status: "Excused", + time: "All day", + creditValue: "$5.00", + }, +]; + +export default {}; \ No newline at end of file