Skip to content

refactor: 중복 가입 및 이중 클릭 방지#234

Merged
hyeeuncho merged 8 commits intodevelopfrom
refactor/#233/duplicated-email
Jul 9, 2025
Merged

refactor: 중복 가입 및 이중 클릭 방지#234
hyeeuncho merged 8 commits intodevelopfrom
refactor/#233/duplicated-email

Conversation

@hyeeuncho
Copy link
Copy Markdown
Member

@hyeeuncho hyeeuncho commented Jul 9, 2025

Summary by CodeRabbit

  • 신규 기능

    • 참가자 관리 페이지에 Excel 내보내기 기능이 추가되었습니다.
    • SMS 인증번호 발송 및 인증 기능이 추가되었습니다.
  • 버그 수정

    • 참가자 카드에서 티켓명이 길 경우 말줄임 처리되어 UI가 깨지지 않도록 개선되었습니다.
  • 기능 개선

    • 버튼 컴포넌트에 type 속성(‘button’, ‘submit’, ‘reset’)이 추가되었습니다.
    • 참가자 리스트 헤더명이 "참여자 정보"에서 "옵션 응답"으로 변경되었습니다.
    • 이벤트 생성, 호스트 생성, 티켓 생성 시 중복 제출을 방지하는 기능이 추가되었습니다.
    • 티켓 주문 시 판매 기간 및 재고 수량을 확인하는 검증이 강화되었습니다.
    • 인증 콜백에서 이메일 중복 상황에 대한 안내 및 홈 이동 처리가 추가되었습니다.
  • UI/UX 개선

    • 연락처 입력란의 레이아웃이 개선되었습니다.
    • 연락처 유효성 검사 메시지가 "000-0000-0000 형식으로 입력해주세요."로 변경되었습니다.

@hyeeuncho hyeeuncho linked an issue Jul 9, 2025 that may be closed by this pull request
@hyeeuncho hyeeuncho self-assigned this Jul 9, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jul 9, 2025

Walkthrough

이 변경사항들은 참가자 Excel 다운로드 기능, SMS 인증 API 및 훅 추가, 중복 제출 방지 로직 도입, UI 텍스트 및 스타일 조정, 입력 검증 메시지 변경 등 다양한 기능 개선 및 UI/UX 향상을 포함합니다. 또한 버튼 컴포넌트에 type 속성 추가와 인증 콜백 처리 로직의 명확화가 이루어졌습니다.

Changes

파일/경로 요약 변경 내용 요약
design-system/ui/Button.tsx ButtonProps에 type 속성 추가, Button 컴포넌트가 type 속성 지원(기본값 'submit')
src/features/dashboard/api/participants.ts 참가자 Excel 다운로드 함수(downloadExcel) 추가
src/pages/dashboard/ui/ParticipantsMangementPage.tsx Excel 내보내기 버튼 및 exportToExcel 함수 추가, 레이아웃 조정
src/features/dashboard/ui/PariticipantsList.tsx 컬럼명 "참여자 정보" → "옵션 응답"으로 변경
src/features/dashboard/ui/ParticipantCard.tsx 티켓명에 max-width, ellipsis 스타일 적용
src/features/event/ui/EventFunnel.tsx
src/pages/dashboard/ui/ticket/TicketCreatePage.tsx
이벤트/호스트/티켓 생성 중복 제출 방지(isSubmittingX) 상태 및 가드 추가
src/features/join/api/user.ts
src/features/join/hooks/useUserHook.ts
SMS 인증번호 발송/검증 API 및 React Query mutation 훅 추가, 성공/실패 alert 처리
src/pages/join/AuthCallback.tsx 'duplicatedEmail' 상태 처리 추가, useEffect 내 동기적 분기 및 중복 실행 방지 ref 도입
src/pages/join/InfoInputPage.tsx 연락처 입력란 flexbox 레이아웃 래퍼 추가, 코드 포맷팅 소폭 변경
src/shared/lib/formValidation.ts 연락처 유효성 검증 메시지 변경(형식 안내 메시지 수정)
src/widgets/event/ui/TicketInfo.tsx 티켓 주문 시: 티켓 존재, 판매기간, 수량 등 추가 검증 로직 도입, 검증 실패 시 alert 후 중단

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ParticipantsManagementPage
  participant downloadExcel(API)
  participant Backend

  User->>ParticipantsManagementPage: "Excel" 버튼 클릭
  ParticipantsManagementPage->>downloadExcel: downloadExcel(eventId)
  downloadExcel->>Backend: GET /host-channels/dashboard/participant-management/excel?eventId
  Backend-->>downloadExcel: Excel 파일(blob), Content-Disposition 헤더
  downloadExcel->>ParticipantsManagementPage: 트리거된 파일 다운로드
  ParticipantsManagementPage->>User: Excel 다운로드 시작
Loading
sequenceDiagram
  participant User
  participant useSendCertificationCode
  participant sendCertificationCode(API)
  participant Backend

  User->>useSendCertificationCode: 인증번호 요청
  useSendCertificationCode->>sendCertificationCode: phoneNum 전달
  sendCertificationCode->>Backend: POST /sms/send
  Backend-->>sendCertificationCode: 응답(성공/실패)
  sendCertificationCode-->>useSendCertificationCode: 결과
  useSendCertificationCode->>User: 성공/실패 alert
Loading
sequenceDiagram
  participant User
  participant TicketCreatePage
  participant createTicketMutation

  User->>TicketCreatePage: 저장 버튼 클릭
  TicketCreatePage->>TicketCreatePage: isSubmitting 체크
  alt 이미 제출 중
    TicketCreatePage-->>User: (중복 제출 무시)
  else 미제출
    TicketCreatePage->>createTicketMutation: 티켓 생성 요청
    createTicketMutation-->>TicketCreatePage: 성공/실패 콜백
    TicketCreatePage->>User: 성공 시 이동, 완료 후 isSubmitting 해제
  end
Loading

Suggested labels

🪄 Refactoring, 🛠️ BugFix

Suggested reviewers

  • Yejiin21
  • xaexunxang

Poem

🐇
변화의 바람이 살랑살랑,
Excel 내보내기, 인증번호도 번쩍!
중복 제출 막아주는 똑똑한 가드,
버튼엔 타입, 티켓명은 말끔하게.
토끼는 깡총, 코드를 응원해!
🥕✨

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@hyeeuncho hyeeuncho added the 🪄 Refactoring 코드 리팩토링 label Jul 9, 2025
@github-actions
Copy link
Copy Markdown

github-actions bot commented Jul 9, 2025

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🔭 Outside diff range comments (2)
src/features/event/ui/EventFunnel.tsx (2)

50-61: 이벤트 생성 중복 방지 로직이 잘 구현되었습니다.

하지만 setIsSubmittingEvent(false)를 호출하는 로직이 누락되어 있습니다. 성공/실패 시 상태를 재설정해야 합니다.

 const handleCreateEvent = () => {
   if (isSubmittingEvent) return;
   setIsSubmittingEvent(true);
   createEvent(eventState, {
     onSuccess: () => {
+      setIsSubmittingEvent(false);
       navigate('/menu/myHost');
     },
     onError: error => {
+      setIsSubmittingEvent(false);
       console.error('API 호출 실패:', error);
     },
   });
 }

69-82: 호스트 생성 중복 방지 로직이 잘 구현되었습니다.

마찬가지로 setIsSubmittingHost(false)를 호출하는 로직이 누락되어 있습니다. 성공/실패 시 상태를 재설정해야 합니다.

 const handleHostCreation = () => {
   if (isSubmittingHost) return;
   setIsSubmittingHost(true);
   createHost(hostState, {
     onSuccess: () => {
+      setIsSubmittingHost(false);
       setHostState(initialHostState);
       goTo(StepNames.HostSelection);
     },
     onError: error => {
+      setIsSubmittingHost(false);
       const message = error?.message || '호스트 생성에 실패했습니다. 다시 시도해주세요.';
       alert(message);
     },
   });
 };
🧹 Nitpick comments (6)
src/features/join/hooks/useUserHook.ts (2)

32-43: 인증번호 발송 훅 구현이 적절합니다.

React Query mutation 패턴을 올바르게 사용하고 있습니다. 다만 alert()보다는 toast나 다른 비침습적 알림 방식을 고려해보세요.


45-57: 인증번호 검증 훅 구현이 적절합니다.

매개변수 구조체를 사용한 접근 방식이 좋습니다. 마찬가지로 alert() 대신 더 나은 사용자 경험을 위해 toast 알림을 고려해보세요.

src/features/dashboard/api/participants.ts (3)

32-32: 프로덕션 코드에서 console.log 제거가 필요합니다.

디버깅용 console.log를 제거해주세요.

-  console.log(response.headers)

35-42: 파일명 추출 로직을 선택적 연결로 개선할 수 있습니다.

정적 분석 도구에서 제안한 대로 선택적 연결을 사용하여 코드를 더 안전하게 만들 수 있습니다.

-if (disposition) {
-  const match = disposition.match(/filename\*=UTF-8''(.+)/);
-  if (match && match[1]) {
-    filename = decodeURIComponent(match[1]);
-  }
-}
+const match = disposition?.match(/filename\*=UTF-8''(.+)/);
+if (match?.[1]) {
+  filename = decodeURIComponent(match[1]);
+}

43-43: 프로덕션 코드에서 console.log 제거가 필요합니다.

디버깅용 console.log를 제거해주세요.

-console.log(disposition)
src/pages/dashboard/ui/ticket/TicketCreatePage.tsx (1)

67-89: 사용하지 않는 변수를 제거해주세요.

catch 블록의 e 변수가 사용되지 않습니다. ESLint 경고를 해결하기 위해 제거하거나 언더스코어로 변경해주세요.

- } catch (e) {
+ } catch {
   setIsSubmitting(false);
 }

또는

- } catch (e) {
+ } catch (_) {
   setIsSubmitting(false);
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e5aae60 and 0e07790.

📒 Files selected for processing (13)
  • design-system/ui/Button.tsx (1 hunks)
  • src/features/dashboard/api/participants.ts (1 hunks)
  • src/features/dashboard/ui/PariticipantsList.tsx (1 hunks)
  • src/features/dashboard/ui/ParticipantCard.tsx (1 hunks)
  • src/features/event/ui/EventFunnel.tsx (3 hunks)
  • src/features/join/api/user.ts (1 hunks)
  • src/features/join/hooks/useUserHook.ts (2 hunks)
  • src/pages/dashboard/ui/ParticipantsMangementPage.tsx (3 hunks)
  • src/pages/dashboard/ui/ticket/TicketCreatePage.tsx (3 hunks)
  • src/pages/join/AuthCallback.tsx (1 hunks)
  • src/pages/join/InfoInputPage.tsx (3 hunks)
  • src/shared/lib/formValidation.ts (1 hunks)
  • src/widgets/event/ui/TicketInfo.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: xaexunxang
PR: GoTogether-Inc/frontend#106
File: src/entities/event/model/eventRequest.ts:26-30
Timestamp: 2025-04-29T10:26:21.217Z
Learning: GoTogether 프로젝트의 이벤트 API에서는 생성(EventCreate)과 수정(EventUpdate) 인터페이스에서 다른 필드명을 사용합니다:
- EventCreate: organizerEmail, organizerPhoneNumber (Swagger 스펙 기준)
- EventUpdate: hostEmail, hostPhoneNumber (Notion 스펙 기준)
이는 백엔드 API 명세의 불일치로 인한 의도적인 차이입니다.
src/shared/lib/formValidation.ts (1)
Learnt from: xaexunxang
PR: GoTogether-Inc/frontend#106
File: src/entities/event/model/eventRequest.ts:26-30
Timestamp: 2025-04-29T10:26:21.217Z
Learning: GoTogether 프로젝트의 이벤트 API에서는 생성(EventCreate)과 수정(EventUpdate) 인터페이스에서 다른 필드명을 사용합니다:
- EventCreate: organizerEmail, organizerPhoneNumber (Swagger 스펙 기준)
- EventUpdate: hostEmail, hostPhoneNumber (Notion 스펙 기준)
이는 백엔드 API 명세의 불일치로 인한 의도적인 차이입니다.
🧬 Code Graph Analysis (6)
src/features/join/api/user.ts (1)
src/shared/types/api/http-client.ts (1)
  • axiosClient (15-22)
src/features/dashboard/api/participants.ts (1)
src/shared/types/api/http-client.ts (1)
  • axiosClient (15-22)
src/pages/join/AuthCallback.tsx (2)
src/app/provider/authStore.ts (1)
  • useAuthStore (17-36)
src/features/join/hooks/useUserHook.ts (1)
  • useUserInfo (5-11)
src/features/join/hooks/useUserHook.ts (1)
src/features/join/api/user.ts (2)
  • sendCertificationCode (27-29)
  • verifyCertificationCode (32-34)
src/pages/dashboard/ui/ParticipantsMangementPage.tsx (1)
src/features/dashboard/api/participants.ts (1)
  • downloadExcel (24-57)
src/pages/dashboard/ui/ticket/TicketCreatePage.tsx (1)
src/features/ticket/api/ticket.ts (1)
  • createTicket (4-7)
🪛 Biome (1.9.4)
src/features/dashboard/api/participants.ts

[error] 39-40: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 ESLint
src/pages/dashboard/ui/ticket/TicketCreatePage.tsx

[error] 87-87: 'e' is defined but never used.

(@typescript-eslint/no-unused-vars)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: storybook
🔇 Additional comments (19)
src/features/join/api/user.ts (2)

26-29: SMS 인증번호 발송 API 함수 구현이 적절합니다.

구현이 간단하고 명확하지만, 응답 데이터를 반환하지 않아 성공/실패 정보를 상위 레이어에서 활용하기 어려울 수 있습니다.


31-34: 인증번호 검증 API 함수 구현이 적절합니다.

함수 구현이 명확하고 매개변수 구조가 적절합니다. 에러 처리는 hook 레이어에서 담당하는 구조로 적절히 분리되어 있습니다.

src/pages/join/AuthCallback.tsx (4)

3-3: useRef 임포트 추가가 적절합니다.

중복 실행 방지를 위한 useRef 사용이 올바른 접근 방식입니다.


9-9: 상태 값 주석 추가가 유용합니다.

가능한 상태 값들을 주석으로 명시하여 코드 이해도를 높였습니다.


12-12: 중복 실행 방지 구현이 적절합니다.

useRef를 사용하여 중복 실행을 방지하는 방식이 효과적입니다.


15-37: 인증 콜백 처리 로직이 개선되었습니다.

각 상태별로 명확한 처리 로직을 구현하고, 중복 실행을 방지하는 가드 로직이 잘 구현되어 있습니다. 'duplicatedEmail' 상태 처리도 적절히 추가되었습니다.

src/features/dashboard/api/participants.ts (1)

45-57: Excel 파일 다운로드 구현이 적절합니다.

Blob을 사용한 파일 다운로드 로직이 올바르게 구현되어 있습니다. 메모리 정리를 위한 revokeObjectURL 호출도 적절합니다.

src/features/event/ui/EventFunnel.tsx (1)

26-28: 중복 클릭 방지 상태 변수 추가가 적절합니다.

이벤트 생성과 호스트 생성의 중복 제출을 방지하기 위한 상태 변수가 명확하게 구현되어 있습니다.

src/features/dashboard/ui/PariticipantsList.tsx (1)

75-75: UI 텍스트 개선이 적절합니다.

컬럼 헤더를 "참여자 정보"에서 "옵션 응답"으로 변경한 것은 해당 컬럼이 실제로 보여주는 내용을 더 명확하게 나타냅니다.

src/features/dashboard/ui/ParticipantCard.tsx (1)

42-44: 티켓 이름 표시 개선이 적절합니다.

긴 티켓 이름으로 인한 레이아웃 깨짐을 방지하기 위해 최대 너비 제한과 텍스트 말줄임 처리를 추가한 것은 좋은 UI 개선입니다.

src/shared/lib/formValidation.ts (1)

12-12: 에러 메시지 단순화가 적절합니다.

전화번호 유효성 검사 에러 메시지를 더 간결하고 직관적인 형태로 변경했습니다. 사용자가 예상 형식을 쉽게 이해할 수 있도록 개선되었습니다.

design-system/ui/Button.tsx (3)

6-6: type 속성 추가가 적절합니다.

Button 컴포넌트에 type 속성을 추가하여 폼 제어 기능을 향상시켰습니다. 기본값 'submit'은 폼 버튼에 적합하며, 옵셔널 속성으로 다양한 사용 사례에 대응할 수 있습니다.


9-9: 기본값 설정이 적절합니다.

type 매개변수에 'submit' 기본값을 설정한 것은 폼 버튼의 일반적인 사용 패턴과 일치합니다.


12-12: type 속성 적용이 올바릅니다.

버튼 엘리먼트에 type 속성을 명시적으로 설정하여 HTML 표준을 준수하고 폼 동작을 명확히 했습니다.

src/pages/join/InfoInputPage.tsx (1)

107-119: 연락처 입력 필드 레이아웃 개선입니다.

연락처 입력 필드를 flex 레이아웃으로 감싸서 향후 추가 UI 요소(예: 인증 버튼)를 위한 공간을 확보했습니다. 레이아웃 구조가 잘 설계되어 있어 확장성을 고려한 좋은 변경입니다.

src/widgets/event/ui/TicketInfo.tsx (1)

66-84: 훌륭한 검증 로직 추가입니다.

티켓 구매 전 필수 검증 사항들이 체계적으로 추가되었습니다:

  • 티켓 존재 여부 확인
  • 판매 기간 검증
  • 재고 수량 검증

이러한 검증은 사용자 경험과 데이터 무결성을 크게 향상시킵니다.

src/pages/dashboard/ui/ParticipantsMangementPage.tsx (1)

51-61: UI 레이아웃 개선이 잘 되었습니다.

Excel 내보내기 버튼이 추가되고 기존 통계 정보와 함께 justify-between 레이아웃으로 잘 배치되었습니다.

src/pages/dashboard/ui/ticket/TicketCreatePage.tsx (2)

17-17: 중복 제출 방지 로직이 잘 추가되었습니다.

isSubmitting 상태를 통한 중복 클릭 방지는 사용자 경험과 데이터 무결성을 위해 중요한 개선사항입니다.


77-86: 비동기 처리와 상태 관리가 잘 구현되었습니다.

createTicket mutation의 콜백을 통한 성공 시 네비게이션과 완료 시 상태 초기화가 적절히 처리되었습니다.

@SimoKii SimoKii self-requested a review July 9, 2025 11:43
@hyeeuncho hyeeuncho merged commit 15c9478 into develop Jul 9, 2025
2 checks passed
@hyeeuncho hyeeuncho deleted the refactor/#233/duplicated-email branch July 9, 2025 11:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🪄 Refactoring 코드 리팩토링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[refactor] 중복 가입 및 이중 클릭 방지

2 participants