mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
chore: updated modal and form validations
This commit is contained in:
parent
d3556f457b
commit
b302addcd9
@ -17,7 +17,7 @@ export enum EModalWidth {
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode;
|
||||
handleClose: () => void;
|
||||
handleClose?: () => void;
|
||||
isOpen: boolean;
|
||||
position?: EModalPosition;
|
||||
width?: EModalWidth;
|
||||
@ -27,7 +27,7 @@ export const ModalCore: React.FC<Props> = (props) => {
|
||||
|
||||
return (
|
||||
<Transition.Root show={isOpen} as={Fragment}>
|
||||
<Dialog as="div" className="relative z-20" onClose={handleClose}>
|
||||
<Dialog as="div" className="relative z-20" onClose={() => handleClose && handleClose}>
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
|
@ -28,6 +28,8 @@ export const CreateEstimateModal: FC<TCreateEstimateModal> = observer((props) =>
|
||||
// states
|
||||
const [estimateSystem, setEstimateSystem] = useState<TEstimateSystemKeys>(EEstimateSystem.POINTS);
|
||||
const [estimatePoints, setEstimatePoints] = useState<TEstimatePointsObject[] | undefined>(undefined);
|
||||
const [estimatePointCreate, setEstimatePointCreate] = useState<TEstimatePointsObject[] | undefined>(undefined);
|
||||
const [estimatePointCreateError, setEstimatePointCreateError] = useState<number[]>([]);
|
||||
const [buttonLoader, setButtonLoader] = useState(false);
|
||||
|
||||
const handleUpdatePoints = (newPoints: TEstimatePointsObject[] | undefined) => setEstimatePoints(newPoints);
|
||||
@ -40,33 +42,39 @@ export const CreateEstimateModal: FC<TCreateEstimateModal> = observer((props) =>
|
||||
}, [isOpen]);
|
||||
|
||||
const handleCreateEstimate = async () => {
|
||||
try {
|
||||
if (!workspaceSlug || !projectId || !estimatePoints) return;
|
||||
setButtonLoader(true);
|
||||
const payload: IEstimateFormData = {
|
||||
estimate: {
|
||||
name: ESTIMATE_SYSTEMS[estimateSystem]?.name,
|
||||
type: estimateSystem,
|
||||
last_used: true,
|
||||
},
|
||||
estimate_points: estimatePoints,
|
||||
};
|
||||
await createEstimate(workspaceSlug, projectId, payload);
|
||||
setEstimatePointCreateError([]);
|
||||
if (estimatePointCreate === undefined || estimatePointCreate?.length === 0) {
|
||||
try {
|
||||
if (!workspaceSlug || !projectId || !estimatePoints) return;
|
||||
|
||||
setButtonLoader(false);
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Estimate created",
|
||||
message: "A new estimate has been added in your project.",
|
||||
});
|
||||
handleClose();
|
||||
} catch (error) {
|
||||
setButtonLoader(false);
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Estimate creation failed",
|
||||
message: "We were unable to create the new estimate, please try again.",
|
||||
});
|
||||
setButtonLoader(true);
|
||||
const payload: IEstimateFormData = {
|
||||
estimate: {
|
||||
name: ESTIMATE_SYSTEMS[estimateSystem]?.name,
|
||||
type: estimateSystem,
|
||||
last_used: true,
|
||||
},
|
||||
estimate_points: estimatePoints,
|
||||
};
|
||||
await createEstimate(workspaceSlug, projectId, payload);
|
||||
|
||||
setButtonLoader(false);
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Estimate created",
|
||||
message: "A new estimate has been added in your project.",
|
||||
});
|
||||
handleClose();
|
||||
} catch (error) {
|
||||
setButtonLoader(false);
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Estimate creation failed",
|
||||
message: "We were unable to create the new estimate, please try again.",
|
||||
});
|
||||
}
|
||||
} else {
|
||||
setEstimatePointCreateError(estimatePointCreate.map((point) => point.key));
|
||||
}
|
||||
};
|
||||
|
||||
@ -74,7 +82,7 @@ export const CreateEstimateModal: FC<TCreateEstimateModal> = observer((props) =>
|
||||
const renderEstimateStepsCount = useMemo(() => (estimatePoints ? "2" : "1"), [estimatePoints]);
|
||||
|
||||
return (
|
||||
<ModalCore isOpen={isOpen} handleClose={handleClose} position={EModalPosition.TOP} width={EModalWidth.XXL}>
|
||||
<ModalCore isOpen={isOpen} position={EModalPosition.TOP} width={EModalWidth.XXL}>
|
||||
<div className="relative space-y-6 py-5">
|
||||
{/* heading */}
|
||||
<div className="relative flex justify-between items-center gap-2 px-5">
|
||||
@ -90,7 +98,7 @@ export const CreateEstimateModal: FC<TCreateEstimateModal> = observer((props) =>
|
||||
<ChevronLeft className="w-4 h-4" />
|
||||
</div>
|
||||
)}
|
||||
<div className="text-xl font-medium text-custom-text-100">New Estimate System</div>
|
||||
<div className="text-xl font-medium text-custom-text-100">New estimate system</div>
|
||||
</div>
|
||||
<div className="text-xs text-gray-400">Step {renderEstimateStepsCount} of 2</div>
|
||||
</div>
|
||||
@ -107,16 +115,26 @@ export const CreateEstimateModal: FC<TCreateEstimateModal> = observer((props) =>
|
||||
/>
|
||||
)}
|
||||
{estimatePoints && (
|
||||
<>
|
||||
<EstimatePointCreateRoot
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
estimateId={undefined}
|
||||
estimateType={estimateSystem}
|
||||
estimatePoints={estimatePoints}
|
||||
setEstimatePoints={setEstimatePoints}
|
||||
/>
|
||||
</>
|
||||
<EstimatePointCreateRoot
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
estimateId={undefined}
|
||||
estimateType={estimateSystem}
|
||||
estimatePoints={estimatePoints}
|
||||
setEstimatePoints={setEstimatePoints}
|
||||
estimatePointCreate={estimatePointCreate}
|
||||
setEstimatePointCreate={(value) => {
|
||||
setEstimatePointCreateError([]);
|
||||
setEstimatePointCreate(value);
|
||||
}}
|
||||
estimatePointCreateError={estimatePointCreateError}
|
||||
/>
|
||||
)}
|
||||
{estimatePointCreateError.length > 0 && (
|
||||
<div className="pt-5 text-sm text-red-500">
|
||||
Estimate points can't be empty. Enter a value in each field or remove those you don't have
|
||||
values for.
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
@ -53,7 +53,7 @@ export const DeleteEstimateModal: FC<TDeleteEstimateModal> = observer((props) =>
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalCore isOpen={isOpen} handleClose={handleClose} position={EModalPosition.TOP} width={EModalWidth.XXL}>
|
||||
<ModalCore isOpen={isOpen} position={EModalPosition.TOP} width={EModalWidth.XXL}>
|
||||
<div className="relative space-y-6 py-5">
|
||||
{/* heading */}
|
||||
<div className="relative flex justify-between items-center gap-2 px-5">
|
||||
|
@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { Dispatch, FC, SetStateAction, useCallback, useState } from "react";
|
||||
import { Dispatch, FC, SetStateAction, useCallback } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Plus } from "lucide-react";
|
||||
import { TEstimatePointsObject, TEstimateSystemKeys } from "@plane/types";
|
||||
@ -17,13 +17,24 @@ type TEstimatePointCreateRoot = {
|
||||
estimateType: TEstimateSystemKeys;
|
||||
estimatePoints: TEstimatePointsObject[];
|
||||
setEstimatePoints: Dispatch<SetStateAction<TEstimatePointsObject[] | undefined>>;
|
||||
estimatePointCreate: TEstimatePointsObject[] | undefined;
|
||||
setEstimatePointCreate: Dispatch<SetStateAction<TEstimatePointsObject[] | undefined>>;
|
||||
estimatePointCreateError: number[];
|
||||
};
|
||||
|
||||
export const EstimatePointCreateRoot: FC<TEstimatePointCreateRoot> = observer((props) => {
|
||||
// props
|
||||
const { workspaceSlug, projectId, estimateId, estimateType, estimatePoints, setEstimatePoints } = props;
|
||||
// states
|
||||
const [estimatePointCreate, setEstimatePointCreate] = useState<TEstimatePointsObject[] | undefined>(undefined);
|
||||
const {
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
estimateId,
|
||||
estimateType,
|
||||
estimatePoints,
|
||||
setEstimatePoints,
|
||||
estimatePointCreate,
|
||||
setEstimatePointCreate,
|
||||
estimatePointCreateError,
|
||||
} = props;
|
||||
|
||||
const handleEstimatePoint = useCallback(
|
||||
(mode: "add" | "remove" | "update", value: TEstimatePointsObject) => {
|
||||
@ -77,9 +88,19 @@ export const EstimatePointCreateRoot: FC<TEstimatePointCreateRoot> = observer((p
|
||||
setEstimatePoints(() => updatedEstimateKeysOrder);
|
||||
};
|
||||
|
||||
const handleCreate = () => {
|
||||
if (estimatePoints && estimatePoints.length + (estimatePointCreate?.length || 0) <= maxEstimatesCount - 1) {
|
||||
handleEstimatePointCreate("add", {
|
||||
id: undefined,
|
||||
key: estimatePoints.length + (estimatePointCreate?.length || 0) + 1,
|
||||
value: "",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (!workspaceSlug || !projectId) return <></>;
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<div className="space-y-1">
|
||||
<div className="text-sm font-medium text-custom-text-200 capitalize">{estimateType}</div>
|
||||
|
||||
<div>
|
||||
@ -118,21 +139,12 @@ export const EstimatePointCreateRoot: FC<TEstimatePointCreateRoot> = observer((p
|
||||
handleEstimatePoint("add", { ...estimatePoint, value: estimatePointValue })
|
||||
}
|
||||
closeCallBack={() => handleEstimatePointCreate("remove", estimatePoint)}
|
||||
handleCreateCallback={() => estimatePointCreate.length === 1 && handleCreate()}
|
||||
isError={estimatePointCreateError.includes(estimatePoint.key) ? true : false}
|
||||
/>
|
||||
))}
|
||||
{estimatePoints && estimatePoints.length + (estimatePointCreate?.length || 0) <= maxEstimatesCount && (
|
||||
<Button
|
||||
variant="link-primary"
|
||||
size="sm"
|
||||
prependIcon={<Plus />}
|
||||
onClick={() =>
|
||||
handleEstimatePointCreate("add", {
|
||||
id: undefined,
|
||||
key: estimatePoints.length + (estimatePointCreate?.length || 0) + 1,
|
||||
value: "",
|
||||
})
|
||||
}
|
||||
>
|
||||
{estimatePoints && estimatePoints.length + (estimatePointCreate?.length || 0) <= maxEstimatesCount - 1 && (
|
||||
<Button variant="link-primary" size="sm" prependIcon={<Plus />} onClick={handleCreate}>
|
||||
Add {estimateType}
|
||||
</Button>
|
||||
)}
|
||||
|
@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { FC, MouseEvent, FocusEvent, useState } from "react";
|
||||
import { FC, useState, FormEvent, useEffect } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Check, Info, X } from "lucide-react";
|
||||
import { TEstimatePointsObject, TEstimateSystemKeys } from "@plane/types";
|
||||
@ -21,6 +21,8 @@ type TEstimatePointCreate = {
|
||||
estimatePoints: TEstimatePointsObject[];
|
||||
handleEstimatePointValue?: (estimateValue: string) => void;
|
||||
closeCallBack: () => void;
|
||||
handleCreateCallback: () => void;
|
||||
isError: boolean;
|
||||
};
|
||||
|
||||
export const EstimatePointCreate: FC<TEstimatePointCreate> = observer((props) => {
|
||||
@ -32,6 +34,8 @@ export const EstimatePointCreate: FC<TEstimatePointCreate> = observer((props) =>
|
||||
estimatePoints,
|
||||
handleEstimatePointValue,
|
||||
closeCallBack,
|
||||
handleCreateCallback,
|
||||
isError,
|
||||
} = props;
|
||||
// hooks
|
||||
const { creteEstimatePoint } = useEstimate(estimateId);
|
||||
@ -40,6 +44,13 @@ export const EstimatePointCreate: FC<TEstimatePointCreate> = observer((props) =>
|
||||
const [loader, setLoader] = useState(false);
|
||||
const [error, setError] = useState<string | undefined>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
if (isError && error === undefined && estimateInputValue.length > 0) {
|
||||
setError("Confirm this value first or discard it.");
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isError]);
|
||||
|
||||
const handleSuccess = (value: string) => {
|
||||
handleEstimatePointValue && handleEstimatePointValue(value);
|
||||
setEstimateInputValue("");
|
||||
@ -51,7 +62,12 @@ export const EstimatePointCreate: FC<TEstimatePointCreate> = observer((props) =>
|
||||
closeCallBack();
|
||||
};
|
||||
|
||||
const handleCreate = async (event: MouseEvent<HTMLButtonElement> | FocusEvent<HTMLInputElement, Element>) => {
|
||||
const handleEstimateInputValue = (value: string) => {
|
||||
setError(undefined);
|
||||
setEstimateInputValue(value);
|
||||
};
|
||||
|
||||
const handleCreate = async (event: FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
@ -110,6 +126,9 @@ export const EstimatePointCreate: FC<TEstimatePointCreate> = observer((props) =>
|
||||
}
|
||||
} else {
|
||||
handleSuccess(estimateInputValue);
|
||||
if (handleCreateCallback) {
|
||||
handleCreateCallback();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setLoader(false);
|
||||
@ -124,7 +143,7 @@ export const EstimatePointCreate: FC<TEstimatePointCreate> = observer((props) =>
|
||||
};
|
||||
|
||||
return (
|
||||
<form className="relative flex items-center gap-2 text-base">
|
||||
<form onSubmit={handleCreate} className="relative flex items-center gap-2 text-base">
|
||||
<div
|
||||
className={cn(
|
||||
"relative w-full border rounded flex items-center my-1",
|
||||
@ -134,42 +153,37 @@ export const EstimatePointCreate: FC<TEstimatePointCreate> = observer((props) =>
|
||||
<input
|
||||
type="text"
|
||||
value={estimateInputValue}
|
||||
onChange={(e) => setEstimateInputValue(e.target.value)}
|
||||
onChange={(e) => handleEstimateInputValue(e.target.value)}
|
||||
className="border-none focus:ring-0 focus:border-0 focus:outline-none p-2.5 w-full bg-transparent"
|
||||
placeholder="Enter estimate point"
|
||||
autoFocus
|
||||
onBlur={(e) => !estimateId && handleCreate(e)}
|
||||
/>
|
||||
{error && (
|
||||
<>
|
||||
<Tooltip tooltipContent={error} 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>
|
||||
</>
|
||||
<Tooltip tooltipContent={error} 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>
|
||||
|
||||
{estimateId && (
|
||||
<>
|
||||
<button
|
||||
type="submit"
|
||||
className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer text-green-500"
|
||||
disabled={loader}
|
||||
onClick={handleCreate}
|
||||
>
|
||||
{loader ? <Spinner className="w-4 h-4" /> : <Check size={14} />}
|
||||
</button>
|
||||
<button
|
||||
className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer"
|
||||
onClick={handleClose}
|
||||
disabled={loader}
|
||||
>
|
||||
<X size={14} className="text-custom-text-200" />
|
||||
</button>
|
||||
</>
|
||||
{estimateInputValue && estimateInputValue.length > 0 && (
|
||||
<button
|
||||
type="submit"
|
||||
className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer text-green-500"
|
||||
disabled={loader}
|
||||
>
|
||||
{loader ? <Spinner className="w-4 h-4" /> : <Check size={14} />}
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer"
|
||||
onClick={handleClose}
|
||||
disabled={loader}
|
||||
>
|
||||
<X size={14} className="text-custom-text-200" />
|
||||
</button>
|
||||
</form>
|
||||
);
|
||||
});
|
||||
|
@ -4,6 +4,7 @@ import { GripVertical, Pencil, Trash2 } from "lucide-react";
|
||||
import { TEstimatePointsObject, TEstimateSystemKeys } from "@plane/types";
|
||||
// components
|
||||
import { EstimatePointUpdate, EstimatePointDelete } from "@/components/estimates/points";
|
||||
import { minEstimatesCount } from "@/constants/estimates";
|
||||
|
||||
type TEstimatePointItemPreview = {
|
||||
workspaceSlug: string;
|
||||
@ -60,16 +61,18 @@ export const EstimatePointItemPreview: FC<TEstimatePointItemPreview> = observer(
|
||||
>
|
||||
<Pencil size={14} className="text-custom-text-200" />
|
||||
</div>
|
||||
<div
|
||||
className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer"
|
||||
onClick={() =>
|
||||
estimateId && estimatePointId
|
||||
? setEstimatePointDeleteToggle(true)
|
||||
: handleEstimatePointValueRemove && handleEstimatePointValueRemove()
|
||||
}
|
||||
>
|
||||
<Trash2 size={14} className="text-custom-text-200" />
|
||||
</div>
|
||||
{estimatePoints.length > minEstimatesCount && (
|
||||
<div
|
||||
className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer"
|
||||
onClick={() =>
|
||||
estimateId && estimatePointId
|
||||
? setEstimatePointDeleteToggle(true)
|
||||
: handleEstimatePointValueRemove && handleEstimatePointValueRemove()
|
||||
}
|
||||
>
|
||||
<Trash2 size={14} className="text-custom-text-200" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { FC, MouseEvent, useEffect, FocusEvent, useState } from "react";
|
||||
import { FC, useEffect, useState, FormEvent } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Check, Info, X } from "lucide-react";
|
||||
import { TEstimatePointsObject, TEstimateSystemKeys } from "@plane/types";
|
||||
@ -59,7 +59,12 @@ export const EstimatePointUpdate: FC<TEstimatePointUpdate> = observer((props) =>
|
||||
closeCallBack();
|
||||
};
|
||||
|
||||
const handleUpdate = async (event: MouseEvent<HTMLButtonElement> | FocusEvent<HTMLInputElement, Element>) => {
|
||||
const handleEstimateInputValue = (value: string) => {
|
||||
setError(undefined);
|
||||
setEstimateInputValue(() => value);
|
||||
};
|
||||
|
||||
const handleUpdate = async (event: FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
@ -71,7 +76,7 @@ export const EstimatePointUpdate: FC<TEstimatePointUpdate> = observer((props) =>
|
||||
let isEstimateValid = false;
|
||||
|
||||
const currentEstimatePointValues = estimatePoints
|
||||
.map((point) => (point?.id != estimatePoint?.id ? point?.value : undefined))
|
||||
.map((point) => (point?.key != estimatePoint?.key ? point?.value : undefined))
|
||||
.filter((value) => value != undefined) as string[];
|
||||
const isRepeated =
|
||||
(estimateType && isEstimatePointValuesRepeated(currentEstimatePointValues, estimateType, estimateInputValue)) ||
|
||||
@ -136,7 +141,7 @@ export const EstimatePointUpdate: FC<TEstimatePointUpdate> = observer((props) =>
|
||||
};
|
||||
|
||||
return (
|
||||
<form className="relative flex items-center gap-2 text-base">
|
||||
<form onSubmit={handleUpdate} className="relative flex items-center gap-2 text-base">
|
||||
<div
|
||||
className={cn(
|
||||
"relative w-full border rounded flex items-center my-1",
|
||||
@ -146,10 +151,9 @@ export const EstimatePointUpdate: FC<TEstimatePointUpdate> = observer((props) =>
|
||||
<input
|
||||
type="text"
|
||||
value={estimateInputValue}
|
||||
onChange={(e) => setEstimateInputValue(e.target.value)}
|
||||
onChange={(e) => handleEstimateInputValue(e.target.value)}
|
||||
className="border-none focus:ring-0 focus:border-0 focus:outline-none p-2.5 w-full bg-transparent"
|
||||
placeholder="Enter estimate point"
|
||||
onBlur={(e) => !estimateId && handleUpdate(e)}
|
||||
autoFocus
|
||||
/>
|
||||
{error && (
|
||||
@ -162,25 +166,24 @@ export const EstimatePointUpdate: FC<TEstimatePointUpdate> = observer((props) =>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{estimateId && (
|
||||
<>
|
||||
<button
|
||||
type="submit"
|
||||
className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer text-green-500"
|
||||
disabled={loader}
|
||||
onClick={handleUpdate}
|
||||
>
|
||||
{loader ? <Spinner className="w-4 h-4" /> : <Check size={14} />}
|
||||
</button>
|
||||
<button
|
||||
className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer"
|
||||
onClick={handleClose}
|
||||
disabled={loader}
|
||||
>
|
||||
<X size={14} className="text-custom-text-200" />
|
||||
</button>
|
||||
</>
|
||||
|
||||
{estimateInputValue && estimateInputValue.length > 0 && (
|
||||
<button
|
||||
type="submit"
|
||||
className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer text-green-500"
|
||||
disabled={loader}
|
||||
>
|
||||
{loader ? <Spinner className="w-4 h-4" /> : <Check size={14} />}
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-sm w-6 h-6 flex-shrink-0 relative flex justify-center items-center hover:bg-custom-background-80 transition-colors cursor-pointer"
|
||||
onClick={handleClose}
|
||||
disabled={loader}
|
||||
>
|
||||
<X size={14} className="text-custom-text-200" />
|
||||
</button>
|
||||
</form>
|
||||
);
|
||||
});
|
||||
|
@ -20,7 +20,7 @@ export const UpdateEstimateModal: FC<TUpdateEstimateModal> = observer((props) =>
|
||||
const { isOpen, handleClose } = props;
|
||||
|
||||
return (
|
||||
<ModalCore isOpen={isOpen} handleClose={handleClose} position={EModalPosition.TOP} width={EModalWidth.XXL}>
|
||||
<ModalCore isOpen={isOpen} position={EModalPosition.TOP} width={EModalWidth.XXL}>
|
||||
<div className="relative space-y-6 py-5">
|
||||
{/* heading */}
|
||||
<div className="relative flex justify-between items-center gap-2 px-5">
|
||||
|
@ -13,7 +13,8 @@ export enum EEstimateUpdateStages {
|
||||
SWITCH = "switch",
|
||||
}
|
||||
|
||||
export const maxEstimatesCount = 11;
|
||||
export const minEstimatesCount = 2;
|
||||
export const maxEstimatesCount = 6;
|
||||
|
||||
export const ESTIMATE_SYSTEMS: TEstimateSystems = {
|
||||
points: {
|
||||
@ -28,7 +29,6 @@ export const ESTIMATE_SYSTEMS: TEstimateSystems = {
|
||||
{ id: undefined, key: 4, value: "5" },
|
||||
{ id: undefined, key: 5, value: "8" },
|
||||
{ id: undefined, key: 6, value: "13" },
|
||||
{ id: undefined, key: 7, value: "21" },
|
||||
],
|
||||
},
|
||||
linear: {
|
||||
@ -40,10 +40,6 @@ export const ESTIMATE_SYSTEMS: TEstimateSystems = {
|
||||
{ id: undefined, key: 4, value: "4" },
|
||||
{ id: undefined, key: 5, value: "5" },
|
||||
{ id: undefined, key: 6, value: "6" },
|
||||
{ id: undefined, key: 7, value: "7" },
|
||||
{ id: undefined, key: 8, value: "8" },
|
||||
{ id: undefined, key: 9, value: "9" },
|
||||
{ id: undefined, key: 10, value: "10" },
|
||||
],
|
||||
},
|
||||
squares: {
|
||||
@ -116,10 +112,6 @@ export const ESTIMATE_SYSTEMS: TEstimateSystems = {
|
||||
{ id: undefined, key: 4, value: "4" },
|
||||
{ id: undefined, key: 5, value: "5" },
|
||||
{ id: undefined, key: 6, value: "6" },
|
||||
{ id: undefined, key: 7, value: "7" },
|
||||
{ id: undefined, key: 8, value: "8" },
|
||||
{ id: undefined, key: 9, value: "9" },
|
||||
{ id: undefined, key: 10, value: "10" },
|
||||
],
|
||||
},
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user