From ecc239a2fec7a65df94e3e814b2274983554da3b Mon Sep 17 00:00:00 2001 From: sangminlee98 Date: Tue, 5 Sep 2023 18:31:38 +0900 Subject: [PATCH 01/11] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20UI=20=EC=95=BD=EA=B4=80=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EB=B0=8F=20=EC=A0=84=EC=B2=B4=EB=8F=99=EC=9D=98=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80,=20=EA=B3=B5=EC=9D=B8=EC=A4=91?= =?UTF-8?q?=EA=B0=9C=EC=82=AC=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20?= =?UTF-8?q?=EB=A7=81=ED=81=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Routes.tsx | 2 + src/components/Terms/MarketingTerm.tsx | 33 +++ src/components/Terms/PrivacyTerm.tsx | 36 +++ src/components/Terms/ServiceTerm.tsx | 313 +++++++++++++++++++++++ src/components/Terms/index.tsx | 324 ++---------------------- src/components/Terms/styles.module.scss | 2 +- src/pages/AgentSignUp/index.tsx | 3 + src/pages/SignUp/index.tsx | 116 ++++++++- src/pages/SignUp/styles.module.scss | 94 +++++++ src/types/signUp.ts | 1 + 10 files changed, 605 insertions(+), 319 deletions(-) create mode 100644 src/components/Terms/MarketingTerm.tsx create mode 100644 src/components/Terms/PrivacyTerm.tsx create mode 100644 src/components/Terms/ServiceTerm.tsx create mode 100644 src/pages/AgentSignUp/index.tsx create mode 100644 src/types/signUp.ts diff --git a/src/Routes.tsx b/src/Routes.tsx index 1db43e5..c7e09ef 100644 --- a/src/Routes.tsx +++ b/src/Routes.tsx @@ -5,6 +5,7 @@ import GlobalLayout from '@/pages/_layout'; const MainPage = lazy(() => import('@/pages/Main')); const LoginPage = lazy(() => import('@/pages/Login')); const SignUpPage = lazy(() => import('@/pages/SignUp')); +const AgentSignUpPage = lazy(() => import('@/pages/AgentSignUp')); const MyPage = lazy(() => import('@/pages/Mypage')); const IntroducePage = lazy(() => import('@/pages/Introduce')); const IntroWritePage = lazy(() => import('@/pages/Introduce/Write')); @@ -28,6 +29,7 @@ export const routes: RouteObject[] = [ { index: true, element: }, { path: 'login', element: }, { path: 'signup', element: }, + { path: 'agentSignup', element: }, { path: 'mypage', element: }, { path: 'introduce', element: }, { path: 'intro_write', element: }, diff --git a/src/components/Terms/MarketingTerm.tsx b/src/components/Terms/MarketingTerm.tsx new file mode 100644 index 0000000..16546e5 --- /dev/null +++ b/src/components/Terms/MarketingTerm.tsx @@ -0,0 +1,33 @@ +import styles from './styles.module.scss'; + +export type MarketingTermProps = { + onToggleClick: () => void; +}; + +export default function MarketingTerm({ onToggleClick }: MarketingTermProps) { + return ( +
+

마켓팅 활용 및 광고성 정보 수신 동의(선택)

+
+

+ 전자적 전송매체(SMS/MMS/이메일 등)를 통해, 주말내집이 제공하는 + 이벤트/혜택 등 다양한 정보(뉴스레터 포함)를 수신하실 수 있고, 기타 + 유용한 광고나 정보를 수신하실 수 있습니다. +

+

+ 본 마케팅 활용 및 광고성 정보수신 등의 항목은 선택사항이므로 동의를 + 거부하는 경우에도 주말내집 서비스의 이용에는 영향이 없습니다. 다만 + 거부시 동의를 통해 제공 가능한 각종 혜택, 이벤트 안내를 받아 보실 수 + 없습니다. +

+

+ 본 수신 동의를 철회하고자 할 경우에는 고객센터(주말내집 이메일)를 통해 + 언제든 수신동의를 철회를 요청하실 수 있습니다. +

+
+ +
+ ); +} diff --git a/src/components/Terms/PrivacyTerm.tsx b/src/components/Terms/PrivacyTerm.tsx new file mode 100644 index 0000000..a9ef530 --- /dev/null +++ b/src/components/Terms/PrivacyTerm.tsx @@ -0,0 +1,36 @@ +import styles from './styles.module.scss'; + +export type PrivacyTermProps = { + onToggleClick: () => void; +}; + +export default function PrivacyTerm({ onToggleClick }: PrivacyTermProps) { + return ( +
+

개인정보 수집 및 이용 동의(선택)

+
+
+

1. 개인정보의 수집·이용 목적

+

마케팅에의 활용.

+
+
+

2. 개인정보 보유 및 이용기간

+

회원 탈퇴 시까지

+
+
+

3. 처리하는 개인정보 항목

+

이름, 이메일 주소, 전화번호, 주거래 매물, 연령대

+
+

+ 이는 주말내집이 제공하는 서비스를 보다 원활하게 이용하도록 하기 위해서 + 그 수집 및 이용이 필요한 개인정보이므로 해당 항목에 동의를 거부하시는 + 경우에도 위 개인정보를 수집 및 이용하는 서비스를 제외하고 나머지 + 서비스에 대해서는 이용이 가능합니다. +

+
+ +
+ ); +} diff --git a/src/components/Terms/ServiceTerm.tsx b/src/components/Terms/ServiceTerm.tsx new file mode 100644 index 0000000..02b8be4 --- /dev/null +++ b/src/components/Terms/ServiceTerm.tsx @@ -0,0 +1,313 @@ +import styles from './styles.module.scss'; + +export type ServiceTermProps = { + onToggleClick: () => void; +}; + +export default function ServiceTerm({ onToggleClick }: ServiceTermProps) { + return ( +
+

이용약관(필수)

+
+

+ 총칙 +

+
+

제 1조(목적)

+

+ 주말내집 서비스 이용약관은 주말내집 (이하 “회사”)가 서비스를 + 제공함에 있어, 회사와 회원 간의 권리, 의무 및 책임 사항 등을 + 규정함을 목적으로 합니다. +

+
+
+

제 2조(정의)

+
    +
  1. 이 약관에서 사용하는 용어의 정의는 다음과 같습니다.
  2. +
      +
    • '회사'란, 서비스를 제공하는 주체를 말합니다.
    • +
    • + '서비스'란, 회사가 제공하는 모든 서비스 및 기능을 + 말합니다. +
    • +
    • + '회원'이란, 약관에 따라 서비스에 회원등록을 하고 + 서비스를 이용하는 자를 말합니다. +
    • +
    • + '계정'이란, 이용계약을 통해 생성된 회원의 고유 + 아이디와 이에 수반하는 정보를 말합니다. +
    • +
    • + '콘텐츠'란, 서비스에서 제공하는 모든 종류의 ‘대화 + 주제’ 등을 말합니다. +
    • +
    • + '관련법'이란, 정보통신망 이용촉진 및 정보보호 등에 + 관한 법률, 개인정보보호법, 통신비밀보호법을 비롯한 국내 법령을 + 말합니다. +
    • +
    +
  3. + 1항에서 정의되지 않는 약관 내 용어의 의미는 일반적인 이용관행에 + 의합니다. +
  4. +
+
+
+

+ 제 3조(약관 등의 명시와 설명 및 개정) +

+
    +
  1. 회사는 이 약관을 회원가입 화면 및 페이지 하단에 게시합니다.
  2. +
  3. + 회사는 관련법을 위배하지 않는 범위 내에서 이 약관을 개정할 수 + 있습니다. +
  4. +
  5. + 개정 내용이 회원에게 불리할 경우, 적용일자 및 개정사유를 명시하여 + 현행약관과 함께 알림 수단을 통해 고지하며 변경될 내용을 변경 30일 + 전에 미리 알려드리겠습니다. +
  6. +
  7. + 회원이 개정약관의 적용에 동의하지 않는 경우, 이용계약을 + 해지함으로써 거부 의사를 표시할 수 있습니다. 단, 30일 내에 거부 + 의사 표시를 하지 않을 경우 약관에 동의한 것으로 간주합니다. +
  8. +
  9. 회원은 본 약관의 일부분만을 동의 또는 거부할 수 없습니다.
  10. +
+
+
+

제 4조(서비스의 제공)

+
    +
  1. 회사는 다음 서비스를 제공합니다.
  2. +
      +
    • 오도이촌 소개 서비스
    • +
    • 커뮤니티 서비스
    • +
    • 마이페이지 서비스
    • +
    • 이벤트, 프로모션, 광고 정보 제공 서비스
    • +
    • 기타 회사가 정하는 서비스
    • +
    +
  3. + 회사는 운영상, 기술상의 필요에 따라 제공하고 있는 서비스를 변경할 + 수 있습니다. +
  4. +
  5. + 회사는 회원의 개인정보 및 서비스 이용 기록에 따라 서비스 이용에 + 차이를 둘 수 있습니다. +
  6. +
  7. + 회사는 천재지변, 인터넷 장애, 경영 악화 등으로 인해 서비스를 + 더이상 제공하기 어려울 경우, 서비스를 통보 없이 중단할 수 + 있습니다. +
  8. +
  9. + 회사는 1항부터 전항까지와 다음 내용으로 인해 발생한 피해에 대해 + 어떠한 책임도 지지 않습니다. +
  10. +
      +
    • + 모든 서비스, 콘텐츠, 이용 기록의 진본성, 무결성, 신뢰성, + 이용가능성 +
    • +
    • + 서비스 내에서 성사된 모임에서 발생한 금전적, 신체적, 정신적 피해 +
    • +
    • + 온라인, 오프라인에서의 서비스 이용 중 사용자에게 발생한 피해 +
    • +
    • + 광고의 버튼, 하이퍼링크 등 외부로 연결된 서비스와 같이 회사가 + 제공하지 않은 서비스에서 발생한 피해 +
    • +
    • + 회원의 귀책 사유 또는 회사의 귀책 사유가 아닌 사유로 발생한 + 회원의 피해 +
    • +
    +
+
+
+

제 5조(서비스 이용계약의 성립)

+
    +
  1. + 회사와 회원의 서비스 이용계약은 서비스 내부의 회원가입 화면 가입 + 양식에 따라 회원정보를 기입한 후 필수 약관에 동의한다는 의사표시를 + 하면서 체결됩니다. +
  2. +
  3. + 회원은 회사에서 제공하는 절차에 따라 회원가입을 진행해야 하며, + 반드시 실제 이메일과 생년월일을 사용해야 합니다. 실제 정보를 + 입력하지 않은 이용자는 법적인 보호를 받을 수 없으며, 서비스 이용에 + 제한을 받을 수 있습니다 +
  4. +
+
+
+

제 6조(개인정보의 관리 및 보호)

+
    +
  1. + 회원이 회사와 체결한 서비스 이용계약은 처음 이용계약을 체결한 + 본인에 한해 적용됩니다. +
  2. +
  3. + 회원의 이메일과 비밀번호, 닉네임 등 모든 개인정보의 관리책임은 + 본인에게 있으므로, 타인에게 양도 및 대여할 수 없으며, 유출되지 + 않도록 관리해야합니다. 만약 본인의 이메일 및 비밀번호를 타인이 + 사용하고 있음을 인지했을 경우 즉시 비밀번호를 변경해야 합니다. +
  4. +
  5. + 회사는 2항부터 전항까지를 이행하지 않아 발생한 피해에 대해 어떠한 + 책임을 지지 않습니다. +
  6. +
+
+
+

제 7조(서비스 이용계약의 종료)

+
    +
  1. + 회원은 언제든지 본인의 계정으로 로그인한 뒤 서비스 내부의 + '회원 탈퇴' 버튼을 누르는 방법으로 탈퇴를 요청할 수 + 있으며, 문의 창구를 통한 탈퇴 요청 등은 처리되지 않습니다. 회사는 + 해당 요청을 확인한 후 탈퇴를 처리합니다. +
  2. +
  3. + 회사는 천재지변, 서비스 종료 등 불가피한 사유로 더이상 서비스를 + 제공할 수 없을 경우, 회원의 동의 없이 회원자격을 박탈할 수 + 있습니다. +
  4. +
  5. + 회사는 1항부터 전항까지로 인해 발생한 피해에 대해 어떠한 책임을 + 지지 않습니다. +
  6. +
+
+
+

제 8조(회원에 대한 통보)

+
    +
  1. + 회사가 회원에 대한 통보를 하는 경우, 회원이 회원가입 시 입력한 + 이메일을 이용합니다. +
  2. +
  3. + 회사는 다수의 회원에 대한 통보를 할 경우 서비스 내부 알림 메시지를 + 띄우는 등의 방법을 통해 개별 통보에 갈음할 수 있습니다. +
  4. +
  5. + 회원이 30일 이내에 의사표시를 하지 않을 경우, 통보 내용에 대해 + 동의한 것으로 간주합니다. +
  6. +
+
+
+

제 9조(저작권의 귀속)

+
    +
  1. + 회사는 유용하고 편리한 서비스를 제공하기 위해, 2022년부터 서비스 + 및 서비스 내부의 기능 체계와 다양한 기능을 직접 설계 및 운영하고 + 있는 데이터베이스 제작자에 해당합니다. 회사는 저작권법에 따라 + 데이터베이스 제작자는 복제권 및 전송권을 포함한 데이터베이스 + 전부에 대한 권리를 가지고 있으며, 이는 법률에 따라 보호를 받는 + 대상입니다. 그러므로 회원은 데이터 베이스 제작자인 회사의 승인 + 없이 데이터베이스의 전부 또는 일부를 복제・배포・방송 또는 전송할 + 수 없습니다. +
  2. +
  3. + 회사가 작성한 콘텐츠에 대한 권리는 회사에 귀속됩니다. 회원은 + 별도의 허락 없이 회사의 콘텐츠에 대해 본래의 서비스 이용을 제외한 + 목적으로 사용, 수정, 배포할 수 없습니다 +
  4. +
+
+
+

제 10조(광고의 게재)

+
    +
  1. + 회사는 서비스의 운용과 관련하여 서비스 화면, 홈페이지, 이메일 등에 + 광고를 게재할 수 있습니다. +
  2. +
  3. + 회사는 서비스에 게재되어 있는 광고주의 판촉활동에 회원이 + 참여하거나 교신 또는 거래의 결과로 인해 발생하는 모든 손실 및 + 손해에 대해 책임을 지지 않습니다. +
  4. +
+
+
+

제 11조(금지행위)

+
    +
  1. 회원에 의한 다음 행위는 금지되어 있습니다.
  2. +
      +
    • 개인정보 또는 계정 기만, 침해, 공유 행위
    • +
    • 개인정보를 허위, 누락, 오기, 도용하여 작성하는 행위
    • +
    • 타인의 개인정보 및 계정을 수집, 저장, 공개, 이용하는 행위
    • +
    • 자신과 타인의 개인정보를 제 3자에게 공개, 양도하는 행위
    • +
    • 시스템 부정행위
    • +
    • 허가하지 않은 방식의 서비스 이용 행위
    • +
    • 회사의 모든 재산에 대한 침해 행위
    • +
    • 업무 방해 행위
    • +
    • + 서비스 관리자 또는 이에 준하는 자격을 사칭하거나 허가없이 + 취득하여 직권을 행사하는 행위 +
    • +
    • 회사 및 타인의 명예를 손상시키거나 업무를 방해하는 행위
    • +
    • + 서비스 내부 정보 일체를 허가 없이 이용, 변조, 삭제 및 외부로 + 유출하는 행위 +
    • +
    • + 이 약관, 개인정보 처리방침에서 이행 및 비이행을 명시한 내용에 + 반하는 행위 +
    • +
    • 기타 현행법에 어긋나거나 부적절하다고 판단되는 행위
    • +
    +
  3. + 회원이 1항에 해당하는 행위를 할 경우, 회사는 다음과 같은 조치를 + 영구적으로 취할 수 있습니다. +
  4. +
      +
    • 회원의 서비스 이용 권한, 자격, 혜택 제한 및 회수
    • +
    • 회원과 체결된 이용계약을 회원의 동의나 통보 없이 파기
    • +
    • 회원가입 거부
    • +
    • 그 외 회사가 필요하다고 판단되는 조치
    • +
    +
  5. + 회사는 1항부터 전항까지로 인해 발생한 피해에 대해 어떠한 책임을 + 지지 않으며, 회원은 귀책사유로 인해 발생한 모든 손해를 배상할 + 책임이 있습니다. +
  6. +
+
+
+

제 12조(재판권 및 준거법)

+
    +
  1. + 회사와 회원 간에 발생한 분쟁에 관한 소송은 대한민국 + 서울중앙지방법원을 관할 법원으로 합니다. 다만, 제소 당시 회원의 + 주소 또는 거소가 분명하지 않거나 외국 거주자의 경우에는 + 민사소송법상의 관할법원에 제기합니다. +
  2. +
  3. 회사와 회원 간에 제기된 소송에는 한국법을 적용합니다.
  4. +
+
+
+

제 13조(기타)

+
    +
  1. 이 약관은 2023년 1월 27일에 제정되었습니다.
  2. +
  3. + 이 약관에서 정하지 아니한 사항과 이 약관의 해석에 관하여는 관련법 + 또는 관례에 따릅니다. +
  4. +
  5. + 이 약관에도 불구하고 다른 약관이나 서비스 이용 중 안내 문구 등으로 + 달리 정함이 있는 경우에는 해당 내용을 우선으로 합니다. +
  6. +
+
+
+ +
+ ); +} diff --git a/src/components/Terms/index.tsx b/src/components/Terms/index.tsx index 8dce9bb..2455402 100644 --- a/src/components/Terms/index.tsx +++ b/src/components/Terms/index.tsx @@ -1,11 +1,16 @@ import React from 'react'; +import { TermType } from '@/types/signUp'; +import MarketingTerm from './MarketingTerm'; +import PrivacyTerm from './PrivacyTerm'; +import ServiceTerm from './ServiceTerm'; import styles from './styles.module.scss'; type TermsProps = { + selectedTerm: TermType; setToggle: React.Dispatch>; }; -export default function Terms({ setToggle }: TermsProps) { +export default function Terms({ selectedTerm, setToggle }: TermsProps) { const onToggleClick = () => { const bodyEl = document.querySelector('body'); bodyEl?.classList.remove('over_hidden'); @@ -13,314 +18,15 @@ export default function Terms({ setToggle }: TermsProps) { }; return (
-
-

이용약관(필수)

-
-

- 총칙 -

-
-

제 1조(목적)

-

- 주말내집 서비스 이용약관은 주말내집 (이하 “회사”)가 서비스를 - 제공함에 있어, 회사와 회원 간의 권리, 의무 및 책임 사항 등을 - 규정함을 목적으로 합니다. -

-
-
-

제 2조(정의)

-
    -
  1. 이 약관에서 사용하는 용어의 정의는 다음과 같습니다.
  2. -
      -
    • '회사'란, 서비스를 제공하는 주체를 말합니다.
    • -
    • - '서비스'란, 회사가 제공하는 모든 서비스 및 기능을 - 말합니다. -
    • -
    • - '회원'이란, 약관에 따라 서비스에 회원등록을 하고 - 서비스를 이용하는 자를 말합니다. -
    • -
    • - '계정'이란, 이용계약을 통해 생성된 회원의 고유 - 아이디와 이에 수반하는 정보를 말합니다. -
    • -
    • - '콘텐츠'란, 서비스에서 제공하는 모든 종류의 ‘대화 - 주제’ 등을 말합니다. -
    • -
    • - '관련법'이란, 정보통신망 이용촉진 및 정보보호 등에 - 관한 법률, 개인정보보호법, 통신비밀보호법을 비롯한 국내 법령을 - 말합니다. -
    • -
    -
  3. - 1항에서 정의되지 않는 약관 내 용어의 의미는 일반적인 이용관행에 - 의합니다. -
  4. -
-
-
-

- 제 3조(약관 등의 명시와 설명 및 개정) -

-
    -
  1. - 회사는 이 약관을 회원가입 화면 및 페이지 하단에 게시합니다. -
  2. -
  3. - 회사는 관련법을 위배하지 않는 범위 내에서 이 약관을 개정할 수 - 있습니다. -
  4. -
  5. - 개정 내용이 회원에게 불리할 경우, 적용일자 및 개정사유를 - 명시하여 현행약관과 함께 알림 수단을 통해 고지하며 변경될 내용을 - 변경 30일 전에 미리 알려드리겠습니다. -
  6. -
  7. - 회원이 개정약관의 적용에 동의하지 않는 경우, 이용계약을 - 해지함으로써 거부 의사를 표시할 수 있습니다. 단, 30일 내에 거부 - 의사 표시를 하지 않을 경우 약관에 동의한 것으로 간주합니다. -
  8. -
  9. 회원은 본 약관의 일부분만을 동의 또는 거부할 수 없습니다.
  10. -
-
-
-

제 4조(서비스의 제공)

-
    -
  1. 회사는 다음 서비스를 제공합니다.
  2. -
      -
    • 오도이촌 소개 서비스
    • -
    • 커뮤니티 서비스
    • -
    • 마이페이지 서비스
    • -
    • 이벤트, 프로모션, 광고 정보 제공 서비스
    • -
    • 기타 회사가 정하는 서비스
    • -
    -
  3. - 회사는 운영상, 기술상의 필요에 따라 제공하고 있는 서비스를 - 변경할 수 있습니다. -
  4. -
  5. - 회사는 회원의 개인정보 및 서비스 이용 기록에 따라 서비스 이용에 - 차이를 둘 수 있습니다. -
  6. -
  7. - 회사는 천재지변, 인터넷 장애, 경영 악화 등으로 인해 서비스를 - 더이상 제공하기 어려울 경우, 서비스를 통보 없이 중단할 수 - 있습니다. -
  8. -
  9. - 회사는 1항부터 전항까지와 다음 내용으로 인해 발생한 피해에 대해 - 어떠한 책임도 지지 않습니다. -
  10. -
      -
    • - 모든 서비스, 콘텐츠, 이용 기록의 진본성, 무결성, 신뢰성, - 이용가능성 -
    • -
    • - 서비스 내에서 성사된 모임에서 발생한 금전적, 신체적, 정신적 - 피해 -
    • -
    • - 온라인, 오프라인에서의 서비스 이용 중 사용자에게 발생한 피해 -
    • -
    • - 광고의 버튼, 하이퍼링크 등 외부로 연결된 서비스와 같이 회사가 - 제공하지 않은 서비스에서 발생한 피해 -
    • -
    • - 회원의 귀책 사유 또는 회사의 귀책 사유가 아닌 사유로 발생한 - 회원의 피해 -
    • -
    -
-
-
-

제 5조(서비스 이용계약의 성립)

-
    -
  1. - 회사와 회원의 서비스 이용계약은 서비스 내부의 회원가입 화면 가입 - 양식에 따라 회원정보를 기입한 후 필수 약관에 동의한다는 - 의사표시를 하면서 체결됩니다. -
  2. -
  3. - 회원은 회사에서 제공하는 절차에 따라 회원가입을 진행해야 하며, - 반드시 실제 이메일과 생년월일을 사용해야 합니다. 실제 정보를 - 입력하지 않은 이용자는 법적인 보호를 받을 수 없으며, 서비스 - 이용에 제한을 받을 수 있습니다 -
  4. -
-
-
-

제 6조(개인정보의 관리 및 보호)

-
    -
  1. - 회원이 회사와 체결한 서비스 이용계약은 처음 이용계약을 체결한 - 본인에 한해 적용됩니다. -
  2. -
  3. - 회원의 이메일과 비밀번호, 닉네임 등 모든 개인정보의 관리책임은 - 본인에게 있으므로, 타인에게 양도 및 대여할 수 없으며, 유출되지 - 않도록 관리해야합니다. 만약 본인의 이메일 및 비밀번호를 타인이 - 사용하고 있음을 인지했을 경우 즉시 비밀번호를 변경해야 합니다. -
  4. -
  5. - 회사는 2항부터 전항까지를 이행하지 않아 발생한 피해에 대해 - 어떠한 책임을 지지 않습니다. -
  6. -
-
-
-

제 7조(서비스 이용계약의 종료)

-
    -
  1. - 회원은 언제든지 본인의 계정으로 로그인한 뒤 서비스 내부의 - '회원 탈퇴' 버튼을 누르는 방법으로 탈퇴를 요청할 수 - 있으며, 문의 창구를 통한 탈퇴 요청 등은 처리되지 않습니다. - 회사는 해당 요청을 확인한 후 탈퇴를 처리합니다. -
  2. -
  3. - 회사는 천재지변, 서비스 종료 등 불가피한 사유로 더이상 서비스를 - 제공할 수 없을 경우, 회원의 동의 없이 회원자격을 박탈할 수 - 있습니다. -
  4. -
  5. - 회사는 1항부터 전항까지로 인해 발생한 피해에 대해 어떠한 책임을 - 지지 않습니다. -
  6. -
-
-
-

제 8조(회원에 대한 통보)

-
    -
  1. - 회사가 회원에 대한 통보를 하는 경우, 회원이 회원가입 시 입력한 - 이메일을 이용합니다. -
  2. -
  3. - 회사는 다수의 회원에 대한 통보를 할 경우 서비스 내부 알림 - 메시지를 띄우는 등의 방법을 통해 개별 통보에 갈음할 수 있습니다. -
  4. -
  5. - 회원이 30일 이내에 의사표시를 하지 않을 경우, 통보 내용에 대해 - 동의한 것으로 간주합니다. -
  6. -
-
-
-

제 9조(저작권의 귀속)

-
    -
  1. - 회사는 유용하고 편리한 서비스를 제공하기 위해, 2022년부터 서비스 - 및 서비스 내부의 기능 체계와 다양한 기능을 직접 설계 및 운영하고 - 있는 데이터베이스 제작자에 해당합니다. 회사는 저작권법에 따라 - 데이터베이스 제작자는 복제권 및 전송권을 포함한 데이터베이스 - 전부에 대한 권리를 가지고 있으며, 이는 법률에 따라 보호를 받는 - 대상입니다. 그러므로 회원은 데이터 베이스 제작자인 회사의 승인 - 없이 데이터베이스의 전부 또는 일부를 복제・배포・방송 또는 - 전송할 수 없습니다. -
  2. -
  3. - 회사가 작성한 콘텐츠에 대한 권리는 회사에 귀속됩니다. 회원은 - 별도의 허락 없이 회사의 콘텐츠에 대해 본래의 서비스 이용을 - 제외한 목적으로 사용, 수정, 배포할 수 없습니다 -
  4. -
-
-
-

제 10조(광고의 게재)

-
    -
  1. - 회사는 서비스의 운용과 관련하여 서비스 화면, 홈페이지, 이메일 - 등에 광고를 게재할 수 있습니다. -
  2. -
  3. - 회사는 서비스에 게재되어 있는 광고주의 판촉활동에 회원이 - 참여하거나 교신 또는 거래의 결과로 인해 발생하는 모든 손실 및 - 손해에 대해 책임을 지지 않습니다. -
  4. -
-
-
-

제 11조(금지행위)

-
    -
  1. 회원에 의한 다음 행위는 금지되어 있습니다.
  2. -
      -
    • 개인정보 또는 계정 기만, 침해, 공유 행위
    • -
    • 개인정보를 허위, 누락, 오기, 도용하여 작성하는 행위
    • -
    • - 타인의 개인정보 및 계정을 수집, 저장, 공개, 이용하는 행위 -
    • -
    • 자신과 타인의 개인정보를 제 3자에게 공개, 양도하는 행위
    • -
    • 시스템 부정행위
    • -
    • 허가하지 않은 방식의 서비스 이용 행위
    • -
    • 회사의 모든 재산에 대한 침해 행위
    • -
    • 업무 방해 행위
    • -
    • - 서비스 관리자 또는 이에 준하는 자격을 사칭하거나 허가없이 - 취득하여 직권을 행사하는 행위 -
    • -
    • 회사 및 타인의 명예를 손상시키거나 업무를 방해하는 행위
    • -
    • - 서비스 내부 정보 일체를 허가 없이 이용, 변조, 삭제 및 외부로 - 유출하는 행위 -
    • -
    • - 이 약관, 개인정보 처리방침에서 이행 및 비이행을 명시한 내용에 - 반하는 행위 -
    • -
    • 기타 현행법에 어긋나거나 부적절하다고 판단되는 행위
    • -
    -
  3. - 회원이 1항에 해당하는 행위를 할 경우, 회사는 다음과 같은 조치를 - 영구적으로 취할 수 있습니다. -
  4. -
      -
    • 회원의 서비스 이용 권한, 자격, 혜택 제한 및 회수
    • -
    • 회원과 체결된 이용계약을 회원의 동의나 통보 없이 파기
    • -
    • 회원가입 거부
    • -
    • 그 외 회사가 필요하다고 판단되는 조치
    • -
    -
  5. - 회사는 1항부터 전항까지로 인해 발생한 피해에 대해 어떠한 책임을 - 지지 않으며, 회원은 귀책사유로 인해 발생한 모든 손해를 배상할 - 책임이 있습니다. -
  6. -
-
-
-

제 12조(재판권 및 준거법)

-
    -
  1. - 회사와 회원 간에 발생한 분쟁에 관한 소송은 대한민국 - 서울중앙지방법원을 관할 법원으로 합니다. 다만, 제소 당시 회원의 - 주소 또는 거소가 분명하지 않거나 외국 거주자의 경우에는 - 민사소송법상의 관할법원에 제기합니다. -
  2. -
  3. 회사와 회원 간에 제기된 소송에는 한국법을 적용합니다.
  4. -
-
-
-

제 13조(기타)

-
    -
  1. 이 약관은 2023년 1월 27일에 제정되었습니다.
  2. -
  3. - 이 약관에서 정하지 아니한 사항과 이 약관의 해석에 관하여는 - 관련법 또는 관례에 따릅니다. -
  4. -
  5. - 이 약관에도 불구하고 다른 약관이나 서비스 이용 중 안내 문구 - 등으로 달리 정함이 있는 경우에는 해당 내용을 우선으로 합니다. -
  6. -
-
-
- -
+ {selectedTerm === 'SERVICE' && ( + + )} + {selectedTerm === 'PRIVACY' && ( + + )} + {selectedTerm === 'MARKETING' && ( + + )}
); } diff --git a/src/components/Terms/styles.module.scss b/src/components/Terms/styles.module.scss index b4c065b..35de5d4 100644 --- a/src/components/Terms/styles.module.scss +++ b/src/components/Terms/styles.module.scss @@ -14,7 +14,7 @@ display: flex; flex-direction: column; width: 38.25rem; - height: 51.5rem; + max-height: 51.5rem; background-color: white; border-radius: 25px; & > h1 { diff --git a/src/pages/AgentSignUp/index.tsx b/src/pages/AgentSignUp/index.tsx new file mode 100644 index 0000000..0462ac2 --- /dev/null +++ b/src/pages/AgentSignUp/index.tsx @@ -0,0 +1,3 @@ +export default function AgentSignUpPage() { + return
공인중개사 회원가입 페이지
; +} diff --git a/src/pages/SignUp/index.tsx b/src/pages/SignUp/index.tsx index 0bafba6..dfc9351 100644 --- a/src/pages/SignUp/index.tsx +++ b/src/pages/SignUp/index.tsx @@ -10,6 +10,7 @@ import { restFetcher } from '@/queryClient'; import Terms from '@/components/Terms'; import userStore from '@/store/userStore'; import useCheckAPI from '@/hooks/useCheckAPI'; +import { TermType } from '@/types/signUp'; import { opacityVariants } from '@/constants/variants'; import styles from './styles.module.scss'; @@ -22,7 +23,7 @@ type IForm = { phone_check: string; age: string; join_paths: string[]; - terms: boolean; + service_term: boolean; }; type ISubmitForm = { email: string; @@ -38,6 +39,7 @@ export default function SignUpPage() { register, watch, handleSubmit, + setValue, formState: { errors }, } = useForm({ mode: 'onSubmit', @@ -93,6 +95,11 @@ export default function SignUpPage() { const [phoneSMSCheck, setPhoneSMSCheck] = useState(false); // 전화번호 인증 완료 상태 const [phoneSMSMessage, setPhoneSMSMessage] = useState(); // 전화번호 인증 완료 상태 const [phoneErrMessage, setPhoneErrMessage] = useState(); // 전화번호 에러 메세지 + const [isServiceTerm, setIsServiceTerm] = useState(false); + const [isPrivacyTerm, setIsPrivacyTerm] = useState(false); + const [isMarketingTerm, setIsMarketingTerm] = useState(false); + const [selectedTerm, setSelectedTerm] = useState(''); + const [ idCheck, idCheckMessage, @@ -121,10 +128,11 @@ export default function SignUpPage() { '이미 존재하는 닉네임 입니다.', '닉네임 형식에 맞지 않습니다.', ); - const onToggleClick = () => { + const onToggleClick = (term: TermType) => { const bodyEl = document.querySelector('body'); bodyEl?.classList.add('over_hidden'); setToggle(true); + setSelectedTerm(term); }; const onEyeClick = (e: React.MouseEvent) => { if (e.currentTarget.id === 'passwordEye') setEyeState((prev) => !prev); @@ -199,6 +207,12 @@ export default function SignUpPage() { }, ); }; + + const handleAllSelect = (isSelected: boolean) => { + setIsServiceTerm(isSelected); + setIsPrivacyTerm(isSelected); + setIsMarketingTerm(isSelected); + }; useEffect(() => { onChangeInput(setIdCheck, setIdCheckMessage, '아이디'); }, [watch('email')]); @@ -221,6 +235,18 @@ export default function SignUpPage() { className={styles.container} > 로고 + +

+ 공인중개사 회원이신가요? +

+ +
@@ -555,28 +581,98 @@ export default function SignUpPage() {
- +
+ + + { + handleAllSelect( + !(isServiceTerm && isPrivacyTerm && isMarketingTerm), + ); + setValue('service_term', !isServiceTerm, { + shouldValidate: true, + }); + }} + checked={isServiceTerm && isPrivacyTerm && isMarketingTerm} + /> + + +
{ + setIsServiceTerm((prev) => !prev); + }, + })} + checked={isServiceTerm} /> - +

- {errors.terms && errors.terms.message} + {errors.service_term && errors.service_term.message}

+ +
+ + setIsPrivacyTerm((prev) => !prev)} + /> + + + +
+ +
+ + setIsMarketingTerm((prev) => !prev)} + /> + + + +
+ +
+ {/* 상세 주소 */} + + + {/* 이메일 */} +
+ +
+ + +
+
+
+ {/* 아이디 */} +
+ +
+ + +
+
+ {/* 비밀번호 */} +
+ +
+ +
+
+ {/* 비밀번호 확인 */} +
+ +
+ +
+
+ {/* 닉네임 */} +
+ +
+ + +
+
+ {/* 휴대폰 */} +
+ +
+ + +
+
+ {/* 주거래 매물 */} +
+ +
+ + + + + + + + + + + + +
+
+ {/* 연령대 */} +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+
+ {/* 가입경로 */} +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ {/* 약관 */} +
+
+ + + + + +
+
+ + + + + +
+
+ + + + + +
+ +
+ + + + + +
+
+ + + + + ); +} diff --git a/src/pages/SignUp/AgentSignUp/styles.module.scss b/src/pages/SignUp/AgentSignUp/styles.module.scss new file mode 100644 index 0000000..81b3de7 --- /dev/null +++ b/src/pages/SignUp/AgentSignUp/styles.module.scss @@ -0,0 +1,49 @@ +.subtitle { + display: flex; + flex-direction: column; + align-items: center; + margin-top: 1.75rem; + & > h3 { + font-size: 1.5rem; + font-weight: 600; + color: var(--basic-text-color); + & > strong { + color: var(--main-color); + } + } +} + +.descriptionWrapper { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 1.5rem; + width: 33rem; + margin-top: 2.5rem; + margin-bottom: 5rem; + padding: 1rem 1.5rem; + background-color: #eceff0; + border-radius: 0.625rem; + font-size: 1.25rem; + line-height: 1.5rem; + color: var(--basic-text-color); + & > div { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + } + & > ul { + margin-left: 1.5rem; + box-sizing: content-box; + display: flex; + flex-direction: column; + justify-content: center; + align-items: flex-start; + list-style-type: disc; + } + & strong { + font-weight: 600; + } +} diff --git a/src/pages/SignUp/styles.module.scss b/src/pages/SignUp/styles.module.scss index a6ceb11..e7b4bac 100644 --- a/src/pages/SignUp/styles.module.scss +++ b/src/pages/SignUp/styles.module.scss @@ -7,6 +7,7 @@ justify-content: center; align-items: center; background-color: var(--background-color); + font-family: 'Pretendard'; } .logo { width: 20rem; diff --git a/src/pages/Trade/Write/index.tsx b/src/pages/Trade/Write/index.tsx index c231283..a971731 100644 --- a/src/pages/Trade/Write/index.tsx +++ b/src/pages/Trade/Write/index.tsx @@ -46,6 +46,14 @@ export default function TradeWritePage() { // const appendSpecialCategory = (category: string) => {}; const [isPostcodeOpen, setIsPostcodeOpen] = useState(false); + const postCodeCallback = (fullAddress: string, zipCode?: string) => { + setForm((prev: TradeBoardForm) => ({ + ...prev, + city: fullAddress, + zipCode: zipCode ?? '', + })); + }; + const onChangeForm = (e: React.ChangeEvent) => { const { name, value } = e.target; @@ -79,7 +87,10 @@ export default function TradeWritePage() { animate="mount" > {isPostcodeOpen && ( - + )}
매물 등록 diff --git a/src/styles/reset.scss b/src/styles/reset.scss index f7cdd07..3f0efcd 100644 --- a/src/styles/reset.scss +++ b/src/styles/reset.scss @@ -11,6 +11,7 @@ --gray-background: #eaeeef; --background-color: #f8fafb; --sub-color: #5772ff; + --basic-text-color: #4d5256; } html, From 68dd29d03cdc024d759c03ab77d8541edc071e6b Mon Sep 17 00:00:00 2001 From: sangminlee98 Date: Tue, 19 Sep 2023 06:36:01 +0900 Subject: [PATCH 03/11] =?UTF-8?q?feat:=20=EA=B3=B5=EC=9D=B8=EC=A4=91?= =?UTF-8?q?=EA=B0=9C=EC=82=AC=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20API?= =?UTF-8?q?=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/SignUp/AgentSignUp/index.tsx | 737 +++++++++++++++++++++++-- src/pages/SignUp/index.tsx | 2 +- 2 files changed, 688 insertions(+), 51 deletions(-) diff --git a/src/pages/SignUp/AgentSignUp/index.tsx b/src/pages/SignUp/AgentSignUp/index.tsx index 89a5bfe..77434b0 100644 --- a/src/pages/SignUp/AgentSignUp/index.tsx +++ b/src/pages/SignUp/AgentSignUp/index.tsx @@ -1,23 +1,260 @@ -import { useState } from 'react'; -import { Navigate } from 'react-router-dom'; +import { useEffect, useState } from 'react'; +import { useForm } from 'react-hook-form'; +import { Navigate, useNavigate } from 'react-router-dom'; +import { useMutation } from '@tanstack/react-query'; import { motion } from 'framer-motion'; +import eyeImage from '@/assets/common/eye.svg'; +import eyeClosedImage from '@/assets/common/eyeClosed.svg'; import logoImage from '@/assets/common/logo.svg'; import AddressModal from '@/components/Trade/AddressModal'; +import { restFetcher } from '@/queryClient'; +import Terms from '@/components/Terms'; import userStore from '@/store/userStore'; +import useCheckAPI from '@/hooks/useCheckAPI'; +import { TermType } from '@/types/signUp'; import { opacityVariants } from '@/constants/variants'; import styles from './styles.module.scss'; import signUpStyles from '../styles.module.scss'; +type IForm = { + email: string; + password: string; + password_check: string; + nick_name: string; + phone_num: string; + phone_check: string; + age: string; + join_paths: string[]; + agent_code: string; + business_code: string; + company_name: string; + agent_name: string; + company_phone_num: string; + assistant_name: string | null; + company_address: string; + company_address_detail: string; + company_email: string; + estate: string; + service_term: boolean; +}; +type ISubmitForm = { + email: string; + password: string; + nick_name: string; + phone_num: string; + age: string; + join_paths: string[]; + agent_code: string; + business_code: string; + company_name: string; + agent_name: string; + company_phone_num: string; + assistant_name: string | null; + company_address: string; + company_address_detail: string; + company_email: string; + estate: string; +}; + export default function AgentSignUpPage() { const { token } = userStore(); - const [isPostcodeOpen, setIsPostcodeOpen] = useState(false); + const navigate = useNavigate(); + + const [toggle, setToggle] = useState(false); // 약관 토글 + const [isPostcodeOpen, setIsPostcodeOpen] = useState(false); // 주소 모달 토글 + const [eyeState, setEyeState] = useState(false); + const [eyeCheckState, setEyeCheckState] = useState(false); + const [isCheckNum, setIsCheckNum] = useState(false); // 전화번호 인증 중 상태 + const [phoneSMSCheck, setPhoneSMSCheck] = useState(false); // 전화번호 인증 완료 상태 + const [phoneSMSMessage, setPhoneSMSMessage] = useState(); // 전화번호 인증 완료 상태 + const [phoneErrMessage, setPhoneErrMessage] = useState(); // 전화번호 에러 메세지 + const [isServiceTerm, setIsServiceTerm] = useState(false); + const [isPrivacyTerm, setIsPrivacyTerm] = useState(false); + const [isMarketingTerm, setIsMarketingTerm] = useState(false); + const [selectedTerm, setSelectedTerm] = useState(''); - const [companyAddress, setCompanyAddress] = useState(''); + const { + register, + watch, + handleSubmit, + setValue, + formState: { errors }, + } = useForm(); + + const { mutate: idCheckAPI } = useMutation((email: string) => + restFetcher({ + method: 'POST', + path: '/users/check/email', + body: { email }, + }), + ); + const { mutate: nicknameCheckAPI } = useMutation((nick_name: string) => + restFetcher({ + method: 'POST', + path: '/users/check/nick-name', + body: { nick_name }, + }), + ); + const { mutate: phoneSMSAPI } = useMutation((phone_num: string) => + restFetcher({ + method: 'POST', + path: '/users/send/sms', + body: { phone_num }, + }), + ); + const { mutate: phoneCheckAPI } = useMutation((phone_check: string) => + restFetcher({ + method: 'POST', + path: '/users/check/sms', + body: { phone_num: watch('phone_num'), code: phone_check }, + }), + ); + const { mutate: singUpAPI } = useMutation((form: ISubmitForm) => + restFetcher({ + method: 'POST', + path: '/users/sign-up', + body: form, + }), + ); + + const [ + idCheck, + idCheckMessage, + idCheckHandler, + setIdCheck, + setIdCheckMessage, + ] = useCheckAPI( + idCheckAPI, + /^(?=.*[A-Za-z])[A-Za-z_0-9]{4,20}$/g, + watch('email'), + '사용가능한 ID입니다.', + '이미 존재하는 아이디 입니다.', + '4~20자리/영문, 숫자, 특수문자’_’만 사용해주세요.', + ); + const [ + nicknameCheck, + nicknameCheckMessage, + nicknameCheckHandler, + setNicknameCheck, + setNicknameCheckMessage, + ] = useCheckAPI( + nicknameCheckAPI, + /^(?=.*[a-zA-Z0-9가-힣])[A-Za-z0-9가-힣]{1,20}$/g, + watch('nick_name'), + '사용가능한 닉네임입니다.', + '이미 존재하는 닉네임 입니다.', + '닉네임 형식에 맞지 않습니다.', + ); + const onToggleClick = (term: TermType) => { + const bodyEl = document.querySelector('body'); + bodyEl?.classList.add('over_hidden'); + setToggle(true); + setSelectedTerm(term); + }; + const onEyeClick = (e: React.MouseEvent) => { + if (e.currentTarget.id === 'passwordEye') setEyeState((prev) => !prev); + else setEyeCheckState((prev) => !prev); + }; + const onSendSMS = () => { + if (/^01(?:0|1|[6-9])[0-9]{7,8}$/g.test(watch('phone_num')) === false) + return; + phoneSMSAPI(watch('phone_num'), { + onSuccess: (res) => { + if (!res) throw Error; + setPhoneErrMessage(undefined); + setIsCheckNum(true); + }, + onError: () => { + setPhoneErrMessage('이미 가입된 전화번호입니다.'); + }, + }); + }; + const onCheckSMS = () => { + if (/^(?=.*[0-9])[0-9]{4}$/g.test(watch('phone_check')) === false) { + setPhoneSMSCheck(false); + setPhoneSMSMessage('잘못된 인증번호입니다.'); + } + phoneCheckAPI(watch('phone_check'), { + onSuccess: (res) => { + if (res.data === true) { + setPhoneSMSCheck(true); + setPhoneSMSMessage('인증에 성공하셨습니다.'); + } else if (res.data === false) { + setPhoneSMSCheck(false); + setPhoneSMSMessage('인증번호가 일치하지 않습니다.'); + } + }, + }); + }; + const onChangeInput = ( + setCheckState: React.Dispatch>, + setMessage: React.Dispatch>, + feild: string, + ) => { + setCheckState(false); + setMessage(`${feild} 중복검사를 해주세요`); + }; const postCodeCallback = (fullAddress: string) => { - setCompanyAddress(fullAddress); + setValue('company_address', fullAddress); + }; + + const onSubmit = (data: IForm) => { + if (!idCheck) { + alert('아이디 중복검사를 해주세요.'); + return; + } + if (!nicknameCheck) { + alert('닉네임 중복검사를 해주세요.'); + return; + } + if (!phoneSMSCheck) { + alert('전화번호 인증을 해주세요.'); + return; + } + const form: ISubmitForm = { + email: data.email, + password: data.password, + nick_name: data.nick_name, + phone_num: data.phone_num, + age: data.age, + join_paths: data.join_paths, + agent_code: data.agent_code, + business_code: data.business_code, + company_name: data.company_name, + agent_name: data.agent_name, + company_phone_num: data.company_phone_num, + assistant_name: data.assistant_name === '' ? null : data.assistant_name, + company_address: data.company_address, + company_address_detail: data.company_address_detail, + company_email: data.company_email, + estate: data.estate, + }; + singUpAPI(form, { + onSuccess: () => { + alert('회원가입에 성공하였습니다.'); + navigate('/login'); + }, + }); + }; + + const handleAllSelect = (isSelected: boolean) => { + setIsServiceTerm(isSelected); + setIsPrivacyTerm(isSelected); + setIsMarketingTerm(isSelected); }; + useEffect(() => { + onChangeInput(setIdCheck, setIdCheckMessage, '아이디'); + }, [watch('email')]); + useEffect(() => { + onChangeInput(setNicknameCheck, setNicknameCheckMessage, '닉네임'); + }, [watch('nick_name')]); + useEffect(() => { + setPhoneSMSCheck(false); + setPhoneSMSMessage('전화번호 인증을 해주세요.'); + }, [watch('phone_num')]); + if (token) { return ; } @@ -70,20 +307,34 @@ export default function AgentSignUpPage() { id="agent_code" type="text" placeholder="‘-’ 포함하여 작성 숫자 14자리" + {...register('agent_code', { + required: '필수 입력입니다.', + // TODO: 형식에 맞는 정규표현식 작성 후 패턴 등록하기 + })} />
+

+ {errors.agent_code && errors.agent_code.message} +

{/* 사업자 등록번호 */}
- +
+

+ {errors.business_code && errors.business_code.message} +

{/* 공인중개사 사무소 상호명 & 대표자 이름 */}
@@ -96,8 +347,14 @@ export default function AgentSignUpPage() { id="company_name" type="text" placeholder="상호명" + {...register('company_name', { + required: '필수 입력입니다.', + })} />
+

+ {errors.company_name && errors.company_name.message} +

{/* 대표자 이름 */}
@@ -108,8 +365,14 @@ export default function AgentSignUpPage() { id="agent_name" type="text" placeholder="부동산 대표자명으로 작성" + {...register('agent_name', { + required: '필수 입력입니다.', + })} />
+

+ {errors.agent_name && errors.agent_name.message} +

{/* 공인중개사 사무소 대표 전화번호 */} @@ -123,11 +386,24 @@ export default function AgentSignUpPage() { id="company_phone_num" type="text" placeholder="지역번호까지 입력 예) 02, 031" + {...register('company_phone_num', { + required: '비밀번호는 필수 입력입니다.', + pattern: { + value: /^\d{9,11}$/g, + message: `'-' 제외한 유효한 번호를 입력해주세요.`, + }, + })} /> +

+ {errors.company_phone_num && errors.company_phone_num.message} +

{/* 중개 보조원명 */} -
+
@@ -147,8 +424,10 @@ export default function AgentSignUpPage() { className={signUpStyles.inputStyle} id="company_address" type="text" - value={companyAddress} readOnly + {...register('company_address', { + required: '필수 입력입니다.', + })} />
+

+ {errors.company_address && errors.company_address.message} +

{/* 상세 주소 */} +

+ {errors.company_address_detail && + errors.company_address_detail.message} +

{/* 이메일 */}
- +
-
+

+ {errors.company_email && errors.company_email.message} +

-
+
{/* 아이디 */}
@@ -194,11 +494,34 @@ export default function AgentSignUpPage() { id="id" type="text" placeholder="4~20자리/영문, 숫자, 특수문자’_’사용가능" + {...register('email', { + required: '아이디는 필수 입력입니다.', + pattern: { + value: /^(?=.*[A-Za-z])[A-Za-z_0-9]{4,20}$/g, + message: '4~20자리/영문, 숫자, 특수문자’_’만 사용해주세요.', + }, + })} /> -
+

+ {errors.email && errors.email.message} + {!errors.email && idCheckMessage && idCheckMessage} +

{/* 비밀번호 */}
@@ -207,22 +530,65 @@ export default function AgentSignUpPage() { + {watch('password') !== '' && ( + eyeImage + )}
+

+ {errors.password && errors.password.message} +

{/* 비밀번호 확인 */}
- +
{ + if (watch('password') !== val) { + return '같은 비밀번호가 아닙니다.'; + } + }, + })} /> + {watch('password_check') !== '' && ( + eyeImage + )}
+

+ {errors.password_check && errors.password_check.message} +

{/* 닉네임 */}
@@ -232,12 +598,39 @@ export default function AgentSignUpPage() { className={signUpStyles.inputStyle} id="nick_name" type="text" - placeholder="20자 이하의 조합 " + placeholder="20자 이하의 조합" + {...register('nick_name', { + required: '닉네임은 필수 입력입니다.', + pattern: { + value: /^(?=.*[a-zA-Z0-9가-힣])[A-Za-z0-9가-힣]{1,20}$/g, + message: '20자 이하의 조합만 사용해주세요.', + }, + })} /> -
+

+ {errors.nick_name && errors.nick_name.message} + {!errors.nick_name && nicknameCheckMessage && nicknameCheckMessage} +

{/* 휴대폰 */}
@@ -248,97 +641,286 @@ export default function AgentSignUpPage() { id="phone_num" type="text" placeholder="‘-’빼고 숫자만 입력" + {...register('phone_num', { + required: '전화번호를 입력해주세요.', + pattern: { + value: /^01(?:0|1|[6-9])[0-9]{7,8}$/g, + message: '‘-’빼고 숫자만 입력해주세요.', + }, + })} /> -
+

+ {errors.phone_num && errors.phone_num.message} + {!errors.phone_num && phoneErrMessage && phoneErrMessage} +

+ {/* 인증번호 */} + {isCheckNum && ( +
+ +
+ + +
+

+ {errors.phone_check && errors.phone_check.message} + {!errors.phone_check && phoneSMSMessage && phoneSMSMessage} +

+
+ )} {/* 주거래 매물 */}
- + - + - +
+

+ {errors.age && errors.age.message} +

{/* 연령대 */}
- + - + - + - + - + - +
+

+ {errors.age && errors.age.message} +

{/* 가입경로 */}
- + - + - + - + - + - + - + - +
+

+ {errors.join_paths && errors.join_paths.message} +

{/* 약관 */} @@ -346,51 +928,106 @@ export default function AgentSignUpPage() {
- + { + handleAllSelect( + !(isServiceTerm && isPrivacyTerm && isMarketingTerm), + ); + setValue('service_term', !isServiceTerm, { + shouldValidate: true, + }); + }} + checked={isServiceTerm && isPrivacyTerm && isMarketingTerm} + />
- + { + setIsServiceTerm((prev) => !prev); + }, + })} + checked={isServiceTerm} + /> -
+

+ {errors.service_term && errors.service_term.message} +

+
- + setIsPrivacyTerm((prev) => !prev)} + /> -
- + setIsMarketingTerm((prev) => !prev)} + /> -
- + {toggle ? ( + + ) : null} ); } diff --git a/src/pages/SignUp/index.tsx b/src/pages/SignUp/index.tsx index dfc9351..ec4eb62 100644 --- a/src/pages/SignUp/index.tsx +++ b/src/pages/SignUp/index.tsx @@ -349,7 +349,7 @@ export default function SignUpPage() { className={styles.inputStyle} id="nick_name" type="text" - placeholder="20자 이하의 조합 " + placeholder="20자 이하의 조합" {...register('nick_name', { required: '닉네임은 필수 입력입니다.', pattern: { From 7e0cffc1ae2df88f6db5cdaea4114942fdeaf025 Mon Sep 17 00:00:00 2001 From: sangminlee98 Date: Tue, 19 Sep 2023 15:58:40 +0900 Subject: [PATCH 04/11] =?UTF-8?q?chore:=20=EA=B5=AC=EA=B8=80=20=ED=83=9C?= =?UTF-8?q?=EA=B7=B8=EB=A7=A4=EB=8B=88=EC=A0=80=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 ++ src/App.tsx | 2 ++ src/hooks/useReactGTM.ts | 12 ++++++++++++ yarn.lock | 10 ++++++++++ 4 files changed, 26 insertions(+) create mode 100644 src/hooks/useReactGTM.ts diff --git a/package.json b/package.json index bdd3fb1..a4550ae 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@tanstack/react-query-devtools": "^4.24.6", "@types/dompurify": "^3.0.1", "@types/lodash": "^4.14.192", + "@types/react-gtm-module": "^2.0.1", "@vitejs/plugin-react": "^3.1.0", "aws-sdk": "^2.1363.0", "axios": "^1.3.6", @@ -34,6 +35,7 @@ "react-daum-postcode": "^3.1.3", "react-dom": "^18.2.0", "react-ga4": "^2.1.0", + "react-gtm-module": "^2.0.11", "react-hook-form": "^7.43.5", "react-icons": "^4.8.0", "react-kakao-maps-sdk": "^1.1.9", diff --git a/src/App.tsx b/src/App.tsx index 6729348..8ab45e1 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,10 +3,12 @@ import { QueryClientProvider } from '@tanstack/react-query'; import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; import { routes } from '@/Routes'; import useReactGA from './hooks/useReactGA'; +import useReactGTM from './hooks/useReactGTM'; import { getClient } from './queryClient'; export default function App() { useReactGA(); + useReactGTM(); const queryClient = getClient(); const elem = useRoutes(routes); diff --git a/src/hooks/useReactGTM.ts b/src/hooks/useReactGTM.ts new file mode 100644 index 0000000..2531621 --- /dev/null +++ b/src/hooks/useReactGTM.ts @@ -0,0 +1,12 @@ +import { useEffect } from 'react'; +import TagManager from 'react-gtm-module'; + +const GTM_ID = import.meta.env.VITE_GTM_ID; + +const GoogleTagManager = () => { + useEffect(() => { + TagManager.initialize({ gtmId: GTM_ID }); + }, [GTM_ID]); +}; + +export default GoogleTagManager; diff --git a/yarn.lock b/yarn.lock index 2a5d634..d4310dc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -589,6 +589,11 @@ dependencies: "@types/react" "*" +"@types/react-gtm-module@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/react-gtm-module/-/react-gtm-module-2.0.1.tgz#b2c6cd14ec251d6ae7fa576edf1d43825908a378" + integrity sha512-T/DN9gAbCYk5wJ1nxf4pSwmXz4d1iVjM++OoG+mwMfz9STMAotGjSb65gJHOS5bPvl6vLSsJnuC+y/43OQrltg== + "@types/react@*", "@types/react@^18.0.27": version "18.0.38" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.38.tgz#02a23bef8848b360a0d1dceef4432c15c21c600c" @@ -3055,6 +3060,11 @@ react-ga4@^2.1.0: resolved "https://registry.yarnpkg.com/react-ga4/-/react-ga4-2.1.0.tgz#56601f59d95c08466ebd6edfbf8dede55c4678f9" integrity sha512-ZKS7PGNFqqMd3PJ6+C2Jtz/o1iU9ggiy8Y8nUeksgVuvNISbmrQtJiZNvC/TjDsqD0QlU5Wkgs7i+w9+OjHhhQ== +react-gtm-module@^2.0.11: + version "2.0.11" + resolved "https://registry.yarnpkg.com/react-gtm-module/-/react-gtm-module-2.0.11.tgz#14484dac8257acd93614e347c32da9c5ac524206" + integrity sha512-8gyj4TTxeP7eEyc2QKawEuQoAZdjKvMY4pgWfycGmqGByhs17fR+zEBs0JUDq4US/l+vbTl+6zvUIx27iDo/Vw== + react-hook-form@^7.43.5: version "7.43.9" resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.43.9.tgz#84b56ac2f38f8e946c6032ccb760e13a1037c66d" From 5448c0468f79af196677222760f19c7023a55d8d Mon Sep 17 00:00:00 2001 From: sangminlee98 Date: Wed, 20 Sep 2023 23:16:10 +0900 Subject: [PATCH 05/11] =?UTF-8?q?fix:=20=EC=A3=BC=EA=B1=B0=EB=9E=98=20?= =?UTF-8?q?=EB=A7=A4=EB=AC=BC=EA=B3=BC=20=EC=97=B0=EB=A0=B9=EB=8C=80=20?= =?UTF-8?q?=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=AC=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=EC=83=81=ED=83=9C=20=EB=A9=94=EC=84=B8=EC=A7=80=20?= =?UTF-8?q?=EA=B3=B5=EC=9C=A0=ED=95=98=EB=8A=94=20=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/SignUp/AgentSignUp/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/SignUp/AgentSignUp/index.tsx b/src/pages/SignUp/AgentSignUp/index.tsx index 77434b0..50ab78f 100644 --- a/src/pages/SignUp/AgentSignUp/index.tsx +++ b/src/pages/SignUp/AgentSignUp/index.tsx @@ -747,7 +747,7 @@ export default function AgentSignUpPage() {

- {errors.age && errors.age.message} + {errors.estate && errors.estate.message}

{/* 연령대 */} From 1ad7be1a199f3b1f463d282d7d3896649cfe0875 Mon Sep 17 00:00:00 2001 From: sangminlee98 Date: Wed, 20 Sep 2023 23:16:10 +0900 Subject: [PATCH 06/11] =?UTF-8?q?fix:=20=EC=A3=BC=EA=B1=B0=EB=9E=98=20?= =?UTF-8?q?=EB=A7=A4=EB=AC=BC=EA=B3=BC=20=EC=97=B0=EB=A0=B9=EB=8C=80=20?= =?UTF-8?q?=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=AC=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=EC=83=81=ED=83=9C=20=EB=A9=94=EC=84=B8=EC=A7=80=20?= =?UTF-8?q?=EA=B3=B5=EC=9C=A0=ED=95=98=EB=8A=94=20=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/SignUp/AgentSignUp/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/SignUp/AgentSignUp/index.tsx b/src/pages/SignUp/AgentSignUp/index.tsx index 77434b0..50ab78f 100644 --- a/src/pages/SignUp/AgentSignUp/index.tsx +++ b/src/pages/SignUp/AgentSignUp/index.tsx @@ -747,7 +747,7 @@ export default function AgentSignUpPage() {

- {errors.age && errors.age.message} + {errors.estate && errors.estate.message}

{/* 연령대 */} From 0d465b4925aa7606f555e494b929c84e533b35e5 Mon Sep 17 00:00:00 2001 From: sangminlee98 Date: Tue, 26 Sep 2023 01:42:35 +0900 Subject: [PATCH 07/11] =?UTF-8?q?feat:=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20API=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/login.ts | 2 +- src/pages/Login/index.tsx | 2 +- src/pages/SignUp/AgentSignUp/index.tsx | 257 +++++++++++++++++++++++-- src/pages/SignUp/index.tsx | 250 ++++++++++++++++++++---- src/types/signUp.ts | 2 +- src/types/user.d.ts | 2 + 6 files changed, 459 insertions(+), 56 deletions(-) diff --git a/src/apis/login.ts b/src/apis/login.ts index 67caba5..a0dfce4 100644 --- a/src/apis/login.ts +++ b/src/apis/login.ts @@ -5,7 +5,7 @@ import { } from '@/types/apiResponseType'; export type LoginForm = { - email: string; + userName: string; password: string; }; diff --git a/src/pages/Login/index.tsx b/src/pages/Login/index.tsx index a51c844..c286c8f 100644 --- a/src/pages/Login/index.tsx +++ b/src/pages/Login/index.tsx @@ -19,7 +19,7 @@ export default function LoginPage() { }; const handleLogin = async () => { const form: LoginForm = { - email: id, + userName: id, password, }; const response = await LoginAPI(form); diff --git a/src/pages/SignUp/AgentSignUp/index.tsx b/src/pages/SignUp/AgentSignUp/index.tsx index 50ab78f..7ef383e 100644 --- a/src/pages/SignUp/AgentSignUp/index.tsx +++ b/src/pages/SignUp/AgentSignUp/index.tsx @@ -16,8 +16,14 @@ import { opacityVariants } from '@/constants/variants'; import styles from './styles.module.scss'; import signUpStyles from '../styles.module.scss'; +type AgentSignUpTerm = + | 'SERVICE_USED_AGREE' + | 'PERSONAL_INFO_NOTI' + | 'PERSONAL_INFO_USED_AGREE' + | 'MARKETING_ADVERTISEMENT_AGREE'; + type IForm = { - email: string; + userName: string; password: string; password_check: string; nick_name: string; @@ -34,11 +40,13 @@ type IForm = { company_address: string; company_address_detail: string; company_email: string; + email_code: string; estate: string; service_term: boolean; + agent_term: boolean; }; type ISubmitForm = { - email: string; + userName: string; password: string; nick_name: string; phone_num: string; @@ -54,6 +62,7 @@ type ISubmitForm = { company_address_detail: string; company_email: string; estate: string; + terms: AgentSignUpTerm[]; }; export default function AgentSignUpPage() { @@ -68,7 +77,12 @@ export default function AgentSignUpPage() { const [phoneSMSCheck, setPhoneSMSCheck] = useState(false); // 전화번호 인증 완료 상태 const [phoneSMSMessage, setPhoneSMSMessage] = useState(); // 전화번호 인증 완료 상태 const [phoneErrMessage, setPhoneErrMessage] = useState(); // 전화번호 에러 메세지 + const [isCheckEmail, setIsCheckEmail] = useState(false); // 이메일 인증 중 상태 + const [emailCheck, setEmailCheck] = useState(false); // 이메일 인증 완료 상태 + const [emailMessage, setEmailMessage] = useState(); // 이메일 인증 상태 메세지 + const [emailErrMessage, setEmailErrMessage] = useState(); // 이메일 에러 메세지 const [isServiceTerm, setIsServiceTerm] = useState(false); + const [isAgentPrivacyTerm, setIsAgentPrivacyTerm] = useState(false); const [isPrivacyTerm, setIsPrivacyTerm] = useState(false); const [isMarketingTerm, setIsMarketingTerm] = useState(false); const [selectedTerm, setSelectedTerm] = useState(''); @@ -79,13 +93,38 @@ export default function AgentSignUpPage() { handleSubmit, setValue, formState: { errors }, - } = useForm(); + } = useForm({ + mode: 'onSubmit', + defaultValues: { + userName: '', + password: '', + password_check: '', + nick_name: '', + phone_num: '', + phone_check: '', + age: '', + join_paths: [], + agent_code: '', + business_code: '', + company_name: '', + agent_name: '', + company_phone_num: '', + assistant_name: '', + company_address: '', + company_address_detail: '', + company_email: '', + email_code: '', + estate: '', + service_term: false, + agent_term: false, + }, + }); - const { mutate: idCheckAPI } = useMutation((email: string) => + const { mutate: idCheckAPI } = useMutation((userName: string) => restFetcher({ method: 'POST', - path: '/users/check/email', - body: { email }, + path: '/users/check/user-name', + body: { userName }, }), ); const { mutate: nicknameCheckAPI } = useMutation((nick_name: string) => @@ -109,6 +148,21 @@ export default function AgentSignUpPage() { body: { phone_num: watch('phone_num'), code: phone_check }, }), ); + const { mutate: emailSendAPI } = useMutation((email: string) => + restFetcher({ + method: 'POST', + path: '/users/send/email', + body: { email }, + }), + ); + const { mutate: emailCheckAPI } = useMutation( + (body: { email: string; code: string }) => + restFetcher({ + method: 'POST', + path: '/users/check/email', + body, + }), + ); const { mutate: singUpAPI } = useMutation((form: ISubmitForm) => restFetcher({ method: 'POST', @@ -126,7 +180,7 @@ export default function AgentSignUpPage() { ] = useCheckAPI( idCheckAPI, /^(?=.*[A-Za-z])[A-Za-z_0-9]{4,20}$/g, - watch('email'), + watch('userName'), '사용가능한 ID입니다.', '이미 존재하는 아이디 입니다.', '4~20자리/영문, 숫자, 특수문자’_’만 사용해주세요.', @@ -186,6 +240,48 @@ export default function AgentSignUpPage() { }, }); }; + const onSendEmail = () => { + if ( + /^([\w\.\_\-])*[a-zA-Z0-9]+([\w\.\_\-])*([a-zA-Z0-9])+([\w\.\_\-])+@([a-zA-Z0-9]+\.)+[a-zA-Z0-9]{2,8}$/g.test( + watch('company_email'), + ) === false + ) + return; + emailSendAPI(watch('company_email'), { + onSuccess: (res) => { + if (!res) throw Error; + setEmailErrMessage(undefined); + setIsCheckEmail(true); + }, + onError: () => { + setEmailErrMessage('이미 가입된 이메일입니다.'); + }, + }); + }; + const onCheckEmail = () => { + if ( + /^([\w\.\_\-])*[a-zA-Z0-9]+([\w\.\_\-])*([a-zA-Z0-9])+([\w\.\_\-])+@([a-zA-Z0-9]+\.)+[a-zA-Z0-9]{2,8}$/g.test( + watch('email_code'), + ) === false + ) { + setEmailCheck(false); + setEmailMessage('잘못된 인증코드입니다.'); + } + emailCheckAPI( + { email: watch('company_email'), code: watch('email_code') }, + { + onSuccess: (res) => { + if (res.data === true) { + setEmailCheck(true); + setEmailMessage('인증에 성공하셨습니다.'); + } else if (res.data === false) { + setEmailCheck(false); + setEmailMessage('인증코드가 일치하지 않습니다.'); + } + }, + }, + ); + }; const onChangeInput = ( setCheckState: React.Dispatch>, setMessage: React.Dispatch>, @@ -199,6 +295,15 @@ export default function AgentSignUpPage() { setValue('company_address', fullAddress); }; + const getTerms = () => { + const termsArr: AgentSignUpTerm[] = []; + if (isServiceTerm) termsArr.push('SERVICE_USED_AGREE'); + if (isAgentPrivacyTerm) termsArr.push('PERSONAL_INFO_NOTI'); + if (isPrivacyTerm) termsArr.push('PERSONAL_INFO_USED_AGREE'); + if (isMarketingTerm) termsArr.push('MARKETING_ADVERTISEMENT_AGREE'); + return termsArr; + }; + const onSubmit = (data: IForm) => { if (!idCheck) { alert('아이디 중복검사를 해주세요.'); @@ -212,8 +317,12 @@ export default function AgentSignUpPage() { alert('전화번호 인증을 해주세요.'); return; } + if (!emailCheck) { + alert('이메일 인증을 해주세요.'); + return; + } const form: ISubmitForm = { - email: data.email, + userName: data.userName, password: data.password, nick_name: data.nick_name, phone_num: data.phone_num, @@ -229,6 +338,7 @@ export default function AgentSignUpPage() { company_address_detail: data.company_address_detail, company_email: data.company_email, estate: data.estate, + terms: getTerms(), }; singUpAPI(form, { onSuccess: () => { @@ -240,13 +350,14 @@ export default function AgentSignUpPage() { const handleAllSelect = (isSelected: boolean) => { setIsServiceTerm(isSelected); + setIsAgentPrivacyTerm(isSelected); setIsPrivacyTerm(isSelected); setIsMarketingTerm(isSelected); }; useEffect(() => { onChangeInput(setIdCheck, setIdCheckMessage, '아이디'); - }, [watch('email')]); + }, [watch('userName')]); useEffect(() => { onChangeInput(setNicknameCheck, setNicknameCheckMessage, '닉네임'); }, [watch('nick_name')]); @@ -254,6 +365,10 @@ export default function AgentSignUpPage() { setPhoneSMSCheck(false); setPhoneSMSMessage('전화번호 인증을 해주세요.'); }, [watch('phone_num')]); + useEffect(() => { + setEmailCheck(false); + setEmailMessage('이메일 인증을 해주세요.'); + }, [watch('company_email')]); if (token) { return ; @@ -306,10 +421,13 @@ export default function AgentSignUpPage() { className={signUpStyles.inputStyle} id="agent_code" type="text" - placeholder="‘-’ 포함하여 작성 숫자 14자리" + placeholder="‘-’빼고 10자리 숫자 입력" {...register('agent_code', { required: '필수 입력입니다.', - // TODO: 형식에 맞는 정규표현식 작성 후 패턴 등록하기 + pattern: { + value: /^\d{10}$/g, + message: '‘-’빼고 10자리 숫자를 입력해주세요', + }, })} /> @@ -325,10 +443,13 @@ export default function AgentSignUpPage() { className={signUpStyles.inputStyle} id="business_code" type="text" - placeholder="‘-’ 포함하여 작성 숫자 10자리" + placeholder="‘-’빼고 14자리 숫자 입력" {...register('business_code', { required: '필수 입력입니다.', - // TODO: 형식에 맞는 정규표현식 작성 후 패턴 등록하기 + pattern: { + value: /^\d{14}$/g, + message: '‘-’빼고 14자리 숫자를 입력해주세요', + }, })} /> @@ -476,11 +597,67 @@ export default function AgentSignUpPage() { }, })} /> +

{errors.company_email && errors.company_email.message} + {!errors.company_email && emailErrMessage && emailErrMessage}

+ {isCheckEmail && ( +
+ +
+ + +
+

+ {errors.email_code && errors.email_code.message} + {!errors.email_code && emailMessage && emailMessage} +

+
+ )} +
- {errors.email && errors.email.message} - {!errors.email && idCheckMessage && idCheckMessage} + {errors.userName && errors.userName.message} + {!errors.userName && idCheckMessage && idCheckMessage}

{/* 비밀번호 */} @@ -933,13 +1110,26 @@ export default function AgentSignUpPage() { type="checkbox" onChange={() => { handleAllSelect( - !(isServiceTerm && isPrivacyTerm && isMarketingTerm), + !( + isServiceTerm && + isAgentPrivacyTerm && + isPrivacyTerm && + isMarketingTerm + ), ); setValue('service_term', !isServiceTerm, { shouldValidate: true, }); + setValue('agent_term', !isAgentPrivacyTerm, { + shouldValidate: true, + }); }} - checked={isServiceTerm && isPrivacyTerm && isMarketingTerm} + checked={ + isServiceTerm && + isAgentPrivacyTerm && + isPrivacyTerm && + isMarketingTerm + } /> @@ -971,6 +1161,35 @@ export default function AgentSignUpPage() { {errors.service_term && errors.service_term.message}

+
+ + { + setIsAgentPrivacyTerm((prev) => !prev); + }, + })} + checked={isAgentPrivacyTerm} + /> + + + +
+

+ {errors.agent_term && errors.agent_term.message} +

+
(); // 전화번호 인증 상태 메세지 + const [phoneErrMessage, setPhoneErrMessage] = useState(); // 전화번호 에러 메세지 + const [isCheckEmail, setIsCheckEmail] = useState(false); // 이메일 인증 중 상태 + const [emailCheck, setEmailCheck] = useState(false); // 이메일 인증 완료 상태 + const [emailMessage, setEmailMessage] = useState(); // 이메일 인증 상태 메세지 + const [emailErrMessage, setEmailErrMessage] = useState(); // 이메일 에러 메세지 + const [isServiceTerm, setIsServiceTerm] = useState(false); + const [isPrivacyTerm, setIsPrivacyTerm] = useState(false); + const [isMarketingTerm, setIsMarketingTerm] = useState(false); + const [selectedTerm, setSelectedTerm] = useState(''); + const { register, watch, @@ -44,18 +72,24 @@ export default function SignUpPage() { } = useForm({ mode: 'onSubmit', defaultValues: { + userName: '', email: '', + email_code: '', password: '', - passwordCheck: '', + password_check: '', nick_name: '', phone_num: '', + phone_check: '', + age: '', + join_paths: [], + service_term: false, }, }); - const { mutate: idCheckAPI } = useMutation((email: string) => + const { mutate: idCheckAPI } = useMutation((userName: string) => restFetcher({ method: 'POST', - path: '/users/check/email', - body: { email }, + path: '/users/check/user-name', + body: { userName }, }), ); const { mutate: nicknameCheckAPI } = useMutation((nick_name: string) => @@ -79,6 +113,21 @@ export default function SignUpPage() { body: { phone_num: watch('phone_num'), code: phone_check }, }), ); + const { mutate: emailSendAPI } = useMutation((email: string) => + restFetcher({ + method: 'POST', + path: '/users/send/email', + body: { email }, + }), + ); + const { mutate: emailCheckAPI } = useMutation( + (body: { email: string; code: string }) => + restFetcher({ + method: 'POST', + path: '/users/check/email', + body, + }), + ); const { mutate: singUpAPI } = useMutation((form: ISubmitForm) => restFetcher({ method: 'POST', @@ -86,19 +135,6 @@ export default function SignUpPage() { body: form, }), ); - const navigate = useNavigate(); - const { token } = userStore(); - const [toggle, setToggle] = useState(false); // 약관 토글 - const [eyeState, setEyeState] = useState(false); - const [eyeCheckState, setEyeCheckState] = useState(false); - const [isCheckNum, setIsCheckNum] = useState(false); // 전화번호 인증 중 상태 - const [phoneSMSCheck, setPhoneSMSCheck] = useState(false); // 전화번호 인증 완료 상태 - const [phoneSMSMessage, setPhoneSMSMessage] = useState(); // 전화번호 인증 완료 상태 - const [phoneErrMessage, setPhoneErrMessage] = useState(); // 전화번호 에러 메세지 - const [isServiceTerm, setIsServiceTerm] = useState(false); - const [isPrivacyTerm, setIsPrivacyTerm] = useState(false); - const [isMarketingTerm, setIsMarketingTerm] = useState(false); - const [selectedTerm, setSelectedTerm] = useState(''); const [ idCheck, @@ -109,7 +145,7 @@ export default function SignUpPage() { ] = useCheckAPI( idCheckAPI, /^(?=.*[A-Za-z])[A-Za-z_0-9]{4,20}$/g, - watch('email'), + watch('userName'), '사용가능한 ID입니다.', '이미 존재하는 아이디 입니다.', '4~20자리/영문, 숫자, 특수문자’_’만 사용해주세요.', @@ -169,6 +205,48 @@ export default function SignUpPage() { }, }); }; + const onSendEmail = () => { + if ( + /^([\w\.\_\-])*[a-zA-Z0-9]+([\w\.\_\-])*([a-zA-Z0-9])+([\w\.\_\-])+@([a-zA-Z0-9]+\.)+[a-zA-Z0-9]{2,8}$/g.test( + watch('email'), + ) === false + ) + return; + emailSendAPI(watch('email'), { + onSuccess: (res) => { + if (!res) throw Error; + setEmailErrMessage(undefined); + setIsCheckEmail(true); + }, + onError: () => { + setEmailErrMessage('이미 가입된 이메일입니다.'); + }, + }); + }; + const onCheckEmail = () => { + if ( + /^([\w\.\_\-])*[a-zA-Z0-9]+([\w\.\_\-])*([a-zA-Z0-9])+([\w\.\_\-])+@([a-zA-Z0-9]+\.)+[a-zA-Z0-9]{2,8}$/g.test( + watch('email_code'), + ) === false + ) { + setEmailCheck(false); + setEmailMessage('잘못된 인증코드입니다.'); + } + emailCheckAPI( + { email: watch('email'), code: watch('email_code') }, + { + onSuccess: (res) => { + if (res.data === true) { + setEmailCheck(true); + setEmailMessage('인증에 성공하셨습니다.'); + } else if (res.data === false) { + setEmailCheck(false); + setEmailMessage('인증코드가 일치하지 않습니다.'); + } + }, + }, + ); + }; const onChangeInput = ( setCheckState: React.Dispatch>, setMessage: React.Dispatch>, @@ -177,6 +255,13 @@ export default function SignUpPage() { setCheckState(false); setMessage(`${feild} 중복검사를 해주세요`); }; + const getTerms = () => { + const termsArr: SignUpTerm[] = []; + if (isServiceTerm) termsArr.push('SERVICE_USED_AGREE'); + if (isPrivacyTerm) termsArr.push('PERSONAL_INFO_USED_AGREE'); + if (isMarketingTerm) termsArr.push('MARKETING_ADVERTISEMENT_AGREE'); + return termsArr; + }; const onSubmit = (data: IForm) => { if (!idCheck) { alert('아이디 중복검사를 해주세요.'); @@ -190,14 +275,20 @@ export default function SignUpPage() { alert('전화번호 인증을 해주세요.'); return; } + if (!emailCheck) { + alert('이메일 인증을 해주세요.'); + return; + } singUpAPI( { + userName: data.userName, email: data.email, password: data.password, nick_name: data.nick_name, phone_num: data.phone_num, age: data.age, join_paths: data.join_paths, + terms: getTerms(), }, { onSuccess: () => { @@ -207,15 +298,15 @@ export default function SignUpPage() { }, ); }; - const handleAllSelect = (isSelected: boolean) => { setIsServiceTerm(isSelected); setIsPrivacyTerm(isSelected); setIsMarketingTerm(isSelected); }; + useEffect(() => { onChangeInput(setIdCheck, setIdCheckMessage, '아이디'); - }, [watch('email')]); + }, [watch('userName')]); useEffect(() => { onChangeInput(setNicknameCheck, setNicknameCheckMessage, '닉네임'); }, [watch('nick_name')]); @@ -223,6 +314,10 @@ export default function SignUpPage() { setPhoneSMSCheck(false); setPhoneSMSMessage('전화번호 인증을 해주세요.'); }, [watch('phone_num')]); + useEffect(() => { + setEmailCheck(false); + setEmailMessage('이메일 인증을 해주세요.'); + }, [watch('email')]); if (token) { return ; @@ -248,15 +343,16 @@ export default function SignUpPage() {
+ {/* 아이디 */}
- +

- {errors.email && errors.email.message} - {!errors.email && idCheckMessage && idCheckMessage} + {errors.userName && errors.userName.message} + {!errors.userName && idCheckMessage && idCheckMessage}

+ {/* 비밀번호 */}
+ {/* 비밀번호 확인 */}
- + { if (watch('password') !== val) { @@ -328,10 +426,10 @@ export default function SignUpPage() { }, })} /> - {watch('passwordCheck') !== '' && ( + {watch('password_check') !== '' && ( )}

- {errors.passwordCheck && errors.passwordCheck.message} + {errors.password_check && errors.password_check.message}

+ {/* 닉네임 */}
@@ -381,6 +480,7 @@ export default function SignUpPage() { {!errors.nick_name && nicknameCheckMessage && nicknameCheckMessage}

+ {/* 전화번호 */}
@@ -411,9 +511,10 @@ export default function SignUpPage() {

{errors.phone_num && errors.phone_num.message} - {!errors.phone_num && phoneErrMessage && phoneErrMessage} + {!errors.phone_num && phoneErrMessage}

+ {/* 전화번호 인증 */} {isCheckNum && (
@@ -453,6 +554,85 @@ export default function SignUpPage() {

)} + {/* 이메일 */} +
+ +
+ + +
+

+ {errors.email && errors.email.message} + {!errors.email && emailErrMessage && emailErrMessage} +

+
+ {/* 이메일 인증 */} + {isCheckEmail && ( +
+ +
+ + +
+

+ {errors.email_code && errors.email_code.message} + {!errors.email_code && emailMessage && emailMessage} +

+
+ )} + + {/* 연령대 */}
@@ -497,6 +677,7 @@ export default function SignUpPage() { {errors.age && errors.age.message}

+ {/* 가입경로 */}
@@ -580,6 +761,7 @@ export default function SignUpPage() {

+ {/* 약관 */}
diff --git a/src/types/signUp.ts b/src/types/signUp.ts index b6ef942..0ecdf22 100644 --- a/src/types/signUp.ts +++ b/src/types/signUp.ts @@ -1 +1 @@ -export type TermType = '' | 'SERVICE' | 'PRIVACY' | 'MARKETING'; +export type TermType = '' | 'SERVICE' | 'AGENT' | 'PRIVACY' | 'MARKETING'; diff --git a/src/types/user.d.ts b/src/types/user.d.ts index 32df88e..32d3e2e 100644 --- a/src/types/user.d.ts +++ b/src/types/user.d.ts @@ -3,12 +3,14 @@ export {}; declare global { type User = { id: string; + userName: string; email: string; nick_name: string; phone_num: string; authority: 'USER' | 'ADMIN'; userType: 'NONE' | 'AGENT' | 'WEB' | 'SERVER'; age: string; + profile_image_url?: string | null; }; type Token = { From 12e99dd04cffd94be8dc4a638d6bed18e8fbca63 Mon Sep 17 00:00:00 2001 From: sangminlee98 Date: Tue, 26 Sep 2023 02:04:40 +0900 Subject: [PATCH 08/11] =?UTF-8?q?feat:=20=EA=B3=B5=EC=9D=B8=EC=A4=91?= =?UTF-8?q?=EA=B0=9C=EC=82=AC=20=EC=95=BD=EA=B4=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Terms/AgentTerm.tsx | 50 ++++++++++++++++++++++++++ src/components/Terms/MarketingTerm.tsx | 2 +- src/components/Terms/PrivacyTerm.tsx | 4 +-- src/components/Terms/ServiceTerm.tsx | 2 +- src/components/Terms/index.tsx | 2 ++ 5 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 src/components/Terms/AgentTerm.tsx diff --git a/src/components/Terms/AgentTerm.tsx b/src/components/Terms/AgentTerm.tsx new file mode 100644 index 0000000..904ab03 --- /dev/null +++ b/src/components/Terms/AgentTerm.tsx @@ -0,0 +1,50 @@ +import styles from './styles.module.scss'; + +type AgentTermProps = { + onToggleClick: () => void; +}; + +export default function AgentTerm({ onToggleClick }: AgentTermProps) { + return ( +
+

공인중개사 식별 개인정보 수집 이용 동의(필수)

+
+

+ 주말내집에서는 개인정보보호법 제15조, 제22조에 근거하여 주말내집 + 회원정보를 수집하고 있습니다. +

+
+

1. 개인정보의 수집·이용 목적

+

+ 공인중개사 회원에 대한 확인을 통해 원활한 주말내집 서비스 제공을 + 위함. +

+
+
+

2. 개인정보 보유 및 이용기간

+

회원 탈퇴 시까지

+
+
+

3. 처리하는 개인정보 항목

+

+ □ 필수항목 : 성명, 전화번호, 공인중개사 등록번호, 사업자 등록번호, + 공인중개사 사무소 상호명, 대표자 이름, 공인중개사 사무소 대표 + 전화번호, 중개 보조원명, 공인중개사 사무소 주소, 이메일 +

+
+
+

+ 4. 동의거부 권리 및 동의거부 시 불이익 안내 +

+

+ 귀하는 개인정보에 수집·이용에 대한 동의를 거부할 권리가 있습니다. + 다만, 필수항목에 대한 동의 거부 시에는 회원가입이 불가능합니다. +

+
+
+ +
+ ); +} diff --git a/src/components/Terms/MarketingTerm.tsx b/src/components/Terms/MarketingTerm.tsx index 16546e5..3603823 100644 --- a/src/components/Terms/MarketingTerm.tsx +++ b/src/components/Terms/MarketingTerm.tsx @@ -1,6 +1,6 @@ import styles from './styles.module.scss'; -export type MarketingTermProps = { +type MarketingTermProps = { onToggleClick: () => void; }; diff --git a/src/components/Terms/PrivacyTerm.tsx b/src/components/Terms/PrivacyTerm.tsx index a9ef530..a8bd161 100644 --- a/src/components/Terms/PrivacyTerm.tsx +++ b/src/components/Terms/PrivacyTerm.tsx @@ -1,6 +1,6 @@ import styles from './styles.module.scss'; -export type PrivacyTermProps = { +type PrivacyTermProps = { onToggleClick: () => void; }; @@ -19,7 +19,7 @@ export default function PrivacyTerm({ onToggleClick }: PrivacyTermProps) {

3. 처리하는 개인정보 항목

-

이름, 이메일 주소, 전화번호, 주거래 매물, 연령대

+

□ 이름, 이메일 주소, 전화번호, 주거래 매물, 연령대

이는 주말내집이 제공하는 서비스를 보다 원활하게 이용하도록 하기 위해서 diff --git a/src/components/Terms/ServiceTerm.tsx b/src/components/Terms/ServiceTerm.tsx index 02b8be4..aa663ab 100644 --- a/src/components/Terms/ServiceTerm.tsx +++ b/src/components/Terms/ServiceTerm.tsx @@ -1,6 +1,6 @@ import styles from './styles.module.scss'; -export type ServiceTermProps = { +type ServiceTermProps = { onToggleClick: () => void; }; diff --git a/src/components/Terms/index.tsx b/src/components/Terms/index.tsx index 2455402..b141063 100644 --- a/src/components/Terms/index.tsx +++ b/src/components/Terms/index.tsx @@ -1,5 +1,6 @@ import React from 'react'; import { TermType } from '@/types/signUp'; +import AgentTerm from './AgentTerm'; import MarketingTerm from './MarketingTerm'; import PrivacyTerm from './PrivacyTerm'; import ServiceTerm from './ServiceTerm'; @@ -21,6 +22,7 @@ export default function Terms({ selectedTerm, setToggle }: TermsProps) { {selectedTerm === 'SERVICE' && ( )} + {selectedTerm === 'AGENT' && } {selectedTerm === 'PRIVACY' && ( )} From 621606c39b47c93b262bcf34ca77d405ef081a06 Mon Sep 17 00:00:00 2001 From: sangminlee98 Date: Tue, 26 Sep 2023 13:52:59 +0900 Subject: [PATCH 09/11] =?UTF-8?q?feat:=20=ED=91=B8=ED=84=B0=20=EC=95=BD?= =?UTF-8?q?=EA=B4=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Common/Footer/index.tsx | 37 +++++++++++++++++++ .../Common/Footer/styles.module.scss | 18 +++++++++ src/pages/SignUp/AgentSignUp/index.tsx | 6 ++- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/components/Common/Footer/index.tsx b/src/components/Common/Footer/index.tsx index 83302e7..2ee78b5 100644 --- a/src/components/Common/Footer/index.tsx +++ b/src/components/Common/Footer/index.tsx @@ -6,6 +6,43 @@ export default function Footer() {

주말내집 by 오이리 © 2022 ALL RIGHTS RESERVED.

문의사항 : 5do2chonri@gmail.com

+ + +
+ +
+ +
); diff --git a/src/components/Common/Footer/styles.module.scss b/src/components/Common/Footer/styles.module.scss index e231c6f..db5c147 100644 --- a/src/components/Common/Footer/styles.module.scss +++ b/src/components/Common/Footer/styles.module.scss @@ -25,3 +25,21 @@ padding-left: 5rem; } } +.buttonWrapper { + display: flex; + gap: 1rem; +} +.button { + background-color: transparent; + border: none; + outline: none; + color: white; + padding: 0; + cursor: pointer; +} + +.divider { + width: 1px; + height: 100%; + background-color: white; +} diff --git a/src/pages/SignUp/AgentSignUp/index.tsx b/src/pages/SignUp/AgentSignUp/index.tsx index 7ef383e..8b48f6c 100644 --- a/src/pages/SignUp/AgentSignUp/index.tsx +++ b/src/pages/SignUp/AgentSignUp/index.tsx @@ -166,7 +166,7 @@ export default function AgentSignUpPage() { const { mutate: singUpAPI } = useMutation((form: ISubmitForm) => restFetcher({ method: 'POST', - path: '/users/sign-up', + path: '/agents/sign-up', body: form, }), ); @@ -342,7 +342,9 @@ export default function AgentSignUpPage() { }; singUpAPI(form, { onSuccess: () => { - alert('회원가입에 성공하였습니다.'); + alert( + '회원가입에 성공하였습니다.\n공인중개사 회원은 관리자 승인 이후에 로그인이 가능합니다.', + ); navigate('/login'); }, }); From 732cf00c7d9f9a31aa357bf73c3595959f15fffb Mon Sep 17 00:00:00 2001 From: sangminlee98 Date: Tue, 26 Sep 2023 15:22:36 +0900 Subject: [PATCH 10/11] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20API=20=EC=97=90=EB=9F=AC=20=ED=95=B8=EB=93=A4?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/SignUp/AgentSignUp/index.tsx | 38 +++++++++++++++----------- src/pages/SignUp/index.tsx | 6 ++++ src/queryClient.ts | 1 + 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/pages/SignUp/AgentSignUp/index.tsx b/src/pages/SignUp/AgentSignUp/index.tsx index 8b48f6c..b947425 100644 --- a/src/pages/SignUp/AgentSignUp/index.tsx +++ b/src/pages/SignUp/AgentSignUp/index.tsx @@ -2,6 +2,7 @@ import { useEffect, useState } from 'react'; import { useForm } from 'react-hook-form'; import { Navigate, useNavigate } from 'react-router-dom'; import { useMutation } from '@tanstack/react-query'; +import { AxiosError } from 'axios'; import { motion } from 'framer-motion'; import eyeImage from '@/assets/common/eye.svg'; import eyeClosedImage from '@/assets/common/eyeClosed.svg'; @@ -11,6 +12,7 @@ import { restFetcher } from '@/queryClient'; import Terms from '@/components/Terms'; import userStore from '@/store/userStore'; import useCheckAPI from '@/hooks/useCheckAPI'; +import { ApiResponseType } from '@/types/apiResponseType'; import { TermType } from '@/types/signUp'; import { opacityVariants } from '@/constants/variants'; import styles from './styles.module.scss'; @@ -305,22 +307,22 @@ export default function AgentSignUpPage() { }; const onSubmit = (data: IForm) => { - if (!idCheck) { - alert('아이디 중복검사를 해주세요.'); - return; - } - if (!nicknameCheck) { - alert('닉네임 중복검사를 해주세요.'); - return; - } - if (!phoneSMSCheck) { - alert('전화번호 인증을 해주세요.'); - return; - } - if (!emailCheck) { - alert('이메일 인증을 해주세요.'); - return; - } + // if (!idCheck) { + // alert('아이디 중복검사를 해주세요.'); + // return; + // } + // if (!nicknameCheck) { + // alert('닉네임 중복검사를 해주세요.'); + // return; + // } + // if (!phoneSMSCheck) { + // alert('전화번호 인증을 해주세요.'); + // return; + // } + // if (!emailCheck) { + // alert('이메일 인증을 해주세요.'); + // return; + // } const form: ISubmitForm = { userName: data.userName, password: data.password, @@ -347,6 +349,10 @@ export default function AgentSignUpPage() { ); navigate('/login'); }, + onError: (err) => { + const error = err as AxiosError; + alert(error.response?.data.message); + }, }); }; diff --git a/src/pages/SignUp/index.tsx b/src/pages/SignUp/index.tsx index 6daaf6a..991a44b 100644 --- a/src/pages/SignUp/index.tsx +++ b/src/pages/SignUp/index.tsx @@ -2,6 +2,7 @@ import { useEffect, useState } from 'react'; import { useForm } from 'react-hook-form'; import { Navigate, useNavigate } from 'react-router-dom'; import { useMutation } from '@tanstack/react-query'; +import { AxiosError } from 'axios'; import { motion } from 'framer-motion'; import eyeImage from '@/assets/common/eye.svg'; import eyeClosedImage from '@/assets/common/eyeClosed.svg'; @@ -10,6 +11,7 @@ import { restFetcher } from '@/queryClient'; import Terms from '@/components/Terms'; import userStore from '@/store/userStore'; import useCheckAPI from '@/hooks/useCheckAPI'; +import { ApiResponseType } from '@/types/apiResponseType'; import { TermType } from '@/types/signUp'; import { opacityVariants } from '@/constants/variants'; import styles from './styles.module.scss'; @@ -295,6 +297,10 @@ export default function SignUpPage() { alert('회원가입에 성공하였습니다.'); navigate('/login'); }, + onError: (err) => { + const error = err as AxiosError; + alert(error.response?.data.message); + }, }, ); }; diff --git a/src/queryClient.ts b/src/queryClient.ts index 7e3fccb..e389538 100644 --- a/src/queryClient.ts +++ b/src/queryClient.ts @@ -50,6 +50,7 @@ export const restFetcher = async ({ return res.data; } catch (err) { console.error(err); + return Promise.reject(err); } }; From 1a2809fee2650f2b8e94116b20b21ed6fd285cf3 Mon Sep 17 00:00:00 2001 From: sangminlee98 Date: Tue, 26 Sep 2023 18:36:39 +0900 Subject: [PATCH 11/11] =?UTF-8?q?fix:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=ED=95=A8=EC=88=98=20=EC=BD=94=EB=93=9C=20=EC=A3=BC?= =?UTF-8?q?=EC=84=9D=20=ED=95=B4=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/SignUp/AgentSignUp/index.tsx | 32 +++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/pages/SignUp/AgentSignUp/index.tsx b/src/pages/SignUp/AgentSignUp/index.tsx index b947425..5192f0f 100644 --- a/src/pages/SignUp/AgentSignUp/index.tsx +++ b/src/pages/SignUp/AgentSignUp/index.tsx @@ -307,22 +307,22 @@ export default function AgentSignUpPage() { }; const onSubmit = (data: IForm) => { - // if (!idCheck) { - // alert('아이디 중복검사를 해주세요.'); - // return; - // } - // if (!nicknameCheck) { - // alert('닉네임 중복검사를 해주세요.'); - // return; - // } - // if (!phoneSMSCheck) { - // alert('전화번호 인증을 해주세요.'); - // return; - // } - // if (!emailCheck) { - // alert('이메일 인증을 해주세요.'); - // return; - // } + if (!idCheck) { + alert('아이디 중복검사를 해주세요.'); + return; + } + if (!nicknameCheck) { + alert('닉네임 중복검사를 해주세요.'); + return; + } + if (!phoneSMSCheck) { + alert('전화번호 인증을 해주세요.'); + return; + } + if (!emailCheck) { + alert('이메일 인증을 해주세요.'); + return; + } const form: ISubmitForm = { userName: data.userName, password: data.password,