프로젝트 (2024-05-10~2024-05-21) 틱톡 AR 필터 모집 공고 (2)

2024. 5. 29. 20:32프로젝트

728x90
반응형

이번에는 프론트 코드의 중요한 부분을 소개하겠습니다.

우선 프론트 작업을하면서 정말 고생이였던 부분은 화면에 보이는 텍스트들을 한줄마다 div로 끊고 max-width를 주워서 들여쓰기를 구연하였습니다.

또한 모바일 부분을 480px , 768px 로 나누어서 진행하였는데 친구들의 각기다른 핸드폰에서는 짤리는 부분도 많았습니다

 

기능 소개

Apply 페이지는 가입버튼 컴포넌트, 라디오 버튼 컴포넌트 등으로 되어있습니다.

 

가입버튼 컴포넌트 

useEffect(() => {
  if (selectedButton === "서울" && selectedRadio === "Team") {
    setRedirectUrl(
      "https://docs.google.com/forms/d/1nCTw4xQaW7Z3svAMFR5m3ek54dQHR2aktn5GI25tJsk/viewform?edit_requested=true"
    );
  } else if (selectedButton === "대전" && selectedRadio === "Team") {
    setRedirectUrl(
      "https://docs.google.com/forms/d/1_wNZfRHhcUVeJB_YLILwJ1q5lPlHftNmvqRysw56SB4/viewform?edit_requested=true"
    );
  } else if (selectedButton === "광주" && selectedRadio === "Team") {
    setRedirectUrl(
      "https://docs.google.com/forms/d/17Y29gQ994vg0S50TSKkgKWuG1PVoKNQv3-5e1B1Rp4c/viewform?edit_requested=true"
    );
  }
}, [selectedButton, selectedRadio]);

 

1. Props 는 selectedButton와 selectedRadio로 되어있습니다.

selectedButton는 사용자가 선택한 버튼 (도시 이름) 이고

selectedRadio는 사용자가 선택한 라디오 버튼입니다.

 

2. useEffect 훅을 사용하여 selectedButton과 selectedRadio가 변경될 때마다 

특정 URL로 리디렉션하도록 redirectUrl 상태를 업데이트합니다.
조건에 맞는 도시와 팀 선택에 따라 각기 다른 Google Forms URL이 설정됩니다.

 

라디오 버튼

import { useContext } from "react";
import { RadioContext } from "../Apply/layout/Contents";
import styled from "styled-components";

function Radio({ children, value, name }) {
  const { selectedRadio, handleRadioChange } = useContext(RadioContext);

  return (
    <Container>
      <StyledRadio
        type="radio"
        value={value}
        name={name}
        checked={selectedRadio === value}
        onChange={() => handleRadioChange(value)}
      />
      <StyledLabel>
        <div className="text-wrapper">{children}</div>
      </StyledLabel>
    </Container>
  );
}

export default Radio;

 

Props는 children, value, name 으로 되어있습니다

children는 라디오 버튼 옆에 표시될 텍스트 또는 요소이고,
value는 라디오 버튼의 값 이고,
name는 라디오 버튼의 이름 속성 (같은 그룹의 라디오 버튼을 지정하기 위해 사용합니다) 이 있습니다.

 

이 컴포넌트는 커스텀 스타일이 적용된 라디오 버튼을 만들고, 

사용자가 선택한 라디오 버튼의 상태를 RadioContext를 통해 전역적으로 관리합니다. 

 

 

콘텐츠 컴포넌트

import React, { createContext } from "react";

export const RadioContext = createContext({});

 

전역 상태 관리를 위해 RadioContext를 생성합니다. 이 컨텍스트를 통해 라디오 버튼의 선택 상태를 관리할 수 있습니다.

 

import React, { useState, useContext } from "react";
import styled from "styled-components";
import icon from "../../../../images/Apply/caution.png";
import BackIcon from "../../../../images/Apply/ball.svg";
import Radio from "../Radio";
import RadioGroup from "../RadioGroup";
import TestBox from "../../Box/StyleBox2_2";
import JoinButton from "../JoinButton";
import ResponsiveLocationButton from "../LocationButton";

export const RadioContext = createContext({});

function Contents() {
  const [selectedButton, setSelectedButton] = useState("");
  const [selectedRadio, setSelectedRadio] = useState("");

  const handleButtonClick = (buttonName) => {
    setSelectedButton(buttonName);
    console.log(buttonName);
  };

  const handleRadioChange = (value) => {
    setSelectedRadio(value);
    console.log(value);
  };

  const radioContextValue = { selectedRadio, handleRadioChange };

  return (
    <RadioContext.Provider value={radioContextValue}>
      <Section>
        <div>
          <Dot src={BackIcon} alt="DotIcon" />
          <TitleContainer>
            <TitleLabel>
              <div className="text-wrapper">등록기간</div>
            </TitleLabel>
          </TitleContainer>
        </div>
        <SubContainer>
          <SubLabel>
            <div className="text-wrapper">5월 6일(월)부터 6월 16일(일)까지</div>
          </SubLabel>
        </SubContainer>
      </Section>
      
      <Section>
        <div>
          <Dot src={BackIcon} alt="DotIcon" />
          <TitleContainer>
            <TitleLabel>
              <div className="text-wrapper">대상</div>
            </TitleLabel>
          </TitleContainer>
        </div>
        <SubContainer>
          <SubLabel>
            <div className="text-wrapper">
              한국에 거주하는 분(18세부터 26세까지)
            </div>
          </SubLabel>
        </SubContainer>
      </Section>

      <Section>
        <TitleContainer>
          <div className="location_container">
            <SubSection className="seoul">
              <div className="sub-location_seoul">서울/경기</div>
              <div className="sub-count_seoul">
                선착순 100명(1회차 50명, 2회차, 50명)
              </div>
            </SubSection>
            <SubSection className="daejeon">
              <div className="sub-location">대전</div>
              <div className="sub-count">선착순 50명</div>
            </SubSection>
            <SubSection className="gwangju">
              <div className="sub-location">광주</div>
              <div className="sub-count">선착순 50명</div>
            </SubSection>
            <SubSection className="note">
              <div className="text-wrapper">
                ※ 팀 참가 인원 포함 총 200명 모집
              </div>
            </SubSection>
          </div>
        </TitleContainer>
      </Section>

      <Section>
        <div>
          <Dot src={BackIcon} alt="DotIcon" />
          <TitleContainer>
            <TitleLabel>
              <div className="text-wrapper">참가방법</div>
            </TitleLabel>
          </TitleContainer>
        </div>
        <SubContainer>
          <SubLabel>
            <div className="text-wrapper">
              개인 또는 2인팀(디자이너 1인, 개발자 1인)
            </div>
          </SubLabel>
        </SubContainer>
      </Section>

      <Section>
        <div>
          <Dot src={BackIcon} alt="DotIcon" />
          <TitleContainer>
            <TitleLabel>
              <div className="text-wrapper">신청지역</div>
            </TitleLabel>
          </TitleContainer>
        </div>
        <StyledContainer>
          <StyledBox>
            <ResponsiveLocationButton
              content="서울"
              onClick={() => handleButtonClick("서울")}
              isActive={selectedButton === "서울"}
            />
            <ResponsiveLocationButton
              content="대전"
              onClick={() => handleButtonClick("대전")}
              isActive={selectedButton === "대전"}
            />
            <ResponsiveLocationButton
              content="광주"
              onClick={() => handleButtonClick("광주")}
              isActive={selectedButton === "광주"}
            /> 
          </StyledBox>
        </StyledContainer>
      </Section>

      <Section>
        <RadioContext.Provider value={radioContextValue}>
          <form
            onSubmit={(e) => {
              e.preventDefault();
            }}
          >
            <RadioGroup label="참가 유형">
              <Radio name="contact" value="Team">
                팀 참가
              </Radio>
              <Radio name="contact" value="Indv">
                개인 참가
              </Radio>
            </RadioGroup>
            <TestBox />
            <JoinButton
              selectedButton={selectedButton}
              selectedRadio={selectedRadio}
            />
          </form>
        </RadioContext.Provider>
      </Section>
    </RadioContext.Provider>
  );
}

export default Contents;

 

Contents 컴포넌트는 여러 섹션을 포함하여 다양한 정보를 사용자에게 제공하는 역할을 합니다. 

 

상태 관리

먼저, useState 훅을 사용하여 컴포넌트의 상태를 관리합니다.

const [selectedButton, setSelectedButton] = useState("");
const [selectedRadio, setSelectedRadio] = useState("");

 

selectedButton는 사용자가 선택한 버튼의 이름을 저장합니다.
selectedRadio는 사용자가 선택한 라디오 버튼의 값을 저장합니다.

 

const handleButtonClick = (buttonName) => {
  setSelectedButton(buttonName);
  console.log(buttonName);
};

const handleRadioChange = (value) => {
  setSelectedRadio(value);
  console.log(value);
};

 

handleButtonClick는 사용자가 버튼을 클릭했을 때 호출되며, selectedButton 상태를 업데이트합니다.
handleRadioChange는 사용자가 라디오 버튼을 변경했을 때 호출되며, selectedRadio 상태를 업데이트합니다.

 

컨텍스트 값 설정

컨텍스트 값을 설정하여 하위 컴포넌트에 전달합니다.

const radioContextValue = { selectedRadio, handleRadioChange };

 

selectedRadio와 handleRadioChange를 포함하는 객체를 생성하여 RadioContext.Provider의 값으로 사용합니다.

 

import React, { useState, createContext } from "react";

// 1. 컨텍스트 생성
export const RadioContext = createContext({});

function Contents() {
  // 2. 상태 관리
  const [selectedRadio, setSelectedRadio] = useState("");

  // 3. 라디오 버튼 변경 핸들러
  const handleRadioChange = (value) => {
    setSelectedRadio(value);
    console.log(value);
  };

  // 4. 컨텍스트 값 객체 생성
  const radioContextValue = { selectedRadio, handleRadioChange };

  return (
    // 5. 컨텍스트 공급자 설정
    <RadioContext.Provider value={radioContextValue}>
      <Section>
        <form onSubmit={(e) => e.preventDefault()}>
          <RadioGroup label="참가 유형">
            <Radio name="contact" value="Team">팀 참가</Radio>
            <Radio name="contact" value="Indv">개인 참가</Radio>
          </RadioGroup>
          <JoinButton selectedRadio={selectedRadio} />
        </form>
      </Section>
    </RadioContext.Provider>
  );
}

export default Contents;

 

주요 부분 설명

컨텍스트 생성: createContext 함수를 사용하여 RadioContext를 생성합니다.


상태 관리: useState 훅을 사용하여 selectedRadio 상태를 관리합니다.


라디오 버튼 변경 핸들러: handleRadioChange 함수는 라디오 버튼 값이 변경될 때 호출되며,

selectedRadio 상태를 업데이트합니다.


컨텍스트 값 객체 생성: selectedRadio와 handleRadioChange를 포함하는 객체인 radioContextValue를 생성합니다.


컨텍스트 공급자 설정: RadioContext.Provider 컴포넌트를 사용하여 radioContextValue 객체를 value 속성에 

전달합니다. 이렇게 하면 RadioContext를 구독하는 모든 하위 컴포넌트에서 이 값을 사용할 수 있습니다.