ProPhoneInput: fix validation and value

This commit is contained in:
2025-11-13 14:33:41 +03:00
parent 0764d3a641
commit a29aa896e0
4 changed files with 65 additions and 48 deletions

View File

@@ -73,8 +73,6 @@ export function GiftBottomSheet({
</Form.Item>
<ProPhoneInput
phone={giftForm.getFieldValue("receiverPhone")}
setPhone={(phone) => giftForm.setFieldValue("receiverPhone", phone)}
propName="receiverPhone"
label={t("address.receiverPhone")}
/>
@@ -109,8 +107,6 @@ export function GiftBottomSheet({
</Form.Item>
<ProPhoneInput
phone={giftForm.getFieldValue("senderPhone")}
setPhone={(phone) => giftForm.setFieldValue("senderPhone", phone)}
propName="senderPhone"
label={t("address.receiverPhone")}
/>

View File

@@ -5,15 +5,21 @@ import { useTranslation } from "react-i18next";
import PhoneInput from "react-phone-input-2";
import { useAppSelector } from "redux/hooks";
import { ProBlack1 } from "ThemeConstants";
import { PhoneNumberUtil } from "google-libphonenumber";
import useFormInstance from "antd/es/form/hooks/useFormInstance";
interface ProPhoneInput extends TitleProps {
phone: string;
setPhone: (phone: string) => void;
propName?: string
label?: string
propName?: string;
label?: string;
getValueCallback?: (value: string) => void;
}
const ProPhoneInput: FunctionComponent<ProPhoneInput> = ({ phone, setPhone, propName, label }) => {
const ProPhoneInput: FunctionComponent<ProPhoneInput> = ({
propName,
label,
getValueCallback,
}) => {
const form = useFormInstance();
const { t } = useTranslation();
const { themeName } = useAppSelector((state) => state.theme);
const { isRTL } = useAppSelector((state) => state.locale);
@@ -23,25 +29,30 @@ const ProPhoneInput: FunctionComponent<ProPhoneInput> = ({ phone, setPhone, prop
name={propName}
label={label}
rules={[
{ required: true, message: "" },
{ required: true, message: t("validation.phoneRequired") },
{
validator: (_, value) => {
if (!value || value.length <= 3) {
return Promise.reject(new Error(""));
}
// Initialize the PhoneNumberUtil instance
const phoneUtil = PhoneNumberUtil.getInstance();
if (
value &&
!phoneUtil.isValidNumber(
phoneUtil.parseAndKeepRawInput(`+${value}`),
)
)
return Promise.reject(new Error(t("validation.invalidPhone")));
return Promise.resolve();
},
},
]}
normalize={(value) => {
if (value && setPhone) {
setPhone(value);
}
return value;
}}
>
<PhoneInputWrapper
phone={phone}
onChange={(value) => {
form.setFieldValue(propName, value);
getValueCallback?.(value);
}}
phone={form.getFieldValue(propName)}
themeName={themeName}
isRTL={isRTL}
placeholder={t("login.mobileNumber")}
@@ -52,8 +63,17 @@ const ProPhoneInput: FunctionComponent<ProPhoneInput> = ({ phone, setPhone, prop
);
};
export const PhoneInputWrapper = ({ phone, themeName, isRTL, placeholder, value, onChange, propName, label }: {
phone: string;
export const PhoneInputWrapper = ({
phone,
themeName,
isRTL,
placeholder,
value,
onChange,
propName,
label,
}: {
phone?: string;
themeName: string;
isRTL: boolean;
placeholder: string;
@@ -106,7 +126,6 @@ export const PhoneInputWrapper = ({ phone, themeName, isRTL, placeholder, value,
autoComplete: "tel",
type: "tel",
inputMode: "numeric",
pattern: "[0-9]*",
}}
/>
</div>

View File

@@ -1,23 +1,19 @@
import ProInputCard from "components/ProInputCard/ProInputCard.tsx";
import ProPhoneInput from "components/ProPhoneInput";
import { selectCart, updatePhone } from "features/order/orderSlice";
import { selectCart } from "features/order/orderSlice";
import { useTranslation } from "react-i18next";
import { useAppDispatch, useAppSelector } from "redux/hooks";
import { useAppSelector } from "redux/hooks";
import { OrderType } from "pages/checkout/hooks/types.ts";
export default function PhoneCard() {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const { phone, orderType } = useAppSelector(selectCart);
const { orderType } = useAppSelector(selectCart);
return (
orderType !== OrderType.Gift && (
<>
<ProInputCard title={t("checkout.phoneNumber")}>
<ProPhoneInput
phone={phone}
setPhone={(phone) => dispatch(updatePhone(phone))}
/>
<ProPhoneInput />
</ProInputCard>
</>
)

View File

@@ -23,19 +23,22 @@ export default function LoginPage() {
const [sendOtp, { isLoading }] = useSendOtpMutation();
const { subdomain } = useParams();
const [phone, setPhone] = useState<string>("");
// const [phone, setPhone] = useState<string>("");
const [selectedDate, setSelectedDate] = useState<string>("");
const [isOpen, setIsOpen] = useState(false);
const navigate = useNavigate();
const handleLogin = async () => {
form.validateFields().then(() => {
if (form.getFieldsValue()) {
localStorage.setItem("userPhone", form.getFieldValue("phone"));
if (form.getFieldsValue())
sendOtp(form.getFieldsValue()).then((response: any) => {
message.info(t("login.OTPSentToYourPhoneNumber"));
navigate(`/${subdomain}/otp`);
localStorage.setItem("otp", response.data.result.otp);
});
}
});
};
return (
@@ -94,7 +97,11 @@ export default function LoginPage() {
/>
</Form.Item>
<Form.Item label={t("login.date")} name="date" required>
<Form.Item
label={t("login.date")}
name="date"
rules={[{ required: true, message: "" }]}
>
<Input
placeholder={t("login.DateOfBirth")}
size="large"
@@ -109,7 +116,7 @@ export default function LoginPage() {
/>
</Form.Item>
<ProPhoneInput phone={phone} setPhone={setPhone} />
<ProPhoneInput label={t("login.phone")} propName="phone" />
<Form.Item label={null}>
<Button
@@ -120,8 +127,7 @@ export default function LoginPage() {
style={{
width: "100%",
borderRadius: 1000,
backgroundColor:
phone.length <= 3 || isLoading
backgroundColor: isLoading
? themeName === "light"
? "rgba(233, 233, 233, 1)"
: DisabledColor
@@ -132,7 +138,7 @@ export default function LoginPage() {
marginTop: "2rem",
boxShadow: "none",
}}
disabled={phone.length <= 3 || isLoading}
disabled={isLoading}
htmlType="submit"
>
{t("login.sendCode")}