Skip to content

[feature] 동아리 지원하기 기능#536

Merged
lepitaaar merged 12 commits intodevelop-fefrom
feature/user-apply
Jul 17, 2025
Merged

[feature] 동아리 지원하기 기능#536
lepitaaar merged 12 commits intodevelop-fefrom
feature/user-apply

Conversation

@lepitaaar
Copy link
Contributor

@lepitaaar lepitaaar commented Jul 11, 2025

#️⃣연관된 이슈

ex) #530

📝작업 내용

동아리 지원하기와 지원서 제작을 활성화 시켰습니다.
동아리가 지원상태가 아닐시 접속 지원하기 되지않음.
수동주소 접속시 알림창 띄우고 리다이렉트.
지원서의 첫번째 질문은 무조건 이름

중점적으로 리뷰받고 싶은 부분(선택)

논의하고 싶은 부분(선택)

새로 질문에 readOnly라는 필드가 생겼는데 가시성에 어떤 차별점을 두는게 좋을까요?

🫡 참고사항

Summary by CodeRabbit

  • 신규 기능

    • 지원서 작성 및 제출 기능이 활성화되어 사용자가 동아리 지원서를 작성하고 제출할 수 있습니다.
    • 관리자 페이지에서 지원서 생성 폼과 지원서 답변 폼 경로가 활성화되었습니다.
  • 버그 수정

    • 지원서 조회 시 서버의 구체적인 에러 메시지가 표시되도록 개선되었습니다.
  • 기능 개선

    • 지원서 첫 번째 질문(이름 입력란)이 고정되어 수정할 수 없도록 변경되었습니다.
    • 지원서 답변 데이터 구조가 일관성 있게 변경되었습니다(answervalue).
    • 지원 버튼 클릭 시 모집 여부에 따라 안내 메시지 및 이동 동작이 명확해졌습니다.
    • 지원 버튼 관련 props가 단순화되어 관리가 쉬워졌습니다.
    • 사이드바의 '지원 관리' 탭 클릭 시 더 이상 안내 메시지가 뜨지 않고 정상적으로 이동합니다.
  • 스타일

    • 읽기 전용 질문에 대해 시각적으로 비활성화된 상태가 적용되었습니다.

@lepitaaar lepitaaar requested review from oesnuj and seongwon030 July 11, 2025 01:35
@lepitaaar lepitaaar self-assigned this Jul 11, 2025
@lepitaaar lepitaaar added 📬 API 서버 API 통신 작업 💻 FE Frontend labels Jul 11, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 11, 2025

Warning

.coderabbit.yaml has a parsing error

The CodeRabbit configuration file in this repository has a parsing error and default settings were used instead. Please fix the error(s) in the configuration file. You can initialize chat with CodeRabbit to get help with the configuration file.

💥 Parsing errors (1)
Validation error: Invalid regex pattern for base branch. Received: "**" at "reviews.auto_review.base_branches[0]"
⚙️ Configuration instructions
  • 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

"""

Walkthrough

이 변경은 지원서 생성 및 답변 입력 폼 관련 라우트를 활성화하고, 지원서 답변 제출 API(applyToClub)를 추가하며, 답변 입력 로직 및 UI를 개선합니다. 또한, 지원서 폼의 첫 번째 질문을 고정(읽기 전용)으로 만들고, 관련 타입 및 컴포넌트 프로퍼티를 정비하였습니다.

Changes

파일/경로 요약 변경 내용 요약
frontend/src/App.tsx 지원서 생성 및 답변 입력 라우트 주석 해제 및 활성화
frontend/src/apis/application/applyToClub.ts 지원서 답변 제출용 applyToClub API 함수 추가
frontend/src/apis/application/getApplication.ts 에러 발생 시 서버 메시지 기반으로 에러 처리 개선
frontend/src/constants/INITIAL_FORM_DATA.ts 첫 질문(이름 입력) 추가, 질문 id 순서 조정
frontend/src/hooks/useAnswers.ts, frontend/src/types/application.ts 답변 객체의 키를 answervalue로 변경, answers 상태 반환 추가, 관련 타입 수정
frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx 첫 번째 질문에 readOnly prop 적용(이름 질문 고정)
frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.tsx,
QuestionBuilder.styles.ts
readOnly prop 추가, 읽기 전용일 때 삭제 버튼 숨김 및 스타일 비활성화
frontend/src/pages/AdminPage/application/answer/AnswerApplicationForm.tsx 지원서 데이터 에러 처리 분리, 답변 제출 핸들러(handleSubmit) 추가, 제출 성공/실패 알림 및 네비게이션 처리
frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.tsx,
ClubDetailFooter.tsx,
ClubDetailHeader.tsx
지원 버튼 prop 단순화(isRecruiting만 사용), 관련 로직 및 UI 정비
frontend/src/pages/AdminPage/components/SideBar/SideBar.tsx '지원 관리' 탭 클릭 시 알림 제거, 네비게이션 허용

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ClubDetailPage
    participant AnswerApplicationForm
    participant useAnswers
    participant applyToClub API

    User->>ClubDetailPage: 지원하기 버튼 클릭
    ClubDetailPage->>AnswerApplicationForm: 지원서 답변 입력 폼 렌더링
    User->>AnswerApplicationForm: 답변 입력
    AnswerApplicationForm->>useAnswers: 답변 상태 업데이트
    User->>AnswerApplicationForm: 제출 버튼 클릭
    AnswerApplicationForm->>applyToClub API: 답변 데이터 제출
    applyToClub API-->>AnswerApplicationForm: 성공/실패 응답
    AnswerApplicationForm->>User: 성공/실패 알림 및 페이지 이동
Loading

Possibly related PRs

Suggested labels

✨ Feature

Suggested reviewers

  • seongwon030
    """

📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 512a559 and ed44003.

📒 Files selected for processing (1)
  • frontend/src/constants/INITIAL_FORM_DATA.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/constants/INITIAL_FORM_DATA.ts
✨ 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.

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.

@netlify
Copy link

netlify bot commented Jul 11, 2025

Deploy Preview for moadong ready!

Name Link
🔨 Latest commit ed44003
🔍 Latest deploy log https://app.netlify.com/projects/moadong/deploys/687351deeb5cad00088efa01
😎 Deploy Preview https://deploy-preview-536--moadong.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 43
Accessibility: 89
Best Practices: 92
SEO: 92
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Contributor

@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: 3

🔭 Outside diff range comments (1)
frontend/src/pages/ClubDetailPage/components/ClubDetailFooter/ClubDetailFooter.tsx (1)

7-17: 사용하지 않는 props를 인터페이스에서 제거하세요.

recruitmentFormpresidentPhoneNumber props가 더 이상 사용되지 않으므로 인터페이스에서 제거해야 합니다.

다음 diff로 수정하세요:

interface ClubDetailFooterProps {
  recruitmentPeriod: string;
- recruitmentForm: string;
- presidentPhoneNumber: string;
}

const ClubDetailFooter = ({
  recruitmentPeriod,
- recruitmentForm,
- presidentPhoneNumber,
}: ClubDetailFooterProps) => {
🧹 Nitpick comments (6)
frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx (1)

161-161: 엄격한 동등성 비교를 사용하세요.

== 대신 ===를 사용하여 타입 안전성을 보장하세요.

-              readOnly={index == 0} //인덱스 0번은 이름을 위한 고정 부분이므로 수정 불가
+              readOnly={index === 0} //인덱스 0번은 이름을 위한 고정 부분이므로 수정 불가
frontend/src/constants/INITIAL_FORM_DATA.ts (1)

8-30: 매직 넘버를 명명된 상수로 교체하세요.

질문 ID에 사용된 하드코딩된 숫자들을 명명된 상수로 교체하여 가독성을 향상시키세요.

다음과 같이 개선할 수 있습니다:

+const QUESTION_IDS = {
+  NAME: 1,
+  SECOND_QUESTION: 2,
+  THIRD_QUESTION: 3,
+} as const;

const INITIAL_FORM_DATA: ApplicationFormData = {
  title: '',
  questions: [
    //맨 처음은 이름
    {
-     id: 1,
+     id: QUESTION_IDS.NAME,
      title: '이름',
      description: '지원자의 이름을 입력해주세요.',
      type: 'SHORT_TEXT',
      options: { required: true },
      items: [],
    },
    {
-     id: 2,
+     id: QUESTION_IDS.SECOND_QUESTION,
      title: '',
      description: '',
      type: 'SHORT_TEXT',
      options: { required: true },
      items: [],
    },
    {
-     id: 3,
+     id: QUESTION_IDS.THIRD_QUESTION,
      title: '',
      description: '',
      type: 'CHOICE',
      options: { required: true },
      items: [{ value: '' }, { value: '' }],
    },
  ],
};
frontend/src/apis/application/applyToClub.ts (2)

16-20: 불필요한 전개 연산자 제거

questions 배열을 생성할 때 전개 연산자 ...answers를 사용하는 것은 불필요합니다. answers가 이미 배열이므로 직접 할당하는 것이 더 효율적입니다.

         body: JSON.stringify({ 
-          questions: [
-            ...answers
-          ]
+          questions: answers
          }),

24-26: 에러 메시지 상수화 고려

하드코딩된 에러 메시지는 일관성을 위해 상수로 추출하는 것을 고려해보세요.

     if (!response.ok) {
-      throw new Error('답변 제출에 실패했습니다.');
+      throw new Error(ERROR_MESSAGES.SUBMIT_FAILED);
     }
frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.tsx (1)

50-53: alert 메시지 상수화

코딩 가이드라인에 따라 매직 넘버와 하드코딩된 문자열을 상수로 추출하는 것이 좋습니다.

+const ALERT_MESSAGES = {
+  RECRUITMENT_CLOSED: '지원모집이 마감되었습니다. 다음에 지원해 주세요.'
+} as const;

     if (!isRecruiting) {
-      alert('지원모집이 마감되었습니다. 다음에 지원해 주세요.')
+      alert(ALERT_MESSAGES.RECRUITMENT_CLOSED);
       return;
     }
frontend/src/pages/AdminPage/application/answer/AnswerApplicationForm.tsx (1)

48-52: 사용자 경험 개선

alert() 대신 토스트 메시지나 모달을 사용하여 더 나은 사용자 경험을 제공하는 것을 고려해보세요. 또한 제출 중 로딩 상태를 표시하는 것도 좋습니다.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 20b400e and db1e1c7.

📒 Files selected for processing (14)
  • frontend/src/App.tsx (3 hunks)
  • frontend/src/apis/application/applyToClub.ts (1 hunks)
  • frontend/src/apis/application/getApplication.ts (1 hunks)
  • frontend/src/constants/INITIAL_FORM_DATA.ts (1 hunks)
  • frontend/src/hooks/useAnswers.ts (2 hunks)
  • frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx (1 hunks)
  • frontend/src/pages/AdminPage/application/answer/AnswerApplicationForm.tsx (3 hunks)
  • frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.styles.ts (1 hunks)
  • frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.tsx (3 hunks)
  • frontend/src/pages/AdminPage/components/SideBar/SideBar.tsx (0 hunks)
  • frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.tsx (3 hunks)
  • frontend/src/pages/ClubDetailPage/components/ClubDetailFooter/ClubDetailFooter.tsx (1 hunks)
  • frontend/src/pages/ClubDetailPage/components/ClubDetailHeader/ClubDetailHeader.tsx (1 hunks)
  • frontend/src/types/application.ts (2 hunks)
💤 Files with no reviewable changes (1)
  • frontend/src/pages/AdminPage/components/SideBar/SideBar.tsx
🧰 Additional context used
📓 Path-based instructions (2)
`frontend/**/*.{ts,tsx}`: Replace magic numbers with named constants for clarity...

frontend/**/*.{ts,tsx}: Replace magic numbers with named constants for clarity.
Replace complex or nested ternary operators with if/else statements or IIFEs for readability.
Assign complex boolean conditions to named variables for clarity.
Use consistent return types for similar functions and hooks.
Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle).
Use unique, descriptive names for custom wrappers and functions to avoid ambiguity.
Define constants near related logic or ensure names link them clearly.

📄 Source: CodeRabbit Inference Engine (frontend/.cursorrules)

List of files the instruction was applied to:

  • frontend/src/apis/application/getApplication.ts
  • frontend/src/types/application.ts
  • frontend/src/App.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubDetailHeader/ClubDetailHeader.tsx
  • frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubDetailFooter/ClubDetailFooter.tsx
  • frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx
  • frontend/src/constants/INITIAL_FORM_DATA.ts
  • frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.styles.ts
  • frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.tsx
  • frontend/src/pages/AdminPage/application/answer/AnswerApplicationForm.tsx
  • frontend/src/apis/application/applyToClub.ts
  • frontend/src/hooks/useAnswers.ts
`frontend/**/*.tsx`: Abstract complex logic/interactions into dedicated componen...

frontend/**/*.tsx: Abstract complex logic/interactions into dedicated components or higher-order components (HOCs).
Separate significantly different conditional UI/logic into distinct components.
Colocate simple, localized logic or use inline definitions to reduce context switching.
Choose field-level or form-level cohesion based on form requirements.
Break down broad state management into smaller, focused hooks or contexts.
Use component composition instead of props drilling.

📄 Source: CodeRabbit Inference Engine (frontend/.cursorrules)

List of files the instruction was applied to:

  • frontend/src/App.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubDetailHeader/ClubDetailHeader.tsx
  • frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubDetailFooter/ClubDetailFooter.tsx
  • frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.tsx
  • frontend/src/pages/AdminPage/application/answer/AnswerApplicationForm.tsx
🧠 Learnings (11)
📓 Common learnings
Learnt from: lepitaaar
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/service/ClubApplyService.java:34-38
Timestamp: 2025-05-19T05:45:52.957Z
Learning: The code duplication between createClubApplication and editClubApplication methods in ClubApplyService.java is acknowledged but will be addressed in a future refactoring, as per the developer's plan.
Learnt from: seongwon030
PR: Moadong/moadong#195
File: frontend/src/pages/AdminPage/AdminPage.tsx:7-7
Timestamp: 2025-03-19T05:18:07.818Z
Learning: AdminPage.tsx에서 현재 하드코딩된 클럽 ID('67d2e3b9b15c136c6acbf20b')는 로그인 기능 구현 후 동적으로 가져오는 방식으로 수정될 예정입니다.
Learnt from: Zepelown
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/entity/ClubApplicationQuestion.java:32-33
Timestamp: 2025-05-15T12:03:57.356Z
Learning: 엔티티 클래스는 요청/응답 객체(DTO)에 의존해서는 안 됩니다. 계층 간 의존성 문제를 방지하기 위해 엔티티와 DTO는 분리되어야 합니다. 예를 들어, `ClubApplicationQuestion` 엔티티가 `ClubApplicationRequest.Options`와 같은 요청 객체를 직접 참조하는 대신, 엔티티 패키지 내에 `QuestionOptions`와 같은 별도의 클래스를 정의하고 사용해야 합니다. 이렇게 하면 요청 객체 변경이 데이터베이스 스키마나 엔티티 계층에 영향을 미치지 않습니다.
frontend/src/types/application.ts (4)
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Replace magic numbers with named constants for clarity.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.118Z
Learning: Applies to frontend/**/*.{ts,tsx} : Define constants near related logic or ensure names link them clearly.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Use consistent return types for similar functions and hooks.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.118Z
Learning: Applies to frontend/**/*.tsx : Choose field-level or form-level cohesion based on form requirements.
frontend/src/App.tsx (10)
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.tsx : Separate significantly different conditional UI/logic into distinct components.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.tsx : Abstract complex logic/interactions into dedicated components or higher-order components (HOCs).
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.tsx : Colocate simple, localized logic or use inline definitions to reduce context switching.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Replace magic numbers with named constants for clarity.
Learnt from: seongwon030
PR: Moadong/moadong#195
File: frontend/src/pages/AdminPage/AdminPage.tsx:7-7
Timestamp: 2025-03-19T05:18:07.818Z
Learning: AdminPage.tsx에서 현재 하드코딩된 클럽 ID('67d2e3b9b15c136c6acbf20b')는 로그인 기능 구현 후 동적으로 가져오는 방식으로 수정될 예정입니다.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.118Z
Learning: Applies to frontend/**/*.{ts,tsx} : Define constants near related logic or ensure names link them clearly.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle).
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.118Z
Learning: Applies to frontend/**/*.tsx : Choose field-level or form-level cohesion based on form requirements.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Use consistent return types for similar functions and hooks.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.118Z
Learning: Applies to frontend/**/*.tsx : Break down broad state management into smaller, focused hooks or contexts.
frontend/src/pages/ClubDetailPage/components/ClubDetailHeader/ClubDetailHeader.tsx (10)
Learnt from: seongwon030
PR: Moadong/moadong#195
File: frontend/src/pages/AdminPage/AdminPage.tsx:7-7
Timestamp: 2025-03-19T05:18:07.818Z
Learning: AdminPage.tsx에서 현재 하드코딩된 클럽 ID('67d2e3b9b15c136c6acbf20b')는 로그인 기능 구현 후 동적으로 가져오는 방식으로 수정될 예정입니다.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.tsx : Separate significantly different conditional UI/logic into distinct components.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.tsx : Colocate simple, localized logic or use inline definitions to reduce context switching.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.118Z
Learning: Applies to frontend/**/*.tsx : Use component composition instead of props drilling.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.118Z
Learning: Applies to frontend/**/*.tsx : Choose field-level or form-level cohesion based on form requirements.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Replace complex or nested ternary operators with if/else statements or IIFEs for readability.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.tsx : Abstract complex logic/interactions into dedicated components or higher-order components (HOCs).
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Replace magic numbers with named constants for clarity.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Assign complex boolean conditions to named variables for clarity.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Use consistent return types for similar functions and hooks.
frontend/src/pages/ClubDetailPage/components/ClubDetailFooter/ClubDetailFooter.tsx (10)
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.tsx : Separate significantly different conditional UI/logic into distinct components.
Learnt from: seongwon030
PR: Moadong/moadong#195
File: frontend/src/pages/AdminPage/AdminPage.tsx:7-7
Timestamp: 2025-03-19T05:18:07.818Z
Learning: AdminPage.tsx에서 현재 하드코딩된 클럽 ID('67d2e3b9b15c136c6acbf20b')는 로그인 기능 구현 후 동적으로 가져오는 방식으로 수정될 예정입니다.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.118Z
Learning: Applies to frontend/**/*.tsx : Use component composition instead of props drilling.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.118Z
Learning: Applies to frontend/**/*.tsx : Choose field-level or form-level cohesion based on form requirements.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.tsx : Colocate simple, localized logic or use inline definitions to reduce context switching.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Use consistent return types for similar functions and hooks.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.tsx : Abstract complex logic/interactions into dedicated components or higher-order components (HOCs).
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Replace complex or nested ternary operators with if/else statements or IIFEs for readability.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Replace magic numbers with named constants for clarity.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle).
frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx (1)
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.118Z
Learning: Applies to frontend/**/*.tsx : Choose field-level or form-level cohesion based on form requirements.
frontend/src/constants/INITIAL_FORM_DATA.ts (1)
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Replace magic numbers with named constants for clarity.
frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.tsx (10)
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.tsx : Separate significantly different conditional UI/logic into distinct components.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.118Z
Learning: Applies to frontend/**/*.tsx : Use component composition instead of props drilling.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.tsx : Abstract complex logic/interactions into dedicated components or higher-order components (HOCs).
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.tsx : Colocate simple, localized logic or use inline definitions to reduce context switching.
Learnt from: seongwon030
PR: Moadong/moadong#195
File: frontend/src/pages/AdminPage/AdminPage.tsx:7-7
Timestamp: 2025-03-19T05:18:07.818Z
Learning: AdminPage.tsx에서 현재 하드코딩된 클럽 ID('67d2e3b9b15c136c6acbf20b')는 로그인 기능 구현 후 동적으로 가져오는 방식으로 수정될 예정입니다.
Learnt from: lepitaaar
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/service/ClubApplyService.java:34-38
Timestamp: 2025-05-19T05:45:52.957Z
Learning: The code duplication between createClubApplication and editClubApplication methods in ClubApplyService.java is acknowledged but will be addressed in a future refactoring, as per the developer's plan.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Use consistent return types for similar functions and hooks.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Replace complex or nested ternary operators with if/else statements or IIFEs for readability.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Replace magic numbers with named constants for clarity.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Assign complex boolean conditions to named variables for clarity.
frontend/src/pages/AdminPage/application/answer/AnswerApplicationForm.tsx (6)
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Use consistent return types for similar functions and hooks.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.tsx : Abstract complex logic/interactions into dedicated components or higher-order components (HOCs).
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.118Z
Learning: Applies to frontend/**/*.tsx : Break down broad state management into smaller, focused hooks or contexts.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.118Z
Learning: Applies to frontend/**/*.tsx : Choose field-level or form-level cohesion based on form requirements.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.tsx : Separate significantly different conditional UI/logic into distinct components.
Learnt from: seongwon030
PR: Moadong/moadong#195
File: frontend/src/pages/AdminPage/AdminPage.tsx:7-7
Timestamp: 2025-03-19T05:18:07.818Z
Learning: AdminPage.tsx에서 현재 하드코딩된 클럽 ID('67d2e3b9b15c136c6acbf20b')는 로그인 기능 구현 후 동적으로 가져오는 방식으로 수정될 예정입니다.
frontend/src/apis/application/applyToClub.ts (2)
Learnt from: lepitaaar
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/service/ClubApplyService.java:34-38
Timestamp: 2025-05-19T05:45:52.957Z
Learning: The code duplication between createClubApplication and editClubApplication methods in ClubApplyService.java is acknowledged but will be addressed in a future refactoring, as per the developer's plan.
Learnt from: seongwon030
PR: Moadong/moadong#195
File: frontend/src/pages/AdminPage/AdminPage.tsx:7-7
Timestamp: 2025-03-19T05:18:07.818Z
Learning: AdminPage.tsx에서 현재 하드코딩된 클럽 ID('67d2e3b9b15c136c6acbf20b')는 로그인 기능 구현 후 동적으로 가져오는 방식으로 수정될 예정입니다.
frontend/src/hooks/useAnswers.ts (1)
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Use consistent return types for similar functions and hooks.
🔇 Additional comments (17)
frontend/src/types/application.ts (2)

17-17: LGTM!

readOnly 프로퍼티 추가가 첫 번째 질문을 고정하기 위한 요구사항을 잘 반영하고 있습니다.


56-56: LGTM!

answer에서 value로 변경하여 일관성을 개선했습니다.

frontend/src/pages/ClubDetailPage/components/ClubDetailHeader/ClubDetailHeader.tsx (1)

46-46: LGTM!

복잡한 조건부 스프레드 연산자를 단순한 불린 값으로 변경하여 코드 가독성을 개선했습니다.

frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.tsx (3)

19-19: LGTM!

readOnly 프로퍼티 추가가 잘 구현되었습니다.


121-121: LGTM!

스타일 컴포넌트에 readOnly 프로퍼티를 전달하여 시각적 피드백을 제공하는 것이 좋습니다.


137-139: LGTM!

readOnly 상태일 때 삭제 버튼을 숨기는 조건부 렌더링이 적절하게 구현되었습니다.

frontend/src/App.tsx (3)

18-19: 경로 활성화를 위한 import 추가가 적절합니다.

지원서 관련 컴포넌트의 import가 정확하게 추가되었습니다.


78-81: 관리자 지원서 생성 경로가 성공적으로 활성화되었습니다.

주석 해제로 인해 /admin/application-edit 경로가 활성화되었습니다.


90-93: 사용자 지원서 작성 경로가 성공적으로 활성화되었습니다.

주석 해제로 인해 /application/:clubId 경로가 활성화되었습니다.

frontend/src/pages/ClubDetailPage/components/ClubDetailFooter/ClubDetailFooter.tsx (1)

31-31: props 간소화가 적절합니다.

ClubApplyButton에 boolean 형태의 isRecruiting prop을 전달하는 것이 더 명확하고 단순합니다.

frontend/src/hooks/useAnswers.ts (2)

10-10: 속성명 변경이 일관되게 적용되었습니다.

answer에서 value로의 속성명 변경이 hook 전반에 걸쳐 일관되게 적용되었습니다.

Also applies to: 17-17, 30-30


32-32: answers 상태 반환 추가가 적절합니다.

hook에서 answers 상태를 반환하도록 추가한 것은 답변 제출 등의 기능을 위해 필요한 개선사항입니다.

frontend/src/apis/application/applyToClub.ts (1)

4-34: 전체적인 API 함수 구조 승인

API 함수가 올바르게 구현되었습니다. 에러 처리, 타입 안정성, 그리고 응답 처리가 적절히 구현되어 있습니다.

frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.tsx (2)

7-7: Props 단순화 개선

recruitmentFormpresidentPhoneNumber 대신 단일 isRecruiting boolean 프로퍼티를 사용하는 것은 컴포넌트 인터페이스를 단순화하고 명확성을 높입니다.


46-55: 클릭 핸들러 로직 개선

조건부 로직이 명확하고 이해하기 쉽게 구현되었습니다. 먼저 모집 상태를 확인하고 조기 반환하는 패턴이 효과적입니다.

frontend/src/pages/AdminPage/application/answer/AnswerApplicationForm.tsx (2)

22-22: 훅 사용 개선

useAnswers 훅에서 answers 상태를 추가로 가져오는 것은 좋은 개선사항입니다. 이를 통해 제출 시 현재 답변 상태에 접근할 수 있습니다.


45-53: 복잡한 제출 로직을 커스텀 훅으로 추출

코딩 가이드라인에 따라 복잡한 로직/상호작용을 전용 컴포넌트나 고차 컴포넌트(HOC)로 추상화해야 합니다. 제출 로직을 커스텀 훅으로 분리하는 것을 고려해보세요.

// hooks/useApplicationSubmission.ts
export const useApplicationSubmission = (clubId: string) => {
  const [isSubmitting, setIsSubmitting] = useState(false);
  
  const handleSubmit = async (answers: AnswerItem[]) => {
    setIsSubmitting(true);
    try {
      await applyToClub(clubId, answers);
      // 성공 처리
    } catch (error) {
      // 에러 처리
    } finally {
      setIsSubmitting(false);
    }
  };
  
  return { handleSubmit, isSubmitting };
};
⛔ Skipped due to learnings
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.tsx : Abstract complex logic/interactions into dedicated components or higher-order components (HOCs).
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.118Z
Learning: Applies to frontend/**/*.tsx : Break down broad state management into smaller, focused hooks or contexts.
Learnt from: seongwon030
PR: Moadong/moadong#195
File: frontend/src/pages/AdminPage/AdminPage.tsx:7-7
Timestamp: 2025-03-19T05:18:07.818Z
Learning: AdminPage.tsx에서 현재 하드코딩된 클럽 ID('67d2e3b9b15c136c6acbf20b')는 로그인 기능 구현 후 동적으로 가져오는 방식으로 수정될 예정입니다.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.tsx : Separate significantly different conditional UI/logic into distinct components.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.tsx : Colocate simple, localized logic or use inline definitions to reduce context switching.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.118Z
Learning: Applies to frontend/**/*.tsx : Choose field-level or form-level cohesion based on form requirements.
Learnt from: Zepelown
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/entity/ClubApplicationQuestion.java:32-33
Timestamp: 2025-05-15T12:03:57.356Z
Learning: 엔티티 클래스는 요청/응답 객체(DTO)에 의존해서는 안 됩니다. 계층 간 의존성 문제를 방지하기 위해 엔티티와 DTO는 분리되어야 합니다. 예를 들어, `ClubApplicationQuestion` 엔티티가 `ClubApplicationRequest.Options`와 같은 요청 객체를 직접 참조하는 대신, 엔티티 패키지 내에 `QuestionOptions`와 같은 별도의 클래스를 정의하고 사용해야 합니다. 이렇게 하면 요청 객체 변경이 데이터베이스 스키마나 엔티티 계층에 영향을 미치지 않습니다.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.118Z
Learning: Applies to frontend/**/*.tsx : Use component composition instead of props drilling.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-07T13:25:48.117Z
Learning: Applies to frontend/**/*.{ts,tsx} : Use consistent return types for similar functions and hooks.

Comment on lines +7 to +8
console.error(`Failed to fetch: ${response.statusText}`)
throw new Error((await response.json()).message);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

응답 본문을 한 번만 읽도록 개선하세요.

response.json()을 두 번 호출하면 "Body has already been read" 오류가 발생할 수 있습니다. 응답 본문을 한 번만 읽고 재사용하세요.

-      console.error(`Failed to fetch: ${response.statusText}`)
-      throw new Error((await response.json()).message);
+      const errorData = await response.json();
+      console.error(`Failed to fetch: ${response.statusText}`, errorData);
+      throw new Error(errorData.message || response.statusText);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
console.error(`Failed to fetch: ${response.statusText}`)
throw new Error((await response.json()).message);
if (!response.ok) {
const errorData = await response.json();
console.error(`Failed to fetch: ${response.statusText}`, errorData);
throw new Error(errorData.message || response.statusText);
}
🤖 Prompt for AI Agents
In frontend/src/apis/application/getApplication.ts around lines 7 to 8, the code
calls response.json() twice, which causes a "Body has already been read" error.
To fix this, read the response body once by awaiting response.json() into a
variable, then use that variable both for logging the error message and throwing
the new Error.

@lepitaaar lepitaaar changed the title Feature/user apply [feature] 동아리 지원하기 기능 Jul 11, 2025
Copy link
Member

@seongwon030 seongwon030 left a comment

Choose a reason for hiding this comment

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

readOnly 필드에 가시성은 문제없어보입니다. 기존 구글폼 부분도 잘 제거해주셨습니다.
남긴 코멘트 한 번 봐주시면 좋을 것 같아요 고생하셨숩니당 ~

Copy link
Member

@oesnuj oesnuj left a comment

Choose a reason for hiding this comment

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

은호님 프론트 첫 기여 축하드려요
기존 코드 읽는 데 시간이 좀 걸렸을 것 같은데 수고 많으셨어요 🙌
코멘트 몇 개 남겨뒀습니다 ㅎㅎ

options={question.options}
items={question.items}
type={question.type}
readOnly={index == 0} //인덱스 0번은 이름을 위한 고정 부분이므로 수정 불가
Copy link
Member

Choose a reason for hiding this comment

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

==도 되긴 하지만, JS에선 타입까지 일치시키는 ===를 보통 더 권장해서 이게 더 안전할 것 같아요 ㅎㅎ

Suggested change
readOnly={index == 0} //인덱스 0번은 이름을 위한 고정 부분이므로 수정 불가
readOnly={index === 0} //인덱스 0번은 이름을 위한 고정 부분이므로 수정 불가

Copy link
Member

Choose a reason for hiding this comment

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

요기 한 가지 생각해볼 점은 이름 질문 하나를 위해 props에 index 기반 하드코딩이 들어간 구조인데요..

만약 백엔드에서 질문 순서가 바뀌어 오거나, 프론트에서 질문 순서를 바꾸는 로직이 들어가게 되면 어떤 질문이 고정돼야 하는지를 코드만으로 판단하기 어려운 구조가 될 수도 있을 것 같아요.

혹시 이름 항목을 고정으로 받게 된 특별한 이유가 있을까요?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

지원자에 대한 이름은 무조건적으로 받아야했어서,
백과 프론트에서 얘기를 했을때 0번인덱스는 무조건 이름을 위한 질문으로 고정시키자 합의를 했습니다.
그에따라 백에서도 첫질문은 이름 부분으로 고정시킬 예정이구요.
혹시나 나중에 질문순서를 변경시키는 로직을 추가할시 고정적으로 받아야하는 질문을 나눠야할꺼 같긴하네요.

아님 지원자 이름을 받는 로직에있어서 더 좋은 의견있으실까요??

lepitaaar and others added 2 commits July 13, 2025 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📬 API 서버 API 통신 작업 💻 FE Frontend

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments