@lmnto/h-mall-shared 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/app.css +457 -0
  2. package/bitbucket-pipelines.yml +223 -0
  3. package/package.json +43 -0
  4. package/public/gif/balloon.gif +0 -0
  5. package/public/gif/gift.gif +0 -0
  6. package/public/img/ai-dialog.png +0 -0
  7. package/public/img/ai-x1-banner.png +0 -0
  8. package/public/img/ai-x1.png +0 -0
  9. package/public/img/alert-Icon.png +0 -0
  10. package/public/img/aleta-payment-kyc-require.png +0 -0
  11. package/public/img/aleta-payment-pending.png +0 -0
  12. package/public/img/aleta-payment-rejected.png +0 -0
  13. package/public/img/aleta-payment-subscription-required.png +0 -0
  14. package/public/img/boost-banner-bg.png +0 -0
  15. package/public/img/boost-banner-right.png +0 -0
  16. package/public/img/boost-banner.png +0 -0
  17. package/public/img/boost-dialog-bg.png +0 -0
  18. package/public/img/boostPower.png +0 -0
  19. package/public/img/boostTooltip.png +0 -0
  20. package/public/img/brand-icon.svg +23 -0
  21. package/public/img/brand-text.svg +11 -0
  22. package/public/img/card-icon.png +0 -0
  23. package/public/img/cashback-Icon.png +0 -0
  24. package/public/img/crown.svg +9 -0
  25. package/public/img/empty-box.png +0 -0
  26. package/public/img/gen3-dialog.png +0 -0
  27. package/public/img/gen3-home-banner-bg.png +0 -0
  28. package/public/img/gen3-image.png +0 -0
  29. package/public/img/gift.png +0 -0
  30. package/public/img/img-placeholder-illustration.svg +6 -0
  31. package/public/img/logo.svg +31 -0
  32. package/public/img/offerBanner.png +0 -0
  33. package/public/img/pagenotfound.png +0 -0
  34. package/public/img/partial-pay-payment-successful.png +0 -0
  35. package/public/img/phoneShippingBG.png +0 -0
  36. package/public/img/placeholder-image.jpg +0 -0
  37. package/public/img/powerIcon.png +0 -0
  38. package/public/img/product-01.png +0 -0
  39. package/public/img/product-02.jpg +0 -0
  40. package/public/img/product-03.jpg +0 -0
  41. package/public/img/product-04.jpg +0 -0
  42. package/public/img/product-05.png +0 -0
  43. package/public/img/product-06.png +0 -0
  44. package/public/img/profile-avatar.svg +12 -0
  45. package/public/img/promotion-icon.png +0 -0
  46. package/public/img/session-expired.png +0 -0
  47. package/public/img/shipping-alert-icon.png +0 -0
  48. package/public/img/shippingIcon.png +0 -0
  49. package/public/img/smart-pay-banner-how.png +0 -0
  50. package/public/img/smart-pay-banner-own.png +0 -0
  51. package/public/img/smart-pay-chose.png +0 -0
  52. package/public/img/smart-pay-easy.png +0 -0
  53. package/public/img/smart-pay-payment.png +0 -0
  54. package/public/img/smart-plan-fire.gif +0 -0
  55. package/public/img/smart-plan-sparkle.gif +0 -0
  56. package/public/img/special.png +0 -0
  57. package/public/img/specialOfferBg.png +0 -0
  58. package/public/img/stop-shipping-banner.png +0 -0
  59. package/public/img/subscriptionBanner.png +0 -0
  60. package/public/img/subscriptionIcon.png +0 -0
  61. package/public/img/successIcon.png +0 -0
  62. package/public/img/wallet-icon.png +0 -0
  63. package/public/img/world-wide-shipping.png +0 -0
  64. package/public/next.svg +1 -0
  65. package/public/vercel.svg +1 -0
  66. package/shared/components/AddressFormComponent.tsx +215 -0
  67. package/shared/components/AddressShippingFormComponent.tsx +223 -0
  68. package/shared/components/AiPaymentDialog.tsx +95 -0
  69. package/shared/components/AppLoadingComponent.tsx +15 -0
  70. package/shared/components/AppLoadingComponentV2.tsx +18 -0
  71. package/shared/components/Button.tsx +48 -0
  72. package/shared/components/BuySubscriptionDialog.tsx +75 -0
  73. package/shared/components/CartDrawerComponent.tsx +324 -0
  74. package/shared/components/CashbackComponent.tsx +48 -0
  75. package/shared/components/CashbackMigrationComponent.tsx +41 -0
  76. package/shared/components/CommissionNonEligibleComponent.tsx +27 -0
  77. package/shared/components/CustomNextImage.tsx +50 -0
  78. package/shared/components/CustomNextLink.tsx +46 -0
  79. package/shared/components/EditAddressFormComponent.tsx +254 -0
  80. package/shared/components/EmptyCartMessageComponent.tsx +25 -0
  81. package/shared/components/EmptyCartMessageForCartPage.tsx +61 -0
  82. package/shared/components/EmptyLegacyOrderMessageForOrdersPage.tsx +52 -0
  83. package/shared/components/EmptyOrderMessageForOrdersPage.tsx +62 -0
  84. package/shared/components/EmptyOrderMessageForShippingOrdersPage.tsx +62 -0
  85. package/shared/components/Footer.tsx +71 -0
  86. package/shared/components/GreetingDialog.tsx +96 -0
  87. package/shared/components/Header.tsx +106 -0
  88. package/shared/components/HoldShippingDialog.tsx +165 -0
  89. package/shared/components/HomeBanners.tsx +298 -0
  90. package/shared/components/InactiveCartDialog.tsx +69 -0
  91. package/shared/components/InputCartQuantity.tsx +342 -0
  92. package/shared/components/Inputfield.tsx +110 -0
  93. package/shared/components/ListItemComponent.tsx +82 -0
  94. package/shared/components/LoadingIconComponent.tsx +284 -0
  95. package/shared/components/OrderNotFoundComponent.tsx +56 -0
  96. package/shared/components/PageHeader.tsx +42 -0
  97. package/shared/components/PhoneNumberCountries.tsx +133 -0
  98. package/shared/components/PhoneShippingDialog.tsx +77 -0
  99. package/shared/components/PickupDialog.tsx +92 -0
  100. package/shared/components/ProductNotFoundComponent.tsx +56 -0
  101. package/shared/components/ProductPriceComponent.tsx +32 -0
  102. package/shared/components/ProfileMenu.tsx +120 -0
  103. package/shared/components/RequestCreditNoteInvoiceDialog.tsx +214 -0
  104. package/shared/components/RequestInvoiceDialog.tsx +194 -0
  105. package/shared/components/SelectCities.tsx +133 -0
  106. package/shared/components/SelectComponent.tsx +334 -0
  107. package/shared/components/SelectCountries.tsx +179 -0
  108. package/shared/components/SelectPickUpStore.tsx +131 -0
  109. package/shared/components/SelectStates.tsx +144 -0
  110. package/shared/components/ServerTime.tsx +68 -0
  111. package/shared/components/SessionDialogComponent.tsx +60 -0
  112. package/shared/components/ShippingAddressFormDialogComponent.tsx +51 -0
  113. package/shared/components/Sidebar.tsx +281 -0
  114. package/shared/components/SpecialOfferDialog.tsx +193 -0
  115. package/shared/components/StatusComponents.tsx +25 -0
  116. package/shared/components/StepperComponent.tsx +79 -0
  117. package/shared/components/StepperSmartPayComponent.tsx +97 -0
  118. package/shared/components/SubscriptionPurchaseDialogComponent.tsx +81 -0
  119. package/shared/components/TableComponent.tsx +144 -0
  120. package/shared/components/TablePaginationComponent.tsx +151 -0
  121. package/shared/components/aleta/AletaManagerComponent.tsx +52 -0
  122. package/shared/components/aleta/KycPendingStatus.tsx +33 -0
  123. package/shared/components/aleta/KycRejectedStatus.tsx +53 -0
  124. package/shared/components/aleta/KycRequiredStatus.tsx +53 -0
  125. package/shared/components/aleta/SubscriptionRequiredStatus.tsx +45 -0
  126. package/shared/components/icons/AletaWalletIcon.tsx +21 -0
  127. package/shared/components/icons/BrandIcon.tsx +97 -0
  128. package/shared/components/icons/BrandText.tsx +47 -0
  129. package/shared/components/icons/CartIcon.tsx +21 -0
  130. package/shared/components/icons/DoneIcon.tsx +27 -0
  131. package/shared/components/icons/HomnifiIcon.tsx +23 -0
  132. package/shared/components/icons/InfoIcon.tsx +16 -0
  133. package/shared/components/icons/SmartPayProductIcon.tsx +31 -0
  134. package/shared/components/payments/DisclaimerAlertDialog.tsx +205 -0
  135. package/shared/components/payments/EmptyAssets.tsx +23 -0
  136. package/shared/components/payments/PaybyWalletItemComponent.tsx +116 -0
  137. package/shared/components/payments/PaymentAssetItemComponent.tsx +101 -0
  138. package/shared/components/payments/RequestProcessingDialog.tsx +123 -0
  139. package/shared/components/payments/WalletSectionManager.tsx +82 -0
  140. package/shared/components/payments/WalletSliderComponent.tsx +326 -0
  141. package/shared/components/payments/WalletTermsAndConditionComponent.tsx +88 -0
  142. package/shared/constants/address-shipping.schema.ts +56 -0
  143. package/shared/constants/address.schema.ts +56 -0
  144. package/shared/constants/app.ts +323 -0
  145. package/shared/constants/environment.ts +23 -0
  146. package/shared/constants/feature-flags.ts +15 -0
  147. package/shared/constants/query-keys.ts +106 -0
  148. package/shared/constants/routes.ts +41 -0
  149. package/shared/constants/socket.ts +15 -0
  150. package/shared/contexts/HomeProductsContext.tsx +51 -0
  151. package/shared/contexts/MainWrapperContext.tsx +289 -0
  152. package/shared/contexts/WebSocketContext.tsx +155 -0
  153. package/shared/hooks/useAddressForm.ts +169 -0
  154. package/shared/hooks/useAddresses.ts +28 -0
  155. package/shared/hooks/useAppForm.ts +39 -0
  156. package/shared/hooks/useCart.ts +207 -0
  157. package/shared/hooks/useCopy.ts +45 -0
  158. package/shared/hooks/useCountries.ts +27 -0
  159. package/shared/hooks/useCustomRouter.ts +51 -0
  160. package/shared/hooks/useDebounce.ts +21 -0
  161. package/shared/hooks/useInvoice.ts +41 -0
  162. package/shared/hooks/useOnlineUser.ts +38 -0
  163. package/shared/hooks/usePayments.ts +101 -0
  164. package/shared/hooks/useShippingAddressForm.ts +70 -0
  165. package/shared/hooks/useShippingAddresses.ts +33 -0
  166. package/shared/hooks/useStores.ts +29 -0
  167. package/shared/hooks/useUserActivity.ts +43 -0
  168. package/shared/i18n/client.ts +27 -0
  169. package/shared/i18n/locales/en.ts +383 -0
  170. package/shared/i18n/locales/it.ts +373 -0
  171. package/shared/i18n/server.ts +7 -0
  172. package/shared/services/addresses.service.ts +27 -0
  173. package/shared/services/api/core/ApiError.ts +29 -0
  174. package/shared/services/api/core/ApiRequestOptions.ts +25 -0
  175. package/shared/services/api/core/ApiResult.ts +11 -0
  176. package/shared/services/api/core/CancelablePromise.ts +130 -0
  177. package/shared/services/api/core/OpenAPI.ts +37 -0
  178. package/shared/services/api/core/request.ts +376 -0
  179. package/shared/services/api/index.ts +64 -0
  180. package/shared/services/api/models/AddAllProductToShippingCartDto.ts +7 -0
  181. package/shared/services/api/models/AddProductToCartDto.ts +8 -0
  182. package/shared/services/api/models/AddProductToShippingCartDto.ts +8 -0
  183. package/shared/services/api/models/AdminPlaceOrderDto.ts +16 -0
  184. package/shared/services/api/models/AssignPickupSerialNumberDto.ts +10 -0
  185. package/shared/services/api/models/CreateUserAddressDto.ts +19 -0
  186. package/shared/services/api/models/DeletCartProductsArrayDto.ts +7 -0
  187. package/shared/services/api/models/GenerateInvoiceDto.ts +7 -0
  188. package/shared/services/api/models/OrderConfirmationEmailDto.ts +8 -0
  189. package/shared/services/api/models/PlaceOrderDto.ts +9 -0
  190. package/shared/services/api/models/PlaceShipmentOrderDto.ts +8 -0
  191. package/shared/services/api/models/ProductBoostDto.ts +18 -0
  192. package/shared/services/api/models/RemoveAssignedSerialNumberDto.ts +9 -0
  193. package/shared/services/api/models/RemoveProductToCartDto.ts +8 -0
  194. package/shared/services/api/models/ShipmentItem.ts +8 -0
  195. package/shared/services/api/models/ShippingCartUpdateBillingAddressesDto.ts +7 -0
  196. package/shared/services/api/models/ShippingCartUpdateShippingMethodDto.ts +7 -0
  197. package/shared/services/api/models/UnfreezeWalletDto.ts +8 -0
  198. package/shared/services/api/models/UpdateCartBillingAddressesDto.ts +7 -0
  199. package/shared/services/api/models/UpdateCartPaymentMethodDto.ts +9 -0
  200. package/shared/services/api/models/UpdateCartShippingMethodDto.ts +7 -0
  201. package/shared/services/api/models/UpdateCartStoreDto.ts +7 -0
  202. package/shared/services/api/models/UpdateProductDto.ts +11 -0
  203. package/shared/services/api/models/UpdateShipmentItemStatusDto.ts +24 -0
  204. package/shared/services/api/models/UpdateShippingCartPaymentMethodDto.ts +9 -0
  205. package/shared/services/api/models/UpdateUserAddressDto.ts +19 -0
  206. package/shared/services/api/models/ValidateAuthCodeDto.ts +8 -0
  207. package/shared/services/api/models/WithdrawOrderWalletDto.ts +8 -0
  208. package/shared/services/api/services/AddressesService.ts +160 -0
  209. package/shared/services/api/services/AdminsDevicesService.ts +28 -0
  210. package/shared/services/api/services/AdminsOrdersService.ts +117 -0
  211. package/shared/services/api/services/AdminsPickupsService.ts +57 -0
  212. package/shared/services/api/services/AdminsProductsService.ts +86 -0
  213. package/shared/services/api/services/CartsService.ts +190 -0
  214. package/shared/services/api/services/CashBackQueueService.ts +39 -0
  215. package/shared/services/api/services/CategoriesService.ts +65 -0
  216. package/shared/services/api/services/DefaultService.ts +19 -0
  217. package/shared/services/api/services/FeaturesFlagsService.ts +20 -0
  218. package/shared/services/api/services/IossQueueService.ts +39 -0
  219. package/shared/services/api/services/OrderCallbackService.ts +67 -0
  220. package/shared/services/api/services/OrderEmailsService.ts +40 -0
  221. package/shared/services/api/services/OrderImportService.ts +228 -0
  222. package/shared/services/api/services/OrdersService.ts +183 -0
  223. package/shared/services/api/services/PaymentGatewayService.ts +19 -0
  224. package/shared/services/api/services/PaymentsService.ts +88 -0
  225. package/shared/services/api/services/ProductsService.ts +67 -0
  226. package/shared/services/api/services/ShipmentOrderCallbackService.ts +67 -0
  227. package/shared/services/api/services/ShipmentOrdersService.ts +88 -0
  228. package/shared/services/api/services/ShipmentsService.ts +30 -0
  229. package/shared/services/api/services/ShippingCartService.ts +247 -0
  230. package/shared/services/api/services/ShippingMethodsService.ts +20 -0
  231. package/shared/services/api/services/StoresService.ts +25 -0
  232. package/shared/services/api/services/SyncServiceQueueService.ts +39 -0
  233. package/shared/services/api/services/UpgradeOrdersService.ts +26 -0
  234. package/shared/services/api/services/UsersAuthService.ts +45 -0
  235. package/shared/services/api/services/UsersService.ts +53 -0
  236. package/shared/services/api/services/XeraQueueService.ts +39 -0
  237. package/shared/services/index.ts +0 -0
  238. package/shared/services/payment-method.service.ts +29 -0
  239. package/shared/stores/cartStore.ts +108 -0
  240. package/shared/stores/countriesStore.ts +62 -0
  241. package/shared/stores/formStore.ts +19 -0
  242. package/shared/stores/loadingStore.ts +12 -0
  243. package/shared/stores/userStore.ts +32 -0
  244. package/shared/types/SelectComponent.types.ts +31 -0
  245. package/shared/types/addressForm.ts +27 -0
  246. package/shared/types/cart.ts +208 -0
  247. package/shared/types/category.ts +6 -0
  248. package/shared/types/creditNote.ts +0 -0
  249. package/shared/types/feature-flags.ts +5 -0
  250. package/shared/types/icon.ts +5 -0
  251. package/shared/types/index.d.ts +84 -0
  252. package/shared/types/order.ts +332 -0
  253. package/shared/types/pagination.ts +5 -0
  254. package/shared/types/payments.ts +68 -0
  255. package/shared/types/product.ts +54 -0
  256. package/shared/types/shoppingCart.ts +219 -0
  257. package/shared/types/upgradeCart.ts +226 -0
  258. package/shared/types/user.ts +36 -0
  259. package/shared/utils/app.util.ts +261 -0
  260. package/shared/utils/notifications.util.ts +39 -0
  261. package/shared/utils/user-session.util.ts +171 -0
  262. package/tailwind.config.ts +234 -0
@@ -0,0 +1,324 @@
1
+ "use client";
2
+
3
+ import { Drawer, IconButton, Typography } from "@material-tailwind/react";
4
+ import { usePathname } from "next/navigation";
5
+ import { useCallback, useEffect, useRef, useState } from "react";
6
+ import { IoIosClose } from "react-icons/io";
7
+
8
+ import {
9
+ CART_STATUS,
10
+ DEFAULT_CURRENCY,
11
+ QUANTITY_ACTIONS,
12
+ } from "../constants/app";
13
+ import { ROUTES } from "../constants/routes";
14
+ import { useCart } from "../hooks/useCart";
15
+ import useCustomRouter from "../hooks/useCustomRouter";
16
+ import { useGlobalDebounce } from "../hooks/useDebounce";
17
+ import { _useScopedI18n } from "../i18n/client";
18
+ import { CartTableItemComponentProps, ICart } from "../types/cart";
19
+ import { replaceForbiddenKeyword } from "../utils/app.util";
20
+ import ButtonCustom from "./Button";
21
+ import CustomNextImage from "./CustomNextImage";
22
+ import EmptyCartMessageComponent from "./EmptyCartMessageComponent";
23
+ import InputCartQuantity from "./InputCartQuantity";
24
+ import ProductPriceComponent from "./ProductPriceComponent";
25
+
26
+ export type CartDrawerComponentProps = {
27
+ open: boolean;
28
+ closeDrawer: () => void;
29
+ isCartLoading: boolean;
30
+ cartData: ICart;
31
+ };
32
+
33
+ export default function CartDrawerComponent({
34
+ open,
35
+ closeDrawer,
36
+ isCartLoading,
37
+ cartData,
38
+ }: CartDrawerComponentProps) {
39
+ //
40
+ const scopeT = _useScopedI18n("sharedComponents.cartDrawerComponent");
41
+
42
+ const pathname = usePathname();
43
+ const { addToCart, removeProductFromCart, updateCartState } = useCart();
44
+ const { push } = useCustomRouter();
45
+ const lastProcessedQuantityRef = useRef<Map<number, number>>(new Map());
46
+ const [hasError, setHasError] = useState<boolean>(false);
47
+ // Sync last processed quantities with cart data when it updates
48
+ useEffect(() => {
49
+ if (cartData?.cartProducts) {
50
+ cartData.cartProducts.forEach((product) => {
51
+ // Update ref to match current cart quantity (from API response)
52
+ lastProcessedQuantityRef.current.set(product.id, product.quantity);
53
+ });
54
+ }
55
+ }, [cartData]);
56
+
57
+ const handleQuantity = useCallback(
58
+ (id: number, qty: number, action: string) => {
59
+ if (cartData) {
60
+ let newCartProducts = [...cartData.cartProducts];
61
+ const targetProduct: CartTableItemComponentProps = newCartProducts.find(
62
+ (item) => item.id === id,
63
+ );
64
+ if (action === QUANTITY_ACTIONS.add) {
65
+ addToCart.mutate({
66
+ productSKU: targetProduct.product.sku,
67
+ quantity: qty,
68
+ });
69
+ } else if (action === QUANTITY_ACTIONS.minus) {
70
+ removeProductFromCart.mutate({
71
+ productSKU: targetProduct.product.sku,
72
+ quantity: qty,
73
+ });
74
+ }
75
+ }
76
+ },
77
+ [cartData, addToCart, removeProductFromCart],
78
+ );
79
+
80
+ //todo: create cartProduct interface
81
+ const renderCartDrawerItems = (
82
+ cartProducts: CartTableItemComponentProps[],
83
+ ) => {
84
+ if (!cartProducts || cartProducts?.length === 0)
85
+ return (
86
+ <>
87
+ {" "}
88
+ <EmptyCartMessageComponent />{" "}
89
+ </>
90
+ );
91
+ return (
92
+ <ul className="flex flex-col">
93
+ {" "}
94
+ {cartProducts?.map((cartProduct: CartTableItemComponentProps) =>
95
+ renderCartItem(cartProduct),
96
+ )}
97
+ </ul>
98
+ );
99
+ };
100
+
101
+ const handleQuantityChange = useGlobalDebounce(
102
+ (qty: number, cartProduct: CartTableItemComponentProps) => {
103
+ const lastProcessedQty =
104
+ lastProcessedQuantityRef.current.get(cartProduct.id) ??
105
+ cartProduct.quantity;
106
+
107
+ if (lastProcessedQty < qty) {
108
+ const diff = qty - lastProcessedQty;
109
+ lastProcessedQuantityRef.current.set(cartProduct.id, qty);
110
+ handleQuantity(cartProduct.id, diff, QUANTITY_ACTIONS.add);
111
+ } else if (lastProcessedQty > qty) {
112
+ const diff = lastProcessedQty - qty;
113
+ lastProcessedQuantityRef.current.set(cartProduct.id, qty);
114
+ handleQuantity(cartProduct.id, diff, QUANTITY_ACTIONS.minus);
115
+ }
116
+ },
117
+ 500,
118
+ );
119
+
120
+ const renderCartItem = (cartProduct: CartTableItemComponentProps) => {
121
+ const handleQuantityAddingRemoving = (qty: number) => {
122
+ handleQuantityChange(qty, cartProduct);
123
+ };
124
+
125
+ return (
126
+ <li
127
+ key={cartProduct.id}
128
+ className="border-b border-b-slate-50 py-3 md:py-4 first-of-type:pt-0"
129
+ >
130
+ <div className="flex gap-2 justify-between items-center ">
131
+ <div className="flex w-3/4 items-center gap-3">
132
+ <div className="w-[60px] border border-slate-50 rounded-md">
133
+ <CustomNextImage
134
+ src={cartProduct.product.featureImage}
135
+ alt={cartProduct.product.name}
136
+ height={60}
137
+ width={60}
138
+ />
139
+ </div>
140
+ <div className="flex justify-start flex-col flex-1 h-full py-1">
141
+ <Typography
142
+ variant="h5"
143
+ className="text-sm font-medium text-black-500 line-clamp-2 font-box"
144
+ >
145
+ {cartProduct.product.name}
146
+ </Typography>
147
+ <Typography
148
+ variant="lead"
149
+ className="text-xs font-medium my-0.5 text-slate-400"
150
+ >
151
+ {scopeT("category")}:{" "}
152
+ {replaceForbiddenKeyword(cartProduct.product.category.name)}
153
+ </Typography>
154
+
155
+ {cartProduct?.maximumUserCanPurchase &&
156
+ cartProduct.userPurchaseLimit != null &&
157
+ cartProduct.quantity >= cartProduct.maximumUserCanPurchase && (
158
+ <Typography
159
+ variant="lead"
160
+ className="text-xs leading-3 font-medium text-orange-500"
161
+ >
162
+ {!!cartProduct.totalOrderExistsForProduct && (
163
+ <>
164
+ {scopeT("alreadyPurchased")}
165
+ &nbsp;
166
+ {cartProduct.totalOrderExistsForProduct}
167
+ </>
168
+ )}
169
+ {scopeT("maxPurchaseLimit")} {cartProduct.userPurchaseLimit}
170
+ </Typography>
171
+ )}
172
+ </div>
173
+ </div>
174
+ </div>
175
+
176
+ {cartProduct.feedBackMessage && (
177
+ <div className="col-span-12 m-2">
178
+ <Typography
179
+ variant="lead"
180
+ className="text-xs text-center leading-5 font-medium text-orange-500 bg-orange-50 border border-orange-300 p-2 rounded-lg"
181
+ >
182
+ {cartProduct.feedBackMessage}
183
+ </Typography>
184
+ </div>
185
+ )}
186
+ {cartProduct.product.maxCartQuantity !== null && (
187
+ <div className="col-span-12 m-2">
188
+ <Typography
189
+ variant="lead"
190
+ className="text-xs text-center leading-5 font-medium text-orange-500 bg-orange-50 border border-orange-300 p-2 rounded-lg"
191
+ >
192
+ You are allowed to purchase {cartProduct.product.maxCartQuantity}{" "}
193
+ items
194
+ </Typography>
195
+ </div>
196
+ )}
197
+ <div className=" pt-3">
198
+ <div className="flex justify-between items-center flex-wrap">
199
+ <div className=" ml-[20%] border-none flex items-center justify-end md:justify-start ">
200
+ <div>
201
+ <div className="flex gap-2 items-baseline">
202
+ <Typography
203
+ variant="h5"
204
+ className="text-base font-semibold text-black-500 mb-0 "
205
+ >
206
+ <ProductPriceComponent
207
+ amount={cartProduct?.unitPrice || 0}
208
+ />
209
+ </Typography>
210
+ {cartProduct?.unitDiscount > 0 && (
211
+ <Typography
212
+ variant="small"
213
+ className="text-xs font-semibold line-through text-black-200 mb-0 "
214
+ >
215
+ <ProductPriceComponent
216
+ amount={cartProduct?.unitOriginalPrice || 0}
217
+ />
218
+ </Typography>
219
+ )}
220
+ </div>
221
+
222
+ {cartProduct?.unitDiscount > 0 && (
223
+ <Typography
224
+ variant="small"
225
+ className="text-xs font-semibold text-green-500 mb-0 "
226
+ >
227
+ Save{" "}
228
+ <ProductPriceComponent
229
+ amount={cartProduct?.unitDiscount || 0}
230
+ />
231
+ </Typography>
232
+ )}
233
+ </div>
234
+ </div>
235
+
236
+ <InputCartQuantity
237
+ quantity={cartProduct.quantity}
238
+ maxCartQuantity={cartProduct.product.maxCartQuantity}
239
+ isLoading={isCartLoading || pathname === ROUTES.dashboard.cart}
240
+ onQuantityChange={handleQuantityAddingRemoving}
241
+ canProductBeRemoved={cartProduct.canProductBeRemoved}
242
+ size="lg"
243
+ maximumUserCanPurchase={
244
+ !!cartProduct.maximumUserCanPurchase
245
+ ? cartProduct.maximumUserCanPurchase
246
+ : Infinity
247
+ }
248
+ quantityStepper={cartProduct.product.quantityStepper}
249
+ onErrorChange={(hasErrorFromQuantityInput) =>
250
+ setHasError(hasErrorFromQuantityInput)
251
+ }
252
+ />
253
+ </div>
254
+ </div>
255
+ </li>
256
+ );
257
+ };
258
+ return (
259
+ <>
260
+ <Drawer
261
+ placement="right"
262
+ open={open}
263
+ size={410}
264
+ onClose={closeDrawer}
265
+ className="max-w-[25rem] h-svh"
266
+ >
267
+ <div className="p-3 md:p-3.5 flex items-center justify-between border-b border-b-slate-50 mb-2">
268
+ <Typography
269
+ variant="h5"
270
+ className="text-sm md:text-base font-semibold text-black-500"
271
+ >
272
+ {scopeT("title")}
273
+ </Typography>
274
+ <IconButton
275
+ variant="text"
276
+ className="text-black-500 w-5 h-5"
277
+ onClick={closeDrawer}
278
+ >
279
+ <IoIosClose className="w-6 h-6 text-black-500" />
280
+ </IconButton>
281
+ </div>
282
+
283
+ <div className="px-3 md:px-4 mr-1 cartAutoHeight">
284
+ {cartData && renderCartDrawerItems(cartData.cartProducts)}
285
+ </div>
286
+
287
+ <ul className="p-3 md:p-4 flex flex-col gap-3">
288
+ <li className="flex justify-between items-center gap-5">
289
+ <Typography
290
+ variant="h5"
291
+ className="text-base font-semibold text-black-500"
292
+ >
293
+ {scopeT("subTotal")}
294
+ </Typography>
295
+ <Typography
296
+ variant="h5"
297
+ className="text-base font-semibold text-black-500"
298
+ >
299
+ {DEFAULT_CURRENCY}
300
+ {cartData && cartData.subTotal}
301
+ </Typography>
302
+ </li>
303
+ <li>
304
+ <ButtonCustom
305
+ onClick={async () => {
306
+ await updateCartState.mutateAsync(CART_STATUS.checkout);
307
+ closeDrawer();
308
+ push(ROUTES.dashboard.checkout);
309
+ }}
310
+ className="w-full"
311
+ icon={undefined}
312
+ loading={updateCartState.isPending}
313
+ disabled={
314
+ (cartData && cartData.cartProducts.length <= 0) || hasError
315
+ }
316
+ >
317
+ {scopeT("checkoutNowBtn")}
318
+ </ButtonCustom>
319
+ </li>
320
+ </ul>
321
+ </Drawer>
322
+ </>
323
+ );
324
+ }
@@ -0,0 +1,48 @@
1
+ import { Typography } from "@material-tailwind/react";
2
+
3
+ import casBackIcon from "../../public/img/cashback-Icon.png";
4
+ import { SMLYK } from "../constants/app";
5
+ import { CashBack } from "../types/shoppingCart";
6
+ import CustomNextImage from "./CustomNextImage";
7
+
8
+ export type CashbackComponentProps = {
9
+ cashBack?: CashBack;
10
+ messageIfNoCashback?: boolean;
11
+ };
12
+
13
+ export default function CashbackComponent({
14
+ cashBack,
15
+ messageIfNoCashback = false,
16
+ }: CashbackComponentProps) {
17
+ return (
18
+ <>
19
+ <div className="cashback-bg flex items-center gap-4 mt-5">
20
+ <CustomNextImage
21
+ src={casBackIcon.src}
22
+ alt={"cashback"}
23
+ width={50}
24
+ height={50}
25
+ />
26
+ <div>
27
+ <Typography variant="h6" className="text-black-500">
28
+ Cashback
29
+ </Typography>
30
+
31
+ <Typography
32
+ variant="lead"
33
+ className="text-slate-600 text-xs font-normal leading-5"
34
+ >
35
+ {!!messageIfNoCashback ? (
36
+ <>No cashback applicable on Pickup delivery mode</>
37
+ ) : (
38
+ <>
39
+ Cashback of ${cashBack?.totalAmount} worth of {SMLYK.label} will
40
+ be credited to your Homnifi wallet
41
+ </>
42
+ )}
43
+ </Typography>
44
+ </div>
45
+ </div>
46
+ </>
47
+ );
48
+ }
@@ -0,0 +1,41 @@
1
+ import { Typography } from "@material-tailwind/react";
2
+
3
+ import casBackIcon from "../../public/img/cashback-Icon.png";
4
+ import { CASHBACK_TOKEN } from "../constants/app";
5
+ import { CashBack } from "../types/shoppingCart";
6
+ import CustomNextImage from "./CustomNextImage";
7
+
8
+ export type CashbackMigrationComponentProps = {
9
+ cashBack?: CashBack;
10
+ };
11
+
12
+ export default function CashbackMigrationComponent({
13
+ cashBack,
14
+ }: CashbackMigrationComponentProps) {
15
+ return (
16
+ <>
17
+ <div className="cashback-bg flex items-center gap-4 mt-5">
18
+ <CustomNextImage
19
+ src={casBackIcon.src}
20
+ alt={"cashback"}
21
+ width={50}
22
+ height={50}
23
+ />
24
+ <div>
25
+ <Typography variant="h6" className="text-black-500">
26
+ Get back Platform token credits
27
+ </Typography>
28
+
29
+ <Typography
30
+ variant="lead"
31
+ className="text-slate-600 text-xs font-normal leading-5"
32
+ >
33
+ ${cashBack?.totalAmount} worth of{" "}
34
+ {CASHBACK_TOKEN?.[cashBack?.assetSymbol]?.label} will be credited to
35
+ your Homnifi wallet.
36
+ </Typography>
37
+ </div>
38
+ </div>
39
+ </>
40
+ );
41
+ }
@@ -0,0 +1,27 @@
1
+ import { Typography } from "@material-tailwind/react";
2
+
3
+ import { _useScopedI18n } from "../i18n/client";
4
+
5
+ export type CommissionNonEligibleComponentProps = {
6
+ name: string;
7
+ };
8
+
9
+ export default function CommissionNonEligibleComponent({
10
+ name,
11
+ }: CommissionNonEligibleComponentProps) {
12
+ //
13
+ const scopeT = _useScopedI18n(
14
+ "sharedComponents.commissionNonEligibleComponent",
15
+ );
16
+
17
+ return (
18
+ <>
19
+ <Typography
20
+ variant="lead"
21
+ className="text-xs text-center leading-5 font-medium text-orange-500 bg-orange-50 border border-orange-300 p-2 px-5 rounded-lg"
22
+ >
23
+ {name} {scopeT("message")}
24
+ </Typography>
25
+ </>
26
+ );
27
+ }
@@ -0,0 +1,50 @@
1
+ import { ImageProps } from "next/image";
2
+ import React, { useMemo, useState } from "react";
3
+
4
+ import { PLACEHOLDER_IMAGE } from "../constants/app";
5
+
6
+ export default function CustomNextImage({
7
+ className,
8
+ ...props
9
+ }: ImageProps & {
10
+ className?: string;
11
+ }) {
12
+ //
13
+ const [isValidImg] = useState(true);
14
+
15
+ const renderImage = useMemo(() => {
16
+ let imgSrc = props.src;
17
+
18
+ if (!props.src) {
19
+ imgSrc = PLACEHOLDER_IMAGE;
20
+ }
21
+
22
+ if (typeof props.src == "string") {
23
+ if (props.src.startsWith("http") || props.src.startsWith("/")) {
24
+ //do nothing
25
+ } else {
26
+ imgSrc = PLACEHOLDER_IMAGE;
27
+ }
28
+ }
29
+
30
+ return (
31
+ <img
32
+ {...props}
33
+ src={imgSrc as string}
34
+ alt={props.alt ? props.alt : ""}
35
+ className={`${className} ${isValidImg ? "" : "bg-gray-300 opacity-30 dark:opacity-100 dark:bg-gray-700 rounded-md"}`}
36
+ />
37
+ // <Image
38
+ // {...props}
39
+ // src={isValidImg ? imgSrc : PLACEHOLDER_IMAGE}
40
+ // alt={props.alt ? props.alt : ''}
41
+ // className={`${className} ${isValidImg ? '' : 'bg-gray-300 opacity-30 dark:opacity-100 dark:bg-gray-700 rounded-md'}`}
42
+ // onError={() => setIsValidImg(false)}
43
+ // priority
44
+ // quality={60}
45
+ // />
46
+ );
47
+ }, [isValidImg, className, props]);
48
+
49
+ return <>{renderImage}</>;
50
+ }
@@ -0,0 +1,46 @@
1
+ import Link, { LinkProps } from "next/link";
2
+ import { usePathname } from "next/navigation";
3
+ import React, { useCallback } from "react";
4
+
5
+ import { useLoadingStore } from "../stores/loadingStore";
6
+
7
+ export default function CustomNextLink({
8
+ children,
9
+ className,
10
+ target,
11
+ onClick,
12
+ ...props
13
+ }: LinkProps & {
14
+ children?: React.ReactNode;
15
+ className?: string;
16
+ target?: React.HTMLAttributeAnchorTarget;
17
+ onClick?: () => void;
18
+ }) {
19
+ //
20
+ const pathname = usePathname();
21
+ const { setLoading } = useLoadingStore();
22
+
23
+ const handleOnClick = useCallback(() => {
24
+ if (pathname != props.href && !props.href.toString().startsWith("http")) {
25
+ setLoading(true);
26
+
27
+ setTimeout(() => {
28
+ setLoading(false);
29
+ }, 5000);
30
+ }
31
+ }, [pathname, props.href, setLoading]);
32
+
33
+ return (
34
+ <Link
35
+ onClick={() => {
36
+ handleOnClick();
37
+ onClick?.();
38
+ }}
39
+ {...props}
40
+ target={target}
41
+ className={className}
42
+ >
43
+ {children}
44
+ </Link>
45
+ );
46
+ }