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