From 3062c19d5d99f5d6277239b1b19c2267692a89f9 Mon Sep 17 00:00:00 2001 From: j8won Date: Sat, 9 Dec 2023 17:09:58 +0900 Subject: [PATCH 01/35] =?UTF-8?q?rename(apply):=20useAnnounce=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=EB=AA=85=20=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-apply/src/components/home/HomeAnnounce.tsx | 4 ++-- service-apply/src/hooks/react-query/useAnnounce.tsx | 6 +++--- service-apply/src/pages/Anouncement/Announcement.page.tsx | 4 ++-- .../src/pages/Anouncement/AnnouncementList.page.tsx | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/service-apply/src/components/home/HomeAnnounce.tsx b/service-apply/src/components/home/HomeAnnounce.tsx index 344f27f..e93250d 100644 --- a/service-apply/src/components/home/HomeAnnounce.tsx +++ b/service-apply/src/components/home/HomeAnnounce.tsx @@ -1,10 +1,10 @@ import { Txt } from '@quokka/design-system'; import { Link } from 'react-router-dom'; -import { useAnounceQuery } from '../../hooks/react-query/useAnnounce'; +import { useAnnounceQuery } from '../../hooks/react-query/useAnnounce'; import clsx from 'clsx'; export const HomeAnnounce = () => { - const { announceData } = useAnounceQuery(); + const { announceData } = useAnnounceQuery(); return (
diff --git a/service-apply/src/hooks/react-query/useAnnounce.tsx b/service-apply/src/hooks/react-query/useAnnounce.tsx index 180b06b..b5812d6 100644 --- a/service-apply/src/hooks/react-query/useAnnounce.tsx +++ b/service-apply/src/hooks/react-query/useAnnounce.tsx @@ -5,7 +5,7 @@ import { getAnnounceById, } from '../../apis/announce.apis'; -export const useAnounceQuery = () => { +export const useAnnounceQuery = () => { const { data: announceData } = useSuspenseQuery({ queryKey: ['anounce'], queryFn: getAnnounceLast, @@ -13,7 +13,7 @@ export const useAnounceQuery = () => { return { announceData }; }; -export const useAnounceListQuery = (page: number) => { +export const useAnnounceListQuery = (page: number) => { const { data: announceListData } = useSuspenseQuery({ queryKey: ['anounceList', page], queryFn: () => getAllAnnounce(page), @@ -21,7 +21,7 @@ export const useAnounceListQuery = (page: number) => { return { announceListData }; }; -export const useAnounceDetailQuery = (announceId: number) => { +export const useAnnounceDetailQuery = (announceId: number) => { const { data: announceDetailData } = useSuspenseQuery({ queryKey: ['anounceDetail', announceId], queryFn: () => getAnnounceById(announceId), diff --git a/service-apply/src/pages/Anouncement/Announcement.page.tsx b/service-apply/src/pages/Anouncement/Announcement.page.tsx index 90bf98c..08a216c 100644 --- a/service-apply/src/pages/Anouncement/Announcement.page.tsx +++ b/service-apply/src/pages/Anouncement/Announcement.page.tsx @@ -1,6 +1,6 @@ import { Container, Txt } from '@quokka/design-system'; import { useNavigate, useParams } from 'react-router-dom'; -import { useAnounceDetailQuery } from '../../hooks/react-query/useAnnounce'; +import { useAnnounceDetailQuery } from '../../hooks/react-query/useAnnounce'; import { Icon } from '../../components/announcement/Icon'; export const AnnouncementPage = () => { @@ -9,7 +9,7 @@ export const AnnouncementPage = () => { if (isNaN(+announcementId)) throw new Error('announcementId must be number'); const navigate = useNavigate(); - const { announceDetailData } = useAnounceDetailQuery(+announcementId); + const { announceDetailData } = useAnnounceDetailQuery(+announcementId); const handleGoBack = () => { navigate(-1); }; diff --git a/service-apply/src/pages/Anouncement/AnnouncementList.page.tsx b/service-apply/src/pages/Anouncement/AnnouncementList.page.tsx index cff004a..558a3ea 100644 --- a/service-apply/src/pages/Anouncement/AnnouncementList.page.tsx +++ b/service-apply/src/pages/Anouncement/AnnouncementList.page.tsx @@ -2,7 +2,7 @@ import { AnnouncementList } from '../../components/announcement/AnnouncementList import { useLocation } from 'react-router-dom'; import { useMemo } from 'react'; import { PageNav } from '../../components/announcement/PageNav'; -import { useAnounceListQuery } from '../../hooks/react-query/useAnnounce'; +import { useAnnounceListQuery } from '../../hooks/react-query/useAnnounce'; const useQueryParameter = () => { const { search } = useLocation(); @@ -14,7 +14,7 @@ export const AnnouncementListPage = () => { const currentPage = query.get('pages') ?? '1'; const { announceListData: { announces, lastPage }, - } = useAnounceListQuery(+currentPage); + } = useAnnounceListQuery(+currentPage); return ( <> From 1331b6e9abda81962bb1e7dfb029cefb99f8b6f8 Mon Sep 17 00:00:00 2001 From: j8won Date: Sat, 9 Dec 2023 17:11:22 +0900 Subject: [PATCH 02/35] =?UTF-8?q?rename(apply):=20HomeInformation=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=EB=AA=85=20=EC=98=A4=ED=83=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-apply/src/components/home/HomeInformation.tsx | 4 ++-- service-apply/src/pages/Home.page.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/service-apply/src/components/home/HomeInformation.tsx b/service-apply/src/components/home/HomeInformation.tsx index c52d1b7..db01efa 100644 --- a/service-apply/src/components/home/HomeInformation.tsx +++ b/service-apply/src/components/home/HomeInformation.tsx @@ -1,7 +1,7 @@ import { Txt } from '@quokka/design-system'; import { useInformationQuery } from '../../hooks/react-query/useInformation'; -export const HomeInforamtion = () => { +export const HomeInformation = () => { const { information } = useInformationQuery(); return ( @@ -20,4 +20,4 @@ export const HomeInforamtion = () => { ); }; -export default HomeInforamtion; +export default HomeInformation; diff --git a/service-apply/src/pages/Home.page.tsx b/service-apply/src/pages/Home.page.tsx index d959c11..824fb4e 100644 --- a/service-apply/src/pages/Home.page.tsx +++ b/service-apply/src/pages/Home.page.tsx @@ -1,7 +1,7 @@ import { Suspense, useEffect } from 'react'; import { Footer } from '../components/common/Footer'; import { MainContainer } from '../components/common/MainContainer'; -import { HomeInforamtion } from '../components/home/HomeInformation'; +import { HomeInformation } from '../components/home/HomeInformation'; import { HomeLogin } from '../components/home/HomeLogin'; import { HomeAnnounce } from '../components/home/HomeAnnounce'; import { HomeTitle } from '../components/home/HomeTitle'; @@ -21,7 +21,7 @@ export const HomePage = () => {
- + From 76a34cba99f0e9748a1330465bf37e6251defc8a Mon Sep 17 00:00:00 2001 From: j8won Date: Sat, 9 Dec 2023 19:15:31 +0900 Subject: [PATCH 03/35] =?UTF-8?q?fix(apply):=20https.ts=EC=9D=98=20fetcher?= =?UTF-8?q?=20=ED=95=A8=EC=88=98=20return=20=EA=B0=92=EC=97=90=EC=84=9C=20?= =?UTF-8?q?Response=20dto=20=EC=82=AC=EC=9A=A9=ED=95=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8F=84=EB=A1=9D=20=EC=BD=94=EB=93=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-apply/src/functions/https.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/service-apply/src/functions/https.ts b/service-apply/src/functions/https.ts index b1a651b..0eb8c71 100644 --- a/service-apply/src/functions/https.ts +++ b/service-apply/src/functions/https.ts @@ -21,7 +21,8 @@ const fetcher = async (url: string, req: RequestInit) => { if (response.status >= 400) { return await errorStatusResult(response); } - return await response.json().then((data) => new Response(data)); + + return await response.json(); }; const errorStatusResult = async (response: globalThis.Response) => { From 3d539eb393ee63810a132f1404e55d128f7b954c Mon Sep 17 00:00:00 2001 From: j8won Date: Sat, 9 Dec 2023 19:16:32 +0900 Subject: [PATCH 04/35] =?UTF-8?q?fix(apply):=20getNotice=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=EC=97=90=EC=84=9C=20Notice=20=EB=A7=A4=EA=B0=9C?= =?UTF-8?q?=EB=B3=80=EC=88=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-apply/src/apis/notice.apis.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service-apply/src/apis/notice.apis.ts b/service-apply/src/apis/notice.apis.ts index fc26f24..d7e0bf0 100644 --- a/service-apply/src/apis/notice.apis.ts +++ b/service-apply/src/apis/notice.apis.ts @@ -7,5 +7,5 @@ export const getNotice = async () => { if (isErrorResponse(response)) { return new Notice({ noticeContent: '' }); } - return new Notice(response.data); + return new Notice(response); }; From 4fbc605a01c14911ce0f56e74c9bd18c18067f2b Mon Sep 17 00:00:00 2001 From: j8won Date: Sat, 9 Dec 2023 19:19:28 +0900 Subject: [PATCH 05/35] =?UTF-8?q?fix(apply):=20getAnnounceLast=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=EC=97=90=EC=84=9C=20LastAnnounce=20=EB=A7=A4=EA=B0=9C?= =?UTF-8?q?=EB=B3=80=EC=88=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-apply/src/apis/announce.apis.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service-apply/src/apis/announce.apis.ts b/service-apply/src/apis/announce.apis.ts index ff6ef5a..d726061 100644 --- a/service-apply/src/apis/announce.apis.ts +++ b/service-apply/src/apis/announce.apis.ts @@ -18,7 +18,7 @@ export const getAnnounceLast = async () => { announceTitle: '게시글이 없습니다', }); } - return new LastAnnounce(response.data); + return new LastAnnounce(response); }; export const getAnnounceById = async (announceId: number) => { From 94bd4db73c4eb6d4fe99ce49c6471484388b723e Mon Sep 17 00:00:00 2001 From: j8won Date: Sat, 9 Dec 2023 19:20:05 +0900 Subject: [PATCH 06/35] =?UTF-8?q?fix(apply):=20postLoin=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=EC=97=90=EC=84=9C=20UserToken=20=EB=A7=A4=EA=B0=9C?= =?UTF-8?q?=EB=B3=80=EC=88=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-apply/src/apis/user.apis.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service-apply/src/apis/user.apis.ts b/service-apply/src/apis/user.apis.ts index e95b1c7..0c0ed4e 100644 --- a/service-apply/src/apis/user.apis.ts +++ b/service-apply/src/apis/user.apis.ts @@ -13,7 +13,7 @@ export const postLogin = async (data: UserLoginRequest) => { if (isErrorResponse(response)) { throw new Error(response.reason); } - return new UserToken(response.data); + return new UserToken(response); }; export interface PasswordFindRequest { From 9fbf98b07f349074648ccfb543cc9dc79018de88 Mon Sep 17 00:00:00 2001 From: j8won Date: Sat, 9 Dec 2023 19:22:11 +0900 Subject: [PATCH 07/35] =?UTF-8?q?fix(apply):=20getRegistration=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=EC=97=90=EC=84=9C=20RegistrationOptionResponse=20?= =?UTF-8?q?=EB=A7=A4=EA=B0=9C=EB=B3=80=EC=88=98=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?=EB=B0=8F=20api=20=EC=8A=A4=ED=8E=99=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=9D=BC=20RegistrationOptionResponse=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9E=90=20=EB=B0=8F=20=EC=9D=B8=ED=84=B0?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-apply/src/apis/dtos/registration.dtos.ts | 6 +++--- service-apply/src/apis/registration.apis.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/service-apply/src/apis/dtos/registration.dtos.ts b/service-apply/src/apis/dtos/registration.dtos.ts index a0b59dc..345e82b 100644 --- a/service-apply/src/apis/dtos/registration.dtos.ts +++ b/service-apply/src/apis/dtos/registration.dtos.ts @@ -50,7 +50,7 @@ interface RegistrationResponseProps { carNum: string; isLight: boolean; phoneNum: string; - sector: { + sectors: { sectorId: number; sectorNum: string; sectorName: string; @@ -79,7 +79,7 @@ export class RegistrationOptionsResponse { isLight, name, phoneNum, - sector, + sectors, studentNum, selectSectorId, affiliation, @@ -89,7 +89,7 @@ export class RegistrationOptionsResponse { this.isCompact = isLight; this.studentName = name; this.phoneNumber = phoneNum; - this.sector = sector; + this.sector = sectors; this.studentNumber = studentNum; this.selectSectorId = selectSectorId; this.affiliation = affiliation; diff --git a/service-apply/src/apis/registration.apis.ts b/service-apply/src/apis/registration.apis.ts index b18f914..c93aff0 100644 --- a/service-apply/src/apis/registration.apis.ts +++ b/service-apply/src/apis/registration.apis.ts @@ -36,12 +36,12 @@ export const getRegistration = email: '', isLight: false, phoneNum: '', - sector: [], + sectors: [], studentNum: '', name: '', selectSectorId: -1, affiliation: '', }); } - return new RegistrationOptionsResponse(response.data); + return new RegistrationOptionsResponse(response); }; From 1b1c4a1cfc6515cdc8b3cec438e347c0f79d315a Mon Sep 17 00:00:00 2001 From: j8won Date: Sat, 9 Dec 2023 19:41:50 +0900 Subject: [PATCH 08/35] =?UTF-8?q?fix(apply):=20postRegistration=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=EC=97=90=EC=84=9C=20Response=20dto=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=20=EC=95=88=20=ED=95=A8=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=A5=B8=20=EC=97=90=EB=9F=AC=20=EC=B2=98=EB=A6=AC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20RegistrationResponse=20=EB=A7=A4?= =?UTF-8?q?=EA=B0=9C=EB=B3=80=EC=88=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-apply/src/apis/registration.apis.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/service-apply/src/apis/registration.apis.ts b/service-apply/src/apis/registration.apis.ts index c93aff0..1b62ed6 100644 --- a/service-apply/src/apis/registration.apis.ts +++ b/service-apply/src/apis/registration.apis.ts @@ -12,16 +12,18 @@ export const postRegistration = async ( ): Promise => { const { isRegistration, ...rest } = registration; const response = await https.post( - `/v1/registration/${registration.isRegistration}`, + `/v1/registration${registration.isRegistration || '/temporary'}`, rest, ); if (isErrorResponse(response)) { - if (response.status === 401 || response.status === 403) { - return reissueToken(() => postRegistration(registration)); - } - throw new Error(response.reason); + // TODO: response 값에 status와 reason이 없기 때문에 토큰 재발행 로직 불가능 + // if (response.status === 401 || response.status === 403) { + // return reissueToken(() => postRegistration(registration)); + // } + // throw new Error(response.reason); + throw new Error('주차권 임시저장에 실패했습니다'); } - return new RegistrationResponse(response.data); + return new RegistrationResponse(response); }; export const getRegistration = From 24d68ac74ee000c07a855cddc17f6b8ee7d68244 Mon Sep 17 00:00:00 2001 From: j8won Date: Sat, 9 Dec 2023 19:46:46 +0900 Subject: [PATCH 09/35] =?UTF-8?q?feat(apply):=20postRegistration=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=EC=97=90=EC=84=9C=20=EC=A3=BC=EC=B0=A8?= =?UTF-8?q?=EA=B6=8C=20=EC=8B=A0=EC=B2=AD=20=ED=98=B9=EC=9D=80=20=EC=9E=84?= =?UTF-8?q?=EC=8B=9C=EC=A0=80=EC=9E=A5=20=EC=97=AC=EB=B6=80=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20=EC=97=90=EB=9F=AC=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-apply/src/apis/registration.apis.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/service-apply/src/apis/registration.apis.ts b/service-apply/src/apis/registration.apis.ts index 1b62ed6..9c7bff5 100644 --- a/service-apply/src/apis/registration.apis.ts +++ b/service-apply/src/apis/registration.apis.ts @@ -12,7 +12,7 @@ export const postRegistration = async ( ): Promise => { const { isRegistration, ...rest } = registration; const response = await https.post( - `/v1/registration${registration.isRegistration || '/temporary'}`, + `/v1/registration${registration.isRegistration ? '' : '/temporary'}`, rest, ); if (isErrorResponse(response)) { @@ -21,6 +21,8 @@ export const postRegistration = async ( // return reissueToken(() => postRegistration(registration)); // } // throw new Error(response.reason); + if (registration.isRegistration) + throw new Error('주차권 신청에 실패했습니다'); throw new Error('주차권 임시저장에 실패했습니다'); } return new RegistrationResponse(response); From 1a16387954c0c26ef933714e3271a5b5e312b144 Mon Sep 17 00:00:00 2001 From: j8won Date: Sun, 10 Dec 2023 00:39:50 +0900 Subject: [PATCH 10/35] =?UTF-8?q?fix(apply):=20useAnnounceListQuery=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=EC=97=90=EC=84=9C=20getAllAnnounce=20?= =?UTF-8?q?=EB=A7=A4=EA=B0=9C=EB=B3=80=EC=88=98=20=EA=B0=92=201=20?= =?UTF-8?q?=EA=B0=90=EC=86=8C=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(=EC=B4=88=EA=B8=B0=EA=B0=92=EC=9D=B4=200)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-apply/src/hooks/react-query/useAnnounce.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service-apply/src/hooks/react-query/useAnnounce.tsx b/service-apply/src/hooks/react-query/useAnnounce.tsx index b5812d6..55d5d62 100644 --- a/service-apply/src/hooks/react-query/useAnnounce.tsx +++ b/service-apply/src/hooks/react-query/useAnnounce.tsx @@ -16,7 +16,7 @@ export const useAnnounceQuery = () => { export const useAnnounceListQuery = (page: number) => { const { data: announceListData } = useSuspenseQuery({ queryKey: ['anounceList', page], - queryFn: () => getAllAnnounce(page), + queryFn: () => getAllAnnounce(page - 1), }); return { announceListData }; }; From 302b99f42dcade365b4299c0b284f01461a61c59 Mon Sep 17 00:00:00 2001 From: j8won Date: Sun, 10 Dec 2023 00:42:08 +0900 Subject: [PATCH 11/35] =?UTF-8?q?fix(apply):=20postPasswordFind=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=EC=97=90=EC=84=9C=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20PasswordF?= =?UTF-8?q?ind=20=EB=A7=A4=EA=B0=9C=EB=B3=80=EC=88=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-apply/src/apis/user.apis.ts | 6 ++++-- .../src/hooks/password-reset/useRequestPasswordForm.tsx | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/service-apply/src/apis/user.apis.ts b/service-apply/src/apis/user.apis.ts index 0c0ed4e..e564714 100644 --- a/service-apply/src/apis/user.apis.ts +++ b/service-apply/src/apis/user.apis.ts @@ -23,9 +23,11 @@ export interface PasswordFindRequest { export const postPasswordFind = async ({ email }: PasswordFindRequest) => { const response = await https.post(`/v1/user/password/find`, { email }); if (isErrorResponse(response)) { - throw new Error(response.reason); + throw new Error('이메일 전송에 실패했습니다'); + // TODO: error response에 따른 에러 발생 + // throw new Error(response.reason); } - return new PasswordFind(response.data); + return new PasswordFind(response); }; export interface PasswordResetRequest { diff --git a/service-apply/src/hooks/password-reset/useRequestPasswordForm.tsx b/service-apply/src/hooks/password-reset/useRequestPasswordForm.tsx index eabcef9..c97acd1 100644 --- a/service-apply/src/hooks/password-reset/useRequestPasswordForm.tsx +++ b/service-apply/src/hooks/password-reset/useRequestPasswordForm.tsx @@ -29,7 +29,7 @@ export const useRequestPasswordForm = () => { { email }, { onSuccess: () => { - alert('이메일을 확인해주세요.'); + alert('본인인증 이메일이 전송되었습니다.'); navigate('/'); }, }, From 187a6bc7d4936418e846a5b7e61cd855b7bee1eb Mon Sep 17 00:00:00 2001 From: j8won Date: Sun, 10 Dec 2023 00:43:48 +0900 Subject: [PATCH 12/35] =?UTF-8?q?fix(apply):=20getAllAnnounce,=20getAnnoun?= =?UTF-8?q?ceById=20=ED=95=A8=EC=88=98=EC=97=90=EC=84=9C=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=EC=B2=98=EB=A6=AC=20=EC=88=98=EC=A0=95=20=EB=B0=8F?= =?UTF-8?q?=20=EB=B0=98=ED=99=98=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EB=A7=A4?= =?UTF-8?q?=EA=B0=9C=EB=B3=80=EC=88=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-apply/src/apis/announce.apis.ts | 8 +++++--- service-apply/src/components/home/HomeLogin.tsx | 1 - 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/service-apply/src/apis/announce.apis.ts b/service-apply/src/apis/announce.apis.ts index d726061..face862 100644 --- a/service-apply/src/apis/announce.apis.ts +++ b/service-apply/src/apis/announce.apis.ts @@ -7,7 +7,7 @@ export const getAllAnnounce = async (page: number) => { if (isErrorResponse(response)) { return new AllAnnounce({ announces: [], lastPage: 0, nextPage: 0 }); } - return new AllAnnounce(response.data); + return new AllAnnounce(response); }; export const getAnnounceLast = async () => { @@ -24,7 +24,9 @@ export const getAnnounceLast = async () => { export const getAnnounceById = async (announceId: number) => { const response = await https.get(`/v1/announce/${announceId}`); if (isErrorResponse(response)) { - throw new Error(response.reason); + throw new Error('게시글을 조회할 수 없습니다'); + // TODO: error response에 따른 에러 발생 + // throw new Error(response.reason); } - return new Announce(response.data); + return new Announce(response); }; diff --git a/service-apply/src/components/home/HomeLogin.tsx b/service-apply/src/components/home/HomeLogin.tsx index 36a442d..c7e7ad6 100644 --- a/service-apply/src/components/home/HomeLogin.tsx +++ b/service-apply/src/components/home/HomeLogin.tsx @@ -33,7 +33,6 @@ export const HomeLogin = () => { { email, pwd: password }, { onError: (error) => { - console.error(error); alert(error.message); setIsError(true); setErrorMessage(error.message); From 509c0cd9636fb45fecd8089f8b9896914debfc68 Mon Sep 17 00:00:00 2001 From: j8won Date: Sun, 10 Dec 2023 00:50:46 +0900 Subject: [PATCH 13/35] =?UTF-8?q?fix(apply):=20api=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EC=97=90=EB=9F=AC=20=EC=B2=98=EB=A6=AC=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 --- service-apply/src/apis/announce.apis.ts | 2 +- service-apply/src/apis/registration.apis.ts | 9 +++++---- service-apply/src/apis/user.apis.ts | 16 +++++++++++----- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/service-apply/src/apis/announce.apis.ts b/service-apply/src/apis/announce.apis.ts index face862..b432d55 100644 --- a/service-apply/src/apis/announce.apis.ts +++ b/service-apply/src/apis/announce.apis.ts @@ -25,7 +25,7 @@ export const getAnnounceById = async (announceId: number) => { const response = await https.get(`/v1/announce/${announceId}`); if (isErrorResponse(response)) { throw new Error('게시글을 조회할 수 없습니다'); - // TODO: error response에 따른 에러 발생 + // TODO: response dto에 status와 reason을 추가해야 아래 로직 가능 // throw new Error(response.reason); } return new Announce(response); diff --git a/service-apply/src/apis/registration.apis.ts b/service-apply/src/apis/registration.apis.ts index 9c7bff5..37d0eb7 100644 --- a/service-apply/src/apis/registration.apis.ts +++ b/service-apply/src/apis/registration.apis.ts @@ -16,7 +16,7 @@ export const postRegistration = async ( rest, ); if (isErrorResponse(response)) { - // TODO: response 값에 status와 reason이 없기 때문에 토큰 재발행 로직 불가능 + // TODO: response dto에 status와 reason을 추가해야 아래 로직 가능 // if (response.status === 401 || response.status === 403) { // return reissueToken(() => postRegistration(registration)); // } @@ -32,9 +32,10 @@ export const getRegistration = async (): Promise => { const response = await https.get('/v1/registration'); if (isErrorResponse(response)) { - if (response.status === 401 || response.status === 403) { - return reissueToken(getRegistration); - } + // TODO: response dto에 status와 reason을 추가해야 아래 로직 가능 + // if (response.status === 401 || response.status === 403) { + // return reissueToken(getRegistration); + // } return new RegistrationOptionsResponse({ carNum: '', email: '', diff --git a/service-apply/src/apis/user.apis.ts b/service-apply/src/apis/user.apis.ts index e564714..6916dbd 100644 --- a/service-apply/src/apis/user.apis.ts +++ b/service-apply/src/apis/user.apis.ts @@ -11,7 +11,9 @@ export interface UserLoginRequest { export const postLogin = async (data: UserLoginRequest) => { const response = await https.post(`/v1/auth/login`, data); if (isErrorResponse(response)) { - throw new Error(response.reason); + // TODO: response dto에 status와 reason을 추가해야 아래 로직 가능 + // throw new Error(response.reason); + throw new Error('로그인을 실패했습니다'); } return new UserToken(response); }; @@ -24,7 +26,7 @@ export const postPasswordFind = async ({ email }: PasswordFindRequest) => { const response = await https.post(`/v1/user/password/find`, { email }); if (isErrorResponse(response)) { throw new Error('이메일 전송에 실패했습니다'); - // TODO: error response에 따른 에러 발생 + // TODO: response dto에 status와 reason을 추가해야 아래 로직 가능 // throw new Error(response.reason); } return new PasswordFind(response); @@ -43,9 +45,11 @@ export const postPasswordReset = async ({ password, }); if (isErrorResponse(response)) { - throw new Error(response.reason); + // TODO: response dto에 status와 reason을 추가해야 아래 로직 가능 + // throw new Error(response.reason); + throw new Error('비밀번호 초기화를 실패했습니다'); } - return new PasswordReset(response.data); + return new PasswordReset(response); }; export const reissueToken = async (retryCallback: () => T): Promise => { @@ -57,7 +61,9 @@ export const reissueToken = async (retryCallback: () => T): Promise => { const response = await https.post(`/v1/auth/login`, { refreshtoken: token }); if (isErrorResponse(response)) { removeToken(); - throw new Error(response.reason); + // TODO: response dto에 status와 reason을 추가해야 아래 로직 가능 + // throw new Error(response.reason); + throw new Error('토큰 재발급에 실패했습니다. 다시 로그인 해주세요.'); } setToken(new UserToken(response.data)); From 28e9e557898a7270b1d7e60c05707de98d0aac55 Mon Sep 17 00:00:00 2001 From: j8won Date: Sun, 10 Dec 2023 00:53:34 +0900 Subject: [PATCH 14/35] =?UTF-8?q?fix(apply):=20PasswordResetForm=20input?= =?UTF-8?q?=20label=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/password-reset/PasswordResetForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service-apply/src/components/password-reset/PasswordResetForm.tsx b/service-apply/src/components/password-reset/PasswordResetForm.tsx index da07591..6aa900f 100644 --- a/service-apply/src/components/password-reset/PasswordResetForm.tsx +++ b/service-apply/src/components/password-reset/PasswordResetForm.tsx @@ -28,7 +28,7 @@ export const PasswordResetForm = ({ code }: { code: string }) => { Date: Mon, 11 Dec 2023 16:38:24 +0900 Subject: [PATCH 15/35] =?UTF-8?q?feat(apply):=20=EC=9E=90=EB=8F=99=20?= =?UTF-8?q?=EC=8B=A0=EC=B2=AD=20=EB=B0=A9=EC=A7=80=20=EB=AA=A8=EB=8B=AC?= =?UTF-8?q?=EC=B0=BD=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/apply/ApplyCaptchaModal.tsx | 70 +++++++++++++++++++ .../src/components/apply/ApplyForm.tsx | 16 ++++- 2 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 service-apply/src/components/apply/ApplyCaptchaModal.tsx diff --git a/service-apply/src/components/apply/ApplyCaptchaModal.tsx b/service-apply/src/components/apply/ApplyCaptchaModal.tsx new file mode 100644 index 0000000..f27bb2b --- /dev/null +++ b/service-apply/src/components/apply/ApplyCaptchaModal.tsx @@ -0,0 +1,70 @@ +import { Button, InputText, Modal, Txt } from '@quokka/design-system'; +import { PropsWithChildren, Suspense, useState } from 'react'; +import ErrorBoundary from '../common/ErrorBoundray'; +import Delete from '../../assets/delete.svg'; + +interface ApplyCaptchaModalProps extends PropsWithChildren { + isOpen: boolean; + onRequestClose: () => void; + onSave: () => void; +} + +const CaptchaForm = ({ onSubmit }: { onSubmit: () => void }) => { + return ( +
+ + 자동 신청 방지 + + +
+ +
+
+ +
+
+ ); +}; + +export const ApplyCaptchaModal = ({ + isOpen, + onRequestClose, + onSave, +}: ApplyCaptchaModalProps) => { + const [isLoading, setIsLoading] = useState(false); + + return ( + + {isLoading ?
loading
: } +
+ ); +}; diff --git a/service-apply/src/components/apply/ApplyForm.tsx b/service-apply/src/components/apply/ApplyForm.tsx index b623114..1ce10db 100644 --- a/service-apply/src/components/apply/ApplyForm.tsx +++ b/service-apply/src/components/apply/ApplyForm.tsx @@ -4,11 +4,14 @@ import { InputTextProps, Radio, Txt, + Modal, } from '@quokka/design-system'; import { useApplyForm } from '../../hooks/useApplyForm'; import { ApplySelector } from './ApplySelector'; import { clsx } from 'clsx'; import { useApplyQuery } from '../../hooks/react-query/useApply'; +import { useState } from 'react'; +import { ApplyCaptchaModal } from './ApplyCaptchaModal'; export const ApplyInputText = ({ className, ...props }: InputTextProps) => { return ( @@ -25,6 +28,7 @@ export const ApplyForm = () => { section: selectSectorId ?? 0, ...rest, }); + const [isCaptchaModalOpen, setIsCaptchaModalOpen] = useState(false); const parkingSection = sector.map((item) => ({ sectionNumber: item.sectorId, @@ -123,10 +127,20 @@ export const ApplyForm = () => { + { + setIsCaptchaModalOpen(false); + }} + onSave={() => onSave({ isRegistration: true })} + />
); From 3752d5bcd9af4c697ce81da76ad9cf753713747a Mon Sep 17 00:00:00 2001 From: j8won Date: Mon, 11 Dec 2023 16:39:15 +0900 Subject: [PATCH 16/35] =?UTF-8?q?feat(apply):=20api=20=EC=8A=A4=ED=8E=99?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EC=A3=BC?= =?UTF-8?q?=EC=B0=A8=EA=B6=8C=20=EC=8B=A0=EC=B2=AD=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?Dto=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/apis/dtos/registration.dtos.ts | 43 ++++++++++++++----- service-apply/src/hooks/useApplyForm.tsx | 30 ++++++++++--- 2 files changed, 55 insertions(+), 18 deletions(-) diff --git a/service-apply/src/apis/dtos/registration.dtos.ts b/service-apply/src/apis/dtos/registration.dtos.ts index 345e82b..15231b5 100644 --- a/service-apply/src/apis/dtos/registration.dtos.ts +++ b/service-apply/src/apis/dtos/registration.dtos.ts @@ -1,38 +1,59 @@ export interface RegistrationRequestProps { - email: string; + isRegistration: boolean; name: string; studentNumber: string; + affiliation: string; carNumber: string; isLightCar: boolean; phoneNumber: string; selectSectorId: number; - isRegistration: boolean; + captchaPendingCode?: string; + captchaAnswer?: string; + email: string; } -export class RegistrationRequest { +export interface RegistrationRequestDto { name: string; - studentNum: string; + studentNumber: string; + affiliation: string; carNum: string; isLight: boolean; phoneNum: string; selectSectorId: number; + captchaPendingCode?: string; + captchaAnswer?: string; +} + +export class RegistrationRequest { isRegistration: boolean; + requestDto: RegistrationRequestDto; + email: string; constructor({ + isRegistration, name, studentNumber, + affiliation, carNumber, isLightCar, phoneNumber, selectSectorId, - isRegistration, + captchaPendingCode, + captchaAnswer, + email, }: RegistrationRequestProps) { - this.name = name; - this.studentNum = studentNumber; - this.carNum = carNumber; - this.isLight = isLightCar; - this.phoneNum = phoneNumber; - this.selectSectorId = selectSectorId; this.isRegistration = isRegistration; + this.requestDto = { + name: name, + studentNumber: studentNumber, + affiliation: affiliation, + carNum: carNumber, + isLight: isLightCar, + phoneNum: phoneNumber, + selectSectorId: selectSectorId, + captchaPendingCode: captchaPendingCode, + captchaAnswer: captchaAnswer, + }; + this.email = email; } } diff --git a/service-apply/src/hooks/useApplyForm.tsx b/service-apply/src/hooks/useApplyForm.tsx index fb17e9f..8e5f906 100644 --- a/service-apply/src/hooks/useApplyForm.tsx +++ b/service-apply/src/hooks/useApplyForm.tsx @@ -7,6 +7,7 @@ import { import { useApplyMutate } from './react-query/useApply'; import { useNavigate } from 'react-router-dom'; import { removeToken } from '../functions/jwt'; +import { RegistrationRequest } from '../apis/dtos/registration.dtos'; type AppFormInputAction = | { @@ -62,23 +63,38 @@ const initValue = { isCompact: false, }; +interface registrationInfo { + isRegistration: boolean; + captchaPendingCode?: string; + captchaAnswer?: string; +} + export const useApplyForm = (init?: ApplyFormInput) => { init ||= initValue; const [state, dispatch] = useReducer(applyFormReducer, init); const { postRegistration } = useApplyMutate(); const navigate = useNavigate(); - const onSave = ({ isRegistration }: { isRegistration: boolean }) => { + const onSave = ({ + isRegistration, + captchaPendingCode, + captchaAnswer, + }: registrationInfo) => { + // TODO: affiliation, email 추가 postRegistration( - { + new RegistrationRequest({ isRegistration: isRegistration, - carNum: state.carNumber, name: state.studentName, - phoneNum: state.phoneNumber, + studentNumber: state.studentNumber, + affiliation: '공과대학', + isLightCar: state.isCompact, + carNumber: state.carNumber, + phoneNumber: state.phoneNumber, selectSectorId: +state.section, - studentNum: state.studentNumber, - isLight: state.isCompact, - }, + captchaPendingCode: captchaPendingCode, + captchaAnswer: captchaAnswer, + email: '', + }), { onError: (error) => { console.error(error); From 393fb27e5ff1c6c694029b76e6a730058cc33647 Mon Sep 17 00:00:00 2001 From: j8won Date: Mon, 11 Dec 2023 18:08:54 +0900 Subject: [PATCH 17/35] =?UTF-8?q?feat(apply):=20ApplyForm=EC=97=90=20?= =?UTF-8?q?=EC=86=8C=EC=86=8D=EB=8C=80=ED=95=99=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/apis/dtos/registration.dtos.ts | 32 ++++++++----------- .../src/components/apply/ApplyForm.tsx | 10 ++++++ service-apply/src/functions/validator.ts | 1 + service-apply/src/hooks/useApplyForm.tsx | 6 ++-- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/service-apply/src/apis/dtos/registration.dtos.ts b/service-apply/src/apis/dtos/registration.dtos.ts index 15231b5..8fa2870 100644 --- a/service-apply/src/apis/dtos/registration.dtos.ts +++ b/service-apply/src/apis/dtos/registration.dtos.ts @@ -12,9 +12,11 @@ export interface RegistrationRequestProps { email: string; } -export interface RegistrationRequestDto { +export class RegistrationRequest { + isRegistration: boolean; + // requestDto: RegistrationRequestDto; name: string; - studentNumber: string; + studentNum: string; affiliation: string; carNum: string; isLight: boolean; @@ -22,12 +24,7 @@ export interface RegistrationRequestDto { selectSectorId: number; captchaPendingCode?: string; captchaAnswer?: string; -} -export class RegistrationRequest { - isRegistration: boolean; - requestDto: RegistrationRequestDto; - email: string; constructor({ isRegistration, name, @@ -42,18 +39,15 @@ export class RegistrationRequest { email, }: RegistrationRequestProps) { this.isRegistration = isRegistration; - this.requestDto = { - name: name, - studentNumber: studentNumber, - affiliation: affiliation, - carNum: carNumber, - isLight: isLightCar, - phoneNum: phoneNumber, - selectSectorId: selectSectorId, - captchaPendingCode: captchaPendingCode, - captchaAnswer: captchaAnswer, - }; - this.email = email; + this.name = name; + this.studentNum = studentNumber; + this.affiliation = affiliation; + this.carNum = carNumber; + this.isLight = isLightCar; + this.phoneNum = phoneNumber; + this.selectSectorId = selectSectorId; + this.captchaPendingCode = captchaPendingCode; + this.captchaAnswer = captchaAnswer; } } diff --git a/service-apply/src/components/apply/ApplyForm.tsx b/service-apply/src/components/apply/ApplyForm.tsx index 1ce10db..1938136 100644 --- a/service-apply/src/components/apply/ApplyForm.tsx +++ b/service-apply/src/components/apply/ApplyForm.tsx @@ -77,6 +77,16 @@ export const ApplyForm = () => { value={state.studentNumber} required /> + + dispatch({ type: 'affiliation', payload: e.target.value }) + } + value={state.affiliation} + required + /> { isRegistration: isRegistration, name: state.studentName, studentNumber: state.studentNumber, - affiliation: '공과대학', + affiliation: state.affiliation, isLightCar: state.isCompact, carNumber: state.carNumber, phoneNumber: state.phoneNumber, selectSectorId: +state.section, captchaPendingCode: captchaPendingCode, captchaAnswer: captchaAnswer, - email: '', + email: state.email, }), { onError: (error) => { From cb734c50c540c976a1ddb7200f79862a08afec5e Mon Sep 17 00:00:00 2001 From: j8won Date: Mon, 11 Dec 2023 20:22:22 +0900 Subject: [PATCH 18/35] =?UTF-8?q?feat(apply):=20AnnouncementListItem=20bor?= =?UTF-8?q?der=20=EC=83=89=EC=83=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/announcement/AnnouncementListItem.tsx | 2 +- service-apply/src/hooks/useApplyForm.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/service-apply/src/components/announcement/AnnouncementListItem.tsx b/service-apply/src/components/announcement/AnnouncementListItem.tsx index 1a3e9e0..e4137ac 100644 --- a/service-apply/src/components/announcement/AnnouncementListItem.tsx +++ b/service-apply/src/components/announcement/AnnouncementListItem.tsx @@ -14,7 +14,7 @@ export const AnnouncementListItem = ({ return ( -
+
{announceTitle} {`${year}-${month}-${day}`}
diff --git a/service-apply/src/hooks/useApplyForm.tsx b/service-apply/src/hooks/useApplyForm.tsx index 5398b6b..feaa0dd 100644 --- a/service-apply/src/hooks/useApplyForm.tsx +++ b/service-apply/src/hooks/useApplyForm.tsx @@ -82,7 +82,6 @@ export const useApplyForm = (init?: ApplyFormInput) => { captchaPendingCode, captchaAnswer, }: registrationInfo) => { - // TODO: affiliation, email 추가 postRegistration( new RegistrationRequest({ isRegistration: isRegistration, From 7feee6625b5a4ac2c7d65b2101ade338e131f69e Mon Sep 17 00:00:00 2001 From: j8won Date: Mon, 11 Dec 2023 23:54:24 +0900 Subject: [PATCH 19/35] =?UTF-8?q?fix(apply):=20=EA=B3=B5=EC=A7=80=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EB=AA=A9=EB=A1=9D=20PageNav=20=EB=A7=A4=EA=B0=9C?= =?UTF-8?q?=EB=B3=80=EC=88=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-apply/src/pages/Anouncement/AnnouncementList.page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service-apply/src/pages/Anouncement/AnnouncementList.page.tsx b/service-apply/src/pages/Anouncement/AnnouncementList.page.tsx index 558a3ea..475775d 100644 --- a/service-apply/src/pages/Anouncement/AnnouncementList.page.tsx +++ b/service-apply/src/pages/Anouncement/AnnouncementList.page.tsx @@ -19,7 +19,7 @@ export const AnnouncementListPage = () => { return ( <> - + ); }; From 6ad4e85d1cabd1216939db7501d02c941b08c84c Mon Sep 17 00:00:00 2001 From: j8won Date: Mon, 11 Dec 2023 23:55:08 +0900 Subject: [PATCH 20/35] =?UTF-8?q?feat(apply):=20=EC=BA=A1=EC=B1=A0=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20api=20=ED=95=A8=EC=88=98=20=EB=B0=8F=20dto?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-apply/src/apis/captcha.apis.ts | 12 ++++++++++++ service-apply/src/apis/dtos/captcha.dtos.ts | 15 +++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 service-apply/src/apis/captcha.apis.ts create mode 100644 service-apply/src/apis/dtos/captcha.dtos.ts diff --git a/service-apply/src/apis/captcha.apis.ts b/service-apply/src/apis/captcha.apis.ts new file mode 100644 index 0000000..cc3b58f --- /dev/null +++ b/service-apply/src/apis/captcha.apis.ts @@ -0,0 +1,12 @@ +import { https } from '../functions/https'; +import { Captcha } from './dtos/captcha.dtos'; +import { isErrorResponse } from './dtos/response.dtos'; + +export const getCaptcha = async () => { + const response = await https.get('/v1/captcha'); + if (isErrorResponse(response)) { + throw new Error('자동 신청 방지 이미지 조회를 실패했습니다.'); + } + + return new Captcha(response); +}; diff --git a/service-apply/src/apis/dtos/captcha.dtos.ts b/service-apply/src/apis/dtos/captcha.dtos.ts new file mode 100644 index 0000000..30925f7 --- /dev/null +++ b/service-apply/src/apis/dtos/captcha.dtos.ts @@ -0,0 +1,15 @@ +export class Captcha { + captchaCode: string; + captchaImageUrl: string; + + constructor({ + captchaCode, + captchaImageUrl, + }: { + captchaCode: string; + captchaImageUrl: string; + }) { + this.captchaCode = captchaCode; + this.captchaImageUrl = captchaImageUrl; + } +} From 832b4d7dd49f33d492e769ad25e388d4299e0fdf Mon Sep 17 00:00:00 2001 From: j8won Date: Mon, 11 Dec 2023 23:55:48 +0900 Subject: [PATCH 21/35] =?UTF-8?q?feat(apply):=20api=20=EC=8A=A4=ED=8E=99?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20Registrat?= =?UTF-8?q?ionRequest=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-apply/src/apis/dtos/registration.dtos.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/service-apply/src/apis/dtos/registration.dtos.ts b/service-apply/src/apis/dtos/registration.dtos.ts index 8fa2870..7d80f03 100644 --- a/service-apply/src/apis/dtos/registration.dtos.ts +++ b/service-apply/src/apis/dtos/registration.dtos.ts @@ -14,7 +14,6 @@ export interface RegistrationRequestProps { export class RegistrationRequest { isRegistration: boolean; - // requestDto: RegistrationRequestDto; name: string; studentNum: string; affiliation: string; @@ -22,7 +21,7 @@ export class RegistrationRequest { isLight: boolean; phoneNum: string; selectSectorId: number; - captchaPendingCode?: string; + captchaCode?: string; captchaAnswer?: string; constructor({ @@ -46,7 +45,7 @@ export class RegistrationRequest { this.isLight = isLightCar; this.phoneNum = phoneNumber; this.selectSectorId = selectSectorId; - this.captchaPendingCode = captchaPendingCode; + this.captchaCode = captchaPendingCode; this.captchaAnswer = captchaAnswer; } } From fc94217337cbaf148c55cd644d15e8358c42df33 Mon Sep 17 00:00:00 2001 From: j8won Date: Tue, 12 Dec 2023 00:05:04 +0900 Subject: [PATCH 22/35] =?UTF-8?q?feat(apply):=20react-modal=EC=9D=B4=20?= =?UTF-8?q?=EC=88=A8=EA=B8=B8=20element=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-apply/src/main.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/service-apply/src/main.tsx b/service-apply/src/main.tsx index 7ec3659..75924f1 100644 --- a/service-apply/src/main.tsx +++ b/service-apply/src/main.tsx @@ -2,6 +2,7 @@ import { StrictMode } from 'react'; import * as ReactDOM from 'react-dom/client'; import App from './app/app'; import './main.css'; +import ReactModal from 'react-modal'; const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement, @@ -11,3 +12,5 @@ root.render( , ); + +ReactModal.setAppElement('#root'); From 1c24be90e373c749263f4bcccf8f781c17a5f9f9 Mon Sep 17 00:00:00 2001 From: j8won Date: Tue, 12 Dec 2023 00:45:11 +0900 Subject: [PATCH 23/35] =?UTF-8?q?feat(apply):=20Spinner=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-apply/src/assets/Spinner.tsx | 12 +++++++++ service-apply/src/assets/spinner.css | 40 ++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 service-apply/src/assets/Spinner.tsx create mode 100644 service-apply/src/assets/spinner.css diff --git a/service-apply/src/assets/Spinner.tsx b/service-apply/src/assets/Spinner.tsx new file mode 100644 index 0000000..0ea5908 --- /dev/null +++ b/service-apply/src/assets/Spinner.tsx @@ -0,0 +1,12 @@ +import './spinner.css'; + +export const Spinner = () => { + return ( +
+
+
+
+
+
+ ); +}; diff --git a/service-apply/src/assets/spinner.css b/service-apply/src/assets/spinner.css new file mode 100644 index 0000000..ba14709 --- /dev/null +++ b/service-apply/src/assets/spinner.css @@ -0,0 +1,40 @@ +.lds-ring { + width: 100%; + height: 120px; + position: relative; + background-color: white; + pointer-events: none; +} +.lds-ring div { + box-sizing: border-box; + display: block; + position: absolute; + left: calc(50% - 40px); + top: calc(50% - 40px); + transform: translate(-50%, -50%); + width: 80px; + height: 80px; + margin: 8px; + border: 8px solid black; + border-radius: 50%; + animation: lds-ring 1.2s 1s cubic-bezier(0.5, 0, 0.5, 1) infinite; + border-color: black transparent transparent transparent; + pointer-events: none; +} +.lds-ring div:nth-child(1) { + animation-delay: -0.45s; +} +.lds-ring div:nth-child(2) { + animation-delay: -0.3s; +} +.lds-ring div:nth-child(3) { + animation-delay: -0.15s; +} +@keyframes lds-ring { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} From 5ea1b3443caea3053485e8cca07081bf1b12a22a Mon Sep 17 00:00:00 2001 From: j8won Date: Tue, 12 Dec 2023 00:55:52 +0900 Subject: [PATCH 24/35] =?UTF-8?q?refactor(apply):=20=EC=BA=A1=EC=B1=A0=20?= =?UTF-8?q?=EB=AA=A8=EB=8B=AC=EC=B0=BD=20state=20=EA=B4=80=EB=A6=AC=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=EC=9D=84=20useApplyForm=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/apply/ApplyForm.tsx | 34 +++++++++++-------- service-apply/src/hooks/useApplyForm.tsx | 9 +++-- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/service-apply/src/components/apply/ApplyForm.tsx b/service-apply/src/components/apply/ApplyForm.tsx index 1938136..cf61286 100644 --- a/service-apply/src/components/apply/ApplyForm.tsx +++ b/service-apply/src/components/apply/ApplyForm.tsx @@ -10,7 +10,6 @@ import { useApplyForm } from '../../hooks/useApplyForm'; import { ApplySelector } from './ApplySelector'; import { clsx } from 'clsx'; import { useApplyQuery } from '../../hooks/react-query/useApply'; -import { useState } from 'react'; import { ApplyCaptchaModal } from './ApplyCaptchaModal'; export const ApplyInputText = ({ className, ...props }: InputTextProps) => { @@ -24,11 +23,11 @@ export const ApplyInputText = ({ className, ...props }: InputTextProps) => { export const ApplyForm = () => { const { registrationData } = useApplyQuery(); const { sector, selectSectorId, ...rest } = registrationData; - const { state, dispatch, onSave } = useApplyForm({ - section: selectSectorId ?? 0, - ...rest, - }); - const [isCaptchaModalOpen, setIsCaptchaModalOpen] = useState(false); + const { state, dispatch, onSave, isCaptchaModalOpen, setIsCaptchaModalOpen } = + useApplyForm({ + section: selectSectorId ?? 0, + ...rest, + }); const parkingSection = sector.map((item) => ({ sectionNumber: item.sectorId, @@ -139,18 +138,25 @@ export const ApplyForm = () => { color="primary" onClick={() => { setIsCaptchaModalOpen(true); - // onSave({ isRegistration: true }); }} > 신청하기 - { - setIsCaptchaModalOpen(false); - }} - onSave={() => onSave({ isRegistration: true })} - /> + {isCaptchaModalOpen && ( + { + setIsCaptchaModalOpen(false); + }} + handleSave={({ inputCode, answerCode }) => + onSave({ + isRegistration: true, + captchaPendingCode: answerCode, + captchaAnswer: inputCode, + }) + } + /> + )}
); diff --git a/service-apply/src/hooks/useApplyForm.tsx b/service-apply/src/hooks/useApplyForm.tsx index feaa0dd..d2fafed 100644 --- a/service-apply/src/hooks/useApplyForm.tsx +++ b/service-apply/src/hooks/useApplyForm.tsx @@ -1,4 +1,4 @@ -import { useReducer } from 'react'; +import { useReducer, useState } from 'react'; import { ApplyFormInput } from '../functions/validator'; import { phoneNumberReplace, @@ -77,6 +77,8 @@ export const useApplyForm = (init?: ApplyFormInput) => { const { postRegistration } = useApplyMutate(); const navigate = useNavigate(); + const [isCaptchaModalOpen, setIsCaptchaModalOpen] = useState(false); + const onSave = ({ isRegistration, captchaPendingCode, @@ -98,11 +100,12 @@ export const useApplyForm = (init?: ApplyFormInput) => { }), { onError: (error) => { - console.error(error); + isCaptchaModalOpen && setIsCaptchaModalOpen(false); alert(error.message); throw new Error(error.message); }, onSuccess: (data) => { + isCaptchaModalOpen && setIsCaptchaModalOpen(false); if (!data) throw new Error('data is undefined'); dispatch({ type: 'reset', payload: null }); alert(data.message); @@ -113,5 +116,5 @@ export const useApplyForm = (init?: ApplyFormInput) => { ); }; - return { state, dispatch, onSave }; + return { state, dispatch, onSave, isCaptchaModalOpen, setIsCaptchaModalOpen }; }; From 0837223cb52a2b5a4e3f860035ac24233e66e977 Mon Sep 17 00:00:00 2001 From: j8won Date: Tue, 12 Dec 2023 00:57:03 +0900 Subject: [PATCH 25/35] =?UTF-8?q?feat(apply):=20=EC=BA=A1=EC=B1=A0=20get?= =?UTF-8?q?=20query=EB=A5=BC=20=EC=BB=A4=EC=8A=A4=ED=85=80=20=ED=9B=85?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-apply/src/hooks/react-query/useCaptcha.tsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 service-apply/src/hooks/react-query/useCaptcha.tsx diff --git a/service-apply/src/hooks/react-query/useCaptcha.tsx b/service-apply/src/hooks/react-query/useCaptcha.tsx new file mode 100644 index 0000000..9215bc6 --- /dev/null +++ b/service-apply/src/hooks/react-query/useCaptcha.tsx @@ -0,0 +1,14 @@ +import { useSuspenseQuery } from '@tanstack/react-query'; +import { getCaptcha } from '../../apis/captcha.apis'; + +export const useCaptchaQuery = () => { + const { data } = useSuspenseQuery({ + queryKey: ['captcha'], + queryFn: getCaptcha, + }); + + return { + captchaCode: data.captchaCode, + captchaImageUrl: data.captchaImageUrl, + }; +}; From 68cc12afa43a5f538a8b0de2aa16f24f72489c37 Mon Sep 17 00:00:00 2001 From: j8won Date: Tue, 12 Dec 2023 00:57:51 +0900 Subject: [PATCH 26/35] =?UTF-8?q?feat(apply):=20=EC=BA=A1=EC=B1=A0=20?= =?UTF-8?q?=EB=AA=A8=EB=8B=AC=EC=B0=BD=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EB=B6=84=EB=A6=AC=20=EB=B0=8F=20=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=20=EB=A1=9C=EC=A7=81=20=EC=BB=A4=EC=8A=A4=ED=85=80=20=ED=9B=85?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/apply/ApplyCaptchaModal.tsx | 66 +++++++++---------- .../src/components/apply/CaptchaForm.tsx | 56 ++++++++++++++++ .../src/hooks/apply/useCaptchaForm.tsx | 27 ++++++++ 3 files changed, 114 insertions(+), 35 deletions(-) create mode 100644 service-apply/src/components/apply/CaptchaForm.tsx create mode 100644 service-apply/src/hooks/apply/useCaptchaForm.tsx diff --git a/service-apply/src/components/apply/ApplyCaptchaModal.tsx b/service-apply/src/components/apply/ApplyCaptchaModal.tsx index f27bb2b..aea264a 100644 --- a/service-apply/src/components/apply/ApplyCaptchaModal.tsx +++ b/service-apply/src/components/apply/ApplyCaptchaModal.tsx @@ -1,47 +1,24 @@ -import { Button, InputText, Modal, Txt } from '@quokka/design-system'; +import { Modal } from '@quokka/design-system'; import { PropsWithChildren, Suspense, useState } from 'react'; -import ErrorBoundary from '../common/ErrorBoundray'; -import Delete from '../../assets/delete.svg'; +import { CaptchaForm } from './CaptchaForm'; +import { Spinner } from '../../assets/Spinner'; interface ApplyCaptchaModalProps extends PropsWithChildren { isOpen: boolean; onRequestClose: () => void; - onSave: () => void; + handleSave: ({ + inputCode, + answerCode, + }: { + inputCode: string; + answerCode: string; + }) => void; } -const CaptchaForm = ({ onSubmit }: { onSubmit: () => void }) => { - return ( -
- - 자동 신청 방지 - - -
- -
-
- -
-
- ); -}; - export const ApplyCaptchaModal = ({ isOpen, onRequestClose, - onSave, + handleSave, }: ApplyCaptchaModalProps) => { const [isLoading, setIsLoading] = useState(false); @@ -64,7 +41,26 @@ export const ApplyCaptchaModal = ({ borderRadius: '1rem', }} > - {isLoading ?
loading
: } + {isLoading ? ( +
+ + 신청 접수 중입니다. 잠시만 기다려주세요. + + + 새로고침 시 신청이 취소됩니다. + +
+ +
+
+ ) : ( + + setIsLoading(true)} + /> + + )} ); }; diff --git a/service-apply/src/components/apply/CaptchaForm.tsx b/service-apply/src/components/apply/CaptchaForm.tsx new file mode 100644 index 0000000..e9a25b0 --- /dev/null +++ b/service-apply/src/components/apply/CaptchaForm.tsx @@ -0,0 +1,56 @@ +import { useCaptchaForm } from '../../hooks/apply/useCaptchaForm'; +import { Txt, InputText, Button } from '@quokka/design-system'; + +interface CaptchaFormProps { + handleSave: ({ + inputCode, + answerCode, + }: { + inputCode: string; + answerCode: string; + }) => void; + handleSubmitLoading: () => void; +} + +export const CaptchaForm = ({ + handleSave, + handleSubmitLoading, +}: CaptchaFormProps) => { + const { input, handleInput, captchaImageUrl, handleSubmit } = useCaptchaForm({ + postRegistration: handleSave, + }); + + return ( +
+ + 자동 신청 방지 + +
+ +
+
+ +
+
+ +
+
+ ); +}; diff --git a/service-apply/src/hooks/apply/useCaptchaForm.tsx b/service-apply/src/hooks/apply/useCaptchaForm.tsx new file mode 100644 index 0000000..52fe754 --- /dev/null +++ b/service-apply/src/hooks/apply/useCaptchaForm.tsx @@ -0,0 +1,27 @@ +import { ChangeEventHandler, FormEventHandler, useState } from 'react'; +import { useCaptchaQuery } from '../react-query/useCaptcha'; + +export const useCaptchaForm = ({ + postRegistration, +}: { + postRegistration: ({ + inputCode, + answerCode, + }: { + inputCode: string; + answerCode: string; + }) => void; +}) => { + const [input, setInput] = useState(''); + const { captchaCode, captchaImageUrl } = useCaptchaQuery(); + + const handleInput: ChangeEventHandler = (e) => { + setInput(e.target.value.replace(/[^0-9]/g, '')); + }; + + const handleSubmit = () => { + postRegistration({ inputCode: input, answerCode: captchaCode }); + }; + + return { input, handleInput, captchaImageUrl, handleSubmit }; +}; From 2645173116621bcff728061497e1490243218771 Mon Sep 17 00:00:00 2001 From: j8won Date: Tue, 12 Dec 2023 15:19:10 +0900 Subject: [PATCH 27/35] =?UTF-8?q?refactor(apply):=20=EC=BA=A1=EC=B1=A0=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20api=20=ED=95=A8=EC=88=98=20=EB=B0=8F=20Dto?= =?UTF-8?q?=EB=A5=BC=20registration=20=ED=8C=8C=EC=9D=BC=EC=97=90=EC=84=9C?= =?UTF-8?q?=20=EA=B4=80=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-apply/src/apis/captcha.apis.ts | 12 ------------ service-apply/src/apis/dtos/captcha.dtos.ts | 15 --------------- service-apply/src/apis/dtos/registration.dtos.ts | 16 ++++++++++++++++ service-apply/src/apis/registration.apis.ts | 10 ++++++++++ .../src/hooks/react-query/useCaptcha.tsx | 2 +- 5 files changed, 27 insertions(+), 28 deletions(-) delete mode 100644 service-apply/src/apis/captcha.apis.ts delete mode 100644 service-apply/src/apis/dtos/captcha.dtos.ts diff --git a/service-apply/src/apis/captcha.apis.ts b/service-apply/src/apis/captcha.apis.ts deleted file mode 100644 index cc3b58f..0000000 --- a/service-apply/src/apis/captcha.apis.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { https } from '../functions/https'; -import { Captcha } from './dtos/captcha.dtos'; -import { isErrorResponse } from './dtos/response.dtos'; - -export const getCaptcha = async () => { - const response = await https.get('/v1/captcha'); - if (isErrorResponse(response)) { - throw new Error('자동 신청 방지 이미지 조회를 실패했습니다.'); - } - - return new Captcha(response); -}; diff --git a/service-apply/src/apis/dtos/captcha.dtos.ts b/service-apply/src/apis/dtos/captcha.dtos.ts deleted file mode 100644 index 30925f7..0000000 --- a/service-apply/src/apis/dtos/captcha.dtos.ts +++ /dev/null @@ -1,15 +0,0 @@ -export class Captcha { - captchaCode: string; - captchaImageUrl: string; - - constructor({ - captchaCode, - captchaImageUrl, - }: { - captchaCode: string; - captchaImageUrl: string; - }) { - this.captchaCode = captchaCode; - this.captchaImageUrl = captchaImageUrl; - } -} diff --git a/service-apply/src/apis/dtos/registration.dtos.ts b/service-apply/src/apis/dtos/registration.dtos.ts index 7d80f03..55bf6f1 100644 --- a/service-apply/src/apis/dtos/registration.dtos.ts +++ b/service-apply/src/apis/dtos/registration.dtos.ts @@ -109,3 +109,19 @@ export class RegistrationOptionsResponse { this.affiliation = affiliation; } } + +export class CaptchaResponse { + captchaCode: string; + captchaImageUrl: string; + + constructor({ + captchaCode, + captchaImageUrl, + }: { + captchaCode: string; + captchaImageUrl: string; + }) { + this.captchaCode = captchaCode; + this.captchaImageUrl = captchaImageUrl; + } +} diff --git a/service-apply/src/apis/registration.apis.ts b/service-apply/src/apis/registration.apis.ts index 37d0eb7..274d1f3 100644 --- a/service-apply/src/apis/registration.apis.ts +++ b/service-apply/src/apis/registration.apis.ts @@ -1,5 +1,6 @@ import { https } from '../functions/https'; import { + CaptchaResponse, RegistrationOptionsResponse, RegistrationRequest, RegistrationResponse, @@ -50,3 +51,12 @@ export const getRegistration = } return new RegistrationOptionsResponse(response); }; + +export const getCaptcha = async () => { + const response = await https.get('/v1/captcha'); + if (isErrorResponse(response)) { + throw new Error('자동 신청 방지 이미지 조회를 실패했습니다.'); + } + + return new CaptchaResponse(response); +}; diff --git a/service-apply/src/hooks/react-query/useCaptcha.tsx b/service-apply/src/hooks/react-query/useCaptcha.tsx index 9215bc6..e7bf3ce 100644 --- a/service-apply/src/hooks/react-query/useCaptcha.tsx +++ b/service-apply/src/hooks/react-query/useCaptcha.tsx @@ -1,5 +1,5 @@ import { useSuspenseQuery } from '@tanstack/react-query'; -import { getCaptcha } from '../../apis/captcha.apis'; +import { getCaptcha } from 'service-apply/src/apis/registration.apis'; export const useCaptchaQuery = () => { const { data } = useSuspenseQuery({ From e17d0c17bf62ce3ce8954c72af3a786a054c6838 Mon Sep 17 00:00:00 2001 From: j8won Date: Wed, 13 Dec 2023 00:32:46 +0900 Subject: [PATCH 28/35] =?UTF-8?q?refactor(apply):=20=EC=8B=A0=EC=B2=AD=20a?= =?UTF-8?q?pi=20=ED=95=A8=EC=88=98=EB=A5=BC=20=EC=9E=84=EC=8B=9C=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=EA=B3=BC=20=EC=8B=A0=EC=B2=AD=20api=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/apis/dtos/registration.dtos.ts | 51 +++++++++++++------ service-apply/src/apis/registration.apis.ts | 35 ++++++++----- .../src/hooks/react-query/useApply.tsx | 44 ++++++++++++++++ .../src/hooks/react-query/useCaptcha.tsx | 14 ----- 4 files changed, 101 insertions(+), 43 deletions(-) delete mode 100644 service-apply/src/hooks/react-query/useCaptcha.tsx diff --git a/service-apply/src/apis/dtos/registration.dtos.ts b/service-apply/src/apis/dtos/registration.dtos.ts index 55bf6f1..5a50e9f 100644 --- a/service-apply/src/apis/dtos/registration.dtos.ts +++ b/service-apply/src/apis/dtos/registration.dtos.ts @@ -1,5 +1,4 @@ -export interface RegistrationRequestProps { - isRegistration: boolean; +export interface TemporarySaveRequestProps { name: string; studentNumber: string; affiliation: string; @@ -7,13 +6,9 @@ export interface RegistrationRequestProps { isLightCar: boolean; phoneNumber: string; selectSectorId: number; - captchaPendingCode?: string; - captchaAnswer?: string; - email: string; } -export class RegistrationRequest { - isRegistration: boolean; +export class TemporarySaveRequest { name: string; studentNum: string; affiliation: string; @@ -21,11 +16,8 @@ export class RegistrationRequest { isLight: boolean; phoneNum: string; selectSectorId: number; - captchaCode?: string; - captchaAnswer?: string; constructor({ - isRegistration, name, studentNumber, affiliation, @@ -33,11 +25,7 @@ export class RegistrationRequest { isLightCar, phoneNumber, selectSectorId, - captchaPendingCode, - captchaAnswer, - email, - }: RegistrationRequestProps) { - this.isRegistration = isRegistration; + }: TemporarySaveRequestProps) { this.name = name; this.studentNum = studentNumber; this.affiliation = affiliation; @@ -45,6 +33,39 @@ export class RegistrationRequest { this.isLight = isLightCar; this.phoneNum = phoneNumber; this.selectSectorId = selectSectorId; + } +} + +export interface RegistrationRequestProps extends TemporarySaveRequestProps { + captchaPendingCode: string; + captchaAnswer: string; +} + +export class RegistrationRequest extends TemporarySaveRequest { + captchaCode: string; + captchaAnswer: string; + + constructor({ + name, + studentNumber, + affiliation, + carNumber, + isLightCar, + phoneNumber, + selectSectorId, + captchaPendingCode, + captchaAnswer, + }: RegistrationRequestProps) { + super({ + name, + studentNumber, + affiliation, + carNumber, + isLightCar, + phoneNumber, + selectSectorId, + }); + this.captchaCode = captchaPendingCode; this.captchaAnswer = captchaAnswer; } diff --git a/service-apply/src/apis/registration.apis.ts b/service-apply/src/apis/registration.apis.ts index 274d1f3..9defd9d 100644 --- a/service-apply/src/apis/registration.apis.ts +++ b/service-apply/src/apis/registration.apis.ts @@ -4,27 +4,34 @@ import { RegistrationOptionsResponse, RegistrationRequest, RegistrationResponse, + TemporarySaveRequest, } from './dtos/registration.dtos'; import { isErrorResponse } from './dtos/response.dtos'; import { reissueToken } from './user.apis'; export const postRegistration = async ( - registration: RegistrationRequest, + data: RegistrationRequest, ): Promise => { - const { isRegistration, ...rest } = registration; - const response = await https.post( - `/v1/registration${registration.isRegistration ? '' : '/temporary'}`, - rest, - ); + const response = await https.post('/v1/registration', data); if (isErrorResponse(response)) { - // TODO: response dto에 status와 reason을 추가해야 아래 로직 가능 - // if (response.status === 401 || response.status === 403) { - // return reissueToken(() => postRegistration(registration)); - // } - // throw new Error(response.reason); - if (registration.isRegistration) - throw new Error('주차권 신청에 실패했습니다'); - throw new Error('주차권 임시저장에 실패했습니다'); + if (response.status === 401 || response.status === 403) { + return reissueToken(() => postRegistration(data)); + } + console.log(response.reason); + throw new Error(response.reason); + } + return new RegistrationResponse(response); +}; + +export const postTemporarySave = async ( + data: TemporarySaveRequest, +): Promise => { + const response = await https.post('/v1/registration/temporary', data); + if (isErrorResponse(response)) { + if (response.status === 401 || response.status === 403) { + return reissueToken(() => postTemporarySave(data)); + } + throw new Error(response.reason); } return new RegistrationResponse(response); }; diff --git a/service-apply/src/hooks/react-query/useApply.tsx b/service-apply/src/hooks/react-query/useApply.tsx index 8113737..9aadfa0 100644 --- a/service-apply/src/hooks/react-query/useApply.tsx +++ b/service-apply/src/hooks/react-query/useApply.tsx @@ -6,10 +6,13 @@ import { import { RegistrationRequest, RegistrationResponse, + TemporarySaveRequest, } from '../../apis/dtos/registration.dtos'; import { + getCaptcha, getRegistration, postRegistration, + postTemporarySave, } from '../../apis/registration.apis'; export const useApplyMutate = () => { @@ -41,6 +44,35 @@ export const useApplyMutate = () => { }; }; +export const useTemporarySaveMutate = () => { + const { mutate } = useMutation({ + mutationKey: ['applyTemporarySave'], + mutationFn: postTemporarySave, + }); + + return { + postTemporarySave: ( + temporarySaveRequest: TemporarySaveRequest, + mutateOption?: Omit< + MutateOptions< + RegistrationResponse, + Error, + TemporarySaveRequest, + unknown + >, + 'onSettled' + >, + ) => { + mutate(temporarySaveRequest, { + ...mutateOption, + onSettled: (data) => { + if (!data) throw new Error('data is undefined'); + }, + }); + }, + }; +}; + export const useApplyQuery = () => { const { data } = useSuspenseQuery({ queryKey: ['apply'], @@ -54,3 +86,15 @@ export const useApplyQuery = () => { registrationData: data, }; }; + +export const useCaptchaQuery = () => { + const { data } = useSuspenseQuery({ + queryKey: ['captcha'], + queryFn: getCaptcha, + }); + + return { + captchaCode: data.captchaCode, + captchaImageUrl: data.captchaImageUrl, + }; +}; diff --git a/service-apply/src/hooks/react-query/useCaptcha.tsx b/service-apply/src/hooks/react-query/useCaptcha.tsx deleted file mode 100644 index e7bf3ce..0000000 --- a/service-apply/src/hooks/react-query/useCaptcha.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { useSuspenseQuery } from '@tanstack/react-query'; -import { getCaptcha } from 'service-apply/src/apis/registration.apis'; - -export const useCaptchaQuery = () => { - const { data } = useSuspenseQuery({ - queryKey: ['captcha'], - queryFn: getCaptcha, - }); - - return { - captchaCode: data.captchaCode, - captchaImageUrl: data.captchaImageUrl, - }; -}; From 8436d96813464aca4903ff96c497183162d5efe2 Mon Sep 17 00:00:00 2001 From: j8won Date: Wed, 13 Dec 2023 00:34:03 +0900 Subject: [PATCH 29/35] =?UTF-8?q?refactor(apply):=20ApplyForm=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=EB=A5=BC=20context=20api=EB=A1=9C=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/apply/ApplyCaptchaModal.tsx | 10 +- .../src/components/apply/ApplyForm.tsx | 255 +++++++++--------- .../src/components/apply/CaptchaForm.tsx | 12 +- .../src/hooks/apply/useApplyFormContext.tsx | 61 +++++ .../src/hooks/apply/useCaptchaForm.tsx | 54 +++- service-apply/src/hooks/useApplyForm.tsx | 111 ++------ service-apply/src/store/ApplyFormContext.tsx | 26 ++ 7 files changed, 282 insertions(+), 247 deletions(-) create mode 100644 service-apply/src/hooks/apply/useApplyFormContext.tsx create mode 100644 service-apply/src/store/ApplyFormContext.tsx diff --git a/service-apply/src/components/apply/ApplyCaptchaModal.tsx b/service-apply/src/components/apply/ApplyCaptchaModal.tsx index aea264a..5e2cf95 100644 --- a/service-apply/src/components/apply/ApplyCaptchaModal.tsx +++ b/service-apply/src/components/apply/ApplyCaptchaModal.tsx @@ -6,19 +6,11 @@ import { Spinner } from '../../assets/Spinner'; interface ApplyCaptchaModalProps extends PropsWithChildren { isOpen: boolean; onRequestClose: () => void; - handleSave: ({ - inputCode, - answerCode, - }: { - inputCode: string; - answerCode: string; - }) => void; } export const ApplyCaptchaModal = ({ isOpen, onRequestClose, - handleSave, }: ApplyCaptchaModalProps) => { const [isLoading, setIsLoading] = useState(false); @@ -56,8 +48,8 @@ export const ApplyCaptchaModal = ({ ) : ( setIsLoading(true)} + closeModal={onRequestClose} /> )} diff --git a/service-apply/src/components/apply/ApplyForm.tsx b/service-apply/src/components/apply/ApplyForm.tsx index cf61286..e5fc9fa 100644 --- a/service-apply/src/components/apply/ApplyForm.tsx +++ b/service-apply/src/components/apply/ApplyForm.tsx @@ -1,15 +1,14 @@ +import { clsx } from 'clsx'; import { InputText, Button, InputTextProps, Radio, Txt, - Modal, } from '@quokka/design-system'; import { useApplyForm } from '../../hooks/useApplyForm'; +import { ApplyFormContext } from '../../store/ApplyFormContext'; import { ApplySelector } from './ApplySelector'; -import { clsx } from 'clsx'; -import { useApplyQuery } from '../../hooks/react-query/useApply'; import { ApplyCaptchaModal } from './ApplyCaptchaModal'; export const ApplyInputText = ({ className, ...props }: InputTextProps) => { @@ -21,13 +20,14 @@ export const ApplyInputText = ({ className, ...props }: InputTextProps) => { }; export const ApplyForm = () => { - const { registrationData } = useApplyQuery(); - const { sector, selectSectorId, ...rest } = registrationData; - const { state, dispatch, onSave, isCaptchaModalOpen, setIsCaptchaModalOpen } = - useApplyForm({ - section: selectSectorId ?? 0, - ...rest, - }); + const { + sector, + state, + dispatch, + onTemporarySave, + isCaptchaModalOpen, + setIsCaptchaModalOpen, + } = useApplyForm(); const parkingSection = sector.map((item) => ({ sectionNumber: item.sectorId, @@ -36,128 +36,127 @@ export const ApplyForm = () => { parkingSection.unshift({ sectionMajor: '선택', sectionNumber: 0 }); return ( -
- - dispatch({ type: 'phoneNumber', payload: e.target.value }) - } - value={state.phoneNumber} - required - /> - - - dispatch({ type: 'studentName', payload: e.target.value }) - } - value={state.studentName} - required - /> - - dispatch({ type: 'studentNumber', payload: e.target.value }) - } - value={state.studentNumber} - required - /> - - dispatch({ type: 'affiliation', payload: e.target.value }) - } - value={state.affiliation} - required - /> - dispatch({ type: 'section', payload: e.target.value })} - value={state.section} - required - /> - - dispatch({ type: 'carNumber', payload: e.target.value }) - } - value={state.carNumber} - required - /> -
-
- 경차 여부 * + +
+ + dispatch({ type: 'phoneNumber', payload: e.target.value }) + } + value={state.phoneNumber} + required + /> + + + dispatch({ type: 'studentName', payload: e.target.value }) + } + value={state.studentName} + required + /> + + dispatch({ type: 'studentNumber', payload: e.target.value }) + } + value={state.studentNumber} + required + /> + + dispatch({ type: 'affiliation', payload: e.target.value }) + } + value={state.affiliation} + required + /> + + dispatch({ type: 'section', payload: e.target.value }) + } + value={state.section} + required + /> + + dispatch({ type: 'carNumber', payload: e.target.value }) + } + value={state.carNumber} + required + /> +
+
+ 경차 여부 * +
+
+ { + dispatch({ type: 'isCompact', payload: true }); + }} + /> + { + dispatch({ type: 'isCompact', payload: false }); + }} + /> +
-
- { - dispatch({ type: 'isCompact', payload: true }); +
+ + + {isCaptchaModalOpen && ( + { + setIsCaptchaModalOpen(false); + }} + /> + )}
-
- - - {isCaptchaModalOpen && ( - { - setIsCaptchaModalOpen(false); - }} - handleSave={({ inputCode, answerCode }) => - onSave({ - isRegistration: true, - captchaPendingCode: answerCode, - captchaAnswer: inputCode, - }) - } - /> - )} -
-
+
); }; diff --git a/service-apply/src/components/apply/CaptchaForm.tsx b/service-apply/src/components/apply/CaptchaForm.tsx index e9a25b0..6c35653 100644 --- a/service-apply/src/components/apply/CaptchaForm.tsx +++ b/service-apply/src/components/apply/CaptchaForm.tsx @@ -2,22 +2,16 @@ import { useCaptchaForm } from '../../hooks/apply/useCaptchaForm'; import { Txt, InputText, Button } from '@quokka/design-system'; interface CaptchaFormProps { - handleSave: ({ - inputCode, - answerCode, - }: { - inputCode: string; - answerCode: string; - }) => void; handleSubmitLoading: () => void; + closeModal: () => void; } export const CaptchaForm = ({ - handleSave, handleSubmitLoading, + closeModal, }: CaptchaFormProps) => { const { input, handleInput, captchaImageUrl, handleSubmit } = useCaptchaForm({ - postRegistration: handleSave, + closeModal, }); return ( diff --git a/service-apply/src/hooks/apply/useApplyFormContext.tsx b/service-apply/src/hooks/apply/useApplyFormContext.tsx new file mode 100644 index 0000000..11ea112 --- /dev/null +++ b/service-apply/src/hooks/apply/useApplyFormContext.tsx @@ -0,0 +1,61 @@ +import { useReducer } from 'react'; +import { + phoneNumberReplace, + studentNumberReplace, +} from '../../functions/replacer'; +import { + ApplyFormContextType, + initApplyFormValue, +} from '../../store/ApplyFormContext'; + +type AppFormInputAction = + | { + type: keyof ApplyFormContextType; + payload: ApplyFormContextType[keyof ApplyFormContextType]; + } + | { + type: 'reset'; + payload: null; + }; + +const applyFormReducer = ( + state: ApplyFormContextType, + action: AppFormInputAction, +): ApplyFormContextType => { + switch (action.type) { + case 'phoneNumber': + return { + ...state, + phoneNumber: phoneNumberReplace(action.payload.toString()), + }; + case 'studentNumber': + return { + ...state, + studentNumber: studentNumberReplace(action.payload.toString()), + }; + case 'reset': + return { + ...state, + ...initApplyFormValue, + }; + case 'affiliation': + case 'email': + case 'studentName': + case 'section': + case 'carNumber': + case 'isCompact': + return { + ...state, + [action.type]: action.payload, + }; + default: + return state; + } +}; + +export const useApplyFormContext = (init?: ApplyFormContextType) => { + init ||= initApplyFormValue; + const [state, dispatch] = useReducer(applyFormReducer, init); + + return { state, dispatch }; +}; diff --git a/service-apply/src/hooks/apply/useCaptchaForm.tsx b/service-apply/src/hooks/apply/useCaptchaForm.tsx index 52fe754..e6e1492 100644 --- a/service-apply/src/hooks/apply/useCaptchaForm.tsx +++ b/service-apply/src/hooks/apply/useCaptchaForm.tsx @@ -1,26 +1,52 @@ -import { ChangeEventHandler, FormEventHandler, useState } from 'react'; -import { useCaptchaQuery } from '../react-query/useCaptcha'; +import { ChangeEventHandler, useContext, useState } from 'react'; +import { useApplyMutate, useCaptchaQuery } from '../react-query/useApply'; +import { RegistrationRequest } from '../../apis/dtos/registration.dtos'; +import { ApplyFormContext } from '../../store/ApplyFormContext'; +import { removeToken } from '../../functions/jwt'; +import { useNavigate } from 'react-router-dom'; -export const useCaptchaForm = ({ - postRegistration, -}: { - postRegistration: ({ - inputCode, - answerCode, - }: { - inputCode: string; - answerCode: string; - }) => void; -}) => { +export const useCaptchaForm = ({ closeModal }: { closeModal: () => void }) => { + const navigate = useNavigate(); const [input, setInput] = useState(''); + const { captchaCode, captchaImageUrl } = useCaptchaQuery(); + const { postRegistration } = useApplyMutate(); + const state = useContext(ApplyFormContext); const handleInput: ChangeEventHandler = (e) => { setInput(e.target.value.replace(/[^0-9]/g, '')); }; const handleSubmit = () => { - postRegistration({ inputCode: input, answerCode: captchaCode }); + postRegistration( + new RegistrationRequest({ + name: state.studentName, + studentNumber: state.studentNumber, + affiliation: state.affiliation, + isLightCar: state.isCompact, + carNumber: state.carNumber, + phoneNumber: state.phoneNumber, + selectSectorId: +state.section, + captchaPendingCode: captchaCode, + captchaAnswer: input, + }), + { + // FIXME: onError, onSuccess 동작 안 함 (쿼리 devtools에서는 error 캐칭 됨) + onError: (error) => { + console.log(error); + alert(error.message); + closeModal(); + throw new Error(error.message); + }, + onSuccess: (data) => { + if (!data) throw new Error('data is undefined'); + alert(data.message); + removeToken(); + closeModal(); + navigate('/'); + }, + }, + ); }; return { input, handleInput, captchaImageUrl, handleSubmit }; diff --git a/service-apply/src/hooks/useApplyForm.tsx b/service-apply/src/hooks/useApplyForm.tsx index d2fafed..d12a96d 100644 --- a/service-apply/src/hooks/useApplyForm.tsx +++ b/service-apply/src/hooks/useApplyForm.tsx @@ -1,92 +1,27 @@ -import { useReducer, useState } from 'react'; -import { ApplyFormInput } from '../functions/validator'; -import { - phoneNumberReplace, - studentNumberReplace, -} from '../functions/replacer'; -import { useApplyMutate } from './react-query/useApply'; +import { useState } from 'react'; +import { useApplyQuery, useTemporarySaveMutate } from './react-query/useApply'; import { useNavigate } from 'react-router-dom'; import { removeToken } from '../functions/jwt'; -import { RegistrationRequest } from '../apis/dtos/registration.dtos'; +import { TemporarySaveRequest } from '../apis/dtos/registration.dtos'; +import { useApplyFormContext } from './apply/useApplyFormContext'; -type AppFormInputAction = - | { - type: keyof ApplyFormInput; - payload: ApplyFormInput[keyof ApplyFormInput]; - } - | { - type: 'reset'; - payload: null; - }; - -const applyFormReducer = ( - state: ApplyFormInput, - action: AppFormInputAction, -): ApplyFormInput => { - switch (action.type) { - case 'phoneNumber': - return { - ...state, - phoneNumber: phoneNumberReplace(action.payload.toString()), - }; - case 'studentNumber': - return { - ...state, - studentNumber: studentNumberReplace(action.payload.toString()), - }; - case 'reset': - return { - ...state, - ...initValue, - }; - case 'affiliation': - case 'email': - case 'studentName': - case 'section': - case 'carNumber': - case 'isCompact': - return { - ...state, - [action.type]: action.payload, - }; - default: - return state; - } -}; - -const initValue = { - phoneNumber: '', - studentNumber: '', - email: '', - studentName: '', - affiliation: '', - section: 0, - carNumber: '', - isCompact: false, -}; +export const useApplyForm = () => { + const navigate = useNavigate(); -interface registrationInfo { - isRegistration: boolean; - captchaPendingCode?: string; - captchaAnswer?: string; -} + const { registrationData } = useApplyQuery(); + const { sector, selectSectorId, ...rest } = registrationData; -export const useApplyForm = (init?: ApplyFormInput) => { - init ||= initValue; - const [state, dispatch] = useReducer(applyFormReducer, init); - const { postRegistration } = useApplyMutate(); - const navigate = useNavigate(); + const { state, dispatch } = useApplyFormContext({ + section: selectSectorId ?? 0, + ...rest, + }); + const { postTemporarySave } = useTemporarySaveMutate(); const [isCaptchaModalOpen, setIsCaptchaModalOpen] = useState(false); - const onSave = ({ - isRegistration, - captchaPendingCode, - captchaAnswer, - }: registrationInfo) => { - postRegistration( - new RegistrationRequest({ - isRegistration: isRegistration, + const onTemporarySave = () => { + postTemporarySave( + new TemporarySaveRequest({ name: state.studentName, studentNumber: state.studentNumber, affiliation: state.affiliation, @@ -94,18 +29,13 @@ export const useApplyForm = (init?: ApplyFormInput) => { carNumber: state.carNumber, phoneNumber: state.phoneNumber, selectSectorId: +state.section, - captchaPendingCode: captchaPendingCode, - captchaAnswer: captchaAnswer, - email: state.email, }), { onError: (error) => { - isCaptchaModalOpen && setIsCaptchaModalOpen(false); alert(error.message); throw new Error(error.message); }, onSuccess: (data) => { - isCaptchaModalOpen && setIsCaptchaModalOpen(false); if (!data) throw new Error('data is undefined'); dispatch({ type: 'reset', payload: null }); alert(data.message); @@ -116,5 +46,12 @@ export const useApplyForm = (init?: ApplyFormInput) => { ); }; - return { state, dispatch, onSave, isCaptchaModalOpen, setIsCaptchaModalOpen }; + return { + sector, + state, + dispatch, + onTemporarySave, + isCaptchaModalOpen, + setIsCaptchaModalOpen, + }; }; diff --git a/service-apply/src/store/ApplyFormContext.tsx b/service-apply/src/store/ApplyFormContext.tsx new file mode 100644 index 0000000..a00ff89 --- /dev/null +++ b/service-apply/src/store/ApplyFormContext.tsx @@ -0,0 +1,26 @@ +import { createContext } from 'react'; + +export interface ApplyFormContextType { + phoneNumber: string; + studentNumber: string; + email: string; + studentName: string; + affiliation: string; + section: number; + carNumber: string; + isCompact: boolean; +} + +export const initApplyFormValue = { + phoneNumber: '', + studentNumber: '', + email: '', + studentName: '', + affiliation: '', + section: 0, + carNumber: '', + isCompact: false, +}; + +export const ApplyFormContext = + createContext(initApplyFormValue); From 200d226a55bd397fe578f7dae1a0d42df47cdbaa Mon Sep 17 00:00:00 2001 From: j8won Date: Wed, 13 Dec 2023 00:38:35 +0900 Subject: [PATCH 30/35] =?UTF-8?q?feat(apply):=20api=20=ED=86=B5=EC=8B=A0?= =?UTF-8?q?=20=EC=8B=A4=ED=8C=A8=20=EC=8B=9C=20reason=EC=9D=84=20=ED=99=9C?= =?UTF-8?q?=EC=9A=A9=ED=95=9C=20=EC=97=90=EB=9F=AC=20=EB=B0=9C=EC=83=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service-apply/src/apis/registration.apis.ts | 7 +++---- service-apply/src/apis/user.apis.ts | 16 ++++------------ 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/service-apply/src/apis/registration.apis.ts b/service-apply/src/apis/registration.apis.ts index 9defd9d..6cfc212 100644 --- a/service-apply/src/apis/registration.apis.ts +++ b/service-apply/src/apis/registration.apis.ts @@ -40,10 +40,9 @@ export const getRegistration = async (): Promise => { const response = await https.get('/v1/registration'); if (isErrorResponse(response)) { - // TODO: response dto에 status와 reason을 추가해야 아래 로직 가능 - // if (response.status === 401 || response.status === 403) { - // return reissueToken(getRegistration); - // } + if (response.status === 401 || response.status === 403) { + return reissueToken(getRegistration); + } return new RegistrationOptionsResponse({ carNum: '', email: '', diff --git a/service-apply/src/apis/user.apis.ts b/service-apply/src/apis/user.apis.ts index 6916dbd..88f4666 100644 --- a/service-apply/src/apis/user.apis.ts +++ b/service-apply/src/apis/user.apis.ts @@ -11,9 +11,7 @@ export interface UserLoginRequest { export const postLogin = async (data: UserLoginRequest) => { const response = await https.post(`/v1/auth/login`, data); if (isErrorResponse(response)) { - // TODO: response dto에 status와 reason을 추가해야 아래 로직 가능 - // throw new Error(response.reason); - throw new Error('로그인을 실패했습니다'); + throw new Error(response.reason); } return new UserToken(response); }; @@ -25,9 +23,7 @@ export interface PasswordFindRequest { export const postPasswordFind = async ({ email }: PasswordFindRequest) => { const response = await https.post(`/v1/user/password/find`, { email }); if (isErrorResponse(response)) { - throw new Error('이메일 전송에 실패했습니다'); - // TODO: response dto에 status와 reason을 추가해야 아래 로직 가능 - // throw new Error(response.reason); + throw new Error(response.reason); } return new PasswordFind(response); }; @@ -45,9 +41,7 @@ export const postPasswordReset = async ({ password, }); if (isErrorResponse(response)) { - // TODO: response dto에 status와 reason을 추가해야 아래 로직 가능 - // throw new Error(response.reason); - throw new Error('비밀번호 초기화를 실패했습니다'); + throw new Error(response.reason); } return new PasswordReset(response); }; @@ -61,9 +55,7 @@ export const reissueToken = async (retryCallback: () => T): Promise => { const response = await https.post(`/v1/auth/login`, { refreshtoken: token }); if (isErrorResponse(response)) { removeToken(); - // TODO: response dto에 status와 reason을 추가해야 아래 로직 가능 - // throw new Error(response.reason); - throw new Error('토큰 재발급에 실패했습니다. 다시 로그인 해주세요.'); + throw new Error(response.reason); } setToken(new UserToken(response.data)); From 6be4aefef92ba31d789a867fbb2084c45e214aa4 Mon Sep 17 00:00:00 2001 From: j8won Date: Wed, 13 Dec 2023 00:51:53 +0900 Subject: [PATCH 31/35] =?UTF-8?q?refactor(apply):=20ApplyCaptchaModalProps?= =?UTF-8?q?=20=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=83=81=EC=86=8D=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/apply/ApplyCaptchaModal.tsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/service-apply/src/components/apply/ApplyCaptchaModal.tsx b/service-apply/src/components/apply/ApplyCaptchaModal.tsx index 5e2cf95..31eed3d 100644 --- a/service-apply/src/components/apply/ApplyCaptchaModal.tsx +++ b/service-apply/src/components/apply/ApplyCaptchaModal.tsx @@ -2,8 +2,9 @@ import { Modal } from '@quokka/design-system'; import { PropsWithChildren, Suspense, useState } from 'react'; import { CaptchaForm } from './CaptchaForm'; import { Spinner } from '../../assets/Spinner'; +import ErrorBoundary from '../common/ErrorBoundray'; -interface ApplyCaptchaModalProps extends PropsWithChildren { +interface ApplyCaptchaModalProps { isOpen: boolean; onRequestClose: () => void; } @@ -47,10 +48,12 @@ export const ApplyCaptchaModal = ({
) : ( - setIsLoading(true)} - closeModal={onRequestClose} - /> + + setIsLoading(true)} + closeModal={onRequestClose} + /> + )} From 8352c07f6a7688b2fcc65f56f7da5e229b0e146c Mon Sep 17 00:00:00 2001 From: j8won Date: Wed, 13 Dec 2023 17:12:17 +0900 Subject: [PATCH 32/35] =?UTF-8?q?fix(apply):=20useCaptchaForm=20=ED=9B=85?= =?UTF-8?q?=20=EC=82=AC=EC=9A=A9=20=EC=9C=84=EC=B9=98=EB=A5=BC=20CaptchaFo?= =?UTF-8?q?rm=EC=97=90=EC=84=9C=20ApplyCaptchaModal=EB=A1=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/apply/ApplyCaptchaModal.tsx | 23 +++++++++------- .../src/components/apply/ApplyForm.tsx | 21 +++++++++------ .../src/components/apply/CaptchaForm.tsx | 27 +++++++++---------- 3 files changed, 39 insertions(+), 32 deletions(-) diff --git a/service-apply/src/components/apply/ApplyCaptchaModal.tsx b/service-apply/src/components/apply/ApplyCaptchaModal.tsx index 31eed3d..55d7797 100644 --- a/service-apply/src/components/apply/ApplyCaptchaModal.tsx +++ b/service-apply/src/components/apply/ApplyCaptchaModal.tsx @@ -1,8 +1,9 @@ import { Modal } from '@quokka/design-system'; -import { PropsWithChildren, Suspense, useState } from 'react'; +import { Suspense, useState } from 'react'; import { CaptchaForm } from './CaptchaForm'; import { Spinner } from '../../assets/Spinner'; import ErrorBoundary from '../common/ErrorBoundray'; +import { useCaptchaForm } from '../../hooks/apply/useCaptchaForm'; interface ApplyCaptchaModalProps { isOpen: boolean; @@ -14,6 +15,9 @@ export const ApplyCaptchaModal = ({ onRequestClose, }: ApplyCaptchaModalProps) => { const [isLoading, setIsLoading] = useState(false); + const { input, handleInput, captchaImageUrl, handleSubmit } = useCaptchaForm({ + closeModal: onRequestClose, + }); return (
) : ( - - - setIsLoading(true)} - closeModal={onRequestClose} - /> - - + { + setIsLoading(true); + handleSubmit(); + }} + /> )} ); diff --git a/service-apply/src/components/apply/ApplyForm.tsx b/service-apply/src/components/apply/ApplyForm.tsx index e5fc9fa..f6fe4a3 100644 --- a/service-apply/src/components/apply/ApplyForm.tsx +++ b/service-apply/src/components/apply/ApplyForm.tsx @@ -10,6 +10,8 @@ import { useApplyForm } from '../../hooks/useApplyForm'; import { ApplyFormContext } from '../../store/ApplyFormContext'; import { ApplySelector } from './ApplySelector'; import { ApplyCaptchaModal } from './ApplyCaptchaModal'; +import { Suspense } from 'react'; +import ErrorBoundary from '../common/ErrorBoundray'; export const ApplyInputText = ({ className, ...props }: InputTextProps) => { return ( @@ -147,14 +149,17 @@ export const ApplyForm = () => { > 신청하기 - {isCaptchaModalOpen && ( - { - setIsCaptchaModalOpen(false); - }} - /> - )} + + + + { + setIsCaptchaModalOpen(false); + }} + /> + +
diff --git a/service-apply/src/components/apply/CaptchaForm.tsx b/service-apply/src/components/apply/CaptchaForm.tsx index 6c35653..fc24ede 100644 --- a/service-apply/src/components/apply/CaptchaForm.tsx +++ b/service-apply/src/components/apply/CaptchaForm.tsx @@ -1,19 +1,19 @@ -import { useCaptchaForm } from '../../hooks/apply/useCaptchaForm'; +import { ChangeEventHandler } from 'react'; import { Txt, InputText, Button } from '@quokka/design-system'; interface CaptchaFormProps { - handleSubmitLoading: () => void; - closeModal: () => void; + codeInput: string; + handleCodeInput: ChangeEventHandler; + captchaImageUrl: string; + handleSubmit: () => void; } export const CaptchaForm = ({ - handleSubmitLoading, - closeModal, + codeInput, + handleCodeInput, + captchaImageUrl, + handleSubmit, }: CaptchaFormProps) => { - const { input, handleInput, captchaImageUrl, handleSubmit } = useCaptchaForm({ - closeModal, - }); - return (
@@ -25,8 +25,8 @@ export const CaptchaForm = ({