HomeNewArrival.tsx 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import { Swiper, SwiperSlide } from "swiper/react";
  2. import { Navigation, Pagination } from "swiper/modules";
  3. import { OpenAddToCartModalButton } from "@/components/common/AddToCartModal/OpenAddToCartModalButton";
  4. // 导入Swiper基础样式
  5. import "swiper/css";
  6. import "swiper/css/navigation";
  7. import type {HomeProduct} from "@/types/home/type"
  8. interface NewArrivalProps {
  9. newArrival: HomeProduct[];
  10. }
  11. const HomeNewArrival = ({ newArrival }: NewArrivalProps) => {
  12. if (!newArrival || newArrival.length === 0) return null;
  13. // 4. 真实数据按每6个拆分一组,替换原来的模拟拆分逻辑
  14. const chunkSize = 6;
  15. const productBlocks: HomeProduct[][] = [];
  16. for (let i = 0; i < newArrival.length; i += chunkSize) {
  17. productBlocks.push(newArrival.slice(i, i + chunkSize));
  18. }
  19. return (
  20. <div className="w-full max-w-[1200px] mx-auto px-4 py-8">
  21. {/* 标题 */}
  22. <h2 className="text-2xl font-bold mb-6">New Arrival</h2>
  23. {/* Swiper容器 */}
  24. <Swiper
  25. slidesPerView={1}
  26. spaceBetween={20}
  27. modules={[Navigation, Pagination]}
  28. pagination={{
  29. el: ".custom-pagination",
  30. clickable: true,
  31. renderBullet: (index, className) => {
  32. // 所有分页默认底色为 #E5E5E5
  33. return `<span class="${className} w-6 h-[5px] rounded-full mx-1 bg-[#E5E5E5]"></span>`;
  34. },
  35. // 激活时强制覆盖底色,加 !important 提高权重
  36. bulletActiveClass: "!bg-[#333]",
  37. }}
  38. className="relative"
  39. >
  40. {/* 渲染2个滑动块 */}
  41. {productBlocks.map((block, blockIndex) => (
  42. <SwiperSlide key={blockIndex} className="!px-0">
  43. {/* 每个块:6个产品,2列布局 */}
  44. <div className="grid grid-cols-2 gap-4">
  45. {block.map((product) => (
  46. <div key={product.id} className="flex flex-col gap-2">
  47. {/* 产品图片 */}
  48. <img
  49. src={product.image_url}
  50. alt={product.name}
  51. className="w-full h-auto object-cover rounded-sm"
  52. />
  53. {/* 产品标题 */}
  54. <p className="text-sm text-gray-800 truncate">
  55. {product.name}
  56. </p>
  57. {/* 评分 + 评论数 */}
  58. <div className="flex items-center gap-1">
  59. <div className="flex">
  60. {/* 星级图标(简化版,可替换为真实星星图标) */}
  61. {[1, 2, 3, 4, 5].map((star) => (
  62. <svg
  63. key={star}
  64. className="w-4 h-4 text-yellow-400"
  65. fill="currentColor"
  66. viewBox="0 0 20 20"
  67. >
  68. <path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
  69. </svg>
  70. ))}
  71. </div>
  72. <span className="text-xs text-gray-600">
  73. {product.review_count}
  74. </span>
  75. </div>
  76. {/* 价格 + 购物车图标 */}
  77. <div className="flex items-center justify-between">
  78. <div className="flex items-center gap-1">
  79. <span className="font-semibold">${product.min_price}</span>
  80. <span className="text-xs text-gray-500 line-through">
  81. ${product.price}
  82. </span>
  83. </div>
  84. {/* 购物车图标 */}
  85. <OpenAddToCartModalButton
  86. productId={product.id}
  87. icon={
  88. <svg
  89. xmlns="http://www.w3.org/2000/svg"
  90. width="32"
  91. height="32"
  92. viewBox="0 0 32 32"
  93. fill="none"
  94. >
  95. <rect
  96. x="0"
  97. y="0"
  98. width="32"
  99. height="32"
  100. rx="8"
  101. fill="#036141"
  102. ></rect>
  103. <path
  104. stroke="rgba(255, 255, 255, 1)"
  105. stroke-width="1.3333333333333333"
  106. stroke-linejoin="round"
  107. stroke-linecap="round"
  108. d="M6.40039 7.79993L8.03372 7.79993L8.73372 10.5999M8.73372 10.5999L11.0671 19.9333L23.2004 19.9333L25.5337 10.5999L8.73372 10.5999Z"
  109. ></path>
  110. <ellipse
  111. cx="11.066040515899658"
  112. cy="23.199928283691406"
  113. rx="1.4000248908996582"
  114. ry="1.4000015258789062"
  115. stroke="rgba(255, 255, 255, 1)"
  116. stroke-width="1.3333333333333333"
  117. stroke-linejoin="round"
  118. stroke-linecap="round"
  119. ></ellipse>
  120. <ellipse
  121. cx="23.1998291015625"
  122. cy="23.199928283691406"
  123. rx="1.4000244140625"
  124. ry="1.4000015258789062"
  125. stroke="rgba(255, 255, 255, 1)"
  126. stroke-width="1.3333333333333333"
  127. stroke-linejoin="round"
  128. stroke-linecap="round"
  129. ></ellipse>
  130. <path
  131. stroke="rgba(255, 255, 255, 1)"
  132. stroke-width="1.3333333333333333"
  133. stroke-linejoin="round"
  134. stroke-linecap="round"
  135. d="M15.2656 15.2665L18.999 15.2665"
  136. ></path>
  137. <path
  138. stroke="rgba(255, 255, 255, 1)"
  139. stroke-width="1.3333333333333333"
  140. stroke-linejoin="round"
  141. stroke-linecap="round"
  142. d="M17.1348 17.1332L17.1348 13.3999"
  143. ></path>
  144. </svg>
  145. }
  146. />
  147. </div>
  148. </div>
  149. ))}
  150. </div>
  151. </SwiperSlide>
  152. ))}
  153. {/* 自定义分页器容器(底部小按钮) */}
  154. <div className="custom-pagination flex justify-center mt-4"></div>
  155. </Swiper>
  156. </div>
  157. );
  158. };
  159. export default HomeNewArrival;