SwiperGroup.tsx 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. "use client";
  2. import Box from "@/components/Box";
  3. import { FC, PropsWithChildren, ReactNode, useRef } from "react";
  4. import { Swiper, SwiperClass, SwiperSlide } from "swiper/react";
  5. import { Category, GameListRep } from "@/api/home";
  6. import { CardProps } from "@/components/Card/Card";
  7. import GroupCard, { GroupProps } from "@/components/Card/GroupCard";
  8. import clsx from "clsx";
  9. import { useTranslations } from "next-intl";
  10. import styles from "./style.module.scss";
  11. type TodoHandler = (item: Category) => void;
  12. interface SwiperGroupProps extends GroupProps, CardProps {
  13. group: Category;
  14. page?: number;
  15. // style
  16. bg?: boolean;
  17. visibleTitle?: boolean;
  18. // todos
  19. visibleTodos?: boolean;
  20. todoHandler?: TodoHandler;
  21. // icon
  22. offsetX?: number;
  23. offsetY?: number;
  24. // SwiperSlide
  25. slideRender?: (data: GameListRep[]) => ReactNode;
  26. }
  27. const HomeSwiper: FC<PropsWithChildren<SwiperGroupProps>> = (props) => {
  28. const {
  29. group,
  30. page = 3,
  31. todoHandler,
  32. bg = true,
  33. visibleTitle = true,
  34. visibleTodos = true,
  35. slideRender,
  36. ...other
  37. } = props;
  38. const t = useTranslations("HomePage");
  39. const swiperRef = useRef<SwiperClass | null>(null);
  40. const bodyClass = clsx(
  41. {
  42. ["bg-[#1a1a1a]"]: bg,
  43. },
  44. "mb-[0.11rem]"
  45. );
  46. if (!group.game_list) return;
  47. const lineNum = page * group.line_num;
  48. const gameList = group.game_list.slice(0, group.line_config_amount);
  49. const swiperData = Array(gameList.length ? Math.ceil(gameList.length / lineNum) : 0)
  50. .fill(0)
  51. .map((_, index) => {
  52. return {
  53. key: index,
  54. data: gameList.slice(index * lineNum, index * lineNum + lineNum).map(subItem => ({ ...subItem, category_name: group.category_name }))
  55. };
  56. });
  57. const prev = () => {
  58. swiperRef.current!.slidePrev();
  59. };
  60. const next = () => {
  61. swiperRef.current!.slideNext();
  62. };
  63. const iconClass = clsx(styles.mainLeftIcon, "pro-iconfont", `pro-${group.icon}`);
  64. return (
  65. <div>
  66. {visibleTitle && (
  67. <Box none>
  68. <div className={styles.mainTitle}>
  69. <div className={styles.mainLeft}>
  70. <div className={iconClass}></div>
  71. <div className={styles.marginLeftTitle}>{group.category_name}</div>
  72. <div className={styles.marginLeftTag}> {t("gameTag")}</div>
  73. </div>
  74. <img
  75. src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAATcAAAA5CAYAAABTX2z2AAAACXBIWXMAAAsTAAALEwEAmpwYAAAF6GlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNi4wLWMwMDIgNzkuMTY0NDg4LCAyMDIwLzA3LzEwLTIyOjA2OjUzICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIyLjAgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyMy0wMy0wOVQxNTozNDowMSswODowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjMtMDMtMDlUMTU6MzQ6MjcrMDg6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjMtMDMtMDlUMTU6MzQ6MjcrMDg6MDAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6YmIzNWRiOGYtMjE1Yi04NDRiLTg0NDAtNjFiYjI1YWU0ZjIyIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjQ0MzZBMDQ2QkU0QzExRUQ4MURCRDI3MkM0QzA2QzVGIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6NDQzNkEwNDZCRTRDMTFFRDgxREJEMjcyQzRDMDZDNUYiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0NDM2QTA0M0JFNEMxMUVEODFEQkQyNzJDNEMwNkM1RiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0NDM2QTA0NEJFNEMxMUVEODFEQkQyNzJDNEMwNkM1RiIvPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDpiYjM1ZGI4Zi0yMTViLTg0NGItODQ0MC02MWJiMjVhZTRmMjIiIHN0RXZ0OndoZW49IjIwMjMtMDMtMDlUMTU6MzQ6MjcrMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMi4wIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5BhExDAAADo0lEQVR4nO3du4tcVQDH8c9KiCJpfBBhxkLUyge2Qv4Ewc42ghZifMT4RGPnAzXRRGMaMWBrI4iVCCqKCBpERXw/kDhgLMQ1nSGuxZlBI7t377z2ztz7+8AwU5wz91Rfzn3s7Eqv1/sdZ7CKP3By+DqBH/AtvsSf5mwwGMz7EBHREdtwwfDzxRXj1vAdjuM9vKNELyJiIa30er21Cef+iNfxGj5QAji17N4iYhbOmWLu5diH95Vd3X7snMWiIiKmNU3c/usKPI6f8TKunPSL+v3+jJYUEV02q7iNnIdb8RWO4dJJviSBi4hpzTpuI9twixK5/Th3TseJiFjXvOI2skM5Xf0E148zMbu3iJjGvOM2cpVyR/UJZVdXSwIXEZPaqriNjvUI3jXhtbiIiLq2Mm4ju5SHgXfVGZzdW0RMoom4wSV4G7sbOn5EtFxTcYPteAUPbzYwu7eIGFeTcYMVPIkDw88bSuAiYhxNx23kfhyxSeAiIupalLjBHTiqInDZvUVEXYsUN7hdAhcRM7BocaME7kUJXERMYRHjBnskcBExhUWNGyVwlTcZEriI2Mgix41ykyGBi4ixLXrcKIF7QQIXEWNYhrjBnXheAhcRNS1L3OAuCVxE1LRMcaME7rAELiI2sWxxg7txSAIXERWWMW6wVwIXERWWNW6UwD0ngYuIdSxz3OAeJXAbSuAiumnZ40YJ3KGqAQlcRPe0IW5kBxcR/9OWuME+CVxEDLUpbiRwETHUtrhRAvds1YAELqL92hg3uBcHqwYkcBHt1ta4wX0SuIjOanPcKIE7UDUggYtop7bHjfJvA5+pGpDARbRPF+IGD0jgIjqlK3GjBO7pqgEJXER7dClu8CCeqhqQwEW0Q9fiBg9J4CJar4txowTuoPxcUkRrrfR6vbWmF9GgY7gNZ6oGDQaDrVlNRMxM1+MGr2I3/tpsYCIXsTwSt+JN3IRTdQYnchGLL3H71xe4ET/VnZDIRSyurt5QWM81+Bg31J3Q7/dz4yFiQSVuZ7sIbyh/zbC97qRELmLx5LR0Y5/h5uH7WHK6GtG87Nw2dh2OK78qsmOcidnJRTQvO7d6fsNjeEmNR0Ymkd1exGxl51bPThzBN9iD85tdTkRsJnEbz2U4ihM4jKubXExEbCxxm8yF2Ks8G/cpHsW1TS4oIs6Wa26z9Svewof4CJ/jdJ2JueYWMVuJ23ydxvf4evg+wC84idXh6xT+HgwGq00tMqKN/gHg555imkrLwAAAAABJRU5ErkJggg=="
  76. alt=""
  77. />
  78. <div className={styles.mainRight}>
  79. {visibleTodos && (
  80. <div onClick={() => todoHandler && todoHandler(group)}>
  81. Todos
  82. <span className={styles.marginRightCount}>{group.to_tal}</span>
  83. </div>
  84. )}
  85. <div onClick={prev}>
  86. <span className="iconfont icon-xiangzuo1"></span>
  87. </div>
  88. <div onClick={next}>
  89. <span className="iconfont icon-xiangyou1"></span>
  90. </div>
  91. </div>
  92. </div>
  93. </Box>
  94. )}
  95. <Box none className={bodyClass}>
  96. <Box>
  97. <Swiper
  98. spaceBetween={10}
  99. slidesPerView={1}
  100. onSwiper={(swiper) => {
  101. swiperRef.current = swiper;
  102. }}
  103. loop
  104. >
  105. {swiperData?.map((data, index) => (
  106. <SwiperSlide key={data.key}>
  107. {slideRender ? (
  108. slideRender(data.data)
  109. ) : (
  110. <GroupCard
  111. data={data.data}
  112. {...other}
  113. groupType={group.bet_type}
  114. ></GroupCard>
  115. )}
  116. </SwiperSlide>
  117. ))}
  118. </Swiper>
  119. </Box>
  120. </Box>
  121. </div>
  122. );
  123. };
  124. export default HomeSwiper;