fix: phone input validation error should display red borders like email input (#13275)
ISSUE - closes #13032 --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
@ -78,6 +78,7 @@ export type MultiItemBaseInputProps = Omit<HTMLInputProps, 'onChange'> & {
|
||||
onChange: (value: string) => void;
|
||||
autoFocus: HTMLInputProps['autoFocus'];
|
||||
placeholder: HTMLInputProps['placeholder'];
|
||||
hasError?: boolean;
|
||||
}) => React.ReactNode;
|
||||
error?: string | null;
|
||||
hasError?: boolean;
|
||||
@ -134,6 +135,7 @@ export const MultiItemBaseInput = forwardRef<
|
||||
onChange,
|
||||
autoFocus,
|
||||
placeholder,
|
||||
hasError,
|
||||
})
|
||||
) : (
|
||||
<StyledInput
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
import { usePhonesField } from '@/object-record/record-field/meta-types/hooks/usePhonesField';
|
||||
import { PhonesFieldMenuItem } from '@/object-record/record-field/meta-types/input/components/PhonesFieldMenuItem';
|
||||
import { recordFieldInputIsFieldInErrorComponentState } from '@/object-record/record-field/states/recordFieldInputIsFieldInErrorComponentState';
|
||||
import { phoneSchema } from '@/object-record/record-field/validation-schemas/phoneSchema';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import styled from '@emotion/styled';
|
||||
import { E164Number, parsePhoneNumber } from 'libphonenumber-js';
|
||||
import ReactPhoneNumberInput from 'react-phone-number-input';
|
||||
@ -19,6 +22,7 @@ export const DEFAULT_PHONE_CALLING_CODE = '1';
|
||||
|
||||
const StyledCustomPhoneInputContainer = styled.div<{
|
||||
hasItem: boolean;
|
||||
hasError?: boolean;
|
||||
}>`
|
||||
${({ hasItem, theme }) =>
|
||||
hasItem &&
|
||||
@ -28,6 +32,13 @@ const StyledCustomPhoneInputContainer = styled.div<{
|
||||
border: 1px solid ${theme.border.color.medium};
|
||||
height: 30px;
|
||||
`}
|
||||
|
||||
${({ hasError, hasItem, theme }) =>
|
||||
hasError &&
|
||||
hasItem &&
|
||||
css`
|
||||
border: 1px solid ${theme.border.color.danger};
|
||||
`}
|
||||
`;
|
||||
|
||||
const StyledCustomPhoneInput = styled(ReactPhoneNumberInput)`
|
||||
@ -93,10 +104,23 @@ export const PhonesFieldInput = ({
|
||||
});
|
||||
};
|
||||
|
||||
const validateInput = (input: string) => ({
|
||||
isValid: phoneSchema.safeParse(input).success,
|
||||
errorMessage: '',
|
||||
});
|
||||
|
||||
const getShowPrimaryIcon = (index: number) =>
|
||||
index === 0 && phones.length > 1;
|
||||
const getShowSetAsPrimaryButton = (index: number) => index > 0;
|
||||
|
||||
const setIsFieldInError = useSetRecoilComponentStateV2(
|
||||
recordFieldInputIsFieldInErrorComponentState,
|
||||
);
|
||||
|
||||
const handleError = (hasError: boolean, values: any[]) => {
|
||||
setIsFieldInError(hasError && values.length === 0);
|
||||
};
|
||||
|
||||
return (
|
||||
<MultiItemFieldInput
|
||||
items={phones}
|
||||
@ -105,6 +129,7 @@ export const PhonesFieldInput = ({
|
||||
onCancel={onCancel}
|
||||
placeholder="Phone"
|
||||
fieldMetadataType={FieldMetadataType.PHONES}
|
||||
validateInput={validateInput}
|
||||
formatInput={(input) => {
|
||||
const phone = parsePhoneNumber(input);
|
||||
if (phone !== undefined) {
|
||||
@ -138,9 +163,12 @@ export const PhonesFieldInput = ({
|
||||
onDelete={handleDelete}
|
||||
/>
|
||||
)}
|
||||
renderInput={({ value, onChange, autoFocus, placeholder }) => {
|
||||
renderInput={({ value, onChange, autoFocus, placeholder, hasError }) => {
|
||||
return (
|
||||
<StyledCustomPhoneInputContainer hasItem={!!phones.length}>
|
||||
<StyledCustomPhoneInputContainer
|
||||
hasItem={!!phones.length}
|
||||
hasError={hasError}
|
||||
>
|
||||
<StyledCustomPhoneInput
|
||||
autoFocus={autoFocus}
|
||||
placeholder={placeholder}
|
||||
@ -154,6 +182,7 @@ export const PhonesFieldInput = ({
|
||||
</StyledCustomPhoneInputContainer>
|
||||
);
|
||||
}}
|
||||
onError={handleError}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
import { parsePhoneNumberWithError } from 'libphonenumber-js';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const phoneSchema = z.string().refine((value) => {
|
||||
if (!value || value.trim() === '') return false;
|
||||
try {
|
||||
const phone = parsePhoneNumberWithError(value);
|
||||
return phone.isValid();
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user