Rename Money/Url to Currency/Link and remove snake_case from composite fields (#2536)

* Rename Money/Url to Currency/Link

* regenerate front types

* renaming money/url field types

* fix double text

* fix tests

* fix server tests

* fix generate-target-column-map

* fix currency convert

* fix: tests

---------

Co-authored-by: Jérémy Magrin <jeremy.magrin@gmail.com>
This commit is contained in:
Weiko
2023-11-17 10:31:17 +01:00
committed by GitHub
parent 31e439681c
commit bc579d64a6
56 changed files with 579 additions and 512 deletions

View File

@ -6,30 +6,30 @@ import { isFieldUuid } from '@/ui/object/field/types/guards/isFieldUuid';
import { FieldContext } from '../contexts/FieldContext';
import { ChipFieldDisplay } from '../meta-types/display/components/ChipFieldDisplay';
import { CurrencyFieldDisplay } from '../meta-types/display/components/CurrencyFieldDisplay';
import { DateFieldDisplay } from '../meta-types/display/components/DateFieldDisplay';
import { DoubleTextChipFieldDisplay } from '../meta-types/display/components/DoubleTextChipFieldDisplay';
import { DoubleTextFieldDisplay } from '../meta-types/display/components/DoubleTextFieldDisplay';
import { EmailFieldDisplay } from '../meta-types/display/components/EmailFieldDisplay';
import { MoneyAmountV2FieldDisplay } from '../meta-types/display/components/MoneyAmountV2FieldDisplay';
import { LinkFieldDisplay } from '../meta-types/display/components/LinkFieldDisplay';
import { MoneyFieldDisplay } from '../meta-types/display/components/MoneyFieldDisplay';
import { NumberFieldDisplay } from '../meta-types/display/components/NumberFieldDisplay';
import { PhoneFieldDisplay } from '../meta-types/display/components/PhoneFieldDisplay';
import { TextFieldDisplay } from '../meta-types/display/components/TextFieldDisplay';
import { URLFieldDisplay } from '../meta-types/display/components/URLFieldDisplay';
import { URLV2FieldDisplay } from '../meta-types/display/components/URLV2FieldDisplay';
import { isFieldChip } from '../types/guards/isFieldChip';
import { isFieldCurrency } from '../types/guards/isFieldCurrency';
import { isFieldDate } from '../types/guards/isFieldDate';
import { isFieldDoubleText } from '../types/guards/isFieldDoubleText';
import { isFieldDoubleTextChip } from '../types/guards/isFieldDoubleTextChip';
import { isFieldEmail } from '../types/guards/isFieldEmail';
import { isFieldLink } from '../types/guards/isFieldLink';
import { isFieldMoney } from '../types/guards/isFieldMoney';
import { isFieldMoneyAmountV2 } from '../types/guards/isFieldMoneyAmountV2';
import { isFieldNumber } from '../types/guards/isFieldNumber';
import { isFieldPhone } from '../types/guards/isFieldPhone';
import { isFieldRelation } from '../types/guards/isFieldRelation';
import { isFieldText } from '../types/guards/isFieldText';
import { isFieldURL } from '../types/guards/isFieldURL';
import { isFieldURLV2 } from '../types/guards/isFieldURLV2';
export const FieldDisplay = () => {
const { fieldDefinition } = useContext(FieldContext);
@ -52,10 +52,10 @@ export const FieldDisplay = () => {
<MoneyFieldDisplay />
) : isFieldURL(fieldDefinition) ? (
<URLFieldDisplay />
) : isFieldURLV2(fieldDefinition) ? (
<URLV2FieldDisplay />
) : isFieldMoneyAmountV2(fieldDefinition) ? (
<MoneyAmountV2FieldDisplay />
) : isFieldLink(fieldDefinition) ? (
<LinkFieldDisplay />
) : isFieldCurrency(fieldDefinition) ? (
<CurrencyFieldDisplay />
) : isFieldPhone(fieldDefinition) ? (
<PhoneFieldDisplay />
) : isFieldChip(fieldDefinition) ? (

View File

@ -5,11 +5,12 @@ import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'
import { FieldContext } from '../contexts/FieldContext';
import { BooleanFieldInput } from '../meta-types/input/components/BooleanFieldInput';
import { ChipFieldInput } from '../meta-types/input/components/ChipFieldInput';
import { CurrencyFieldInput } from '../meta-types/input/components/CurrencyFieldInput';
import { DateFieldInput } from '../meta-types/input/components/DateFieldInput';
import { DoubleTextChipFieldInput } from '../meta-types/input/components/DoubleTextChipFieldInput';
import { DoubleTextFieldInput } from '../meta-types/input/components/DoubleTextFieldInput';
import { EmailFieldInput } from '../meta-types/input/components/EmailFieldInput';
import { MoneyAmountV2FieldInput } from '../meta-types/input/components/MoneyAmountV2FieldInput';
import { LinkFieldInput } from '../meta-types/input/components/LinkFieldInput';
import { MoneyFieldInput } from '../meta-types/input/components/MoneyFieldInput';
import { NumberFieldInput } from '../meta-types/input/components/NumberFieldInput';
import { PhoneFieldInput } from '../meta-types/input/components/PhoneFieldInput';
@ -17,23 +18,22 @@ import { ProbabilityFieldInput } from '../meta-types/input/components/Probabilit
import { RelationFieldInput } from '../meta-types/input/components/RelationFieldInput';
import { TextFieldInput } from '../meta-types/input/components/TextFieldInput';
import { URLFieldInput } from '../meta-types/input/components/URLFieldInput';
import { URLV2FieldInput } from '../meta-types/input/components/URLV2FieldInput';
import { FieldInputEvent } from '../types/FieldInputEvent';
import { isFieldBoolean } from '../types/guards/isFieldBoolean';
import { isFieldChip } from '../types/guards/isFieldChip';
import { isFieldCurrency } from '../types/guards/isFieldCurrency';
import { isFieldDate } from '../types/guards/isFieldDate';
import { isFieldDoubleText } from '../types/guards/isFieldDoubleText';
import { isFieldDoubleTextChip } from '../types/guards/isFieldDoubleTextChip';
import { isFieldEmail } from '../types/guards/isFieldEmail';
import { isFieldLink } from '../types/guards/isFieldLink';
import { isFieldMoney } from '../types/guards/isFieldMoney';
import { isFieldMoneyAmountV2 } from '../types/guards/isFieldMoneyAmountV2';
import { isFieldNumber } from '../types/guards/isFieldNumber';
import { isFieldPhone } from '../types/guards/isFieldPhone';
import { isFieldProbability } from '../types/guards/isFieldProbability';
import { isFieldRelation } from '../types/guards/isFieldRelation';
import { isFieldText } from '../types/guards/isFieldText';
import { isFieldURL } from '../types/guards/isFieldURL';
import { isFieldURLV2 } from '../types/guards/isFieldURLV2';
type FieldInputProps = {
onSubmit?: FieldInputEvent;
@ -102,16 +102,16 @@ export const FieldInput = ({
onTab={onTab}
onShiftTab={onShiftTab}
/>
) : isFieldURLV2(fieldDefinition) ? (
<URLV2FieldInput
) : isFieldLink(fieldDefinition) ? (
<LinkFieldInput
onEnter={onEnter}
onEscape={onEscape}
onClickOutside={onClickOutside}
onTab={onTab}
onShiftTab={onShiftTab}
/>
) : isFieldMoneyAmountV2(fieldDefinition) ? (
<MoneyAmountV2FieldInput
) : isFieldCurrency(fieldDefinition) ? (
<CurrencyFieldInput
onEnter={onEnter}
onEscape={onEscape}
onClickOutside={onClickOutside}

View File

@ -7,6 +7,8 @@ import { isFieldBoolean } from '../types/guards/isFieldBoolean';
import { isFieldBooleanValue } from '../types/guards/isFieldBooleanValue';
import { isFieldChip } from '../types/guards/isFieldChip';
import { isFieldChipValue } from '../types/guards/isFieldChipValue';
import { isFieldCurrency } from '../types/guards/isFieldCurrency';
import { isFieldCurrencyValue } from '../types/guards/isFieldCurrencyValue';
import { isFieldDate } from '../types/guards/isFieldDate';
import { isFieldDateValue } from '../types/guards/isFieldDateValue';
import { isFieldDoubleText } from '../types/guards/isFieldDoubleText';
@ -15,9 +17,9 @@ import { isFieldDoubleTextChipValue } from '../types/guards/isFieldDoubleTextChi
import { isFieldDoubleTextValue } from '../types/guards/isFieldDoubleTextValue';
import { isFieldEmail } from '../types/guards/isFieldEmail';
import { isFieldEmailValue } from '../types/guards/isFieldEmailValue';
import { isFieldLink } from '../types/guards/isFieldLink';
import { isFieldLinkValue } from '../types/guards/isFieldLinkValue';
import { isFieldMoney } from '../types/guards/isFieldMoney';
import { isFieldMoneyAmountV2 } from '../types/guards/isFieldMoneyAmountV2';
import { isFieldMoneyAmountV2Value } from '../types/guards/isFieldMoneyAmountV2Value';
import { isFieldMoneyValue } from '../types/guards/isFieldMoneyValue';
import { isFieldNumber } from '../types/guards/isFieldNumber';
import { isFieldNumberValue } from '../types/guards/isFieldNumberValue';
@ -30,8 +32,6 @@ import { isFieldRelationValue } from '../types/guards/isFieldRelationValue';
import { isFieldText } from '../types/guards/isFieldText';
import { isFieldTextValue } from '../types/guards/isFieldTextValue';
import { isFieldURL } from '../types/guards/isFieldURL';
import { isFieldURLV2 } from '../types/guards/isFieldURLV2';
import { isFieldURLV2Value } from '../types/guards/isFieldURLV2Value';
import { isFieldURLValue } from '../types/guards/isFieldURLValue';
export const usePersistField = () => {
@ -73,8 +73,8 @@ export const usePersistField = () => {
const fieldIsURL =
isFieldURL(fieldDefinition) && isFieldURLValue(valueToPersist);
const fieldIsURLV2 =
isFieldURLV2(fieldDefinition) && isFieldURLV2Value(valueToPersist);
const fieldIsLink =
isFieldLink(fieldDefinition) && isFieldLinkValue(valueToPersist);
const fieldIsBoolean =
isFieldBoolean(fieldDefinition) &&
@ -90,9 +90,9 @@ export const usePersistField = () => {
const fieldIsMoney =
isFieldMoney(fieldDefinition) && isFieldMoneyValue(valueToPersist);
const fieldIsMoneyAmountV2 =
isFieldMoneyAmountV2(fieldDefinition) &&
isFieldMoneyAmountV2Value(valueToPersist);
const fieldIsCurrency =
isFieldCurrency(fieldDefinition) &&
isFieldCurrencyValue(valueToPersist);
const fieldIsPhone =
isFieldPhone(fieldDefinition) && isFieldPhoneValue(valueToPersist);
@ -169,8 +169,8 @@ export const usePersistField = () => {
fieldIsMoney ||
fieldIsDate ||
fieldIsPhone ||
fieldIsURLV2 ||
fieldIsMoneyAmountV2
fieldIsLink ||
fieldIsCurrency
) {
const fieldName = fieldDefinition.metadata.fieldName;

View File

@ -0,0 +1,8 @@
import { useCurrencyField } from '../../hooks/useCurrencyField';
import { CurrencyDisplay } from '../content-display/components/CurrencyDisplay';
export const CurrencyFieldDisplay = () => {
const { fieldValue } = useCurrencyField();
return <CurrencyDisplay value={fieldValue} />;
};

View File

@ -0,0 +1,8 @@
import { useLinkField } from '../../hooks/useLinkField';
import { LinkDisplay } from '../content-display/components/LinkDisplay';
export const LinkFieldDisplay = () => {
const { fieldValue } = useLinkField();
return <LinkDisplay value={fieldValue} />;
};

View File

@ -1,8 +0,0 @@
import { useMoneyAmountV2Field } from '../../hooks/useMoneyAmountV2Field';
import { MoneyAmountV2Display } from '../content-display/components/MoneyAmountV2Display';
export const MoneyAmountV2FieldDisplay = () => {
const { fieldValue } = useMoneyAmountV2Field();
return <MoneyAmountV2Display value={fieldValue} />;
};

View File

@ -1,8 +0,0 @@
import { useURLV2Field } from '../../hooks/useURLV2Field';
import { URLV2Display } from '../content-display/components/URLDisplayV2';
export const URLV2FieldDisplay = () => {
const { fieldValue } = useURLV2Field();
return <URLV2Display value={fieldValue} />;
};

View File

@ -0,0 +1,18 @@
import { FieldCurrencyValue } from '@/ui/object/field/types/FieldMetadata';
import { convertCurrencyMicrosToCurrency } from '~/utils/convert-currency-amount';
import { EllipsisDisplay } from './EllipsisDisplay';
type CurrencyDisplayProps = {
value?: FieldCurrencyValue;
};
// TODO: convert currencyCode to currency symbol
export const CurrencyDisplay = ({ value }: CurrencyDisplayProps) => {
return (
<EllipsisDisplay>
{convertCurrencyMicrosToCurrency(value?.amountMicros)}{' '}
{value?.currencyCode}
</EllipsisDisplay>
);
};

View File

@ -6,7 +6,7 @@ import {
LinkType,
SocialLink,
} from '@/ui/navigation/link/components/SocialLink';
import { FieldURLV2Value } from '@/ui/object/field/types/FieldMetadata';
import { FieldLinkValue } from '@/ui/object/field/types/FieldMetadata';
import { EllipsisDisplay } from './EllipsisDisplay';
@ -20,8 +20,8 @@ const StyledRawLink = styled(RoundedLink)`
}
`;
type URLV2DisplayProps = {
value?: FieldURLV2Value;
type LinkDisplayProps = {
value?: FieldLinkValue;
};
const checkUrlType = (url: string) => {
@ -39,18 +39,18 @@ const checkUrlType = (url: string) => {
return LinkType.Url;
};
export const URLV2Display = ({ value }: URLV2DisplayProps) => {
export const LinkDisplay = ({ value }: LinkDisplayProps) => {
const handleClick = (event: MouseEvent<HTMLElement>) => {
event.stopPropagation();
};
const absoluteUrl = value?.link
? value.link.startsWith('http')
? value.link
: 'https://' + value.link
const absoluteUrl = value?.url
? value.url.startsWith('http')
? value.url
: 'https://' + value.url
: '';
const displayedValue = value?.text || value?.link || '';
const displayedValue = value?.label || value?.url || '';
const type = checkUrlType(absoluteUrl);

View File

@ -1,15 +0,0 @@
import { FieldMoneyAmountV2Value } from '@/ui/object/field/types/FieldMetadata';
import { EllipsisDisplay } from './EllipsisDisplay';
type MoneyAmountV2DisplayProps = {
value?: FieldMoneyAmountV2Value;
};
export const MoneyAmountV2Display = ({ value }: MoneyAmountV2DisplayProps) => {
return (
<EllipsisDisplay>
{value?.amount} {value?.currency}
</EllipsisDisplay>
);
};

View File

@ -5,19 +5,19 @@ import { FieldContext } from '../../contexts/FieldContext';
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
import { usePersistField } from '../../hooks/usePersistField';
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
import { FieldMoneyAmountV2Value } from '../../types/FieldMetadata';
import { FieldCurrencyValue } from '../../types/FieldMetadata';
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
import { isFieldMoneyAmountV2 } from '../../types/guards/isFieldMoneyAmountV2';
import { isFieldMoneyAmountV2Value } from '../../types/guards/isFieldMoneyAmountV2Value';
import { isFieldCurrency } from '../../types/guards/isFieldCurrency';
import { isFieldCurrencyValue } from '../../types/guards/isFieldCurrencyValue';
export const useMoneyAmountV2Field = () => {
export const useCurrencyField = () => {
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
assertFieldMetadata('MONEY_AMOUNT_V2', isFieldMoneyAmountV2, fieldDefinition);
assertFieldMetadata('CURRENCY', isFieldCurrency, fieldDefinition);
const fieldName = fieldDefinition.metadata.fieldName;
const [fieldValue, setFieldValue] = useRecoilState<FieldMoneyAmountV2Value>(
const [fieldValue, setFieldValue] = useRecoilState<FieldCurrencyValue>(
entityFieldsFamilySelector({
entityId: entityId,
fieldName: fieldName,
@ -26,8 +26,8 @@ export const useMoneyAmountV2Field = () => {
const persistField = usePersistField();
const persistMoneyAmountV2Field = (newValue: FieldMoneyAmountV2Value) => {
if (!isFieldMoneyAmountV2Value(newValue)) {
const persistCurrencyField = (newValue: FieldCurrencyValue) => {
if (!isFieldCurrencyValue(newValue)) {
return;
}
@ -36,11 +36,11 @@ export const useMoneyAmountV2Field = () => {
const fieldInitialValue = useFieldInitialValue();
const initialValue: FieldMoneyAmountV2Value = fieldInitialValue?.isEmpty
? { amount: 0, currency: '' }
const initialValue: FieldCurrencyValue = fieldInitialValue?.isEmpty
? { amountMicros: 0, currencyCode: '' }
: !isNaN(Number(fieldInitialValue?.value))
? { amount: Number(fieldInitialValue?.value), currency: '' }
: { amount: 0, currency: '' } ?? fieldValue;
? { amountMicros: Number(fieldInitialValue?.value), currencyCode: '' }
: { amountMicros: 0, currencyCode: '' } ?? fieldValue;
return {
fieldDefinition,
@ -48,6 +48,6 @@ export const useMoneyAmountV2Field = () => {
initialValue,
setFieldValue,
hotkeyScope,
persistMoneyAmountV2Field,
persistCurrencyField,
};
};

View File

@ -5,19 +5,19 @@ import { FieldContext } from '../../contexts/FieldContext';
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
import { usePersistField } from '../../hooks/usePersistField';
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
import { FieldURLV2Value } from '../../types/FieldMetadata';
import { FieldLinkValue } from '../../types/FieldMetadata';
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
import { isFieldURLV2 } from '../../types/guards/isFieldURLV2';
import { isFieldURLV2Value } from '../../types/guards/isFieldURLV2Value';
import { isFieldLink } from '../../types/guards/isFieldLink';
import { isFieldLinkValue } from '../../types/guards/isFieldLinkValue';
export const useURLV2Field = () => {
export const useLinkField = () => {
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
assertFieldMetadata('URL_V2', isFieldURLV2, fieldDefinition);
assertFieldMetadata('LINK', isFieldLink, fieldDefinition);
const fieldName = fieldDefinition.metadata.fieldName;
const [fieldValue, setFieldValue] = useRecoilState<FieldURLV2Value>(
const [fieldValue, setFieldValue] = useRecoilState<FieldLinkValue>(
entityFieldsFamilySelector({
entityId: entityId,
fieldName: fieldName,
@ -26,16 +26,16 @@ export const useURLV2Field = () => {
const fieldInitialValue = useFieldInitialValue();
const initialValue: FieldURLV2Value = fieldInitialValue?.isEmpty
? { link: '', text: '' }
const initialValue: FieldLinkValue = fieldInitialValue?.isEmpty
? { url: '', label: '' }
: fieldInitialValue?.value
? { link: fieldInitialValue.value, text: '' }
? { url: fieldInitialValue.value, label: '' }
: fieldValue;
const persistField = usePersistField();
const persistURLField = (newValue: FieldURLV2Value) => {
if (!isFieldURLV2Value(newValue)) {
const persistLinkField = (newValue: FieldLinkValue) => {
if (!isFieldLinkValue(newValue)) {
return;
}
@ -48,6 +48,6 @@ export const useURLV2Field = () => {
initialValue,
setFieldValue,
hotkeyScope,
persistURLField,
persistLinkField,
};
};

View File

@ -0,0 +1,94 @@
import { TextInput } from '@/ui/object/field/meta-types/input/components/internal/TextInput';
import { convertCurrencyToCurrencyMicros } from '~/utils/convert-currency-amount';
import { useCurrencyField } from '../../hooks/useCurrencyField';
import { FieldInputOverlay } from './internal/FieldInputOverlay';
import { FieldInputEvent } from './DateFieldInput';
export type CurrencyFieldInputProps = {
onClickOutside?: FieldInputEvent;
onEnter?: FieldInputEvent;
onEscape?: FieldInputEvent;
onTab?: FieldInputEvent;
onShiftTab?: FieldInputEvent;
};
export const CurrencyFieldInput = ({
onEnter,
onEscape,
onClickOutside,
onTab,
onShiftTab,
}: CurrencyFieldInputProps) => {
const { hotkeyScope, initialValue, persistCurrencyField } =
useCurrencyField();
const handleEnter = (newValue: string) => {
onEnter?.(() =>
persistCurrencyField({
amountMicros:
convertCurrencyToCurrencyMicros(parseFloat(newValue)) ?? 0,
currencyCode: initialValue.currencyCode,
}),
);
};
const handleEscape = (newValue: string) => {
onEscape?.(() =>
persistCurrencyField({
amountMicros:
convertCurrencyToCurrencyMicros(parseFloat(newValue)) ?? 0,
currencyCode: initialValue.currencyCode,
}),
);
};
const handleClickOutside = (
event: MouseEvent | TouchEvent,
newValue: string,
) => {
onClickOutside?.(() =>
persistCurrencyField({
amountMicros:
convertCurrencyToCurrencyMicros(parseFloat(newValue)) ?? 0,
currencyCode: initialValue.currencyCode,
}),
);
};
const handleTab = (newValue: string) => {
onTab?.(() =>
persistCurrencyField({
amountMicros:
convertCurrencyToCurrencyMicros(parseFloat(newValue)) ?? 0,
currencyCode: initialValue.currencyCode,
}),
);
};
const handleShiftTab = (newValue: string) => {
onShiftTab?.(() =>
persistCurrencyField({
amountMicros:
convertCurrencyToCurrencyMicros(parseFloat(newValue)) ?? 0,
currencyCode: initialValue.currencyCode,
}),
);
};
return (
<FieldInputOverlay>
<TextInput
value={initialValue.amountMicros?.toString() ?? ''}
placeholder="Currency"
onClickOutside={handleClickOutside}
onEnter={handleEnter}
onEscape={handleEscape}
onShiftTab={handleShiftTab}
onTab={handleTab}
hotkeyScope={hotkeyScope}
/>
</FieldInputOverlay>
);
};

View File

@ -1,11 +1,11 @@
import { FieldDoubleText } from '../../../types/FieldDoubleText';
import { useURLV2Field } from '../../hooks/useURLV2Field';
import { useLinkField } from '../../hooks/useLinkField';
import { DoubleTextInput } from './internal/DoubleTextInput';
import { FieldInputOverlay } from './internal/FieldInputOverlay';
import { FieldInputEvent } from './DateFieldInput';
export type URLV2FieldInputProps = {
export type LinkFieldInputProps = {
onClickOutside?: FieldInputEvent;
onEnter?: FieldInputEvent;
onEscape?: FieldInputEvent;
@ -13,29 +13,29 @@ export type URLV2FieldInputProps = {
onShiftTab?: FieldInputEvent;
};
export const URLV2FieldInput = ({
export const LinkFieldInput = ({
onEnter,
onEscape,
onClickOutside,
onTab,
onShiftTab,
}: URLV2FieldInputProps) => {
const { initialValue, hotkeyScope, persistURLField } = useURLV2Field();
}: LinkFieldInputProps) => {
const { initialValue, hotkeyScope, persistLinkField } = useLinkField();
const handleEnter = (newURL: FieldDoubleText) => {
onEnter?.(() =>
persistURLField({
link: newURL.firstValue,
text: newURL.secondValue,
persistLinkField({
url: newURL.firstValue,
label: newURL.secondValue,
}),
);
};
const handleEscape = (newURL: FieldDoubleText) => {
onEscape?.(() =>
persistURLField({
link: newURL.firstValue,
text: newURL.secondValue,
persistLinkField({
url: newURL.firstValue,
label: newURL.secondValue,
}),
);
};
@ -45,27 +45,27 @@ export const URLV2FieldInput = ({
newURL: FieldDoubleText,
) => {
onClickOutside?.(() =>
persistURLField({
link: newURL.firstValue,
text: newURL.secondValue,
persistLinkField({
url: newURL.firstValue,
label: newURL.secondValue,
}),
);
};
const handleTab = (newURL: FieldDoubleText) => {
onTab?.(() =>
persistURLField({
link: newURL.firstValue,
text: newURL.secondValue,
persistLinkField({
url: newURL.firstValue,
label: newURL.secondValue,
}),
);
};
const handleShiftTab = (newURL: FieldDoubleText) => {
onShiftTab?.(() =>
persistURLField({
link: newURL.firstValue,
text: newURL.secondValue,
persistLinkField({
url: newURL.firstValue,
label: newURL.secondValue,
}),
);
};
@ -73,9 +73,9 @@ export const URLV2FieldInput = ({
return (
<FieldInputOverlay>
<DoubleTextInput
firstValue={initialValue.link}
secondValue={initialValue.text}
firstValuePlaceholder={'Link'}
firstValue={initialValue.url}
secondValue={initialValue.label}
firstValuePlaceholder={'Url'}
secondValuePlaceholder={'Label'}
hotkeyScope={hotkeyScope}
onClickOutside={handleClickOutside}

View File

@ -1,93 +0,0 @@
import { DoubleTextInput } from '@/ui/object/field/meta-types/input/components/internal/DoubleTextInput';
import { usePersistField } from '../../../hooks/usePersistField';
import { FieldDoubleText } from '../../../types/FieldDoubleText';
import { useMoneyAmountV2Field } from '../../hooks/useMoneyAmountV2Field';
import { FieldInputOverlay } from './internal/FieldInputOverlay';
import { FieldInputEvent } from './DateFieldInput';
export type MoneyAmountV2FieldInputProps = {
onClickOutside?: FieldInputEvent;
onEnter?: FieldInputEvent;
onEscape?: FieldInputEvent;
onTab?: FieldInputEvent;
onShiftTab?: FieldInputEvent;
};
export const MoneyAmountV2FieldInput = ({
onEnter,
onEscape,
onClickOutside,
onTab,
onShiftTab,
}: MoneyAmountV2FieldInputProps) => {
const { hotkeyScope, initialValue } = useMoneyAmountV2Field();
const persistField = usePersistField();
const handleEnter = (newDoubleText: FieldDoubleText) => {
onEnter?.(() =>
persistField({
amount: parseFloat(newDoubleText.firstValue),
currency: newDoubleText.secondValue,
}),
);
};
const handleEscape = (newDoubleText: FieldDoubleText) => {
onEscape?.(() =>
persistField({
amount: parseFloat(newDoubleText.firstValue),
currency: newDoubleText.secondValue,
}),
);
};
const handleClickOutside = (
event: MouseEvent | TouchEvent,
newDoubleText: FieldDoubleText,
) => {
onClickOutside?.(() =>
persistField({
amount: parseFloat(newDoubleText.firstValue),
currency: newDoubleText.secondValue,
}),
);
};
const handleTab = (newDoubleText: FieldDoubleText) => {
onTab?.(() =>
persistField({
amount: parseFloat(newDoubleText.firstValue),
currency: newDoubleText.secondValue,
}),
);
};
const handleShiftTab = (newDoubleText: FieldDoubleText) => {
onShiftTab?.(() =>
persistField({
amount: parseFloat(newDoubleText.firstValue),
currency: newDoubleText.secondValue,
}),
);
};
return (
<FieldInputOverlay>
<DoubleTextInput
firstValue={initialValue.amount?.toString() ?? ''}
secondValue={initialValue.currency ?? ''}
firstValuePlaceholder="Amount"
secondValuePlaceholder="Currency"
onClickOutside={handleClickOutside}
onEnter={handleEnter}
onEscape={handleEscape}
onShiftTab={handleShiftTab}
onTab={handleTab}
hotkeyScope={hotkeyScope}
/>
</FieldInputOverlay>
);
};

View File

@ -7,12 +7,14 @@ import { FieldDefinition } from '../../types/FieldDefinition';
import { FieldMetadata } from '../../types/FieldMetadata';
import { isFieldBoolean } from '../../types/guards/isFieldBoolean';
import { isFieldChip } from '../../types/guards/isFieldChip';
import { isFieldCurrency } from '../../types/guards/isFieldCurrency';
import { isFieldCurrencyValue } from '../../types/guards/isFieldCurrencyValue';
import { isFieldDate } from '../../types/guards/isFieldDate';
import { isFieldDoubleTextChip } from '../../types/guards/isFieldDoubleTextChip';
import { isFieldEmail } from '../../types/guards/isFieldEmail';
import { isFieldLink } from '../../types/guards/isFieldLink';
import { isFieldLinkValue } from '../../types/guards/isFieldLinkValue';
import { isFieldMoney } from '../../types/guards/isFieldMoney';
import { isFieldMoneyAmountV2 } from '../../types/guards/isFieldMoneyAmountV2';
import { isFieldMoneyAmountV2Value } from '../../types/guards/isFieldMoneyAmountV2Value';
import { isFieldNumber } from '../../types/guards/isFieldNumber';
import { isFieldPhone } from '../../types/guards/isFieldPhone';
import { isFieldProbability } from '../../types/guards/isFieldProbability';
@ -20,8 +22,6 @@ import { isFieldRelation } from '../../types/guards/isFieldRelation';
import { isFieldRelationValue } from '../../types/guards/isFieldRelationValue';
import { isFieldText } from '../../types/guards/isFieldText';
import { isFieldURL } from '../../types/guards/isFieldURL';
import { isFieldURLV2 } from '../../types/guards/isFieldURLV2';
import { isFieldURLV2Value } from '../../types/guards/isFieldURLV2Value';
import { entityFieldsFamilyState } from '../entityFieldsFamilyState';
const isValueEmpty = (value: unknown) => !assertNotNull(value) || value === '';
@ -98,21 +98,21 @@ export const isEntityFieldEmptyFamilySelector = selectorFamily({
);
}
if (isFieldMoneyAmountV2(fieldDefinition)) {
if (isFieldCurrency(fieldDefinition)) {
const fieldName = fieldDefinition.metadata.fieldName;
const fieldValue = get(entityFieldsFamilyState(entityId))?.[fieldName];
return (
!isFieldMoneyAmountV2Value(fieldValue) ||
isValueEmpty(fieldValue?.amount)
!isFieldCurrencyValue(fieldValue) ||
isValueEmpty(fieldValue?.amountMicros)
);
}
if (isFieldURLV2(fieldDefinition)) {
if (isFieldLink(fieldDefinition)) {
const fieldName = fieldDefinition.metadata.fieldName;
const fieldValue = get(entityFieldsFamilyState(entityId))?.[fieldName];
return !isFieldURLV2Value(fieldValue) || isValueEmpty(fieldValue?.link);
return !isFieldLinkValue(fieldValue) || isValueEmpty(fieldValue?.url);
}
throw new Error(

View File

@ -21,7 +21,7 @@ export type FieldURLMetadata = {
fieldName: string;
};
export type FieldURLV2Metadata = {
export type FieldLinkMetadata = {
placeHolder: string;
fieldName: string;
};
@ -42,7 +42,7 @@ export type FieldMoneyMetadata = {
isPositive?: boolean;
};
export type FieldMoneyAmountV2Metadata = {
export type FieldCurrencyMetadata = {
fieldName: string;
placeHolder: string;
isPositive?: boolean;
@ -91,22 +91,22 @@ export type FieldBooleanMetadata = {
};
export type FieldMetadata =
| FieldUuidMetadata
| FieldTextMetadata
| FieldRelationMetadata
| FieldBooleanMetadata
| FieldChipMetadata
| FieldCurrencyMetadata
| FieldDateMetadata
| FieldDoubleTextChipMetadata
| FieldDoubleTextMetadata
| FieldPhoneMetadata
| FieldURLMetadata
| FieldURLV2Metadata
| FieldNumberMetadata
| FieldMoneyMetadata
| FieldMoneyAmountV2Metadata
| FieldEmailMetadata
| FieldDateMetadata
| FieldLinkMetadata
| FieldMoneyMetadata
| FieldNumberMetadata
| FieldPhoneMetadata
| FieldProbabilityMetadata
| FieldBooleanMetadata;
| FieldRelationMetadata
| FieldTextMetadata
| FieldURLMetadata
| FieldUuidMetadata;
export type FieldTextValue = string;
export type FieldUUidValue = string;
@ -115,10 +115,10 @@ export type FieldChipValue = string;
export type FieldDateValue = string | null;
export type FieldPhoneValue = string;
export type FieldURLValue = string;
export type FieldURLV2Value = { link: string; text: string };
export type FieldLinkValue = { url: string; label: string };
export type FieldNumberValue = number | null;
export type FieldMoneyValue = number | null;
export type FieldMoneyAmountV2Value = { currency: string; amount: number };
export type FieldCurrencyValue = { currencyCode: string; amountMicros: number };
export type FieldEmailValue = string;
export type FieldProbabilityValue = number;

View File

@ -11,8 +11,8 @@ export type FieldType =
| 'DATE'
| 'PHONE'
| 'URL'
| 'URL_V2'
| 'LINK'
| 'PROBABILITY'
| 'MONEY_AMOUNT_V2'
| 'CURRENCY'
| 'MONEY_AMOUNT'
| 'MONEY';

View File

@ -2,12 +2,13 @@ import { FieldDefinition } from '../FieldDefinition';
import {
FieldBooleanMetadata,
FieldChipMetadata,
FieldCurrencyMetadata,
FieldDateMetadata,
FieldDoubleTextChipMetadata,
FieldDoubleTextMetadata,
FieldEmailMetadata,
FieldLinkMetadata,
FieldMetadata,
FieldMoneyAmountV2Metadata,
FieldMoneyMetadata,
FieldNumberMetadata,
FieldPhoneMetadata,
@ -15,45 +16,44 @@ import {
FieldRelationMetadata,
FieldTextMetadata,
FieldURLMetadata,
FieldURLV2Metadata,
FieldUuidMetadata,
} from '../FieldMetadata';
import { FieldType } from '../FieldType';
type AssertFieldMetadataFunction = <
E extends FieldType,
T extends E extends 'TEXT'
? FieldTextMetadata
: E extends 'UUID'
? FieldUuidMetadata
: E extends 'RELATION'
? FieldRelationMetadata
T extends E extends 'BOOLEAN'
? FieldBooleanMetadata
: E extends 'CHIP'
? FieldChipMetadata
: E extends 'DOUBLE_TEXT_CHIP'
? FieldDoubleTextChipMetadata
: E extends 'DOUBLE_TEXT'
? FieldDoubleTextMetadata
: E extends 'NUMBER'
? FieldNumberMetadata
: E extends 'EMAIL'
? FieldEmailMetadata
: E extends 'BOOLEAN'
? FieldBooleanMetadata
: E extends 'CURRENCY'
? FieldCurrencyMetadata
: E extends 'DATE'
? FieldDateMetadata
: E extends 'PHONE'
? FieldPhoneMetadata
: E extends 'URL'
? FieldURLMetadata
: E extends 'URL_V2'
? FieldURLV2Metadata
: E extends 'PROBABILITY'
? FieldProbabilityMetadata
: E extends 'DOUBLE_TEXT'
? FieldDoubleTextMetadata
: E extends 'DOUBLE_TEXT_CHIP'
? FieldDoubleTextChipMetadata
: E extends 'EMAIL'
? FieldEmailMetadata
: E extends 'LINK'
? FieldLinkMetadata
: E extends 'MONEY_AMOUNT'
? FieldMoneyMetadata
: E extends 'MONEY_AMOUNT_V2'
? FieldMoneyAmountV2Metadata
: E extends 'NUMBER'
? FieldNumberMetadata
: E extends 'PHONE'
? FieldPhoneMetadata
: E extends 'PROBABILITY'
? FieldProbabilityMetadata
: E extends 'RELATION'
? FieldRelationMetadata
: E extends 'TEXT'
? FieldTextMetadata
: E extends 'URL'
? FieldURLMetadata
: E extends 'UUID'
? FieldUuidMetadata
: never,
>(
fieldType: E,

View File

@ -0,0 +1,6 @@
import { FieldDefinition } from '../FieldDefinition';
import { FieldCurrencyMetadata, FieldMetadata } from '../FieldMetadata';
export const isFieldCurrency = (
field: FieldDefinition<FieldMetadata>,
): field is FieldDefinition<FieldCurrencyMetadata> => field.type === 'CURRENCY';

View File

@ -0,0 +1,13 @@
import { z } from 'zod';
import { FieldCurrencyValue } from '../FieldMetadata';
const currencySchema = z.object({
currencyCode: z.string(),
amountMicros: z.number(),
});
export const isFieldCurrencyValue = (
fieldValue: unknown,
): fieldValue is FieldCurrencyValue =>
currencySchema.safeParse(fieldValue).success;

View File

@ -0,0 +1,6 @@
import { FieldDefinition } from '../FieldDefinition';
import { FieldLinkMetadata, FieldMetadata } from '../FieldMetadata';
export const isFieldLink = (
field: FieldDefinition<FieldMetadata>,
): field is FieldDefinition<FieldLinkMetadata> => field.type === 'LINK';

View File

@ -0,0 +1,13 @@
import { z } from 'zod';
import { FieldLinkValue } from '../FieldMetadata';
const linkSchema = z.object({
url: z.string(),
label: z.string(),
});
// TODO: add zod
export const isFieldLinkValue = (
fieldValue: unknown,
): fieldValue is FieldLinkValue => linkSchema.safeParse(fieldValue).success;

View File

@ -1,7 +0,0 @@
import { FieldDefinition } from '../FieldDefinition';
import { FieldMetadata, FieldMoneyAmountV2Metadata } from '../FieldMetadata';
export const isFieldMoneyAmountV2 = (
field: FieldDefinition<FieldMetadata>,
): field is FieldDefinition<FieldMoneyAmountV2Metadata> =>
field.type === 'MONEY_AMOUNT_V2';

View File

@ -1,13 +0,0 @@
import { z } from 'zod';
import { FieldMoneyAmountV2Value } from '../FieldMetadata';
const moneyAmountV2Schema = z.object({
currency: z.string(),
amount: z.number(),
});
export const isFieldMoneyAmountV2Value = (
fieldValue: unknown,
): fieldValue is FieldMoneyAmountV2Value =>
moneyAmountV2Schema.safeParse(fieldValue).success;

View File

@ -1,6 +0,0 @@
import { FieldDefinition } from '../FieldDefinition';
import { FieldMetadata, FieldURLV2Metadata } from '../FieldMetadata';
export const isFieldURLV2 = (
field: FieldDefinition<FieldMetadata>,
): field is FieldDefinition<FieldURLV2Metadata> => field.type === 'URL_V2';

View File

@ -1,13 +0,0 @@
import { z } from 'zod';
import { FieldURLV2Value } from '../FieldMetadata';
const urlV2Schema = z.object({
link: z.string(),
text: z.string(),
});
// TODO: add zod
export const isFieldURLV2Value = (
fieldValue: unknown,
): fieldValue is FieldURLV2Value => urlV2Schema.safeParse(fieldValue).success;