어이 주니어 답게행동해. (카테고리 메뉴를 얕보지말라..)

하율찬·2022년 7월 20일
0
post-thumbnail

어이 개발자친구.. 예비 개발자답게 행동해..
이번 기술구현하는 데 나 자신을 굉장히 과신했다.
나는 금방 바꿀수 있을거라 생각했다.
하지만 경기도 오산이었다.
디자이너님이 카테고리메뉴 UI를 드롭다운에서 체크형식으로 변경을 부탁하셨다.

처음에 각 분야별로 1개씩 버튼을 만들어서 클릭하면 값이 들어가는 형식으로 하면 되겠다 라는 생각을 시작했다.


 const Category1 = () => {
    setcategoryName((official) => !official);

    official == true ? setOfficial("공무원") : setOfficial("");

    console.log(official);
    console.log(categoryName);
  };

 return(
  <Chat1> 카테고리</Chat1>

              <div>
                <input type="radio"/>
                <button onClick={Category1}>공무원</button>
                <button>코딩</button>
                <button>자격증</button>
              </div>

)

그래서 onclick이벤트가 발생할시에 useState 훅을 사용하여 안에 공무원이라는 값이 들어갔다 나왔다. 될줄알았지만 그렇지않았다.
막상 생각대로 안되니까 어떻게 검색해야할지도 막막했다. 카테고리 메뉴 번갈아..? 카테고리메뉴 상태관리 등 점점 내가 원하는 기능과는 멀어져갔다. 그러던 중에 리액트 부트스트랩을 뒤지던중에

이런걸 발견하고 말았다.
그래서 체크 박스는 다중선택과 체크박스에 있는 데이터를 넣을수 있다는 것이 떠올라서 부랴부랴 체크박스를 검색하여서

여기까지 왔다.
나는 체크박스도 input이기에 label태그와 함께 하여 커스텀해야한 다는 것을 인지하고 하나씩 바꿔나가서 버튼을 눌렀을때 색이 바뀌도록 하는 일만 남았다.(삽질의 시작)

콘솔에는 각각 다찍히는데 클릭시에 CSS가 바뀌지 않았다..
styled-components에 분명 porps를 주어 체크해주었는데도 말이다..

	 {names.map((item) => {
                  return (
                    <CateLabel key={item.id}>
                      <CateInput
                        type="checkbox"
                        style={{ display: "none", width: "400px" }}
                        // 이때 value값으로 name를 지정해준다.
                        value={item.name}
                        // onChange이벤트가 발생하면 check여부와 value(name)값을 전달하여 배열에 name를 넣어준다.
                        onChange={(e) => {
                          onCheckedElement(e.target.checked, e.target.value);
                        }}
                        //  체크표시 & 해제를 시키는 로직. 배열에 name이 있으면 true, 없으면 false
                        checked={
                          categoryName.includes(item.name) ? true : false
                        }
                      />

                      <div>{item.name}</div>
                    </CateLabel>

1단계
const CateLabel = styled.label`
margin-right: 5px;
display: inline-block;
margin-bottom: 12px;
color: black;
background-color: ${(props) => (props.checked ? "black;" : "blue;")};
border: solid 1px black;
font-size: 18px;
font-weight: 900;
padding:1px;
transition: all 80ms linear;
user-select: none;
outline: none;
cursor: pointer;
border-radius: 4px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
&:focus {
  background-color: black;

}
}}
`;
2단계

const CateInput = styled.input`
  background-color: ${(props) => (props.checked ? "black;" : "blue;")};
`;
const CateLabel = styled.label`
margin-right: 5px;
display: inline-block;
margin-bottom: 12px;
color: black;
border: solid 1px black;
font-size: 18px;
font-weight: 900;
padding:1px;
transition: all 80ms linear;
user-select: none;
outline: none;
cursor: pointer;
border-radius: 4px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
&:focus {
  background-color: black;

}
}}

맞다.. 나는 label의 형태를 바꾸는 거기때문에 input 속성이 바뀌어봤자 절때 바뀌지 않는것이었다... 그래서 label에 checked의 속성을 똑같이 복붙해서 넣으니 바로 원하는대로 색이 바뀌었다...

전체코드..

import React from "react";

import styled from "styled-components";
import axios from "axios";


// 카테고리 명 표시
const names = [
  { id: 1, name: "자격증" },
  { id: 2, name: "대입" },
  { id: 3, name: "독서" },
  { id: 4, name: "자기계발" },
  { id: 5, name: "취미" },
  { id: 6, name: "어학" },
  { id: 7, name: "코딩" },
  { id: 8, name: "공무원" },
  { id: 9, name: "자유주제" },
];

const Login = ({ onClose }) => {


  // 카테고리 표시
  const [categoryName, setcategoryName] = React.useState([]);
  //  onChange함수를 사용하여 이벤트 감지, 필요한 값 받아오기
  const onCheckedElement = (checked, item) => {
    if (checked) {
      setcategoryName([...categoryName, item]);
    } else if (!checked) {
      setcategoryName(categoryName.filter((el) => el !== item));
    }
  };
  // x를 누르면 리스팅 목록에서 카테고리가 삭제되며 체크도 해제 된다

  // 서버에 방 정보 보내는 통신
  const CreateAxios = () => {
    const token = localStorage.getItem("accessToken");
    const userId = localStorage.getItem("userId");
    axios({
      method: "POST",
      url: `/api/room/create/${userId}`,
      data: {
        tagName: ["전체", ...categoryName],
        isLike: false,
      },

      baseURL: "http://3.35.26.55",
      headers: {
        "content-type": "application/json",
        Authorization: `Bearer ${token}`,
      },
    })
      .then((response) => {
        console.log(response);
        alert("방생성이 되었습니다.");
        onClose();
        //방상세페이지로 이동.
      })
      .catch((error) => {
        console.log(error);
        alert("error.message");
      });
  };

  return (
    <Container>
      <Background
        ref={outZone_ref}
        onClick={(e) => {
          if (outZone_ref.current === e.target) {
            onClose();
          }
        }}
      >
        <ModalBlock>
          <Title> 스터디 생성</Title>
          <Line />
          <Label>
            <div>
              <Chat2>스터디명</Chat2>
              
              <Chat1> 카테고리</Chat1>

              <div style={{ width: "309px" }}>
                {names.map((item) => {
                  return (
                    <CateLabel
                      key={item.id}
                      checked={categoryName.includes(item.name) ? true : false}
                    >
                      <CateInput
                        type="checkbox"
                        style={{ display: "none", width: "400px" }}
                        // 이때 value값으로 name를 지정해준다.
                        value={item.name}
                        // onChange이벤트가 발생하면 check여부와 value(name)값을 전달하여 배열에 name를 넣어준다.
                        onChange={(e) => {
                          onCheckedElement(e.target.checked, e.target.value);
                        }}
                        //  체크표시 & 해제를 시키는 로직. 배열에 name이 있으면 true, 없으면 false
                        checked={
                          categoryName.includes(item.name) ? true : false
                        }
                      />

                      <div>{item.name}</div>
                    </CateLabel>
                  );
                })}
              </div>
            </div>
          </Label>
          <BtnG>
            <Btn1
              onClick={() => {
                onClose();
              }}
            >
              취소
            </Btn1>
            <Btn2
              onClick={() => {
                CreateAxios();
                onClose();
              }}
            >
              스터디 생성
            </Btn2>
          </BtnG>
        </ModalBlock>
      </Background>
    </Container>
  );
};
const CateInput = styled.input``;
const CateLabel = styled.label`
  margin-right: 5px;
  display: inline-block;
  justify-content: center;
  margin-bottom: 10px;
  width: 72px;
  height: 32px;
  border-radius: 15px;
  background-color: ${(props) => (props.checked ? "#1D9FFD" : "white")};
  color: ${(props) => (props.checked ? "white" : "#808080")};
  border: solid 1px #808080;
  font-size: 15px;
  padding: 5px 1.8px 1.8px 1px;
  transition: all 80ms linear;
  user-select: none;
  outline: none;
  cursor: pointer;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
`;

const Container = styled.div`
  position: fixed;
  width: 100%;
  height: 100%;
  z-index: 100;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
`;
const Background = styled.div`
  position: fixed;
  width: 100%;
  height: 100%;
  background-color: rgba(255, 255, 255, 0.15);
  backdrop-filter: blur(5px);
`;

const ModalBlock = styled.div`
  display: flex;
  flex-direction: column;
  align-content: center;
  text-align: center;
  position: absolute;
  background-color: white;
  color: black;
  width: 508px;
  height: 690px;
  box-shadow: 1px 1px 1px 1px gray;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  animation: modal-show 1s;
  @keyframes modal-show {
    from {
      opacity: 0;
      margin-top: -50px;
    }
    to {
      opacity: 1;
      margin-top: 0;
    }
  }
`;

const Title = styled.span`
  font-size: 30px;
  font-weight: bold;
  display: flex;
  flex-direction: column;
  align-content: center;
  text-align: center;
  margin-top: 24px;
`;

const Line = styled.hr`
  background-color: black;
  width: 410px;
  height: 2px;
  margin-top: 12px;
  margin-bottom: 15px;
`;
const Label1 = styled.label`
  float: left;
  margin-top: 10px;
  font-size: 16px;
  font-weight: bold;
  display: flex;
  flex-direction: column;
  align-content: center;
  text-align: center;
`;
const Label = styled.label`
  float: left;
  margin-top: 10px;
  font-size: 16px;
  font-weight: bold;
  display: flex;
  flex-direction: column;
  align-content: center;
  text-align: center;
`;

const RadioBox = styled.input`
  margin-top: 10px;
  appearance: none;
  border: 1.5px solid black;
  border-radius: 20px;
  width: 16px;
  height: 16px;
  cursor: pointer;

  &:checked {
    width: 16px;
    height: 16px;
    background-color: white;
    padding: 1.5px;
    &::after {
      position: fixed;
      content: "";
      display: block;
      border-radius: 50%;
      width: 9.5px;
      height: 9.4px;
      margin-left: 0.2px;
      background: black;
    }
  }
`;

const Chat2 = styled.span`
  margin-right: 32px;
`;

const Chat1 = styled.span`
  margin-right: 12px;
`;

const Chat3 = styled.span`
  margin-right: 12px;
  vertical-align: middle;
  display: inline-block;
  margin: 0;
  padding: 0;
`;
const Input1 = styled.input`
  --saf-0: rgba(var(--sk_foreground_high_solid, 134, 134, 134), 1);
  border: 1px solid var(--saf-0);
  transition: border 80ms ease-out, box-shadow 80ms ease-out;
  box-sizing: border-box;
  color: rgba(var(--sk_primary_foreground, 29, 28, 29), 1);
  background-color: rgba(var(--sk_primary_background, 255, 255, 255), 1);
  padding: 12px;
  width: 309px;
  height: 36px;
  font-size: 18px;
  line-height: 1.33333333;
`;

const BtnG = styled.div`
  margin-bottom: 40px;
  margin-top: 32px;
`;

const Btn1 = styled.button`
  margin-right: 15px;
  display: inline-block;
  margin-right: 15px;
  margin-bottom: 12px;
  width: 197px;
  height: 50px;
  color: black;
  background-color: white;
  border: solid 1px black;
  font-size: 18px;
  font-weight: 900;
  min-width: 96px;
  padding: 0 16px 3px;
  transition: all 80ms linear;
  user-select: none;
  outline: none;
  cursor: pointer;
  border-radius: 4px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);

  &:hover {
    background-color: rgba(74, 21, 75, 0.9);
    border: none;
  }

  &:focus {
    --saf-0: rgba(var(--sk_highlight, 18, 100, 163), 1);
    box-shadow: 0 0 0 1px var(--saf-0), 0 0 0 5px rgba(29, 155, 209, 0.3);
  }
`;

const Btn2 = styled.button`
  display: inline-block;
  margin-bottom: 12px;
  width: 150px;
  color: #fff;
  background-color: #1d9ffd;
  border: none;
  font-size: 18px;
  font-weight: 900;
  height: 50px;
  width: 197px;
  padding: 0 16px 3px;
  transition: all 80ms linear;
  user-select: none;
  outline: none;
  cursor: pointer;
  border-radius: 4px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);

  &:hover {
    background-color: rgba(74, 21, 75, 0.9);
    border: none;
  }

  &:focus {
    --saf-0: rgba(var(--sk_highlight, 18, 100, 163), 1);
    box-shadow: 0 0 0 1px var(--saf-0), 0 0 0 5px rgba(29, 155, 209, 0.3);
  }
`;

const Input = styled.input`
  --saf-0: rgba(var(--sk_foreground_high_solid, 134, 134, 134), 1);
  border: 1px solid var(--saf-0);
  transition: border 80ms ease-out, box-shadow 80ms ease-out;
  box-sizing: border-box;
  color: rgba(var(--sk_primary_foreground, 29, 28, 29), 1);
  background-color: rgba(var(--sk_primary_background, 255, 255, 255), 1);
  padding: 12px;
  width: 309px;
  height: 36px;
  font-size: 18px;
  line-height: 1.33333333;
`;
export default Login;
profile
함께 일하고 싶어지는 동료가 되기를 원하는 프론트엔드 개발자입니다.

0개의 댓글