Преглед на файлове

sales-raking-scroll-home

tuyetnhi преди 1 година
родител
ревизия
2d2df95621

+ 3 - 0
package.json

@@ -88,5 +88,8 @@
     "webpack-dev-server": "^3.10.3",
     "webpack-merge": "^4.2.2",
     "yarn": "^1.22.17"
+  },
+  "dependencies": {
+    "currency.js": "^2.0.4"
   }
 }

+ 7 - 0
src/@types/index.d.ts

@@ -308,6 +308,13 @@ declare module 'metarare' {
         name: string;
         thumbnail_image: string;
     }
+
+    export interface ISalesRanking {
+        id: number;
+        name: string;
+        thumbnail_image: string;
+        total_revenue: number;
+    }
 }
 
 declare module '*.svg';

+ 60 - 0
src/components/common/SaleRankingCard.tsx

@@ -0,0 +1,60 @@
+import classNames from "classnames/bind";
+import { ISalesRanking } from "metarare";
+import * as React from "react";
+import Img from "./Img";
+import styles from "./SalesRankingCard.scss";
+import currency from "currency.js";
+
+const cx = classNames.bind(styles);
+
+export interface ISalesRankingCardProps extends ISalesRanking {
+  className: string;
+}
+
+export default function SalesRankingCard({
+  id: rank,
+  name,
+  thumbnail_image,
+  className,
+  total_revenue,
+}: ISalesRankingCardProps) {
+  const renderColor = () => {
+    if (rank === 1) return "#ffd700";
+    if (rank === 2) return "#c0c0c0";
+    if (rank === 3) return "#cd7f32";
+    return "#3d3d3d";
+  };
+  return (
+    <div className={cx("sales_ranking_card", className)}>
+      <div
+        className={cx("ranking")}
+        style={{
+          background: renderColor(),
+        }}
+      >
+        <span>{rank}</span>
+      </div>
+      <div className={cx("card_wrap")}>
+        <div className={cx("thumb_area")}>
+          <Img
+            src={thumbnail_image}
+            alt=""
+            width="260"
+            height="260"
+            className={cx("thumb")}
+          />
+        </div>
+        <div className={cx("info_area")}>
+          <div className={cx("total")}>
+            Total:{" "}
+            {currency(total_revenue).format({
+              symbol: "$",
+              precision: 0,
+            })}
+          </div>
+          <div className={cx("name")}>{name}</div>
+        </div>
+      </div>
+    </div>
+  );
+}

+ 69 - 0
src/components/common/SalesRankingCard.scss

@@ -0,0 +1,69 @@
+@import "/assets/css/_lib";
+
+.sales_ranking_card {
+    position: relative;
+
+    &.scroll {
+        position: relative;
+        display: inline-block;
+        padding: 0 10px;
+        width: calc(50vw - 30px);
+        vertical-align: top;
+
+        @include pc {
+            width: 14%;
+            box-sizing: border-box;
+        }
+    }
+    & > .ranking{
+        position: absolute;
+        top: 10%;
+        left: 20%;
+        width: 12%;
+        aspect-ratio: 1;
+        border-radius: 50%;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        font-size: 14px;
+        color: #fff;
+        z-index: 1;
+        font-family: 'HelveticaNeue', 'Helvetica', arial, 'sans-serif' !important;
+    }
+}
+
+.card_wrap {
+    position: relative;
+    overflow: hidden;
+    padding-bottom: 40px;
+    border-radius: 16px;
+    background-color: #fff;
+    box-sizing: border-box;
+
+    &>.thumb_area {
+        padding: 14%;
+
+        &>.thumb {
+            border-radius: 50%;
+            width: 100%;
+            aspect-ratio: 1;
+            height: auto;
+        }
+    }
+
+    &>.info_area {
+        text-align: center;
+        font-size: large;
+
+        &>.name {}
+
+        &>.total {
+            font-size: 14px;
+            font-weight: 400;
+            line-height: 20px;
+            color: #888;
+            cursor: pointer;
+            margin-left: 20px;
+        }
+    }
+}

+ 0 - 1
src/components/mobile/ArtistScrollList.tsx

@@ -3,7 +3,6 @@ import classNames from 'classnames/bind';
 
 import Flicking from '@egjs/react-flicking';
 import styles from './NFTScrollList.scss';
-import NFTCard from '@src/components/common/NFTCard';
 import { IArtist, INFT } from 'metarare';
 import ArtistCard from '../common/ArtistCard';
 

+ 29 - 0
src/components/mobile/SalesRankingScrollList.tsx

@@ -0,0 +1,29 @@
+import React from "react";
+import classNames from "classnames/bind";
+
+import Flicking from "@egjs/react-flicking";
+import styles from "./NFTScrollList.scss";
+import { ISalesRanking, INFT } from "metarare";
+import SalesRankingCard from "../common/SaleRankingCard";
+
+const cx = classNames.bind(styles);
+
+interface IOwnProps {
+  list: ISalesRanking[];
+}
+
+const SalesRankingScrollList: React.FC<IOwnProps> = ({ list }) => {
+  return (
+    <div className={cx("nft_scroll")}>
+      <Flicking align="prev">
+        {list.map((item, index) => (
+          <div key={`${item.id}_${index}`} className={cx("nft_panel")}>
+            <SalesRankingCard {...item} className="scroll" />
+          </div>
+        ))}
+      </Flicking>
+    </div>
+  );
+};
+
+export default SalesRankingScrollList;

+ 74 - 0
src/components/pc/SalesRankingScrollList.tsx

@@ -0,0 +1,74 @@
+import React, { useEffect, useState } from 'react';
+import classNames from 'classnames/bind';
+
+import Flicking, { ViewportSlot } from '@egjs/react-flicking';
+import { Arrow } from '@egjs/flicking-plugins';
+import styles from './NFTScrollList.scss';
+import { ISalesRanking, INFT } from 'metarare';
+import SalesRankingCard from '../common/SaleRankingCard';
+
+const cx = classNames.bind(styles);
+
+interface IOwnProps {
+  list: ISalesRanking[];
+};
+
+const PANEL_COUNT = 7;
+
+const SalesRankingScrollList: React.FC<IOwnProps> = ({
+  list
+}) => {
+  const plugins = [new Arrow()];
+  const [panel, setPanel] = useState<ISalesRanking[][]>([]);
+
+  useEffect(() => {
+    if (list?.length) {
+      const panel = [];
+      for (let i = 0; i < list.length; i += PANEL_COUNT) {
+        panel.push(list.slice(i, i + PANEL_COUNT));
+      }
+
+      setPanel(panel);
+    }
+  }, [list]);
+
+  return (
+    <div className={cx("nft_scroll")}>
+      {!!panel.length && (
+        <Flicking plugins={plugins}>
+          {panel?.map((list, index) => (
+            <div className={cx("nft_panel")} key={index}>
+              {list.map((item, index) => (
+                <SalesRankingCard
+                  {...item}
+                  key={index}
+                  className="scroll"
+                />
+              ))}
+            </div>
+          ))}
+          <ViewportSlot>
+            <div className={cx("pc_wrapper")}>
+              <span
+                className={cx(
+                  "flicking-arrow-prev",
+                  "btn_flicking",
+                  "main_prev"
+                )}
+              ></span>
+              <span
+                className={cx(
+                  "flicking-arrow-next",
+                  "btn_flicking",
+                  "main_next"
+                )}
+              ></span>
+            </div>
+          </ViewportSlot>
+        </Flicking>
+      )}
+    </div>
+  );
+};
+
+export default SalesRankingScrollList;

+ 82 - 0
src/containers/common/SalesRankingscrollList.tsx

@@ -0,0 +1,82 @@
+import MobileSalesRankingScrollList from "@src/components/mobile/SalesRankingScrollList";
+import PCSalesRankingScrollList from "@src/components/pc/SalesRankingScrollList";
+import { ISalesRanking } from "metarare";
+import * as React from "react";
+
+export interface ISalesRankingScrollListProps {}
+
+export default function SalesRankingScrollList(props: ISalesRankingScrollListProps) {
+  return (
+    <>
+      <div className={"mo_wrapper"}>
+        <MobileSalesRankingScrollList list={dataFake} />
+      </div>
+      <div className={"pc_wrapper"}>
+        <PCSalesRankingScrollList list={dataFake} />
+      </div>
+    </>
+  );
+}
+
+const dataFake: ISalesRanking[] = [
+  {
+    id: 1,
+    name: "John Doe",
+    thumbnail_image: "https://picsum.photos/300/300",
+    total_revenue: 100000,
+  },
+  {
+    id: 2,
+    name: "Kasper Henderson",
+    thumbnail_image: "https://picsum.photos/300/300",
+    total_revenue: 90000,
+  },
+  {
+    id: 3,
+    name: "Cooper Lynn",
+    thumbnail_image: "https://picsum.photos/300/300",
+    total_revenue: 80000,
+  },
+  {
+    id: 4,
+    name: "Iris Stein",
+    thumbnail_image: "https://picsum.photos/300/300",
+    total_revenue: 70000,
+  },
+  {
+    id: 5,
+    name: "Leland Richards",
+    thumbnail_image: "https://picsum.photos/300/300",
+    total_revenue: 60000,
+  },
+  {
+    id: 6,
+    name: "Octavia Norris",
+    thumbnail_image: "https://picsum.photos/300/300",
+    total_revenue: 50000,
+  },
+  {
+    id: 7,
+    name: "Leland Richards",
+    thumbnail_image: "https://picsum.photos/300/300",
+    total_revenue: 40000,
+  },
+  {
+    id: 8,
+    name: "Octavia Norris",
+    thumbnail_image: "https://picsum.photos/300/300",
+    total_revenue: 30000,
+  },
+  {
+    id: 9,
+    name: "Leland Richards",
+    thumbnail_image: "https://picsum.photos/300/300",
+    total_revenue: 20000,
+  },
+  {
+    id: 10,
+    name: "Octavia Norris",
+    thumbnail_image: "https://picsum.photos/300/300",
+    total_revenue: 10000,
+  },
+];

+ 9 - 0
src/pages/Home.scss

@@ -23,4 +23,13 @@
           line-height: 32px;
       }
   }
+}
+
+.see_more{
+    font-size: 14px;
+    font-weight: 400;
+    line-height: 20px;
+    color: #005abc;
+    cursor: pointer;
+    margin-left: 20px;
 }

+ 7 - 3
src/pages/Home.tsx

@@ -12,6 +12,7 @@ import { fetchHome } from '@src/store/reducers/HomeReducer';
 import Loading from '@src/components/common/Loading';
 import useMore from '@src/hooks/useMore';
 import ArtistsScrollList from '@src/containers/common/ArtistsScrollList';
+import SalesRankingScrollList from '@src/containers/common/SalesRankingscrollList';
 
 const cx = classNames.bind(styles);
 
@@ -91,10 +92,13 @@ const Home: React.FC = () => {
             <strong className={cx('home_title')}>탐색하기 🔍</strong>
             <ExploreContentContainer list={filterProps.exploreList} filterProps={filterProps} handler={filterHandler} onClickMore={onClickMore} showMore={showMore} isLoaded={isExploreListLoaded} />
           </div> */}
-           <div className={cx('home_group')}>
-            <strong className={cx('home_title')}>Registered Artists 🔍</strong>
+          <div className={cx('home_group')}>
+            <strong className={cx('home_title')}>Registered Artists 🧑‍🎨</strong>
             <ArtistsScrollList />
-            {/* <ExploreContentContainer list={filterProps.exploreList} filterProps={filterProps} handler={filterHandler} onClickMore={onClickMore} showMore={showMore} isLoaded={isExploreListLoaded} /> */}
+          </div>
+          <div className={cx('home_group')}>
+            <strong className={cx('home_title')}>Sales Ranking 🏆 <a className={cx('see_more')}>Sea more</a></strong>
+            <SalesRankingScrollList />
           </div>
         </>
       )}

+ 5 - 0
yarn.lock

@@ -4172,6 +4172,11 @@ csstype@^3.0.2:
   resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.8.tgz#d2266a792729fb227cd216fb572f43728e1ad340"
   integrity sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==
 
+currency.js@^2.0.4:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/currency.js/-/currency.js-2.0.4.tgz#a8a4d69be3b2e509bf67a560c78220bc04809cf1"
+  integrity sha512-6/OplJYgJ0RUlli74d93HJ/OsKVBi8lB1+Z6eJYS1YZzBuIp4qKKHpJ7ad+GvTlWmLR/hLJOWTykN5Nm8NJ7+w==
+
 cyclist@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"