From c27116ae13443b303ffc2456ef108d1a26f168eb Mon Sep 17 00:00:00 2001 From: Hwang Juhee Date: Tue, 5 Apr 2022 03:31:23 +0900 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20:sparkles:=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EC=9E=AC=EC=84=A4=EC=A0=95=20=EB=B7=B0=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Password/PasswordChangeForm.tsx | 90 +++++++++++++++++++ src/pages/auth/findPw.tsx | 19 ++++ 2 files changed, 109 insertions(+) create mode 100644 src/components/Password/PasswordChangeForm.tsx create mode 100644 src/pages/auth/findPw.tsx diff --git a/src/components/Password/PasswordChangeForm.tsx b/src/components/Password/PasswordChangeForm.tsx new file mode 100644 index 00000000..9acd6174 --- /dev/null +++ b/src/components/Password/PasswordChangeForm.tsx @@ -0,0 +1,90 @@ +import styled from 'styled-components'; +import { theme } from 'styles/theme'; + +function PasswordChangeForm() { + return ( + + +

비밀번호를 잊어버리셨나요?

+
+ +

소담에 가입했던 이메일을 입력해주세요

+

비밀번호 재설정에 필요한 인증번호를 전송해드립니다

+
+ + 존재하지 않는 이메일입니다 + 인증번호 발송 +
+ ); +} + +const StyledRoot = styled.div` + width: 100%; + height: 100%; + padding: 12rem 0 16rem 0; + display: flex; + flex-direction: column; + align-items: center; +`; + +const StyledTitleWrapper = styled.div` + text-align: center; + margin-bottom: 1.6rem; + + & > h3 { + font-weight: 700; + font-size: 2.6rem; + line-height: 3.8rem; + color: ${theme.colors.purpleText}; + } +`; + +const StyledExplain = styled.div` + margin-bottom: 5.8rem; + display: flex; + flex-direction: column; + justify-content: space-between; + text-align: center; + & > h3 { + font-weight: 500; + font-size: 1.5rem; + line-height: 2.2rem; + color: ${theme.colors.black2}; + } +`; + +const StyledInput = styled.input` + width: 39.1rem; + height: 5rem; + margin-bottom: 2.8rem; + background-color: white; + border: 1px solid ${theme.colors.purpleText}; + border-radius: 5px; + font-size: 1.3rem; + font-weight: 500; + padding-left: 1.6rem; + color: ${theme.colors.black2}; + + & > :placeholder { + color: ${theme.colors.gray1}; + } +`; + +const StyledWarningMessage = styled.h3` + font-size: 1.4rem; + margin-bottom: 1.6rem; + line-height: 2rem; + color: ${theme.colors.purpleText}; +`; + +const StyledButton = styled.button` + width: 39.1rem; + height: 4.6rem; + background-color: ${theme.colors.gray2}; + border-radius: 5px; + border: 0; + color: white; + font-size: 1.5rem; + font-weight: 700; +`; +export default PasswordChangeForm; diff --git a/src/pages/auth/findPw.tsx b/src/pages/auth/findPw.tsx new file mode 100644 index 00000000..ff248fa0 --- /dev/null +++ b/src/pages/auth/findPw.tsx @@ -0,0 +1,19 @@ +import PasswordChangeForm from 'components/Password/PasswordChangeForm'; +import styled from 'styled-components'; + +function findPw() { + return ( + + + + ); +} + +const StyledRoot = styled.div` + height: 60rem; + display: flex; + flex-direction: column; + align-items: center; +`; + +export default findPw; From f97d2ddc03ad5067a228804dd78c7ebb8eef35c1 Mon Sep 17 00:00:00 2001 From: Hwang Juhee Date: Tue, 17 May 2022 21:30:23 +0900 Subject: [PATCH 2/5] =?UTF-8?q?chore:=20:gear:=20=ED=83=9C=EA=B7=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EC=BD=94=EB=93=9C=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EB=B0=98=EC=98=81=20#128?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Password/PasswordChangeForm.tsx | 82 ++++++++++--------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/src/components/Password/PasswordChangeForm.tsx b/src/components/Password/PasswordChangeForm.tsx index 9acd6174..fee0dcec 100644 --- a/src/components/Password/PasswordChangeForm.tsx +++ b/src/components/Password/PasswordChangeForm.tsx @@ -8,18 +8,20 @@ function PasswordChangeForm() {

비밀번호를 잊어버리셨나요?

-

소담에 가입했던 이메일을 입력해주세요

-

비밀번호 재설정에 필요한 인증번호를 전송해드립니다

+

소담에 가입했던 이메일을 입력해주세요

+

비밀번호 재설정에 필요한 인증번호를 전송해드립니다

- - 존재하지 않는 이메일입니다 - 인증번호 발송 + + +

존재하지 않는 이메일입니다

+ +
); } -const StyledRoot = styled.div` - width: 100%; +const StyledRoot = styled.section` + width: 39.1rem; height: 100%; padding: 12rem 0 16rem 0; display: flex; @@ -45,7 +47,7 @@ const StyledExplain = styled.div` flex-direction: column; justify-content: space-between; text-align: center; - & > h3 { + & > p { font-weight: 500; font-size: 1.5rem; line-height: 2.2rem; @@ -53,38 +55,44 @@ const StyledExplain = styled.div` } `; -const StyledInput = styled.input` - width: 39.1rem; - height: 5rem; - margin-bottom: 2.8rem; - background-color: white; - border: 1px solid ${theme.colors.purpleText}; - border-radius: 5px; - font-size: 1.3rem; - font-weight: 500; - padding-left: 1.6rem; - color: ${theme.colors.black2}; +const StyledForm = styled.form` + width: 100%; - & > :placeholder { - color: ${theme.colors.gray1}; + & > input { + width: 100%; + height: 5rem; + margin-bottom: 2.8rem; + background-color: white; + border: 1px solid ${theme.colors.purpleText}; + border-radius: 5px; + font-size: 1.3rem; + font-weight: 500; + padding-left: 1.6rem; + color: ${theme.colors.black2}; + + & ::placeholder { + color: ${theme.colors.gray1}; + } } -`; -const StyledWarningMessage = styled.h3` - font-size: 1.4rem; - margin-bottom: 1.6rem; - line-height: 2rem; - color: ${theme.colors.purpleText}; -`; + & > p { + text-align: center; + font-size: 1.4rem; + margin-bottom: 1.6rem; + line-height: 2rem; + color: ${theme.colors.purpleText}; + } -const StyledButton = styled.button` - width: 39.1rem; - height: 4.6rem; - background-color: ${theme.colors.gray2}; - border-radius: 5px; - border: 0; - color: white; - font-size: 1.5rem; - font-weight: 700; + & > button { + width: 100%; + height: 4.6rem; + background-color: ${theme.colors.gray2}; + border-radius: 5px; + border: 0; + color: white; + font-size: 1.5rem; + font-weight: 700; + } `; + export default PasswordChangeForm; From a7ac2154dbb13f1bd3f18b94bf69a9763b752b1e Mon Sep 17 00:00:00 2001 From: Hwang Juhee Date: Tue, 17 May 2022 22:35:15 +0900 Subject: [PATCH 3/5] =?UTF-8?q?css:=20:art:=20=EC=9D=B8=EC=A6=9D=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9E=85=EB=A0=A5=EB=B7=B0=20=ED=8D=BC=EB=B8=94?= =?UTF-8?q?=EB=A6=AC=EC=8B=B1=20#128?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Password/AuthNumForm.tsx | 103 ++++++++++++++++++ src/pages/auth/findpw/authnum.tsx | 19 ++++ .../auth/{findPw.tsx => findpw/email.tsx} | 0 3 files changed, 122 insertions(+) create mode 100644 src/components/Password/AuthNumForm.tsx create mode 100644 src/pages/auth/findpw/authnum.tsx rename src/pages/auth/{findPw.tsx => findpw/email.tsx} (100%) diff --git a/src/components/Password/AuthNumForm.tsx b/src/components/Password/AuthNumForm.tsx new file mode 100644 index 00000000..ce56f769 --- /dev/null +++ b/src/components/Password/AuthNumForm.tsx @@ -0,0 +1,103 @@ +import styled from 'styled-components'; +import { theme } from 'styles/theme'; + +function AuthNumForm() { + return ( + + +

인증번호 입력

+

회원님의 이메일로 발송된 인증번호 네자리를 입력해주세요

+
+ + + + + + + 인증번호가 일치하지 않습니다. + 확인 + 인증번호 재발송 +
+ ); +} +const StyledRoot = styled.div` + width: 39.1rem; + height: 100%; + padding: 12rem 0 9.8rem 0; + display: flex; + flex-direction: column; + align-items: center; +`; + +const StyledTitleWrapper = styled.div` + width: 100%; + text-align: center; + margin-bottom: 5.8rem; + + & > h3 { + margin-bottom: 1.6rem; + font-weight: 700; + font-size: 2.6rem; + line-height: 3.8rem; + color: ${theme.colors.purpleText}; + } + + & > p { + font-weight: 500; + font-size: 1.5rem; + line-height: 2.2rem; + color: ${theme.colors.black2}; + } +`; + +const StyledInputWrapper = styled.div` + width: 26.2rem; + display: flex; + justify-content: space-between; + margin-bottom: 3.2rem; + + & > input { + width: 5.5rem; + height: 7.1rem; + border: 1px solid ${theme.colors.purpleText}; + border-radius: 5px; + font-size: 2.4rem; + font-weight: 700; + line-height: 3.4rem; + color: ${theme.colors.black2}; + text-align: center; + } +`; + +const StyledWarningMessage = styled.p` + font-size: 1.4rem; + margin-bottom: 1.6rem; + line-height: 2rem; + margin-bottom: 1.6rem; + color: ${theme.colors.purpleText}; +`; + +const StyledOkBtn = styled.button` + width: 39.1rem; + height: 4.6rem; + margin-bottom: 1.6rem; + background-color: ${theme.colors.gray2}; + border-radius: 5px; + border: 0; + color: white; + font-size: 1.5rem; + font-weight: 700; +`; + +const StyledResendBtn = styled.button` + width: 39.1rem; + height: 4.6rem; + background-color: ${theme.colors.purpleMain}; + border-radius: 5px; + border: 0; + color: white; + font-size: 1.5rem; + font-weight: 700; +`; + +export default AuthNumForm; diff --git a/src/pages/auth/findpw/authnum.tsx b/src/pages/auth/findpw/authnum.tsx new file mode 100644 index 00000000..db2907bf --- /dev/null +++ b/src/pages/auth/findpw/authnum.tsx @@ -0,0 +1,19 @@ +import AuthNumForm from 'components/Password/AuthNumForm'; +import styled from 'styled-components'; + +function findPw() { + return ( + + + + ); +} + +const StyledRoot = styled.div` + height: 60rem; + display: flex; + flex-direction: column; + align-items: center; +`; + +export default findPw; diff --git a/src/pages/auth/findPw.tsx b/src/pages/auth/findpw/email.tsx similarity index 100% rename from src/pages/auth/findPw.tsx rename to src/pages/auth/findpw/email.tsx From 4bd46e94fedb74a5fb4eca0d8fcd996477167892 Mon Sep 17 00:00:00 2001 From: Jinny Date: Wed, 18 May 2022 04:08:42 +0900 Subject: [PATCH 4/5] =?UTF-8?q?feat:=20:sparkles:=20=EC=9D=B8=EC=A6=9D?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=ED=81=B4=EB=A6=BD=EB=B3=B4=EB=93=9C=20?= =?UTF-8?q?=EB=B3=B5=EC=82=AC=20=EB=B0=8F=20=EC=98=A4=ED=86=A0=ED=8F=AC?= =?UTF-8?q?=EC=BB=A4=EC=8A=A4=20#128?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Password/AuthNumForm.tsx | 63 +++++++++++++++++++++++-- src/hooks/useClipboard.ts | 32 +++++++++++++ 2 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 src/hooks/useClipboard.ts diff --git a/src/components/Password/AuthNumForm.tsx b/src/components/Password/AuthNumForm.tsx index ce56f769..c586395d 100644 --- a/src/components/Password/AuthNumForm.tsx +++ b/src/components/Password/AuthNumForm.tsx @@ -1,18 +1,71 @@ +import useClipboard from 'hooks/useClipboard'; +import { ChangeEvent, KeyboardEvent, useCallback, useEffect, useRef, useState } from 'react'; +import shortid from 'shortid'; import styled from 'styled-components'; import { theme } from 'styles/theme'; function AuthNumForm() { + const [authNums, setAuthNums] = useState(new Array(4).fill('')); // authNums 인증번호 4자리를 배열로 관리 + const inputParentRef = useRef(null); // input 태그 4개를 감싸는 부모 태그의 ref + const focusIdx = useRef(0); // 포커스를 줄 input 태그의 인덱스 + + useClipboard(inputParentRef, setAuthNums); + + const focusTargetInput = useCallback((targetIdx: number) => { + const inputParent = inputParentRef.current; + if (inputParent) { + const targetChild = inputParent.children[targetIdx]; + if (targetChild instanceof HTMLInputElement) targetChild.focus(); + } + }, []); + + const handleChangeAuthNum = (e: ChangeEvent, authNumIdx: number) => { + setAuthNums((prevAuthNums) => { + const nextAuthNums = [...prevAuthNums]; + nextAuthNums.splice(authNumIdx, 1, e.target.value); + // 첫번째인자 : 인덱스, 두번째 인자: 몇개바꿀건지, 3번째인자: 뭐로 바꿀건지?? + // authNumIdx 번째에있는 값에서 첫번쨰를, e.target.value로 바꿔라 + // 내가 입력한 값으로 해당하는 배열원소의 값을 바까라! 이해됨? + if (e.target.value) focusIdx.current = authNumIdx + 1; + else focusIdx.current = authNumIdx - 1 < 0 ? 0 : authNumIdx - 1; + return nextAuthNums; + }); + }; + + const handleKeyPressAtEmpty = (e: KeyboardEvent) => { + if (!(e.target instanceof HTMLInputElement)) return; + // 백스페이스를 눌러서 포커스가 <- 이 방향으로 갱신되어야할 때. + if (e.key === 'Backspace' && !e.target.value) { + setAuthNums([...authNums]); + focusIdx.current = focusIdx.current - 1 < 0 ? 0 : focusIdx.current - 1; + } + }; + + useEffect(() => { + focusTargetInput(focusIdx.current); + }, [authNums, focusTargetInput]); + return (

인증번호 입력

회원님의 이메일로 발송된 인증번호 네자리를 입력해주세요

- - - - - + + {authNums.map((authNum, authNumIdx) => ( + handleChangeAuthNum(e, authNumIdx)} + onKeyDown={handleKeyPressAtEmpty} + /> + ))} 인증번호가 일치하지 않습니다. 확인 diff --git a/src/hooks/useClipboard.ts b/src/hooks/useClipboard.ts new file mode 100644 index 00000000..2eea979b --- /dev/null +++ b/src/hooks/useClipboard.ts @@ -0,0 +1,32 @@ +import { RefObject, useEffect } from 'react'; + +/** + * @param {RefObject} containerRef -> 붙여넣기 이벤트를 어디에다가 등록할건지 useRef 객체 받음. + * @param {(copiedTextArray:string[])=>void} pasteHandler -> 붙여넣기 이벤트가 일어났을 때 무슨 일을 할건지 정의. + */ + +function useClipboard( + containerRef: RefObject, + pasteHandler: (copiedTextArray: string[]) => void, +) { + useEffect(() => { + const container = containerRef.current; + function parseCopiedTextToArray() { + if ('clipboard' in navigator) { + // 클립보드에 복사되어있는 텍스트를 가져옴. + navigator.clipboard.readText().then((copiedText) => { + // 5678 -> ['5','6','7','8']; + pasteHandler(Array.from(copiedText).slice(0, 4)); + }); + } + } + + container?.addEventListener('paste', parseCopiedTextToArray); + + return () => { + container?.removeEventListener('paste', parseCopiedTextToArray); + }; + }, []); +} + +export default useClipboard; From 543cb481676bde1d4512a73887748d490bfabb9c Mon Sep 17 00:00:00 2001 From: Hwang Juhee Date: Thu, 26 May 2022 02:09:42 +0900 Subject: [PATCH 5/5] =?UTF-8?q?css:=20:art:=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EB=B3=80=EA=B2=BD=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EB=B7=B0=20=ED=8D=BC=EB=B8=94=EB=A6=AC=EC=8B=B1=20#128?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Password/NewPasswordForm.tsx | 108 ++++++++++++++++++++ src/pages/auth/findpw/newpw.tsx | 19 ++++ 2 files changed, 127 insertions(+) create mode 100644 src/components/Password/NewPasswordForm.tsx create mode 100644 src/pages/auth/findpw/newpw.tsx diff --git a/src/components/Password/NewPasswordForm.tsx b/src/components/Password/NewPasswordForm.tsx new file mode 100644 index 00000000..d6319c46 --- /dev/null +++ b/src/components/Password/NewPasswordForm.tsx @@ -0,0 +1,108 @@ +import styled from 'styled-components'; +import { theme } from 'styles/theme'; + +function NewPasswordForm() { + return ( + + +

비밀번호를 변경해주세요!

+
+ +

안전한 사용을 위하여, 기존 비밀번호를 변경해야 합니다

+

아래에 새 비밀번호를 입력해주세요

+
+ +

‘영문, 숫자’ 포함하여 8글자 이상 15자 미만

+ + +
+ 입력 형식에 맞지 않습니다 + 변경 완료 +
+ ); +} + +const StyledRoot = styled.section` + width: 39.1rem; + padding: 12rem 0 16rem 0; + display: flex; + flex-direction: column; + align-items: center; +`; + +const StyledTitleWrapper = styled.div` + text-align: center; + margin-bottom: 1.6rem; + + & > h3 { + font-weight: 700; + font-size: 2.6rem; + line-height: 3.8rem; + color: ${theme.colors.purpleText}; + } +`; + +const StyledExplain = styled.div` + margin-bottom: 3.5rem; + display: flex; + flex-direction: column; + justify-content: space-between; + text-align: center; + & > p { + font-weight: 500; + font-size: 1.5rem; + line-height: 2.2rem; + color: ${theme.colors.black2}; + } +`; + +const StyledForm = styled.form` + width: 100%; + + & > input { + width: 100%; + height: 5rem; + margin-bottom: 1.6rem; + background-color: white; + border: 1px solid ${theme.colors.purpleText}; + border-radius: 5px; + font-size: 1.3rem; + font-weight: 500; + padding-left: 1.6rem; + color: ${theme.colors.black2}; + + & ::placeholder { + color: ${theme.colors.gray1}; + } + } + + & > p { + text-align: right; + font-size: 1rem; + margin-bottom: 0.9rem; + line-height: 2rem; + color: ${theme.colors.purpleText}; + } +`; + +const StyledAlert = styled.p` + text-align: center; + font-size: 1.2rem; + margin-top: 1.5rem; + line-height: 2rem; + color: ${theme.colors.purpleText}; +`; + +const StyledButton = styled.button` + width: 100%; + height: 4.6rem; + margin-top: 1.6rem; + background-color: ${theme.colors.gray2}; + border-radius: 5px; + border: 0; + color: white; + font-size: 1.5rem; + font-weight: 700; +`; + +export default NewPasswordForm; diff --git a/src/pages/auth/findpw/newpw.tsx b/src/pages/auth/findpw/newpw.tsx new file mode 100644 index 00000000..f597e6cc --- /dev/null +++ b/src/pages/auth/findpw/newpw.tsx @@ -0,0 +1,19 @@ +import NewPasswordForm from 'components/Password/NewPasswordForm'; +import styled from 'styled-components'; + +function findPw() { + return ( + + + + ); +} + +const StyledRoot = styled.div` + height: 60rem; + display: flex; + flex-direction: column; + align-items: center; +`; + +export default findPw;