맡은 역할

yonghee·2021년 11월 15일
0

나랏말싸미

목록 보기
2/3

포지션 : Front-End

Local MyPage(main)




UI

local MyPage(main)의 UI는 아코디언 메뉴 형식으로 구성하였다

input type="checkbox" type="radio" 이 둘의 차이점은 heckbox는 중복 선택이 가능하며 radio 버튼은 단일 선택만 가능하다. 따라서 checkbox 타입을 사용하였다.

속성내용
name서버로 전송될 라디오 및 체크박스의 이름. key 값에 해당함 라디오 버튼은 동일한 그룹끼리 같은 name 값을 지정함
value서버로 넘어갈 값을 지정
checked초깃값으로 기본 선택될 항목을 설정

:checked : 클래스를 활용하여 사용자가 JavaScript 를 사용하지 않고 체크박스 상태에 따라 콘텐츠를 토글할 수 있도록 합니다.

HTML input id
id 값은 일반적으로 CSS나 자바스크립트 등에서 선택자로 사용됩니다. 하지만 id 값은 HTML의 input 태그에서는 label 태그와 연결 할 때도 사용할 수 있습니다.

label for
label 태그는 checkbox, radio와 같은 체크박스 등의 속성에 설명하는 문자를 삽입할 때 사용하는 태그입니다. for 라는 속성을 삽입해서 input의 id값과 일치 시키면 체크 박스의 클릭 범위를 증가시킬 수 있습니다.

<Li>
            <input className="checkbox" type="checkbox"  id="section-1-radio"/>
            <label className="tab" for="section-1-radio" id="section-1-tab">
                <div className="mileage-title">보유 상평통보: </div>
                <div className="mileage">{userData.mileage}</div>
                <div className="mileage-store">저잣거리 보기</div>
            </label>
            <div className="itemListContainer" >
              <div className="buyItems">
                {buyItems.length !== 0 ? (
                  <>
                  {buyItems.map((el)=>(
                    <div className="buyItemsBox">
                      <div className="itemImage">
                        <Link to="/mileageshop" ><img src={el.itemImage} alt="items"/></Link>
                      </div>
                      <div className="itemName">{el.itemName}</div>
                      <div className="cost">가격: {el.cost}</div>
                      <div className="quantity">재고: {el.quantity}</div>
                      <div className="company">() {el.company}</div>
                    </div>
                  ))}
                  </>
                ) : (
                  <>
                  <div>
                    상품이 존재하지 않습니다.
                  </div>
                  </>
                )}
              </div>               
            </div>
        </Li>

기능 & api연동

데이터를 이용한 화면 구성

Local MyPage(Main)은 기본적으로 회원의 email, name, image, mileage 와 구매내역 내가 만든 문제를 볼 수가 있다

email, name, image, mileage 기본 정보는 useState(userData)를 통해 초기 상태값을 지정해주고 axios를 통해 데이터를 받아오는데 useEffect를 통해 랜더링 될 때 데이터를 받아오며 받아온 값을 useState(setUserData)를 통해 상태값을 변경해주는 형식으로 코드를 구성하였다.

구매 가능한 상품, 구매 내역들 또한 useState, useEffect, axios를 사용하여 같은 방식으로 구현하고 데이터 값은 map을 이용하여 값을 출력하였다.

const MyPage = (props) => {
  const userState = useUserState();
  const [userData, setUserData] = useState({
    email: '',
    name: '',
    image: '',
    mileage: '',
  })
  const [deleteCheckOpen, setDeleteCheckOpen] = useState(false);
  const [selectedQuiz, setSelectedQuiz] = useState('')

  const [buyItems, setBuyItems] = useState([]);
  const [usedItems, setUsedItem] = useState([]);
  const [quiz, setQuiz] = useState([]);

  useEffect(() => {
    if(userState.isUserLoggedIn) {
      axios.get("/users/info") 
      .then((response) => {
        setUserData({
          email : response.data.data.userData.email,
          name : response.data.data.userData.name,
          image : response.data.data.userData.image,
          mileage : response.data.data.userData.mileage,
        })    
      });

      axios.get("/mypublish") 
      .then((response)=> {
        setQuiz(response.data.data.madeQuiz)
        DEBUG_MODE && console.log(response.data.data.madeQuiz)
      });

      axios.get("/myitems")
      .then((response) => {
        setUsedItem(response.data.data.userData.user_usedItems);
      });
      
      axios.get("/items/all")
      .then((response) => {
        DEBUG_MODE && console.log(response);
        DEBUG_MODE && console.log(response.data.data.itemList);
        setBuyItems(response.data.data.itemList);
      });
    }
  }, []);

Local MyPage(RankModal)

UI

모달창 만들기

모달창을 만드는 핵심은 웹 브라우저 페이지를 하나의 큰창으로 잡고 반투명을 만들고 그 안에 박스 하나를 만들어 출력하는 방식이다 처음에는 새로운 창을 띄우는 것이 아닌데 창을 띄우는 것으로 착각하여 라우터를 사용하는 착오가 있었다.

position: fixed; : 특정 위치에 고정시켜 스크롤을 내려도 그 자리에 계속 위치하게 설정
z-index: 999; :z-index의 가장 중요한 특징 중 하나는 아무 요소나 다 z-index를 넣는다고 해서 우선순위를 넣을 수 는 없다는 점이다.z-index 속성이 적용되기 위해서는 z-index를 적용한 영역이 position:static 값이 아니어야 한다. z-index의 기본값은 auto 이고 보통 1, 9, 100, -1, -100등의 숫자로 그 속성의 값을 지정한다

background-color: rgba(0,0,0,0.75); 값으로 설정하여 반투명으로 만들었다.

const ModalBackground = styled.div`
  position: fixed;
  z-index: 999;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background-color: rgba(0,0,0,0.75);
  display: flex;
  justify-content: center;
  place-items: center;

> div {
  @media (max-width: 768px) {
      width: 30em;
    }
  width: 40em;
  
  border-radius: 12px;
  background-color: white;
  box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
  display: flex;
  flex-direction: column;
  padding: 25px;  
}
`;

기능 & api연동

개인적으로 React 라이브러리를 사용하면서 React의 장점이 이런 부분이고 가장 기본이 되는 기능들을 비교적 잘 활용한 부분이었던 것 같다

모달창 만들기

모달창을 만들 때 클릭하여 박스 상자를 띄우고 닫고를 어떻게 기능적으로 구현 할 것인가 였는데 useState를 활용하였다. 초기값을 어떤 식으로 줄 것인가 공부하면서 알게 된점은 boolean 타입을 사용한다는 것이다 따라서 초기값을 false로 주었다. 그리고 버튼을 클릭하였을 때 상태값을 true값으로 바꾸게 설정하엿다. 그러면 상태값이 true 바뀌고 &&뒤에 엘리먼트는 조건이 true인 경우에만 출력 된다 조건이 false 경우는 React무시한다 따라서 Modal6 컴포넌트를 출력하게 된다 setOpenModal={setModalOpen}를 props로 내려준 이유는 창을 닫을 때 또한 상태값을 바꿔저야 하기 떄문이다. 닫을 떄는 반대로 false값으로 상태 값을 바꾸게 된다.

1. const [modalOpen, setModalOpen] = useState(false);
2. onClick={() => {setModalOpen(true)}}
3. {modalOpen && <Modal6 setOpenModal={setModalOpen} />}
4. onClick={() => {setOpenModal(false)}}
import Modal6 from './RankModal'

const MyPage = (props) => {

const [modalOpen, setModalOpen] = useState(false);
return (
    <>      
      {modalOpen && <Modal6 setOpenModal={setModalOpen} />}
      <SecondBox>
          <img 
            className="profile"
            src={userData.image}
            alt="" />
        <div className='profileData'>
          <h2>ID: {userData.email}</h2>
          <h2>이름: {userData.name}</h2>
        </div>
        <div className="class">
          <button
            className="openModalBtn"
            onClick={() => {
              setModalOpen(true);
            }}
          >
            <FontAwesomeIcon icon={faTrophy} size="4x" 							className="class" />
          </button>
        </div>  
      </SecondBox>
	<>
}           
export default MyPage;

const Modal6 = ({ setOpenModal }) => {
  const [rank, setRank] = useState([]);
  const [limit, setLimit] = useState(7);
  const [button, setButton] = useState(true);

  useEffect(() => {  
    axios.get(`/users/rank/?offset=0&limit=${limit}`
    ).then((response)  => {
      setRank(response.data.data.rankList);
    }).catch((err) => {
      DEBUG_MODE && console.log(err);
    });
   }, []);

   const moreData = () => {    
    setLimit(limit + 3)    
   }
   useEffect(() => {
    axios.get(`/users/rank/?offset=0&limit=${limit}`
    ).then((response) => {
     setRank(response.data.data.rankList);
     if(response.data.data.message) {
       setButton(false);
     }
    }).catch((err) => {
      DEBUG_MODE && console.log(err);
    });
  }, [limit])

  return (
    <ModalBackground>
      <div className="modalContainer">
      <TitleCloseBtn>
          <button
            onClick={() => {
              setOpenModal(false);
            }}
          >
            &times;
          </button>
        </TitleCloseBtn>
        <Title>
          <h1>전체 랭킹</h1>
          <span className="classTitle">순위</span>
          <span className="nameTitle">이름</span>
          <span className="mileageTitle">마일리지</span> 
                   
          <div style={{backgroundImage: `url(${RankModalImg}`}}>
          {rank.map((el, i)=> 
            <div key={i}>
              <span className="class">{i+1}</span>
              <span className="name">{el.name}</span>
              <span className="mileage">{el.mileage}</span>            
            </div>
          )}
          </div>  
        </Title>        
        <Footer>
            {
              button ?
          <button className='trueBtn'
            onClick={moreData}
            id="cancelBtn"
          >
            더보기
          </button>
          :
          <button className='falseBtn'
            onClick={moreData}
            id="cancelBtn"
          >
            
          </button>
             }          
          </Footer>
      </div>
      </ModalBackground>
  );
}

api연동(Pagination)

Pagination : 모달창 이 열리게 되면 api 요청을 통해 데이터를 출력해야 하는데 목록형 UI(상품 등)에서 데이터를 한번에 가져오는것이 아니라 필요한만큼, 또는 화면에 보이는 만큼만 백엔드에 요청하고 응답받아 사용하는 방식을 활용하여 데이터를 받아 왔다.

axios.get(/users/rank/?offset=0&limit=${limit})
limit(page size) : 한 페이지에 보여줄 데이터의 갯수
offset : 데이터가 시작하는 위치(index)
필요한 만큼 받아 오려면 구간을 정해줘야 하는데 limit값과 offset값을 설정하면 가능하다

const moreData = () => {setLimit(limit + 3)}
<button className='trueBtn' onClick={moreData} id="cancelBtn">

또한 버튼을 클릭 하였을 때 추가적으로 받아 올 수 있도록 설정하였다.

const Modal6 = ({ setOpenModal }) => {
  const [rank, setRank] = useState([]);
  const [limit, setLimit] = useState(7);
  const [button, setButton] = useState(true);

  useEffect(() => {  
    axios.get(`/users/rank/?offset=0&limit=${limit}`
    ).then((response)  => {
      setRank(response.data.data.rankList);
    }).catch((err) => {
      DEBUG_MODE && console.log(err);
    });
   }, []);

   const moreData = () => {    
    setLimit(limit + 3)    
   }
   useEffect(() => {
    axios.get(`/users/rank/?offset=0&limit=${limit}`
    ).then((response) => {
     setRank(response.data.data.rankList);
     if(response.data.data.message) {
       setButton(false);
     }
    }).catch((err) => {
      DEBUG_MODE && console.log(err);
    });
  }, [limit])

  return (
    <ModalBackground>
      <div className="modalContainer">
      <TitleCloseBtn>
          <button
            onClick={() => {
              setOpenModal(false);
            }}
          >
            &times;
          </button>
        </TitleCloseBtn>
        <Title>
          <h1>전체 랭킹</h1>
          <span className="classTitle">순위</span>
          <span className="nameTitle">이름</span>
          <span className="mileageTitle">마일리지</span> 
                   
          <div style={{backgroundImage: `url(${RankModalImg}`}}>
          {rank.map((el, i)=> 
            <div key={i}>
              <span className="class">{i+1}</span>
              <span className="name">{el.name}</span>
              <span className="mileage">{el.mileage}</span>            
            </div>
          )}
          </div>  
        </Title>        
        <Footer>
            {
              button ?
          <button className='trueBtn'
            onClick={moreData}
            id="cancelBtn"
          >
            더보기
          </button>
          :
          <button className='falseBtn'
            onClick={moreData}
            id="cancelBtn"
          >
            
          </button>
             }          
          </Footer>
      </div>
      </ModalBackground>
  );
}

export default Modal6;

회원가입 회원정보 수정

Login UI

Signin UI

MyPage UI

Resign UI

관리자 Login UI

profile
필요할 때 남기는 날것의 기록 공간

0개의 댓글