HomeNewArrival.tsx 7.1 KB

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