Explorar o código

优惠券逻辑

zhangzf hai 5 días
pai
achega
41d78604c3

BIN=BIN
public/image/account/couponBg.png


+ 120 - 47
src/app/(public)/customer/account/mycoupon/_components/CouponList.tsx

@@ -1,47 +1,59 @@
 // src/components/CouponList.tsx
-import React, { useState } from 'react';
+import React, { useState,useEffect } from "react";
 import { useInfiniteScroll } from "./UseInfiniteScroll";
-
-// 优惠券数据类型
+import { clientFetch } from "@/lib/restApiClient";
 interface CouponItem {
   id: number;
-  discount: string; // 优惠金额(如 $15 OFF)
-  desc: string; // 优惠描述
-  valid: string; // 有效期
+  code: string;
+  cart_rule_id: number;
+  rule_name: string;
+  rule_description: string;
+  discount_text: string;
+  status: string;
+  expired_at: string;
+  starts_from: string;
+  ends_till: string;
+  created_at: string;
 }
 
+
 const CouponList: React.FC = () => {
   // 初始化优惠券数据
   const [coupons, setCoupons] = useState<CouponItem[]>([
-    { id: 1, discount: '$15 OFF', desc: 'For All Products', valid: 'Valid:6/2/2026-12/31/2026' },
-    { id: 2, discount: '$10 OFF', desc: 'For All Products', valid: 'Valid:6/2/2026-12/31/2026' },
+    {
+      id: 103,
+      code: "UFP73XEZ",
+      cart_rule_id: 1,
+      rule_name: "测试优惠券",
+      rule_description: "For All Products",
+      discount_text: "$20 OFF",
+      status: "available",
+      expired_at: "2027-03-01",
+      starts_from: "",
+      ends_till: "",
+      created_at: "",
+    },
   ]);
-  const [hasMore, setHasMore] = useState(true); // 模拟:初始有更多数据,加载2次后无更多
+  const [hasMore] = useState(false); // 模拟:初始有更多数据,加载2次后无更多
 
   // 加载更多优惠券(模拟异步请求)
   const loadMoreCoupons = async () => {
-    return new Promise<void>((resolve) => {
-      setTimeout(() => {
-        if (coupons.length >= 6) { // 模拟最多加载6条
-          setHasMore(false);
-          resolve();
-          return;
-        }
-        // 模拟新增数据
-        const newCoupons = [
-          { 
-            id: coupons.length + 1, 
-            discount: `$${5 * (coupons.length + 1)} OFF`, 
-            desc: 'For All Products', 
-            valid: 'Valid:6/2/2026-12/31/2026' 
-          },
-        ];
-        setCoupons(prev => [...prev, ...newCoupons]);
-        resolve();
-      }, 800);
-    });
+   return;
   };
+ useEffect(() => {
+    const load = async () => {
+      const resp = await clientFetch("/api/customer/coupons");
+      console.log("resp------------------------:",resp);
+      if(resp.success){
+         const dataObj = resp.data||[];
+         setCoupons((prev) => [...prev, ...dataObj]);
+      }
+     
+      // console.log("完整返回:", dataObj);
+    };
 
+    load();
+  }, []);
   // 复用懒加载Hook
   const { containerRef, isLoading } = useInfiniteScroll({
     loadMore: loadMoreCoupons,
@@ -49,31 +61,92 @@ const CouponList: React.FC = () => {
   });
 
   return (
-    <div 
+    <div
       ref={containerRef}
       className="h-[calc(100vh-80px)] overflow-auto px-2 py-4"
     >
       {/* 优惠券列表 */}
       <div className="space-y-4">
         {coupons.map((item) => (
-          <div 
+          <div
             key={item.id}
-            className="flex items-center bg-pink-100 rounded-lg overflow-hidden"
+            className="
+              flex
+              items-center
+              bg-[url('/image/account/couponBg.png')]
+              bg-cover
+              bg-center
+              w-[358px]
+              h-[88px]
+              overflow-hidden
+              m-auto
+            "
           >
-            {/* 优惠信息区 */}
-            <div className="flex-1 p-4 text-pink-600">
-              <h3 className="text-2xl font-bold">{item.discount}</h3>
-              <p className="text-sm mt-1">{item.desc}</p>
-              <p className="text-xs mt-2 text-pink-500">{item.valid}</p>
-            </div>
-            {/* 分割线 */}
-            <div className="w-0.5 bg-pink-300 h-16 relative">
-              <div className="absolute top-0 left-[-4px] w-2 h-2 bg-white border border-pink-300 rounded-full"></div>
-              <div className="absolute bottom-0 left-[-4px] w-2 h-2 bg-white border border-pink-300 rounded-full"></div>
+            {/* 左侧优惠信息 */}
+            <div
+              className="
+                flex-1
+                pl-6
+                pt-2
+              "
+            >
+              <div
+                className="
+                  text-[40px]
+                  leading-none
+                  font-bold
+                  text-[#036141]
+              
+                "
+              >
+                {item.discount_text}
+              </div>
+
+              <div
+                className="
+                mt-1
+                text-ly-12
+                font-normal
+                text-black
+              "
+              >
+                {item.rule_description || "For All Products"}
+              </div>
             </div>
-            {/* 使用按钮区 */}
-            <div className="px-6 py-4 font-bold text-black">
-              Use Now
+
+            {/* 右侧按钮和日期 */}
+            <div
+              className="
+                flex
+                w-[150px]
+                flex-col
+                items-center
+                justify-center
+              "
+            >
+              <button
+                className="
+                  h-[32px]
+                  w-[100px]
+                  rounded-full
+                  bg-[#008052]
+                  text-ly-14
+                  font-medium
+                  text-white
+                "
+              >
+                Use Now
+              </button>
+
+              <div
+                className="
+                  mt-2
+                  text-ly-12
+                  text-black
+                "
+              >
+                Expire In {item.expired_at}
+              </div>
             </div>
           </div>
         ))}
@@ -81,10 +154,10 @@ const CouponList: React.FC = () => {
 
       {/* 加载状态/无更多提示 */}
       <div className="text-center mt-4 text-gray-400 text-sm">
-        {isLoading ? 'Loading...' : hasMore ? '' : 'No More Data'}
+        {isLoading ? "Loading..." : hasMore ? "" : "No More Data"}
       </div>
     </div>
   );
 };
 
-export default CouponList;
+export default CouponList;

+ 3 - 3
src/app/(public)/customer/account/mycoupon/_components/TabButton.tsx

@@ -7,11 +7,11 @@ const TabButton: React.FC = () => {
   return (
     <div>
       {/* Tab 切换栏 */}
-      <div className="flex w-full">
+      <div className="flex w-full pt-6 pb-4 border-b border-[#ACBDB8] px-4 gap-3">
         {/* My Coupon Tab */}
         <button
           onClick={() => setActiveTab("coupon")}
-          className={`flex-1 py-3 text-center font-medium ${
+          className={`flex-1 py-3 text-center font-medium rounded-[40px] border border-black ${
             activeTab === "coupon"
               ? "bg-black text-white "
               : "bg-white text-black"
@@ -22,7 +22,7 @@ const TabButton: React.FC = () => {
         {/* My Giftcard Tab */}
         <button
           onClick={() => setActiveTab("giftcard")}
-          className={`flex-1 py-3 text-center font-medium ${
+          className={`flex-1 py-3 text-center font-medium rounded-[40px] border border-black ${
             activeTab === "giftcard"
               ? "bg-black text-white"
               : "bg-white text-black"

+ 2 - 2
src/app/(public)/customer/account/mycoupon/page.tsx

@@ -3,7 +3,7 @@ import TabButton from "./_components/TabButton"
 const CouponsPage: React.FC = () => {
   return (
     <div className="w-full h-full">
-       <div className="bg-[#fff] pr-2.5 pl-2.5 w-full text-center text-base h-11 leading-11 font-semibold relative text-[#0b0b0b]">
+       <div className="bg-[#fff] pr-2.5 pl-2.5 w-full text-center text-base h-11 leading-11 font-semibold relative text-[#0b0b0b] border-b border-[#E1E1E1]">
         <Link
           className="absolute left-2.5 text-2xl inline-block top-1/2  -translate-y-1/2"
           href="/customer/account/mypoints"
@@ -25,7 +25,7 @@ const CouponsPage: React.FC = () => {
             ></path>
           </svg>
         </Link>
-        <span className="vipReturnTitles">Accessories</span>
+        <span className="vipReturnTitles">Coupon</span>
       </div>
       <TabButton/>
     </div>

+ 32 - 0
src/app/api/customer/coupons/route.ts

@@ -0,0 +1,32 @@
+import { NextResponse } from "next/server";
+import { restApiFetch } from "@/utils/bagisto";
+
+
+
+export async function GET() {
+  try {
+
+    const response = await restApiFetch<any>({
+      api: "/customer/coupons",
+      method: "GET",
+      cache: "no-store",
+
+    });
+
+    return NextResponse.json(
+      response.body,
+      {status: response.status}
+    );
+
+  } catch (error) {
+
+
+    return NextResponse.json(
+      {
+        message: "Network error",
+        error: error instanceof Error ? error.message : error,
+      },
+      { status: 500 }
+    );
+  }
+}