diff --git a/frontend/src/components/CostEstimate/index.js b/frontend/src/components/CostEstimate/index.js
index 11141fda..59b5e437 100644
--- a/frontend/src/components/CostEstimate/index.js
+++ b/frontend/src/components/CostEstimate/index.js
@@ -23,6 +23,8 @@ export const CostEstimateCollapsed = () => {
};
export const CostEstimateFull = () => {
+ var isUrgent = false;
+ var urgentMultiplier = 1.5;
const dispatch = useDispatch();
const costEstimateMap = useSelector(
(state) => state.costEstimateReducer.costEstimateList
@@ -30,6 +32,13 @@ export const CostEstimateFull = () => {
const formResponses = useSelector((state) => state.formReducer.formResponses);
let costSum = 0;
+ formResponses.some((response) => {
+ if (response.question.question_type === "urgent") {
+ isUrgent = response.question.answer === "Yes" ? true : false;
+ }
+ return null;
+ });
+
return (
{
{formResponses.map((response) => {
- const cost = costEstimateMap.get(response.question.answer_id);
+ const cost = isUrgent ? urgentMultiplier * costEstimateMap.get(response.question.answer_id) : costEstimateMap.get(response.question.answer_id);
let quantity = response.quantity ?? 1;
costSum += cost * quantity;
return (
diff --git a/frontend/src/components/DragAndDrop/component-sideview-dnd-data.js b/frontend/src/components/DragAndDrop/component-sideview-dnd-data.js
index 73393aed..f9ba12ef 100644
--- a/frontend/src/components/DragAndDrop/component-sideview-dnd-data.js
+++ b/frontend/src/components/DragAndDrop/component-sideview-dnd-data.js
@@ -105,6 +105,15 @@ export const ProjectSelectorCard = () => {
);
};
+export const UrgentCard = () => {
+ return (
+
+
+ Urgent Request
+
+ );
+};
+
export const componentsSideViewData = {
components: {
multi: {
@@ -147,12 +156,16 @@ export const componentsSideViewData = {
id: "project",
component: ProjectSelectorCard,
},
+ urgent: {
+ id: "urgent",
+ component: UrgentCard,
+ },
},
sections: {
"question-elements": {
id: "question-elements",
title: "Question Elements",
- componentIds: ["multi", "single", "text", "dropdown"],
+ componentIds: ["multi", "single", "text", "dropdown", "urgent"],
},
"layout-elements": {
id: "layout-elements",
diff --git a/frontend/src/components/FormBuilder/index.js b/frontend/src/components/FormBuilder/index.js
index a9cc40dd..7ad323ef 100644
--- a/frontend/src/components/FormBuilder/index.js
+++ b/frontend/src/components/FormBuilder/index.js
@@ -1,5 +1,5 @@
import "./index.css";
-import { useSelector } from "react-redux";
+import { useSelector, useDispatch } from "react-redux";
import { appColor } from "../../constants";
import DropdownEditor from "../Dropdown/DropdownEditor";
import FileInputEditor from "../FileInput/FileInputEditor";
@@ -7,6 +7,7 @@ import TextAnswerEditor from "../TextAnswer/TextAnswerEditor";
import MultiSelectEditor from "../MultiSelect/MultiSelectEditor";
import ContactInfoEditor from "../ContactInfo/ContactInfoEditor";
import SingleSelectEditor from "../SingleSelect/SingleSelectEditor";
+import UrgentEditor from "../Urgent/UrgentEditor";
import FormTitle from "./FormTitle";
import HeadingEditor from "../Heading/HeadingEditor";
import FileDownloadEditor from "../FileDownload/FileDownloadEditor";
@@ -58,15 +59,20 @@ function renderQuestion(question) {
return
;
case "project":
return
;
+ case "urgent":
+ return
;
default:
return null;
}
}
function FormBuilder() {
+ const dispatch = useDispatch();
+
const questionList = useSelector(
(state) => state.questionReducer.questionList
);
+
const selectedQuestion = useSelector(
(state) => state.logicReducer.currentLogicQuestion
);
@@ -160,6 +166,7 @@ function FormBuilder() {
)}
{provided.placeholder}
+
)}
diff --git a/frontend/src/components/SingleSelect/index.js b/frontend/src/components/SingleSelect/index.js
index a573e045..9e34466f 100644
--- a/frontend/src/components/SingleSelect/index.js
+++ b/frontend/src/components/SingleSelect/index.js
@@ -63,6 +63,7 @@ function SingleSelect({ question }) {
question: option,
},
});
+ console.log(option)
dispatch({
type: ADD_RESPONSE,
payload: {
diff --git a/frontend/src/components/Urgent/UrgentEditor/index.css b/frontend/src/components/Urgent/UrgentEditor/index.css
new file mode 100644
index 00000000..db92e5dc
--- /dev/null
+++ b/frontend/src/components/Urgent/UrgentEditor/index.css
@@ -0,0 +1,49 @@
+.question-cancel-button{
+ font-size: 18px;
+ /* text-align: center; */
+ background: transparent;
+ border: none;
+ align-self: right;
+}
+
+.single-select-option{
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ width: 100%;
+}
+.single-select-option-delete{
+ height: 50%;
+}
+
+.single-select-options-container{
+ display: flex;
+ margin-top: 2%;
+ margin-bottom: 2%;
+ width: 100%;
+ padding-left: 5px;
+ padding-right: 5px;
+}
+
+.new-question-input-container {
+ display: flex;
+ margin:none;
+ padding:none;
+ justify-content: left;
+ align-items: center;
+ width: 100%;
+}
+
+.new-question-input {
+ display: flex;
+ border: none;
+ width: 100%;
+}
+
+.new-question-input:focus{
+ outline: none;
+}
+
+.new-question-checkbox{
+ width: 30px;
+}
\ No newline at end of file
diff --git a/frontend/src/components/Urgent/UrgentEditor/index.js b/frontend/src/components/Urgent/UrgentEditor/index.js
new file mode 100644
index 00000000..03809a7c
--- /dev/null
+++ b/frontend/src/components/Urgent/UrgentEditor/index.js
@@ -0,0 +1,176 @@
+import "./index.css";
+import "../../index.css";
+import { useEffect, useState } from "react";
+import Radio from "@mui/material/Radio";
+import RadioGroup from "@mui/material/RadioGroup";
+import FormControlLabel from "@mui/material/FormControlLabel";
+import FormControl from "@mui/material/FormControl";
+import X from "../../../assets/X.png";
+import DragDots from "../../../assets/DragDots.png";
+import { useDispatch, useSelector } from "react-redux";
+import uuid from "react-uuid";
+import {
+ DELETE_ANSWER,
+ DELETE_QUESTION,
+ LOAD_QUESTION,
+ SAVE_ANSWER,
+ SAVE_QUESTION,
+} from "../../../redux/actions/questionActions";
+import { SET_LOGIC_QUESTION } from "../../../redux/actions/logicActions";
+import EditComponentFooter from "../../EditComponentFooter";
+
+function UrgentEditor({ question }) {
+ const dispatch = useDispatch();
+ const questionList = useSelector(
+ (state) => state.questionReducer.questionList
+ );
+
+ const [options, setOptions] = useState([]);
+ const answerList = useSelector((state) => state.questionReducer.answerList);
+
+ const [questionNum, setQuestionNum] = useState("");
+ const [title, setTitle] = useState("");
+
+ useEffect(() => {
+ setQuestionNum(`Q${question.position_index}`);
+ setTitle("Is this request urgent?");
+ }, [question]);
+
+ useEffect(() => {
+ var optionList = answerList[question.question_id ?? ""] ?? [];
+ optionList = optionList.sort((a, b) => {
+ let fa = a.answer;
+ let fb = b.answer;
+
+ if (fa < fb) {
+ return -1;
+ }
+ if (fa > fb) {
+ return 1;
+ }
+ return 0;
+ });
+ optionList = optionList.filter((option) => option !== "");
+ optionList.push("");
+ optionList.unshift({answer_id: uuid(), answer: "No"});
+ optionList.unshift({answer_id: uuid(), answer: "Yes"});
+ setOptions(optionList);
+ }, [answerList, question]);
+
+ return (
+
+
+
{
+ dispatch({
+ type: SET_LOGIC_QUESTION,
+ payload: question,
+ });
+ }}
+ >
+ {questionNum}
+
+
setTitle(event.target.value)}
+ onBlur={() => {
+ dispatch({
+ type: SAVE_QUESTION,
+ payload: {
+ ...question,
+ form_id: question.fk_form_id,
+ question_title: title, //text.target.value,
+ question_index: question.position_index,
+ },
+ });
+ dispatch({ type: LOAD_QUESTION, payload: question.fk_form_id });
+ }}
+ />
+
{
+ questionList.forEach((questionObj) => {
+ if (questionObj.position_index >= question.position_index) {
+ questionObj.question_index = questionObj.position_index - 1;
+ questionObj.question_title = questionObj.question;
+ questionObj.form_id = questionObj.fk_form_id;
+ dispatch({ type: SAVE_QUESTION, payload: questionObj });
+ }
+ });
+ dispatch({
+ type: DELETE_QUESTION,
+ payload: {
+ question_id: question.question_id,
+ },
+ });
+ dispatch({ type: LOAD_QUESTION, payload: question.fk_form_id });
+ }}
+ />
+
+ {/* Copy Everything Except Content Below For Reusability */}
+
+
+
+
+ {options.map((option, index) => {
+ return (
+
+ } />
+ {
+ const answerVal = e.target.value;
+ if (answerVal.trim() !== "") {
+ dispatch({
+ type: SAVE_ANSWER,
+ payload: {
+ answer_id: option.answer_id ?? uuid(),
+ fk_question_id: question.question_id,
+ question_type: question.question_type,
+ answer: answerVal,
+ form_id: question.fk_form_id,
+ },
+ });
+ } else {
+ dispatch({
+ type: DELETE_ANSWER,
+ payload: {
+ answer_id: option.answer_id,
+ form_id: question.fk_form_id,
+ },
+ });
+ }
+ setOptions([]);
+ }}
+ // If we want to have key down functionality as well:
+ onKeyDown={(e) => {
+ if (e.key === "Enter") {
+ e.target.blur();
+ }
+ }}
+ />
+
+ );
+ })}
+
+
+
+ {/* Copy Everything Except Content Above For Reusability */}
+
+
+ );
+}
+
+export default UrgentEditor;
diff --git a/frontend/src/components/Urgent/index.css b/frontend/src/components/Urgent/index.css
new file mode 100644
index 00000000..db92e5dc
--- /dev/null
+++ b/frontend/src/components/Urgent/index.css
@@ -0,0 +1,49 @@
+.question-cancel-button{
+ font-size: 18px;
+ /* text-align: center; */
+ background: transparent;
+ border: none;
+ align-self: right;
+}
+
+.single-select-option{
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ width: 100%;
+}
+.single-select-option-delete{
+ height: 50%;
+}
+
+.single-select-options-container{
+ display: flex;
+ margin-top: 2%;
+ margin-bottom: 2%;
+ width: 100%;
+ padding-left: 5px;
+ padding-right: 5px;
+}
+
+.new-question-input-container {
+ display: flex;
+ margin:none;
+ padding:none;
+ justify-content: left;
+ align-items: center;
+ width: 100%;
+}
+
+.new-question-input {
+ display: flex;
+ border: none;
+ width: 100%;
+}
+
+.new-question-input:focus{
+ outline: none;
+}
+
+.new-question-checkbox{
+ width: 30px;
+}
\ No newline at end of file
diff --git a/frontend/src/components/Urgent/index.js b/frontend/src/components/Urgent/index.js
new file mode 100644
index 00000000..ea932ea5
--- /dev/null
+++ b/frontend/src/components/Urgent/index.js
@@ -0,0 +1,103 @@
+import "./index.css";
+import "../index.css";
+import { useEffect, useState } from "react";
+import Radio from "@mui/material/Radio";
+import RadioGroup from "@mui/material/RadioGroup";
+import FormControlLabel from "@mui/material/FormControlLabel";
+import FormControl from "@mui/material/FormControl";
+import { useDispatch, useSelector } from "react-redux";
+import Divider from "../Divider";
+import {
+ ADD_RESPONSE,
+ REMOVE_SINGLE_RESPONSE,
+} from "../../redux/actions/formActions";
+import uuid from "react-uuid";
+
+function Urgent({ question }) {
+ const dispatch = useDispatch();
+ const [options, setOptions] = useState([]);
+ const answerList = useSelector((state) => state.questionReducer.answerList);
+
+ useEffect(() => {
+ var optionList = answerList[question.question_id ?? ""] ?? [];
+ optionList = optionList.sort((a, b) => {
+ let fa = a.answer;
+ let fb = b.answer;
+ if (fa < fb) {
+ return -1;
+ }
+ if (fa > fb) {
+ return 1;
+ }
+ return 0;
+ });
+ optionList = optionList.filter((option) => option !== "");
+ optionList.unshift({question_id: question.question_id,
+ fk_form_id: question.fk_form_id,
+ question_type: 'urgent',
+ question: 'Is this request urgent?',
+ answer_id: uuid(),
+ answer: "No"});
+ optionList.unshift({question_id: question.question_id,
+ fk_form_id: question.fk_form_id,
+ question_type: 'urgent',
+ question: 'Is this request urgent?',
+ answer_id: uuid(),
+ answer: "Yes"});
+ setOptions(optionList);
+ }, [answerList, question]);
+
+ return (
+
+
+ {"Is this request urgent?"}
+
{question.mandatory ? "*" : ""}
+
+
+
+
+ {options.map((option, index) => {
+ return (
+
+
{
+ if (e.target.checked) {
+ dispatch({
+ type: REMOVE_SINGLE_RESPONSE,
+ payload: {
+ question: option,
+ },
+ });
+ console.log(option)
+ dispatch({
+ type: ADD_RESPONSE,
+ payload: {
+ id: uuid(),
+ response: option.answer_id,
+ question: option,
+ },
+ });
+ }
+ }}
+ />
+ }
+ />
+ {option.answer}
+
+ );
+ })}
+
+
+
+
+
+ );
+}
+
+export default Urgent;
diff --git a/frontend/src/screens/request-form/complete-request-form.js b/frontend/src/screens/request-form/complete-request-form.js
index 2afde2ed..32dfe2b6 100644
--- a/frontend/src/screens/request-form/complete-request-form.js
+++ b/frontend/src/screens/request-form/complete-request-form.js
@@ -5,6 +5,7 @@ import { appColor } from "../../constants";
import { LOAD_QUESTION } from "../../redux/actions/questionActions";
import { LOAD_COST } from "../../redux/actions/costActions";
import MultiSelect from "../../components/MultiSelect";
+import Urgent from "../../components/Urgent";
import SingleSelect from "../../components/SingleSelect";
import TextAnswer from "../../components/TextAnswer";
import Dropdown from "../../components/Dropdown";
@@ -57,6 +58,8 @@ function RequestForm() {
return
;
case "contact":
return
;
+ case "urgent":
+ return
;
default:
return null;
}
diff --git a/frontend/src/screens/request-form/request-form.js b/frontend/src/screens/request-form/request-form.js
index 6be7f648..eab18d5b 100644
--- a/frontend/src/screens/request-form/request-form.js
+++ b/frontend/src/screens/request-form/request-form.js
@@ -3,10 +3,11 @@ import { useDispatch, useSelector } from "react-redux";
import { Navigate } from "react-router-dom";
import "./request-form.css";
import { appColor } from "../../constants";
-import { LOAD_QUESTION } from "../../redux/actions/questionActions";
+import { LOAD_QUESTION} from "../../redux/actions/questionActions";
import { LOAD_COST } from "../../redux/actions/costActions";
import MultiSelect from "../../components/MultiSelect";
import SingleSelect from "../../components/SingleSelect";
+import Urgent from "../../components/Urgent";
import TextAnswer from "../../components/TextAnswer";
import Dropdown from "../../components/Dropdown";
import Heading from "../../components/Heading";
@@ -70,6 +71,8 @@ function RequestForm() {
return
;
case "project":
return
;
+ case "urgent":
+ return
;
default:
return null;
}
@@ -78,6 +81,8 @@ function RequestForm() {
// Basic Form Validation and Submit
function submitForm() {
var filled = true;
+ var isUrgent = false;
+ var urgentMultiplier = 1.5;
questions.forEach((question) => {
if (
question.mandatory &&
@@ -101,6 +106,12 @@ function RequestForm() {
? projectItem[0].response
: "PROJECTID-A";
const billableList = [];
+ formResponses.some((response) => {
+ if (response.question.question_type === "urgent") {
+ isUrgent = response.question.answer === "Yes" ? true : false;
+ }
+ return null;
+ });
formResponses.map((response) => {
const cost = costEstimateMap.get(response.question.answer_id);
let quantity = response.quantity ?? 1;
@@ -109,7 +120,7 @@ function RequestForm() {
billableList.push({
service: service,
quantity: quantity,
- cost: cost * quantity,
+ cost: isUrgent? cost * quantity * urgentMultiplier : cost * quantity,
});
} else {
// This question's cost not in current stored cost estimate