Prechádzať zdrojové kódy

proxy.ts cookie 初始化问题修改; footer 订阅改为接口形式;其他一些细节优化

fogwind 3 dní pred
rodič
commit
b0cd26592c

+ 1 - 2
src/actions/index.ts

@@ -5,5 +5,4 @@ export {switchCurrencyAction} from "./switchCurrencyAction";
 export {addProductToCartAction} from "./addProductToCartAction";
 export {deleteCartProductAction} from "./deleteCartProductAction";
 export {logoutAction} from "@/actions/logoutAction";
-export {recoverPasswordAction} from "@/actions/recoverPasswordAction";
-export {subscribeNewsletterAction} from "@/actions/subscribeNewsletterAction";
+export {recoverPasswordAction} from "@/actions/recoverPasswordAction";

+ 0 - 41
src/actions/subscribeNewsletterAction.tsx

@@ -1,41 +0,0 @@
-"use server";
-
-import { serverGraphqlFetch } from "@utils/bagisto";
-import { SUBSCRIBE_TO_NEWSLETTER } from "@/graphql/theme/mutations";
-import type { CreateNewsletterResponse } from "@/types/customer/type";
-
-
-export async function subscribeNewsletterAction(param: {email: string;}){
-
-    try{
-        const response = await serverGraphqlFetch<CreateNewsletterResponse,{input:{customerEmail: string}}>({
-            query: SUBSCRIBE_TO_NEWSLETTER,
-            variables: {
-                input: {
-                    customerEmail: param.email
-                }
-            },
-            cache: "no-store",
-            takeAuthorization: false
-        });
-        const newsletterRes = response.data?.createNewsletter?.newsletter;
-        let success = true;
-        let msg = "";
-        if(response.error) {
-            success = false;
-            msg = response.error.message;
-        } else {
-            success = newsletterRes?.success ?? false;
-            msg = newsletterRes?.message ?? 'Fail to subscribe!';
-        }
-        return {
-            success: success,
-            msg: msg
-        };
-    } catch(e: any) {
-        return {
-            success:false,
-            msg: e.message || 'Fail to subscribe!'
-        };
-    }
-}

+ 5 - 3
src/app/api/graphql/route.ts

@@ -14,7 +14,7 @@ import {
     CREATE_CHECKOUT_SHIPPING_METHODS,
     CREATE_CHECKOUT_PAYMENT_METHODS,
     CREATE_CHECKOUT_ORDER,
-    CREATE_PRODUCT_REVIEW,
+    // CREATE_PRODUCT_REVIEW,
     CREATE_PAYMENT_INITIATE,
     CREATE_SAVE_CHECKOUT_CART,
     GET_ORDER_DETAILS,
@@ -36,7 +36,7 @@ const ALLOWED_OPERATIONS: Record<string, any> = {
     CreateCheckoutShippingMethod: CREATE_CHECKOUT_SHIPPING_METHODS,
     CreateCheckoutPaymentMethod: CREATE_CHECKOUT_PAYMENT_METHODS,
     CreateCheckoutOrder: CREATE_CHECKOUT_ORDER,
-    CreateProductReview: CREATE_PRODUCT_REVIEW,
+    // CreateProductReview: CREATE_PRODUCT_REVIEW,
     CreatePaymentInitiate: CREATE_PAYMENT_INITIATE, // 创建订单
     CreateSaveCheckoutCart: CREATE_SAVE_CHECKOUT_CART,
     GetOrderDetails: GET_ORDER_DETAILS, // 获取订单详情
@@ -50,7 +50,7 @@ interface FetchOption  {
     query: string;
     variables?: Record<string, any>;
     cache?: RequestCache;
-    guestToken?: string;
+    takeAuthorization?: boolean;
     operationName?: string;
 }
 
@@ -63,6 +63,7 @@ function authorizationOperations(body: Record<string, any>): FetchOption {
     return {
         query,
         variables: finalVariables,
+        takeAuthorization: true,
         cache: "no-store",
         // operationName
     }
@@ -77,6 +78,7 @@ function notAuthorizationOperations(body: Record<string, any>): FetchOption {
         query,
         variables,
         cache: "no-store",
+        takeAuthorization: false,
         // operationName
     }
 }

+ 7 - 15
src/app/layout.tsx

@@ -89,18 +89,10 @@ export default async function RootLayout({
   ////////eruda调试/////////
   const loadEruda = cookieStore.get('9527_LOAD_ERUDA_3345678');
   ////////eruda调试////////
-  const currentCurrency = cookieStore.get(CURRENT_CURRENCY);
-  const currentLocale = cookieStore.get(CURRENT_LOCAL);
-  const currentChannel = cookieStore.get(CURRENT_CHANNEL);
-  if(currentCurrency === undefined) {
-    throw new Error('Currency is not defined');
-  }
-  if(currentLocale === undefined) {
-    throw new Error('Local is not defined');
-  }
-  if(currentChannel === undefined) {
-    throw new Error('Channel is not defined');
-  }
+  const currentCurrency = cookieStore.get(CURRENT_CURRENCY)?.value ?? env.DEFAULT_CURRENCY;
+  const currentLocale = cookieStore.get(CURRENT_LOCAL)?.value ?? env.DEFAULT_LOCAL;
+  const currentChannel = cookieStore.get(CURRENT_CHANNEL)?.value ?? env.DEFAULT_CHANNEL;
+
 
   // 获取country list 和currency list
   const {data: countryResData} = await serverGraphqlFetch<{
@@ -127,9 +119,9 @@ export default async function RootLayout({
     defaultLocale: defaultLocale,
     storeName: storeName,
     // 用户当前使用值
-    currentCurrency: currentCurrency.value,
-    currentLocale: currentLocale.value,
-    currentChannel: currentChannel.value
+    currentCurrency: currentCurrency,
+    currentLocale: currentLocale,
+    currentChannel: currentChannel
   };
 
   const {data: cartDetailsRes} = await serverGraphqlFetch<GetCartItemData>({

+ 33 - 12
src/components/layout/footer/SubscribeNewsletter.tsx

@@ -2,7 +2,8 @@
 
 import Link from "next/link";
 import { useForm, type FieldErrors } from "react-hook-form";
-import {subscribeNewsletterAction} from "@/actions";
+import { SUBSCRIBE_TO_NEWSLETTER } from "@/graphql/theme/mutations";
+import { useApolloClient } from "@apollo/client/react";
 import { useCustomToast } from "@utils/hooks/useToast";
 import { overlayLoading } from "@/components/theme/ui/kernel/loading/api";
 import { EMAIL_REGEX } from "@utils/constants";
@@ -13,10 +14,10 @@ type FormValues = {
 };
 
 export default function SubscribeNewsletter() {
+    const apolloClient = useApolloClient();
     const { showToast } = useCustomToast();
     const {
         register,
-        reset,
         handleSubmit,
         formState: { errors }
     } = useForm<FormValues>({
@@ -29,17 +30,37 @@ export default function SubscribeNewsletter() {
     });
 
     const onSubmit = async (data: FormValues) => {
-
         overlayLoading.start();
-        const result = await subscribeNewsletterAction({email: data.email});
-        console.log(result);
-        if(result.success) {
-            showToast(result.msg, 'success');
-            reset();
-        } else {
-            showToast(result.msg, 'danger');
-        }
-        overlayLoading.stop();
+        apolloClient.mutate({
+            mutation: SUBSCRIBE_TO_NEWSLETTER,
+            variables: {
+                input: {
+                    customerEmail: data.email
+                }
+            }
+        }).then((res) => {
+            overlayLoading.stop();
+            const resData = res.data?.createNewsletter?.newsletter;
+            let success = true;
+            let msg = "";
+            if(resData) {
+                success = resData.success;
+                msg = resData.message;
+                
+            } else {
+                success = false;
+                msg = 'Fail to subscribe!';
+            }
+
+            if(success) {
+                showToast(msg, 'success');
+            } else {
+                showToast(msg, 'danger');
+            }
+        }).catch((err) => {
+            overlayLoading.stop();
+            showToast(err.message, "danger");
+        });
 
     };
 

+ 1 - 5
src/components/theme/toast/ToastContainer.tsx

@@ -6,11 +6,7 @@ export const ToastContainer = () => {
   const { toasts, removeToast } = useToast();
 
   return (
-    <div
-      className="fixed left-1/2 z-[999] w-[80%] -translate-x-1/2 sm:max-w-md
-        top-4 bottom-auto
-        md:bottom-4 md:top-auto"
-    >
+    <div className="fixed left-1/2 z-[999] w-[80%] -translate-x-1/2 sm:max-w-md top-4 bottom-auto">
       {toasts.map((toast) => (
         <Toast key={toast.id} toast={toast} onRemove={removeToast} />
       ))}

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

@@ -12,7 +12,7 @@ export const Price = ({
     {`${new Intl.NumberFormat(undefined, {
       style: "currency",
       currency: currencyCode,
-      currencyDisplay: "narrowSymbol",
+      // currencyDisplay: "narrowSymbol",
     }).format(parseFloat(amount))}`}
   </p>
 );

+ 3 - 2
src/graphql/theme/mutations/subscribeToNewsletter.ts

@@ -1,6 +1,7 @@
-import { gql } from "@apollo/client";
+import { gql, type TypedDocumentNode} from "@apollo/client";
+import type { CreateNewsletterResponse } from "@/types/customer/type";
 
-export const SUBSCRIBE_TO_NEWSLETTER = gql`
+export const SUBSCRIBE_TO_NEWSLETTER: TypedDocumentNode<CreateNewsletterResponse,{input:{customerEmail: string}}> = gql`
   mutation createNewsletter($input: createNewsletterInput!) {
     createNewsletter(input: $input) {
       newsletter {

+ 31 - 26
src/proxy.ts

@@ -2,40 +2,45 @@ import { NextResponse } from 'next/server'
 import type { NextRequest } from 'next/server'
 import {handleCurrency} from "./proxy/currency";
 import {handleAuth} from "./proxy/auth";
-
-export async function proxy(
-    request:NextRequest
-){
-    let response = NextResponse.next();
-
-    /**
-     * Currency
-     */
-    response = handleCurrency(
-        request,
-        response
-    );
-
-
-
-    /**
-     * Auth
-     */
-    response = await handleAuth(
-        request,
-        response
+import { currencyCookieOptions } from "@/utils/constants/server";
+
+export async function proxy(request: NextRequest) {
+  // 找出缺失的默认 Cookie
+  const missingCookies = handleCurrency(request);
+
+  // 补齐当前请求缺失的 Cookie
+  for (const cookie of missingCookies) {
+    request.cookies.set(cookie.name, cookie.value);
+  }
+
+  // 将修改后的请求头转发给 Server Components
+  let response = NextResponse.next({
+    request: {
+      headers: request.headers,
+    },
+  });
+
+  // 将默认 Cookie 写入浏览器
+  for (const cookie of missingCookies) {
+    response.cookies.set(
+      cookie.name,
+      cookie.value,
+      currencyCookieOptions,
     );
+  }
 
+  // 处理认证与重定向
+  response = await handleAuth(request, response);
 
-
-    return response;
-
+  return response;
 }
 
 
+
 export const config = {
     matcher:[
-        "/((?!_next|api|.*\\..*).*)" // 匹配到的不经过proxy.ts处理
+        // 匹配到的不经过proxy.ts处理
+        "/((?!_next|api|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js|map|woff|woff2|ttf|eot)$).*)",
     ]
 
 };

+ 19 - 28
src/proxy/currency.ts

@@ -1,34 +1,25 @@
 import type { NextRequest } from "next/server";
-import type { NextResponse } from "next/server";
 import {CURRENT_CURRENCY,CURRENT_LOCAL,CURRENT_CHANNEL} from "@/utils/constants";
-import {currencyCookieOptions} from "@/utils/constants/server";
 import { env } from "@/env";
 
-export function handleCurrency(
-    request: NextRequest,
-    response: NextResponse
-) {
-
-    const currency = request.cookies.get(CURRENT_CURRENCY);
-    const local = request.cookies.get(CURRENT_LOCAL);
-    const channel = request.cookies.get(CURRENT_CHANNEL);
-    const defaultCurrency = env.DEFAULT_CURRENCY;
-    const defaultLocal = env.DEFAULT_LOCAL;
-    const defaultChannel = env.DEFAULT_CHANNEL;
-
-    if (!currency && defaultCurrency) {
-        
-        response.cookies.set(CURRENT_CURRENCY,defaultCurrency,currencyCookieOptions);
-    }
-    if (!local && defaultLocal) {
-        
-        response.cookies.set(CURRENT_LOCAL,defaultLocal,currencyCookieOptions);
-    }
-    if (!channel && defaultChannel) {
-        
-        response.cookies.set(CURRENT_CHANNEL,defaultChannel,currencyCookieOptions);
-    }
-
-    return response;
+// 检查请求头中是否包含对应cookie
+export function handleCurrency(request: NextRequest) {
+  const defaults = [
+    {
+      name: CURRENT_CURRENCY,
+      value: env.DEFAULT_CURRENCY,
+    },
+    {
+      name: CURRENT_LOCAL,
+      value: env.DEFAULT_LOCAL,
+    },
+    {
+      name: CURRENT_CHANNEL,
+      value: env.DEFAULT_CHANNEL,
+    },
+  ];
 
+  return defaults.filter(
+    (item) => !request.cookies.has(item.name)
+  );
 }