import React, { useEffect, useState } from "react";
import { ItxList } from "@app/_components/transactionTable/ineterface";
import { Iitem } from "@app/(page)/nft/collections/interface";
const usePagination = (txList: any) => {
const [page, setPage] = useState<number>(1);
const [pageTxList, setPageTxList] = useState<ItxList[] | Iitem[] | null>(
null
);
const [maxPage, setMaxPage] = useState<number>(0);
const pageHandler = (selectedPage: number) => {
if (selectedPage > 0 && selectedPage < maxPage + 1) {
setPage(selectedPage);
}
};
useEffect(() => {
setMaxPage(Math.ceil((txList?.length as number) / 25));
if (page === maxPage) {
setPageTxList(txList?.slice((page - 1) * 25));
} else {
setPageTxList(txList?.slice((page - 1) * 25, page * 25));
}
}, [page, txList, maxPage]);
return {
page,
pageHandler,
maxPage,
pageTxList,
};
};
export default usePagination;
/* eslint-disable @next/next/no-img-element */
"use client";
import React, { useEffect, useState } from "react";
import Image from "next/image";
import { IAddInfo, ItxList, TxListProps } from "./ineterface";
import { createPortal } from "react-dom";
import AdditionalInfo from "./additionalInfo";
import TxList from "./txListContainer";
import usePagination from "@app/_hooks/usePagination";
import Pagination from "../pagination/Pagiation";
const TxListWrap: React.FC<TxListProps> = ({ txList }) => {
const [addInfoModal, setAddInfoModal] = useState<Element | null>(null);
const [isToggled, setIsToggled] = useState<boolean>(false);
const { maxPage, page, pageHandler, pageTxList } = usePagination(txList);
useEffect(() => {
setAddInfoModal(document.getElementById("portal"));
}, [isToggled]);
// 실제에서는 react-query로 가져올 예정
const [addInfoTempData, setAddInfoTempData] = useState<IAddInfo>({
status: "Success",
transactionFee: "0.0000000000231",
gasInfo: "293840",
gasLimit: "318840",
nonce: "0",
blockNum: "18497",
position: "18",
});
const toggleHandler = () => {
setIsToggled(!isToggled);
};
return (
<div className="mt-10 h-auto max-h-[600px]">
<div className=" overflow-x-auto h-auto max-h-[500px]">
<div className="w-[300%] h-8 border-b border-gray flex ">
<div className="w-[5%] flex justify-center items-center ">?</div>
<div className=" w-[20%] flex justify-center items-center ">
Txn Hash
</div>
<div className=" w-[10%] flex justify-center items-center ">
Method
</div>
<div className=" w-[10%] flex justify-center items-center ">
Block
</div>
<div className=" w-[10%] flex justify-center items-center ">Age</div>
<div className=" w-[20%] flex justify-center items-center ">
From
</div>
<div className=" w-[20%] flex justify-center items-center ">To</div>
<div className=" w-[10%] flex justify-center items-center ">
Value
</div>
</div>
<TxList
pageTxList={pageTxList as ItxList[]}
toggleHandler={toggleHandler}
/>
{isToggled && addInfoModal
? createPortal(
<AdditionalInfo
addInfoTempData={addInfoTempData}
toggleHandler={toggleHandler}
/>,
addInfoModal
)
: ""}
</div>
<Pagination page={page} pageHandler={pageHandler} maxPage={maxPage} />
</div>
);
};
export default TxListWrap;
"use client";
import React, { useState } from "react";
import ItemTitle from "@app/_components/itemTitle";
import { INftTxDetailProps } from "./interface";
import ItemTableWrap from "@app/_components/itemTable";
import OverViewInfo from "./_contents/OverViewInfo";
import MarketInfo from "./_contents/MarketInfo";
import OtherInfo from "./_contents/OtherInfo";
import TxListWrap from "@app/_components/transactionTable";
import { ItxList } from "@app/_components/transactionTable/ineterface";
import TabWrap from "@app/_components/tabComponent/TabWrap";
import TabButton from "@app/_components/tabComponent/Tab";
import NFTInfo from "./_contents/Info";
const NftTxDetail: React.FC<INftTxDetailProps> = ({ params }) => {
const tempDataArr: ItxList[] = Array.from({ length: 105 }, (ele, index) => ({
age: "asd",
block: "123124124",
from: "0x12312kj312kjb3jk",
to: "0xqweqwnekjads2asdk2",
method: "Transfer",
txHash: "0x123fjafk231s",
value: index.toString(),
}));
const [toggleLabelNum, setToggleLabelNum] = useState<string | null>(
"Transfers"
);
const toggleHandler = (label: string) => {
setToggleLabelNum(label);
};
const componentHandler = (label: string) => {
if (label === "Transfers") {
console.log("Transfers");
return <TxListWrap txList={tempDataArr} />;
} else if (label === "Info") {
return <NFTInfo />;
} else {
return <></>;
}
};
return (
<div className="bg-mainBackGroundColor ">
<ItemTitle title={params.nftId} />
<div className="w-20 h-8 m-6 border-2 border-white bg-white rounded-xl font-bold flex justify-center items-center text-sm">
ERC-721
</div>
<ItemTableWrap>
<OverViewInfo />
</ItemTableWrap>
<ItemTableWrap>
<MarketInfo />
</ItemTableWrap>
<ItemTableWrap>
<OtherInfo />
</ItemTableWrap>
<div className="flex overflow-x-auto flex-nowrap py-5">
<TabButton
label="Transfers"
toggleLabelNum={toggleLabelNum}
toggleHandler={toggleHandler}
/>
<TabButton
label="Holders"
toggleLabelNum={toggleLabelNum}
toggleHandler={toggleHandler}
/>
<TabButton
label="Inventory"
toggleLabelNum={toggleLabelNum}
toggleHandler={toggleHandler}
/>
<TabButton
label="Info"
toggleLabelNum={toggleLabelNum}
toggleHandler={toggleHandler}
/>
</div>
{componentHandler(toggleLabelNum as string)}
</div>
);
};
export default NftTxDetail;
contents 폴더는 다음과 같다.
'use client'
import ItemTableWrap from '@app/_components/itemTable'
import usePagination from '@app/_hooks/usePagination'
import React from 'react'
const NFTHolders = () => {
const tempNftData=Array.from({length:40},()=>{
})
// const {}=usePagination()
return (
<ItemTableWrap>
</ItemTableWrap>
)
}
export default NFTHolders
import React from "react";
import ItemTableWrap from "@app/_components/itemTable";
const NFTInfo = () => {
return (
<ItemTableWrap>
<h1 className=" font-bold text-lg">OverView</h1>
<p className="mt-5 overflow-y-scroll">
[Note - Citizens with Reward Rates of 1 do not have Vaults. A Vault can
be attached to increase Yield for BYTES 2.0 Staking. Citizens with
Reward Rates of 2 or above have Vaults.] Upload complete. Wake up,
Citizen. The road ahead is long, so strap in. A new world awaits us. Neo
Tokyo is a collection of VCs, developers, token founders, and highly
proficient builders all gathered in one exclusive area of web3. Our
calling at Neo Tokyo is to prepare and be well positioned at the
forefront of the metaverse revolution, once it inevitably arrives.
https://neotokyo.codes
</p>
</ItemTableWrap>
);
};
export default NFTInfo;
import React from "react";
const MarketInfo = () => {
return (
<div className="w-full h-full flex flex-col items-start">
<div className="m-5 text-lg font-bold h-1/4">Market</div>
<div className="m-5 h-1/4">
<div className="text-itemDetail-textLabelColor">VOLUME(24H)</div>
<div className="">
{" "}
<span>40</span> <span>ETH</span>{" "}
</div>
</div>
<div className="m-5 h-1/4">
<div className="text-itemDetail-textLabelColor">MIN PRICE(24H)</div>
<div className="">
{" "}
<span>$</span> <span>770,18.03</span> <span>@40.0000000ETH</span>{" "}
</div>
</div>
<div className="m-5 h-1/4">
<div className="text-itemDetail-textLabelColor">MAX PRICE(24H)</div>
<div className="">
<span>$</span> <span>770,18.03</span> <span>@40.0000000ETH</span>
</div>
</div>
</div>
);
};
export default MarketInfo;
import Image from "next/image";
import React from "react";
import copy from "../../../../../../public/copy.png";
const OtherInfo = () => {
return (
<div className="w-full h-full flex flex-col items-start">
<div className="m-5 text-lg font-bold h-1/4">Other Info</div>
<div className="m-5 h-1/4">
<div className="text-itemDetail-textLabelColor">TOKEN CONTRACT</div>
<div className="w-full grid grid-cols-2 gap-4 mt-4 ">
<Image
className="flex "
src={copy}
alt="종이 아이콘"
width={15}
height={3}
/>
<div className="truncate text-blue-600">0xasdasdkjaqwjhrqwjyrqwjyeasddsa</div>
</div>
</div>
</div>
);
};
export default OtherInfo;
import React from "react";
const OverViewInfo = () => {
return (
<div className="w-full h-full flex flex-col items-start">
<div className="m-5 text-lg font-bold h-1/4">Overview</div>
<div className="m-5 h-1/4">
<div className="text-itemDetail-textLabelColor">MAX TOTAL SUPPLY</div>
<div className="">123123</div>
</div>
<div className="m-5 h-1/4">
<div className="text-itemDetail-textLabelColor">HOLDERS</div>
<div className="">25,301</div>
</div>
<div className="m-5 h-1/4">
<div className="text-itemDetail-textLabelColor">TOTAL TRANSFERS</div>
<div className="">-</div>
</div>
</div>
);
};
export default OverViewInfo;
페이지를 열심히 찍어내고 있지만, 가끔 팀원들과 안 맞는 디렉토리 구조, 페이지네이션을 위한 커스텀 훅 등등으로 부가시간이 많이 소요되고 있다. 커스텀훅을 제네릭으로 바꾸는 등 좀 더 리팩토링 하고 페이지를 더 빨리 생산해야 한다.