diff --git a/amplify.yml b/amplify.yml new file mode 100644 index 0000000..cf31de5 --- /dev/null +++ b/amplify.yml @@ -0,0 +1,22 @@ +version: 1 +backend: + phases: + build: + commands: + - nvm install 20 + - nvm use 20 + - npm ci --cache .npm --prefer-offline + - npx ampx pipeline-deploy --branch $AWS_BRANCH --app-id $AWS_APP_ID +frontend: + phases: + build: + commands: + - npm run build + artifacts: + baseDirectory: .next + files: + - '**/*' + cache: + paths: + - .next/cache/**/* + - .npm/**/* \ No newline at end of file diff --git a/amplify/data/resource.ts b/amplify/data/resource.ts index 0355503..c73ee18 100644 --- a/amplify/data/resource.ts +++ b/amplify/data/resource.ts @@ -15,6 +15,7 @@ const schema = a.schema({ courses: a.hasMany("Course", "organizationId"), pathways: a.hasMany("Pathway", "organizationId"), admins: a.hasMany("User", "organizationId"), + tasks: a.hasMany("Tasks", "organizationId"), }) .authorization((allow) => [allow.guest()]), User: a @@ -66,13 +67,16 @@ const schema = a.schema({ courses: a.hasMany("Course", "semesterId"), }) .authorization((allow) => [allow.guest()]), - - // Orginal Example - // Todo: a - // .model({ - // content: a.string(), - // }) - // .authorization((allow) => [allow.guest()]), + Tasks: a + .model({ + TaskId: a.id(), + title: a.string(), + details: a.string(), + date: a.date(), + important: a.boolean(), + done: a.boolean(), + }) + .authorization((allow) => [allow.guest()]), }); export type Schema = ClientSchema; @@ -89,7 +93,7 @@ Go to your frontend source code. From your client-side code, generate a Data client to make CRUDL requests to your table. (THIS SNIPPET WILL ONLY WORK IN THE FRONTEND CODE FILE.) -Using JavaScript or Next.js React Server Components, Middleware, Server +Using JavaScript or Next.js React Server Components, Middleware, Server Actions or Pages Router? Review how to generate Data clients for those use cases: https://docs.amplify.aws/gen2/build-a-backend/data/connect-to-API/ =========================================================================*/ diff --git a/package-lock.json b/package-lock.json index 9e3c3d8..489230b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,13 +14,15 @@ "@dnd-kit/core": "^6.1.0", "@dnd-kit/sortable": "^8.0.0", "@emotion/cache": "^11.11.0", - "@emotion/react": "^11.11.3", - "@emotion/styled": "^11.11.0", + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", "@hello-pangea/dnd": "^16.6.0", "@mui/icons-material": "^5.14.18", - "@mui/material": "^5.14.18", + "@mui/material": "^5.15.21", "@mui/material-nextjs": "^5.15.7", + "@mui/x-date-pickers": "^7.7.1", "aws-amplify": "^6.3.7", + "dayjs": "^1.11.11", "mui-nested-menu": "^3.3.0", "next": "latest", "react": "latest", @@ -12183,6 +12185,7 @@ "version": "11.11.4", "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.11.0", @@ -12223,6 +12226,7 @@ "version": "11.11.5", "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.5.tgz", "integrity": "sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.11.0", @@ -13757,9 +13761,10 @@ } }, "node_modules/@mui/core-downloads-tracker": { - "version": "5.15.20", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.20.tgz", - "integrity": "sha512-DoL2ppgldL16utL8nNyj/P12f8mCNdx/Hb/AJnX9rLY4b52hCMIx1kH83pbXQ6uMy6n54M3StmEbvSGoj2OFuA==", + "version": "5.15.21", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.21.tgz", + "integrity": "sha512-dp9lXBaJZzJYeJfQY3Ow4Rb49QaCEdkl2KKYscdQHQm6bMJ+l4XPY3Cd9PCeeJTsHPIDJ60lzXbeRgs6sx/rpw==", + "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" @@ -13791,13 +13796,14 @@ } }, "node_modules/@mui/material": { - "version": "5.15.20", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.20.tgz", - "integrity": "sha512-tVq3l4qoXx/NxUgIx/x3lZiPn/5xDbdTE8VrLczNpfblLYZzlrbxA7kb9mI8NoBF6+w9WE9IrxWnKK5KlPI2bg==", + "version": "5.15.21", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.21.tgz", + "integrity": "sha512-nTyCcgduKwHqiuQ/B03EQUa+utSMzn2sQp0QAibsnYe4tvc3zkMbO0amKpl48vhABIY3IvT6w9615BFIgMt0YA==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.23.9", "@mui/base": "5.0.0-beta.40", - "@mui/core-downloads-tracker": "^5.15.20", + "@mui/core-downloads-tracker": "^5.15.21", "@mui/system": "^5.15.20", "@mui/types": "^7.2.14", "@mui/utils": "^5.15.20", @@ -14004,6 +14010,72 @@ } } }, + "node_modules/@mui/x-date-pickers": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.7.1.tgz", + "integrity": "sha512-p7/TY8QcdQd6RelNqzW5q89GeUFctvZnDHTfQVEC0l0nAy7ArE6u21uNF8QWGrijZoJXCM+OlIRzlZADaUPpWA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7", + "@mui/base": "^5.0.0-beta.40", + "@mui/system": "^5.15.20", + "@mui/utils": "^5.15.20", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^5.15.14", + "date-fns": "^2.25.0 || ^3.2.0", + "date-fns-jalali": "^2.13.0-0 || ^3.2.0-0", + "dayjs": "^1.10.7", + "luxon": "^3.0.2", + "moment": "^2.29.4", + "moment-hijri": "^2.1.2", + "moment-jalaali": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "date-fns": { + "optional": true + }, + "date-fns-jalali": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + }, + "moment-hijri": { + "optional": true + }, + "moment-jalaali": { + "optional": true + } + } + }, "node_modules/@next/env": { "version": "14.2.4", "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.4.tgz", @@ -17802,6 +17874,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dayjs": { + "version": "1.11.11", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", + "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==", + "license": "MIT" + }, "node_modules/debounce-promise": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/debounce-promise/-/debounce-promise-3.1.2.tgz", diff --git a/package.json b/package.json index 9cf1c5d..9dc35a1 100755 --- a/package.json +++ b/package.json @@ -19,13 +19,15 @@ "@dnd-kit/core": "^6.1.0", "@dnd-kit/sortable": "^8.0.0", "@emotion/cache": "^11.11.0", - "@emotion/react": "^11.11.3", - "@emotion/styled": "^11.11.0", + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", "@hello-pangea/dnd": "^16.6.0", "@mui/icons-material": "^5.14.18", - "@mui/material": "^5.14.18", + "@mui/material": "^5.15.21", "@mui/material-nextjs": "^5.15.7", + "@mui/x-date-pickers": "^7.7.1", "aws-amplify": "^6.3.7", + "dayjs": "^1.11.11", "mui-nested-menu": "^3.3.0", "next": "latest", "react": "latest", diff --git a/src/app/(home)/tasks/page.js b/src/app/(home)/tasks/page.js index cfa7891..5516583 100755 --- a/src/app/(home)/tasks/page.js +++ b/src/app/(home)/tasks/page.js @@ -4,61 +4,65 @@ import React, { useState, useMemo } from 'react'; // Material UI imports -import Typography from '@mui/material/Typography'; -import IconButton from '@mui/material/IconButton'; -import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline'; -import Box from '@mui/material/Box'; import { useTheme } from '@mui/material/styles'; // Component Imports import Column from '../../../components/Layouts/TasksColumn'; -import TaskDialog from '@/components/Dialogs/TaskDialog'; // Data Imports -import { initialData } from '@/components/Data/initialData'; +import { initialTasks } from '@/components/Data/initialData'; // Assuming DragDropContext will be used later import { DragDropContext } from '@hello-pangea/dnd'; +import TaskHeaderCard from "../../../components/Cards/TaskHeaderCard"; +import TaskCard from "../../../components/Cards/TaskCard"; -export default function Lists() { - // State management - const [open, setOpen] = useState(false); - const handlePlusClick = () => setOpen(true); - const handleTaskDialogClose = () => setOpen(false); +import { Box } from "@mui/material"; +import DatePickerDialog from "@/components/Dialogs/DatePickerDialog"; + +export default function Lists () +{ + // State management + const [tasks, setTasks] = useState(initialTasks); // Use theme from Material UI const theme = useTheme(); - // Memoize data to avoid recomputation on every render - const data = useMemo(() => initialData, []); + const handleTaskDelete = (id) => + { + setTasks(tasks.filter((t) => t.id !== id)); + console.log('deleted'); + } + + const handleTaskAddClick = () => + { + const newTask = { + id: tasks.length, + title: "", + details: "", + date: "", + important: false, + done: false + }; + setTasks([...tasks, newTask]); + console.log('added a task'); + } return ( <> - {data.columnOrder.map((columnId) => { - const column = data.columns[columnId]; - const tasks = column.tasksIds.map((taskId) => data.tasks[taskId]); - const title = column.title; - - return ( - - - {title} - - - - - - ); - })} + + + { + tasks.map((t, index) => + { + return ( + (index === tasks.length - 1) ? + handleTaskDelete(t.id)} /> + : handleTaskDelete(t.id)} /> + ) + }) + } + ); -} +} \ No newline at end of file diff --git a/src/components/Cards/TaskCard.js b/src/components/Cards/TaskCard.js index 11f0757..c5a2ba7 100644 --- a/src/components/Cards/TaskCard.js +++ b/src/components/Cards/TaskCard.js @@ -7,40 +7,112 @@ import NotesIcon from '@mui/icons-material/Notes'; import CalendarMonthIcon from '@mui/icons-material/CalendarMonth'; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; - +import Box from "@mui/material/Box"; +import IconButton from "@mui/material/IconButton"; +import Tooltip from "@mui/material/Tooltip"; +import MoreVertOutlined from "@mui/icons-material/MoreVertOutlined"; +import Menu from "@mui/material/Menu"; +import MenuItem from "@mui/material/MenuItem"; +import StarOutlineIcon from '@mui/icons-material/StarOutline'; +import { Star } from "@mui/icons-material"; +import dayjs from 'dayjs'; //React -import React from 'react'; +import React, { useState } from 'react'; +import DatePickerDialog from "../Dialogs/DatePickerDialog"; + -export default function TaskCard () +export default function TaskCard ({ task, borderBottomRadius, onDeleteClick }) { + const { title, details, date, important, done } = task; + + const [isHovering, setIsHovering] = useState(false); + const [anchorEl, setAnchorEl] = useState(null); + const [isImportant, setIsImportant] = useState(important); + const [openCalendarDialog, setOpenCalendarDialog] = useState(false); + const [dateValue, setDateValue] = useState(dayjs(date)); + const taskOptionsOpen = Boolean(anchorEl); + + const handleMouseOver = () => setIsHovering(true); + const handleMouseLeave = () => setIsHovering(false); + const handleTaskOptionsClose = () => setAnchorEl(null); + const handleTaskOptionsOpen = (event) => setAnchorEl(event.currentTarget); + const handleImportantIconClick = () => setIsImportant(!isImportant); + const handleDateIconClick = () => setOpenCalendarDialog(true); + const handleCloseDialog = () => setOpenCalendarDialog(false); + + console.log(dateValue); + + + const TaskOptionsMenu = ( + + + Delete + + + ) + return ( <> -
+ - + -
+ - -
+ + { + (isHovering) ? + <> + + + + + + + + {isImportant ? : } + + + {TaskOptionsMenu} + + : + <> + } + +
-
+ - -
+ + -
- -
+ -
+ + ); } \ No newline at end of file diff --git a/src/components/Cards/TaskHeaderCard.js b/src/components/Cards/TaskHeaderCard.js index 61daa02..3ca2f12 100644 --- a/src/components/Cards/TaskHeaderCard.js +++ b/src/components/Cards/TaskHeaderCard.js @@ -9,29 +9,63 @@ import Button from '@mui/material/Button'; import MoreVertOutlined from '@mui/icons-material/MoreVertOutlined'; import IconButton from '@mui/material/IconButton'; import Tooltip from '@mui/material/Tooltip'; +import Menu from "@mui/material/Menu"; +import MenuItem from "@mui/material/MenuItem"; // React import React from 'react'; +import { useState } from 'react'; + +export default function TaskHeaderCard ({ handleAddTask }) +{ + + const [anchorEl, setAnchorEl] = useState(null); + const taskHeaderOptionsOpen = Boolean(anchorEl); + + const handleTaskHeaderOptionsClose = () => setAnchorEl(null); + const handleTaskHeaderOptionsOpen = (event) => setAnchorEl(event.currentTarget); + + const TaskHeaderOptionsMenu = ( + + + Delete all tasks + + + ) -export default function TaskHeaderCard() { return ( <> -
- -
+ + + My Tasks - + -
+ {TaskHeaderOptionsMenu} + -
+ ); } \ No newline at end of file diff --git a/src/components/Data/initialData.js b/src/components/Data/initialData.js index 2978470..54366a2 100644 --- a/src/components/Data/initialData.js +++ b/src/components/Data/initialData.js @@ -1,9 +1,9 @@ export const initialData = { tasks: { - 'task-1': { id: 'task-1', content: 'Complete the Tasks Page', date: 'January 14th, 2023', important: true, checked: false}, - 'task-2': { id: 'task-2', content: 'Transfer the Backend Stack to Amplify 2.0', date: 'January 25th, 2023', important: true, checked: false}, - 'class-1': { id: 'class-1', content: "COMP.4220 - Machine Learning", date: 'January 16th, 2023', important: true, checked: false}, - 'class-2': {id: 'class-2', content: "COMP.2040 - Computing IV", date: 'January 16th, 2023', important: false, checked: true}, + 'task-1': { id: 'task-1', content: 'Complete the Tasks Page', date: 'January 14th, 2023', important: true, checked: false }, + 'task-2': { id: 'task-2', content: 'Transfer the Backend Stack to Amplify 2.0', date: 'January 25th, 2023', important: true, checked: false }, + 'class-1': { id: 'class-1', content: "COMP.4220 - Machine Learning", date: 'January 16th, 2023', important: true, checked: false }, + 'class-2': { id: 'class-2', content: "COMP.2040 - Computing IV", date: 'January 16th, 2023', important: false, checked: true }, }, columns: { @@ -24,4 +24,79 @@ export const initialData = { }, }, columnOrder: ['column-1', 'column-2', 'column-3'], -}; \ No newline at end of file +}; + +export const initialTasks = [ + { + id: '1', + title: "finish homework", + details: "finish it by 11:59pm", + date: "2024-06-23", + important: false, + done: false + }, + { + id: '2', + title: "sfsdfs", + details: "sdfsdf them", + date: "2024-06-23", + important: true, + done: false + }, + { + id: '3', + title: "Tangowe4ngoiretngsks", + details: "io4kbgoi4qbgi them", + date: "2024-06-23", + important: true, + done: false + }, + { + id: '4', + title: "oi3bgib4ng5", + details: "fiib435go'ib1345gib1gnish them", + date: "2024-06-23", + important: true, + done: false + }, + { + id: '5', + title: "oi13b'4goib134g", + details: "j1b3;gjob13'gob them", + date: "2024-06-23", + important: true, + done: false + }, + { + id: '6', + title: "Tasks", + details: "finish them", + date: "2024-06-23", + important: false, + done: false + }, + { + id: '7', + title: "Tasks", + details: "finish them", + date: "2024-23-23", + important: false, + done: false + }, + { + id: '8', + title: "Tasks", + details: "finish them", + date: "2024-11-23", + important: true, + done: false + }, + { + id: '9', + title: "Tasks", + details: "finish them", + date: "2024-06-23", + important: false, + done: false + } +] \ No newline at end of file diff --git a/src/components/Dialogs/DatePickerDialog.js b/src/components/Dialogs/DatePickerDialog.js new file mode 100644 index 0000000..2073ab1 --- /dev/null +++ b/src/components/Dialogs/DatePickerDialog.js @@ -0,0 +1,42 @@ +"use client" + +//React +import React, { useState } from 'react'; + +//MUI +import { Dialog } from "@mui/material"; +import { StaticDatePicker } from '@mui/x-date-pickers/StaticDatePicker'; +import { LocalizationProvider } from "@mui/x-date-pickers"; +import dayjs from 'dayjs'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; + +export default function DatePickerDialog({ dateValue, setDateValue, setOpenCalendarDialog, openCalendarDialog, onClose }) { + + const onAccept = (value) => { + console.log("output from onAccept:" + value); + setDateValue(dayjs(value)); + setOpenCalendarDialog(false); + } + + const handleCloseDialog = () => { + setOpenCalendarDialog(false); + } + + return ( + + + { onAccept(value) }} + open={openCalendarDialog} + /> + + + ); +} \ No newline at end of file diff --git a/src/components/Dialogs/TaskDialog.js b/src/components/Dialogs/TaskDialog.js deleted file mode 100644 index eee9472..0000000 --- a/src/components/Dialogs/TaskDialog.js +++ /dev/null @@ -1,87 +0,0 @@ -// React -import * as React from 'react'; - -// MUI imports -import Button from "@mui/material/Button"; -import TextField from "@mui/material/TextField"; -import Typography from "@mui/material/Typography"; -import Dialog from "@mui/material/Dialog"; -import DialogTitle from "@mui/material/DialogTitle"; -import DialogContent from "@mui/material/DialogContent"; -import DialogActions from "@mui/material/DialogActions"; -import IconButton from "@mui/material/IconButton"; -import CalendarMonthIcon from '@mui/icons-material/CalendarMonth'; - -export default function TaskDialog({ open, handleClose, handleAddTaskCard }) { - // need to work on the PaperProps - const [openCalendar, setOpenCalendar] = React.useState(false); - - function handleCalendarIconClick() { - setOpenCalendar(true); - } - - function handleCloseCalendar() { - setOpenCalendar(false); - } - - return ( - <> - - Create Task - - - - {/* Could be better if the below text field's a text box */} - - - - {/* Add date functionality below as well */} -
- {/* Change so that Add date aligns with the calendar icon */} - Add date - - {/* Should be able to select a date on click. */} - -
- - {/* Actions to perform (cancel, add) */} -
- - - {/* Need to add functionality */} - -
- - ); -} \ No newline at end of file