ContinueToPayOrderInfo.tsx 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. "use client";
  2. import { useState } from "react";
  3. import Image from "next/image";
  4. import { useRouter } from 'next/navigation';
  5. import {useConfig} from "@/utils/hooks/useConfig";
  6. import { OrderDetails } from "@/types/customer/type";
  7. import { confirmDialog } from "@/components/theme/ui/kernel/confirm/api";
  8. import ProductsModalPendingOrder from "./ProductsModalPendingOrder";
  9. import dynamic from "next/dynamic";
  10. import {getAddressFromOrderDetailAddressList} from "@/utils/orderDetailTools";
  11. const CountDown = dynamic(() => import("@/components/common/CountDown"), {
  12. ssr: false,
  13. });
  14. export default function ContinueToPayOrderInfo({
  15. orderDetail
  16. }: {
  17. orderDetail: OrderDetails;
  18. }) {
  19. const router = useRouter();
  20. const {currencies,getCurrentCurrencyItem} = useConfig();
  21. const currentCurrency = getCurrentCurrencyItem();
  22. const currencySymbol = currentCurrency.symbol;
  23. const orderCurrency = currencies.find(item => item.code === orderDetail.orderCurrencyCode) || null;
  24. const orderSymbol = orderCurrency?.symbol || currencySymbol;
  25. const [productsModalOpen, setProductsModalOpen] = useState(false);
  26. const countDownEnd = (new Date(orderDetail.createdAt)).getTime() + 24*3600*1000;
  27. const shippingAddress = getAddressFromOrderDetailAddressList(orderDetail.addresses,"order_shipping");
  28. const billingAddress = getAddressFromOrderDetailAddressList(orderDetail.addresses,"order_billing");
  29. const totalQty = orderDetail.totalQtyOrdered > 1 ? String(orderDetail.totalQtyOrdered) + 'Items' : '1 Item';
  30. const productItems = orderDetail.items.edges.map((item) => {
  31. return item.node;
  32. });
  33. // 倒计时结束跳转到首页
  34. const handleCountDownEnd = () => {
  35. confirmDialog({
  36. title: "Order Timeout",
  37. content: "This order timeout, has been canceled. Will redirect to home page.",
  38. noCancel: true,
  39. }).then(() => {
  40. router.replace('/');
  41. });
  42. };
  43. const closeProductsModal = () => {
  44. setProductsModalOpen(false);
  45. };
  46. const openProductsModal = () => {
  47. setProductsModalOpen(true);
  48. };
  49. return(
  50. <>
  51. <div className="sticky top-15 z-10 box-border w-full h-14 px-4 flex items-center justify-between bg-ly-green">
  52. <span className="text-ly-14 font-medium text-white">Awaiting For Payment</span>
  53. <CountDown
  54. endTime={countDownEnd}
  55. onCountDownEnd={handleCountDownEnd}
  56. />
  57. </div>
  58. <div className="mt-6 box-border px-4">
  59. <h3 className="text-ly-24 font-medium">Shipping Address</h3>
  60. <div className="w-full mt-3 box-border rounded-md border-1 px-3.75 bg-[url(/image/address-bg.webp)] bg-position-[0_-84%] bg-size-[100%_auto]">
  61. <div className="border-b-1 flex h-11.25 items-center justify-between">
  62. <p className="text-ly-13 font-medium">
  63. {shippingAddress.firstName} {shippingAddress.lastName}
  64. <span className="border-r border-ly-gray h-3.5 mx-2"></span>
  65. {shippingAddress.phone}
  66. </p>
  67. {/* <svg className="w-4 h-4" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="0" y="0" width="16" height="16" fill="#FFFFFF" fillOpacity="0"></rect><path stroke="rgba(0, 0, 0, 1)" strokeWidth="1.5" strokeLinejoin="round" strokeLinecap="square" d="M6.32031 4.27051L10.4202 8.37036L6.32031 12.4702"></path></svg> */}
  68. </div>
  69. <div className="flex items-center h-10">
  70. <svg className="w-4 h-4" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24" fill="none">
  71. <path stroke="rgba(0, 0, 0, 1)" strokeWidth="1.5" strokeLinejoin="round" strokeLinecap="round" d="M6.01652 15.917C4.48522 16.3764 3.53809 17.0111 3.53809 17.712C3.53809 19.1141 7.32661 20.2507 12 20.2507C16.6734 20.2507 20.4619 19.1141 20.4619 17.712C20.4619 17.0111 19.5148 16.3764 17.9835 15.917"></path>
  72. <path d="M12.0002 16.8657C12.0002 16.8657 17.5005 13.271 17.5005 9.11522C17.5005 6.15182 15.0379 3.74951 12.0002 3.74951C8.96254 3.74951 6.5 6.15182 6.5 9.11522C6.5 13.271 12.0002 16.8657 12.0002 16.8657Z" stroke="rgba(0, 0, 0, 1)" strokeWidth="1.5" strokeLinejoin="round" ></path>
  73. <path d="M11.9983 11.3653C13.1666 11.3653 14.1138 10.4181 14.1138 9.24979C14.1138 8.08144 13.1666 7.13428 11.9983 7.13428C10.83 7.13428 9.88281 8.08144 9.88281 9.24979C9.88281 10.4181 10.83 11.3653 11.9983 11.3653Z" stroke="rgba(0, 0, 0, 1)" strokeWidth="1.5" strokeLinejoin="round" ></path>
  74. </svg>
  75. <span className="text-ly-12 ml-2.5">
  76. {shippingAddress.address},
  77. {shippingAddress.city},
  78. {shippingAddress.state},
  79. {shippingAddress.postcode},
  80. {shippingAddress.country}
  81. </span>
  82. </div>
  83. </div>
  84. </div>
  85. <div className="mt-6 box-border px-4">
  86. <h3 className="text-ly-24 font-medium">Billing Address</h3>
  87. <div className="w-full mt-3 box-border rounded-md border-1 px-3.75 bg-[url(/image/address-bg.webp)] bg-position-[0_-84%] bg-size-[100%_auto]">
  88. <div className="border-b-1 flex h-11.25 items-center justify-between">
  89. <p className="text-ly-13 font-medium">
  90. {billingAddress.firstName} {billingAddress.lastName}
  91. <span className="border-r border-ly-gray h-3.5 mx-2"></span>
  92. {billingAddress.phone}
  93. </p>
  94. {/* <svg className="w-4 h-4" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="0" y="0" width="16" height="16" fill="#FFFFFF" fillOpacity="0"></rect><path stroke="rgba(0, 0, 0, 1)" strokeWidth="1.5" strokeLinejoin="round" strokeLinecap="square" d="M6.32031 4.27051L10.4202 8.37036L6.32031 12.4702"></path></svg> */}
  95. </div>
  96. <div className="flex items-center h-10">
  97. <svg className="w-4 h-4" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24" fill="none">
  98. <path stroke="rgba(0, 0, 0, 1)" strokeWidth="1.5" strokeLinejoin="round" strokeLinecap="round" d="M6.01652 15.917C4.48522 16.3764 3.53809 17.0111 3.53809 17.712C3.53809 19.1141 7.32661 20.2507 12 20.2507C16.6734 20.2507 20.4619 19.1141 20.4619 17.712C20.4619 17.0111 19.5148 16.3764 17.9835 15.917"></path>
  99. <path d="M12.0002 16.8657C12.0002 16.8657 17.5005 13.271 17.5005 9.11522C17.5005 6.15182 15.0379 3.74951 12.0002 3.74951C8.96254 3.74951 6.5 6.15182 6.5 9.11522C6.5 13.271 12.0002 16.8657 12.0002 16.8657Z" stroke="rgba(0, 0, 0, 1)" strokeWidth="1.5" strokeLinejoin="round" ></path>
  100. <path d="M11.9983 11.3653C13.1666 11.3653 14.1138 10.4181 14.1138 9.24979C14.1138 8.08144 13.1666 7.13428 11.9983 7.13428C10.83 7.13428 9.88281 8.08144 9.88281 9.24979C9.88281 10.4181 10.83 11.3653 11.9983 11.3653Z" stroke="rgba(0, 0, 0, 1)" strokeWidth="1.5" strokeLinejoin="round" ></path>
  101. </svg>
  102. <span className="text-ly-12 ml-2.5">
  103. {billingAddress.address},
  104. {billingAddress.city},
  105. {billingAddress.state},
  106. {billingAddress.postcode},
  107. {billingAddress.country}
  108. </span>
  109. </div>
  110. </div>
  111. </div>
  112. <div className="w-full box-border px-4 mt-6">
  113. <div className="flex items-center">
  114. <span className="text-ly-12 flex-none mr-1">
  115. Order Summary({totalQty})
  116. </span>
  117. <button className="flex-none w-4 h-4" onClick={openProductsModal}>
  118. <svg className="block w-full h-full" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="0" y="0" width="16" height="16" fill="#FFFFFF" fillOpacity="0"></rect><path stroke="rgba(0, 0, 0, 1)" strokeWidth="1.5" strokeLinejoin="round" strokeLinecap="square" d="M6.32031 4.27051L10.4202 8.37036L6.32031 12.4702"></path></svg>
  119. </button>
  120. </div>
  121. <div className="relative w-full box-border pr-9 mt-3.5">
  122. <div className="w-full box-border flex overflow-x-auto">
  123. {productItems.map((product) => {
  124. return(
  125. <div key={product.id} className="relative flex-none w-16 h-21.5 mr-3 last:mr-0">
  126. <Image src="https://cdn.asteriahair.com/media/catalog/product/6/_/6_3_2.png" alt="product" fill={true} />
  127. </div>
  128. )
  129. })}
  130. </div>
  131. <button className="absolute top-1/2 right-1 w-4 h-4 -translate-y-1/2"
  132. onClick={openProductsModal}
  133. >
  134. <svg className="block w-full h-full" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16" fill="none"><path fill="rgba(0, 0, 0, 1)" d="M14 8.66667L2 8.66667L2 7.33333L14 7.33333L14 8.66667ZM1.33333 7.33333L2 7.33333L2 8.66667L1.33333 8.66667L1.33333 7.33333ZM14 8.66667C13.6318 8.66667 13.3333 8.36819 13.3333 8C13.3333 7.63181 13.6318 7.33333 14 7.33333C14.3682 7.33333 14.6667 7.63181 14.6667 8C14.6667 8.36819 14.3682 8.66667 14 8.66667Z"></path><path stroke="rgba(0, 0, 0, 1)" strokeWidth="1.3333333333333333" strokeLinejoin="round" strokeLinecap="square" d="M10 4L14 8L10 12"></path></svg>
  135. </button>
  136. </div>
  137. </div>
  138. <div className="box-border px-4 w-full mt-6">
  139. <h3 className="text-ly-24 font-medium">Promotion Details</h3>
  140. <div className="flex justify-between mt-3 first:mt-0">
  141. <p className="text-ly-12 leading-ly-20">Subtotal</p>
  142. <p className="text-ly-12 leading-ly-20">{orderSymbol}{orderDetail.subTotal}</p>
  143. </div>
  144. {orderDetail.rewardPointsEarned > 0 &&
  145. <div className="flex justify-between mt-3 first:mt-0">
  146. <p className="text-ly-12 leading-ly-20">You Earn</p>
  147. <p className="text-ly-12 leading-ly-20">{orderDetail.rewardPointsEarned} Reward Points</p>
  148. </div>
  149. }
  150. {orderDetail.shippingAmount !== 0 &&
  151. <div className="flex justify-between mt-3 first:mt-0">
  152. <p className="text-ly-12 leading-ly-20">Shipping</p>
  153. <p className="text-ly-12 leading-ly-20">{orderSymbol}{orderDetail.shippingAmount}</p>
  154. </div>
  155. }
  156. {Number(orderDetail?.shippingInsuranceAmount) > 0 &&
  157. <div className="flex justify-between mt-3 first:mt-0">
  158. <p className="text-ly-12 leading-ly-20">Shipping</p>
  159. <p className="text-ly-12 leading-ly-20">{orderSymbol}{Number(orderDetail.shippingInsuranceAmount)}</p>
  160. </div>
  161. }
  162. {orderDetail.taxAmount !== 0 &&
  163. <div className="flex justify-between mt-3 first:mt-0">
  164. <p className="text-ly-12 leading-ly-20">Tax</p>
  165. <p className="text-ly-12 leading-ly-20">{orderSymbol}{orderDetail.taxAmount}</p>
  166. </div>
  167. }
  168. {(orderDetail.vipPlusAmount !== '0.00' && orderDetail.vipPlusAmount !== null) &&
  169. <div className="flex justify-between mt-3 first:mt-0">
  170. <p className="text-ly-12 leading-ly-20">Plus Fee</p>
  171. <p className="text-ly-12 leading-ly-20">{orderSymbol}{orderDetail.vipPlusAmount}</p>
  172. </div>
  173. }
  174. {orderDetail.discountAmount !== 0 &&
  175. <div className="flex justify-between mt-3 first:mt-0">
  176. <p className="text-ly-12 leading-ly-20">Discount</p>
  177. <p className="text-ly-12 leading-ly-20">-{orderSymbol}{orderDetail.discountAmount}</p>
  178. </div>
  179. }
  180. {(orderDetail.giftcardAmount !== '0.00' && orderDetail.giftcardAmount !== null) &&
  181. <div className="flex justify-between mt-3 first:mt-0">
  182. <p className="text-ly-12 leading-ly-20">Gift Card</p>
  183. <p className="text-ly-12 leading-ly-20">-{orderSymbol}{orderDetail.giftcardAmount}</p>
  184. </div>
  185. }
  186. {(orderDetail.vipDiscountAmount !== '0.00' && orderDetail.vipDiscountAmount !== null) &&
  187. <div className="flex justify-between mt-3 first:mt-0">
  188. <p className="text-ly-12 leading-ly-20">Plus Save</p>
  189. <p className="text-ly-12 leading-ly-20">-{orderSymbol}{orderDetail.vipDiscountAmount}</p>
  190. </div>
  191. }
  192. {orderDetail.rewardPointsAmount > 0 &&
  193. <div className="flex justify-between mt-3 first:mt-0">
  194. <p className="text-ly-12 leading-ly-20">You Redeem ({orderDetail.rewardPointsUsed} Reward Points)</p>
  195. <p className="text-ly-12 leading-ly-20">-{orderSymbol}{orderDetail.rewardPointsAmount}</p>
  196. </div>
  197. }
  198. {/* <div className="flex justify-between mt-3 first:mt-0">
  199. <p className="text-ly-12 leading-ly-20">You Earn</p>
  200. <p className="text-ly-12 leading-ly-20">600 Reward Points</p>
  201. </div> */}
  202. <div className="flex justify-between mt-3 first:mt-0">
  203. <p className="text-ly-16 leading-ly-24">Total</p>
  204. <p className="text-ly-16 leading-ly-24 font-bold">{orderSymbol}{orderDetail.grandTotal}</p>
  205. </div>
  206. </div>
  207. {/** 产品弹窗 */}
  208. <ProductsModalPendingOrder
  209. isOpen={productsModalOpen}
  210. products={productItems}
  211. currencySymbol={orderSymbol}
  212. onClose={() => closeProductsModal()}
  213. />
  214. </>
  215. );
  216. }