Pārlūkot izejas kodu

Merge branch 'master' into pc-zzf

zhangzf 2 dienas atpakaļ
vecāks
revīzija
55ae2b2b05
49 mainītis faili ar 1242 papildinājumiem un 1360 dzēšanām
  1. 5 1
      README.md
  2. 0 0
      public/favicon.svg
  3. 12 12
      src/app/(checkout)/checkout/_components/CheckoutAddress/AddressResultDisplay.tsx
  4. 44 37
      src/app/(checkout)/checkout/_components/CheckoutAddress/BillingAddressCheckout.tsx
  5. 192 171
      src/app/(checkout)/checkout/_components/CheckoutAddress/CheckoutAssress.tsx
  6. 75 68
      src/app/(checkout)/checkout/_components/CheckoutAddress/ShippingAddressCheckout.tsx
  7. 17 13
      src/app/(checkout)/checkout/_components/CheckoutCoupon/CheckoutCoupon.tsx
  8. 45 96
      src/app/(checkout)/checkout/_components/CheckoutProducts/CheckoutProducts.tsx
  9. 46 43
      src/app/(checkout)/checkout/_components/CheckoutWrapper.tsx
  10. 61 102
      src/app/(checkout)/checkout/_components/ContinueToPay/ContinueToPayOrderInfo.tsx
  11. 7 10
      src/app/(checkout)/checkout/_components/ContinueToPay/PaymentMethodContinueTpPay.tsx
  12. 52 0
      src/app/(checkout)/checkout/_components/ContinueToPay/ProductsInPendingOrder.tsx
  13. 0 124
      src/app/(checkout)/checkout/_components/ContinueToPay/ProductsModalPendingOrder.tsx
  14. 2 1
      src/app/(checkout)/checkout/_components/GiftCard/CheckoutGiftCardGate.tsx
  15. 5 5
      src/app/(checkout)/checkout/_components/LostInsurance/LostInsurance.tsx
  16. 10 12
      src/app/(checkout)/checkout/_components/PaymentMethodCheckout.tsx
  17. 11 11
      src/app/(checkout)/checkout/_components/PromotionsDetails.tsx
  18. 10 10
      src/app/(checkout)/checkout/_components/RewardPointsRedeemMoney/RewardPointsRedeemMoney.tsx
  19. 6 6
      src/app/(checkout)/checkout/_components/ShippingMethodCheckout.tsx
  20. 9 9
      src/app/(checkout)/checkout/_components/VipPlus/CheckoutVipPlus.tsx
  21. 9 9
      src/app/(checkout)/checkout/cart/_components/PromiseInCart.tsx
  22. 1 3
      src/app/(checkout)/checkout/cart/page.tsx
  23. 19 16
      src/app/(checkout)/checkout/continuetopay/page.tsx
  24. 1 2
      src/app/(checkout)/checkout/page.tsx
  25. 14 10
      src/app/(checkout)/layout.tsx
  26. 4 8
      src/app/(public)/customer/account/_components/AccountVipPopup.tsx
  27. 228 53
      src/app/(public)/paymentresult/_components/CancelOrFailure.tsx
  28. 10 6
      src/app/(public)/paymentresult/_components/Faqs.tsx
  29. 76 92
      src/app/(public)/paymentresult/_components/OrderDetailWrapper.tsx
  30. 1 1
      src/app/(public)/paymentresult/result/page.tsx
  31. 2 22
      src/app/globals.css
  32. 6 1
      src/app/layout.tsx
  33. 11 0
      src/components/common/SocialShare/SocialShare.tsx
  34. 0 14
      src/components/customer/OpenAuth.tsx
  35. 39 1
      src/components/customer/SettingModal.tsx
  36. 0 265
      src/components/customer/credentials/CredentialModal.tsx
  37. 0 21
      src/components/customer/credentials/index.tsx
  38. 0 23
      src/components/layout/navbar/CartAndUserActions.tsx
  39. 2 0
      src/components/layout/navbar/MobileMenu.tsx
  40. 39 0
      src/components/layout/navbar/NavbarActions.tsx
  41. 2 2
      src/components/layout/navbar/NavbarSearchIcon.tsx
  42. 11 41
      src/components/layout/navbar/index.tsx
  43. 1 1
      src/components/theme/ui/CommonModal.tsx
  44. 5 5
      src/components/theme/ui/PhoneNumberInput/PhoneNumberInput.tsx
  45. 5 5
      src/components/theme/ui/kernel/confirm/host.tsx
  46. 125 0
      src/providers/SocialShareProvider.tsx
  47. 1 26
      src/types/checkout/type.ts
  48. 1 1
      src/utils/hooks/useCheckoutAddress.ts
  49. 20 1
      src/utils/orderDetailTools.ts

+ 5 - 1
README.md

@@ -357,7 +357,11 @@ useEffect 只会在客户端执行,具体是在浏览器绘制后执行,服
     ---- 47 条 请求方法已经扩展是否携带token的参数,但是不再添加对于token的有效性校验,以后端接口返回的错误为依据判断有效性
 48. 游客token的创建优化(想在服务端创建写入token)--- 已完成
 49. 结账页地址模块未登录用户输入邮箱后判断是否注册过,如果注册过让用户登录;--- 已完成
-50. 注册接口,提交的phone是 +1 345345345 格式,但是保存到数据库后成了+1345345345
+50. 注册接口,提交的phone是 +1 345345345 格式,但是保存到数据库后成了+1345345345 --- 后端已处理
+51. 关于分享组件:https://chatgpt.com/share/6aa351f3-5ed0-83ea-8320-43d34d66f10a
+    -- 可以参考https://github.com/nygardk/react-share
+    -- 接着SocialShare写
+    -- https://developer.mozilla.org/zh-CN/docs/Web/API/Clipboard/writeText
 
 
 > 39,40 参考 https://chatgpt.com/share/6a4f0637-ad28-83ea-ad44-423740795054

src/app/favicon.svg → public/favicon.svg


+ 12 - 12
src/app/(checkout)/checkout/_components/CheckoutAddress/AddressResultDisplay.tsx

@@ -30,37 +30,37 @@ export default function AddressResultDisplay({
     return (
         <>
         {shippingAddress === null || !addressIsAvailable ?
-            <div className="box-border w-full h-15 flex items-center px-3.75 relative bg-[url(/image/address-bg.webp)] bg-position-[0_-84%] bg-size-[100%_auto]"
+            <div className="box-border w-full h-15 flex items-center px-4 relative bg-[url(/image/address-bg.webp)] bg-position-[0_-84%] bg-size-[100%_auto]"
                 onClick={onAddressModalOpenClick}
             >
-                <svg className="w-4 h-4 mr-1" 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">
+                <svg className="w-6 h-6 mr-2" 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">
                     <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>
                     <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>
                     <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>
                 </svg>
-                <span className="text-ly-12 text-ly-errorcolor">Fill in your shipping address for fast delivery</span>
+                <span className="text-ly-14 text-ly-errorcolor">Fill in your shipping address for fast delivery</span>
          
-                <svg className="absolute top-1/2 right-3.75 -translate-y-1/2 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>
+                <svg className="absolute top-1/2 right-4 -translate-y-1/2 w-6 h-6" 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>
             </div>
             :
-            <div className="w-full box-border px-3.75 bg-[url(/image/address-bg.webp)] bg-position-[0_-84%] bg-size-[100%_auto]"
+            <div className="w-full box-border px-4 bg-[url(/image/address-bg.webp)] bg-position-[0_-84%] bg-size-[100%_auto]"
                 onClick={onAddressModalOpenClick}
             >
-                <div className="border-b-1 flex h-11.25 items-center justify-between">
-                    <p className="text-ly-13 font-medium">
+                <div className="border-b-1 flex h-12.5 items-center justify-between">
+                    <p className="text-ly-14 font-medium">
                         {shippingAddress.firstName} {shippingAddress.lastName}
-                        <span className="border-r border-ly-gray h-3.5 mx-2"></span> 
+                        <span className="border-r border-ly-gray h-3.5 mx-4"></span> 
                         {shippingAddress.phone}
                     </p>
-                    <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>
+                    <svg className="w-6 h-6" 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>
                 </div>
-                <div className="flex items-center h-10">
-                    <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">
+                <div className="flex items-center h-14">
+                    <svg className="w-6 h-6 mr-3" 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">
                         <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>
                         <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>
                         <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>
                     </svg>
-                    <span className="text-ly-12 ml-2.5">
+                    <span className="text-ly-14 leading-ly-20">
                         {shippingAddress.address}, 
                         {shippingAddress.city}, 
                         {shippingAddress.state}, 

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 44 - 37
src/app/(checkout)/checkout/_components/CheckoutAddress/BillingAddressCheckout.tsx


+ 192 - 171
src/app/(checkout)/checkout/_components/CheckoutAddress/CheckoutAssress.tsx

@@ -1,15 +1,17 @@
 "use client";
 
 import {type Ref, useState, useEffect, useCallback, useImperativeHandle, useMemo } from "react";
+import clsx from "clsx";
 import { useRouter } from 'next/navigation';
-import { useForm, FormProvider } from "react-hook-form";
+import { useForm, FormProvider, useWatch } from "react-hook-form";
 import { useCustomToast } from "@/utils/hooks/useToast";
-import {useCheckoutAddress} from "@/utils/hooks/useCheckoutAddress"
+import {useCheckoutAddress, addressIsSame} from "@/utils/hooks/useCheckoutAddress"
 import {useLoginModal} from "@/providers/LoginModalProvider";
 import { useGetCustomerAddress } from "@utils/hooks/useGetCustomerAddress";
 import { EMAIL_REGEX } from "@utils/constants";
 import type { 
     ShipAddressFormData,
+    BillAddressFormData,
     FullAddressFormData,
     CreateCheckoutAddressVariables,
 } from "@/types/checkout/type";
@@ -20,11 +22,8 @@ import {clientFetch} from "@/lib/restApiClient";
 import { confirmDialog } from "@/components/theme/ui/kernel/confirm/api";
 import { overlayLoading } from "@/components/theme/ui/kernel/loading/api";
 import {normalizePhoneForForm} from "@/utils/phoneNumberTools";
-import AddressResultDisplay from "./AddressResultDisplay";
 import ShippingAddressCheckout from "./ShippingAddressCheckout";
 import BillingAddressCheckout from "./BillingAddressCheckout";
-import CommonModal from "@/components/theme/ui/CommonModal";
-
 
 
 export interface RefCheckoutAddressHandle {
@@ -41,50 +40,44 @@ export interface RefCheckoutAddressHandle {
 /**
  * 地址表单默认值
  */
-function getBillingAddressFormData(billingAddress:CartAddress) {
-    const billingCountry = billingAddress.country || 'US';
-    const billingPhoneNumber =  normalizePhoneForForm(billingAddress.phone, billingCountry) || "";
-    const res = {
-        "billingAddressId": billingAddress.id,
-        "billingEmail": billingAddress.email,
-        "billingFirstName": billingAddress.firstName,
-        "billingLastName": billingAddress.lastName,
+function getBillingAddressFormData(billingAddress:CartAddress|null) {
+    let res:Omit<BillAddressFormData,'billingSameAsShipping'> = {
+        "billingAddressId": "",
+        "billingEmail": '',
+        "billingFirstName": "",
+        "billingLastName": "",
         "billingCompanyName": "",
-        "billingAddress": billingAddress.address,
-        "billingCountry": billingCountry,
-        "billingState": billingAddress.state,
-        "billingCity": billingAddress.city,
-        "billingPostcode": billingAddress.postcode,
-        "billingPhoneNumber": billingPhoneNumber,
-    };
-
-    return res;
-}
-function getShippingAddressFormData(shippingAddress:CartAddress) {
-    const shippingCountry = shippingAddress.country || 'US';
-    const shippingPhoneNumber =  normalizePhoneForForm(shippingAddress.phone, shippingCountry) || "";
-    const res = {
-        "shippingAddressId": shippingAddress.id,
-        "shippingEmail": shippingAddress.email,
-        "shippingFirstName": shippingAddress.firstName,
-        "shippingLastName": shippingAddress.lastName,
-        "shippingCompanyName": "",
-        "shippingAddress": shippingAddress.address,
-        "shippingCountry": shippingCountry,
-        "shippingState": shippingAddress.state,
-        "shippingCity": shippingAddress.city,
-        "shippingPostcode": shippingAddress.postcode,
-        "shippingPhoneNumber": shippingPhoneNumber,
+        "billingAddress": "",
+        "billingCountry": "US",
+        "billingState": "",
+        "billingCity": "",
+        "billingPostcode": "",
+        "billingPhoneNumber": "",
     };
+    if(billingAddress) {
+        const billingCountry = billingAddress.country || 'US';
+        const billingPhoneNumber =  normalizePhoneForForm(billingAddress.phone, billingCountry) || "";
+        res = {
+            "billingAddressId": billingAddress.id,
+            "billingEmail": billingAddress.email,
+            "billingFirstName": billingAddress.firstName,
+            "billingLastName": billingAddress.lastName,
+            "billingCompanyName": "",
+            "billingAddress": billingAddress.address,
+            "billingCountry": billingCountry,
+            "billingState": billingAddress.state,
+            "billingCity": billingAddress.city,
+            "billingPostcode": billingAddress.postcode,
+            "billingPhoneNumber": billingPhoneNumber,
+        };
+    }
 
     return res;
 }
-function getAddressFormDataFromCart(cartDetail:CartDetail, loginEmail?: string) {
-    const shippingAddress = cartDetail.shippingAddress;
-    const billingAddress = cartDetail.billingAddress;
-    const defaultValues = {
+function getShippingAddressFormData(shippingAddress:CartAddress|null) {
+    let res: ShipAddressFormData = {
         "shippingAddressId": "",
-        "shippingEmail": loginEmail ?? '',
+        "shippingEmail": "",
         "shippingFirstName": "",
         "shippingLastName": "",
         "shippingCompanyName": "",
@@ -93,62 +86,45 @@ function getAddressFormDataFromCart(cartDetail:CartDetail, loginEmail?: string)
         "shippingState": "",
         "shippingCity": "",
         "shippingPostcode": "",
-        "shippingPhoneNumber": "",
-        "billingAddressId": "",
-        "billingEmail": loginEmail ?? '',
-        "billingFirstName": "",
-        "billingLastName": "",
-        "billingCompanyName": "",
-        "billingAddress": "",
-        "billingCountry": "US",
-        "billingState": "",
-        "billingCity": "",
-        "billingPostcode": "",
-        "billingPhoneNumber": "",
-        "billingSameAsShipping": true
+        "shippingPhoneNumber": ""
+    };
+    if(shippingAddress) {
+        const shippingCountry = shippingAddress.country || 'US';
+        const shippingPhoneNumber =  normalizePhoneForForm(shippingAddress.phone, shippingCountry) || "";
+        res = {
+            "shippingAddressId": shippingAddress.id,
+            "shippingEmail": shippingAddress.email,
+            "shippingFirstName": shippingAddress.firstName,
+            "shippingLastName": shippingAddress.lastName,
+            "shippingCompanyName": "",
+            "shippingAddress": shippingAddress.address,
+            "shippingCountry": shippingCountry,
+            "shippingState": shippingAddress.state,
+            "shippingCity": shippingAddress.city,
+            "shippingPostcode": shippingAddress.postcode,
+            "shippingPhoneNumber": shippingPhoneNumber,
+        };
     }
-    if(billingAddress) {
-        const bs = getBillingAddressFormData(billingAddress);
-        defaultValues.billingAddressId = bs.billingAddressId;
-        defaultValues.billingEmail = bs.billingEmail;
-        defaultValues.billingFirstName = bs.billingFirstName;
-        defaultValues.billingLastName = bs.billingLastName;
-        defaultValues.billingCompanyName = bs.billingCompanyName;
-        defaultValues.billingAddress = bs.billingAddress;
-        defaultValues.billingCountry = bs.billingCountry;
-        defaultValues.billingState = bs.billingState;
-        defaultValues.billingCity = bs.billingCity;
-        defaultValues.billingPostcode = bs.billingPostcode;
-        defaultValues.billingPhoneNumber = bs.billingPhoneNumber;
-        // defaultValues.billingSameAsShipping = true;
+
+    return res;
+}
+function getAddressFormDataFromCart(cartDetail:CartDetail, loginEmail?: string) {
+    const shippingAddress = cartDetail.shippingAddress;
+    const billingAddress = cartDetail.billingAddress;
+    const bs = getBillingAddressFormData(billingAddress);
+    const ss = getShippingAddressFormData(shippingAddress);
+    if(loginEmail && !bs.billingEmail) {
+        bs.billingEmail = loginEmail;
     }
-    if(shippingAddress) {
-        const ss = getShippingAddressFormData(shippingAddress);
-        defaultValues.shippingAddressId = ss.shippingAddressId;
-        defaultValues.shippingEmail = ss.shippingEmail;
-        defaultValues.shippingFirstName = ss.shippingFirstName;
-        defaultValues.shippingLastName = ss.shippingLastName;
-        defaultValues.shippingCompanyName = ss.shippingCompanyName;
-        defaultValues.shippingAddress = ss.shippingAddress;
-        defaultValues.shippingCountry = ss.shippingCountry;
-        defaultValues.shippingState = ss.shippingState;
-        defaultValues.shippingCity = ss.shippingCity;
-        defaultValues.shippingPostcode = ss.shippingPostcode;
-        defaultValues.shippingPhoneNumber = ss.shippingPhoneNumber;
+    if(loginEmail && !ss.shippingEmail) {
+        ss.shippingEmail = loginEmail;
     }
-    if( defaultValues.billingEmail === defaultValues.shippingEmail &&
-        defaultValues.billingFirstName === defaultValues.shippingFirstName &&
-        defaultValues.billingLastName === defaultValues.shippingLastName &&
-        defaultValues.billingCompanyName === defaultValues.shippingCompanyName &&
-        defaultValues.billingAddress === defaultValues.shippingAddress &&
-        defaultValues.billingCountry === defaultValues.shippingCountry &&
-        defaultValues.billingState === defaultValues.shippingState &&
-        defaultValues.billingCity === defaultValues.shippingCity &&
-        defaultValues.billingPostcode === defaultValues.shippingPostcode &&
-        defaultValues.billingPhoneNumber === defaultValues.shippingPhoneNumber
-    ) {
-        defaultValues.billingSameAsShipping = true;
+    const defaultValues: FullAddressFormData = {
+        ...ss,
+        ...bs,
+        "billingSameAsShipping": addressIsSame(bs,ss)
     }
+
     return defaultValues;
 }
 /**
@@ -240,7 +216,6 @@ export function CheckoutAddress({
     const [myAddressList, setMyAddressList] = useState<CustomerAddressItem[]>([]);
     const [showShipFormField, setShowShipFormField] = useState(false);
     const [showBillFormField, setShowBillFormField] = useState(false);
-    const [addressFormModalOpen, setAddressFormModalOpen] = useState(false);
 
 
     useImperativeHandle(ref, () => {
@@ -267,25 +242,6 @@ export function CheckoutAddress({
     },[]);
 
 
-    const openAddressFormModal = () => {
-        setAddressFormModalOpen(true);
-        setShowShipFormField(false);
-        setShowBillFormField(false);
-        if(cartData.billingAddress && cartData.shippingAddress) {
-            addressForm.reset({
-                ...getAddressFormDataFromCart(cartData)
-            });
-        }
-
-        
-    };
-    const closeAddressFormModal = () => {
-        setAddressFormModalOpen(false);
-        setShowShipFormField(false);
-        setShowBillFormField(false);
-        // 重置表单
-        addressForm.reset();
-    };
     const addressFormOnSubmit = async (formData: FullAddressFormData) => { 
         // console.log('addressFormOnSubmit ---- ',formData); return;
         const saveAddressParam = generateSaveCheckoutAddressParam(formData);
@@ -305,11 +261,38 @@ export function CheckoutAddress({
                     return;
                 }
 
-                addressForm.resetField('shippingAddressId',{
-                    defaultValue: createAddressData.shippingAddressId
-                });
-                addressForm.resetField('billingAddressId',{
-                    defaultValue: createAddressData.billingAddressId
+                const shipAddressAfterSave: ShipAddressFormData = {
+                    shippingAddressId: createAddressData.shippingAddressId,
+                    shippingEmail: createAddressData.shippingEmail,
+                    shippingFirstName: createAddressData.shippingFirstName,
+                    shippingLastName: createAddressData.shippingLastName,
+                    shippingCompanyName: createAddressData.shippingCompanyName || '',
+                    shippingAddress: createAddressData.shippingAddress,
+                    shippingCountry: createAddressData.shippingCountry,
+                    shippingState: createAddressData.shippingState,
+                    shippingCity: createAddressData.shippingCity,
+                    shippingPostcode: createAddressData.shippingPostcode,
+                    shippingPhoneNumber: createAddressData.shippingPhoneNumber,
+                };
+                const billAddressAfterSave: Omit<BillAddressFormData,'billingSameAsShipping'> = {
+                    billingAddressId: createAddressData.billingAddressId,
+                    billingFirstName: createAddressData.billingFirstName,
+                    billingLastName: createAddressData.billingLastName,
+                    billingEmail: createAddressData.billingEmail,
+                    billingCompanyName: createAddressData.billingCompanyName || '',
+                    billingAddress: createAddressData.billingAddress,
+                    billingCity: createAddressData.billingCity,
+                    billingState: createAddressData.billingState,
+                    billingCountry: createAddressData.billingCountry,
+                    billingPostcode: createAddressData.billingPostcode,
+                    billingPhoneNumber: createAddressData.billingPhoneNumber
+                };
+                // 重置表单,更新默认值
+                addressForm.reset({
+                    ...shipAddressAfterSave,
+                    ...billAddressAfterSave,
+                    billingSameAsShipping: addressIsSame(billAddressAfterSave,shipAddressAfterSave)
+
                 });
 
         
@@ -343,11 +326,13 @@ export function CheckoutAddress({
                     billingAddress: newBillingAddress,
                     shippingAddress: newShippingAddress
                 });
+
+                showShipFormFieldChange(false);
+                showBillFormFieldChange(false);
                
             } else {
                 showToast(saveRes.msg, 'danger');
             }
-            setAddressFormModalOpen(false);
         } catch(err) {
             // 错误处理
             console.error("save address error", err);
@@ -436,6 +421,38 @@ export function CheckoutAddress({
         
     };
 
+    const isBillSameAsShip = useWatch({
+        control: addressForm.control,
+        name: "billingSameAsShipping",
+    });
+    const showSaveBtn = () => {
+        let res = false;
+        if(
+            (noShipAddress || noBillAddress) ||
+            (!isBillSameAsShip && noBillAddress) ||
+            showShipFormField || showBillFormField
+        ) {
+            res = true;
+        }
+
+        return res;
+    };
+    const showCancelBtn = () => {
+        let res = false;
+        if(
+            showShipFormField || showBillFormField
+        ) {
+            res = true;
+        }
+
+        return res;
+    };
+    const cancelHandler = () => {
+        showShipFormFieldChange(false);
+        showBillFormFieldChange(false);
+        // 重置表单
+        addressForm.reset();
+    };
     // function tt() {
     //     const arr = [
     //         ['US','3803800217'], 
@@ -456,56 +473,60 @@ export function CheckoutAddress({
     //     });
     // }
     return (<>
-        <AddressResultDisplay shippingAddress={cartData.shippingAddress || null} 
-            onAddressModalOpenClick={openAddressFormModal}
-        />
-        <CommonModal
-            isOpen={addressFormModalOpen}
-            onClose={closeAddressFormModal}
-            header={
-                <div className="w-full box-border p-3.75 h-14.5 flex justify-between items-center">
-                    <span>Shipping Address</span>
-                    <button className="w-6 h-6" onClick={closeAddressFormModal}>
-                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" className="h-6 transition-all ease-in-out hover:scale-110"><path strokeLinecap="round" strokeLinejoin="round" d="M6 18 18 6M6 6l12 12"></path></svg>
-                    </button>
-                </div>
-            }
-            body={
-                <div className="box-border w-full h-full p-3.75">
-                    <div>
-                        <FormProvider {...addressForm}>
-                            <form>
-                                <ShippingAddressCheckout 
-                                    noAddress={noShipAddress}
-                                    isGuest={cartData.isGuest}
-                                    customerAddressList={myAddressList}
-                                    showFormField={showShipFormField}
-                                    onShowFormFieldChange={showShipFormFieldChange}
-                                    onEmailChange={verifyEmailIsRegistered}
-                                />
-                                <BillingAddressCheckout 
-                                    noAddress={noBillAddress}
-                                    isGuest={cartData.isGuest}
-                                    customerAddressList={myAddressList}
-                                    showFormField={showBillFormField}
-                                    onShowFormFieldChange={showBillFormFieldChange}
-                                />
-                            </form>
-                        </FormProvider>
-                    </div>
-                </div>
-            }
-            footer={
-                <div className="box-border w-full p-3.75">
-                <button className="block flex justify-center items-center w-full h-12 bg-ly-green rounded-3xl text-white text-ly-16 font-bold"
-                    onClick={addressForm.handleSubmit(addressFormOnSubmit)}
-                >
-                    Save
-                </button>
-                </div>
-            }
-        />
-            
 
+
+        <div >
+            <FormProvider {...addressForm}>
+                <form>
+                    <ShippingAddressCheckout 
+                        noAddress={noShipAddress}
+                        isGuest={cartData.isGuest}
+                        customerAddressList={myAddressList}
+                        showFormField={showShipFormField}
+                        onShowFormFieldChange={showShipFormFieldChange}
+                        onEmailChange={verifyEmailIsRegistered}
+                    />
+                    <BillingAddressCheckout 
+                        noAddress={noBillAddress}
+                        isGuest={cartData.isGuest}
+                        customerAddressList={myAddressList}
+                        showFormField={showBillFormField}
+                        onShowFormFieldChange={showBillFormFieldChange}
+                    />
+                </form>
+            </FormProvider>
+        </div>
+            
+        
+        {/**
+         * save 按钮
+         * noShipAddress || noBillAddress 显示
+         * billingSameAsShipping是false && noBillAddress 显示
+         * change shipping address 显示
+         * change billing address 显示
+         * 
+         * cancel 按钮
+         * change shipping address 显示
+         * change billing address 显示
+         */}
+        <div className="box-border w-full">
+            <button className={clsx("justify-center items-center w-full h-12 mt-4 bg-ly-green rounded-3xl text-white text-ly-16 font-bold",
+                showSaveBtn() ? 'flex' : 'hidden'
+            )}
+                type="button"
+                onClick={addressForm.handleSubmit(addressFormOnSubmit)}
+            >
+                Save
+            </button>
+
+            <button className={clsx("flex justify-center items-center w-full h-12 mt-3 border-1 rounded-3xl text-ly-16 font-bold",
+                showCancelBtn() ? 'flex' : 'hidden'
+            )}
+                type="button"
+                onClick={cancelHandler}
+            >
+                Cancel
+            </button>
+        </div>
     </>);
 };

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 75 - 68
src/app/(checkout)/checkout/_components/CheckoutAddress/ShippingAddressCheckout.tsx


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 17 - 13
src/app/(checkout)/checkout/_components/CheckoutCoupon/CheckoutCoupon.tsx


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 45 - 96
src/app/(checkout)/checkout/_components/CheckoutProducts/CheckoutProducts.tsx


+ 46 - 43
src/app/(checkout)/checkout/_components/CheckoutWrapper.tsx

@@ -323,9 +323,9 @@ export default function CheckoutWrapper({
             console.log('checkoutWrapper unmout==========================');
         }
     },[]);
-    return (<>
-        <section className="w-full">
-            <div>
+    return (<div className="w-full flex justify-between max-w-312 mx-auto items-start mt-6 mb-30 px-6">
+        <section className="flex-initial w-164">
+            <div className="pb-6 border-b-1">
                 <CheckoutAddress 
                     ref={checkoutAddressRef}
                     loginEmail={loginEmail}
@@ -337,16 +337,26 @@ export default function CheckoutWrapper({
                   
             </div>
 
-
-            <div className="mt-6 box-border px-4">
-                <CheckoutProducts 
-                    cartData={cartData}
-                    onCartChange={onCartDataChange}
+            <div className="mt-6 box-border pb-6 border-b-1">
+                <CheckoutCoupon 
+                    couponCode={cartData.couponCode || ''}
+                    discountAmount={cartData.formattedDiscountAmount}
+                    onCouponChange={onCartDataChange}
                 />
             </div>
 
-            <div className="mt-6 box-border px-4">
-                <h3 className="text-ly-24 font-medium" onClick={testEruda}>Shipping Method</h3>
+            {!cartData.isGuest &&
+                <div className="mt-6 box-border pb-6 border-b-1">
+                    <CheckoutGiftCardGate 
+                        giftcardNumber={cartData.giftcardNumber || ''}
+                        formattedGiftcardAmount={cartData.formattedGiftcardAmount} 
+                        onChangeGiftcard={onCartDataChange}
+                    />
+                </div>
+            }
+
+            <div className="mt-6 box-border">
+                <h3 className="text-ly-20 font-medium" onClick={testEruda}>Shipping Method</h3>
            
                 <ShippingMethodCheckout 
                     ref={methodShiippingRef}  
@@ -358,22 +368,16 @@ export default function CheckoutWrapper({
                 />
             </div>
             {cartData.shippingInsuranceEnabled &&
-                <div className="mt-3 box-border px-4">
+                <div className="mt-4 box-border pb-6 border-b-1">
                     <LostInsurance 
                         cartData={cartData}
                         onSwitchInsurance={onCartDataChange}
                     />
                 </div>
             }
-            <div className="mt-6 box-border px-4">
-                <CheckoutCoupon 
-                    couponCode={cartData.couponCode || ''}
-                    discountAmount={cartData.formattedDiscountAmount}
-                    onCouponChange={onCartDataChange}
-                />
-            </div>
+            
 
-            <div className="mt-6 box-border px-4">
+            <div className="mt-6 box-border pb-6 border-b-1">
                 <RewardPointsRedeemMoney 
                     isGuest={cartData.isGuest}
                     cartUsedPoints={cartData.rewardPointsUsed}
@@ -384,34 +388,19 @@ export default function CheckoutWrapper({
             </div>
             
             
-
-            {!cartData.isGuest &&
-                <div className="mt-6 box-border px-4">
-                    <CheckoutGiftCardGate 
-                        giftcardNumber={cartData.giftcardNumber || ''}
-                        formattedGiftcardAmount={cartData.formattedGiftcardAmount} 
-                        onChangeGiftcard={onCartDataChange}
-                    />
-                </div>
-            }
-            <div className="mt-6 box-border px-4">
+            <div className="mt-6 box-border pb-6 border-b-1">
                 <CheckoutVipPlus 
                     cartData={cartData} 
                     onSwitchVip={onCartDataChange}
                 />
             </div>
             
-            <div className="mt-6 box-border px-4">
-                <h3 className="text-ly-24 font-medium">Promotion Details</h3>
-                <div className="w-full box-border mt-3">
-                    <PromotionsDetails cartData={cartData} />
-                </div>
-            </div>
+           
 
-            <div className="mt-6 box-border px-4">
-                <h3 className="text-ly-24 font-medium">Payment Method</h3>
+            <div className="mt-6 box-border">
+                <h3 className="text-ly-20 font-medium">Payment Method</h3>
                 { paymentMethodLoading && <LoadingPaymentMethod /> }
-                { (!paymentMethodLoading && paymentMethodError) && <p className="mt-3 text-red-500 text-ly-12">{paymentMethodError}</p>}
+                { (!paymentMethodLoading && paymentMethodError) && <p className="mt-4 text-red-500 text-ly-12">{paymentMethodError}</p>}
                 {(!paymentMethodLoading && !paymentMethodError) &&
                 <PaymentMethodCheckout 
                     ref={methodPaymentRef}
@@ -424,8 +413,22 @@ export default function CheckoutWrapper({
                 
                 
             </div>
-            <div className="mt-3 box-border px-4 pb-8">
-                <p className="text-ly-12 text-[#666666] leading-ly-20">By providing your information, you agree to Wiggins'sPrivacy Policyand Terms of Use.</p>
+
+        </section>
+        <section className="flex-initial box-border w-120 border-1 p-4 ml-4">
+            <div className="box-border">
+                <CheckoutProducts 
+                    cartData={cartData}
+                    onCartChange={onCartDataChange}
+                />
+            </div>
+            <div className="mt-8 box-border">
+                <h3 className="text-ly-20 font-medium">Promotion Details</h3>
+                <div className="w-full box-border mt-4">
+                    <PromotionsDetails cartData={cartData} />
+                </div>
+            </div>
+            <div className="mt-4 box-border">
                 <div className="mt-6 w-full">
                     { paymentMethodLoading && <LoadingCheckoutPlaceOrder />}
                     
@@ -453,6 +456,6 @@ export default function CheckoutWrapper({
                 </div>
             </div>
 
-        </section>  
-    </>);
+        </section>
+    </div>);
 };

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 61 - 102
src/app/(checkout)/checkout/_components/ContinueToPay/ContinueToPayOrderInfo.tsx


+ 7 - 10
src/app/(checkout)/checkout/_components/ContinueToPay/PaymentMethodContinueTpPay.tsx

@@ -1,7 +1,6 @@
 "use client";
 
 import clsx from "clsx";
-import Image from "next/image";
 import { use,useState,useCallback } from "react";
 import { useForm, get, useWatch } from "react-hook-form";
 import { useRouter } from 'next/navigation'
@@ -436,24 +435,22 @@ export function PaymentMethodContinueTpPay({
 
     return (
         <>
-            <form name="shipping method" className="w-full box-border px-4 mt-4">
-                <div className="mt-3 w-full">
+            <form name="shipping method" className="w-full box-border">
+                <div className="mt-4 w-full">
                     {paymentMethodsData.error && <p className="text-red-500 text-ly-12">{paymentMethodsData.error.message}</p>}
                     <ul className="w-full">
                     {
                         paymentMethods.map((item) => {
-                            return (<li className="w-full mt-3" key={item.method}>
+                            return (<li className="w-full mt-4" key={item.method}>
                                 <label htmlFor={"paymentmethod-" + item.method} 
                                     className="group box-border flex items-center relative bg-ly-lightgray  p-3 rounded-sm has-checked:bg-white has-checked:border-1 has-checked:border-ly-green"
                                 >
                                     <p className="pr-2 flex-none relative">
-                                        <Image className="block h-8 w-auto"
+                                        <img className="block h-8 w-auto"
                                             src={getPaymentMethodLogo(item.method)} alt={"Payment Method " + item.title}
-                                            width={32}
-                                            height={32}
                                         />
                                     </p>
-                                    <p className="text-ly-12 text-[#666666] ml-1">{genetePaymentTips(item.method)}</p>
+                                    <p className="text-ly-14 text-[#666666] ml-1">{genetePaymentTips(item.method)}</p>
 
                                     <div className="absolute top-1/2 -translate-y-1/2 right-3 flex items-center">
                                         <svg className="check w-4 h-4 hidden group-has-[:checked]:block" 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="1" y="1" width="14" height="14" rx="1"    fill="#000000" ></rect><path    stroke="rgba(255, 255, 255, 1)" strokeWidth="1.5"  strokeLinecap="square"  d="M5.3335 8L7.3335 10L11.3335 6"></path></svg>
@@ -487,9 +484,9 @@ export function PaymentMethodContinueTpPay({
                 </div> 
             </form>
             
-            <div className="w-full box-border px-4 mt-3">
+            <div className="w-full box-border mt-4">
                 <p className="text-ly-12 text-[#666666] leading-4.75">
-                    By providing your information, you agree to Wiggins'sPrivacy Policyand Terms of Use.
+                    By providing your information, you agree to Asteria's Privacy Policyand Terms of Use.
                 </p>
 
                 <div className="mt-6 w-full">

+ 52 - 0
src/app/(checkout)/checkout/_components/ContinueToPay/ProductsInPendingOrder.tsx

@@ -0,0 +1,52 @@
+"use client";
+
+import Image from "next/image";
+import type {ProductsInOrderDetails} from "@/types/customer/type";
+import {getProductAdditionalInfo} from "@/utils/orderDetailTools";
+
+
+export default function ProductsInPendingOrder({
+    products,
+    currencySymbol,
+}: {
+    products: ProductsInOrderDetails[],
+    currencySymbol: string;
+}) {
+
+    return (
+        <div className="w-full">
+            {products.map((product) => {
+                const baseImage = JSON.parse(product.baseImage);
+                return (
+                    <div key={product.id} 
+                        className="flex justify-between w-full box-border pb-4 border-b-1 border-[#f0f0f0] mt-4 last:border-0 last:pb-0 last:mt-0"
+                    >
+                        <div className="relative flex-initial w-22 h-30 mr-2">
+                            <Image className="object-cover" fill
+                                src={baseImage.medium_image_url}
+                                alt={product.name} 
+                            />
+                        </div>
+                        <div className="flex-1 flex flex-col justify-between ">
+                            <div>
+                                <p className="text-ly-14 leading-ly-20 line-clamp-2 text-ly-placeholder">
+                                    {product.name}
+                                </p>
+                                <p className="text-ly-14 leading-ly-20 mt-3">
+                                    {getProductAdditionalInfo(JSON.parse(product.additional))}
+                                </p>
+                            </div>
+                            <div className="flex justify-between items-center">
+                                <span className="text-ly-14 font-bold">
+                                    {currencySymbol + product.price}
+                                </span>
+                                <span className="text-ly-14">X {product.qtyOrdered}</span>
+                            </div>
+                        </div>
+                    </div>
+                )
+            })}
+            
+        </div>
+    );
+}

+ 0 - 124
src/app/(checkout)/checkout/_components/ContinueToPay/ProductsModalPendingOrder.tsx

@@ -1,124 +0,0 @@
-"use client";
-
-import Image from "next/image";
-import CommonModal from "@/components/theme/ui/CommonModal";
-import type {ProductsInOrderDetails, ProductItemAdditional} from "@/types/customer/type";
-
-
-// 根据products 计算总价和总个数
-function caclculateTotal(products: ProductsInOrderDetails[]) {
-    let total = 0;
-    let totalItems = 0;
-
-    products.forEach((product) => {
-        total += product.total * 100;
-        totalItems += product.qtyOrdered;
-    });
-    let ss = String(total);
-    if(ss.length >= 3) {
-        ss = ss.slice(0, ss.length - 2) + "." + ss.slice(ss.length - 2);
-    } else if(ss.length === 2) {
-        ss = "0." + ss;
-    } else {
-        ss = "0.0" + ss;
-    }
-
-    return { 
-        subTotal: ss, 
-        totalItems: totalItems > 1 ? String(totalItems) + " Items" : String(totalItems) + " Item"
-    };
-}
-
-function getProductAdditionalInfo(productItem: ProductItemAdditional) { 
-    const attributeKeys = Object.keys(productItem.attributes);
-    let res = '';
-    attributeKeys.forEach(key => {
-      const attribute = productItem.attributes[key];
-      if (attribute) {
-        // option_label value_label
-
-        if(res) {
-            res = res + ', ' + attribute.option_label + ': ' + attribute.value_label;
-        } else {
-            res = attribute.option_label + ': ' + attribute.value_label;
-        }
-      }
-    });
-    return res;
-}
-
-export default function ProductsModalPendingOrder({
-    isOpen,
-    products,
-    currencySymbol,
-    onClose,
-}: {
-    isOpen: boolean;
-    products: ProductsInOrderDetails[],
-    currencySymbol: string;
-    onClose: () => void;
-}) {
-
-    const { subTotal, totalItems } = caclculateTotal(products);
-    
-
-    const closeModal = () => {
-        onClose();
-    };
-  return (
-    <CommonModal
-      isOpen={isOpen}
-      onClose={() => closeModal()}
-      header={
-        <div className="relative w-full box-border p-4">
-            <div className="flex justify-between items-center">
-                <span className="text-ly-16 flex-none">Order Summary</span>
-                <button className="flex-none w-6 h-6" onClick={() => closeModal()}>
-                    <svg className="block w-full h-full" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon"><path strokeLinecap="round" strokeLinejoin="round" d="M6 18 18 6M6 6l12 12"></path></svg>
-                </button>
-            </div>
-            
-            <div className="mt-6 flex justify-between items-center">
-                <span className="text-ly-12">{totalItems}</span>
-                <span className="text-ly-14 font-bold">{currencySymbol + subTotal}</span>
-            </div>
-        </div>
-      }
-      body={
-        <div className="w-full px-4 pb-6">
-            {products.map((product) => {
-                const baseImage = JSON.parse(product.baseImage);
-                return (
-                    <div key={product.id} className="flex justify-between w-full box-border pb-4 border-b-1 border-[#f0f0f0] mt-4 last:border-0 last:pb-0 last:mt-0">
-                        <div className="relative flex-none w-33 h-44 mr-2">
-                            <Image className="object-cover" fill
-                                src={baseImage.medium_image_url}
-                                alt={product.name} 
-                            />
-                        </div>
-                        <div className="flex-auto flex flex-col justify-between ">
-                            <div>
-                                <p className="text-ly-12 leading-ly-20 line-clamp-2 text-ly-placeholder">
-                                    {product.name}
-                                </p>
-                                <p className="text-ly-12 leading-ly-20 mt-3">
-                                    {getProductAdditionalInfo(JSON.parse(product.additional))}
-                                </p>
-                            </div>
-                            <div className="flex justify-between items-center">
-                                <span className="text-ly-14 font-bold">
-                                    {currencySymbol + product.price}
-                                </span>
-                                <span className="text-ly-12">X {product.qtyOrdered}</span>
-                            </div>
-                        </div>
-                    </div>
-                )
-            })}
-            
-        </div>
-      }
-      
-    />
-  )
-}

+ 2 - 1
src/app/(checkout)/checkout/_components/GiftCard/CheckoutGiftCardGate.tsx

@@ -54,6 +54,7 @@ export default function CheckoutGiftCardGate({
             currentPageRef.current = res.pagination.current_page;
         } else {
             showToast(res.message,"danger");
+            setHasMore(false);
         }
     },[showToast]);
 
@@ -107,7 +108,7 @@ export default function CheckoutGiftCardGate({
     return (
         <>
             <div className="relative box-border w-full flex justify-between items-center">
-                <span className="text-ly-24 font-medium">Gift Card</span>
+                <span className="text-ly-20 font-medium">Gift Card</span>
                
                 
                 <div className="flex items-center">

+ 5 - 5
src/app/(checkout)/checkout/_components/LostInsurance/LostInsurance.tsx

@@ -56,19 +56,19 @@ export default function LostInsurance({
         title = `Fixed $${cartData.shippingInsuranceValue} Package Insurance`;
     }
     return (<>
-        <div className="relative box-border w-full bg-[#F9F9F9] p-3">
+        <div className="relative box-border w-full bg-[#F9F9F9] p-4">
             <div className="flex justify-between items-center">
-                <span className="text-ly-13">
+                <span className="text-ly-14">
                     {title}
                 </span>
-                <span className="text-ly-12">
+                <span className="text-ly-14">
                     {cartData.formattedShippingInsuranceAmount}
                 </span>
             </div>
-            <div className="mt-2 w-57 text-ly-12 leading-3.5 text-ly-placeholder">
+            <div className="mt-2.5 text-ly-14 leading-4.5 text-ly-placeholder">
                 Increased compensation for courier packages issued within 30 days.
             </div>
-            <div className="absolute bottom-3 right-3 flex justify-between items-center">
+            <div className="absolute bottom-4 right-4 flex justify-between items-center">
                 <label className="group relative w-9 h-5.5 flex-none">
                     <input className="absolute w-full h-full top-0 left-0 opacity-0 z-10"
                         type="checkbox" checked={cartData.useShippingInsurance}

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 10 - 12
src/app/(checkout)/checkout/_components/PaymentMethodCheckout.tsx


+ 11 - 11
src/app/(checkout)/checkout/_components/PromotionsDetails.tsx

@@ -15,61 +15,61 @@ export default function PromotionsDetails({cartData}:{
     return (
         <div className="w-full box-border">
             <ul className="w-full">
-                <li className="flex justify-between items-center text-ly-12 mt-4 first:mt-0">
+                <li className="flex justify-between items-center text-ly-14 mt-4 first:mt-0">
                     <span>Subtotal</span>
                     <span>{cartData.formattedSubtotal}</span>
                 </li>
                 {cartData.shippingAmount !== 0 &&
-                    <li className="flex justify-between items-center text-ly-12 mt-4 first:mt-0">
+                    <li className="flex justify-between items-center text-ly-14 mt-4 first:mt-0">
                         <span>Shipping Method</span>
                         <span>{cartData.formattedShippingAmount}</span>
                     </li>
                 }
                 {cartData.earnableRewardPoints > 0 &&
-                    <li className="flex justify-between items-center text-ly-12 mt-4 first:mt-0">
+                    <li className="flex justify-between items-center text-ly-14 mt-4 first:mt-0">
                         <span>You Earn</span>
                         <span>{cartData.earnableRewardPoints} Reward Points</span>
                     </li>
                 }
                 {cartData.shippingInsuranceAmount !== 0 &&
-                    <li className="flex justify-between items-center text-ly-12 mt-4 first:mt-0">
+                    <li className="flex justify-between items-center text-ly-14 mt-4 first:mt-0">
                         <span>{title}</span>
                         <span>{cartData.formattedShippingInsuranceAmount}</span>
                     </li>
                 }
                 {cartData.vipPlusAmount !== 0 &&
-                    <li className="flex justify-between items-center text-ly-12 mt-4 first:mt-0">
+                    <li className="flex justify-between items-center text-ly-14 mt-4 first:mt-0">
                         <span>Vip Plus Fee</span>
                         <span>{cartData.formattedVipPlusAmount}</span>
                     </li>
                 }
                 {cartData.rewardPointsAmount !== 0 &&
-                    <li className="flex justify-between items-center text-ly-12 mt-4 first:mt-0">
+                    <li className="flex justify-between items-center text-ly-14 mt-4 first:mt-0">
                         <span>You Redeem ({cartData.rewardPointsUsed} Reward Points)</span>
                         <span className="flex items-center flex-none h-6 bg-ly-gold px-2 text-ly-14">-{cartData.formattedRewardPointsAmount}</span>
                     </li>
                 }
                 {cartData.discountAmount !== 0 &&
-                    <li className="flex justify-between items-center text-ly-12 mt-4 first:mt-0">
+                    <li className="flex justify-between items-center text-ly-14 mt-4 first:mt-0">
                         <span>Coupon</span>
                         <span className="flex items-center flex-none h-6 bg-ly-gold px-2 text-ly-14">-{cartData.formattedDiscountAmount}</span>
                     </li>
                 }
                 {cartData.vipDiscountAmount !== 0 &&
-                    <li className="flex justify-between items-center text-ly-12 mt-4 first:mt-0">
+                    <li className="flex justify-between items-center text-ly-14 mt-4 first:mt-0">
                         <span>Plus</span>
                         <span className="flex items-center flex-none h-6 bg-ly-gold px-2 text-ly-14">-{cartData.formattedVipDiscountAmount}</span>
                     </li>
                 }
                 {cartData.giftcardAmount !== 0 &&
-                    <li className="flex justify-between items-center text-ly-12 mt-4 first:mt-0">
+                    <li className="flex justify-between items-center text-ly-14 mt-4 first:mt-0">
                         <span>Gift Card</span>
                         <span className="flex items-center flex-none h-6 bg-ly-gold px-2 text-ly-14">-{cartData.formattedGiftcardAmount}</span>
                     </li>
                 }
-                <li className="flex justify-between items-center text-ly-12 mt-4 first:mt-0">
+                <li className="flex justify-between items-center text-ly-14 mt-4 first:mt-0 pt-6 border-t-1 border-[#f0f0f0]">
                     <span>Grand Total</span>
-                    <span>{cartData.formattedGrandTotal}</span>
+                    <span className="text-ly-24 font-bold">{cartData.formattedGrandTotal}</span>
                 </li>
             </ul>
         </div>

+ 10 - 10
src/app/(checkout)/checkout/_components/RewardPointsRedeemMoney/RewardPointsRedeemMoney.tsx

@@ -97,13 +97,13 @@ export default function RewardPointsRedeemMoney({
     return (
         <>
             {isGuest ?
-                <div className="text-ly-12 p-2.5 bg-ly-middlegray">
+                <div className="text-ly-14 p-2.5 bg-ly-middlegray">
                     Please <button className="underline" onClick={guestUserClick}>LOGIN</button> to use reward points
                 </div>
             :
             <div className="w-full">
                 <div className="relative box-border w-full flex justify-between items-center">
-                    <span className="text-ly-24 font-medium">Reward points redeem</span>
+                    <span className="text-ly-20 font-medium">Reward points redeem</span>
                 
                     
                     <div className="flex items-center">
@@ -113,26 +113,26 @@ export default function RewardPointsRedeemMoney({
                         </span>
                         }
                         
-                        <button className="w-6 h-6 flex-none">
+                        {/* <button className="w-6 h-6 flex-none">
                             <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>
-                        </button>
+                        </button> */}
                     </div>
                 </div>
                 
-                <div className="w-full mt-3">
-                    <div className="box-border w-full bg-ly-middlegray p-3 rounded-md">
+                <div className="w-full mt-4">
+                    <div className="box-border w-full bg-ly-middlegray p-4 rounded-md">
                         
-                        <p className="text-ly-12">
+                        <p className="text-ly-14">
                             You have <span className="font-bold">{hasRewardPoints} Reward Points</span>  available.  100 point = $1. Input points value below to redeem.
                         </p>
-                        <div className="flex justify-between items-center mt-3 box-border w-full border-1 h-12 rounded-sm pl-3 pr-2 bg-white">
-                            <input className="focus:outline-none"
+                        <div className="flex justify-between items-center mt-3 box-border w-full border-1 h-12 rounded-sm pl-4 pr-1 bg-white">
+                            <input className="focus:outline-none text-ly-14"
                                 type="text"
                                 value={usedPoints === '0' ? '' : usedPoints}
                                 placeholder="Reward Points"
                                 onChange={pointsInputChange}
                             />
-                            <button className="flex items-center text-ly-14 rounded-sm bg-ly-green text-white px-2 h-8"
+                            <button className="flex items-center text-ly-14 rounded-sm bg-ly-green text-white px-4 h-9"
                                 onClick={submitPointsUse}
                             >
                                 {cartUsedPoints > 0 ? 'Cancel' : 'Apply'}

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 6 - 6
src/app/(checkout)/checkout/_components/ShippingMethodCheckout.tsx


+ 9 - 9
src/app/(checkout)/checkout/_components/VipPlus/CheckoutVipPlus.tsx

@@ -157,7 +157,7 @@ export default function CheckoutVipPlus({
             </div>
         }
         {!cartData.isVip &&
-            <div className="relative box-border w-full ly-vipplus-bg p-3.75">
+            <div className="relative box-border w-full ly-vipplus-bg p-6">
                 
                 <div className="flex items-center text-ly-12 font-bold">
                     Asteriahair Plus
@@ -169,15 +169,15 @@ export default function CheckoutVipPlus({
                     <span>Pay {staticVipData.price} save</span>
                     <span className="ml-1 text-ly-middlegreen">extra {staticVipData.discount} off every order</span>
                 </div>
-                <div className="mt-2 text-ly-12">
+                <div className="mt-2 text-ly-14">
                     {staticVipData.days} days validity
                 </div>
                 <div className="flex items-center mt-3">
                     <span className="text-ly-16 font-bold">{staticVipData.price}</span>
-                    <span className="ml-2.5 text-ly-12 text-ly-deepgray line-through">{staticVipData.linePrice}</span>
+                    <span className="ml-2.5 text-ly-14 text-ly-deepgray line-through">{staticVipData.linePrice}</span>
                 </div>
                 
-                <div className="absolute bottom-3.75 right-3.75 flex justify-between items-center">
+                <div className="absolute bottom-6 right-6 flex justify-between items-center">
                     <label className="group relative w-9 h-5.5 flex-none">
                         <input className="absolute w-full h-full top-0 left-0 opacity-0 z-10"
                             type="checkbox" checked={vipChecked}
@@ -196,20 +196,20 @@ export default function CheckoutVipPlus({
             destroyOnClose={true}
             isOpen={isShow}
             onClose={toggleModal}
-            contentClassName={"left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 w-80 rounded-xl bg-white px-3"}
+            contentClassName={"left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 w-144.5 rounded-xl bg-white px-6"}
             body={
                 <div className="relative py-4">
                     <div className="text-center text-ly-16 font-bold">Asteriahair Plus</div>  
-                    <p className="text-center text-ly-12 leading-5 mt-3">
+                    <p className="text-center text-ly-14 leading-5 mt-5">
                         In order to provide customers with a better shopping experience, Asteriahair has specially launched Asteriahair PLUS membership (no refund after purchase). PLUS members can enjoy unlimited free shipping, 5% off on each order within 180 days, exclusive instant discounts, exclusive customer service, free returns and other membership privileges.
                     </p>
-                    <p className="text-center text-ly-12 leading-5 mt-2">
+                    <p className="text-center text-ly-14 leading-5 mt-3">
                         We hope to establish a long-term win-win relationship with you through PLUS. At the same time, we will continue to enrich the rights and interests of PLUS members and provide you with more complete services.
                     </p>
-                    <p className="text-center text-ly-12 leading-5 mt-2">
+                    <p className="text-center text-ly-14 leading-5 mt-3">
                         Thank you for choosing Asteriahair. We are dedicated to creating the ultimate shopping experience for you!(The final right of interpretation belongs to Asteriahair)
                     </p>
-                    <p className="text-center text-ly-12 leading-5 mt-2">
+                    <p className="text-center text-ly-14 leading-5 mt-3">
                         Note: PLUS membership can't be used for wholesale orders, clearance and flash sale products.
                     </p>
                     <button className="absolute top-4 right-4 w-6 h-6" onClick={() => toggleModal(false)}>

+ 9 - 9
src/app/(checkout)/checkout/cart/_components/PromiseInCart.tsx

@@ -6,17 +6,17 @@ export function PromiseInCart() {
 
 
     return (
-        <div className="flex items-center justify-between w-full box-border bg-[#EAE9E1] h-10 px-5">
-            <div className="flex-none w-17.5 text-center text-ly-12 leading-4">
-                30 Days <br/>Free Return
+        <div className="flex items-center justify-center w-full box-border bg-[#EAE9E1] h-10">
+            <div className="flex-none text-center text-ly-14 leading-4">
+                30 Days Free Return
             </div>
-            <div className="relative text-center text-ly-12 leading-4 px-8">
-                <span className=" absolute left-0 top-1/2 -translate-y-1/2 h-5 border-[#cccccc] border-l-1"></span>
-                24-48 Hrs <br/>Free Fast Shipping
-                <span className=" absolute right-0 top-1/2 -translate-y-1/2 h-5 border-[#cccccc] border-l-1"></span>
+            <span className="h-5 border-[#cccccc] border-l-1 mx-32.5"></span>
+            <div className="flex-none text-center text-ly-14 leading-4 ">
+                24-48 Hrs Free Fast Shipping
             </div>
-            <div className="flex-none w-17.5 text-center text-ly-12 leading-4">
-                Buy Now <br/>& Pay Later
+            <span className="h-5 border-[#cccccc] border-l-1 mx-32.5"></span>
+            <div className="flex-none text-center text-ly-14 leading-4">
+                Buy Now & Pay Later
             </div>
         </div>
     );

+ 1 - 3
src/app/(checkout)/checkout/cart/page.tsx

@@ -4,7 +4,6 @@ import { GET_CART_ITEM, GET_CUSTOMER_ORDERS } from "@/graphql";
 import { auth } from "@/utils/auth/auth-helper";
 import type { GetCartItemData } from "@/types/cart/type";
 import type { OrderListData, OrderListDataVariables, OrderDetails } from "@/types/customer/type";
-import TitleHeader from "@components/layout/navbar/TitleHeader";
 import { EmptyCart } from "./_components/EmptyCart";
 import { PromiseInCart } from "./_components/PromiseInCart";
 import { CartWrapper } from "./_components/CartWrapper";
@@ -55,10 +54,9 @@ export default async function CheckoutPage() {
     if(cartDetails) {
         cartDatahash = createHash('sha256').update(JSON.stringify(cartDetails)).digest('hex');
     }
-    const title = "My Cart" + (cartDetails?.itemsQty ? ' ('+cartDetails?.itemsQty+')' : '');
+
     return (
         <>
-            <TitleHeader title={title} />
             <PromiseInCart />
             {(unpaidOrder && !unpaidOrderExpiried) &&
 

+ 19 - 16
src/app/(checkout)/checkout/continuetopay/page.tsx

@@ -10,7 +10,7 @@ import type { OrderDetailsData } from "@/types/customer/type";
 import type { RepayOrderPaymentMethodsData } from "@/types/checkout/type";
 import {PaymentMethodContinueTpPay} from "../_components/ContinueToPay/PaymentMethodContinueTpPay";
 import LoadingPaymentMethod from "../_components/LoadingPaymentMethod";
-import TitleHeader from "@components/layout/navbar/TitleHeader";
+
 
 // 只能存在一个待支付订单
 export const dynamic = "force-dynamic";
@@ -64,9 +64,8 @@ export default async function ContinueToPay({searchParams}: {
     });
       
     return (<>
-        <TitleHeader title="Continue To Pay" />
         {orderDetailError ?
-            <div className="box-border px-4 w-full">
+            <div className="box-border max-w-312 mx-auto mb-30 mt-6 px-6">
             
                 
                 <div className="w-12 h-12 mx-auto mt-9">
@@ -77,27 +76,31 @@ export default async function ContinueToPay({searchParams}: {
                     <span className="text-ly-16">{orderDetailError.message}</span>
                 </p>
 
-                <Link href="/" className="mt-6 flex justify-center items-center h-12 border-1 rounded-3xl text-ly-14">
+                <Link href="/" className="mt-6 mx-auto flex justify-center items-center w-30 h-12 border-1 rounded-3xl text-ly-16">
                     Continue Shopping
                 </Link>
             </div>
         :
-            <div className="w-full pb-8">
+            <div className="flex justify-between items-start box-border max-w-312 mx-auto mb-30 mt-6 px-6">
+                <div className="flex-initial w-164 mr-4">
+                    <ContinueToPayOrderInfo orderDetail={orderDetailData} />
+                </div>
             
-                <ContinueToPayOrderInfo orderDetail={orderDetailData} />
+                
             
-                <div className="mt-6 box-border px-4">
-                    <h3 className="text-ly-24 font-medium">Payment Method</h3>
+                <div className="flex-initial w-120 box-border">
+                    <h3 className="text-ly-20 font-medium">Payment Method</h3>
+                    <Suspense fallback={<LoadingPaymentMethod/>}> 
+                        <PaymentMethodContinueTpPay 
+                            orderId={orderDetailData._id}
+                            orderDetail={orderDetailData}
+                            paymentMethodsDataPromise={paymentMethodsResponse}
+                            defaultPaymentMethod={orderDetailData.payment}
+                        />
+                    </Suspense>
 
                 </div>
-                <Suspense fallback={<LoadingPaymentMethod/>}> 
-                    <PaymentMethodContinueTpPay 
-                        orderId={orderDetailData._id}
-                        orderDetail={orderDetailData}
-                        paymentMethodsDataPromise={paymentMethodsResponse}
-                        defaultPaymentMethod={orderDetailData.payment}
-                    />
-                </Suspense>
+                
                 
             </div>
         }

+ 1 - 2
src/app/(checkout)/checkout/page.tsx

@@ -5,7 +5,7 @@ import CheckoutWrapper from "./_components/CheckoutWrapper";
 import { GET_CART_ITEM } from "@/graphql";
 import { auth } from "@/utils/auth/auth-helper";
 import type { GetCartItemData } from "@/types/cart/type";
-import TitleHeader from "@components/layout/navbar/TitleHeader";
+
 
 /**
  * 进入结账页 
@@ -34,7 +34,6 @@ export default async function CheckoutPage() {
     const cartDatahash = createHash('sha256').update(JSON.stringify(cartDetails)).digest('hex');
     return (
         <>
-            <TitleHeader title="Checkout" />
             <CheckoutWrapper key={cartDatahash}
                 cartDetailData={cartDetails}
                 loginEmail={session?.user?.email || ""}

+ 14 - 10
src/app/(checkout)/layout.tsx

@@ -1,16 +1,20 @@
 
 import { type ReactNode } from "react";
+import Footer from "@/components/layout/footer";
+import Navbar from "@/components/layout/navbar";
+
 export default async function CheckoutLayout({
-  children,
+    children,
 }: {
-  children: ReactNode;
+    children: ReactNode;
 }) {
-  return (
-    <>
-
-      <div className="mx-auto w-full">
-        {children}
-      </div>
-    </>
-  );
+    return (
+        <>
+            <Navbar />
+            <div className="mx-auto w-full">
+                {children}
+            </div>
+            <Footer />
+        </>
+    );
 }

+ 4 - 8
src/app/(public)/customer/account/_components/AccountVipPopup.tsx

@@ -3,7 +3,7 @@
 // 轮播逻辑
 import { Swiper, SwiperSlide } from "swiper/react";
 import { Navigation, Scrollbar } from "swiper/modules";
-import { Swiper as SwiperType } from "swiper/types";
+import type { Swiper as SwiperType } from "swiper/types";
 import { useEffect, useState } from "react";
 import Image from "next/image";
 import "swiper/css";
@@ -121,17 +121,16 @@ export default function AccountVipPopup({
   visible: boolean;
   onClose: () => void;
 }) {
-  // swiper实例
-  const [_swiperRef, setSwiperRef] = useState<SwiperType | null>(null);
+
   // 当前slide下标
   const [activeIndex, setActiveIndex] = useState(0);
-  const [_loading, setLoading] = useState(true);
+
   const [VipGrothData, setVipGrothData] = useState<any>(null);
   // 如果不显示,直接 return null
   useEffect(() => {
     const fetchGrothValue = async () => {
       try {
-        setLoading(true);
+  
         const res = await clientFetch("/api/customer/growth-value");
         if (res.success) {
           setVipGrothData(res.data);
@@ -139,8 +138,6 @@ export default function AccountVipPopup({
         }
       } catch (error) {
         console.error("获取vip成长值失败:", error);
-      } finally {
-        setLoading(false);
       }
     };
     fetchGrothValue();
@@ -261,7 +258,6 @@ export default function AccountVipPopup({
                         nextEl: ".btn-next", // 右箭头class
                         disabledClass: "opacity-20", // 滑到首尾自动加这个类,Tailwind直接用
                       }}
-                      onSwiper={(swiper) => setSwiperRef(swiper)}
                       onSlideChange={handleSlideChange}
                       spaceBetween={0}
                       className="swiper-container-horizontal"

+ 228 - 53
src/app/(public)/paymentresult/_components/CancelOrFailure.tsx

@@ -1,13 +1,18 @@
 "use client";
 
 import {use, useEffect, useRef} from "react";
+import { redirect, RedirectType } from 'next/navigation';
+import Image from "next/image";
 import Link from "next/link";
 import type {FetchGraphqlResult} from "@/types/graphqlFetch/type";
 import type { OrderDetailsData } from "@/types/customer/type";
 import { usePlaceOrder } from "@/utils/hooks/usePlaceOrder";
-import Faqs from "./Faqs";
+import { useConfig } from "@utils/hooks/useConfig";
+import {getAddressFromOrderDetailAddressList,getProductAdditionalInfo} from "@/utils/orderDetailTools";
 import { useAppDispatch } from "@/store/hooks";
 import { fetchCartDetail } from "@/store/slices/cart-slice";
+import Faqs from "./Faqs";
+
 export default function CancelOrFailure({
     orderDetailPromise,
     paymentStatus,
@@ -18,14 +23,28 @@ export default function CancelOrFailure({
     isGuest: boolean
 }) { 
     const dispatch = useAppDispatch();
+    const {currencies} = useConfig();
     const promiseRes = use(orderDetailPromise);
     const orderDetailRes = promiseRes.data?.customerOrder ?? null;
+    if(!orderDetailRes) {
+        redirect('/', RedirectType.replace);
+    }
     const {cancelOrder} = usePlaceOrder();
     const orderId = orderDetailRes?._id;
     const orderStatus = orderDetailRes?.status;
     const cancelOrderRef = useRef(false);
+    const shippingAddress = getAddressFromOrderDetailAddressList(orderDetailRes.addresses,"order_shipping");
+    const currency = currencies.find(item => item.code === orderDetailRes.orderCurrencyCode) || null;
+    let orderCreatedAt = 'Can\'t get order date';
+    if(orderDetailRes?.createdAt) {
+        const localDate = new Date(orderDetailRes.createdAt);
+        orderCreatedAt = localDate.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
+    }
+    const productItems = orderDetailRes?.items?.edges.map(item => {
+        return item.node;
+    }) || [];
+
     useEffect(() => {
-        console.log('isGuest ---- ',isGuest);
         if(isGuest && !cancelOrderRef.current) {
             
             // 如果是游客,取消订单
@@ -42,60 +61,216 @@ export default function CancelOrFailure({
             cancelOrderRef.current = true;
         }
     }, [orderId,orderStatus]);
-    return (
-        <div className="box-border px-4 w-full">
-            {paymentStatus === 'failure' &&
-                <>
-                    <div className="w-12 h-12 mx-auto mt-9">
-                        <svg className="failure block w-full h-full" width="200" height="200" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="27635"><path d="M736 332.8L556.8 512l179.2 179.2-44.8 44.8L512 556.8l-179.2 179.2-44.8-44.8L467.2 512 288 332.8l44.8-44.8L512 467.2l179.2-179.2 44.8 44.8z" p-id="27636"></path><path d="M512 0a512 512 0 1 1 0 1024A512 512 0 0 1 512 0z m0 64a448 448 0 1 0 0 896A448 448 0 0 0 512 64z" p-id="27637"></path></svg>
-                    </div>
-                    <p className="text-ly-16 text-center mt-6">
-                        {isGuest ?
-                            "payment Failed! Your order has been cancelled."
-                        :
-                            "Payment Failed! You can try again."
-                        }
-                        
-                    </p>
-                </>
-            }
-            {paymentStatus === 'cancel' &&
-                <>
-                    <div className="w-12 h-12 mx-auto mt-9">
-                        <svg className="warning block w-full h-full" width="200" height="200" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="24135"><path d="M874.6496 512a362.6496 362.6496 0 1 0-725.3504 0 362.6496 362.6496 0 0 0 725.3504 0z m64 0a426.6496 426.6496 0 1 1-853.3504 0 426.6496 426.6496 0 0 1 853.3504 0z m-458.7008 85.3504V298.7008h64v298.6496h-64z m0 128v-64h64v64h-64z" p-id="24136"></path></svg>
-                    </div>
-                    <p className="text-ly-16 text-center mt-6">
-                        {isGuest ?
-                            "payment cancelled! Your order has been cancelled."
-                        :
-                            "Payment cancelled! You can continue to pay."
-                        }
-                        
-                    </p>
-                </>
-            }
 
-            <p className="text-ly-16 mt-4 flex justify-center">
-                <span className="px-3.75 leading-ly-28 bg-[#f0fffa]">Order #{orderId}</span>
-            </p>
-            {/* <p className="text-ly-12 text-center mt-4 leading-ly-22">
-                Hello, {orderDetailRes?.customerFirstName} <br/>
-                Thank you so much for your order !<br/>
-                We’ll get started on your order very soon!<br/>
-                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.
-            </p> */}
-            {isGuest ?
-                <Link href="/" className="mt-6 flex justify-center items-center h-12 border-1 rounded-3xl text-ly-14">
-                    Continue Shopping
-                </Link>
-            :
-                <Link href={`/checkout/continuetopay?orderid=${orderId}`} className="mt-6 flex justify-center items-center h-12 border-1 rounded-3xl text-ly-14">
-                    Continue To Pay
-                </Link>
-            }
+
+
+    return (<div className="flex items-start justify-between max-w-312 mx-auto px-6">
+        <div className="flex-initial w-164 mr-4">
+            <div className="box-border w-full">
+                {paymentStatus === 'failure' &&
+                    <>
+                        <div className="w-12 h-12 mx-auto">
+                            <svg className="failure block w-full h-full" width="200" height="200" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="27635"><path d="M736 332.8L556.8 512l179.2 179.2-44.8 44.8L512 556.8l-179.2 179.2-44.8-44.8L467.2 512 288 332.8l44.8-44.8L512 467.2l179.2-179.2 44.8 44.8z" p-id="27636"></path><path d="M512 0a512 512 0 1 1 0 1024A512 512 0 0 1 512 0z m0 64a448 448 0 1 0 0 896A448 448 0 0 0 512 64z" p-id="27637"></path></svg>
+                        </div>
+                        <p className="text-ly-16 text-center mt-4">
+                            {isGuest ?
+                                "payment Failed! Your order has been cancelled."
+                            :
+                                "Payment Failed! You can try again."
+                            }
+                            
+                        </p>
+                    </>
+                }
+                {paymentStatus === 'cancel' &&
+                    <>
+                        <div className="w-12 h-12 mx-auto">
+                            <svg className="warning block w-full h-full" width="200" height="200" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="24135"><path d="M874.6496 512a362.6496 362.6496 0 1 0-725.3504 0 362.6496 362.6496 0 0 0 725.3504 0z m64 0a426.6496 426.6496 0 1 1-853.3504 0 426.6496 426.6496 0 0 1 853.3504 0z m-458.7008 85.3504V298.7008h64v298.6496h-64z m0 128v-64h64v64h-64z" p-id="24136"></path></svg>
+                        </div>
+                        <p className="text-ly-16 text-center mt-4">
+                            {isGuest ?
+                                "payment cancelled! Your order has been cancelled."
+                            :
+                                orderStatus !=='canceled' ? "Payment cancelled! You can continue to pay." : "Order has been cancelled!"
+                            }
+                            
+                        </p>
+                    </>
+                }
+                <p className="text-ly-16 mt-4 flex justify-center">
+                    <span className="px-3.75 leading-ly-28 bg-[#f0fffa]">Order #{orderId}</span>
+                </p>
+                {isGuest || orderStatus ==='canceled' ?
+                    <Link href="/" className="mt-6 flex justify-center items-center h-12 border-1 rounded-3xl text-ly-16">
+                        Continue Shopping
+                    </Link>
+                :
+                    <Link href={`/checkout/continuetopay?orderid=${orderId}`} className="mt-6 flex justify-center items-center h-12 border-1 rounded-3xl text-ly-16">
+                        Continue To Pay
+                    </Link>
+                }
+            </div>
             <div className="box-border w-full mt-6">
                 <Faqs />
             </div>
+            <div className="box-border w-full mt-6">
+                <h4 className="text-ly-20 font-medium">Order Information</h4>
+                <div className="mt-6 flex justify-between gap-6">
+                    <div className="text-ly-14 flex-none w-35.5">Ship to:</div>
+                    <div className="text-ly-14 leading-ly-20 text-[#666666] flex-1">
+                        {
+                            shippingAddress.firstName 
+                            + ' ' + shippingAddress.lastName 
+                            + ' ' + shippingAddress.phone
+                            + ' ' + shippingAddress.address
+                            + ' ' + shippingAddress.city
+                            + ' ' + shippingAddress.state 
+                            + ' ' + shippingAddress.postcode
+                            + ' ' + shippingAddress.country
+                        }
+                    </div>
+                </div>
+                <div className="mt-4 flex justify-between gap-6">
+                    <div className="text-ly-14 flex-none w-35.5">Order number:</div>
+                    <div className="text-ly-14 leading-ly-20 text-[#666666] flex-1">
+                        {orderDetailRes?._id}
+                    </div>
+                </div>
+                <div className="mt-4 flex justify-between gap-6">
+                    <div className="text-ly-14 flex-none w-35.5">Status:</div>
+                    <div className="text-ly-14 leading-ly-20 text-[#666666] flex-1 capitalize">
+                        {orderDetailRes?.status}
+                    </div>
+                </div>
+                <div className="mt-4 flex justify-between gap-6">
+                    <div className="text-ly-14 flex-none w-35.5">Order date:</div>
+                    <div className="text-ly-14 leading-ly-20 text-[#666666] flex-1">
+                        {orderCreatedAt}
+                    </div>
+                </div>
+                <div className="mt-4 flex justify-between gap-6">
+                    <div className="text-ly-14 flex-none w-35.5">Shipping method:</div>
+                    <div className="text-ly-14 leading-ly-20 text-[#666666] flex-1">
+                        {orderDetailRes?.shippingTitle}
+                    </div>
+                </div>
+                <div className="mt-4 flex justify-between gap-6">
+                    <div className="text-ly-14 flex-none w-35.5">Payment method:</div>
+                    <div className="text-ly-14 leading-ly-20 text-[#666666] flex-1">
+                        {orderDetailRes?.payment?.methodTitle}
+                    </div>
+                </div>
+
+            </div>
+        </div>
+
+        <div className="flex-initial box-border w-120 border-1 p-4">
+            <h3 className="text-ly-20">My Bag({orderDetailRes.totalQtyOrdered})</h3>
+            <div className="box-border w-full max-h-130 overflow-y-auto scrollbar-thin scrollbar-thumb-gray-200">
+                {productItems.map((product) => {
+                    const baseImage = JSON.parse(product.baseImage);
+                    return (
+                        <div key={product.id} className="w-full flex gap-2 mt-4 pt-4 border-t-1 border-[#f0f0f0]">
+                            <div className="relative w-33 h-44 flex-initial">
+                                <Image className="object-cover" fill
+                                    src={baseImage.medium_image_url}
+                                    alt={product.name} 
+                                />
+                            </div>
+                            <div className="flex-1 flex flex-col justify-between">
+                                <div>
+                                    <p className="text-ly-14 leading-ly-20 line-clamp-2">
+                                        {product.name}
+                                    </p>
+                                    {
+                                        product.additional && 
+                                        <p className="mt-2 text-ly-14 leading-ly-20 text-ly-placeholder">
+                                            {getProductAdditionalInfo(JSON.parse(product.additional))}
+                                        </p>
+                                    }
+                                    
+                                </div>
+                                <div className="flex justify-between">
+                                    <p className="text-ly-14 leading-ly-20 font-bold">
+                                        {currency && currency.symbol}{product.price}
+                                    </p>
+                                    <p className="text-ly-14 leading-ly-20">x {product.qtyOrdered}</p>
+                                </div>
+                            </div>
+                        </div>
+                    );
+                })}
+                
+            </div>
+
+            <div className="box-border w-full mt-8">
+                <div className="flex justify-between items-center mt-4 first:mt-0">
+                    <p className="text-ly-14">Subtotal</p>
+                    <p className="text-ly-14">{currency && currency.symbol}{orderDetailRes?.subTotal}</p>
+                </div>
+                {orderDetailRes?.rewardPointsEarned > 0 &&
+                    <div className="flex justify-between items-center mt-4 first:mt-0">
+                        <p className="text-ly-14">You Earn</p>
+                        <p className="text-ly-14">{orderDetailRes?.rewardPointsEarned} Reward Points</p>
+                    </div>
+                }
+                {!!orderDetailRes?.shippingAmount &&
+                    <div className="flex justify-between items-center mt-4 first:mt-0">
+                        <p className="text-ly-14">Shipping</p>
+                        <p className="text-ly-14">{currency && currency.symbol}{orderDetailRes?.shippingAmount}</p>
+                    </div>
+                }
+                {Number(orderDetailRes?.shippingInsuranceAmount) > 0 &&
+                    <div className="flex justify-between items-center mt-4 first:mt-0">
+                        <p className="text-ly-14">Insurance of Lost</p>
+                        <p className="text-ly-14">{currency && currency.symbol}{Number(orderDetailRes?.shippingInsuranceAmount)}</p>
+                    </div>
+                }
+                {!!orderDetailRes?.taxAmount &&
+                    <div className="flex justify-between items-center mt-4 first:mt-0">
+                        <p className="text-ly-14">Tax</p>
+                        <p className="text-ly-14">{currency && currency.symbol}{orderDetailRes?.taxAmount}</p>
+                    </div>
+                }
+                {(orderDetailRes?.vipPlusAmount !== '0.00' && orderDetailRes?.vipPlusAmount !== null) &&
+                    <div className="flex justify-between items-center mt-4 first:mt-0">
+                        <p className="text-ly-14">Plus Fee</p>
+                        <p className="text-ly-14">{currency && currency.symbol}{orderDetailRes?.vipPlusAmount}</p>
+                    </div>
+                }
+                {orderDetailRes?.rewardPointsAmount > 0 &&
+                    <div className="flex justify-between items-center mt-4 first:mt-0">
+                        <p className="text-ly-14">You Redeem ({orderDetailRes.rewardPointsUsed} Reward Points)</p>
+                        <p className="flex items-center h-6 px-2 bg-ly-gold text-ly-14">-{currency && currency.symbol}{orderDetailRes?.rewardPointsAmount}</p>
+                    </div>
+                }
+                {!!orderDetailRes?.discountAmount &&
+                    <div className="flex justify-between items-center mt-4 first:mt-0">
+                        <p className="text-ly-14">Discount</p>
+                        <p className="flex items-center h-6 px-2 bg-ly-gold text-ly-14">-{currency && currency.symbol}{orderDetailRes?.discountAmount}</p>
+                    </div>
+                }
+                {(orderDetailRes?.giftcardAmount !== '0.00' && orderDetailRes?.giftcardAmount !== null) &&
+                    <div className="flex justify-between items-center mt-4 first:mt-0">
+                        <p className="text-ly-14">Gift Card</p>
+                        <p className="flex items-center h-6 px-2 bg-ly-gold text-ly-14">-{currency && currency.symbol}{orderDetailRes?.giftcardAmount}</p>
+                    </div>
+                }
+                {(orderDetailRes?.vipDiscountAmount !== '0.00' && orderDetailRes?.vipDiscountAmount !== null) &&
+                    <div className="flex justify-between items-center mt-4 first:mt-0">
+                        <p className="text-ly-14">Plus Save</p>
+                        <p className="flex items-center h-6 px-2 bg-ly-gold text-ly-14">-{currency && currency.symbol}{orderDetailRes?.vipDiscountAmount}</p>
+                    </div>
+                }
+                {/* <div className="flex justify-between mt-3 first:mt-0">
+                    <p className="text-ly-12 leading-ly-20">You Earn</p>
+                    <p className="text-ly-12 leading-ly-20">600 Reward Points</p>
+                </div> */}
+                <div className="flex justify-between mt-4 first:mt-0 pt-6 border-t-1 border-[#f0f0f0]">
+                    <p className="text-ly-14">Total</p>
+                    <p className="text-ly-24 font-bold">{currency && currency.symbol}{orderDetailRes?.grandTotal}</p>
+                </div>
+            </div>
         </div>
-    );
+    </div>);
 }

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 10 - 6
src/app/(public)/paymentresult/_components/Faqs.tsx


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 76 - 92
src/app/(public)/paymentresult/_components/OrderDetailWrapper.tsx


+ 1 - 1
src/app/(public)/paymentresult/result/page.tsx

@@ -44,7 +44,7 @@ export default async function SuccessPage({searchParams}: {
 
     return (
         
-        <div className="w-full">
+        <div className="w-full mt-6 mb-30">
             {paymentResult === 'success' && 
                 <Suspense fallback={<SuccessPageSkeleton />}>
                     <OrderDetailWrapper orderDetailPromise={orderDetailPromise} 

+ 2 - 22
src/app/globals.css

@@ -9,27 +9,6 @@ body {
   scrollbar-color: #6b7280 transparent;
 }
 
-html::-webkit-scrollbar,
-body::-webkit-scrollbar {
-  width: 6px;
-  height: 6px;
-}
-
-html::-webkit-scrollbar-track,
-body::-webkit-scrollbar-track {
-  background: transparent;
-}
-
-html::-webkit-scrollbar-thumb,
-body::-webkit-scrollbar-thumb {
-  background-color: #6b7280;
-  border-radius: 9999px;
-}
-
-.dark html::-webkit-scrollbar-thumb,
-.dark body::-webkit-scrollbar-thumb {
-  background-color: #d4d4d4;
-}
 
 /**
  * 移动端适配核心:clamp() 根字号  在390px设计稿下 16px ≈ 4.1025641vw = 1rem
@@ -137,6 +116,7 @@ html {
 body {
   background: var(--background);
   color: var(--foreground);
+  min-width: 768px;
 }
 
 @layer components {
@@ -213,7 +193,7 @@ body {
   }
   /*输入框样式*/
   .ly-input{
-    @apply block w-full box-border text-ly-12 px-4 leading-4 border-1 border-ly-inputborder h-11.5 placeholder:text-ly-placeholder focus:outline-none
+    @apply block w-full box-border text-ly-16 px-4 leading-4 border-1 border-ly-inputborder h-14 placeholder:text-ly-placeholder focus:outline-none
   }
 
   .fade-in{

+ 6 - 1
src/app/layout.tsx

@@ -54,7 +54,12 @@ export const outfit = localFont({
 });
 
 export async function generateMetadata() {
-  return generateMetadataForPage("", staticSeo.default);
+  return {
+    icons: {
+      icon: "/favicon.svg",
+    },
+    ...generateMetadataForPage("", staticSeo.default)
+  };
 }
 
 export default async function RootLayout({

+ 11 - 0
src/components/common/SocialShare/SocialShare.tsx

@@ -0,0 +1,11 @@
+"use client";
+
+export function SocialShare() {
+
+    return <>
+    
+    
+    </>;
+}
+
+

+ 0 - 14
src/components/customer/OpenAuth.tsx

@@ -1,14 +0,0 @@
-import { UserIcon } from "@heroicons/react/24/outline";
-import clsx from "clsx";
-
-export default function OpenAuth({ className }: { className?: string }) {
-  return (
-    <>
-      <div className="relative flex items-center justify-center rounded-md border-0 lg:border border-solid border-neutral-200 dark:border-neutral-700 lg:h-11 lg:w-11">
-        <UserIcon className={clsx("h-5 w-5  ", className)} />
-      </div>
-    </>
-
-  );
-}
-

+ 39 - 1
src/components/customer/SettingModal.tsx

@@ -1,6 +1,13 @@
 "use client";
 import Link from "next/link";
 import { useState } from "react";
+import { useRouter } from "next/navigation";
+import { signOut } from "next-auth/react";
+import { logoutAction } from "@/actions";
+import { useCustomToast } from '@/utils/hooks/useToast';
+import { useAppDispatch } from "@/store/hooks";
+import { clearCart } from "@/store/slices/cart-slice";
+import { overlayLoading } from "@/components/theme/ui/kernel/loading/api";
 import HelpModal from "../../app/(public)/customer/account/_components/HelpModal";
 export default function SettingModal({
   visible,
@@ -9,7 +16,38 @@ export default function SettingModal({
   visible: boolean;
   onClose: () => void;
 }) {
+  const router = useRouter();
+  const dispatch = useAppDispatch();
+  const { showToast } = useCustomToast();
   const [showSetting, setShowSetting] = useState(false);
+  const logOutHandler = async () => {
+    try {
+      overlayLoading.start();
+      const res = await logoutAction();
+
+      if (!res.success) {
+        showToast(res.message, "danger");
+        return;
+      }
+
+      await signOut({
+        callbackUrl: "/customer/login",
+        redirect: false,
+      });
+
+      dispatch(clearCart());
+      showToast("You are logged out successfully!", "success");
+      overlayLoading.stop();
+      setTimeout(() => {
+        router.push("/customer/login");
+        router.refresh();
+      }, 100);
+    } catch (err: unknown) {
+      overlayLoading.stop();
+      const message = err instanceof Error ? err.message : "Logout failed";
+      showToast(message, "danger");
+    }
+  };
   // 如果不显示,直接 return null
   if (!visible) return null;
   
@@ -132,7 +170,7 @@ export default function SettingModal({
 
               {/* Log Out */}
               <div className="py-4  absolute left-1/2 -translate-x-1/2 bottom-7 ">
-                <button className="text-black font-medium  w-full underline text-center">
+                <button onClick={logOutHandler} className="text-black font-medium  w-full underline text-center" type="button">
                   Log Out
                 </button>
               </div>

+ 0 - 265
src/components/customer/credentials/CredentialModal.tsx

@@ -1,265 +0,0 @@
-"use client";
-
-import { useDisclosure } from "@heroui/use-disclosure";
-import { AnimatePresence, motion } from "framer-motion";
-import clsx from "clsx";
-import { useSession, signOut } from "next-auth/react";
-import Link from "next/link";
-import { Avatar } from "@heroui/avatar";
-import { useForm } from "react-hook-form";
-import { usePathname, useRouter } from "next/navigation";
-import { useCustomToast } from '@/utils/hooks/useToast';
-import { useBodyScrollLock } from "@utils/hooks/useBodyScrollLock";
-import OpenAuth from "../OpenAuth";
-import { isObject } from '@/utils/type-guards';
-import LoadingDots from "@components/common/icons/LoadingDots";
-import { logoutAction } from "@/actions";
-import { useAppDispatch } from "@/store/hooks";
-import { clearCart } from "@/store/slices/cart-slice";
-
-
-export default function CredentialModal({
-  children,
-  className,
-  onOpen,
-  onClose,
-  isOpen,
-}: {
-  children?: React.ReactNode;
-  className?: string;
-  onOpen?: () => void;
-  onClose?: () => void;
-  isOpen?: boolean;
-}) {
-  const {
-    isOpen: internalIsOpen,
-    onOpen: internalOnOpen,
-    onClose: internalOnClose,
-    onOpenChange: _internalOnOpenChange,
-  } = useDisclosure();
-
-  const isControlled = isOpen !== undefined;
-  const finalIsOpen = isControlled ? isOpen : internalIsOpen;
-  const finalOnOpen = isControlled ? onOpen : internalOnOpen;
-  const finalOnClose = isControlled ? onClose : internalOnClose;
-
-  const pathname = usePathname();
-  const router = useRouter();
-  const dispatch = useAppDispatch();
-  const { showToast } = useCustomToast();
-
-
-  useBodyScrollLock(finalIsOpen );
-
-
-  const {
-    handleSubmit,
-    formState: { isSubmitting },
-  } = useForm();
-
-  const {data: session} = useSession();
-
-  const onSubmit = async () => {
-    try {
-  
-      const res = await logoutAction();
-
-      if (!res.success) {
-        showToast(res.message, "danger");
-        return;
-      }
-
-      await signOut({
-        callbackUrl: "/customer/login",
-        redirect: false,
-      });
-
-      dispatch(clearCart());
-      showToast("You are logged out successfully!", "success");
-      setTimeout(() => {
-        router.push("/customer/login");
-        router.refresh();
-      }, 100);
-    } catch (err: unknown) {
-      const message = err instanceof Error ? err.message : "Logout failed";
-      showToast(message, "danger");
-    }
-  };
-
-  const innerContent = (_onClose?: () => void) => (
-    <div className={clsx("flex w-full flex-col rounded-md py-4", {
-      "gap-y-6": !!session?.user,
-      "gap-y-10": !session?.user,
-    })}>
-      {isObject(session?.user) ? (
-        <>
-          <header>
-            <div className={clsx("flex flex-col gap-3", "items-center justify-center")}>
-              <div className={clsx("flex gap-3",  "flex-col items-center")}>
-                <Avatar
-                  isBordered
-                  showFallback
-                  color="default"
-                  icon={<OpenAuth className={clsx("h-12 w-12")} />}
-                  size={"lg"}
-                  className={clsx( "h-24 w-24 text-large")}
-                />
-                <div className={clsx("flex flex-col justify-center", "items-center gap-1")}>
-                  <h4 className={clsx("leading-none dark:text-white", "text-xl font-bold text-black")}>
-                    {session?.user?.name}
-                  </h4>
-                  <h5 className={clsx("tracking-tight dark:text-white",  "text-sm text-gray-500")}>
-                    {session?.user?.email}
-                  </h5>
-                </div>
-              </div>
-
-              <p className={clsx("text-default-500 dark:text-white", "text-center mt-2")}>
-                Manage Cart, Orders
-                <span aria-label="confetti" className="px-2" role="img">
-                  🎉
-                </span>
-              </p>
-            </div>
-          </header>
-
-          <footer>
-            <form onSubmit={handleSubmit(onSubmit)} className={clsx("flex justify-center")}>
-              <button
-                className={clsx(
-                  "rounded-full bg-gray-800 px-5 py-2.5 text-sm font-medium text-white hover:bg-gray-900 focus:outline-none focus:ring-4 focus:ring-gray-300 dark:border-gray-700 dark:bg-gray-800 dark:hover:bg-gray-700 dark:focus:ring-gray-700",
-                  isSubmitting ? " cursor-not-allowed" : " cursor-pointer",
-                  "w-40 min-w-[150px] mt-2"
-                )}
-                type="submit"
-              >
-                <div className="mx-1">
-                  {isSubmitting ? (
-                    <div className="flex items-center justify-center">
-                      <p>Loading</p>
-                      <LoadingDots className="bg-white" />
-                    </div>
-                  ) : (
-                    <p> Log Out</p>
-                  )}
-                </div>
-              </button>
-            </form>
-          </footer>
-        </>
-      ) : (
-        <>
-          <header className="text-center">
-            <div className="flex flex-col gap-y-2">
-              <h4 className="font-bold leading-none text-black dark:text-white text-3xl">
-                Welcome Guest
-              </h4>
-              <p className="text-default-500 dark:text-neutral-400 text-lg">
-                Manage Cart, Orders
-                <span aria-label="confetti" className="px-2" role="img">
-                  🎉
-                </span>
-              </p>
-            </div>
-          </header>
-
-          <footer className="flex gap-4">
-            <Link className="w-full" href="/customer/login" onClick={finalOnClose} aria-label="Go to sign in page">
-              <button
-                className={clsx(
-                  "w-full rounded-full bg-blue-600 px-5 py-3 text-center text-sm font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-4 focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800",
-                  pathname === "/customer/login"
-                    ? " cursor-not-allowed"
-                    : " cursor-pointer"
-                )}
-                disabled={pathname === "/customer/login"}
-                type="button"
-              >
-                Sign In
-              </button>
-            </Link>
-
-            <Link className="w-full" href="/customer/register" onClick={finalOnClose} aria-label="Go to create account page">
-              <button
-                className={clsx(
-                  "w-full rounded-full bg-[#1e293b] px-5 py-3 text-sm font-medium text-white hover:bg-gray-900 focus:outline-none focus:ring-4 focus:ring-gray-300 dark:border-gray-700 dark:bg-gray-800 dark:hover:bg-gray-700 dark:focus:ring-gray-700",
-                  pathname === "/customer/register"
-                    ? " cursor-not-allowed"
-                    : " cursor-pointer"
-                )}
-                disabled={pathname === "/customer/register"}
-                type="button"
-              >
-                Sign Up
-              </button>
-            </Link>
-          </footer>
-        </>
-      )}
-    </div>
-  );
-
-
-  return (
-    <>
-      <button
-        type="button"
-        aria-label="Open account"
-        className={clsx(className, "cursor-pointer bg-transparent")}
-        onClick={finalOnOpen}
-      >
-        {children ? children : <OpenAuth />}
-      </button>
-
-      <AnimatePresence>
-        {finalIsOpen && (
-          <>
-            <motion.div
-              initial={{ opacity: 0 }}
-              animate={{ opacity: 1 }}
-              exit={{ opacity: 0 }}
-              onClick={finalOnClose}
-              className="fixed inset-0 z-40 bg-transparent"
-              style={{ top: "68px", bottom: "64px" }}
-            />
-
-            <motion.div
-              initial={{ x: "100%" }}
-              animate={{ x: 0 }}
-              exit={{ x: "100%" }}
-              transition={{ type: "spring", damping: 30, stiffness: 300, mass: 0.8 }}
-              className="fixed right-0 z-50 flex flex-col border-l border-neutral-200 bg-white dark:border-neutral-800 dark:bg-black lg:hidden"
-              style={{
-                top: "68px",
-                bottom: "64px",
-                width: "100%",
-                maxWidth: "448px",
-                height: "calc(var(--visual-viewport-height) - 132px)",
-              }}
-            >
-              <div className="flex flex-col gap-1 border-b border-neutral-100 p-4 dark:border-neutral-800">
-                <div className="flex items-center justify-between">
-                  <p className="text-xl font-semibold dark:text-white">Account</p>
-                  <button
-                    aria-label="Close account"
-                    className="rounded-full p-1 hover:bg-neutral-100 "
-                    onClick={finalOnClose}
-                    type="button"
-                  >
-                    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" className="h-6 transition-all ease-in-out hover:scale-110"><path strokeLinecap="round" strokeLinejoin="round" d="M6 18 18 6M6 6l12 12"></path></svg>
-                  </button>
-                </div>
-              </div>
-
-              <div className="flex flex-1 flex-col justify-center px-4 py-0 drawer-scrollbar-hidden">
-                {innerContent(finalOnClose)}
-              </div>
-
-              <div className="p-4" />
-            </motion.div>
-          </>
-        )}
-      </AnimatePresence>
-    </>
-  );
-}

+ 0 - 21
src/components/customer/credentials/index.tsx

@@ -1,21 +0,0 @@
-import CredentialModal from "./CredentialModal";
-
-export default function UserAccount({
-  children,
-  className,
-  onOpen,
-  onClose,
-  isOpen,
-}: {
-  children?: React.ReactNode;
-  className?: string;
-  onOpen?: () => void;
-  onClose?: () => void;
-  isOpen?: boolean;
-}) {
-  return (
-    <CredentialModal className={className} onOpen={onOpen} onClose={onClose} isOpen={isOpen}>
-      {children}
-    </CredentialModal>
-  );
-}

+ 0 - 23
src/components/layout/navbar/CartAndUserActions.tsx

@@ -1,23 +0,0 @@
-import { Suspense } from "react";
-import Cart from "@/components/cart";
-import UserAccount from "@components/customer/credentials";
-import { IconSkeleton } from "@/components/common/skeleton/IconSkeleton";
-
-
-export function CartAndUserActions() {
-  return (
-    <div className="flex max-w-fit gap-2 md:gap-4">
-
-     
-        <Cart />
-      
-      <Suspense fallback={<IconSkeleton />}>
-        
-
-            <UserAccount />
-
-       
-      </Suspense>
-    </div>
-  );
-}

+ 2 - 0
src/components/layout/navbar/MobileMenu.tsx

@@ -191,6 +191,7 @@ export default function MobileMenu({ menu, isOpen, onClose,isGuest }: MobileMenu
           
                  <main className="flex-1 overflow-y-auto p-3 pr-4">
                    {/*顶部横幅占位 */}
+                   {activeMainMenu?.wapImage && 
                    <div className="w-full  bg-gray-100 mb-4 flex items-end">
                      {/* <span className="text-3xl text-white pl-6 pb-4">Shop By Feature</span> */}
                       <Image
@@ -201,6 +202,7 @@ export default function MobileMenu({ menu, isOpen, onClose,isGuest }: MobileMenu
                          height={37}
                        />
                    </div>
+                   }
                  
                    {subMenuList.length === 0 ? (
                      <div className="text-gray-500 text-xl">No sub categories</div>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 39 - 0
src/components/layout/navbar/NavbarActions.tsx


+ 2 - 2
src/components/layout/navbar/NavbarSearchIcon.tsx

@@ -21,11 +21,11 @@ export default function NavbarSearchIcon() {
             cy="8.75"
             r="8"
             stroke="rgba(0, 0, 0, 1)"
-            stroke-width="1.5"
+            strokeWidth="1.5"
           ></circle>
           <path
             stroke="rgba(0, 0, 0, 1)"
-            stroke-width="1.5"
+            strokeWidth="1.5"
             d="M14.25 15.25L17.25 18.25"
           ></path>
         </svg>

+ 11 - 41
src/components/layout/navbar/index.tsx

@@ -1,20 +1,14 @@
 import Link from "next/link";
 import { Suspense } from "react";
-// import Search from "./Search";
-// import { SearchSkeleton } from "@/components/common/skeleton/SearchSkeleton";
 import LogoIcon from "@components/common/icons/LogoIcon";
 import MobileMenuTrigger from "./MobileMenuTrigger";
-import { CartAndUserActions } from "./CartAndUserActions";
+import { NavbarActions } from "./NavbarActions";
 import { NavigationSkeleton } from "./NavigationSkeleton";
-import { ActionsSkeleton } from "./ActionsSkeleton";
 import { NavbarErrorBoundary } from "@/components/error/ErrorBoundary";
 
 import { 
-  // GET_TREE_CATEGORIES,
   GET_TREEFRONT_MENUS } from "@/graphql";
-// import { cachedGraphQLRequest } from "@utils/hooks/useCache";
 import { serverGraphqlFetch } from "@utils/bagisto/index";
-// import { TreeCategoriesResponse } from "@/types/theme/category-tree";
 import NavbarSearchIcon from "./NavbarSearchIcon"
 import type { GetTreefrontMenusResult } from "@/types/theme/menus";
 import { authOptions } from "@utils/auth";
@@ -23,37 +17,14 @@ export default async function Navbar() {
 
     const session = await getServerSession(authOptions);// 游客是null
     const isGuest = session === null;
-  // const { data } = await cachedGraphQLRequest<TreeCategoriesResponse>(
-  //   "category",
-  //   GET_TREE_CATEGORIES,
-  //   { parentId: 1 },
-  // );
-  // console.log('TreeCategoriesResponse --- ',data)
-  // const categories = data?.treeCategories || [];
-   const { data: menudata } = await serverGraphqlFetch<
-  GetTreefrontMenusResult
->({
-  query: GET_TREEFRONT_MENUS,
-});
-console.log('GetTreefrontMenusResult --- ',menudata)
-  const menudatas =menudata? menudata.treefrontMenus:[];
-  // const filteredCategories = categories
-  //   .filter((cat: any) => cat.id !== "1")
-  //   .map((cat: any) => {
-  //     const translation = cat.translation;
-  //     return {
-  //       id: cat.id,
-  //       _id: cat._id,
-  //       name: translation?.name || "",
-  //       slug: translation?.slug || "",
-  //     };
-  //   })
-  //   .filter((item: any) => item.name && item.slug);
 
-  // const menuData = [
-  //   { id: "all", name: "All", slug: "" },
-  //   ...filteredCategories.slice(0, 3),
-  // ];
+    const { data: menudata } = await serverGraphqlFetch<
+      GetTreefrontMenusResult
+    >({
+      query: GET_TREEFRONT_MENUS,
+    });
+    console.log('GetTreefrontMenusResult --- ',menudata)
+    const menudatas =menudata? menudata.treefrontMenus:[];
 
   return (
     <NavbarErrorBoundary>
@@ -81,10 +52,9 @@ console.log('GetTreefrontMenusResult --- ',menudata)
               <LogoIcon />
             </Link>
 
-            {/* 3. DYNAMIC HOLE: Auth & Cart (Blocked by Session/Cookies) */}
-            <Suspense fallback={<ActionsSkeleton />}>
-              <CartAndUserActions />
-            </Suspense>
+
+            <NavbarActions isGuest={isGuest} />
+
           </div>
         </nav>
       </header>

+ 1 - 1
src/components/theme/ui/CommonModal.tsx

@@ -48,7 +48,7 @@ export default function CommonModal({
     const [rootPddingTop, setRootPddingTop] = useState(0);
 
     const baseClassNname = "absolute box-border transition-transform duration-300 ease-out";
-    let applyClassName = "bottom-0 left-0 h-17/20 w-full bg-white rounded-t-xl";
+    let applyClassName = "top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 h-3/5 w-130 bg-white rounded-xl";
     if(contentClassName) {
         applyClassName = contentClassName;
     }

+ 5 - 5
src/components/theme/ui/PhoneNumberInput/PhoneNumberInput.tsx

@@ -168,9 +168,9 @@ function PhoneNumberInput({
                 value={value}
                 ref={ref}
             />
-            <div className="flex gap-4 box-border border-1 border-ly-inputborder rounded-lg">
-                <div className="px-3.75" onClick={handleShowCodeList}>
-                    <div className="h-11.5 text-ly-12 flex items-center">
+            <div className="flex gap-4 box-border border-1 border-ly-inputborder">
+                <div className="px-4" onClick={handleShowCodeList}>
+                    <div className="h-14 text-ly-16 flex items-center">
                         
                         <Image alt="china flag" width={24} height={18} className="w-6 h-4.5 mr-2"
                             src={`/image/flags/4x3/${displayCountryCode.toLowerCase()}.svg`}
@@ -180,7 +180,7 @@ function PhoneNumberInput({
                     </div>
                 </div>
                 
-                <input className="flex-auto h-11.5 pr-3 placeholder:text-ly-placeholder text-ly-12 focus:outline-none" 
+                <input className="flex-auto h-14 pr-4 placeholder:text-ly-placeholder text-ly-16 focus:outline-none" 
                     value={phoneNumber}
                     type="text"
                     placeholder={placeholder}
@@ -200,7 +200,7 @@ function PhoneNumberInput({
             >
                 <ul>
                     {phoneCodeList.map((item) => {
-                        return (<li className="text-ly-12 flex items-center h-8 gap-2" key={item.code} 
+                        return (<li className="text-ly-16 flex items-center h-9 gap-2" key={item.code} 
                             onClick={() => {
                                 phoneCodeSelect(item.phoneCode, item.code);
                                 // phoneCodeChange(item.code);

+ 5 - 5
src/components/theme/ui/kernel/confirm/host.tsx

@@ -30,12 +30,12 @@ export function ConfirmHost() {
         onClick={(e) => e.stopPropagation()}
         >
             {/* <div className="fixed z-1000 flex justify-center items-center bg-black/40 inset-0"> */}
-                <div className="w-4/5 p-4 bg-white rounded-lg">
+                <div className="w-80 p-3 bg-white rounded-xl">
                     <h3 className="text-center text-ly-18 font-bold mb-6">{current.title}</h3>
-                    <p className="text-ly-14 font-medium">{current.content}</p>
-                    <div className="w-full flex justify-end gap-3 mt-6">
-                        {!current.noOk && <button className="w-20 h-8 flex justify-center items-center rounded-xs bg-ly-green text-ly-12 font-medium text-white" onClick={() => close(true)}>OK</button>}
-                        {!current.noCancel && <button className="w-20 h-8 flex justify-center items-center rounded-xs bg-ly-gray text-ly-12 font-medium" onClick={() => close(false)}>Cancel</button>}
+                    <p className="text-ly-16 leading-5 text-center">{current.content}</p>
+                    <div className="w-full flex justify-center gap-3 mt-6">
+                        {!current.noOk && <button className="w-35.5 h-12 flex justify-center items-center rounded-3xl border-1 text-ly-16 font-medium" onClick={() => close(true)}>Yes</button>}
+                        {!current.noCancel && <button className="w-35.5 h-12 flex justify-center items-center rounded-3xl bg-ly-green text-white text-ly-16 font-medium" onClick={() => close(false)}>Cancel</button>}
                     </div>
                 </div>
             {/* </div> */}

+ 125 - 0
src/providers/SocialShareProvider.tsx

@@ -0,0 +1,125 @@
+"use client";
+/*
+import Script from "next/script";
+import {
+  createContext,
+  useContext,
+  useState
+} from "react";
+
+type ShareToSocialName = "pinterest" | "facebook" | "teitter" | "X" | "x" | "whatsapp" | "email" | "copy_link";
+type SDKLoadState = "none" | "loading" | "error" | "success";
+type SDKName = "pinterest";
+interface SocialSDKState {
+  pinterest: SDKLoadState;
+}
+
+interface SocialShareContextProps {
+  loadSDKState: SocialSDKState;
+}
+
+const pinterestShareSDKURL = "https://assets.pinterest.com/js/pinit.js";
+
+
+const SocialShareContext = createContext<SocialShareContextProps|null>(null);
+
+
+export function SocialShareProvider({
+    children
+}: {
+    children:React.ReactNode;
+}){
+
+    const [loadSDKState, setLoadSDKState] = useState<SocialSDKState>({
+        pinterest: 'none', // none loading error success
+    });
+
+    const onSdkLoad = (m:SDKName) => {
+        setLoadSDKState((prev) => {
+            return {
+                ...prev,
+                [m]: 'success'
+            }
+        });
+    };
+    const onSdkError = (m:SDKName) => {
+        setLoadSDKState((prev) => {
+            return {
+                ...prev,
+                [m]: 'error'
+            }
+        });
+    };
+
+    const handlerShare = ({
+        name,
+        url,
+        title,
+        pic,
+    }:{
+        name: ShareToSocialName;
+        url: string;
+        title: string;
+        pic: string;
+    }) => {
+        var facebook = 'https://www.facebook.com/sharer/sharer.php?u={url}&t={title}&pic={pic}';
+	
+        if(name === 'pinterest') {
+            if(loadSDKState.pinterest === 'success') {
+                // window.PinUtils.pinOne({
+                //     url: url,
+                //     media: pic,
+                //     description: title,
+                // });
+
+            }
+            
+        } else if(name === 'facebook') {
+            // shareModal.simpleShare.facebook();
+            var facebook = 'https://www.facebook.com/sharer/sharer.php?u={url}&t={title}&pic={pic}';
+        } else if(name === 'teitter') {
+            var twitter = 'https://twitter.com/intent/tweet?text={title}&url={url}';
+        } else if(name === 'whatsapp') {
+            var waShareUrl = 'https://wa.me/?text=' + window.encodeURIComponent(title + url)
+            window.open(waShareUrl,'t','toolbar=0,resizable=1,status=0,width=640,height=528,left=500,top=300');
+        }else if(name === 'email') {
+            // var aDom = jQuery('<a></a>');
+            // aDom.attr('href', 'mailto:?subject=' + window.encodeURIComponent('Share Alipearlhair Product') + '&body=' + window.encodeURIComponent(shareModal.shareInfo.url));
+            // aDom[0].click();
+        } else if(name === 'copy_link') {
+            // shareModal.copyText(shareModal.shareInfo.url);
+        }
+    };
+
+    return (
+        <SocialShareContext.Provider
+            value={{
+                loadSDKState
+            }}
+        >
+            
+            <Script id="pinterest-share-sdk" strategy="lazyOnload"
+                src={pinterestShareSDKURL}
+                onLoad={() => onSdkLoad('pinterest')}
+                onError={() => {
+                    onSdkError('pinterest');
+                }}
+            />
+            
+
+            {children}
+
+        </SocialShareContext.Provider>
+    )
+
+}
+
+export const useSocialShareContext = () => {
+    const context = useContext(SocialShareContext);
+    if (!context) {
+        throw new Error("useSocialShareContext must be used within a SocialShareProvider");
+    }
+
+    return context;
+};
+*/

+ 1 - 26
src/types/checkout/type.ts

@@ -461,32 +461,7 @@ export interface State {
 }
 
 
-export interface ShipAddressFormData { 
-    shippingAddressId: string | number,
-    shippingEmail: string,
-    shippingFirstName: string,
-    shippingLastName: string,
-    shippingCompanyName: string,
-    shippingAddress: string,
-    shippingCountry: string,
-    shippingState: string,
-    shippingCity: string,
-    shippingPostcode: string,
-    shippingPhoneNumber: string,
-}
-export interface BillAddressFormData { 
-    billingAddressId: string | number,
-    billingEmail: string,
-    billingFirstName: string,
-    billingLastName: string,
-    billingCompanyName: string,
-    billingAddress: string,
-    billingCountry: string,
-    billingState: string,
-    billingCity: string,
-    billingPostcode: string,
-    billingPhoneNumber: string,
-}
+
 
 export interface CreatePaymentReplay{
     id: number;

+ 1 - 1
src/utils/hooks/useCheckoutAddress.ts

@@ -12,7 +12,7 @@ import {normalizePhoneForForm} from "@/utils/phoneNumberTools";
 /**
  * 对比shipping address与billing address的数据是否完全相同
  */
-export function addressIsSame(billAddress: BillAddressFormData | null, shipAddress: ShipAddressFormData | null) {
+export function addressIsSame(billAddress: Omit<BillAddressFormData,'billingSameAsShipping'> | null, shipAddress: ShipAddressFormData | null) {
     if(billAddress === null && shipAddress === null) {
         return true;
     } else if(billAddress !== null && shipAddress !== null) {

+ 20 - 1
src/utils/orderDetailTools.ts

@@ -1,4 +1,4 @@
-import type { AddressListInOrderDetails,OrderAddressType } from "@/types/customer/type";
+import type { AddressListInOrderDetails,OrderAddressType,ProductItemAdditional } from "@/types/customer/type";
 import type { CartAddress } from "@/types/cart/type";
 
 export function getAddressFromOrderDetailAddressList(addressList: AddressListInOrderDetails, addressType: OrderAddressType) {
@@ -25,6 +25,25 @@ export function getAddressFromOrderDetailAddressList(addressList: AddressListInO
     return res;
 
 }
+
+export function getProductAdditionalInfo(productItem: ProductItemAdditional) { 
+    const attributeKeys = Object.keys(productItem.attributes);
+    let res = '';
+    attributeKeys.forEach(key => {
+      const attribute = productItem.attributes[key];
+      if (attribute) {
+        // option_label value_label
+
+        if(res) {
+            res = res + ', ' + attribute.option_label + ': ' + attribute.value_label;
+        } else {
+            res = attribute.option_label + ': ' + attribute.value_label;
+        }
+      }
+    });
+    return res;
+}
+
 export function getProductFinalPriceInOrder() {}
 // export function getProductAdditinalInOrder(itemAdditional: string) {
 //     const additinal = JSON.parse(itemAdditional);