OrderDetailWrapper.tsx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. "use client";
  2. import {use, useEffect} from "react";
  3. import Link from "next/link";
  4. import Image from "next/image";
  5. import {GraphqlRequestResult} from "@/types/graphqlFetch/type";
  6. import { OrderDetailsData,ProductItemAdditional } from "@/types/customer/type";
  7. import { useCurrencyList } from "@utils/hooks/useCurrencyList";
  8. import Faqs from "./Faqs";
  9. function getProductAdditionalInfo(productItem: ProductItemAdditional) {
  10. const attributeKeys = Object.keys(productItem.attributes);
  11. let res = '';
  12. attributeKeys.forEach(key => {
  13. const attribute = productItem.attributes[key];
  14. if (attribute) {
  15. // option_label value_label
  16. if(res) {
  17. res = res + ', ' + attribute.option_label + ': ' + attribute.value_label;
  18. } else {
  19. res = attribute.option_label + ': ' + attribute.value_label;
  20. }
  21. }
  22. });
  23. return res;
  24. }
  25. export default function OrderDetailWrapper({
  26. orderDetailPromise,
  27. isGuest
  28. }: {
  29. orderDetailPromise: Promise<GraphqlRequestResult<OrderDetailsData>>;
  30. isGuest: boolean;
  31. }) {
  32. const {currencies} = useCurrencyList();
  33. const promiseRes = use(orderDetailPromise);
  34. const orderDetailRes = promiseRes.data?.customerOrder ?? null;
  35. const shippingAddress = orderDetailRes?.addresses?.edges.find(item => item.node.addressType === "order_shipping");
  36. let orderCreatedAt = 'Can\'t get order date';
  37. if(orderDetailRes?.createdAt) {
  38. const localDate = new Date(orderDetailRes.createdAt);
  39. orderCreatedAt = localDate.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
  40. }
  41. const productItems = orderDetailRes?.items?.edges.map(item => {
  42. return item.node;
  43. }) || [];
  44. const currency = currencies?.find(item => item.code === orderDetailRes?.orderCurrencyCode) || null;
  45. useEffect(() => {
  46. // 如果是游客且支付成功,删除cookie里的GUEST_CART_TOKEN GUEST_CART_ID
  47. /**Cookies can only be modified in a Server Action or Route Handler. Read more: https://nextjs.org/docs/app/api-reference/functions/cookies#options */
  48. if(isGuest) {
  49. fetch("/api/clearCartCookie",{
  50. method:"POST"
  51. });
  52. }
  53. }, [isGuest]);
  54. return (
  55. <>
  56. <div className="box-border px-4 w-full">
  57. <div className="w-12 h-12 mx-auto mt-9">
  58. <svg className="block w-full h-full" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M24 44C29.5228 44 34.5228 41.7614 38.1421 38.1421C41.7614 34.5228 44 29.5228 44 24C44 18.4772 41.7614 13.4772 38.1421 9.85786C34.5228 6.23858 29.5228 4 24 4C18.4772 4 13.4772 6.23858 9.85786 9.85786C6.23858 13.4772 4 18.4772 4 24C4 29.5228 6.23858 34.5228 9.85786 38.1421C13.4772 41.7614 18.4772 44 24 44Z" stroke="rgba(0, 0, 0, 1)" strokeWidth="3" strokeLinejoin="round" ></path><path stroke="rgba(0, 0, 0, 1)" strokeWidth="3" strokeLinecap="square" d="M16 24L22 30L34 18"></path></svg>
  59. </div>
  60. <p className="text-ly-16 text-center mt-6">Your Order Has Been Received</p>
  61. <p className="text-ly-16 mt-4 flex justify-center">
  62. <span className="px-3.75 leading-ly-28 bg-[#f0fffa]">Order #{orderDetailRes?._id}</span>
  63. </p>
  64. <p className="text-ly-12 text-center mt-4 leading-ly-22">
  65. Hello, {orderDetailRes?.customerFirstName} <br/>
  66. Thank you so much for your order !<br/>
  67. We’ll get started on your order very soon!<br/>
  68. You’ll receive an order confirmation email with details of your order in an hour, please be sure to check your email and confirm your order, that is very important for us to process your order.
  69. </p>
  70. <Link href="/" className="mt-6 flex justify-center items-center h-12 border-1 rounded-3xl text-ly-14">
  71. Continue Shopping
  72. </Link>
  73. </div>
  74. <div className="box-border px-4 w-full mt-6">
  75. <Faqs />
  76. </div>
  77. <div className="box-border px-4 w-full mt-6">
  78. <h4 className="text-ly-24 font-medium">Order Information</h4>
  79. <div className="mt-6 flex justify-between">
  80. <div className="text-ly-12 flex-none">Ship to:</div>
  81. <div className="w-40.5 text-ly-12 leading-ly-20 text-[#666666] flex-none">
  82. {
  83. shippingAddress?.node.firstName
  84. + ' ' + shippingAddress?.node.lastName
  85. + ' ' + shippingAddress?.node.phone
  86. + ' ' + shippingAddress?.node.address
  87. + ' ' + shippingAddress?.node.city
  88. + ' ' + shippingAddress?.node.state
  89. + ' ' + shippingAddress?.node.postcode
  90. + ' ' + shippingAddress?.node.country
  91. }
  92. </div>
  93. </div>
  94. <div className="mt-6 flex justify-between">
  95. <div className="text-ly-12 flex-none">Order number:</div>
  96. <div className="w-40.5 text-ly-12 leading-ly-20 text-[#666666] flex-none">
  97. {orderDetailRes?._id}
  98. </div>
  99. </div>
  100. <div className="mt-6 flex justify-between">
  101. <div className="text-ly-12 flex-none">Status:</div>
  102. <div className="w-40.5 text-ly-12 leading-ly-20 text-[#666666] flex-none capitalize">
  103. {orderDetailRes?.status}
  104. </div>
  105. </div>
  106. <div className="mt-6 flex justify-between">
  107. <div className="text-ly-12 flex-none">Order date:</div>
  108. <div className="w-40.5 text-ly-12 leading-ly-20 text-[#666666] flex-none">
  109. {orderCreatedAt}
  110. </div>
  111. </div>
  112. <div className="mt-6 flex justify-between">
  113. <div className="text-ly-12 flex-none">Shipping method:</div>
  114. <div className="w-40.5 text-ly-12 leading-ly-20 text-[#666666] flex-none">
  115. {orderDetailRes?.shippingTitle}
  116. </div>
  117. </div>
  118. <div className="mt-6 flex justify-between">
  119. <div className="text-ly-12 flex-none">Payment method:</div>
  120. <div className="w-40.5 text-ly-12 leading-ly-20 text-[#666666] flex-none">
  121. {orderDetailRes?.payment?.methodTitle}
  122. </div>
  123. </div>
  124. </div>
  125. <div className="box-border px-4 w-full mt-6">
  126. {productItems.map((product) => {
  127. return (
  128. <div key={product.id} className="w-full flex gap-2 pb-4 border-b-1 border-[#f0f0f0] last:border-0 last:pb-0">
  129. <div className="relative w-33 h-44 flex-none">
  130. <Image fill src="https://cdn.alipearlhair.com/media/catalog/product/2/_/2_104_20.jpg" alt="logo" />
  131. </div>
  132. <div className="flex-none w-50.75 flex flex-col justify-between">
  133. <div>
  134. <p className="text-ly-12 leading-ly-20 line-clamp-2">
  135. {product.name}
  136. </p>
  137. {
  138. product.additional &&
  139. <p className="mt-2 text-ly-12 leading-ly-20 text-ly-placeholder">
  140. {getProductAdditionalInfo(JSON.parse(product.additional))}
  141. </p>
  142. }
  143. </div>
  144. <div className="flex justify-between">
  145. <p className="text-ly-14 leading-ly-20 font-bold">
  146. {currency && currency.symbol}{product.price}
  147. </p>
  148. <p className="text-ly-12 leading-ly-20">x {product.qtyOrdered}</p>
  149. </div>
  150. </div>
  151. </div>
  152. );
  153. })}
  154. </div>
  155. <div className="box-border px-4 w-full mt-6 pt-6 border-t-1 border-black">
  156. <div className="flex justify-between mt-3 first:mt-0">
  157. <p className="text-ly-12 leading-ly-20">Subtotal</p>
  158. <p className="text-ly-12 leading-ly-20">{currency && currency.symbol}{orderDetailRes?.subTotal}</p>
  159. </div>
  160. <div className="flex justify-between mt-3 first:mt-0">
  161. <p className="text-ly-12 leading-ly-20">Shipping</p>
  162. <p className="text-ly-12 leading-ly-20">{currency && currency.symbol}{orderDetailRes?.shippingAmount}</p>
  163. </div>
  164. <div className="flex justify-between mt-3 first:mt-0">
  165. <p className="text-ly-12 leading-ly-20">Tax</p>
  166. <p className="text-ly-12 leading-ly-20">{currency && currency.symbol}{orderDetailRes?.taxAmount}</p>
  167. </div>
  168. <div className="flex justify-between mt-3 first:mt-0">
  169. <p className="text-ly-12 leading-ly-20">Discount</p>
  170. <p className="text-ly-12 leading-ly-20">{currency && currency.symbol}{orderDetailRes?.discountAmount}</p>
  171. </div>
  172. {/* <div className="flex justify-between mt-3 first:mt-0">
  173. <p className="text-ly-12 leading-ly-20">You Earn</p>
  174. <p className="text-ly-12 leading-ly-20">600 Reward Points</p>
  175. </div> */}
  176. <div className="flex justify-between mt-3 first:mt-0">
  177. <p className="text-ly-16 leading-ly-24">Total</p>
  178. <p className="text-ly-16 leading-ly-24 font-bold">{currency && currency.symbol}{orderDetailRes?.grandTotal}</p>
  179. </div>
  180. </div>
  181. </>
  182. );
  183. }