From 1c69f758cba354729afe9ee50fd2d34a615d4b31 Mon Sep 17 00:00:00 2001 From: cindyhjli Date: Mon, 27 May 2024 22:00:36 -0400 Subject: [PATCH 1/9] add task modal --- frontend/src/App.tsx | 4 +- .../src/components/pages/tasks/TaskModal.tsx | 253 ++++++++++++++++++ .../src/components/pages/tasks/TasksPage.tsx | 7 +- 3 files changed, 260 insertions(+), 4 deletions(-) create mode 100644 frontend/src/components/pages/tasks/TaskModal.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 4e361f4d..a88061f6 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -91,9 +91,9 @@ const App = (): React.ReactElement => { + // - + // } /> >; +}; + +const FormField = ({ + label, + value, + type = "text", + onChange, + submitPressed, + required = false, + isPassword = false, + showPassword, + setShowPassword, +}: { + label: string; + value: string; + type?: string; + onChange: (e: React.ChangeEvent) => void; + submitPressed: boolean; + required?: boolean; + isPassword?: boolean; + showPassword?: boolean; + setShowPassword?: React.Dispatch>; +}) => ( + + + + {label} + + + + {isPassword && setShowPassword && ( + + + + )} + + + +); + +const DateInput = ({ + dueDateTime, + setDueDateTime, + isAllDay, + setIsAllDay, + recurrenceFrequency, + setRecurrenceFrequency, + submitPressed, +}: { + dueDateTime: string; + setDueDateTime: React.Dispatch>; + isAllDay: boolean; + setIsAllDay: React.Dispatch>; + recurrenceFrequency: string; + setRecurrenceFrequency: React.Dispatch>; + submitPressed: boolean; +}) => ( + + + + Due Date + + + setDueDateTime(e.target.value)} + /> + + setIsAllDay(e.target.checked)} + > + All Day + + + + + + +); + +const TaskModal = ({ isOpen, setIsOpen }: Props): React.ReactElement => { + const [title, setTitle] = useState(""); + const [location, setLocation] = useState(""); + const [dueDateTime, setDueDateTime] = useState(""); + const [isAllDay, setIsAllDay] = useState(false); + const [recurrenceFrequency, setRecurrenceFrequency] = useState(""); + const [marillacBucks, setMarillacBucks] = useState(""); + + const [submitPressed, setSubmitPressed] = useState(false); + + const handleSubmit = () => { + setSubmitPressed(true); + if (!title || !location || !dueDateTime || !marillacBucks) { + // TODO: Add error handling + } + // TODO: API call to add task + }; + + const resetFormState = () => { + setTitle(""); + setLocation(""); + setDueDateTime(""); + setIsAllDay(false); + setRecurrenceFrequency(""); + setMarillacBucks(""); + + setSubmitPressed(false); + }; + + const handleMoneyInput = () => { + const moneyRegex = /^\d*(\.\d{0,2})?$/; + + // if (value === '' || moneyRegex.test(value)) { + // setValue(value); + // } + }; + + + return ( + + + Edit Chore + + + + setTitle(e.target.value)} + submitPressed={submitPressed} + required + /> + + Location + + + + + + setMarillacBucks(e.target.value)} + submitPressed={submitPressed} + required + /> + + + + + + + + ); +}; + +export default TaskModal; \ No newline at end of file diff --git a/frontend/src/components/pages/tasks/TasksPage.tsx b/frontend/src/components/pages/tasks/TasksPage.tsx index 40215d0d..ee2ecdb0 100644 --- a/frontend/src/components/pages/tasks/TasksPage.tsx +++ b/frontend/src/components/pages/tasks/TasksPage.tsx @@ -12,6 +12,7 @@ import { } from "@chakra-ui/react"; import { Add, Search } from "@mui/icons-material"; +import TaskModal from "./TaskModal"; import { TaskType, Task, @@ -39,6 +40,7 @@ const TasksPage = (): React.ReactElement => { const [optionalTasks, setOptionalTasks] = useState([]); const [customTasks, setCustomTasks] = useState([]); const [choreTasks, setChoreTasks] = useState([]); + const [isModalOpen, setIsModalOpen] = useState(false); const [taskType, setTaskType] = useState("REQUIRED"); const [taskData, setTaskData] = useState([]); @@ -126,11 +128,12 @@ const TasksPage = (): React.ReactElement => { data={taskData} columnInfo={taskDataColumns} maxResults={8} - onEdit={() => {}} + onEdit={() => {setIsModalOpen(true);}} /> + ); }; - + export default TasksPage; From 0722d12a6425649716af6314bf13c17859173ea7 Mon Sep 17 00:00:00 2001 From: cindyhjli Date: Wed, 29 May 2024 21:09:41 -0400 Subject: [PATCH 2/9] fix task modal inputs --- frontend/package.json | 1 + .../src/components/pages/tasks/TaskModal.tsx | 105 ++++++++++++------ 2 files changed, 73 insertions(+), 33 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index dd6f119a..65defb85 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -38,6 +38,7 @@ "react-bootstrap": "^1.5.2", "react-dom": "^18.2.0", "react-google-login": "^5.2.2", + "react-icons": "^5.2.1", "react-json-schema": "^1.2.2", "react-jsonschema-form": "^1.8.1", "react-router-dom": "^6.4.3", diff --git a/frontend/src/components/pages/tasks/TaskModal.tsx b/frontend/src/components/pages/tasks/TaskModal.tsx index 6576bc28..6d80f387 100644 --- a/frontend/src/components/pages/tasks/TaskModal.tsx +++ b/frontend/src/components/pages/tasks/TaskModal.tsx @@ -14,6 +14,7 @@ import { import VisibilityIcon from "@mui/icons-material/Visibility"; import VisibilityOffIcon from "@mui/icons-material/VisibilityOff"; import { TbTrash } from "react-icons/tb"; +import { format } from 'date-fns'; import ModalContainer from "../../common/ModalContainer"; @@ -27,6 +28,7 @@ const FormField = ({ value, type = "text", onChange, + onBlur, submitPressed, required = false, isPassword = false, @@ -37,6 +39,7 @@ const FormField = ({ value: string; type?: string; onChange: (e: React.ChangeEvent) => void; + onBlur?: () => void; submitPressed: boolean; required?: boolean; isPassword?: boolean; @@ -80,39 +83,64 @@ const FormField = ({ ); const DateInput = ({ - dueDateTime, - setDueDateTime, + dueDate, + setDueDate, + dueTime, + setDueTime, isAllDay, setIsAllDay, recurrenceFrequency, setRecurrenceFrequency, submitPressed, }: { - dueDateTime: string; - setDueDateTime: React.Dispatch>; + dueDate: string; + setDueDate: React.Dispatch>; + dueTime: string; + setDueTime: React.Dispatch>; isAllDay: boolean; setIsAllDay: React.Dispatch>; recurrenceFrequency: string; setRecurrenceFrequency: React.Dispatch>; submitPressed: boolean; -}) => ( +}) => { + const formatDate = (inputDate: Date) => { + return format(inputDate, 'yyyy-MM-dd'); + }; + + return ( Due Date - setDueDateTime(e.target.value)} - /> + + setDueDate(e.target.value)} + /> + at + setDueTime(e.target.value)} + /> + ); +}; const TaskModal = ({ isOpen, setIsOpen }: Props): React.ReactElement => { const [title, setTitle] = useState(""); const [location, setLocation] = useState(""); - const [dueDateTime, setDueDateTime] = useState(""); + const [dueDate, setDueDate] = useState(""); + const [dueTime, setDueTime] = useState(""); const [isAllDay, setIsAllDay] = useState(false); const [recurrenceFrequency, setRecurrenceFrequency] = useState(""); - const [marillacBucks, setMarillacBucks] = useState(""); + const [unformattedMarillacBucks, setUnformattedMarillacBucks] = useState(''); + const [formattedMarillacBucks, setFormattedMarillacBucks] = useState('$'); const [submitPressed, setSubmitPressed] = useState(false); const handleSubmit = () => { setSubmitPressed(true); - if (!title || !location || !dueDateTime || !marillacBucks) { + if (!title || !location || !dueDate || !dueTime || !formattedMarillacBucks) { // TODO: Add error handling } // TODO: API call to add task @@ -159,20 +190,26 @@ const TaskModal = ({ isOpen, setIsOpen }: Props): React.ReactElement => { const resetFormState = () => { setTitle(""); setLocation(""); - setDueDateTime(""); + setDueDate(""); + setDueTime(""); setIsAllDay(false); setRecurrenceFrequency(""); - setMarillacBucks(""); + setUnformattedMarillacBucks(""); + setFormattedMarillacBucks("$"); setSubmitPressed(false); }; const handleMoneyInput = () => { - const moneyRegex = /^\d*(\.\d{0,2})?$/; - - // if (value === '' || moneyRegex.test(value)) { - // setValue(value); - // } + console.log("Marillac bucks field blurred. unformattedMarillacBucks: ", unformattedMarillacBucks); + let inputValue = unformattedMarillacBucks.replace(/[^0-9.]/g, ''); // Remove non-numeric and non-period characters + + if (inputValue) { + let numberValue = parseFloat(inputValue).toFixed(2); + console.log("rounded numberValue", numberValue); + setFormattedMarillacBucks(`$${numberValue}`); + console.log("formattedMarillacBucks:", formattedMarillacBucks); + } }; @@ -181,7 +218,7 @@ const TaskModal = ({ isOpen, setIsOpen }: Props): React.ReactElement => { Edit Chore @@ -209,8 +246,10 @@ const TaskModal = ({ isOpen, setIsOpen }: Props): React.ReactElement => { { /> setMarillacBucks(e.target.value)} + value={formattedMarillacBucks} + type="text" + onChange={(e) => setUnformattedMarillacBucks(e.target.value)} + onBlur={handleMoneyInput} submitPressed={submitPressed} required /> - - + =16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/@floating-ui/react-dom": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.0.tgz", - "integrity": "sha512-lNzj5EQmEKn5FFKc04+zasr09h/uX8RtJRNj5gUXsSQIXHVWTVh+hVAg1vOMCexkX8EgvemMvIFpQfkosnVNyA==", - "dependencies": { - "@floating-ui/dom": "^1.0.0" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/@floating-ui/utils": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.2.tgz", - "integrity": "sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==" - }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/date-fns": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", - "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/kossnocorp" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-datepicker": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-6.9.0.tgz", - "integrity": "sha512-QTxuzeem7BUfVFWv+g5WuvzT0c5BPo+XTCNbMTZKSZQLU+cMMwSUHwspaxuIcDlwNcOH0tiJ+bh1fJ2yxOGYWA==", - "dependencies": { - "@floating-ui/react": "^0.26.2", - "clsx": "^2.1.0", - "date-fns": "^3.3.1", - "prop-types": "^15.7.2", - "react-onclickoutside": "^6.13.0" - }, - "peerDependencies": { - "react": "^16.9.0 || ^17 || ^18", - "react-dom": "^16.9.0 || ^17 || ^18" - } - }, - "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/react-onclickoutside": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.1.tgz", - "integrity": "sha512-LdrrxK/Yh9zbBQdFbMTXPp3dTSN9B+9YJQucdDu3JNKRrbdU+H+/TVONJoWtOwy4II8Sqf1y/DTI6w/vGPYW0w==", - "funding": { - "type": "individual", - "url": "https://github.com/Pomax/react-onclickoutside/blob/master/FUNDING.md" - }, - "peerDependencies": { - "react": "^15.5.x || ^16.x || ^17.x || ^18.x", - "react-dom": "^15.5.x || ^16.x || ^17.x || ^18.x" - } - }, - "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/tabbable": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", - "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" - } - }, - "dependencies": { - "@floating-ui/core": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.2.tgz", - "integrity": "sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg==", - "requires": { - "@floating-ui/utils": "^0.2.0" - } - }, - "@floating-ui/dom": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.5.tgz", - "integrity": "sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==", - "requires": { - "@floating-ui/core": "^1.0.0", - "@floating-ui/utils": "^0.2.0" - } - }, - "@floating-ui/react": { - "version": "0.26.16", - "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.16.tgz", - "integrity": "sha512-HEf43zxZNAI/E781QIVpYSF3K2VH4TTYZpqecjdsFkjsaU1EbaWcM++kw0HXFffj7gDUcBFevX8s0rQGQpxkow==", - "requires": { - "@floating-ui/react-dom": "^2.1.0", - "@floating-ui/utils": "^0.2.0", - "tabbable": "^6.0.0" - } - }, - "@floating-ui/react-dom": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.0.tgz", - "integrity": "sha512-lNzj5EQmEKn5FFKc04+zasr09h/uX8RtJRNj5gUXsSQIXHVWTVh+hVAg1vOMCexkX8EgvemMvIFpQfkosnVNyA==", - "requires": { - "@floating-ui/dom": "^1.0.0" - } - }, - "@floating-ui/utils": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.2.tgz", - "integrity": "sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==" - }, - "clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" - }, - "date-fns": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", - "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==" - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, - "prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0" - } - }, - "react-datepicker": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-6.9.0.tgz", - "integrity": "sha512-QTxuzeem7BUfVFWv+g5WuvzT0c5BPo+XTCNbMTZKSZQLU+cMMwSUHwspaxuIcDlwNcOH0tiJ+bh1fJ2yxOGYWA==", - "requires": { - "@floating-ui/react": "^0.26.2", - "clsx": "^2.1.0", - "date-fns": "^3.3.1", - "prop-types": "^15.7.2", - "react-onclickoutside": "^6.13.0" - } - }, - "react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - } - }, - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "react-onclickoutside": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.1.tgz", - "integrity": "sha512-LdrrxK/Yh9zbBQdFbMTXPp3dTSN9B+9YJQucdDu3JNKRrbdU+H+/TVONJoWtOwy4II8Sqf1y/DTI6w/vGPYW0w==", - "requires": {} - }, - "scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0" - } - }, - "tabbable": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", - "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" - } - } -} diff --git a/package.json b/package.json deleted file mode 100644 index 62bee7fb..00000000 --- a/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "dependencies": { - "react-datepicker": "^6.9.0" - } -} From 69b88143e562ab70ad8173e1cc0da3cf498c85a6 Mon Sep 17 00:00:00 2001 From: KathleenX7 Date: Wed, 3 Jul 2024 20:57:43 -0400 Subject: [PATCH 6/9] finish task modal and make Form Field its own file --- frontend/package.json | 1 + frontend/src/App.tsx | 4 +- frontend/src/components/common/FormField.tsx | 86 +++++++++++++++++++ .../pages/residents/ResidentModal.tsx | 58 +------------ .../src/components/pages/tasks/TaskModal.tsx | 78 +++-------------- frontend/src/theme/inputs.ts | 1 - frontend/yarn.lock | 6 +- 7 files changed, 106 insertions(+), 128 deletions(-) create mode 100644 frontend/src/components/common/FormField.tsx diff --git a/frontend/package.json b/frontend/package.json index dd6f119a..65defb85 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -38,6 +38,7 @@ "react-bootstrap": "^1.5.2", "react-dom": "^18.2.0", "react-google-login": "^5.2.2", + "react-icons": "^5.2.1", "react-json-schema": "^1.2.2", "react-jsonschema-form": "^1.8.1", "react-router-dom": "^6.4.3", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index a88061f6..06381ce0 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -115,9 +115,9 @@ const App = (): React.ReactElement => { + // - + // } /> ) => void; + onBlur?: () => void; + submitPressed: boolean; + required?: boolean; + isPassword?: boolean; + showPassword?: boolean; + setShowPassword?: React.Dispatch>; + leftElement?: string; +}) => ( + + + + {label} + + + {leftElement && + {leftElement} + } + + + {isPassword && setShowPassword && ( + + + + )} + + + +); + +export default FormField; diff --git a/frontend/src/components/pages/residents/ResidentModal.tsx b/frontend/src/components/pages/residents/ResidentModal.tsx index 9b0915a7..44527c54 100644 --- a/frontend/src/components/pages/residents/ResidentModal.tsx +++ b/frontend/src/components/pages/residents/ResidentModal.tsx @@ -13,69 +13,13 @@ import VisibilityIcon from "@mui/icons-material/Visibility"; import VisibilityOffIcon from "@mui/icons-material/VisibilityOff"; import ModalContainer from "../../common/ModalContainer"; +import FormField from "../../common/FormField"; type Props = { isOpen: boolean; setIsOpen: React.Dispatch>; }; -const FormField = ({ - label, - value, - type = "text", - onChange, - submitPressed, - required = false, - isPassword = false, - showPassword, - setShowPassword, -}: { - label: string; - value: string; - type?: string; - onChange: (e: React.ChangeEvent) => void; - submitPressed: boolean; - required?: boolean; - isPassword?: boolean; - showPassword?: boolean; - setShowPassword?: React.Dispatch>; -}) => ( - - - - {label} - - - - {isPassword && setShowPassword && ( - - - - )} - - - -); - const ResidentModal = ({ isOpen, setIsOpen }: Props): React.ReactElement => { const [firstName, setFirstName] = useState(""); const [lastName, setLastName] = useState(""); diff --git a/frontend/src/components/pages/tasks/TaskModal.tsx b/frontend/src/components/pages/tasks/TaskModal.tsx index d70e9a3a..8f2a91ed 100644 --- a/frontend/src/components/pages/tasks/TaskModal.tsx +++ b/frontend/src/components/pages/tasks/TaskModal.tsx @@ -15,75 +15,15 @@ import { import VisibilityIcon from "@mui/icons-material/Visibility"; import VisibilityOffIcon from "@mui/icons-material/VisibilityOff"; import { TbTrash } from "react-icons/tb"; -import 'dayjs/locale/de'; import ModalContainer from "../../common/ModalContainer"; +import FormField from "../../common/FormField"; type Props = { isOpen: boolean; setIsOpen: React.Dispatch>; }; -const FormField = ({ - label, - value, - type = "text", - onChange, - onBlur, - submitPressed, - required = false, - isPassword = false, - showPassword, - setShowPassword, -}: { - label: string; - value: string; - type?: string; - onChange: (e: React.ChangeEvent) => void; - onBlur?: () => void; - submitPressed: boolean; - required?: boolean; - isPassword?: boolean; - showPassword?: boolean; - setShowPassword?: React.Dispatch>; -}) => ( - - - - {label} - - - - {isPassword && setShowPassword && ( - - - - )} - - - -); - const generateOptions = () => { const options = []; for (let hour = 0; hour < 24; hour+=1) { @@ -177,6 +117,7 @@ const DateInput = ({ w="200px" isChecked={isAllDay} onChange={(e) => setIsAllDay(e.target.checked)} + m={0} > All Day @@ -207,7 +148,7 @@ const TaskModal = ({ isOpen, setIsOpen }: Props): React.ReactElement => { const [dueTime, setDueTime] = useState(""); const [isAllDay, setIsAllDay] = useState(false); const [recurrenceFrequency, setRecurrenceFrequency] = useState(""); - const [marillacBucks, setMarillacBucks] = useState('$ '); + const [marillacBucks, setMarillacBucks] = useState(''); const [submitPressed, setSubmitPressed] = useState(false); @@ -226,7 +167,7 @@ const TaskModal = ({ isOpen, setIsOpen }: Props): React.ReactElement => { setDueTime(""); setIsAllDay(false); setRecurrenceFrequency(""); - setMarillacBucks("$"); + setMarillacBucks(""); setSubmitPressed(false); }; @@ -236,7 +177,7 @@ const TaskModal = ({ isOpen, setIsOpen }: Props): React.ReactElement => { if (inputValue) { const numberValue = parseFloat(inputValue).toFixed(2); - setMarillacBucks(`$${numberValue}`); + setMarillacBucks(numberValue); } }; @@ -255,10 +196,12 @@ const TaskModal = ({ isOpen, setIsOpen }: Props): React.ReactElement => { submitPressed={submitPressed} required /> - - Location - + + + Location + + setDueDate(e.target.value)} - /> - - at - - - - - setIsAllDay(e.target.checked)} - m={0} - > - All Day - - + return ( + + + + Due Date + + + + setDueDate(e.target.value)} + /> + + at + + + + + setIsAllDay(e.target.checked)} + m={0} + > + All Day + + + - - - -); + + + ); }; const TaskModal = ({ isOpen, setIsOpen }: Props): React.ReactElement => { @@ -148,7 +141,7 @@ const TaskModal = ({ isOpen, setIsOpen }: Props): React.ReactElement => { const [dueTime, setDueTime] = useState(""); const [isAllDay, setIsAllDay] = useState(false); const [recurrenceFrequency, setRecurrenceFrequency] = useState(""); - const [marillacBucks, setMarillacBucks] = useState(''); + const [marillacBucks, setMarillacBucks] = useState(""); const [submitPressed, setSubmitPressed] = useState(false); @@ -173,8 +166,8 @@ const TaskModal = ({ isOpen, setIsOpen }: Props): React.ReactElement => { }; const handleMoneyInput = () => { - const inputValue = marillacBucks.replace(/[^0-9.]/g, ''); // Remove non-numeric and non-period characters - + const inputValue = marillacBucks.replace(/[^0-9.]/g, ""); // Remove non-numeric and non-period characters + if (inputValue) { const numberValue = parseFloat(inputValue).toFixed(2); setMarillacBucks(numberValue); @@ -182,12 +175,15 @@ const TaskModal = ({ isOpen, setIsOpen }: Props): React.ReactElement => { }; // delete task api stuff - const handleDelete = () => { - - } + const handleDelete = () => {}; return ( - + { Cancel