cart & checkout: apply validation based on required inputs in each service & add phone input in checkout page

This commit is contained in:
2025-10-14 23:25:08 +03:00
parent af27d1e509
commit b88cc28c89
13 changed files with 186 additions and 113 deletions

View File

@@ -1,5 +1,5 @@
import { PlusOutlined } from "@ant-design/icons";
import { Card, Divider, Space } from "antd";
import { Card, Divider, Form, Space } from "antd";
import ArabicPrice from "components/ArabicPrice";
import CartActionsButtons from "components/CartActionsButtons/CartActionsButtons.tsx";
import ImageWithFallback from "components/ImageWithFallback";
@@ -35,7 +35,9 @@ interface CartMobileTabletLayoutProps {
form: FormInstance;
}
export default function CartMobileTabletLayout({ form }: CartMobileTabletLayoutProps) {
export default function CartMobileTabletLayout({
form,
}: CartMobileTabletLayoutProps) {
const { t } = useTranslation();
const { items, collectionMethod } = useAppSelector(selectCart);
const { id } = useParams();
@@ -235,24 +237,30 @@ export default function CartMobileTabletLayout({ form }: CartMobileTabletLayoutP
{/* Collection Method */}
{orderType === "pickup" && (
<ProInputCard title={t("cart.collectionMethod")}>
<ProRatioGroups
options={[
{ label: t("cart.Cash"), value: "cod", price: "" },
{
label: t("cart.e-payment"),
value: "paymentgateway",
price: "",
},
]}
value={collectionMethod}
onRatioClick={(value) => {
if (value === "cod") {
updateCollectionMethod(value);
} else {
updateCollectionMethod(value);
}
}}
/>
<Form.Item
name="collectionMethod"
required
rules={[{ required: true }]}
>
<ProRatioGroups
options={[
{ label: t("cart.Cash"), value: "cod", price: "" },
{
label: t("cart.e-payment"),
value: "paymentgateway",
price: "",
},
]}
value={collectionMethod}
onRatioClick={(value) => {
if (value === "cod") {
updateCollectionMethod(value);
} else {
updateCollectionMethod(value);
}
}}
/>
</Form.Item>
</ProInputCard>
)}

View File

@@ -1,5 +1,5 @@
import { colors } from "ThemeConstants.ts";
import { Button, FormInstance } from "antd";
import { Button, FormInstance, message } from "antd";
import { selectCart } from "features/order/orderSlice.ts";
import { useTranslation } from "react-i18next";
import { Link, useNavigate, useParams } from "react-router-dom";
@@ -17,15 +17,15 @@ export default function CartFooter({ form }: CartFooterProps) {
const orderType = localStorage.getItem("orderType");
const navigate = useNavigate();
// Check if checkout should be disabled
const isCheckoutDisabled = items.length === 0;
const handleCheckoutClick = async () => {
try {
await form.validateFields();
navigate(`/${id}/checkout`);
} catch (error) {
console.log("Form validation failed:", error);
if (items.length === 0) message.warning(t("cart.pleaseAddItemsToCart"));
else {
try {
await form.validateFields();
navigate(`/${id}/checkout`);
} catch (error) {
console.log("Form validation failed:", error);
}
}
};
@@ -60,7 +60,6 @@ export default function CartFooter({ form }: CartFooterProps) {
color: "white",
width: "100%",
}}
disabled={isCheckoutDisabled}
onClick={handleCheckoutClick}
>
{t("cart.checkout")}

View File

@@ -1,3 +1,4 @@
import { Form } from "antd";
import ProInputCard from "components/ProInputCard/ProInputCard.tsx";
import ProRatioGroups from "components/ProRatioGroups/ProRatioGroups.tsx";
import { selectCart, updateEstimateTime } from "features/order/orderSlice.ts";
@@ -27,22 +28,24 @@ export default function TimeEstimateCard() {
return (
<>
<ProInputCard title={t("cart.estimateTime")}>
<ProRatioGroups
options={[
{ label: t("cart.now"), value: "now", price: "" },
{ label: t("cart.later"), value: "later", price: "" },
]}
value={estimateWay}
onRatioClick={(value) => {
if (value === "now") {
setEstimateWay(value);
handleEstimateTimeSave(new Date(), "now");
} else {
setEstimateWay(value);
setIsEstimateTimeOpen(true);
}
}}
/>
<Form.Item name="estimateWay" required rules={[{ required: true }]}>
<ProRatioGroups
options={[
{ label: t("cart.now"), value: "now", price: "" },
{ label: t("cart.later"), value: "later", price: "" },
]}
value={estimateWay}
onRatioClick={(value) => {
if (value === "now") {
setEstimateWay(value);
handleEstimateTimeSave(new Date(), "now");
} else {
setEstimateWay(value);
setIsEstimateTimeOpen(true);
}
}}
/>
</Form.Item>
</ProInputCard>
{isDesktop ? (
<Dialog

View File

@@ -1,3 +1,7 @@
.youMightAlsoLikeTitle {
margin: 0 16px 16px 16px;
}
.youMightAlsoLikeContainer {
display: flex;
flex-direction: row;
@@ -66,6 +70,9 @@
.youMightAlsoLikeContainer {
height: 200px !important;
}
.youMightAlsoLikeTitle {
margin: 16px;
}
}
/* Hover effects for devices that support hover */

View File

@@ -117,7 +117,7 @@ export default function YouMightAlsoLike() {
return (
<>
<div style={{ margin: 16 }}>
<div className={styles.youMightAlsoLikeTitle} >
<ProText
strong
style={{