fixes
- change refresh icon & apply refreshing logic - apply validation in action btn in menu - preserve on customer info state upon refresh
This commit is contained in:
@@ -83,7 +83,7 @@
|
||||
color: var(--secondary-background);
|
||||
}
|
||||
|
||||
.minusIcon{
|
||||
.minusIcon {
|
||||
color: var(--secondary-foreground);
|
||||
}
|
||||
|
||||
|
||||
@@ -134,9 +134,10 @@ export default function CartActionsButtons({ item }: { item: CartItem }) {
|
||||
}),
|
||||
)
|
||||
}
|
||||
disabled={item.quantity >= 99}
|
||||
className={styles.addButton}
|
||||
style={{
|
||||
backgroundColor: colors.primary,
|
||||
backgroundColor: "#FFC600",
|
||||
width: 28,
|
||||
height: 28,
|
||||
border: "none",
|
||||
|
||||
@@ -2,9 +2,10 @@ interface PlusIconType {
|
||||
className?: string;
|
||||
onClick?: () => void;
|
||||
dimesion?: string
|
||||
color?: string
|
||||
}
|
||||
|
||||
const PlusIcon = ({ className, onClick, dimesion }: PlusIconType) => {
|
||||
const PlusIcon = ({ className, onClick, dimesion, color }: PlusIconType) => {
|
||||
return (
|
||||
<svg
|
||||
width={dimesion || "16"}
|
||||
@@ -17,7 +18,7 @@ const PlusIcon = ({ className, onClick, dimesion }: PlusIconType) => {
|
||||
>
|
||||
<path
|
||||
d="M7.99992 3.3335V12.6668M3.33325 8.00016H12.6666"
|
||||
stroke="#FFD633"
|
||||
stroke={color || "#FFD633"}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
|
||||
29
src/components/Icons/RefershIcon.tsx
Normal file
29
src/components/Icons/RefershIcon.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
interface RefershIconType {
|
||||
className?: string;
|
||||
onClick?: () => void;
|
||||
dimension?: number;
|
||||
}
|
||||
|
||||
const RefershIcon = ({ className, onClick, dimension }: RefershIconType) => {
|
||||
return (
|
||||
<svg
|
||||
width={dimension || "18"}
|
||||
height={dimension || "18"}
|
||||
viewBox="0 0 18 18"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={className}
|
||||
onClick={onClick}
|
||||
>
|
||||
<path
|
||||
d="M1.5 7.5C1.5 7.5 1.59099 6.86307 4.22703 4.22703C6.86307 1.59099 11.1369 1.59099 13.773 4.22703C14.7069 5.16099 15.31 6.30054 15.5821 7.5M1.5 7.5V3M1.5 7.5H6M16.5 10.5C16.5 10.5 16.409 11.1369 13.773 13.773C11.1369 16.409 6.86307 16.409 4.22703 13.773C3.29307 12.839 2.69002 11.6995 2.41787 10.5M16.5 10.5V15M16.5 10.5H12"
|
||||
stroke="#5F6C7B"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default RefershIcon;
|
||||
@@ -3,16 +3,25 @@
|
||||
flex-direction: row;
|
||||
justify-content: end;
|
||||
padding: 0 16px;
|
||||
gap: 10px;
|
||||
gap: 8px;
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
z-index: 1000;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
:global(.ant-app-rtl) .languageSwitch {
|
||||
left: 0;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
:global(.ant-app-ltr) .languageSwitch {
|
||||
right: 0;
|
||||
.refreshIcon {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
:global(.ant-app-rtl) .refreshIcon {
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { useDispatch } from "react-redux";
|
||||
import { useAppSelector } from "redux/hooks";
|
||||
import ProText from "../ProText";
|
||||
import styles from "./LanguageSwitch.module.css";
|
||||
import RefershIcon from "components/Icons/RefershIcon";
|
||||
|
||||
export function LanguageSwitch() {
|
||||
const dispatch = useDispatch();
|
||||
@@ -23,11 +24,15 @@ export function LanguageSwitch() {
|
||||
});
|
||||
};
|
||||
|
||||
const refreshPage = () => {
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.languageSwitch}>
|
||||
<GlobalOutlined
|
||||
style={{
|
||||
color: themeName === "dark" ? "#fff" : "#434E5C",
|
||||
color: themeName === "dark" ? "#fff" : "#333333",
|
||||
fontSize: 15,
|
||||
marginRight: 3,
|
||||
cursor: isPending ? "wait" : "pointer",
|
||||
@@ -37,23 +42,19 @@ export function LanguageSwitch() {
|
||||
/>
|
||||
<ProText
|
||||
style={{
|
||||
color: themeName === "dark" ? "#fff" : "#434E5C",
|
||||
color: themeName === "dark" ? "#fff" : "#333333",
|
||||
fontSize: 14,
|
||||
marginRight: 3,
|
||||
opacity: isPending ? 0.7 : 1,
|
||||
[isRTL ? "marginLeft" : "marginRight"]: 3,
|
||||
}}
|
||||
onClick={changeLanguage}
|
||||
>
|
||||
{isPending ? "..." : isRTL ? "English" : "Arabic"}
|
||||
</ProText>
|
||||
<ShakeOutlined
|
||||
style={{
|
||||
color: themeName === "dark" ? "#fff" : "#434E5C",
|
||||
fontSize: 15,
|
||||
marginRight: 3,
|
||||
[isRTL ? "marginLeft" : "marginRight"]: 3,
|
||||
}}
|
||||
/>
|
||||
<div onClick={refreshPage}>
|
||||
<RefershIcon dimension={18} className={styles.refreshIcon} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -113,6 +113,7 @@ export const CART_STORAGE_KEYS = {
|
||||
HIDDEN_SERVICES: "fascano_hidden_services",
|
||||
VISIBLE_SERVICES: "fascano_visible_services",
|
||||
ESTIMATE_WAY: "fascano_estimate_way",
|
||||
CUSTOMER_NAME: "fascano_customer_name",
|
||||
} as const;
|
||||
|
||||
// Utility functions for localStorage
|
||||
@@ -201,7 +202,7 @@ const initialState: CartState = {
|
||||
estimateWay: getFromLocalStorage(CART_STORAGE_KEYS.ESTIMATE_WAY, ""),
|
||||
order: getFromLocalStorage(CART_STORAGE_KEYS.ORDER, null),
|
||||
splitBillAmount: 0,
|
||||
customerName: "",
|
||||
customerName: getFromLocalStorage(CART_STORAGE_KEYS.CUSTOMER_NAME, ""),
|
||||
totalServices: 8,
|
||||
hiddenServices: 0,
|
||||
visibleServices: 0,
|
||||
@@ -701,6 +702,12 @@ const orderSlice = createSlice({
|
||||
},
|
||||
updateCustomerName(state, action: PayloadAction<string>) {
|
||||
state.customerName = action.payload;
|
||||
if (typeof window !== "undefined") {
|
||||
localStorage.setItem(
|
||||
CART_STORAGE_KEYS.CUSTOMER_NAME,
|
||||
JSON.stringify(state.customerName),
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import ProInputCard from "components/ProInputCard/ProInputCard.tsx";
|
||||
import ProPhoneInput from "components/ProPhoneInput";
|
||||
import { selectCart, updateCustomerName } from "features/order/orderSlice";
|
||||
import {
|
||||
selectCart,
|
||||
updateCustomerName,
|
||||
updatePhone,
|
||||
} from "features/order/orderSlice";
|
||||
import { OrderType } from "pages/checkout/hooks/types.ts";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useAppDispatch, useAppSelector } from "redux/hooks";
|
||||
@@ -9,9 +13,12 @@ import styles from "./CustomerInformationCard.module.css";
|
||||
|
||||
export default function CustomerInformationCard() {
|
||||
const { t } = useTranslation();
|
||||
const { orderType } = useAppSelector(selectCart);
|
||||
const { orderType, customerName, phone } = useAppSelector(selectCart);
|
||||
const dispatch = useAppDispatch();
|
||||
const customerName = useAppSelector((state) => state.order.customerName);
|
||||
|
||||
const setPhone = (value: string) => {
|
||||
dispatch(updatePhone(value));
|
||||
};
|
||||
|
||||
return (
|
||||
orderType !== OrderType.Gift && (
|
||||
@@ -30,7 +37,7 @@ export default function CustomerInformationCard() {
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<ProPhoneInput propName="phone" />
|
||||
<ProPhoneInput propName="phone" value={phone} onChange={setPhone} />
|
||||
</div>
|
||||
</ProInputCard>
|
||||
</>
|
||||
|
||||
@@ -24,13 +24,13 @@ import { useEffect } from "react";
|
||||
export default function CheckoutPage() {
|
||||
const { t } = useTranslation();
|
||||
const [form] = Form.useForm();
|
||||
const { phone, order, orderType, collectionMethod, coupon } =
|
||||
const { phone, order, orderType, collectionMethod, coupon, customerName } =
|
||||
useAppSelector(selectCart);
|
||||
const { token } = useAppSelector((state) => state.auth);
|
||||
const dispatch = useAppDispatch();
|
||||
useEffect(() => {
|
||||
form.setFieldsValue({ coupon, collectionMethod });
|
||||
}, [form, phone]);
|
||||
form.setFieldsValue({ coupon, collectionMethod, phone, customerName });
|
||||
}, [form, phone, coupon, collectionMethod, customerName]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -1,25 +1,93 @@
|
||||
.plusIcon {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
.quantityControls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: var(--background);
|
||||
border-radius: 888px;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.addButton {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
.quantityLabel {
|
||||
font-size: 14px;
|
||||
color: var(--secondary-color);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.quantityInputContainer {
|
||||
display: flex;
|
||||
padding: 0 1px;
|
||||
align-items: center;
|
||||
border-radius: 888px;
|
||||
width: 90px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.quantityButton {
|
||||
padding: 0;
|
||||
width: 28px !important;
|
||||
height: 28px !important;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--secondary-background);
|
||||
background-color: var(--primary);
|
||||
border-radius: 50%;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.quantityInput {
|
||||
text-align: center;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
border: 0;
|
||||
color: #fff;
|
||||
font-size: 1rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.actionRect {
|
||||
fill: var(--background) !important;
|
||||
.removeButton {
|
||||
padding: 4px 0;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.addButton svg rect {
|
||||
fill: var(--background) !important;
|
||||
.deleteButtonContainer {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
border-radius: 50%;
|
||||
padding: 8px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
:global(.darkApp) .addButton rect {
|
||||
fill: var(--background) !important;
|
||||
.deleteIcon {
|
||||
font-size: 18px;
|
||||
color: var(--secondary-color);
|
||||
}
|
||||
|
||||
.cartItemActions :global(.ant-input-number-outlined) {
|
||||
border: none;
|
||||
width: 40px;
|
||||
background-color: inherit;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.cartItemActions :global(.ant-input-number-input) {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.plusIcon {
|
||||
margin-bottom: 1px;
|
||||
color: var(--secondary-background);
|
||||
}
|
||||
|
||||
.minusIcon {
|
||||
color: var(--secondary-foreground);
|
||||
}
|
||||
|
||||
.deleteIcon {
|
||||
position: relative;
|
||||
right: 1px;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { MinusOutlined, PlusOutlined } from "@ant-design/icons";
|
||||
import { Button, message } from "antd";
|
||||
import { Button, InputNumber, message } from "antd";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { useGetRestaurantDetailsQuery } from "redux/api/others";
|
||||
@@ -8,7 +8,7 @@ import { useAppSelector, useAppDispatch } from "redux/hooks";
|
||||
import { Product } from "utils/types/appTypes";
|
||||
import NextIcon from "components/Icons/NextIcon";
|
||||
import { addItem, removeItem, updateQuantity } from "features/order/orderSlice";
|
||||
import ProText from "components/ProText";
|
||||
import PlusIcon from "components/Icons/PlusIcon";
|
||||
|
||||
export function AddToCartButton({ item }: { item: Product }) {
|
||||
const { t } = useTranslation();
|
||||
@@ -161,68 +161,66 @@ export function AddToCartButton({ item }: { item: Product }) {
|
||||
return isInCart && !hasOptions ? (
|
||||
<>
|
||||
<div
|
||||
className={styles.addButton}
|
||||
style={{
|
||||
width: 90,
|
||||
height: 30,
|
||||
position: "absolute",
|
||||
bottom: 3,
|
||||
[isRTL ? "left" : "right"]: 1,
|
||||
background: "#FAFAFA",
|
||||
borderRadius: 888,
|
||||
className={styles.cartItemActions}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault;
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
shape="circle"
|
||||
iconPlacement="start"
|
||||
icon={<MinusOutlined title="minus" style={{ color: "black" }} />}
|
||||
size="small"
|
||||
onClick={handleMinusClick}
|
||||
className={styles.addButton}
|
||||
style={{
|
||||
backgroundColor: "white",
|
||||
width: 28,
|
||||
height: 28,
|
||||
position: "absolute",
|
||||
bottom: 1,
|
||||
[isRTL ? "left" : "right"]: 60,
|
||||
minWidth: 28,
|
||||
border: "none",
|
||||
}}
|
||||
/>
|
||||
<ProText
|
||||
style={{
|
||||
position: "absolute",
|
||||
bottom: 7,
|
||||
[isRTL ? "left" : "right"]: 45,
|
||||
fontSize: 14,
|
||||
fontWeight: 700,
|
||||
fontStyle: "Bold",
|
||||
lineHeight: "100%",
|
||||
letterSpacing: "0.06px",
|
||||
textAlign: "center",
|
||||
verticalAlign: "middle",
|
||||
}}
|
||||
>
|
||||
{totalQuantity}
|
||||
</ProText>
|
||||
<Button
|
||||
shape="circle"
|
||||
iconPlacement="start"
|
||||
icon={<PlusOutlined title="plus" />}
|
||||
size="small"
|
||||
onClick={handlePlusClick}
|
||||
className={styles.addButton}
|
||||
style={{
|
||||
backgroundColor: "#FFC600",
|
||||
width: 28,
|
||||
height: 28,
|
||||
position: "absolute",
|
||||
bottom: 1,
|
||||
[isRTL ? "left" : "right"]: 2,
|
||||
minWidth: 28,
|
||||
}}
|
||||
/>
|
||||
<div className={styles.quantityControls}>
|
||||
<div className={styles.quantityInputContainer}>
|
||||
<Button
|
||||
shape="circle"
|
||||
iconPlacement="start"
|
||||
icon={<MinusOutlined title="minus" style={{ color: "black" }} />}
|
||||
size="small"
|
||||
onClick={handleMinusClick}
|
||||
className={styles.addButton}
|
||||
style={{
|
||||
backgroundColor: "white",
|
||||
width: 28,
|
||||
height: 28,
|
||||
border: "none",
|
||||
}}
|
||||
/>
|
||||
<InputNumber
|
||||
min={1}
|
||||
max={99}
|
||||
value={totalQuantity}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault;
|
||||
}}
|
||||
onChange={(value: number | null) =>
|
||||
dispatch(
|
||||
updateQuantity({
|
||||
id: item.id,
|
||||
uniqueId: basicCartItem?.uniqueId || "",
|
||||
quantity: value || 1,
|
||||
}),
|
||||
)
|
||||
}
|
||||
size="small"
|
||||
controls={false}
|
||||
className={styles.quantityInput}
|
||||
name="id"
|
||||
/>
|
||||
<Button
|
||||
shape="circle"
|
||||
iconPlacement="start"
|
||||
icon={<PlusIcon color="#FFF" />}
|
||||
size="small"
|
||||
onClick={handlePlusClick}
|
||||
disabled={totalQuantity >= 99}
|
||||
className={styles.addButton}
|
||||
style={{
|
||||
backgroundColor: "#FFC600",
|
||||
width: 28,
|
||||
height: 28,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
@@ -246,6 +244,7 @@ export function AddToCartButton({ item }: { item: Product }) {
|
||||
)
|
||||
}
|
||||
onClick={handleClick}
|
||||
disabled={!hasOptions && totalQuantity >= 99}
|
||||
className={styles.addButton}
|
||||
style={{
|
||||
color: "#302E3E",
|
||||
|
||||
@@ -2,7 +2,6 @@ import styles from "pages/menu/components/MenuList/ProductCard.module.css";
|
||||
import { Card, Badge } from "antd";
|
||||
import ProText from "components/ProText.tsx";
|
||||
import ArabicPrice from "components/ArabicPrice";
|
||||
import { colors } from "ThemeConstants.ts";
|
||||
import { ItemDescriptionIcons } from "components/ItemDescriptionIcons/ItemDescriptionIcons.tsx";
|
||||
import ImageWithFallback from "components/ImageWithFallback";
|
||||
import { Product } from "utils/types/appTypes.ts";
|
||||
@@ -207,7 +206,14 @@ export default function ProductCard({ item, setIsBottomSheetOpen }: Props) {
|
||||
width={91}
|
||||
height={96}
|
||||
/>
|
||||
<AddToCartButton item={item} />
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
bottom: 3,
|
||||
}}
|
||||
>
|
||||
<AddToCartButton item={item} />
|
||||
</div>
|
||||
</Badge>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -171,7 +171,7 @@
|
||||
}
|
||||
|
||||
.headerContainer {
|
||||
margin: 5px 0px;
|
||||
margin: 5px 0 0 0;
|
||||
}
|
||||
|
||||
/* Enhanced responsive item description */
|
||||
|
||||
Reference in New Issue
Block a user