Project1 - OpenSea

이휘준·2022년 8월 16일
0
post-thumbnail

[깃헙 레포]

https://github.com/codestates/BEB-05-LeeSea

역할 분담

프로젝트1에서는 4명이 한 팀을 이뤄서 오픈씨 클론 코딩을 진행했다. 우리팀은 front-end, back-end, contract 등 파트 별로 업무를 나누기보다 프로젝트 개발을 경험하면서 front-end 및 blockchain에 대해 다양하게 공부할 수 있도록 하기 위해 기능 단위로 업무를 분배했습니다.

처음에는 서로 적응이 되지 않아서 조금 해매였지만 주기적으로 미팅을 진행하였고 이를 통해 좀 더 명확하고 구체적인 목표를 구상했습니다.

구현 목표

-플랫폼에 등록된 NFT들을 보여준다.
-NFT 민팅을 쉽게 할 수 있게 해준다.
-자신의 NFT를 판매할 수 있다.
-다른 사람들이 판매하는 NFT를 구매할 수 있다.
-위의 기능들을 고려해서 다음과 같은 페이지들을 구상했다.

-처음 웹사이트에 접속했을 때 보이는 Home
-플랫폼에 등록된 NFT들을 보여주는 Explore
-플랫폼에 연결된 나의 지갑이 소유하고 있는 NFT들을 보여주는 Profile
-NFT를 민팅할 수 있는 기능을 지원하는 Create
-소유하고 있는 NFT를 판매할 수 있는 Sell
-원하는 NFT를 구매할 수 있는 Buy
-메타마스크 지갑과 연결하기

목업



페이지 구성

Home.js

import React from 'react';
import { Link } from 'react-router-dom';

const Home = () => {
	return (
		<div className='home-container'>
			<div className='home-title-section'>
				<div className='home-title-area'>
					<h1 className='home-title'>Welcome to LeeSea!<br></br>Discover, collect, and sell extraordinary NFTs</h1>
					<h3 className='home-description'>LeeSea가 만든 NFT마켓에 지금 참여하세요.</h3>
				</div>
				<div className='home-btn-area'>
					<Link to="/explore"><button type="button" className="home-btn go-to-explore">Explore</button></Link>
					<Link to="/create"><button type="button" className="home-btn go-to-create">Create</button></Link>
				</div>
			</div>
			<div className="home-title-image" >
				<img className='image-item' src="https://cdn.pixabay.com/photo/2016/07/11/11/48/printing-on-t-shirt-1509512_1280.png" width="100%" height="100%" alt='...'></img>
				<img className='image-item' src="https://cdn.pixabay.com/photo/2016/09/12/05/41/van-gogh-1663090_1280.jpg" width="100%" height="100%" alt='...'></img>
				<img className='image-item' src="https://cdn.pixabay.com/photo/2020/06/06/11/48/caricature-5266261_1280.jpg" width="100%" height="100%" alt='...'></img>
				<img className='image-item' src="https://cdn.pixabay.com/photo/2018/03/20/10/04/illustrator-3242713_1280.jpg" width="100%" height="100%" alt='...'></img>
				<img className='image-item' src="https://cdn.pixabay.com/photo/2017/03/19/15/14/happiness-2156794_1280.png" width="100%" height="100%" alt='...'></img>
				<img className='image-item' src="https://cdn.pixabay.com/photo/2018/04/09/19/55/low-poly-3305284_1280.jpg" width="100%" height="100%" alt='...'></img>
				<img className='image-item' src="https://cdn.pixabay.com/photo/2020/05/19/13/48/cartoon-5190942_1280.jpg" width="100%" height="100%" alt='...'></img>
				<img className='image-item' src="https://cdn.pixabay.com/photo/2020/06/10/02/22/caricature-5280770_1280.jpg" width="100%" height="100%" alt='...'></img>
			</div>
			{/* <img className="home-title-image" src="" width="100%" height="100%" alt='...'></img> */}			
		</div>
	);

}


export default Home;

Explore.js

import { useEffect } from 'react';
import { tokenActions } from '../redux/tokenSlice'
import { useSelector, useDispatch } from 'react-redux';
import Erc721 from '../components/Erc721';


function Explore(){
    const totalSupply = useSelector((state) => state.token.totalSupply);
    const account = useSelector((state) => state.account.address);
    const dispatch = useDispatch()
    useEffect(() => {
        dispatch(tokenActions.setTotalSupply());
        if (account) {
          dispatch(tokenActions.setMyTokenIds(account));
        }
    }, [account])
    return(
        <div className = "tokenlist">
            <h2 className="explore-title">Explore</h2>
            <p className="explore-description">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Enim ipsa vitae fugiat, ullam similique quisquam magni, eveniet maxime earum dolor vero minus est laudantium ducimus quia sed amet aspernatur ipsum!</p>
            <div className="erc721List">
                {[...Array(totalSupply)].map((_, idx) => {
                    const tokenId = idx + 1;
                    return(
                        <Erc721 tokenId={tokenId} key={tokenId}/>
                    )
                })}
            </div>
        </div>
    );
}  
export default Explore;

Create.js

import { useEffect } from 'react';
import { tokenActions } from '../redux/tokenSlice'
import { useSelector, useDispatch } from 'react-redux';
import Erc721 from '../components/Erc721';


function Explore(){
    const totalSupply = useSelector((state) => state.token.totalSupply);
    const account = useSelector((state) => state.account.address);
    const dispatch = useDispatch()
    useEffect(() => {
        dispatch(tokenActions.setTotalSupply());
        if (account) {
          dispatch(tokenActions.setMyTokenIds(account));
        }
    }, [account])
    return(
        <div className = "tokenlist">
            <h2 className="explore-title">Explore</h2>
            <p className="explore-description">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Enim ipsa vitae fugiat, ullam similique quisquam magni, eveniet maxime earum dolor vero minus est laudantium ducimus quia sed amet aspernatur ipsum!</p>
            <div className="erc721List">
                {[...Array(totalSupply)].map((_, idx) => {
                    const tokenId = idx + 1;
                    return(
                        <Erc721 tokenId={tokenId} key={tokenId}/>
                    )
                })}
            </div>
        </div>
    );
}  
export default Explore;

Profile.js

import { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux'; // redux
// import '../components/styles/Profile.css';
import MyToken from '../components/MyToken';
import { accountActions } from '../redux/accountSlice';
import { tokenActions } from '../redux/tokenSlice'


function Profile() {
  const tokenContract = useSelector((state) => state.token.tokenContract);
  const myTokenIds = useSelector((state) => state.token.myTokenIds);
  const account = useSelector((state) => state.account.address);
  const dispatch = useDispatch()

  useEffect(() => {
    dispatch(tokenActions.setTokenContract());
    if (account) {
      dispatch(tokenActions.setMyTokenIds(account));
    }
  }, [tokenContract, account])

  const signout = () => {
      dispatch(accountActions.setAccount(''))
  }

  return tokenContract? (
    <div className="Profile">
      {/* 지갑 연결이 안 된 경우 */}
      <div className={account ? "hidden" : ""}>
        <div className="alert alert-danger" role="alert">
          Please connect to your wallet first.
        </div>
      </div>

      {/* 지갑 연결이 된 경우 */}
      <div className={!account ? "hidden" : ""}>
        <div className="profile-header">
          <div className="profile-header-1">
            <h2 className="profile-header-title">Profile</h2>
            <button type="button" className="logout-btn" onClick={signout}>로그아웃</button>
          </div>
          <div className="profile-header-2">
            <img className="profile-header-2-image" src="https://static.opensea.io/general/ETH.svg" />
            <p className="account-address">{account}</p>
          </div>
        </div>

        <div className="profile-contents">
          <h5 className="profile-item-header">내 NFT 목록</h5>
            <div className="profile-items">
              {myTokenIds.map((tokenId) => <MyToken tokenId={tokenId} key={tokenId} />)}
            </div>
        </div>
      </div>
    </div>
  ): null;
}

export default Profile

회고

내가 수업 때 배웠던 부분을 아직 내것으로 만들지 못했다는 것이 정말 아쉬웠고 또 수업 이외에도 내가 공부해야 할 부분들이 많구나라는 것을 느꼈다. 그리고 무엇보다도 개발자는 팀원들과 커뮤니케이션과 호흡이 중요하다는 것을 깨닫게 되었다.

0개의 댓글