From 46ec28937ec0d3aba963de0f7db8695cae598acc Mon Sep 17 00:00:00 2001 From: JavidSumra Date: Fri, 8 Nov 2024 16:12:31 +0530 Subject: [PATCH 01/18] Update Resource Forms to Enhance Validation --- .../Form/FormFields/TextFormField.tsx | 4 +++ src/components/Resource/ResourceCreate.tsx | 2 ++ .../Resource/ResourceDetailsUpdate.tsx | 34 ++++++++++++++----- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/components/Form/FormFields/TextFormField.tsx b/src/components/Form/FormFields/TextFormField.tsx index c104b09feaa..c6d7437ec98 100644 --- a/src/components/Form/FormFields/TextFormField.tsx +++ b/src/components/Form/FormFields/TextFormField.tsx @@ -29,6 +29,8 @@ export type TextFormFieldProps = FormFieldBaseProps & trailingPadding?: string | undefined; leadingPadding?: string | undefined; suggestions?: string[]; + min?: number | string; + max?: number | string; clearable?: boolean | undefined; }; @@ -63,6 +65,8 @@ const TextFormField = forwardRef((props: TextFormFieldProps, ref) => { type={props.type === "password" ? getPasswordFieldType() : props.type} name={field.name} value={field.value} + min={Number(props?.min)} + max={Number(props?.max)} required={field.required} onChange={(e) => field.handleChange(e.target.value)} /> diff --git a/src/components/Resource/ResourceCreate.tsx b/src/components/Resource/ResourceCreate.tsx index 078b2f84c0c..05072d94ca1 100644 --- a/src/components/Resource/ResourceCreate.tsx +++ b/src/components/Resource/ResourceCreate.tsx @@ -300,6 +300,8 @@ export default function ResourceCreate(props: resourceProps) { diff --git a/src/components/Resource/ResourceDetailsUpdate.tsx b/src/components/Resource/ResourceDetailsUpdate.tsx index 766cdc5775e..1dc4360cdd2 100644 --- a/src/components/Resource/ResourceDetailsUpdate.tsx +++ b/src/components/Resource/ResourceDetailsUpdate.tsx @@ -48,9 +48,15 @@ const requiredFields: any = { approving_facility_object: { errorText: "Resource approving facility can not be empty.", }, - assigned_facility_type: { + assigned_facility_object: { errorText: "Please Select Facility Type", }, + title: { + errorText: "Title is required.", + }, + reason: { + errorText: "Description is required.", + }, }; const initError = Object.assign( @@ -101,7 +107,15 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { const errors = { ...initError }; let isInvalidForm = false; Object.keys(requiredFields).forEach((field) => { - if (!state.form[field] || !state.form[field].length) { + if ( + field === "approving_facility_object" || + field === "assigned_facility_object" + ) { + if (!state.form[field] || !state.form[field]?.name) { + errors[field] = requiredFields[field].errorText; + isInvalidForm = true; + } + } else if (!state.form[field] || state.form[field].trim().length === 0) { errors[field] = requiredFields[field].errorText; isInvalidForm = true; } @@ -144,7 +158,7 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { }); const handleSubmit = async () => { - const validForm = validateForm(); + const validForm = !validateForm(); if (validForm) { setIsLoading(true); @@ -233,7 +247,7 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { setSelected={(obj) => setFacility(obj, "approving_facility_object") } - errors={state.errors.approving_facility} + errors={state.errors.approving_facility_object} /> @@ -243,13 +257,13 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { setFacility(obj, "assigned_facility_object") } - errors={state.errors.assigned_facility} + errors={state.errors.assigned_facility_object} />
@@ -257,6 +271,7 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { label="Required Quantity" name="requested_quantity" type="number" + min={1} value={state.form.requested_quantity} onChange={handleChange} /> @@ -265,6 +280,7 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { {
@@ -291,8 +308,9 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { placeholder="Type your description here" value={state.form.reason} onChange={handleChange} - label="Description of request*" + label="Description of request" error={state.errors.reason} + required /> From 9256e70980d89160619c3e449fae15838aec26f6 Mon Sep 17 00:00:00 2001 From: JavidSumra Date: Sat, 9 Nov 2024 09:40:05 +0530 Subject: [PATCH 02/18] fix resource update test suit --- cypress/e2e/resource_spec/ResourcesHomepage.cy.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cypress/e2e/resource_spec/ResourcesHomepage.cy.ts b/cypress/e2e/resource_spec/ResourcesHomepage.cy.ts index 8dc526a68c3..07d8b550676 100644 --- a/cypress/e2e/resource_spec/ResourcesHomepage.cy.ts +++ b/cypress/e2e/resource_spec/ResourcesHomepage.cy.ts @@ -1,6 +1,6 @@ +import FacilityPage from "../../pageobject/Facility/FacilityCreation"; import LoginPage from "../../pageobject/Login/LoginPage"; import ResourcePage from "../../pageobject/Resource/ResourcePage"; -import FacilityPage from "../../pageobject/Facility/FacilityCreation"; describe("Resource Page", () => { let createdResource: string; @@ -68,6 +68,10 @@ describe("Resource Page", () => { cy.visit(createdResource); resourcePage.clickUpdateStatus(); resourcePage.updateStatus("APPROVED"); + cy.clickAndSelectOption( + "input[name='assigned_facility_object']", + "Dummy Request Fulfilment Center, Ernakulam", + ); resourcePage.clickSubmitButton(); resourcePage.verifySuccessNotification( "Resource request updated successfully", From 9d3a9ba85850c37f4231aeefd867add2a9b23a09 Mon Sep 17 00:00:00 2001 From: JavidSumra Date: Tue, 19 Nov 2024 12:39:29 +0530 Subject: [PATCH 03/18] Updated Handle Input to avoid Negative Value --- src/Utils/utils.ts | 14 ++++++++++++++ src/components/Form/FormFields/TextFormField.tsx | 4 ++-- src/components/Resource/ResourceCreate.tsx | 3 ++- src/components/Resource/ResourceDetailsUpdate.tsx | 3 +++ 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/Utils/utils.ts b/src/Utils/utils.ts index 3888406ad29..c87b8653c8e 100644 --- a/src/Utils/utils.ts +++ b/src/Utils/utils.ts @@ -544,3 +544,17 @@ export const fahrenheitToCelsius = (fahrenheit: number) => { export const keysOf = (obj: T) => { return Object.keys(obj) as (keyof T)[]; }; + +export const handleNegativeValue = ( + event: React.FormEvent, +): void => { + const input = event.currentTarget; + + // Remove all instances of '-' from the input value + input.value = input.value.replace(/-/g, ""); + + // Optional: Ensure the input value is a valid number + if (isNaN(Number(input.value))) { + input.value = ""; // Reset to empty if input is not a number + } +}; diff --git a/src/components/Form/FormFields/TextFormField.tsx b/src/components/Form/FormFields/TextFormField.tsx index c6d7437ec98..e14b4a2558e 100644 --- a/src/components/Form/FormFields/TextFormField.tsx +++ b/src/components/Form/FormFields/TextFormField.tsx @@ -65,8 +65,8 @@ const TextFormField = forwardRef((props: TextFormFieldProps, ref) => { type={props.type === "password" ? getPasswordFieldType() : props.type} name={field.name} value={field.value} - min={Number(props?.min)} - max={Number(props?.max)} + min={Number(props?.min || Number.MIN_SAFE_INTEGER)} + max={Number(props?.max || Number.MAX_SAFE_INTEGER)} required={field.required} onChange={(e) => field.handleChange(e.target.value)} /> diff --git a/src/components/Resource/ResourceCreate.tsx b/src/components/Resource/ResourceCreate.tsx index 05072d94ca1..6fd4e73077b 100644 --- a/src/components/Resource/ResourceCreate.tsx +++ b/src/components/Resource/ResourceCreate.tsx @@ -30,7 +30,7 @@ import * as Notification from "@/Utils/Notifications"; import routes from "@/Utils/request/api"; import request from "@/Utils/request/request"; import useQuery from "@/Utils/request/useQuery"; -import { parsePhoneNumber } from "@/Utils/utils"; +import { handleNegativeValue, parsePhoneNumber } from "@/Utils/utils"; interface resourceProps { facilityId: number; @@ -304,6 +304,7 @@ export default function ResourceCreate(props: resourceProps) { min={1} value={state.form.required_quantity} onChange={handleChange} + onInput={handleNegativeValue} />
diff --git a/src/components/Resource/ResourceDetailsUpdate.tsx b/src/components/Resource/ResourceDetailsUpdate.tsx index 1dc4360cdd2..8c1253ffece 100644 --- a/src/components/Resource/ResourceDetailsUpdate.tsx +++ b/src/components/Resource/ResourceDetailsUpdate.tsx @@ -25,6 +25,7 @@ import * as Notification from "@/Utils/Notifications"; import routes from "@/Utils/request/api"; import request from "@/Utils/request/request"; import useQuery from "@/Utils/request/useQuery"; +import { handleNegativeValue } from "@/Utils/utils"; interface resourceProps { id: string; @@ -274,6 +275,7 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { min={1} value={state.form.requested_quantity} onChange={handleChange} + onInput={handleNegativeValue} />
@@ -285,6 +287,7 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { value={state.form.assigned_quantity} onChange={handleChange} disabled={state.form.status !== "PENDING"} + onInput={handleNegativeValue} />
From a5d862deb05097411f86d51b491fe365f8b1fee7 Mon Sep 17 00:00:00 2001 From: JavidSumra Date: Tue, 19 Nov 2024 12:58:18 +0530 Subject: [PATCH 04/18] Remove Unnecessary Comments --- src/Utils/utils.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Utils/utils.ts b/src/Utils/utils.ts index c87b8653c8e..839cf9a73d9 100644 --- a/src/Utils/utils.ts +++ b/src/Utils/utils.ts @@ -549,12 +549,8 @@ export const handleNegativeValue = ( event: React.FormEvent, ): void => { const input = event.currentTarget; - - // Remove all instances of '-' from the input value input.value = input.value.replace(/-/g, ""); - - // Optional: Ensure the input value is a valid number if (isNaN(Number(input.value))) { - input.value = ""; // Reset to empty if input is not a number + input.value = ""; } }; From de7d8291a2754daa714de36a18fa398d5f4a3c8f Mon Sep 17 00:00:00 2001 From: JavidSumra Date: Thu, 21 Nov 2024 11:02:56 +0530 Subject: [PATCH 05/18] Add Requested Changes --- src/Utils/utils.ts | 7 ++----- src/components/Form/FormFields/TextFormField.tsx | 4 ---- src/components/Resource/ResourceCreate.tsx | 4 ++-- src/components/Resource/ResourceDetailsUpdate.tsx | 6 +++--- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/Utils/utils.ts b/src/Utils/utils.ts index 839cf9a73d9..d2fcfda5351 100644 --- a/src/Utils/utils.ts +++ b/src/Utils/utils.ts @@ -545,12 +545,9 @@ export const keysOf = (obj: T) => { return Object.keys(obj) as (keyof T)[]; }; -export const handleNegativeValue = ( +export const sanitizeNumberInput = ( event: React.FormEvent, ): void => { const input = event.currentTarget; - input.value = input.value.replace(/-/g, ""); - if (isNaN(Number(input.value))) { - input.value = ""; - } + input.value = input.value.replace(/[^0-9]/g, ""); }; diff --git a/src/components/Form/FormFields/TextFormField.tsx b/src/components/Form/FormFields/TextFormField.tsx index e83cf6fb7fd..fd948e0a264 100644 --- a/src/components/Form/FormFields/TextFormField.tsx +++ b/src/components/Form/FormFields/TextFormField.tsx @@ -32,8 +32,6 @@ export type TextFormFieldProps = FormFieldBaseProps & trailingPadding?: string | undefined; leadingPadding?: string | undefined; suggestions?: string[]; - min?: number | string; - max?: number | string; clearable?: boolean | undefined; }; @@ -102,8 +100,6 @@ const TextFormField = forwardRef((props: TextFormFieldProps, ref) => { type={props.type === "password" ? getPasswordFieldType() : props.type} name={field.name} value={field.value} - min={Number(props?.min || Number.MIN_SAFE_INTEGER)} - max={Number(props?.max || Number.MAX_SAFE_INTEGER)} required={field.required} onChange={(e) => field.handleChange(e.target.value)} /> diff --git a/src/components/Resource/ResourceCreate.tsx b/src/components/Resource/ResourceCreate.tsx index 6fd4e73077b..ace9ff3b677 100644 --- a/src/components/Resource/ResourceCreate.tsx +++ b/src/components/Resource/ResourceCreate.tsx @@ -30,7 +30,7 @@ import * as Notification from "@/Utils/Notifications"; import routes from "@/Utils/request/api"; import request from "@/Utils/request/request"; import useQuery from "@/Utils/request/useQuery"; -import { handleNegativeValue, parsePhoneNumber } from "@/Utils/utils"; +import { parsePhoneNumber, sanitizeNumberInput } from "@/Utils/utils"; interface resourceProps { facilityId: number; @@ -304,7 +304,7 @@ export default function ResourceCreate(props: resourceProps) { min={1} value={state.form.required_quantity} onChange={handleChange} - onInput={handleNegativeValue} + onInput={sanitizeNumberInput} />
diff --git a/src/components/Resource/ResourceDetailsUpdate.tsx b/src/components/Resource/ResourceDetailsUpdate.tsx index 8c1253ffece..1aac55c4652 100644 --- a/src/components/Resource/ResourceDetailsUpdate.tsx +++ b/src/components/Resource/ResourceDetailsUpdate.tsx @@ -25,7 +25,7 @@ import * as Notification from "@/Utils/Notifications"; import routes from "@/Utils/request/api"; import request from "@/Utils/request/request"; import useQuery from "@/Utils/request/useQuery"; -import { handleNegativeValue } from "@/Utils/utils"; +import { sanitizeNumberInput } from "@/Utils/utils"; interface resourceProps { id: string; @@ -275,7 +275,7 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { min={1} value={state.form.requested_quantity} onChange={handleChange} - onInput={handleNegativeValue} + onInput={sanitizeNumberInput} />
@@ -287,7 +287,7 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { value={state.form.assigned_quantity} onChange={handleChange} disabled={state.form.status !== "PENDING"} - onInput={handleNegativeValue} + onInput={sanitizeNumberInput} />
From bfaf9ce4c083492ba4ebfb37a16fa69ce4c011e0 Mon Sep 17 00:00:00 2001 From: JavidSumra Date: Tue, 26 Nov 2024 11:03:27 +0530 Subject: [PATCH 06/18] Fix Min Value issue in Resource Create/Update Form --- src/Utils/utils.ts | 3 +++ src/components/Resource/ResourceCreate.tsx | 6 +++--- src/components/Resource/ResourceDetailsUpdate.tsx | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Utils/utils.ts b/src/Utils/utils.ts index d2fcfda5351..329870a3557 100644 --- a/src/Utils/utils.ts +++ b/src/Utils/utils.ts @@ -550,4 +550,7 @@ export const sanitizeNumberInput = ( ): void => { const input = event.currentTarget; input.value = input.value.replace(/[^0-9]/g, ""); + if (parseFloat(input.value || "1") < parseFloat(input?.min || "0")) { + input.value = input?.min || "0"; + } }; diff --git a/src/components/Resource/ResourceCreate.tsx b/src/components/Resource/ResourceCreate.tsx index ace9ff3b677..de04e97d45c 100644 --- a/src/components/Resource/ResourceCreate.tsx +++ b/src/components/Resource/ResourceCreate.tsx @@ -46,7 +46,7 @@ const initForm: any = { reason: "", refering_facility_contact_name: "", refering_facility_contact_number: "+91", - required_quantity: null, + requested_quantity: null, }; const requiredFields: any = { @@ -191,7 +191,7 @@ export default function ResourceCreate(props: resourceProps) { refering_facility_contact_number: parsePhoneNumber( state.form.refering_facility_contact_number, ), - requested_quantity: state.form.requested_quantity || 0, + requested_quantity: state.form.requested_quantity || 1, }; const { res, data } = await request(routes.createResource, { @@ -302,7 +302,7 @@ export default function ResourceCreate(props: resourceProps) { name="requested_quantity" type="number" min={1} - value={state.form.required_quantity} + value={state.form.requested_quantity} onChange={handleChange} onInput={sanitizeNumberInput} /> diff --git a/src/components/Resource/ResourceDetailsUpdate.tsx b/src/components/Resource/ResourceDetailsUpdate.tsx index 1aac55c4652..1d9abc2deb6 100644 --- a/src/components/Resource/ResourceDetailsUpdate.tsx +++ b/src/components/Resource/ResourceDetailsUpdate.tsx @@ -174,11 +174,11 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { title: state.form.title, reason: state.form.reason, assigned_to: state.form.assigned_to, - requested_quantity: state.form.requested_quantity || 0, + requested_quantity: state.form.requested_quantity || 1, assigned_quantity: state.form.status === "PENDING" ? state.form.assigned_quantity - : resourceDetails?.assigned_quantity || 0, + : resourceDetails?.assigned_quantity || 1, }; const { res, data } = await request(routes.updateResource, { From 0dcc5859c15d64456cd7c8e27439c44abc0c7e6c Mon Sep 17 00:00:00 2001 From: JavidSumra Date: Tue, 26 Nov 2024 11:16:13 +0530 Subject: [PATCH 07/18] Fix sanitize function --- src/Utils/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utils/utils.ts b/src/Utils/utils.ts index 329870a3557..e3e61bc9a70 100644 --- a/src/Utils/utils.ts +++ b/src/Utils/utils.ts @@ -550,7 +550,7 @@ export const sanitizeNumberInput = ( ): void => { const input = event.currentTarget; input.value = input.value.replace(/[^0-9]/g, ""); - if (parseFloat(input.value || "1") < parseFloat(input?.min || "0")) { + if (parseFloat(input.value || "1") < parseFloat(input?.min || "1")) { input.value = input?.min || "0"; } }; From 5a0b57f12beb83aad6e7ea125a036bec36f29f93 Mon Sep 17 00:00:00 2001 From: JavidSumra Date: Tue, 26 Nov 2024 11:20:38 +0530 Subject: [PATCH 08/18] Fix Min Value Error issue in Resource Form Fields --- src/Utils/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utils/utils.ts b/src/Utils/utils.ts index e3e61bc9a70..ed1c3ecf065 100644 --- a/src/Utils/utils.ts +++ b/src/Utils/utils.ts @@ -550,7 +550,7 @@ export const sanitizeNumberInput = ( ): void => { const input = event.currentTarget; input.value = input.value.replace(/[^0-9]/g, ""); - if (parseFloat(input.value || "1") < parseFloat(input?.min || "1")) { + if (parseFloat(input.value || "0") < parseFloat(input?.min || "1")) { input.value = input?.min || "0"; } }; From 83d3113c2b39352b61f64c96b98ec448f8c1193b Mon Sep 17 00:00:00 2001 From: JavidSumra Date: Sat, 30 Nov 2024 12:33:30 +0530 Subject: [PATCH 09/18] Fix 0 Value on Resourse Request --- src/Utils/utils.ts | 5 ++++- src/components/Resource/ResourceCreate.tsx | 1 + src/components/Resource/ResourceDetailsUpdate.tsx | 6 +++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Utils/utils.ts b/src/Utils/utils.ts index ed1c3ecf065..b4095908e3a 100644 --- a/src/Utils/utils.ts +++ b/src/Utils/utils.ts @@ -550,7 +550,10 @@ export const sanitizeNumberInput = ( ): void => { const input = event.currentTarget; input.value = input.value.replace(/[^0-9]/g, ""); - if (parseFloat(input.value || "0") < parseFloat(input?.min || "1")) { + if ( + input.value && + parseFloat(input.value || "0") < parseFloat(input?.min || "1") + ) { input.value = input?.min || "0"; } }; diff --git a/src/components/Resource/ResourceCreate.tsx b/src/components/Resource/ResourceCreate.tsx index de04e97d45c..1b3bea923ef 100644 --- a/src/components/Resource/ResourceCreate.tsx +++ b/src/components/Resource/ResourceCreate.tsx @@ -192,6 +192,7 @@ export default function ResourceCreate(props: resourceProps) { state.form.refering_facility_contact_number, ), requested_quantity: state.form.requested_quantity || 1, + assigned_quantity: 1, }; const { res, data } = await request(routes.createResource, { diff --git a/src/components/Resource/ResourceDetailsUpdate.tsx b/src/components/Resource/ResourceDetailsUpdate.tsx index 1d9abc2deb6..93f54b44c6f 100644 --- a/src/components/Resource/ResourceDetailsUpdate.tsx +++ b/src/components/Resource/ResourceDetailsUpdate.tsx @@ -177,7 +177,7 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { requested_quantity: state.form.requested_quantity || 1, assigned_quantity: state.form.status === "PENDING" - ? state.form.assigned_quantity + ? state.form.assigned_quantity || 1 : resourceDetails?.assigned_quantity || 1, }; @@ -273,7 +273,7 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { name="requested_quantity" type="number" min={1} - value={state.form.requested_quantity} + value={state.form.requested_quantity ?? 1} onChange={handleChange} onInput={sanitizeNumberInput} /> @@ -284,7 +284,7 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { type="number" min={1} label="Approved Quantity" - value={state.form.assigned_quantity} + value={state.form.assigned_quantity ?? 1} onChange={handleChange} disabled={state.form.status !== "PENDING"} onInput={sanitizeNumberInput} From 1936cef45da7550c5a501e1e31a097200c025d1a Mon Sep 17 00:00:00 2001 From: JavidSumra Date: Thu, 5 Dec 2024 08:17:24 +0530 Subject: [PATCH 10/18] Fix Approved Quntity Issue --- src/components/Resource/ResourceCreate.tsx | 1 - src/components/Resource/ResourceDetailsUpdate.tsx | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/components/Resource/ResourceCreate.tsx b/src/components/Resource/ResourceCreate.tsx index 1b3bea923ef..de04e97d45c 100644 --- a/src/components/Resource/ResourceCreate.tsx +++ b/src/components/Resource/ResourceCreate.tsx @@ -192,7 +192,6 @@ export default function ResourceCreate(props: resourceProps) { state.form.refering_facility_contact_number, ), requested_quantity: state.form.requested_quantity || 1, - assigned_quantity: 1, }; const { res, data } = await request(routes.createResource, { diff --git a/src/components/Resource/ResourceDetailsUpdate.tsx b/src/components/Resource/ResourceDetailsUpdate.tsx index 93f54b44c6f..26346bcc883 100644 --- a/src/components/Resource/ResourceDetailsUpdate.tsx +++ b/src/components/Resource/ResourceDetailsUpdate.tsx @@ -177,8 +177,8 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { requested_quantity: state.form.requested_quantity || 1, assigned_quantity: state.form.status === "PENDING" - ? state.form.assigned_quantity || 1 - : resourceDetails?.assigned_quantity || 1, + ? state.form.assigned_quantity || 0 + : resourceDetails?.assigned_quantity || 0, }; const { res, data } = await request(routes.updateResource, { @@ -282,9 +282,9 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { Date: Thu, 5 Dec 2024 15:04:42 +0530 Subject: [PATCH 11/18] Fix Validation --- src/Utils/utils.ts | 13 ----- src/components/Resource/ResourceCreate.tsx | 20 ++++++- .../Resource/ResourceDetailsUpdate.tsx | 56 +++++++++++++------ 3 files changed, 56 insertions(+), 33 deletions(-) diff --git a/src/Utils/utils.ts b/src/Utils/utils.ts index b4095908e3a..3888406ad29 100644 --- a/src/Utils/utils.ts +++ b/src/Utils/utils.ts @@ -544,16 +544,3 @@ export const fahrenheitToCelsius = (fahrenheit: number) => { export const keysOf = (obj: T) => { return Object.keys(obj) as (keyof T)[]; }; - -export const sanitizeNumberInput = ( - event: React.FormEvent, -): void => { - const input = event.currentTarget; - input.value = input.value.replace(/[^0-9]/g, ""); - if ( - input.value && - parseFloat(input.value || "0") < parseFloat(input?.min || "1") - ) { - input.value = input?.min || "0"; - } -}; diff --git a/src/components/Resource/ResourceCreate.tsx b/src/components/Resource/ResourceCreate.tsx index de04e97d45c..5efc2c68024 100644 --- a/src/components/Resource/ResourceCreate.tsx +++ b/src/components/Resource/ResourceCreate.tsx @@ -30,7 +30,7 @@ import * as Notification from "@/Utils/Notifications"; import routes from "@/Utils/request/api"; import request from "@/Utils/request/request"; import useQuery from "@/Utils/request/useQuery"; -import { parsePhoneNumber, sanitizeNumberInput } from "@/Utils/utils"; +import { parsePhoneNumber } from "@/Utils/utils"; interface resourceProps { facilityId: number; @@ -74,6 +74,9 @@ const requiredFields: any = { errorText: "Description of resource request is mandatory", invalidText: "Please enter Description of resource request", }, + requested_quantity: { + errorText: "Requested Quantity Can't be Less than 1", + }, }; const initError = Object.assign( @@ -138,6 +141,15 @@ export default function ResourceCreate(props: resourceProps) { } return; } + case "requested_quantity": + if (state.form[field]) { + const value = state.form[field]; + if (!value || parseFloat(value) < 1) { + errors[field] = `Value Can't be Smaller than 1`; + isInvalidForm = true; + } + } + break; default: if (!state.form[field]) { errors[field] = requiredFields[field].errorText; @@ -173,6 +185,8 @@ export default function ResourceCreate(props: resourceProps) { const handleSubmit = async () => { const validForm = validateForm(); + console.log(validForm); + if (validForm) { setIsLoading(true); @@ -302,9 +316,9 @@ export default function ResourceCreate(props: resourceProps) { name="requested_quantity" type="number" min={1} - value={state.form.requested_quantity} + value={state.form.requested_quantity ?? 1} onChange={handleChange} - onInput={sanitizeNumberInput} + error={state.errors.requested_quantity} />
diff --git a/src/components/Resource/ResourceDetailsUpdate.tsx b/src/components/Resource/ResourceDetailsUpdate.tsx index 26346bcc883..da9a3ed3eda 100644 --- a/src/components/Resource/ResourceDetailsUpdate.tsx +++ b/src/components/Resource/ResourceDetailsUpdate.tsx @@ -25,7 +25,6 @@ import * as Notification from "@/Utils/Notifications"; import routes from "@/Utils/request/api"; import request from "@/Utils/request/request"; import useQuery from "@/Utils/request/useQuery"; -import { sanitizeNumberInput } from "@/Utils/utils"; interface resourceProps { id: string; @@ -58,6 +57,12 @@ const requiredFields: any = { reason: { errorText: "Description is required.", }, + requested_quantity: { + errorText: "Requested Quantity Can't be Less than 1", + }, + assigned_quantity: { + errorText: "Approving Quantity Can't be Less than 0", + }, }; const initError = Object.assign( @@ -107,23 +112,40 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { const validateForm = () => { const errors = { ...initError }; let isInvalidForm = false; + Object.keys(requiredFields).forEach((field) => { - if ( - field === "approving_facility_object" || - field === "assigned_facility_object" - ) { - if (!state.form[field] || !state.form[field]?.name) { - errors[field] = requiredFields[field].errorText; - isInvalidForm = true; - } - } else if (!state.form[field] || state.form[field].trim().length === 0) { - errors[field] = requiredFields[field].errorText; - isInvalidForm = true; + switch (field) { + case "approving_facility_object": + case "assigned_facility_object": + if (!state.form[field] || !state.form[field]?.name) { + errors[field] = requiredFields[field].errorText; + isInvalidForm = true; + } + break; + + case "requested_quantity": + case "assigned_quantity": + if (state.form[field]) { + const value = state.form[field]; + const minVal = field === "assigned_quantity" ? 0 : 1; + if (!value || parseFloat(value) < minVal) { + errors[field] = `Value Can't be Smaller than ${minVal}`; + isInvalidForm = true; + } + } + break; + + default: + if (!state.form[field] || state.form[field].trim().length === 0) { + errors[field] = requiredFields[field].errorText; + isInvalidForm = true; + } + break; } }); dispatch({ type: "set_error", errors }); - return isInvalidForm; + return !isInvalidForm; }; const handleChange = (e: FieldChangeEvent) => { @@ -159,8 +181,8 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { }); const handleSubmit = async () => { - const validForm = !validateForm(); - + const validForm = validateForm(); + console.log(validForm); if (validForm) { setIsLoading(true); @@ -275,7 +297,7 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { min={1} value={state.form.requested_quantity ?? 1} onChange={handleChange} - onInput={sanitizeNumberInput} + error={state.errors.requested_quantity} />
@@ -287,7 +309,7 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { value={state.form.assigned_quantity ?? 0} onChange={handleChange} disabled={state.form.status !== "PENDING"} - onInput={sanitizeNumberInput} + error={state.errors.assigned_quantity} />
From 31bc4f1930685f8f695add5f5f8b384b2255f413 Mon Sep 17 00:00:00 2001 From: JavidSumra Date: Thu, 5 Dec 2024 15:32:03 +0530 Subject: [PATCH 12/18] Add Suggestions --- .../Resource/ResourceDetailsUpdate.tsx | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/src/components/Resource/ResourceDetailsUpdate.tsx b/src/components/Resource/ResourceDetailsUpdate.tsx index da9a3ed3eda..24154749cd3 100644 --- a/src/components/Resource/ResourceDetailsUpdate.tsx +++ b/src/components/Resource/ResourceDetailsUpdate.tsx @@ -113,34 +113,33 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { const errors = { ...initError }; let isInvalidForm = false; + const validators = { + facilityValidator: (field: string) => + !state.form[field] || !state.form[field]?.name, + quantityValidator: (field: string) => { + const value = state.form[field]; + const minVal = field === "assigned_quantity" ? 0 : 1; + return !value || parseFloat(value) < minVal; + }, + textValidator: (field: string) => + !state.form[field] || state.form[field].trim().length === 0, + }; + + const fieldTypes = { + facility: ["approving_facility_object", "assigned_facility_object"], + quantity: ["requested_quantity", "assigned_quantity"], + }; + Object.keys(requiredFields).forEach((field) => { - switch (field) { - case "approving_facility_object": - case "assigned_facility_object": - if (!state.form[field] || !state.form[field]?.name) { - errors[field] = requiredFields[field].errorText; - isInvalidForm = true; - } - break; - - case "requested_quantity": - case "assigned_quantity": - if (state.form[field]) { - const value = state.form[field]; - const minVal = field === "assigned_quantity" ? 0 : 1; - if (!value || parseFloat(value) < minVal) { - errors[field] = `Value Can't be Smaller than ${minVal}`; - isInvalidForm = true; - } - } - break; - - default: - if (!state.form[field] || state.form[field].trim().length === 0) { - errors[field] = requiredFields[field].errorText; - isInvalidForm = true; - } - break; + const validator = fieldTypes.facility.includes(field) + ? validators.facilityValidator + : fieldTypes.quantity.includes(field) + ? validators.quantityValidator + : validators.textValidator; + + if (validator(field)) { + errors[field] = requiredFields[field].errorText; + isInvalidForm = true; } }); @@ -182,7 +181,7 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { const handleSubmit = async () => { const validForm = validateForm(); - console.log(validForm); + if (validForm) { setIsLoading(true); From 43c635d43e1be5f1a718ea883ae633537e6bdb82 Mon Sep 17 00:00:00 2001 From: JavidSumra Date: Thu, 5 Dec 2024 16:58:48 +0530 Subject: [PATCH 13/18] Add Translation and Revert to switch case logic --- public/locale/en.json | 14 ++++ src/components/Resource/ResourceCreate.tsx | 27 ++++---- .../Resource/ResourceDetailsUpdate.tsx | 66 ++++++++++--------- 3 files changed, 61 insertions(+), 46 deletions(-) diff --git a/public/locale/en.json b/public/locale/en.json index b5f46dd7308..1d40bf43419 100644 --- a/public/locale/en.json +++ b/public/locale/en.json @@ -326,6 +326,7 @@ "approve": "Approve", "approved_by_district_covid_control_room": "Approved by District COVID Control Room", "approving_facility": "Name of Approving Facility", + "approving_facility_error": "Name of the referring facility is required.", "archive": "Archive", "archived": "Archived", "are_non_editable_fields": "are non-editable fields", @@ -346,6 +347,7 @@ "assign_to_volunteer": "Assign to a Volunteer", "assigned_doctor": "Assigned Doctor", "assigned_facility": "Facility assigned", + "assigned_quantity_error": "Value can't be smaller than 0", "assigned_to": "Assigned to", "assigned_volunteer": "Assigned Volunteer", "async_operation_warning": "This operation may take some time. Please check back later.", @@ -658,6 +660,9 @@ "emergency_contact_person_name_volunteer": "Emergency Contact Person Name (Volunteer)", "emergency_contact_volunteer": "Emergency Contact (Volunteer)", "empty_date_time": "--:-- --; --/--/----", + "empty_description_error": "Description is required field.", + "empty_resource_error": "Resource approving facility cannot be empty.", + "empty_title_error": "Title is required field.", "encounter_date_field_label__A": "Date & Time of Admission to the Facility", "encounter_date_field_label__DC": "Date & Time of Domiciliary Care commencement", "encounter_date_field_label__DD": "Date & Time of Consultation", @@ -1138,10 +1143,12 @@ "ration_card__NO_CARD": "Non-card holder", "ration_card_category": "Ration Card Category", "reason": "Reason", + "reason_error": "Description of the resource request is mandatory.", "reason_for_discontinuation": "Reason for discontinuation", "reason_for_edit": "Reason for edit", "reason_for_referral": "Reason for referral", "reason_for_shift": "Reason for shift", + "reason_invalid": "Please enter a description for the resource request.", "recommended_aspect_ratio_for": "Recommended aspect ratio for", "record": "Record Audio", "record_delete_confirm": "Are you sure you want to delete this record?", @@ -1151,6 +1158,9 @@ "redirected_to_create_consultation": "Note: You will be redirected to create consultation form. Please complete the form to finish the transfer process", "referral_letter": "Referral Letter", "referred_to": "Referred to", + "referring_facility_contact_name_error": "Name of the contact at the referring facility is required.", + "referring_facility_contact_number_error": "Phone number of the contact at the referring facility is required.", + "referring_facility_contact_number_invalid": "Please enter a valid phone number.", "refresh": "Refresh", "refresh_list": "Refresh List", "refuted": "Refuted", @@ -1173,6 +1183,7 @@ "request_sample_test": "Request Sample Test", "request_title": "Request Title", "request_title_placeholder": "Type your title here", + "requested_quantity_error": "Value can't be smaller than 1", "required": "Required", "required_quantity": "Required Quantity", "resend_otp": "Resend OTP", @@ -1226,6 +1237,7 @@ "select_date": "Select date", "select_eligible_policy": "Select an Eligible Insurance Policy", "select_facility_for_discharged_patients_warning": "Facility needs to be selected to view discharged patients.", + "select_facility_type_error": "Please select a facility type.", "select_for_administration": "Select for Administration", "select_groups": "Select Groups", "select_investigation": "Select Investigations (all investigations will be selected by default)", @@ -1314,6 +1326,8 @@ "test_type": "Type of test done", "tested_on": "Tested on", "third_party_software_licenses": "Third Party Software Licenses", + "title_error": "Title for the resource request is mandatory.", + "title_invalid": "Please enter a title for the resource request.", "titrate_dosage": "Titrate Dosage", "to_be_conducted": "To be conducted", "total_amount": "Total Amount", diff --git a/src/components/Resource/ResourceCreate.tsx b/src/components/Resource/ResourceCreate.tsx index 5efc2c68024..7b4cf64b1f9 100644 --- a/src/components/Resource/ResourceCreate.tsx +++ b/src/components/Resource/ResourceCreate.tsx @@ -1,3 +1,4 @@ +import { t } from "i18next"; import { navigate } from "raviger"; import { useReducer, useState } from "react"; import { useTranslation } from "react-i18next"; @@ -51,31 +52,31 @@ const initForm: any = { const requiredFields: any = { category: { - errorText: "Category", + errorText: t("category"), }, sub_category: { - errorText: "Subcategory", + errorText: t("sub_category"), }, approving_facility: { - errorText: "Name of the referring facility", + errorText: t("approving_facility_error"), }, refering_facility_contact_name: { - errorText: "Name of contact of the referring facility", + errorText: t("referring_facility_contact_name_error"), }, refering_facility_contact_number: { - errorText: "Phone number of contact of the referring facility", - invalidText: "Please enter valid phone number", + errorText: t("referring_facility_contact_number_error"), + invalidText: t("referring_facility_contact_number_invalid"), }, title: { - errorText: "Title for resource request is mandatory", - invalidText: "Please enter title for resource request", + errorText: t("title_error"), + invalidText: t("title_invalid"), }, reason: { - errorText: "Description of resource request is mandatory", - invalidText: "Please enter Description of resource request", + errorText: t("reason_error"), + invalidText: t("reason_invalid"), }, requested_quantity: { - errorText: "Requested Quantity Can't be Less than 1", + errorText: t("requested_quantity_error"), }, }; @@ -145,7 +146,7 @@ export default function ResourceCreate(props: resourceProps) { if (state.form[field]) { const value = state.form[field]; if (!value || parseFloat(value) < 1) { - errors[field] = `Value Can't be Smaller than 1`; + errors[field] = requiredFields[field].text; isInvalidForm = true; } } @@ -185,8 +186,6 @@ export default function ResourceCreate(props: resourceProps) { const handleSubmit = async () => { const validForm = validateForm(); - console.log(validForm); - if (validForm) { setIsLoading(true); diff --git a/src/components/Resource/ResourceDetailsUpdate.tsx b/src/components/Resource/ResourceDetailsUpdate.tsx index 24154749cd3..ba7a65f93de 100644 --- a/src/components/Resource/ResourceDetailsUpdate.tsx +++ b/src/components/Resource/ResourceDetailsUpdate.tsx @@ -1,3 +1,4 @@ +import { t } from "i18next"; import { navigate, useQueryParams } from "raviger"; import { useReducer, useState } from "react"; @@ -46,22 +47,22 @@ const initForm: any = { const requiredFields: any = { approving_facility_object: { - errorText: "Resource approving facility can not be empty.", + errorText: t("empty_resource_error"), }, assigned_facility_object: { - errorText: "Please Select Facility Type", + errorText: t("select_facility_type_error"), }, title: { - errorText: "Title is required.", + errorText: t("empty_title_err"), }, reason: { - errorText: "Description is required.", + errorText: t("empty_description_error"), }, requested_quantity: { - errorText: "Requested Quantity Can't be Less than 1", + errorText: t("requested_quantity_error"), }, assigned_quantity: { - errorText: "Approving Quantity Can't be Less than 0", + errorText: t("assigned_quantity_error"), }, }; @@ -113,33 +114,34 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { const errors = { ...initError }; let isInvalidForm = false; - const validators = { - facilityValidator: (field: string) => - !state.form[field] || !state.form[field]?.name, - quantityValidator: (field: string) => { - const value = state.form[field]; - const minVal = field === "assigned_quantity" ? 0 : 1; - return !value || parseFloat(value) < minVal; - }, - textValidator: (field: string) => - !state.form[field] || state.form[field].trim().length === 0, - }; - - const fieldTypes = { - facility: ["approving_facility_object", "assigned_facility_object"], - quantity: ["requested_quantity", "assigned_quantity"], - }; - Object.keys(requiredFields).forEach((field) => { - const validator = fieldTypes.facility.includes(field) - ? validators.facilityValidator - : fieldTypes.quantity.includes(field) - ? validators.quantityValidator - : validators.textValidator; - - if (validator(field)) { - errors[field] = requiredFields[field].errorText; - isInvalidForm = true; + switch (field) { + case "approving_facility_object": + case "assigned_facility_object": + if (!state.form[field] || !state.form[field]?.name) { + errors[field] = requiredFields[field].errorText; + isInvalidForm = true; + } + break; + + case "requested_quantity": + case "assigned_quantity": + if (state.form[field]) { + const value = state.form[field]; + const minVal = field === "assigned_quantity" ? 0 : 1; + if (!value || parseFloat(value) < minVal) { + errors[field] = requiredFields[field].errorText; + isInvalidForm = true; + } + } + break; + + default: + if (!state.form[field] || state.form[field].trim().length === 0) { + errors[field] = requiredFields[field].errorText; + isInvalidForm = true; + } + break; } }); From 08ac2c99fc5fdc673d0f673fd97e05711eaa220f Mon Sep 17 00:00:00 2001 From: JavidSumra Date: Mon, 9 Dec 2024 13:06:04 +0530 Subject: [PATCH 14/18] Add Requested Changes --- public/locale/en.json | 1 + src/Routers/routes/ResourceRoutes.tsx | 7 +- src/components/Resource/ResourceCreate.tsx | 643 ++++++++++++++------- 3 files changed, 426 insertions(+), 225 deletions(-) diff --git a/public/locale/en.json b/public/locale/en.json index 1d40bf43419..bd77f47bd17 100644 --- a/public/locale/en.json +++ b/public/locale/en.json @@ -1383,6 +1383,7 @@ "update_preset_position_to_current": "Update preset's position to camera's current position", "update_record": "Update Record", "update_record_for_asset": "Update record for asset", + "update_resource_request": "Update Resource Request", "update_shift_request": "Update Shift Request", "update_status_details": "Update Status/Details", "updated": "Updated", diff --git a/src/Routers/routes/ResourceRoutes.tsx b/src/Routers/routes/ResourceRoutes.tsx index 547aeb53610..4eda54fa408 100644 --- a/src/Routers/routes/ResourceRoutes.tsx +++ b/src/Routers/routes/ResourceRoutes.tsx @@ -1,8 +1,9 @@ import { Redirect } from "raviger"; import BoardView from "@/components/Resource/ResourceBoard"; +import ResourceCreate from "@/components/Resource/ResourceCreate"; import ResourceDetails from "@/components/Resource/ResourceDetails"; -import { ResourceDetailsUpdate } from "@/components/Resource/ResourceDetailsUpdate"; +// import { ResourceDetailsUpdate } from "@/components/Resource/ResourceDetailsUpdate"; import ListView from "@/components/Resource/ResourceList"; import { AppRoutes } from "@/Routers/AppRouter"; @@ -15,7 +16,9 @@ const ResourceRoutes: AppRoutes = { "/resource/board": () => , "/resource/list": () => , "/resource/:id": ({ id }) => , - "/resource/:id/update": ({ id }) => , + "/resource/:id/update": ({ id }) => ( + + ), }; export default ResourceRoutes; diff --git a/src/components/Resource/ResourceCreate.tsx b/src/components/Resource/ResourceCreate.tsx index 7b4cf64b1f9..ce83aafe550 100644 --- a/src/components/Resource/ResourceCreate.tsx +++ b/src/components/Resource/ResourceCreate.tsx @@ -1,28 +1,27 @@ -import { t } from "i18next"; -import { navigate } from "raviger"; +import { navigate, useQueryParams } from "raviger"; import { useReducer, useState } from "react"; import { useTranslation } from "react-i18next"; -import Card from "@/CAREUI/display/Card"; - -import { Cancel, Submit } from "@/components/Common/ButtonV2"; import { FacilitySelect } from "@/components/Common/FacilitySelect"; import Loading from "@/components/Common/Loading"; import Page from "@/components/Common/Page"; -import { PhoneNumberValidator } from "@/components/Form/FieldValidators"; +import { + PhoneNumberValidator, + RequiredFieldValidator, +} from "@/components/Form/FieldValidators"; import { FieldLabel } from "@/components/Form/FormFields/FormField"; import PhoneNumberFormField from "@/components/Form/FormFields/PhoneNumberFormField"; import RadioFormField from "@/components/Form/FormFields/RadioFormField"; import { SelectFormField } from "@/components/Form/FormFields/SelectFormField"; import TextAreaFormField from "@/components/Form/FormFields/TextAreaFormField"; import TextFormField from "@/components/Form/FormFields/TextFormField"; -import { FieldChangeEvent } from "@/components/Form/FormFields/Utils"; import useAppHistory from "@/hooks/useAppHistory"; import { OptionsType, RESOURCE_CATEGORY_CHOICES, + RESOURCE_CHOICES, RESOURCE_SUBCATEGORIES, } from "@/common/constants"; import { phonePreg } from "@/common/validation"; @@ -33,51 +32,48 @@ import request from "@/Utils/request/request"; import useQuery from "@/Utils/request/useQuery"; import { parsePhoneNumber } from "@/Utils/utils"; +import CircularProgress from "../Common/CircularProgress"; +import UserAutocomplete from "../Common/UserAutocompleteFormField"; +import { FacilityModel } from "../Facility/models"; +import Form from "../Form/Form"; +import { UserBareMinimum } from "../Users/models"; + interface resourceProps { facilityId: number; + resourceId?: string; +} + +interface ResourceData { + status?: OptionsType["text"]; + category?: string; + sub_category?: number; + approving_facility_object: FacilityModel | null; + assigned_facility_object?: FacilityModel | null; + emergency: string; + request_title: string; + request_description: string; + refering_facility_contact_name?: string; + refering_facility_contact_number: string; + requested_quantity: string | null; + assigned_quantity?: string | null; + assigned_to_object: UserBareMinimum | null; + origin_facility_object?: FacilityModel | null; } -const initForm: any = { +const initForm: ResourceData = { + status: "PENDING", category: "OXYGEN", sub_category: 1000, - approving_facility: null, - assigned_facility: null, + approving_facility_object: null, + assigned_facility_object: null, emergency: "false", - title: "", - reason: "", + request_title: "", + request_description: "", refering_facility_contact_name: "", refering_facility_contact_number: "+91", + assigned_to_object: null, requested_quantity: null, -}; - -const requiredFields: any = { - category: { - errorText: t("category"), - }, - sub_category: { - errorText: t("sub_category"), - }, - approving_facility: { - errorText: t("approving_facility_error"), - }, - refering_facility_contact_name: { - errorText: t("referring_facility_contact_name_error"), - }, - refering_facility_contact_number: { - errorText: t("referring_facility_contact_number_error"), - invalidText: t("referring_facility_contact_number_invalid"), - }, - title: { - errorText: t("title_error"), - invalidText: t("title_invalid"), - }, - reason: { - errorText: t("reason_error"), - invalidText: t("reason_invalid"), - }, - requested_quantity: { - errorText: t("requested_quantity_error"), - }, + assigned_quantity: null, }; const initError = Object.assign( @@ -92,9 +88,46 @@ const initialState = { export default function ResourceCreate(props: resourceProps) { const { goBack } = useAppHistory(); - const { facilityId } = props; + const { facilityId, resourceId } = props; const { t } = useTranslation(); + const [qParams, _] = useQueryParams(); const [isLoading, setIsLoading] = useState(false); + const [initialResourceData, setInitialResouceData] = + useState(initForm); + const resourceStatusOptions = RESOURCE_CHOICES.map((obj) => obj.text); + + const requiredFields: any = { + category: { + errorText: t("category"), + }, + sub_category: { + errorText: t("sub_category"), + }, + approving_facility_object: { + errorText: t("approving_facility_error"), + }, + refering_facility_contact_name: { + errorText: t("referring_facility_contact_name_error"), + }, + refering_facility_contact_number: { + errorText: t("referring_facility_contact_number_error"), + invalidText: t("referring_facility_contact_number_invalid"), + }, + request_title: { + errorText: t("title_error"), + invalidText: t("title_invalid"), + }, + request_description: { + errorText: t("reason_error"), + invalidText: t("reason_invalid"), + }, + requested_quantity: { + errorText: t("requested_quantity_error"), + }, + assigned_quantity: { + errorText: t("assigned_quantity_error"), + }, + }; const resourceFormReducer = (state = initialState, action: any) => { switch (action.type) { @@ -118,226 +151,390 @@ export default function ResourceCreate(props: resourceProps) { const [state, dispatch] = useReducer(resourceFormReducer, initialState); const { data: facilityData } = useQuery(routes.getAnyFacility, { - prefetch: facilityId !== undefined, + prefetch: !!facilityId, pathParams: { id: String(facilityId) }, }); - const validateForm = () => { - const errors = { ...initError }; - let isInvalidForm = false; - Object.keys(requiredFields).forEach((field) => { + const resourceQuery = useQuery(routes.getResourceDetails, { + pathParams: { + id: resourceId!, + }, + prefetch: !!resourceId, + onResponse: ({ data: resource }) => { + if (!resource) return; + + setInitialResouceData({ + ...resource, + request_title: resource.title, + request_description: resource.reason, + sub_category: + Number( + RESOURCE_SUBCATEGORIES.find( + (item) => item.text === resource.sub_category, + )?.id, + ) ?? 1000, + emergency: resource.emergency ? "true" : "false", + requested_quantity: resource.requested_quantity.toString(), + assigned_quantity: resource.assigned_quantity.toString(), + status: qParams.status || resource.status, + }); + dispatch({ type: "set_form", form: resource }); + + setIsLoading(false); + }, + }); + + const { loading: assignedUserLoading } = useQuery(routes.userList); + + const ResourceFormValidator = ( + form: ResourceData, + ): Partial> => { + const errors: Partial> = {}; + + Object.entries(requiredFields).forEach(([field, config]) => { + const { errorText, invalidText }: any = config; + switch (field) { case "refering_facility_contact_number": { - const phoneNumber = parsePhoneNumber(state.form[field]); - if (!state.form[field]) { - errors[field] = requiredFields[field].errorText; - isInvalidForm = true; + if (resourceId) break; + const phoneNumber = parsePhoneNumber(form[field]); + if (!form[field as keyof ResourceData]) { + errors[field as keyof ResourceData] = errorText; } else if ( !phoneNumber || - !PhoneNumberValidator()(phoneNumber) === undefined || + !PhoneNumberValidator()(phoneNumber) || !phonePreg(String(phoneNumber)) ) { - errors[field] = requiredFields[field].invalidText; - isInvalidForm = true; + errors[field as keyof ResourceData] = invalidText; } - return; + break; } case "requested_quantity": - if (state.form[field]) { - const value = state.form[field]; - if (!value || parseFloat(value) < 1) { - errors[field] = requiredFields[field].text; - isInvalidForm = true; - } + case "assigned_quantity": { + const value = form[field as keyof ResourceData]; + const minVal = field === "assigned_quantity" ? 0 : 1; + if (!value || parseFloat(String(value)) < minVal) { + errors[field as keyof ResourceData] = errorText; + } + break; + } + case "approving_facility_object": + if (!form[field]?.name) { + errors[field as keyof ResourceData] = errorText; } break; default: - if (!state.form[field]) { - errors[field] = requiredFields[field].errorText; - isInvalidForm = true; + if (!form[field as keyof ResourceData]) { + errors[field as keyof ResourceData] = errorText; } + break; } }); - dispatch({ type: "set_error", errors }); - return !isInvalidForm; - }; - - const handleChange = (e: FieldChangeEvent) => { - const form = { ...state.form }; - const { name, value } = e; - form[name] = value; - dispatch({ type: "set_form", form }); - }; - - const handleValueChange = (value: any, name: string) => { - const form = { ...state.form }; - form[name] = value; - dispatch({ type: "set_form", form }); + console.log(errors); + return errors; }; - const handleFormFieldChange = (event: FieldChangeEvent) => { - dispatch({ - type: "set_form", - form: { ...state.form, [event.name]: event.value }, - }); - }; - - const handleSubmit = async () => { - const validForm = validateForm(); - - if (validForm) { - setIsLoading(true); - - const resourceData = { - status: "PENDING", - category: state.form.category, - sub_category: state.form.sub_category, - origin_facility: String(props.facilityId), - approving_facility: (state.form.approving_facility || {}).id, - assigned_facility: (state.form.assigned_facility || {}).id, - emergency: state.form.emergency === "true", - title: state.form.title, - reason: state.form.reason, - refering_facility_contact_name: - state.form.refering_facility_contact_name, - refering_facility_contact_number: parsePhoneNumber( - state.form.refering_facility_contact_number, - ), - requested_quantity: state.form.requested_quantity || 1, - }; - - const { res, data } = await request(routes.createResource, { + const handleSubmit = async (form: ResourceData) => { + setIsLoading(true); + + const resourceData = { + status: "PENDING", + category: form.category, + sub_category: form.sub_category?.toString(), + origin_facility: + form.origin_facility_object?.id || String(props.facilityId), + approving_facility: (form.approving_facility_object || {}).id, + assigned_facility: (form.assigned_facility_object || {}).id, + emergency: form.emergency === "true", + title: form.request_title, + reason: form.request_description, + refering_facility_contact_name: form.refering_facility_contact_name, + refering_facility_contact_number: parsePhoneNumber( + form.refering_facility_contact_number, + ), + requested_quantity: parseFloat(form.requested_quantity || "1"), + assigned_quantity: parseFloat(form.assigned_quantity || "0"), + assigned_to_object: form.assigned_to_object ?? null, + assigned_to: form.assigned_to_object?.id.toString() ?? undefined, + }; + + if (resourceId) { + const { res, data } = await request(routes.updateResource, { + pathParams: { id: resourceId }, body: resourceData, }); - setIsLoading(false); - if (res?.ok && data) { - await dispatch({ type: "set_form", form: initForm }); + if (res && res.status == 200 && data) { + dispatch({ type: "set_form", form: data }); Notification.Success({ - msg: "Resource request created successfully", + msg: "Resource request updated successfully", }); - navigate(`/resource/${data.id}`); + navigate(`/resource/${resourceId}`); } - } + setIsLoading(false); + } // } else { + // // const { res, data } = await request(routes.createResource, { + // // body: resourceData, + // // }); + // // setIsLoading(false); + + // // if (res?.ok && data) { + // // await dispatch({ type: "set_form", form: initForm }); + // // Notification.Success({ + // // msg: "Resource request created successfully", + // // }); + + // // navigate(`/resource/${data.id}`); + console.log("created"); + // } + // } }; - if (isLoading) { + if (isLoading || resourceQuery.loading) { return ; } return ( - - - - -
- {t("approving_facility")} - - handleValueChange(value, "approving_facility") - } - errors={state.errors.approving_facility} - /> -
- - (o ? t("yes") : t("no"))} - optionValue={(o) => String(o)} - value={state.form.emergency} - onChange={handleChange} - /> - - option} - optionValue={(option: string) => option} - onChange={({ value }) => handleValueChange(value, "category")} - /> - option.text} - optionValue={(option: OptionsType) => option.id} - onChange={({ value }) => handleValueChange(value, "sub_category")} - /> - - - - - -
- -
- -
- goBack()} /> - -
-
+ + disabled={isLoading} + defaults={initialResourceData} + onCancel={goBack} + className="rounded transition-all sm:rounded-xl bg-white mt-2" + onSubmit={handleSubmit} + validate={ResourceFormValidator} + > + {(field) => ( +
+ {/* Create Flow */} + {!resourceId && ( + <> + + + +
+ {t("approving_facility")} + { + field("approving_facility_object").onChange({ + name: "approving_facility_object", + value: selected, + }); + }} + {...field( + "approving_facility_object", + RequiredFieldValidator(t("approving_facility_error")), + )} + errors={state.errors.approving_facility_object} + /> +
+ (o ? t("yes") : t("no"))} + optionValue={(o) => String(o)} + {...field("emergency")} + /> + + option} + optionValue={(option: string) => option} + required + /> + option.text} + optionValue={(option: OptionsType) => option.id} + /> + + + +
+ +
+ + )} + + {/* Update Flow */} + {resourceId && ( + <> + option} + {...field("status")} + /> + {assignedUserLoading ? ( + + ) : ( + + )} + +
+ {t("approving_facility")} + { + field("approving_facility_object").onChange({ + name: "approving_facility_object", + value: selected, + }); + }} + {...field( + "approving_facility_object", + RequiredFieldValidator(t("approving_facility_error")), + )} + errors={state.errors.approving_facility_object} + /> +
+
+ + What facility would you like to assign the request to + + { + field("assigned_facility_object").onChange({ + name: "assigned_facility_object", + value: selected, + }); + }} + errors={state.errors.approving_facility_object} + /> +
+ + + + + + (o ? t("yes") : t("no"))} + optionValue={(o) => String(o)} + {...field("emergency")} + /> +
+ +
+ + )} +
+ )} +
); } From c5624e9fe6bfd2345f65870bddcb52b336f01219 Mon Sep 17 00:00:00 2001 From: JavidSumra Date: Mon, 9 Dec 2024 14:20:15 +0530 Subject: [PATCH 15/18] Fix Failing Test --- .../pageobject/Facility/FacilityCreation.ts | 6 +-- src/components/Resource/ResourceCreate.tsx | 41 +++++++++---------- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/cypress/pageobject/Facility/FacilityCreation.ts b/cypress/pageobject/Facility/FacilityCreation.ts index 4c064956fcc..55ebc501df7 100644 --- a/cypress/pageobject/Facility/FacilityCreation.ts +++ b/cypress/pageobject/Facility/FacilityCreation.ts @@ -364,14 +364,14 @@ class FacilityPage { ) { cy.get("#refering_facility_contact_name").type(name); cy.get("#refering_facility_contact_number").type(phone_number); - cy.get("[name='approving_facility']") + cy.get("[name='approving_facility_object']") .type(facility) .then(() => { cy.get("[role='option']").first().click(); }); - cy.get("#title").type(title); + cy.get("#request_title").type(title); cy.get("#requested_quantity").type(quantity); - cy.get("#reason").type(description); + cy.get("#request_description").type(description); } clickSubmitRequestButton() { diff --git a/src/components/Resource/ResourceCreate.tsx b/src/components/Resource/ResourceCreate.tsx index ce83aafe550..09406b70495 100644 --- a/src/components/Resource/ResourceCreate.tsx +++ b/src/components/Resource/ResourceCreate.tsx @@ -72,8 +72,8 @@ const initForm: ResourceData = { refering_facility_contact_name: "", refering_facility_contact_number: "+91", assigned_to_object: null, - requested_quantity: null, - assigned_quantity: null, + requested_quantity: "", + assigned_quantity: "", }; const initError = Object.assign( @@ -202,7 +202,7 @@ export default function ResourceCreate(props: resourceProps) { errors[field as keyof ResourceData] = errorText; } else if ( !phoneNumber || - !PhoneNumberValidator()(phoneNumber) || + !PhoneNumberValidator()(phoneNumber) === undefined || !phonePreg(String(phoneNumber)) ) { errors[field as keyof ResourceData] = invalidText; @@ -211,6 +211,7 @@ export default function ResourceCreate(props: resourceProps) { } case "requested_quantity": case "assigned_quantity": { + if (!resourceId && field === "assigned_quantity") break; const value = form[field as keyof ResourceData]; const minVal = field === "assigned_quantity" ? 0 : 1; if (!value || parseFloat(String(value)) < minVal) { @@ -231,7 +232,6 @@ export default function ResourceCreate(props: resourceProps) { } }); dispatch({ type: "set_error", errors }); - console.log(errors); return errors; }; @@ -255,7 +255,7 @@ export default function ResourceCreate(props: resourceProps) { ), requested_quantity: parseFloat(form.requested_quantity || "1"), assigned_quantity: parseFloat(form.assigned_quantity || "0"), - assigned_to_object: form.assigned_to_object ?? null, + assigned_to_object: form.assigned_to_object, assigned_to: form.assigned_to_object?.id.toString() ?? undefined, }; @@ -274,22 +274,21 @@ export default function ResourceCreate(props: resourceProps) { navigate(`/resource/${resourceId}`); } setIsLoading(false); - } // } else { - // // const { res, data } = await request(routes.createResource, { - // // body: resourceData, - // // }); - // // setIsLoading(false); - - // // if (res?.ok && data) { - // // await dispatch({ type: "set_form", form: initForm }); - // // Notification.Success({ - // // msg: "Resource request created successfully", - // // }); - - // // navigate(`/resource/${data.id}`); - console.log("created"); - // } - // } + } else { + const { res, data } = await request(routes.createResource, { + body: resourceData, + }); + setIsLoading(false); + + if (res?.ok && data) { + await dispatch({ type: "set_form", form: initForm }); + Notification.Success({ + msg: "Resource request created successfully", + }); + + navigate(`/resource/${data.id}`); + } + } }; if (isLoading || resourceQuery.loading) { From 1033d253639293281a31dcb4842301630c11f95c Mon Sep 17 00:00:00 2001 From: JavidSumra Date: Mon, 9 Dec 2024 17:26:31 +0530 Subject: [PATCH 16/18] Fix error state for assigned facility --- src/components/Resource/ResourceCreate.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Resource/ResourceCreate.tsx b/src/components/Resource/ResourceCreate.tsx index 09406b70495..9fd1f343293 100644 --- a/src/components/Resource/ResourceCreate.tsx +++ b/src/components/Resource/ResourceCreate.tsx @@ -477,7 +477,7 @@ export default function ResourceCreate(props: resourceProps) { value: selected, }); }} - errors={state.errors.approving_facility_object} + errors={state.errors.assigned_facility_object} /> From 94f6607a2a4a3ba7461e20c3ab648fbfa3df44fd Mon Sep 17 00:00:00 2001 From: JavidSumra Date: Tue, 10 Dec 2024 10:54:07 +0530 Subject: [PATCH 17/18] Add Requested Changes --- .../pageobject/Facility/FacilityCreation.ts | 4 +- src/Routers/routes/ResourceRoutes.tsx | 5 +- src/components/Resource/ResourceCreate.tsx | 83 ++-- .../Resource/ResourceDetailsUpdate.tsx | 365 ------------------ 4 files changed, 42 insertions(+), 415 deletions(-) delete mode 100644 src/components/Resource/ResourceDetailsUpdate.tsx diff --git a/cypress/pageobject/Facility/FacilityCreation.ts b/cypress/pageobject/Facility/FacilityCreation.ts index 55ebc501df7..b0ece8d5120 100644 --- a/cypress/pageobject/Facility/FacilityCreation.ts +++ b/cypress/pageobject/Facility/FacilityCreation.ts @@ -369,9 +369,9 @@ class FacilityPage { .then(() => { cy.get("[role='option']").first().click(); }); - cy.get("#request_title").type(title); + cy.get("#title").type(title); cy.get("#requested_quantity").type(quantity); - cy.get("#request_description").type(description); + cy.get("#reason").type(description); } clickSubmitRequestButton() { diff --git a/src/Routers/routes/ResourceRoutes.tsx b/src/Routers/routes/ResourceRoutes.tsx index 4eda54fa408..60e7a94ea00 100644 --- a/src/Routers/routes/ResourceRoutes.tsx +++ b/src/Routers/routes/ResourceRoutes.tsx @@ -3,7 +3,6 @@ import { Redirect } from "raviger"; import BoardView from "@/components/Resource/ResourceBoard"; import ResourceCreate from "@/components/Resource/ResourceCreate"; import ResourceDetails from "@/components/Resource/ResourceDetails"; -// import { ResourceDetailsUpdate } from "@/components/Resource/ResourceDetailsUpdate"; import ListView from "@/components/Resource/ResourceList"; import { AppRoutes } from "@/Routers/AppRouter"; @@ -16,9 +15,7 @@ const ResourceRoutes: AppRoutes = { "/resource/board": () => , "/resource/list": () => , "/resource/:id": ({ id }) => , - "/resource/:id/update": ({ id }) => ( - - ), + "/resource/:id/update": ({ id }) => , }; export default ResourceRoutes; diff --git a/src/components/Resource/ResourceCreate.tsx b/src/components/Resource/ResourceCreate.tsx index 9fd1f343293..37da5c7b429 100644 --- a/src/components/Resource/ResourceCreate.tsx +++ b/src/components/Resource/ResourceCreate.tsx @@ -34,31 +34,30 @@ import { parsePhoneNumber } from "@/Utils/utils"; import CircularProgress from "../Common/CircularProgress"; import UserAutocomplete from "../Common/UserAutocompleteFormField"; -import { FacilityModel } from "../Facility/models"; +import { ResourceModel } from "../Facility/models"; import Form from "../Form/Form"; -import { UserBareMinimum } from "../Users/models"; interface resourceProps { - facilityId: number; + facilityId?: number; resourceId?: string; } -interface ResourceData { - status?: OptionsType["text"]; - category?: string; - sub_category?: number; - approving_facility_object: FacilityModel | null; - assigned_facility_object?: FacilityModel | null; +type ResourceData = Partial< + Omit< + ResourceModel, + | "status" + | "requested_quantity" + | "assigned_quantity" + | "emergency" + | "sub_category" + > +> & { + sub_category: number; + status: string; + requested_quantity: string; + assigned_quantity: string; emergency: string; - request_title: string; - request_description: string; - refering_facility_contact_name?: string; - refering_facility_contact_number: string; - requested_quantity: string | null; - assigned_quantity?: string | null; - assigned_to_object: UserBareMinimum | null; - origin_facility_object?: FacilityModel | null; -} +}; const initForm: ResourceData = { status: "PENDING", @@ -67,8 +66,8 @@ const initForm: ResourceData = { approving_facility_object: null, assigned_facility_object: null, emergency: "false", - request_title: "", - request_description: "", + title: "", + reason: "", refering_facility_contact_name: "", refering_facility_contact_number: "+91", assigned_to_object: null, @@ -113,11 +112,11 @@ export default function ResourceCreate(props: resourceProps) { errorText: t("referring_facility_contact_number_error"), invalidText: t("referring_facility_contact_number_invalid"), }, - request_title: { + title: { errorText: t("title_error"), invalidText: t("title_invalid"), }, - request_description: { + reason: { errorText: t("reason_error"), invalidText: t("reason_invalid"), }, @@ -151,8 +150,8 @@ export default function ResourceCreate(props: resourceProps) { const [state, dispatch] = useReducer(resourceFormReducer, initialState); const { data: facilityData } = useQuery(routes.getAnyFacility, { - prefetch: !!facilityId, pathParams: { id: String(facilityId) }, + prefetch: !!facilityId, }); const resourceQuery = useQuery(routes.getResourceDetails, { @@ -165,8 +164,6 @@ export default function ResourceCreate(props: resourceProps) { setInitialResouceData({ ...resource, - request_title: resource.title, - request_description: resource.reason, sub_category: Number( RESOURCE_SUBCATEGORIES.find( @@ -184,7 +181,9 @@ export default function ResourceCreate(props: resourceProps) { }, }); - const { loading: assignedUserLoading } = useQuery(routes.userList); + const { loading: assignedUserLoading } = useQuery(routes.userList, { + prefetch: !!resourceId, + }); const ResourceFormValidator = ( form: ResourceData, @@ -197,7 +196,7 @@ export default function ResourceCreate(props: resourceProps) { switch (field) { case "refering_facility_contact_number": { if (resourceId) break; - const phoneNumber = parsePhoneNumber(form[field]); + const phoneNumber = parsePhoneNumber(form[field] ?? ""); if (!form[field as keyof ResourceData]) { errors[field as keyof ResourceData] = errorText; } else if ( @@ -239,7 +238,7 @@ export default function ResourceCreate(props: resourceProps) { setIsLoading(true); const resourceData = { - status: "PENDING", + status: form.status || "PENDING", category: form.category, sub_category: form.sub_category?.toString(), origin_facility: @@ -247,11 +246,11 @@ export default function ResourceCreate(props: resourceProps) { approving_facility: (form.approving_facility_object || {}).id, assigned_facility: (form.assigned_facility_object || {}).id, emergency: form.emergency === "true", - title: form.request_title, - reason: form.request_description, + title: form.title, + reason: form.reason, refering_facility_contact_name: form.refering_facility_contact_name, refering_facility_contact_number: parsePhoneNumber( - form.refering_facility_contact_number, + form.refering_facility_contact_number ?? "", ), requested_quantity: parseFloat(form.requested_quantity || "1"), assigned_quantity: parseFloat(form.assigned_quantity || "0"), @@ -301,7 +300,9 @@ export default function ResourceCreate(props: resourceProps) { resourceId ? t("update_resource_request") : t("create_resource_request") } crumbsReplacements={{ - [facilityId]: { name: facilityData?.name || "" }, + ...(resourceId + ? { [resourceId]: { name: initialResourceData?.title } } + : { [String(facilityId)]: { name: facilityData?.name || "" } }), resource: { style: "pointer-events-none" }, }} backUrl={ @@ -393,10 +394,7 @@ export default function ResourceCreate(props: resourceProps) { /> diff --git a/src/components/Resource/ResourceDetailsUpdate.tsx b/src/components/Resource/ResourceDetailsUpdate.tsx deleted file mode 100644 index ba7a65f93de..00000000000 --- a/src/components/Resource/ResourceDetailsUpdate.tsx +++ /dev/null @@ -1,365 +0,0 @@ -import { t } from "i18next"; -import { navigate, useQueryParams } from "raviger"; -import { useReducer, useState } from "react"; - -import Card from "@/CAREUI/display/Card"; - -import { Cancel, Submit } from "@/components/Common/ButtonV2"; -import CircularProgress from "@/components/Common/CircularProgress"; -import { FacilitySelect } from "@/components/Common/FacilitySelect"; -import Loading from "@/components/Common/Loading"; -import Page from "@/components/Common/Page"; -import UserAutocomplete from "@/components/Common/UserAutocompleteFormField"; -import { FieldLabel } from "@/components/Form/FormFields/FormField"; -import RadioFormField from "@/components/Form/FormFields/RadioFormField"; -import { SelectFormField } from "@/components/Form/FormFields/SelectFormField"; -import TextAreaFormField from "@/components/Form/FormFields/TextAreaFormField"; -import TextFormField from "@/components/Form/FormFields/TextFormField"; -import { FieldChangeEvent } from "@/components/Form/FormFields/Utils"; -import { UserModel } from "@/components/Users/models"; - -import useAppHistory from "@/hooks/useAppHistory"; - -import { RESOURCE_CHOICES } from "@/common/constants"; - -import * as Notification from "@/Utils/Notifications"; -import routes from "@/Utils/request/api"; -import request from "@/Utils/request/request"; -import useQuery from "@/Utils/request/useQuery"; - -interface resourceProps { - id: string; -} - -const resourceStatusOptions = RESOURCE_CHOICES.map((obj) => obj.text); - -const initForm: any = { - approving_facility_object: null, - assigned_facility_object: null, - emergency: "false", - title: "", - reason: "", - assigned_facility_type: "", - assigned_to: "", - requested_quantity: null, - assigned_quantity: null, -}; - -const requiredFields: any = { - approving_facility_object: { - errorText: t("empty_resource_error"), - }, - assigned_facility_object: { - errorText: t("select_facility_type_error"), - }, - title: { - errorText: t("empty_title_err"), - }, - reason: { - errorText: t("empty_description_error"), - }, - requested_quantity: { - errorText: t("requested_quantity_error"), - }, - assigned_quantity: { - errorText: t("assigned_quantity_error"), - }, -}; - -const initError = Object.assign( - {}, - ...Object.keys(initForm).map((k) => ({ [k]: "" })), -); - -const initialState = { - form: { ...initForm }, - errors: { ...initError }, -}; - -export const ResourceDetailsUpdate = (props: resourceProps) => { - const { goBack } = useAppHistory(); - const [qParams, _] = useQueryParams(); - const [isLoading, setIsLoading] = useState(true); - const [assignedUser, SetAssignedUser] = useState(); - const resourceFormReducer = (state = initialState, action: any) => { - switch (action.type) { - case "set_form": { - return { - ...state, - form: action.form, - }; - } - case "set_error": { - return { - ...state, - errors: action.errors, - }; - } - default: - return state; - } - }; - - const [state, dispatch] = useReducer(resourceFormReducer, initialState); - - const { loading: assignedUserLoading } = useQuery(routes.userList, { - onResponse: ({ res, data }) => { - if (res?.ok && data && data.count) { - SetAssignedUser(data.results[0]); - } - }, - }); - - const validateForm = () => { - const errors = { ...initError }; - let isInvalidForm = false; - - Object.keys(requiredFields).forEach((field) => { - switch (field) { - case "approving_facility_object": - case "assigned_facility_object": - if (!state.form[field] || !state.form[field]?.name) { - errors[field] = requiredFields[field].errorText; - isInvalidForm = true; - } - break; - - case "requested_quantity": - case "assigned_quantity": - if (state.form[field]) { - const value = state.form[field]; - const minVal = field === "assigned_quantity" ? 0 : 1; - if (!value || parseFloat(value) < minVal) { - errors[field] = requiredFields[field].errorText; - isInvalidForm = true; - } - } - break; - - default: - if (!state.form[field] || state.form[field].trim().length === 0) { - errors[field] = requiredFields[field].errorText; - isInvalidForm = true; - } - break; - } - }); - - dispatch({ type: "set_error", errors }); - return !isInvalidForm; - }; - - const handleChange = (e: FieldChangeEvent) => { - dispatch({ - type: "set_form", - form: { ...state.form, [e.name]: e.value }, - }); - }; - - const handleOnSelect = (user: any) => { - const form = { ...state.form }; - form["assigned_to"] = user?.value?.id; - SetAssignedUser(user.value); - dispatch({ type: "set_form", form }); - }; - - const setFacility = (selected: any, name: string) => { - const form = { ...state.form }; - form[name] = selected; - dispatch({ type: "set_form", form }); - }; - - const { data: resourceDetails } = useQuery(routes.getResourceDetails, { - pathParams: { id: props.id }, - onResponse: ({ res, data }) => { - if (res && data) { - const d = data; - d["status"] = qParams.status || data.status; - dispatch({ type: "set_form", form: d }); - } - setIsLoading(false); - }, - }); - - const handleSubmit = async () => { - const validForm = validateForm(); - - if (validForm) { - setIsLoading(true); - - const resourceData = { - category: "OXYGEN", - status: state.form.status, - origin_facility: state.form.origin_facility_object?.id, - approving_facility: state.form?.approving_facility_object?.id, - assigned_facility: state.form?.assigned_facility_object?.id, - emergency: [true, "true"].includes(state.form.emergency), - title: state.form.title, - reason: state.form.reason, - assigned_to: state.form.assigned_to, - requested_quantity: state.form.requested_quantity || 1, - assigned_quantity: - state.form.status === "PENDING" - ? state.form.assigned_quantity || 0 - : resourceDetails?.assigned_quantity || 0, - }; - - const { res, data } = await request(routes.updateResource, { - pathParams: { id: props.id }, - body: resourceData, - }); - setIsLoading(false); - - if (res && res.status == 200 && data) { - dispatch({ type: "set_form", form: data }); - Notification.Success({ - msg: "Resource request updated successfully", - }); - - navigate(`/resource/${props.id}`); - } else { - setIsLoading(false); - } - } - }; - - if (isLoading) { - return ; - } - - return ( - -
- -
-
- option} - /> -
-
-
- {assignedUserLoading ? ( - - ) : ( - - )} -
-
-
- Name of resource approving facility - - setFacility(obj, "approving_facility_object") - } - errors={state.errors.approving_facility_object} - /> -
- -
- - What facility would you like to assign the request to - - - setFacility(obj, "assigned_facility_object") - } - errors={state.errors.assigned_facility_object} - /> -
-
- -
-
- -
- -
- -
- -
- -
- -
- (o ? "Yes" : "No")} - optionValue={(o) => String(o)} - value={String(state.form.emergency)} - error={state.errors.emergency} - /> -
- -
- goBack()} /> - -
-
-
-
-
- ); -}; From 995618ab7b7c6364a8cc64a1705f60de4a4e4384 Mon Sep 17 00:00:00 2001 From: JavidSumra Date: Tue, 10 Dec 2024 16:34:33 +0530 Subject: [PATCH 18/18] Fix Placeholder issue --- public/locale/en.json | 1 + src/components/Resource/ResourceCreate.tsx | 8 +++----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/public/locale/en.json b/public/locale/en.json index e292b449d58..839ab8841dd 100644 --- a/public/locale/en.json +++ b/public/locale/en.json @@ -344,6 +344,7 @@ "assign": "Assign", "assign_a_volunteer_to": "Assign a volunteer to {{name}}", "assign_bed": "Assign Bed", + "assign_facility_label": "What facility would you like to assign the request to", "assign_to_volunteer": "Assign to a Volunteer", "assigned_doctor": "Assigned Doctor", "assigned_facility": "Facility assigned", diff --git a/src/components/Resource/ResourceCreate.tsx b/src/components/Resource/ResourceCreate.tsx index 37da5c7b429..95ba5bd8377 100644 --- a/src/components/Resource/ResourceCreate.tsx +++ b/src/components/Resource/ResourceCreate.tsx @@ -461,9 +461,7 @@ export default function ResourceCreate(props: resourceProps) { />
- - What facility would you like to assign the request to - + {t("assign_facility_label")}