zhangzf 6 дней назад
Родитель
Сommit
7e4fafd6c6
29 измененных файлов с 183 добавлено и 148 удалено
  1. 5 1
      src/app/(public)/_components/HomeContent.tsx
  2. 2 2
      src/app/(public)/_components/HomeMiddleBanner.tsx
  3. 30 28
      src/app/(public)/_components/JinGangSwiper.tsx
  4. 3 3
      src/app/(public)/_components/RecommendedProducts.tsx
  5. 6 6
      src/app/(public)/_components/TopImageSwiper.tsx
  6. 14 10
      src/app/(public)/_components/Trending.tsx
  7. 12 11
      src/app/(public)/category/[slug]/[id]/_components/ProductListing.tsx
  8. 14 14
      src/app/(public)/category/[slug]/[id]/page.tsx
  9. 12 11
      src/app/(public)/customer/account/_components/AccountVipPopup.tsx
  10. 4 1
      src/app/(public)/customer/address/eidt/[id]/page.tsx
  11. 3 1
      src/app/(public)/customer/order/track/order_id/[id]/_components/TrackDetail.tsx
  12. 1 1
      src/app/(public)/page.tsx
  13. 2 2
      src/app/(public)/product/[...urlProduct]/page.tsx
  14. 1 1
      src/app/(public)/product/_components/ProductReviewSection.tsx
  15. 1 1
      src/app/(public)/product/_components/popup/PriceModal.tsx
  16. 12 8
      src/app/(public)/product/_components/question/ComponentsQuestionModal.tsx
  17. 2 2
      src/app/(public)/product/_components/review/AddProductReviewForm.tsx
  18. 2 1
      src/app/(public)/product/_components/review/QuestionInputModal.tsx
  19. 6 6
      src/app/(public)/product/_components/review/ReviewAdd.tsx
  20. 12 8
      src/app/(public)/product/_components/review/ReviewDetail.tsx
  21. 1 1
      src/app/(public)/product/_components/review/ReviewImageUploader.tsx
  22. 5 5
      src/app/(public)/product/_components/review/ReviewModal.tsx
  23. 1 1
      src/app/(public)/search/_components/HotSearch.tsx
  24. 4 4
      src/app/(public)/search/page.tsx
  25. 2 2
      src/app/api/home/route.ts
  26. 2 2
      src/components/common/button/ReviewButton.tsx
  27. 1 0
      src/components/layout/navbar/Search.tsx
  28. 1 1
      src/components/layout/navbar/SearchPop.tsx
  29. 22 14
      src/components/theme/filters/NewMobileFilter.tsx

+ 5 - 1
src/app/(public)/_components/HomeContent.tsx

@@ -93,7 +93,11 @@ const MOCK_DATA = {
 };
 
 export default function HomeContent({ homeData }: HomeContentProps) {
-    const { channel, sections, categories } = homeData;
+    const { 
+      // channel,
+       sections,
+        // categories 
+      } = homeData;
       // 过滤出 banner 板块
   const bannerSection = sections.find(sec => sec.name === "banner");
   const bannerImages = bannerSection?.images ?? [];

+ 2 - 2
src/app/(public)/_components/HomeMiddleBanner.tsx

@@ -10,11 +10,11 @@ interface middleBannerProps {
   middleBanner: HomeSectionImage[];
 }
 export default function HomeMiddleBanner({ middleBanner }: middleBannerProps) {
-  if (!middleBanner || middleBanner.length === 0) return null;
-  const middleBannerImages = middleBanner;
   const [activeIndex, setActiveIndex] = useState(0);
 
   const [swiperRef] = useState(null);
+  if (!middleBanner || middleBanner.length === 0) return null;
+  const middleBannerImages = middleBanner;
 
   const handleSlideChange = (swiper: any) => {
     setActiveIndex(swiper.activeIndex);

+ 30 - 28
src/app/(public)/_components/JinGangSwiper.tsx

@@ -67,22 +67,22 @@ interface jinGangProps {
 // ];
 
 export default function JinGangSwiper({ jinGang }: jinGangProps) {
-    if (!jinGang || jinGang.length === 0) return null;
-    // 4. 真实数据按每6个拆分一组,替换原来的模拟拆分逻辑
-    const chunkSize = 6;
-    const productBlocks: HomeSectionImage[][] = [];
-    for (let i = 0; i < jinGang.length; i += chunkSize) {
-      productBlocks.push(jinGang.slice(i, i + chunkSize));
-    }
   const [activeIndex, setActiveIndex] = useState(0);
 
   const [swiperRef, setSwiperRef] = useState<SwiperType | null>(null);
+  if (!jinGang || jinGang.length === 0) return null;
+  // 4. 真实数据按每6个拆分一组,替换原来的模拟拆分逻辑
+  const chunkSize = 6;
+  const productBlocks: HomeSectionImage[][] = [];
+  for (let i = 0; i < jinGang.length; i += chunkSize) {
+    productBlocks.push(jinGang.slice(i, i + chunkSize));
+  }
 
-  const handleSlideChange = (swiper:any) => {
+  const handleSlideChange = (swiper: any) => {
     setActiveIndex(swiper.activeIndex);
   };
 
-  const handleIndicatorClick = (index:any) => {
+  const handleIndicatorClick = (index: any) => {
     if (swiperRef) {
       swiperRef.slideTo(index);
       setActiveIndex(index);
@@ -95,30 +95,32 @@ export default function JinGangSwiper({ jinGang }: jinGangProps) {
         modules={[Navigation]}
         spaceBetween={10}
         slidesPerView={1}
-         onSwiper={(swiper) => setSwiperRef(swiper)}
+        onSwiper={(swiper) => setSwiperRef(swiper)}
         onSlideChange={handleSlideChange}
         className="mb-6"
       >
-      {productBlocks.map((block, blockIndex) => (
-         <SwiperSlide key={blockIndex}>
-          <div className="grid grid-cols-3 gap-2">
-            {block.map((item, idx) => (
-              <div key={`block1-${idx}`} className="relative w-full aspect-[3/4]">
-                <Image
-                  src={item.image}
-                  alt={item.title}
-                  fill
-                  className="object-cover rounded-md"
-                />
-                {/* <div className="absolute bottom-2 left-2 text-white text-sm font-medium bg-black/50 px-2 py-1 rounded">
+        {productBlocks.map((block, blockIndex) => (
+          <SwiperSlide key={blockIndex}>
+            <div className="grid grid-cols-3 gap-2">
+              {block.map((item, idx) => (
+                <div
+                  key={`block1-${idx}`}
+                  className="relative w-full aspect-[3/4]"
+                >
+                  <Image
+                    src={item.image}
+                    alt={item.title}
+                    fill
+                    className="object-cover rounded-md"
+                  />
+                  {/* <div className="absolute bottom-2 left-2 text-white text-sm font-medium bg-black/50 px-2 py-1 rounded">
                   {item.name}
                 </div> */}
-              </div>
-            ))}
-          </div>
-        </SwiperSlide>
-      ))}
-     
+                </div>
+              ))}
+            </div>
+          </SwiperSlide>
+        ))}
       </Swiper>
 
       {/* 底部指示器按钮:2个,激活态黑色,未激活灰色 */}

+ 3 - 3
src/app/(public)/_components/RecommendedProducts.tsx

@@ -55,9 +55,9 @@ const mockGetProductApi = async (page: number, pageSize: number) => {
 const PAGE_SIZE = 6;
 
 export default function RecommendedProducts({ recommended }: recommendedProps) {
-    if (!recommended || recommended.length === 0) return null;
+  
   // 已渲染的全部商品
-  const [productList, setProductList] = useState<HomeProduct[]>(recommended);
+  const [productList, _setProductList] = useState<HomeProduct[]>(recommended);
   // 当前页码
   const [page, setPage] = useState(1);
   // 数据总条数
@@ -101,7 +101,7 @@ export default function RecommendedProducts({ recommended }: recommendedProps) {
     setPage(nextPage);
     fetchPageData(nextPage);
   };
-
+  if (!recommended || recommended.length === 0) return null;
   // 五星星星渲染
   const renderStars = (count: number) => {
     return Array.from({ length: count }).map((_, idx) => (

+ 6 - 6
src/app/(public)/_components/TopImageSwiper.tsx

@@ -16,12 +16,12 @@ const TopImageSwiper = ({ bannerImages }: TopImageSwiperProps) => {
   // 兜底:没有图片不渲染,防止报错
   if (!bannerImages || bannerImages.length === 0) return null;
   // ✅ 直接在这里放你的图片数组,想加多少加多少
-  const images = [
-    'https://cdn.asteriahair.com/uploads/202607/01/20260701165056_761989a0fdc11d5e.jpg',
-    'https://cdn.asteriahair.com/uploads/202607/01/20260701165110_3fff435adf276b89.jpg',
-    'https://cdn.asteriahair.com/uploads/202607/01/20260701165123_c424f6f1d0b29522.jpg',
-    'https://cdn.asteriahair.com/uploads/202607/01/20260701165056_761989a0fdc11d5e.jpg',
-  ];
+  // const images = [
+  //   'https://cdn.asteriahair.com/uploads/202607/01/20260701165056_761989a0fdc11d5e.jpg',
+  //   'https://cdn.asteriahair.com/uploads/202607/01/20260701165110_3fff435adf276b89.jpg',
+  //   'https://cdn.asteriahair.com/uploads/202607/01/20260701165123_c424f6f1d0b29522.jpg',
+  //   'https://cdn.asteriahair.com/uploads/202607/01/20260701165056_761989a0fdc11d5e.jpg',
+  // ];
 
   return (
     <div className="w-full max-w-[1200px] mx-auto ">

+ 14 - 10
src/app/(public)/_components/Trending.tsx

@@ -51,12 +51,21 @@ interface trendingProps {
 // ];
 
 const Trending = ({ trending }: trendingProps) => {
-  if (!trending || trending.length === 0) return null;
-  const  productList = trending
-  // 视频弹窗状态
+   // 视频弹窗状态
   const [openVideoModal, setOpenVideoModal] = useState(false);
   const [currentVideoSrc, setCurrentVideoSrc] = useState("");
-  const videoRef = useRef<HTMLVideoElement>(null);
+   const videoRef = useRef<HTMLVideoElement>(null);
+   // 弹窗打开自动播放
+  useEffect(() => {
+    if (openVideoModal && videoRef.current) {
+      videoRef.current.play().catch((err) => console.log("播放拦截", err));
+    }
+  }, [openVideoModal]);
+  
+  if (!trending || trending.length === 0) return null;
+  const  productList = trending
+ 
+ 
 
   // 打开弹窗并赋值视频地址
   const handlePlayClick = (videoUrl: string) => {
@@ -73,12 +82,7 @@ const Trending = ({ trending }: trendingProps) => {
     }
   };
 
-  // 弹窗打开自动播放
-  useEffect(() => {
-    if (openVideoModal && videoRef.current) {
-      videoRef.current.play().catch((err) => console.log("播放拦截", err));
-    }
-  }, [openVideoModal]);
+ 
 
   return (
     <div className="w-full max-w-[960px] mx-auto">

+ 12 - 11
src/app/(public)/category/[slug]/[id]/_components/ProductListing.tsx

@@ -41,7 +41,7 @@ export default function ProductListing({
   initialTotal,
   initialQuery,
 }: ProductListingProps) {
-    // 新增:页面刷新初始化源头打印
+  // 新增:页面刷新初始化源头打印
   console.log("【页面刷新初始initialQuery】", initialQuery);
   console.log("【刷新初始filters(传给筛选器的源头)】", initialQuery.filters);
   const [query, setQuery] = useState(initialQuery);
@@ -50,17 +50,8 @@ export default function ProductListing({
 
   const [pageInfo, setPageInfo] = useState(initialPageInfo);
 
-  const [total, setTotal] = useState(initialTotal);
+  const [_total, setTotal] = useState(initialTotal);
   const firstRender = useRef(true);
-  useEffect(() => {
-    if (firstRender.current) {
-      firstRender.current = false;
-      console.log("刷新页面不触发调接口");
-      
-      return;
-    }
-    fetchProducts(query);
-  }, [query.filters, query.sort, query.search]);
   const fetchProducts = async (currentQuery: QueryState) => {
     try {
       const res = await fetch("/api/products", {
@@ -97,6 +88,16 @@ export default function ProductListing({
       console.error("fetch products error", error);
     }
   };
+  useEffect(() => {
+    if (firstRender.current) {
+      firstRender.current = false;
+      console.log("刷新页面不触发调接口");
+
+      return;
+    }
+    fetchProducts(query);
+  }, [query.filters, query.sort, query.search]);
+
   const router = useRouter();
   const pathname = usePathname();
   console.log("query-----:", query);

+ 14 - 14
src/app/(public)/category/[slug]/[id]/page.tsx

@@ -1,18 +1,18 @@
 import { Metadata } from "next";
 import { notFound } from "next/navigation";
-import { isArray } from "@/utils/type-guards";
-import FilterList from "@components/theme/filters/FilterList";
-import Pagination from "@components/catalog/Pagination";
+// import { isArray } from "@/utils/type-guards";
+// import FilterList from "@components/theme/filters/FilterList";
+// import Pagination from "@components/catalog/Pagination";
 import ProductListing from "./_components/ProductListing";
 import { ProductsResponse } from "@components/catalog/type";
 import {
   GET_FILTER_PRODUCTS,
-  GET_TREE_CATEGORIES,
+  // GET_TREE_CATEGORIES,
   GET_CATEHORY_BY_ID,
 } from "@/graphql";
 import {
-  cachedGraphQLRequest,
-  cachedCategoryRequest,
+  // cachedGraphQLRequest,
+  // cachedCategoryRequest,
   getFilterAttributes,
 } from "@/utils/hooks/useCache";
 import { SortByFields } from "@utils/constants";
@@ -21,16 +21,16 @@ import CategoryDesc from "./_components/CategoryDesc";
 import FaqList, { FaqItem } from "./_components/FaqList";
 import { Suspense } from "react";
 import FilterListSkeleton from "@components/common/skeleton/FilterSkeleton";
-import { TreeCategoriesResponse } from "@/types/theme/category-tree";
+// import { TreeCategoriesResponse } from "@/types/theme/category-tree";
 // import { MobileSearchBar } from "@components/layout/navbar/MobileSearch";
 import {
-  extractNumericId,
-  findCategoryBySlug,
+  // extractNumericId,
+  // findCategoryBySlug,
   buildProductFilters,
 } from "@utils/helper";
 import { serverGraphqlFetch } from "@/utils/bagisto/index";
 import {
-  CategoryNode,
+  // CategoryNode,
   CategorySingleResponse,
 } from "@/types/theme/category-tree";
 
@@ -40,7 +40,7 @@ export async function generateMetadata({
 }: {
   params: Promise<{ slug: string; id: string }>;
 }): Promise<Metadata> {
-  const { slug: categorySlug, id: categoryId } = await params;
+  const { slug: _categorySlug, id: categoryId } = await params;
   const { data: categoryData } = await serverGraphqlFetch<
     CategorySingleResponse,
     { id: number }
@@ -78,7 +78,7 @@ export default async function CategoryPage({
   searchParams?: Promise<{ [key: string]: string | string[] | undefined }>;
 }) {
   //   const { collection: categorySlug } = await params;
-  const { slug: categorySlug, id: categoryId } = await params;
+  const { slug: _categorySlug, id: categoryId } = await params;
   const resolvedParams = await searchParams;
   function getSearchParam(
     value: string | string[] | undefined,
@@ -127,13 +127,13 @@ export default async function CategoryPage({
   // };
   const searchValue = getSearchParam(resolvedParams?.q) ?? "";
 
-  const page = getSearchParam(resolvedParams?.page);
+  // const page = getSearchParam(resolvedParams?.page);
 
   const cursor = getSearchParam(resolvedParams?.cursor);
 
   const before = getSearchParam(resolvedParams?.before);
   const itemsPerPage = 12;
-  const currentPage = page ? parseInt(page) - 1 : 0;
+  // const currentPage = page ? parseInt(page) - 1 : 0;
   const sortValue = getSearchParam(resolvedParams?.sort) ?? "name-asc";
   const selectedSort =
     SortByFields.find((s) => s.key === sortValue) || SortByFields[0];

+ 12 - 11
src/app/(public)/customer/account/_components/AccountVipPopup.tsx

@@ -121,21 +121,13 @@ export default function AccountVipPopup({
   visible: boolean;
   onClose: () => void;
 }) {
-  // 如果不显示,直接 return null
-  if (!visible) return null;
   // swiper实例
-  const [swiperRef, setSwiperRef] = useState<SwiperType | null>(null);
+  const [_swiperRef, setSwiperRef] = useState<SwiperType | null>(null);
   // 当前slide下标
   const [activeIndex, setActiveIndex] = useState(0);
-  // 滑动切换触发
-  const handleSlideChange = (swiper: SwiperType) => {
-    setActiveIndex(swiper.activeIndex);
-    console.log("aaa slide huadongle ");
-  };
-  const slideItem = vipList[activeIndex];
-  const slideLevelNum = slideItem?.level ?? 1;
-  const [loading, setLoading] = useState(true);
+  const [_loading, setLoading] = useState(true);
   const [VipGrothData, setVipGrothData] = useState<any>(null);
+  // 如果不显示,直接 return null
   useEffect(() => {
     const fetchGrothValue = async () => {
       try {
@@ -153,6 +145,15 @@ export default function AccountVipPopup({
     };
     fetchGrothValue();
   }, []);
+  if (!visible) return null;
+  // 滑动切换触发
+  const handleSlideChange = (swiper: SwiperType) => {
+    setActiveIndex(swiper.activeIndex);
+    console.log("aaa slide huadongle ");
+  };
+  const slideItem = vipList[activeIndex];
+  const slideLevelNum = slideItem?.level ?? 1;
+
   const progressPercent = VipGrothData
     ? Math.min(
         Math.max(

+ 4 - 1
src/app/(public)/customer/address/eidt/[id]/page.tsx

@@ -191,7 +191,10 @@ const CustomerAddressEditPage = () => {
                 control={addressForm.control}
                 name="country"
                 rules={{ required: "Country is required" }}
-                render={({ field }) => {
+                render={({ 
+                  // field
+
+                 }) => {
                   return (
                     <Select
                       placeholder="Country/Region"

+ 3 - 1
src/app/(public)/customer/order/track/order_id/[id]/_components/TrackDetail.tsx

@@ -30,7 +30,7 @@ interface TrackAddressProps {
 }
 
 export default function TrackAddress({ address, id }: TrackAddressProps) {
-  const [addr, setAddr] = useState<AddressData | null>(address);
+  const [addr] = useState<AddressData | null>(address);
   const { showToast } = useCustomToast();
 
   // 弹窗控制状态
@@ -92,6 +92,8 @@ export default function TrackAddress({ address, id }: TrackAddressProps) {
           showToast(resData.message, "warning");
         }
       } catch (err) {
+        console.log("err--------------------:",err);
+        
         showToast("Failed to fetch tracking info", "warning");
       }
     };

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

@@ -1,6 +1,6 @@
 // import { GET_THEME_CUSTOMIZATION } from "@/graphql";
 // import RenderThemeCustomization from "@components/home/RenderThemeCustomization";
-import HomeImageBanner from "@components/home/HomeImageBanner";
+// import HomeImageBanner from "@components/home/HomeImageBanner";
 // import { ThemeCustomizationResponse } from "@/types/theme/theme-customization";
 // import { cachedGraphQLRequest } from "@/utils/hooks/useCache";
 import { DatePicker } from "@heroui/date-picker";

+ 2 - 2
src/app/(public)/product/[...urlProduct]/page.tsx

@@ -1,8 +1,8 @@
 import { notFound } from "next/navigation";
 import { Suspense } from "react";
 // import clsx from "clsx";
-import type { ProductReviewList } from "@/types/products/productDetail";
-import { getProductReviews } from "@utils/hooks/getProductReviews";
+// import type { ProductReviewList } from "@/types/products/productDetail";
+// import { getProductReviews } from "@utils/hooks/getProductReviews";
 import { restApiFetch } from "@utils/bagisto/index";
 import {
   ProductDetailSkeleton,

+ 1 - 1
src/app/(public)/product/_components/ProductReviewSection.tsx

@@ -2,7 +2,7 @@ import ReviewDetail from "@/app/(public)/product/_components/review/ReviewDetail
 import { NoReview } from "@/app/(public)/product/_components/review/NoReview";
 // import { getProductReviews } from "@utils/hooks/getProductReviews";
 import type { ProductReviewList } from "@/types/products/productDetail";
-import React, { memo } from "react";
+import React from "react";
 // 组件入参TS规范
 interface ProductReviewSectionProps {
   productId: string;

+ 1 - 1
src/app/(public)/product/_components/popup/PriceModal.tsx

@@ -1,5 +1,5 @@
 "use client";
-import clsx from "clsx";
+// import clsx from "clsx";
 import { Price } from "@components/theme/ui/Price";
 
 // 价格数据类型,复用之前商品价格结构

+ 12 - 8
src/app/(public)/product/_components/question/ComponentsQuestionModal.tsx

@@ -1,11 +1,11 @@
 import { useState, useEffect } from "react";
 import { X } from "lucide-react";
 import { QaItem } from "./QAModal";
-interface WigAnswer {
-  id: string;
-  answer: string;
-  likeCount: number;
-}
+// interface WigAnswer {
+  // id: string;
+  // answer: string;
+  // likeCount: number;
+// }
 interface WigQuestionModalProps {
   open: boolean;
   onClose: () => void;
@@ -24,9 +24,13 @@ export default function ComponentsQuestionModal({
   const [commentText, setCommentText] = useState("");
 
   // 弹窗打开重置评论
-  useEffect(() => {
-    if (open) setCommentText("");
-  }, [open]);
+ useEffect(() => {
+  if (open && commentText !== "") {
+    queueMicrotask(() => {
+      setCommentText("");
+    });
+  }
+}, [open, commentText]);
 
   // 提交评论
   const handlePostComment = () => {

+ 2 - 2
src/app/(public)/product/_components/review/AddProductReviewForm.tsx

@@ -5,7 +5,7 @@ import { AddRatingStar } from "./AddRatingStar";
 import { Button } from "@components/common/button/Button";
 import ReviewImageUploader from "./ReviewImageUploader";
 import { useCustomToast } from "@utils/hooks/useToast";
-import { useProductReview } from "@utils/hooks/useProductReview";
+// import { useProductReview } from "@utils/hooks/useProductReview";
 import type {
   UploadImgItem,
   ReviewFormData,
@@ -24,7 +24,7 @@ export default function AddProductReviewForm({
   onCloseForm,
 }: AddProductReviewFormProps) {
   const { showToast } = useCustomToast();
-  const { createProductReview, isLoading } = useProductReview();
+  // const { createProductReview, isLoading } = useProductReview();
 
   // 图片状态
   const [imgList, setImgList] = useState<UploadImgItem[]>([]);

+ 2 - 1
src/app/(public)/product/_components/review/QuestionInputModal.tsx

@@ -9,7 +9,7 @@ interface QuestionInputModalProps {
 }
 
 export default function QuestionInputModal({
-  productId,
+  // productId,
   onCloseForm,
 }: QuestionInputModalProps) {
   const MAX_LENGTH = 300;
@@ -37,6 +37,7 @@ export default function QuestionInputModal({
       setContent("");
       onCloseForm();
     } catch (err) {
+      console.log('err-----------:',err);
       setErrorMsg("Submit failed, please try again");
     } finally {
       setLoading(false);

+ 6 - 6
src/app/(public)/product/_components/review/ReviewAdd.tsx

@@ -1,8 +1,8 @@
 "use client";
 
 import { useState } from "react";
-import { Modal, ModalContent } from "@heroui/modal";
-import AddProductReview from "./AddProductReview";
+// import { Modal, ModalContent } from "@heroui/modal";
+// import AddProductReview from "./AddProductReview";
 import { ReviewButton } from "@components/common/button/ReviewButton";
 import AddProductReviewForm from "./AddProductReviewForm";
 import QuestionInputModal from "./QuestionInputModal";
@@ -12,8 +12,8 @@ export default function ReviewAdd({ productId }: { productId: string }) {
   const [qusopen, setQueopen] = useState(false);
   const handleCloseForm = () => setOpen(false);
   const setShowForm = () => {
-    setOpen((prev) => true);
-    setQueopen((prev) => false);
+    setOpen(() => true);
+    setQueopen(() => false);
   };
   return (
     <>
@@ -21,8 +21,8 @@ export default function ReviewAdd({ productId }: { productId: string }) {
         <ReviewButton setShowForm={setShowForm} />
         <div
           onClick={() => {
-            setOpen((prev) => false);
-            setQueopen((prev) => true);
+            setOpen(() => false);
+            setQueopen(() => true);
           }}
           className="relative flex font-normal text-ly-14 leading-ly-24 text-[#1E3932FF] py-1 px-3.5  cursor-pointer h-fit items-center justify-center rounded-full bg-[#E1E8E6FF] p-4 tracking-wide mt-4"
         >

+ 12 - 8
src/app/(public)/product/_components/review/ReviewDetail.tsx

@@ -1,16 +1,20 @@
 "use client";
 
-import { Rating } from "@components/common/Rating";
+// import { Rating } from "@components/common/Rating";
 import { GridTileImage } from "@components/theme/ui/grid/Tile";
-import { formatDate, getInitials, getReviews } from "@/utils/helper";
+import { 
+  // formatDate, 
+  getInitials, 
+  // getReviews 
+} from "@/utils/helper";
 import { isArray } from "@/utils/type-guards";
 import { Avatar } from "@heroui/avatar";
-import { Tooltip } from "@heroui/tooltip";
+// import { Tooltip } from "@heroui/tooltip";
 import clsx from "clsx";
-import React, { FC, useState, useEffect, memo } from "react";
+import React, { FC, useState } from "react";
 import { ProductReviewNode } from "@/components/catalog/type";
 import ReviewModal from "./ReviewModal";
-import { ReviewTabType } from "@/types/products/review";
+// import { ReviewTabType } from "@/types/products/review";
 
 interface ProductReviewEdge {
   __typename: "ProductReviewEdge";
@@ -30,7 +34,7 @@ interface ReviewDetailProps {
 
 const ReviewDetail: FC<ReviewDetailProps> = ({
   reviewDetails,
-  totalReview,
+  // totalReview,
   productId,
   modalOpen,
   onClose,
@@ -112,9 +116,9 @@ const ReviewDetail: FC<ReviewDetailProps> = ({
                 (
                   {
                     name,
-                    title,
+                    // title,
                     comment,
-                    created_at,
+                    // created_at,
                     rating,
                     attachments,
                     customer,

+ 1 - 1
src/app/(public)/product/_components/review/ReviewImageUploader.tsx

@@ -1,5 +1,5 @@
 "use client";
-import { useState } from "react";
+// import { useState } from "react";
 import Image from "next/image";
 import { AddUploadImage } from "@components/common/icons/AddUploadImage";
 import { useCustomToast } from "@utils/hooks/useToast";

+ 5 - 5
src/app/(public)/product/_components/review/ReviewModal.tsx

@@ -1,5 +1,5 @@
 "use client";
-import React, { memo, useState, useRef, useEffect, useCallback } from "react";
+import React, {  useState, useRef, useEffect, useCallback } from "react";
 import {
   ReviewTabType,
   ProductReviewList,
@@ -12,7 +12,7 @@ import { clientFetch } from "@/lib/restApiClient";
 const PAGE_SIZE = 10;
 
 interface ReviewModalProps {
-  open: Boolean;
+  open: boolean;
   onClose: () => void;
   onChangeTab: (tabKey: string) => void;
   productId: string;
@@ -86,8 +86,8 @@ async function fetchReviewApi(
   //   });
   // }
   // 根据tab筛选数据
-  let filteredList = [...res?.data?.data];
-  let totalReview = res?.pagination?.total;
+  const filteredList = [...res?.data?.data];
+  const totalReview = res?.pagination?.total;
   // if (tab === "newest") {
   //   // 最新:创建时间倒序
   //   filteredList.sort(
@@ -174,7 +174,7 @@ const ReviewModal: React.FC<ReviewModalProps> = React.memo(
 
     // 筛选当前Tab展示的评论
     const filterReviewList = useCallback(() => {
-      let list = [...fullReviewList];
+      const list = [...fullReviewList];
       // if (activeTab === "newest") {
       //   list.sort(
       //     (a, b) =>

+ 1 - 1
src/app/(public)/search/_components/HotSearch.tsx

@@ -1,7 +1,7 @@
 'use client';
 
 import Link from 'next/link';
-import { createUrl } from '@/utils/helper';
+// import { createUrl } from '@/utils/helper';
 
 const hotTags = [
   {

+ 4 - 4
src/app/(public)/search/page.tsx

@@ -1,12 +1,12 @@
 import dynamicImport from "next/dynamic";
 import Grid from "@/components/theme/ui/grid/Grid";
-import NotFound from "@/components/theme/search/not-found";
+// import NotFound from "@/components/theme/search/not-found";
 import { isArray } from "@/utils/type-guards";
 import { serverGraphqlFetch } from "@utils/bagisto/index";
 import {
   GET_PRODUCTS,
-  GET_PRODUCTS_PAGINATION,
-  GET_FILTER_PRODUCTS,
+  // GET_PRODUCTS_PAGINATION,
+  // GET_FILTER_PRODUCTS,
   SEARCH_PRODUCTS,
 } from "@/graphql";
 import {
@@ -17,7 +17,7 @@ import { generateMetadataForPage, buildProductFilters } from "@/utils/helper";
 import SortOrder from "@/components/theme/filters/SortOrder";
 import { SortByFields } from "@/utils/constants";
 // import MobileFilter from "@/components/theme/filters/MobileFilter";
-import FilterList from "@/components/theme/filters/FilterList";
+// import FilterList from "@/components/theme/filters/FilterList";
 import {
   ProductsResponse,
   SearchProductsResponse,

+ 2 - 2
src/app/api/home/route.ts

@@ -3,9 +3,9 @@ import { restApiFetch } from "@/utils/bagisto";
 import { isBagistoError } from "@/utils/type-guards";
 import { getAuthToken } from "@/utils/helper";
 type Params = Promise<{ id: string }>;
-export async function GET(req: NextRequest, { params }: { params: Params }) {
+export async function GET(req: NextRequest, {  }: { params: Params }) {
   try {
-     const { id } = await params; // 解包拿到订单ID
+    //  const { id } = await params; // 解包拿到订单ID
     const guestToken = getAuthToken(req);
 
    const apiUrl = `/home`;

+ 2 - 2
src/components/common/button/ReviewButton.tsx

@@ -7,8 +7,8 @@ export const ReviewButton = ({ setShowForm, className }: { setShowForm: () => vo
     const router = useRouter();
     const handleAddReview = () => {
         if (IsGuest === "true" || IsGuest === null) {
-              setShowForm();
-            // router.push("/customer/login");
+            //   setShowForm();
+            router.push("/customer/login");
         } else {
             setShowForm();
         }

+ 1 - 0
src/components/layout/navbar/Search.tsx

@@ -37,6 +37,7 @@ export default function Search({
     const interval = setInterval(() => {
       setPlaceholderIndex(prev => (prev + 1) % placeholderList.length);
     }, 3000); // 每3秒切换一次
+    return () => clearInterval(interval);
   }, [placeholderList.length]);
     // 防抖跳转
   useEffect(() => {

+ 1 - 1
src/components/layout/navbar/SearchPop.tsx

@@ -17,7 +17,7 @@ interface SearchPopProps {
 }
 
 export default function SearchPop({ open, onClose }: SearchPopProps) {
-  const { data, loading, error, searchProducts } = useSearchProduct();
+  const { data, error, searchProducts } = useSearchProduct();
   const [keyword, setKeyword] = useState("");
   const debounceTimerRef = useRef<NodeJS.Timeout | null>(null);
 

+ 22 - 14
src/components/theme/filters/NewMobileFilter.tsx

@@ -16,7 +16,7 @@ import {
   XMarkIcon,
 } from "@heroicons/react/24/outline";
 
-import { useEffect, useState } from "react";
+import { useEffect, useState, useRef } from "react";
 
 interface MobileFilterProps {
   filterAttributes: any[];
@@ -32,6 +32,8 @@ export default function MobileFilter({
   onChange,
 }: MobileFilterProps) {
   const { isOpen, onOpen, onOpenChange } = useDisclosure();
+  // 记录上一次抽屉状态,用来捕获【关闭→打开】瞬间
+  const prevIsOpenRef = useRef(isOpen);
 
   /**
    * 弹窗里面临时选择
@@ -46,23 +48,29 @@ export default function MobileFilter({
    * 打开弹窗同步父组件状态
    */
   useEffect(() => {
-    if (isOpen) {
-      console.log('dadadadadadadadisopen');
-      
-      setTempFilters(filters);
-
-      const expand: any = {};
-
-      filterAttributes.forEach((attr) => {
-        expand[attr.code] = true;
+    // 仅从关闭切换到打开时执行
+    if (!prevIsOpenRef.current && isOpen) {
+      console.log("dadadadadadadadisopen");
+      // 使用 queueMicrotask 把状态更新延后,避开同步setState警告
+      queueMicrotask(() => {
+        // 浅拷贝,断开引用
+        setTempFilters({ ...filters });
+
+        const expand: Record<string, boolean> = {};
+        filterAttributes.forEach((attr) => {
+          expand[attr.code] = true;
+        });
+        setExpandedGroups(expand);
       });
-
-      setExpandedGroups(expand);
     }
-    // 打印父组件实时传入的筛选(每次filters/isOpen变化都会打印)
+    prevIsOpenRef.current = isOpen;
+
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [isOpen]);
+    useEffect(() => {
     console.log("【父组件传入筛选filters】", filters);
     console.log("【抽屉是否打开isOpen】", isOpen);
-  }, [isOpen, filters, filterAttributes]);
+  }, [isOpen, filters]);
 
   /**
    * 单选