From a232fdabe21b30ce08418db7f983f1243db7f8e5 Mon Sep 17 00:00:00 2001 From: Mohammed Al-yaseen Date: Wed, 14 Jan 2026 17:37:37 +0300 Subject: [PATCH] show data in cards --- .../productChoicesCard/ProductChoicesCard.tsx | 162 ++++++++++++++++ .../components/CartMobileTabletLayout.tsx | 130 +------------ .../youMayLike/YouMightAlsoLike.tsx | 2 +- src/pages/checkout/hooks/types.ts | 31 ++- .../AddToCartButton/AddToCartButton.tsx | 6 +- src/pages/order/components/OrderDetails.tsx | 142 +------------- src/pages/orders/types.ts | 183 +++++++++--------- .../product/components/ProductFooter.tsx | 101 +++++----- src/utils/types/appTypes.ts | 24 ++- 9 files changed, 370 insertions(+), 411 deletions(-) create mode 100644 src/components/productChoicesCard/ProductChoicesCard.tsx diff --git a/src/components/productChoicesCard/ProductChoicesCard.tsx b/src/components/productChoicesCard/ProductChoicesCard.tsx new file mode 100644 index 0000000..86a4803 --- /dev/null +++ b/src/components/productChoicesCard/ProductChoicesCard.tsx @@ -0,0 +1,162 @@ +import { Space, Divider } from "antd"; +import ProText from "components/ProText.tsx"; +import styles from "pages/cart/cart.module.css"; +import ArabicPrice from "components/ArabicPrice"; +import ImageWithFallback from "components/ImageWithFallback"; +import CartActionsButtons from "components/CartActionsButtons/CartActionsButtons.tsx"; +import { CartItem } from "utils/types/appTypes.ts"; +import { useAppSelector } from "redux/hooks.ts"; +import useBreakPoint from "hooks/useBreakPoint.ts"; +import { OrderItem } from "pages/checkout/hooks/types.ts"; + +type ProductChoicesCardProps = { + product: CartItem | OrderItem; + addDividerAfter: boolean; +}; +export default function ProductChoicesCard({ + product, + addDividerAfter, +}: ProductChoicesCardProps) { + const { isRTL } = useAppSelector((state) => state.locale); + const { isMobile, isTablet } = useBreakPoint(); + + const getMenuItemImageStyle = () => { + if (isMobile) { + return { + width: 115, + height: 96, + }; + } + return { + width: 120, + height: 120, + }; + }; + + return ( +
+ + +
+ + {product.name} + +
+ + {product.type === "CartItem" && + (isRTL + ? product.variant?.optionsAR.map((o) => o.value).join(", ") + : product.variant?.options.map((o) => o.value).join(", "))} + {product.type === "OrderItem" && product.variantName} + + + {product.type === "CartItem" + ? product.extrasgroupnew?.map((o) => ( + + {isRTL ? o.extrasStringAR : o.extrasString} + + )) + : // ToDo + product.itemline} +
+
+ +
+
+
+ + {product.type === "CartItem" && ( +
+ +
+ )} +
+
+ + {addDividerAfter && } +
+ ); +} diff --git a/src/pages/cart/components/CartMobileTabletLayout.tsx b/src/pages/cart/components/CartMobileTabletLayout.tsx index b937f7a..1dbff65 100644 --- a/src/pages/cart/components/CartMobileTabletLayout.tsx +++ b/src/pages/cart/components/CartMobileTabletLayout.tsx @@ -1,9 +1,6 @@ import { Card, Divider, Space, Layout, Button, Popconfirm } from "antd"; -import ArabicPrice from "components/ArabicPrice"; -import CartActionsButtons from "components/CartActionsButtons/CartActionsButtons.tsx"; -import ImageWithFallback from "components/ImageWithFallback"; + import ProHeader from "components/ProHeader/ProHeader.tsx"; -import ProText from "components/ProText.tsx"; import ProTitle from "components/ProTitle.tsx"; import { clearCart, selectCart } from "features/order/orderSlice.ts"; import styles from "pages/cart/cart.module.css"; @@ -20,10 +17,10 @@ import SpecialRequestCard from "pages/cart/components/specialRequest/SpecialRequ import TableNumberCard from "pages/cart/components/TableNumberCard.tsx"; import { OrderType } from "pages/checkout/hooks/types"; import { useTranslation } from "react-i18next"; -import { Variant } from "utils/types/appTypes"; import DeleteIcon from "components/Icons/DeleteIcon"; import PlusIcon from "components/Icons/PlusIcon"; import { GiftItemsCard } from "pages/redeem/components/GiftItemsCard"; +import ProductChoicesCard from "components/productChoicesCard/ProductChoicesCard.tsx"; interface CartMobileTabletLayoutProps { form: FormInstance; @@ -41,18 +38,6 @@ export default function CartMobileTabletLayout({ const getResponsiveClass = () => (isTablet ? "tablet" : "mobile"); const navigate = useNavigate(); const dispatch = useAppDispatch(); - const getMenuItemImageStyle = () => { - if (isMobile) { - return { - width: 115, - height: 96, - }; - } - return { - width: 120, - height: 120, - }; - }; return ( @@ -137,112 +122,11 @@ export default function CartMobileTabletLayout({ )} {items.map((item, index) => ( -
- - -
- - {item.name}{" "} - - {isRTL - ? (item.variant as Variant)?.optionsAR?.[0]?.value - : (item.variant as Variant)?.options?.[0]?.value} - - -
- - {item.description} - -
-
- -
-
-
- -
- -
-
-
- - {index !== items.length - 1 && ( - - )} -
+ ))} - - -
- -
- - - {index !== orderDetails?.orderItems?.length - 1 && ( - - )} - + {orderDetails?.orderItems.map((item, index) => ( + ))} diff --git a/src/pages/orders/types.ts b/src/pages/orders/types.ts index 8ed6ebc..00d63df 100644 --- a/src/pages/orders/types.ts +++ b/src/pages/orders/types.ts @@ -1,92 +1,93 @@ export interface ProductDetails { - data: Daum[] - name: string - nameAR: string - image: string - price: number - variants: Variant[] - theExtrasGroups: TheExtrasGroup[] - discount: number - options: Option[] - hasVariants: number - currency: string - short_description: string - short_descriptionAR: string - } - - export interface Daum { - id: number - name: string - data: string[] - prices: string[] - pricesNew: string[] - nameAR: string - dataAR: string[] - } - - export interface Variant { - id: number - price: number - options: string - image: string - qty: number - enable_qty: number - order: number - item_id: number - created_at: string - updated_at: string - deleted_at: any - available: string - OptionsList: string - extras: any[] - } - - export interface TheExtrasGroup { - id: number - name: string - nameAR: string - label: string - labelAR: string - limit: number - item_id: number - created_at: string - updated_at: string - deleted_at: any - force_limit_selection: number - extras: Extra[] - } - - export interface Extra { - id: number - item_id: number - price: number - name: string - nameAR: string - created_at: string - updated_at: string - deleted_at: any - extra_for_all_variants: number - is_custome: number - is_available: number - modifier_id: any - pivot: Pivot - } - - export interface Pivot { - group_id: number - extra_id: number - } - - export interface Option { - id: number - item_id: number - name: string - nameAR: string - options: string - optionsAR: string - optionprices: string - created_at: string - updated_at: string - deleted_at: any - } - \ No newline at end of file + data: Daum[]; + name: string; + nameAR: string; + image: string; + price: number; + variants: Variant[]; + theExtrasGroups: TheExtrasGroup[]; + discount: number; + options: Option[]; + hasVariants: number; + currency: string; + short_description: string; + short_descriptionAR: string; +} + +export interface Daum { + id: number; + name: string; + data: string[]; + prices: string[]; + pricesNew: string[]; + nameAR: string; + dataAR: string[]; +} +type VariantOptionType = { option: string; value: string }; + +export interface Variant { + id: number; + price: number; + options: VariantOptionType[]; + optionsAR: VariantOptionType[]; + image: string; + qty: number; + enable_qty: number; + order: number; + item_id: number; + created_at: string; + updated_at: string; + deleted_at: any; + available: string; + OptionsList: string; + extras: any[]; +} + +export interface TheExtrasGroup { + id: number; + name: string; + nameAR: string; + label: string; + labelAR: string; + limit: number; + item_id: number; + created_at: string; + updated_at: string; + deleted_at: any; + force_limit_selection: number; + extras: Extra[]; +} + +export interface Extra { + id: number; + item_id: number; + price: number; + name: string; + nameAR: string; + created_at: string; + updated_at: string; + deleted_at: any; + extra_for_all_variants: number; + is_custome: number; + is_available: number; + modifier_id: any; + pivot: Pivot; +} + +export interface Pivot { + group_id: number; + extra_id: number; +} + +export interface Option { + id: number; + item_id: number; + name: string; + nameAR: string; + options: string; + optionsAR: string; + optionprices: string; + created_at: string; + updated_at: string; + deleted_at: any; +} diff --git a/src/pages/product/components/ProductFooter.tsx b/src/pages/product/components/ProductFooter.tsx index 38e4cc3..681a2b9 100644 --- a/src/pages/product/components/ProductFooter.tsx +++ b/src/pages/product/components/ProductFooter.tsx @@ -85,10 +85,23 @@ export default function ProductFooter({ comment: specialRequest, variant: selectedVariant, extras: selectedExtras, - extrasgroupnew: Object.keys(selectedGroups).map((key) => ({ - groupid: key, - extrasid: selectedGroups[Number(key)], - })), + extrasgroupnew: Object.keys(selectedGroups).map((key) => { + const groupInfo = product.theExtrasGroups?.find( + (g) => g.id.toString() === key, + ); + const selectedGroupExtrasIds = selectedGroups[Number(key)]; + + const extrasInfo = groupInfo?.extras.filter((e) => + selectedGroupExtrasIds.includes(e.id.toString()), + ); + console.log(extrasInfo); + return { + groupid: key, + extrasid: selectedGroupExtrasIds, + extrasString: `${groupInfo?.name}: ${extrasInfo?.map((e) => e.name).join(", ")}`, + extrasStringAR: `${groupInfo?.nameAR}: ${extrasInfo?.map((e) => e.nameAR).join(" + ")}`, + }; + }), extrasgroup: Object.entries(selectedGroups).flatMap( ([groupId, extrasIds]) => { if (!extrasIds || extrasIds.length === 0) { @@ -117,7 +130,7 @@ export default function ProductFooter({ }), ); // Navigate back to menu - scroll position will be restored automatically - if (!isDesktop && !isBottomSheetView ) window.history.back(); + if (!isDesktop && !isBottomSheetView) window.history.back(); else { onClose?.(); } @@ -175,46 +188,44 @@ export default function ProductFooter({ width: "100%", }} > - - + + diff --git a/src/utils/types/appTypes.ts b/src/utils/types/appTypes.ts index 99151d2..bb1404f 100644 --- a/src/utils/types/appTypes.ts +++ b/src/utils/types/appTypes.ts @@ -314,24 +314,29 @@ export interface Translation { // ################################################# -export interface CartItem { +export type CartItem = { + type: "CartItem"; id: number | string; name: string; price: number; image: string; quantity: number; description: string; - variant?: Variant | string; + variant?: Variant; extras?: Extra[]; - extrasgroupnew?: Array<{ groupid: string; extrasid: Array }>; + extrasgroupnew?: Array<{ + groupid: string; + extrasid: Array; + extrasString: string; + extrasStringAR: string; + }>; extrasgroup?: Array; isHasLoyalty?: boolean; no_of_stamps_give?: number; comment?: string; // Unique identifier for cart items with the same product but different variants/extras/comments uniqueId?: string; - -} +}; export interface UserType { id: number; @@ -616,8 +621,17 @@ export interface Option { export interface Extra { id: number; + item_id: number; price: number; name: string; + nameAR: string; + created_at: string; + updated_at: string; + deleted_at: any; + extra_for_all_variants: number; + is_custome: number; + is_available: number; + modifier_id: any; } export interface TheExtrasGroup {