chore: handled inline errors in the estimate switch

This commit is contained in:
guru_sainath 2024-05-30 11:27:28 +05:30
parent c2e07c6b7c
commit 8822c8b184
3 changed files with 120 additions and 38 deletions

View File

@ -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<TEstimatePointItemSwitchPreview> = 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<TEstimatePointItemSwitchPreview>
<div className="flex-shrink-0 w-4 h-4 relative flex justify-center items-center">
<MoveRight size={12} />
</div>
<div className="relative w-full border rounded flex items-center border-custom-border-200">
<div
className={cn(
"relative w-full border rounded flex items-center",
isError ? `border-red-500` : `border-custom-border-200`
)}
>
<input
type="text"
value={currentEstimatePoint?.value}
onChange={(e) => 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 && (
<>
<Tooltip
tooltipContent={
errorType === "empty-fields" ? "please fill this estimate point." : `Repeating estimate point`
}
position="bottom"
>
<div className="flex-shrink-0 w-3.5 h-3.5 overflow-hidden mr-3 relative flex justify-center items-center text-red-500">
<Info size={14} />
</div>
</Tooltip>
</>
)}
</div>
</div>
);

View File

@ -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<TEstimatePointSwitchRoot> = observer((p
const { asJson: estimate, estimatePointIds, estimatePointById, updateEstimateSwitch } = useEstimate(estimateId);
// states
const [estimatePoints, setEstimatePoints] = useState<TEstimatePointsObject[] | undefined>(undefined);
const [estimateError, setEstimateError] = useState<{ type: string; ids: string[] } | undefined>(undefined);
useEffect(() => {
if (!estimatePointIds) return;
@ -44,43 +47,82 @@ export const EstimatePointSwitchRoot: FC<TEstimatePointSwitchRoot> = 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<TEstimatePointSwitchRoot> = observer((p
if (!workspaceSlug || !projectId || !estimateId || !estimatePoints) return <></>;
return (
<>
<div className="space-y-3">
<div className="space-y-3 px-5 pb-5">
<div className="text-sm font-medium flex items-center gap-2">
<div className="w-full">Current {estimate?.type}</div>
<div className="flex-shrink-0 w-4 h-4" />
@ -106,9 +148,11 @@ export const EstimatePointSwitchRoot: FC<TEstimatePointSwitchRoot> = observer((p
<EstimatePointItemSwitchPreview
key={estimateObject?.id}
estimateId={estimateId}
estimatePointId={estimateObject.id}
estimatePointId={estimateObject?.id}
estimatePoint={estimateObject}
handleEstimatePoint={(value: string) => handleEstimatePoints(index, value)}
errorType={estimateError?.type}
isError={estimateObject?.id ? estimateError?.ids?.includes(estimateObject.id) : false}
/>
))}
</div>

View File

@ -67,12 +67,18 @@ export const UpdateEstimateModal: FC<TUpdateEstimateModal> = observer((props) =>
)}
</div>
<div className="px-5">
{!estimateEditType && <EstimateUpdateStageOne handleEstimateEditType={handleEstimateEditType} />}
<div>
{!estimateEditType && (
<div className="px-5">
<EstimateUpdateStageOne handleEstimateEditType={handleEstimateEditType} />
</div>
)}
{estimateEditType && estimateId && (
<>
{estimateEditType === EEstimateUpdateStages.EDIT && (
<EstimatePointEditRoot workspaceSlug={workspaceSlug} projectId={projectId} estimateId={estimateId} />
<div className="px-5">
<EstimatePointEditRoot workspaceSlug={workspaceSlug} projectId={projectId} estimateId={estimateId} />
</div>
)}
{estimateEditType === EEstimateUpdateStages.SWITCH && estimateSystemSwitchType && (
<EstimatePointSwitchRoot