diff --git a/front/src/modules/companies/components/CompanyBoardCard.tsx b/front/src/modules/companies/components/CompanyBoardCard.tsx
index fee2491752..1bc5dae9f9 100644
--- a/front/src/modules/companies/components/CompanyBoardCard.tsx
+++ b/front/src/modules/companies/components/CompanyBoardCard.tsx
@@ -10,8 +10,8 @@ import { BoardCardContext } from '@/pipeline/states/BoardCardContext';
import { pipelineProgressIdScopedState } from '@/pipeline/states/pipelineProgressIdScopedState';
import { selectedBoardCardsState } from '@/pipeline/states/selectedBoardCardsState';
import { BoardCardEditableFieldDate } from '@/ui/board/card-field/components/BoardCardEditableFieldDate';
-import { BoardCardEditableFieldText } from '@/ui/board/card-field/components/BoardCardEditableFieldText';
import { ChipVariant } from '@/ui/chip/components/EntityChip';
+import { NumberEditableField } from '@/ui/editable-field/variants/components/NumberEditableField';
import { IconCurrencyDollar } from '@/ui/icon';
import { IconCalendarEvent } from '@/ui/icon';
import { Checkbox } from '@/ui/input/components/Checkbox';
@@ -22,6 +22,8 @@ import {
} from '~/generated/graphql';
import { getLogoUrlFromDomainName } from '~/utils';
+import { CompanyAccountOwnerEditableField } from '../editable-field/components/CompanyAccountOwnerEditableField';
+
import { CompanyChip } from './CompanyChip';
const StyledBoardCard = styled.div<{ selected: boolean }>`
@@ -143,19 +145,18 @@ export function CompanyBoardCard() {
-
-
-
- handleCardUpdate({
- ...pipelineProgress,
- amount: parseInt(value),
- })
- }
- />
-
+ }
+ placeholder="Opportunity amount"
+ value={pipelineProgress.amount}
+ onSubmit={(value) =>
+ handleCardUpdate({
+ ...pipelineProgress,
+ amount: value,
+ })
+ }
+ />
+
}
editModeContent={
@@ -44,6 +37,7 @@ export function CompanyAccountOwnerEditableField({ company }: OwnProps) {
<>>
)
}
+ isDisplayModeContentEmpty={!company.accountOwner}
/>
diff --git a/front/src/modules/companies/editable-field/components/CompanyCreatedAtEditableField.tsx b/front/src/modules/companies/editable-field/components/CompanyCreatedAtEditableField.tsx
index 9eb61352a2..dcda0fe260 100644
--- a/front/src/modules/companies/editable-field/components/CompanyCreatedAtEditableField.tsx
+++ b/front/src/modules/companies/editable-field/components/CompanyCreatedAtEditableField.tsx
@@ -1,8 +1,8 @@
import { useEffect, useState } from 'react';
import { EditableField } from '@/ui/editable-field/components/EditableField';
+import { EditableFieldEditModeDate } from '@/ui/editable-field/components/EditableFieldEditModeDate';
import { FieldContext } from '@/ui/editable-field/states/FieldContext';
-import { EditableFieldEditModeDate } from '@/ui/editable-field/variants/components/EditableFieldEditModeDate';
import { IconCalendar } from '@/ui/icon';
import { RecoilScope } from '@/ui/recoil-scope/components/RecoilScope';
import { Company, useUpdateCompanyMutation } from '~/generated/graphql';
diff --git a/front/src/modules/pipeline/progress/components/PipelineProgressAmountEditableField.tsx b/front/src/modules/pipeline/progress/components/PipelineProgressAmountEditableField.tsx
new file mode 100644
index 0000000000..338b2807ac
--- /dev/null
+++ b/front/src/modules/pipeline/progress/components/PipelineProgressAmountEditableField.tsx
@@ -0,0 +1,79 @@
+import { useEffect, useState } from 'react';
+
+import { EditableField } from '@/ui/editable-field/components/EditableField';
+import { FieldContext } from '@/ui/editable-field/states/FieldContext';
+import { IconCurrencyDollar } from '@/ui/icon';
+import { InplaceInputText } from '@/ui/inplace-input/components/InplaceInputText';
+import { RecoilScope } from '@/ui/recoil-scope/components/RecoilScope';
+import {
+ PipelineProgress,
+ useUpdateOnePipelineProgressMutation,
+} from '~/generated/graphql';
+
+type OwnProps = {
+ progress: Pick;
+};
+
+export function PipelineProgressAmountEditableField({ progress }: OwnProps) {
+ const [internalValue, setInternalValue] = useState(
+ progress.amount?.toString(),
+ );
+
+ const [updateOnePipelineProgress] = useUpdateOnePipelineProgressMutation();
+
+ useEffect(() => {
+ setInternalValue(progress.amount?.toString());
+ }, [progress.amount]);
+
+ async function handleChange(newValue: string) {
+ setInternalValue(newValue);
+ }
+
+ async function handleSubmit() {
+ if (!internalValue) return;
+
+ try {
+ const numberValue = parseInt(internalValue);
+
+ if (isNaN(numberValue)) {
+ throw new Error('Not a number');
+ }
+
+ await updateOnePipelineProgress({
+ variables: {
+ id: progress.id,
+ amount: numberValue,
+ },
+ });
+
+ setInternalValue(numberValue.toString());
+ } catch {
+ handleCancel();
+ }
+ }
+
+ async function handleCancel() {
+ setInternalValue(progress.amount?.toString());
+ }
+
+ return (
+
+ }
+ editModeContent={
+ {
+ handleChange(newValue);
+ }}
+ />
+ }
+ displayModeContent={internalValue}
+ />
+
+ );
+}
diff --git a/front/src/modules/ui/editable-field/variants/components/EditableFieldEditModeDate.tsx b/front/src/modules/ui/editable-field/components/EditableFieldEditModeDate.tsx
similarity index 91%
rename from front/src/modules/ui/editable-field/variants/components/EditableFieldEditModeDate.tsx
rename to front/src/modules/ui/editable-field/components/EditableFieldEditModeDate.tsx
index 28878d1ddc..fa0a6f784d 100644
--- a/front/src/modules/ui/editable-field/variants/components/EditableFieldEditModeDate.tsx
+++ b/front/src/modules/ui/editable-field/components/EditableFieldEditModeDate.tsx
@@ -2,7 +2,7 @@ import { HotkeyScope } from '@/ui/hotkey/types/HotkeyScope';
import { InplaceInputDate } from '@/ui/inplace-input/components/InplaceInputDate';
import { parseDate } from '~/utils/date-utils';
-import { useEditableField } from '../../hooks/useEditableField';
+import { useEditableField } from '../hooks/useEditableField';
type OwnProps = {
value: string;
diff --git a/front/src/modules/ui/editable-field/variants/components/NumberEditableField.tsx b/front/src/modules/ui/editable-field/variants/components/NumberEditableField.tsx
new file mode 100644
index 0000000000..2a23b2dfd8
--- /dev/null
+++ b/front/src/modules/ui/editable-field/variants/components/NumberEditableField.tsx
@@ -0,0 +1,79 @@
+import { useEffect, useState } from 'react';
+
+import { EditableField } from '@/ui/editable-field/components/EditableField';
+import { FieldContext } from '@/ui/editable-field/states/FieldContext';
+import { InplaceInputText } from '@/ui/inplace-input/components/InplaceInputText';
+import { RecoilScope } from '@/ui/recoil-scope/components/RecoilScope';
+
+type OwnProps = {
+ icon?: React.ReactNode;
+ placeholder?: string;
+ value: number | null | undefined;
+ onSubmit?: (newValue: number) => void;
+};
+
+export function NumberEditableField({
+ icon,
+ placeholder,
+ value,
+ onSubmit,
+}: OwnProps) {
+ const [internalValue, setInternalValue] = useState(value?.toString());
+
+ useEffect(() => {
+ setInternalValue(value?.toString());
+ }, [value]);
+
+ async function handleChange(newValue: string) {
+ setInternalValue(newValue);
+ }
+
+ async function handleSubmit() {
+ if (!internalValue) return;
+
+ try {
+ const numberValue = parseInt(internalValue);
+
+ if (isNaN(numberValue)) {
+ throw new Error('Not a number');
+ }
+
+ // TODO: find a way to store this better in DB
+ if (numberValue > 2000000000) {
+ throw new Error('Number too big');
+ }
+
+ onSubmit?.(numberValue);
+
+ setInternalValue(numberValue.toString());
+ } catch {
+ handleCancel();
+ }
+ }
+
+ async function handleCancel() {
+ setInternalValue(value?.toString());
+ }
+
+ return (
+
+ {
+ handleChange(newValue);
+ }}
+ />
+ }
+ displayModeContent={internalValue}
+ isDisplayModeContentEmpty={!(internalValue !== '')}
+ />
+
+ );
+}
diff --git a/front/src/modules/ui/editable-field/variants/components/TextEditableField.tsx b/front/src/modules/ui/editable-field/variants/components/TextEditableField.tsx
new file mode 100644
index 0000000000..d180f10ee7
--- /dev/null
+++ b/front/src/modules/ui/editable-field/variants/components/TextEditableField.tsx
@@ -0,0 +1,62 @@
+import { useEffect, useState } from 'react';
+
+import { EditableField } from '@/ui/editable-field/components/EditableField';
+import { FieldContext } from '@/ui/editable-field/states/FieldContext';
+import { InplaceInputText } from '@/ui/inplace-input/components/InplaceInputText';
+import { RecoilScope } from '@/ui/recoil-scope/components/RecoilScope';
+
+type OwnProps = {
+ icon?: React.ReactNode;
+ placeholder?: string;
+ value: string | null | undefined;
+ onSubmit?: (newValue: string) => void;
+};
+
+export function TextEditableField({
+ icon,
+ placeholder,
+ value,
+ onSubmit,
+}: OwnProps) {
+ const [internalValue, setInternalValue] = useState(value);
+
+ useEffect(() => {
+ setInternalValue(value);
+ }, [value]);
+
+ async function handleChange(newValue: string) {
+ setInternalValue(newValue);
+ }
+
+ async function handleSubmit() {
+ if (!internalValue) return;
+
+ onSubmit?.(internalValue);
+ }
+
+ async function handleCancel() {
+ setInternalValue(value);
+ }
+
+ return (
+
+ {
+ handleChange(newValue);
+ }}
+ />
+ }
+ displayModeContent={internalValue}
+ isDisplayModeContentEmpty={!(internalValue !== '')}
+ />
+
+ );
+}