개발자로 전향중

react hook form 사용 예시 and 자동 전화번호 하이픈 본문

React

react hook form 사용 예시 and 자동 전화번호 하이픈

hovinee 2022. 10. 6. 18:36
import React, { useState, useEffect, useRef } from "react";
import styled from "styled-components";
import { useForm, SubmitHandler } from "react-hook-form";

import PreReservationBtn from "../../public/images/web/Main/Button_booking.svg";
import PreReservationBtnhover from "../../public/images/web/Main/Button_booking_mouseover.svg";
import MLogo from "../../public/images/web/Main/Logo_Fatalbomb.svg";
import ButtonClose from "../../public/images/web/Main/Button_Close_Mobile.svg";
import Image from "next/image";
import ModalBackImg from "../../public/images/web/Main/Pc_BookingPopup_Background.png";
import MobileModalBackImg from "../../public/images/web/Main/Mobile_Booking_Background.png"

//Mobile layout
import { SCREEN_SIZE } from "../../constants/screenSize";
import { getValue } from "@mui/system";

interface modalprops {
  premodalhover: boolean;
  prereserve: boolean;
  Setpremodalhover: React.Dispatch<React.SetStateAction<boolean>>;
  Setprereserve: React.Dispatch<React.SetStateAction<boolean>>;
  mobileResize: number;
}

export interface IFormInput {
  nickname: string;
  phonenumber: string;
}
const PreModal = ({
  premodalhover,
  prereserve,
  Setpremodalhover,
  Setprereserve,
  mobileResize

}: modalprops) => {


  const {
    register,
    handleSubmit,
    formState: { errors },
    setValue,
    watch
  } = useForm<IFormInput>();

  const ismodalhover = () => {
    Setpremodalhover(!premodalhover);
  };

  const isprebooking = () => {
    Setprereserve(!prereserve);
  };


  const onSubmitHandler: SubmitHandler<IFormInput> = (data) => {
    console.log(data)
  }

  const [hyphen, setHyphen] = useState<string>("")
  const watchAllFields = watch("phonenumber");



  useEffect(() => {

    if (watchAllFields && watchAllFields.length === 11) {
      setHyphen(watch("phonenumber").replace(/(\d{3})(\d{4})(\d{4})/, '$1-$2-$3'))
      setTimeout(() => { setValue("phonenumber", hyphen); }, 0.00001);
    }


  }, [hyphen, watchAllFields]);


  return (
    <PreModalWrapper>
      <PreModalUi>
        <PreModalUiInner>

          <ModalClose onClick={() => { isprebooking() }}>
            {mobileResize <= 480 ?
              <Image src={ButtonClose}
                alt="모달닫기"
                width={15}
                height={15} /> :
              <Image src={ButtonClose}
                alt="모달닫기"
                width={25}
                height={25} />}
          </ModalClose>

          <ModalLogo>
            {mobileResize <= 480 ?
              <Image src={MLogo}
                alt="모달로고"
                width={120}
                height={50} /> :
              <Image src={MLogo}
                alt="모달로고"
                width={150}
                height={60} />}

          </ModalLogo>

          <UserInfo>
            <form onSubmit={handleSubmit(onSubmitHandler)}>
              <div className='userinfo--text'>
                휴대폰번호
                <span className='userinfo--important'>
                  (필수)
                </span>
              </div>
              <UserInfoPhone
                type="text"
                placeholder="-을 제외하고 입력해주세요"
                {...register("phonenumber",
                  {
                    required: "핸드폰 번호를 입력해주세요.",
                    maxLength: {
                      value: 13,
                      message: "핸드폰의 정보가 정확하지 않습니다."
                    },
                    minLength: {
                      value: 13,
                      message: "핸드폰의 정보가 정확하지 않습니다."
                    }
                  })}

              />

              <Alert>{ watchAllFields && watchAllFields.length === 13 ? "" : errors.phonenumber?.message}</Alert>

              <div className='userinfo--text'>
                닉네임
                <span className='userinfo--important'>
                  (필수)
                </span>
              </div>


              <UserInfoNick
                type="text"
                placeholder="2-10글자 이내로 입력해주세요"
                {...register("nickname",
                  {
                    required: "닉네임을 입력해주세요",
                    pattern: {
                      value : /^[\w\Wㄱ-ㅎㅏ-ㅣ가-힣]{2,10}$/,
                      message : "닉네임의 이름이 정확하지 않습니다."
                    },
                    maxLength: {
                      value: 10,
                      message: "닉네임의 이름이 정확하지 않습니다."
                    }
                  })}
              />
              <Alert>{errors.nickname?.message}</Alert>

              <DuplicatedBtnWrapper>
                <DuplicatedBtn type="submit">
                  중복확인
                </DuplicatedBtn>
              </DuplicatedBtnWrapper>
            </form>



            <Agreepersnal>
              <input type="checkbox" className='modalcheckbox' />
              <div className='persoanlcheck'>
                개인정보 수집 및 이용 동의
                <span className='personalimportant'>
                  (필수)
                </span>
              </div>
            </Agreepersnal>


            <div className='personal'>
              Ⅰ. 개인정보의 수집 및 이용 동의서
              - 이용자가 제공한 모든 정보는 다음의 목적을 위해 활용하며, 하기 목적 이외의 용도로는 사용되지 않습니다.
              ① 개인정보 수집 항목 및 수집·이용 목적
              가) 수집 항목 (필수항목)
              - 성명(국문), 주민등록번호, 주소, 전화번호(자택, 휴대전화), 사진, 이메일, 나이, 재학정보, 병역사항,
              외국어 점수, 가족관계, 재산정도, 수상내역, 사회활동, 타 장학금 수혜현황, 요식업 종사 현황 등 지원
              신청서에 기재된 정보 또는 신청자가 제공한 정보
              나) 수집 및 이용 목적
              - 하이트진로 장학생 선발 전형 진행
              - 하이트진로 장학생과의 연락 및 자격확인
              - 하이트진로 장학생 자원관리
              ② 개인정보 보유 및 이용기간
              - 수집·이용 동의일로부터 개인정보의 수집·이용목적을 달성할 때까지
              ③ 동의거부관리
              - 귀하께서는 본 안내에 따른 개인정보 수집, 이용에 대하여 동의를 거부하실 권리가 있습니다. 다만,
              귀하가 개인정보의 수집/이용에 동의를 거부하시는 경우에 장학생 선발 과정에 있어 불이익이 발생할 수
              있음을 알려드립니다.
            </div>
          </UserInfo>

          {mobileResize <= 480 ?
            <div className="prebutton" onMouseEnter={ismodalhover} onMouseLeave={ismodalhover}>
              {premodalhover ?
                <Image src={PreReservationBtnhover}
                  alt="모달사전예약호바"
                  width={177}
                  height={51} /> :
                <Image src={PreReservationBtn}
                  alt="모달사전예약"
                  width={177}
                  height={51} />}
            </div> :
            <div className="prebutton" onMouseEnter={ismodalhover} onMouseLeave={ismodalhover}>
              {premodalhover ?
                <Image src={PreReservationBtnhover}
                  alt="모달사전예약호바"
                  width={220}
                  height={63} /> :
                <Image src={PreReservationBtn}
                  alt="모달사전예약"
                  width={220}
                  height={63} />}
            </div>}

        </PreModalUiInner>


        {mobileResize <= 480 ?
          <Image src={MobileModalBackImg}
            layout="fill"
            width={375}
            height={812}
          /> :
          <Image src={ModalBackImg}
            layout="fill"
            width={1358}
            height={888}
          />}

      </PreModalUi>
    </PreModalWrapper>
  );
};

const PreModalWrapper = styled.div`
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.6);
  width: 100%;
  height: 100%;
  z-index: 20;
  

`
const PreModalUi = styled.div`
    position: relative;
    width: 70%;
    margin-top: 50px;
    margin-right: auto;
    margin-left: auto;
    height: 90vh;
    z-index: 100; 
    opacity: 1;

    @media screen and (max-width: ${SCREEN_SIZE.WIDTH.MOBILE}) {
      width: 100%;
      height: 100%;
      margin-top: 0px;
      }
  
    .personal {
      width: 100%;
      height: 228px;
      margin-top: 12px;
      background: #FFFFFF33 0% 0% no-repeat padding-box;
      border: 2px solid #FFFFFFB3;
      border-radius: 2px;
      opacity: 1;
      backdrop-filter: blur(10px);
      -webkit-backdrop-filter: blur(10px);
      overflow:auto;
      color:white;
      @media screen and (max-width: ${SCREEN_SIZE.WIDTH.MOBILE}) {
        height: 30vh;
      }
    }

    .prebutton {
      width: 220px;
      cursor:pointer;
      margin-top: 30px;
      margin-left: auto;
      margin-right: auto;
      @media screen and (max-width: ${SCREEN_SIZE.WIDTH.MOBILE}) {
        width: 177px;
        height: 51px;
        margin-top: 10px;
      }
  }
`

const PreModalUiInner = styled.div`
    z-index: 1;
    position: absolute;
    width: 100%;
    height:100%;

    `;

const ModalClose = styled.div`
    width: 100%;
    display: flex;
    justify-content: flex-end;
    margin-top: 18px;
    padding-right: 18px;
    cursor: pointer;
    
`
const ModalLogo = styled.div`
    width: 150px;
    height: 50px;
    margin: 30px auto 0px auto;
    @media screen and (max-width: ${SCREEN_SIZE.WIDTH.MOBILE}) {
      width: 120px;
      margin: 10px auto 20px auto;
      }
`

const UserInfo = styled.div`
    width: 70%;
    margin-left: auto;
    margin-right: auto;

    @media screen and (max-width: ${SCREEN_SIZE.WIDTH.MOBILE}) {
      width: 85%;
      }

    .userinfo--text {
      margin-top: 36px;
      font: normal normal normal 18px NanumSquare_ac;
      margin-left: 4px;
      letter-spacing: 0px;
      color: #FFFFFF;
      opacity: 0.9;
      @media screen and (max-width: ${SCREEN_SIZE.WIDTH.MOBILE}) {
        font: normal normal normal 15px NanumSquare_ac;
        }
    }

    .userinfo--important {
      font: normal normal normal 16px NanumSquare_ac;
      letter-spacing: 0px;
      color: #FFFFFF;
      opacity: 0.7;
      margin-left: 5px;
      @media screen and (max-width: ${SCREEN_SIZE.WIDTH.MOBILE}) {
        font: normal normal normal 13px NanumSquare_ac;
        }
    }


`

const DuplicatedBtnWrapper = styled.div`
    width: 100%;
    display: flex;
    justify-content: flex-end;
    margin-top: 10px;
    padding-right: 10px;
`
const DuplicatedBtn = styled.button`

    background: #FFFFFF33 0% 0% no-repeat padding-box;
    border: 1px solid #FFFFFFB3;
    border-radius: 2px;
    opacity: 0.9;
    color: #FFFFFF;
    display: inline-block; 
    cursor: pointer;
    padding: 6px 12px 6px 12px;
    :hover {
      background: #FFFFFF66 0% 0% no-repeat padding-box;
      border: 1px solid #FFFFFF;
      border-radius: 2px;
      opacity: 1;

    }
    @media screen and (max-width: ${SCREEN_SIZE.WIDTH.MOBILE}) {
      padding: 3px 6px 3px 6px;
      font-size: 12px;
      }
`

const Alert = styled.div`
  font: normal normal normal 12px NanumSquare_ac;
  margin-top: 2px;
  margin-left: 4px;
  letter-spacing: 0px;
  color: #FF4040;
  opacity: 0.8;
`;

const UserInfoPhone = styled.input`
    width: 100%;
    height: 42px;
    margin-top: 10px;
    background: #FFFFFF33 0% 0% no-repeat padding-box;
    border: 1.5px solid #FFFFFFB3;
    border-radius: 2px;
    opacity: 1;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    color: white;
    padding-left: 10px;
    font-size: 15px;
    :focus {
      outline: none;
    }

    @media screen and (max-width: ${SCREEN_SIZE.WIDTH.MOBILE}) {
      height: 32px;
      }
`

const UserInfoNick = styled.input`
  width: 100%;
  height: 42px;
  margin-top: 10px;
  background: #FFFFFF33 0% 0% no-repeat padding-box;
  border: 1.5px solid #FFFFFFB3;
  border-radius: 2px;
  opacity: 1;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: white;
  padding-left: 10px;
  font-size: 15px;
  :focus {
    outline: none;
  }
  @media screen and (max-width: ${SCREEN_SIZE.WIDTH.MOBILE}) {
    height: 32px;
    }
`

const Agreepersnal = styled.div`
  margin-top: 34px;
  display: flex;
  align-items: center;
  height: 32px;
  width: 100%;


  .modalcheckbox {
    width: 20px;
    height: 20px;
    background: #FFFFFF4D 0% 0% no-repeat padding-box;
    border: 2px solid #FFFFFFB3;
    border-radius: 2px;
    opacity: 1;
    @media screen and (max-width: ${SCREEN_SIZE.WIDTH.MOBILE}) {
      width: 16px;
      height: 16px;
      }
  }

  .persoanlcheck {
    text-align: left;
    margin-left: 5px;
    margin-bottom: 2px;
    font: normal normal normal 18px NanumSquare_ac;
    letter-spacing: 0px;
    color: white;
    opacity: 1;
    @media screen and (max-width: ${SCREEN_SIZE.WIDTH.MOBILE}) {
      font: normal normal normal 15px NanumSquare_ac;
      margin-bottom: 1px;
      }
  }

  .personalimportant {
    margin-left: 5px;
    text-align: left;
    font: normal normal normal 16px NanumSquare_ac;
    letter-spacing: 0px;
    color: #FFFFFF;
    opacity: 0.7;
    @media screen and (max-width: ${SCREEN_SIZE.WIDTH.MOBILE}) {
      font: normal normal normal 13px NanumSquare_ac;
      }
  }
`

export default PreModal;