From 8822c8b184f37a238d9da1925d4960c22b7657df Mon Sep 17 00:00:00 2001 From: guru_sainath Date: Thu, 30 May 2024 11:27:28 +0530 Subject: [PATCH] chore: handled inline errors in the estimate switch --- .../estimates/points/switch/preview.tsx | 38 +++++- .../estimates/points/switch/root.tsx | 108 ++++++++++++------ web/components/estimates/update/modal.tsx | 12 +- 3 files changed, 120 insertions(+), 38 deletions(-) diff --git a/web/components/estimates/points/switch/preview.tsx b/web/components/estimates/points/switch/preview.tsx index 6a98e164a..5b65cc8b3 100644 --- a/web/components/estimates/points/switch/preview.tsx +++ b/web/components/estimates/points/switch/preview.tsx @@ -1,7 +1,10 @@ import { FC } from "react"; import { observer } from "mobx-react"; -import { MoveRight } from "lucide-react"; +import { Info, MoveRight } from "lucide-react"; import { TEstimatePointsObject } from "@plane/types"; +import { Tooltip } from "@plane/ui"; +// helpers +import { cn } from "@/helpers/common.helper"; // hooks import { useEstimatePoint } from "@/hooks/store"; @@ -10,10 +13,19 @@ type TEstimatePointItemSwitchPreview = { estimatePointId: string | undefined; estimatePoint: TEstimatePointsObject; handleEstimatePoint: (value: string) => void; + errorType?: string; + isError?: boolean; }; export const EstimatePointItemSwitchPreview: FC = observer((props) => { - const { estimateId, estimatePointId, estimatePoint: currentEstimatePoint, handleEstimatePoint } = props; + const { + estimateId, + estimatePointId, + estimatePoint: currentEstimatePoint, + handleEstimatePoint, + errorType = "", + isError = false, + } = props; // hooks const { asJson: estimatePoint } = useEstimatePoint(estimateId, estimatePointId); @@ -26,14 +38,34 @@ export const EstimatePointItemSwitchPreview: FC
-
+
handleEstimatePoint(e.target.value)} className="border-none focus:ring-0 focus:border-0 focus:outline-none p-2.5 w-full bg-transparent" autoFocus + placeholder="Enter estimate point value" /> + {isError && ( + <> + +
+ +
+
+ + )}
); diff --git a/web/components/estimates/points/switch/root.tsx b/web/components/estimates/points/switch/root.tsx index 34fb34010..c14cff377 100644 --- a/web/components/estimates/points/switch/root.tsx +++ b/web/components/estimates/points/switch/root.tsx @@ -6,6 +6,8 @@ import { Button, TOAST_TYPE, setToast } from "@plane/ui"; import { EstimatePointItemSwitchPreview } from "@/components/estimates/points"; // constants import { EEstimateSystem, EEstimateUpdateStages, ESTIMATE_SYSTEMS } from "@/constants/estimates"; +// helpers +import { isEstimatePointValuesRepeated } from "@/helpers/estimates"; // hooks import { useEstimate } from "@/hooks/store"; @@ -25,6 +27,7 @@ export const EstimatePointSwitchRoot: FC = observer((p const { asJson: estimate, estimatePointIds, estimatePointById, updateEstimateSwitch } = useEstimate(estimateId); // states const [estimatePoints, setEstimatePoints] = useState(undefined); + const [estimateError, setEstimateError] = useState<{ type: string; ids: string[] } | undefined>(undefined); useEffect(() => { if (!estimatePointIds) return; @@ -44,43 +47,82 @@ export const EstimatePointSwitchRoot: FC = observer((p }); }; + const validateEstimateErrorHandlers = () => { + const currentEstimateError = (estimatePoints || []) + ?.map((estimatePoint) => { + if (!estimatePoint.value || estimatePoint.value === "") return estimatePoint.id; + }) + .filter((estimatePointId) => estimatePointId !== undefined) as string[]; + setEstimateError({ type: "empty-fields", ids: currentEstimateError }); + + if (currentEstimateError.length > 0) return true; + else return false; + }; + const handleSwitchEstimate = async () => { try { if (!workspaceSlug || !projectId) return; - const validatedEstimatePoints: TEstimatePointsObject[] = []; - if ([EEstimateSystem.POINTS, EEstimateSystem.TIME].includes(estimateSystemSwitchType)) { - estimatePoints?.map((estimatePoint) => { - if ( - estimatePoint.value && - ((estimatePoint.value != "0" && Number(estimatePoint.value)) || estimatePoint.value === "0") - ) - validatedEstimatePoints.push(estimatePoint); - }); - } else { - estimatePoints?.map((estimatePoint) => { - if (estimatePoint.value) validatedEstimatePoints.push(estimatePoint); - }); - } - if (validatedEstimatePoints.length === estimatePoints?.length) { - const payload: IEstimateFormData = { - estimate: { - name: ESTIMATE_SYSTEMS[estimateSystemSwitchType]?.name, - type: estimateSystemSwitchType, - }, - estimate_points: validatedEstimatePoints, - }; - await updateEstimateSwitch(workspaceSlug, projectId, payload); - setToast({ - type: TOAST_TYPE.SUCCESS, - title: "Estimate system created", - message: "Created and Enabled successfully", - }); - handleClose(); + setEstimateError(undefined); + if (!validateEstimateErrorHandlers()) { + const isRepeated = + (estimateSystemSwitchType && + estimatePoints && + isEstimatePointValuesRepeated( + estimatePoints?.map((estimatePoint) => estimatePoint?.value), + estimateSystemSwitchType, + undefined + )) || + false; + + if (!isRepeated) { + const validatedEstimatePoints: TEstimatePointsObject[] = []; + if ([EEstimateSystem.POINTS, EEstimateSystem.TIME].includes(estimateSystemSwitchType)) { + estimatePoints?.map((estimatePoint) => { + if ( + estimatePoint.value && + ((estimatePoint.value != "0" && Number(estimatePoint.value)) || estimatePoint.value === "0") + ) + validatedEstimatePoints.push(estimatePoint); + }); + } else { + estimatePoints?.map((estimatePoint) => { + if (estimatePoint.value) validatedEstimatePoints.push(estimatePoint); + }); + } + if (validatedEstimatePoints.length === estimatePoints?.length) { + const payload: IEstimateFormData = { + estimate: { + name: ESTIMATE_SYSTEMS[estimateSystemSwitchType]?.name, + type: estimateSystemSwitchType, + }, + estimate_points: validatedEstimatePoints, + }; + await updateEstimateSwitch(workspaceSlug, projectId, payload); + setToast({ + type: TOAST_TYPE.SUCCESS, + title: "Estimate system created", + message: "Created and Enabled successfully", + }); + handleClose(); + } else { + setToast({ + type: TOAST_TYPE.ERROR, + title: "Error!", + message: "something went wrong", + }); + } + } else { + setToast({ + type: TOAST_TYPE.ERROR, + title: "Error!", + message: "Estimate point values cannot be repeated", + }); + } } else { setToast({ type: TOAST_TYPE.ERROR, title: "Error!", - message: "something went wrong", + message: "Please fill all the estimate point fields", }); } } catch (error) { @@ -95,7 +137,7 @@ export const EstimatePointSwitchRoot: FC = observer((p if (!workspaceSlug || !projectId || !estimateId || !estimatePoints) return <>; return ( <> -
+
Current {estimate?.type}
@@ -106,9 +148,11 @@ export const EstimatePointSwitchRoot: FC = observer((p handleEstimatePoints(index, value)} + errorType={estimateError?.type} + isError={estimateObject?.id ? estimateError?.ids?.includes(estimateObject.id) : false} /> ))}
diff --git a/web/components/estimates/update/modal.tsx b/web/components/estimates/update/modal.tsx index f83eae767..3a0897297 100644 --- a/web/components/estimates/update/modal.tsx +++ b/web/components/estimates/update/modal.tsx @@ -67,12 +67,18 @@ export const UpdateEstimateModal: FC = observer((props) => )}
-
- {!estimateEditType && } +
+ {!estimateEditType && ( +
+ +
+ )} {estimateEditType && estimateId && ( <> {estimateEditType === EEstimateUpdateStages.EDIT && ( - +
+ +
)} {estimateEditType === EEstimateUpdateStages.SWITCH && estimateSystemSwitchType && (