Skip to content

Conversation

@seongwon030
Copy link
Member

@seongwon030 seongwon030 commented Dec 30, 2025

#️⃣연관된 이슈

ex) #이슈번호, #이슈번호

📝작업 내용

이번 PR에서 작업한 내용을 간략히 설명해주세요(이미지/동영상 첨부 가능)

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

리뷰어가 특별히 봐주었으면 하는 부분이 있다면 작성해주세요

ex) 메서드 XXX의 이름을 더 잘 짓고 싶은데 혹시 좋은 명칭이 있을까요?

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

논의하고 싶은 부분이 있다면 작성해주세요.

🫡 참고사항

Summary by CodeRabbit

  • New Features

    • 페이지 이동 시 자동 맨 위 스크롤 동작 추가
    • 모집 예정(UPCOMING) 상태 표시 및 처리 추가
    • SNS 링크 클릭 이벤트(분석) 수집 및 공유 아이콘 모바일 대응 추가
  • UI/Style Improvements

    • 버튼·입력·모바일 스타일 조정(크기·라운드·색상·반응성 개선)
    • 디자인 시스템 색상 통일 및 레이아웃 패딩/정렬 개선
  • Bug Fixes

    • 모집 마감/기간 표기 로직 개선(상태 기반 데드라인 텍스트)

✏️ Tip: You can customize this high-level summary in your review settings.

suhyun113 and others added 30 commits December 28, 2025 16:02
[fix] 동아리 상세페이지 모집 버튼 푸터 삭제 복구
[feat] 모집예정 상태를 추가한다
suhyun113 and others added 9 commits December 30, 2025 17:36
@seongwon030 seongwon030 self-assigned this Dec 30, 2025
@seongwon030 seongwon030 added 💻 FE Frontend 📈 release 릴리즈 배포 labels Dec 30, 2025
@vercel
Copy link

vercel bot commented Dec 30, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
moadong Ready Ready Preview, Comment Dec 30, 2025 4:27pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 30, 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.
  • You can also validate your configuration using the online YAML validator.
  • 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

라우팅용 ScrollToTop 컴포넌트 추가 및 App에 적용, 훅명 useScroll → useScrollDetection 정규화, 모집 상태 타입(RecruitmentStatus) 추가 및 getDeadlineText 시그니처/로직 변경, UI 스타일·반응형·분기(UPCOMING/ALWAYS) 연동과 Mixpanel 추적 통합이 포함된 변경입니다.

Changes

Cohort / File(s) 변경 요약
앱 라우트 스크롤
frontend/src/App.tsx, frontend/src/hooks/ScrollToTop.tsx, frontend/src/hooks/useScrollDetection.ts, frontend/src/components/common/Header/Header.tsx
ScrollToTop 컴포넌트 추가 및 App에 렌더링. useScroll 훅을 useScrollDetection으로 리네이밍 및 Header에서 교체.
모집 상태 타입·유틸
frontend/src/types/club.ts, frontend/src/utils/getDeadLineText.ts, frontend/src/utils/getDeadLineText.test.ts
RecruitmentStatus 타입 추가('OPEN'
상태 표시 연동
frontend/src/components/ClubStateBox/ClubStateBox.tsx, frontend/src/styles/clubTags.ts
UPCOMING('모집예정')에 대한 STATE_TEXT 및 STATUS_COLORS 매핑 추가.
공통 컴포넌트 스타일 수정
frontend/src/components/common/Button/Button.tsx, frontend/src/components/common/InputField/InputField.styles.ts, frontend/src/styles/Global.styles.ts
Button 크기/타이포 변경(높이·폰트), Input 필드 border-radius 및 플레이스홀더 색상/폰트 적용, 폼 요소 전반에 font-family 적용.
ClubDetail 하단·신청 버튼
frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx, frontend/src/pages/ClubDetailPage/components/ClubDetailFooter/*, frontend/src/pages/ClubDetailPage/components/ClubApplyButton/*
ClubDetailFooter에 recruitmentStatus prop 추가 및 전달. ClubApplyButton에 recruitmentStatus 기반 비활성화 처리(UPCOMING/CLOSED), 핸들러/상태명 리네이밍 및 스타일/반응형 개선.
프로필 카드·공유 버튼
frontend/src/pages/ClubDetailPage/components/ClubProfileCard/ClubProfileCard.tsx, frontend/src/pages/ClubDetailPage/components/ShareButton/*
ClubProfileCard에 Mixpanel SNS 클릭 트래킹 추가. ShareButton에 디바이스 감지로 모바일 전용 아이콘 적용 및 아이콘 크기 조정.
Admin 모집 편집(캘린더 포함)
frontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.tsx, frontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.styles.ts, frontend/src/pages/AdminPage/tabs/RecruitEditTab/components/Calendar/Calendar.styles.ts
상시 모집 판별을 문자열 비교에서 isFarFuture(end) 날짜 기반으로 변경. 스타일을 테마 컬러·media로 통합 및 border-radius/크기 조정.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • oesnuj
  • suhyun113

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive PR 제목이 너무 일반적이고 모호합니다. '[release] FE 릴리즈'는 실제 변경 사항을 구체적으로 설명하지 않으며, 본질적으로 무엇이 변경되었는지 알 수 없습니다. 제목을 더 구체적으로 변경하세요. 예: '[release] FE: 모집 상태 관리 개선 및 UI 스타일 리팩토링' 또는 주요 변경 사항을 명시하는 형태로 수정 권장합니다.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ 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

Comment @coderabbitai help to get the list of available commands and usage tips.

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: 2

🧹 Nitpick comments (4)
frontend/src/pages/ClubDetailPage/components/ClubProfileCard/ClubProfileCard.tsx (1)

13-20: recruitmentStatus prop의 타입을 RecruitmentStatus로 변경하세요.

RecruitmentStatus 타입이 club.ts에 정의되어 있으므로, Props 인터페이스에서도 동일한 타입을 사용하면 타입 안전성을 확보할 수 있습니다. 코딩 가이드라인에 따라 유사한 데이터에 대해 일관된 타입을 사용해야 합니다.

🔎 제안된 수정
+import { RecruitmentStatus, SNSPlatform } from '@/types/club';
-import { SNSPlatform } from '@/types/club';
 
 interface Props {
   name: string;
   logo?: string;
   cover?: string;
-  recruitmentStatus: string;
+  recruitmentStatus: RecruitmentStatus;
   socialLinks: Record<SNSPlatform, string>;
   introDescription: string;
 }
frontend/src/pages/ClubDetailPage/components/ClubDetailFooter/ClubDetailFooter.styles.ts (1)

8-9: 매직 넘버를 명명된 상수로 추출하는 것을 고려하세요.

패딩 값들(10px, 24px, 16px)이 하드코딩되어 있습니다. 이러한 값들을 디자인 토큰이나 명명된 상수로 추출하면 유지보수성과 일관성이 향상됩니다.

🔎 제안하는 리팩터링
+const FOOTER_SPACING = {
+  VERTICAL: '10px',
+  BOTTOM_DESKTOP: '24px',
+  BOTTOM_MOBILE: '16px',
+} as const;
+
 export const ClubDetailFooterContainer = styled.div`
   position: sticky;
   bottom: 0;
   width: 100%;
   z-index: 1040; // TODO: Portal로 모달 분리 후 header보다 낮게 재조정
-  padding: 10px 0px 24px 0px;
+  padding: ${FOOTER_SPACING.VERTICAL} 0px ${FOOTER_SPACING.BOTTOM_DESKTOP} 0px;

   display: flex;
   align-items: center;
   justify-content: space-between;
   gap: 16px;

   background-color: white;
   border-top: 1px solid #cdcdcd;

   ${media.mobile} {
-    padding: 10px 0px 16px 0px;
+    padding: ${FOOTER_SPACING.VERTICAL} 0px ${FOOTER_SPACING.BOTTOM_MOBILE} 0px;
   }
 `;

Based on learnings, 매직 넘버는 명명된 상수로 교체하여 명확성을 높여야 합니다.

Also applies to: 19-21

frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.styles.ts (1)

14-45: 매직 넘버를 명명된 상수로 추출하는 것을 고려하세요.

버튼 크기 관련 값들(60px, 273px, 44px, 16px 등)이 하드코딩되어 있습니다. 이러한 값들을 명명된 상수로 추출하면 의미가 명확해지고 유지보수가 용이해집니다.

🔎 제안하는 리팩터링
+const BUTTON_SIZES = {
+  DESKTOP: {
+    WIDTH: '517px',
+    HEIGHT: '60px',
+    FONT_SIZE: '20px',
+    FONT_WEIGHT: 700,
+  },
+  MOBILE: {
+    WIDTH: '273px',
+    HEIGHT: '44px',
+    FONT_SIZE: '16px',
+    FONT_WEIGHT: 500,
+  },
+} as const;
+
 export const ApplyButton = styled.button`
   display: flex;
   align-items: center;
   justify-content: center;
   border: none;
   border-radius: 10px;
   cursor: ${({disabled}) => (disabled ? 'default' : 'pointer')};
   transition: transform 0.2s ease-in-out;
   background-color: ${({ disabled }) => disabled ? colors.gray[500] : colors.primary[800]};

   padding: 10px 40px;
-  width: 517px;
-  height: 60px;
-  font-size: 20px;
+  width: ${BUTTON_SIZES.DESKTOP.WIDTH};
+  height: ${BUTTON_SIZES.DESKTOP.HEIGHT};
+  font-size: ${BUTTON_SIZES.DESKTOP.FONT_SIZE};
   font-style: normal;
-  font-weight: 700;
+  font-weight: ${BUTTON_SIZES.DESKTOP.FONT_WEIGHT};
   color: ${colors.gray[200]};
   text-align: center;

   img {
     font-size: 12px;
     font-weight: 600;
   }

   ${media.mobile} {
-    width: 273px;
-    height: 44px;
-    font-size: 16px;
-    font-weight: 500;
+    width: ${BUTTON_SIZES.MOBILE.WIDTH};
+    height: ${BUTTON_SIZES.MOBILE.HEIGHT};
+    font-size: ${BUTTON_SIZES.MOBILE.FONT_SIZE};
+    font-weight: ${BUTTON_SIZES.MOBILE.FONT_WEIGHT};
     background-color: ${({ disabled }) => disabled ? colors.gray[500] : colors.gray[900]};
   }
 `;

Based on learnings, 매직 넘버는 명명된 상수로 교체하여 명확성을 높여야 합니다.

frontend/src/utils/getDeadLineText.ts (1)

13-13: recruitmentStatus 파라미터에 타입 안전성을 강화하세요.

recruitmentStatusstring으로 타입이 지정되어 있지만, RecruitmentStatus 타입이 이미 정의되어 있습니다. 타입 안전성을 위해 구체적인 타입을 사용하는 것이 좋습니다.

🔎 제안하는 수정

파일 상단에 타입을 import하세요:

 import { format, differenceInCalendarDays } from 'date-fns';
 import { ko } from 'date-fns/locale';
+import { RecruitmentStatus } from '@/types/club';

그런 다음 파라미터 타입을 업데이트하세요:

 const getDeadlineText = (
   recruitmentStart: Date | null,
   recruitmentEnd: Date | null,
-  recruitmentStatus: string,
+  recruitmentStatus: RecruitmentStatus,
   today: Date = new Date(),
 ): string => {
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between fa4d869 and a87e2a6.

⛔ Files ignored due to path filters (2)
  • frontend/src/assets/images/icons/share_icon.svg is excluded by !**/*.svg
  • frontend/src/assets/images/icons/share_icon_mobile.svg is excluded by !**/*.svg
📒 Files selected for processing (23)
  • frontend/src/App.tsx
  • frontend/src/components/ClubStateBox/ClubStateBox.tsx
  • frontend/src/components/common/Button/Button.tsx
  • frontend/src/components/common/Header/Header.tsx
  • frontend/src/components/common/InputField/InputField.styles.ts
  • frontend/src/hooks/ScrollToTop.tsx
  • frontend/src/hooks/useScrollDetection.ts
  • frontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.styles.ts
  • frontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.tsx
  • frontend/src/pages/AdminPage/tabs/RecruitEditTab/components/Calendar/Calendar.styles.ts
  • frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.styles.ts
  • frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubDetailFooter/ClubDetailFooter.styles.ts
  • frontend/src/pages/ClubDetailPage/components/ClubDetailFooter/ClubDetailFooter.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubProfileCard/ClubProfileCard.tsx
  • frontend/src/pages/ClubDetailPage/components/ShareButton/ShareButton.styles.ts
  • frontend/src/pages/ClubDetailPage/components/ShareButton/ShareButton.tsx
  • frontend/src/styles/Global.styles.ts
  • frontend/src/styles/clubTags.ts
  • frontend/src/types/club.ts
  • frontend/src/utils/getDeadLineText.test.ts
  • frontend/src/utils/getDeadLineText.ts
🧰 Additional context used
📓 Path-based instructions (3)
frontend/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (frontend/.cursorrules)

frontend/**/*.{ts,tsx,js,jsx}: Replace magic numbers with named constants for clarity
Replace complex/nested ternaries with if/else or IIFEs for readability
Assign complex boolean conditions to named variables for explicit meaning
Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle)
Use unique and descriptive names for custom wrappers/functions to avoid ambiguity
Define constants near related logic or ensure names link them clearly to avoid silent failures
Break down broad state management into smaller, focused hooks/contexts to reduce coupling

Files:

  • frontend/src/types/club.ts
  • frontend/src/pages/ClubDetailPage/components/ShareButton/ShareButton.tsx
  • frontend/src/hooks/ScrollToTop.tsx
  • frontend/src/components/ClubStateBox/ClubStateBox.tsx
  • frontend/src/App.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubProfileCard/ClubProfileCard.tsx
  • frontend/src/styles/Global.styles.ts
  • frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx
  • frontend/src/hooks/useScrollDetection.ts
  • frontend/src/pages/AdminPage/tabs/RecruitEditTab/components/Calendar/Calendar.styles.ts
  • frontend/src/utils/getDeadLineText.test.ts
  • frontend/src/utils/getDeadLineText.ts
  • frontend/src/pages/ClubDetailPage/components/ClubDetailFooter/ClubDetailFooter.tsx
  • frontend/src/styles/clubTags.ts
  • frontend/src/pages/ClubDetailPage/components/ShareButton/ShareButton.styles.ts
  • frontend/src/components/common/Header/Header.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.tsx
  • frontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.tsx
  • frontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.styles.ts
  • frontend/src/components/common/Button/Button.tsx
  • frontend/src/components/common/InputField/InputField.styles.ts
  • frontend/src/pages/ClubDetailPage/components/ClubDetailFooter/ClubDetailFooter.styles.ts
  • frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.styles.ts
frontend/**/*.{ts,tsx}

📄 CodeRabbit inference engine (frontend/.cursorrules)

Use consistent return types for similar functions/hooks

Files:

  • frontend/src/types/club.ts
  • frontend/src/pages/ClubDetailPage/components/ShareButton/ShareButton.tsx
  • frontend/src/hooks/ScrollToTop.tsx
  • frontend/src/components/ClubStateBox/ClubStateBox.tsx
  • frontend/src/App.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubProfileCard/ClubProfileCard.tsx
  • frontend/src/styles/Global.styles.ts
  • frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx
  • frontend/src/hooks/useScrollDetection.ts
  • frontend/src/pages/AdminPage/tabs/RecruitEditTab/components/Calendar/Calendar.styles.ts
  • frontend/src/utils/getDeadLineText.test.ts
  • frontend/src/utils/getDeadLineText.ts
  • frontend/src/pages/ClubDetailPage/components/ClubDetailFooter/ClubDetailFooter.tsx
  • frontend/src/styles/clubTags.ts
  • frontend/src/pages/ClubDetailPage/components/ShareButton/ShareButton.styles.ts
  • frontend/src/components/common/Header/Header.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.tsx
  • frontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.tsx
  • frontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.styles.ts
  • frontend/src/components/common/Button/Button.tsx
  • frontend/src/components/common/InputField/InputField.styles.ts
  • frontend/src/pages/ClubDetailPage/components/ClubDetailFooter/ClubDetailFooter.styles.ts
  • frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.styles.ts
frontend/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (frontend/.cursorrules)

frontend/**/*.{tsx,jsx}: Abstract complex logic/interactions into dedicated 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 when using form libraries like react-hook-form
Use Component Composition instead of Props Drilling to reduce coupling

Files:

  • frontend/src/pages/ClubDetailPage/components/ShareButton/ShareButton.tsx
  • frontend/src/hooks/ScrollToTop.tsx
  • frontend/src/components/ClubStateBox/ClubStateBox.tsx
  • frontend/src/App.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubProfileCard/ClubProfileCard.tsx
  • frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubDetailFooter/ClubDetailFooter.tsx
  • frontend/src/components/common/Header/Header.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.tsx
  • frontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.tsx
  • frontend/src/components/common/Button/Button.tsx
🧠 Learnings (11)
📚 Learning: 2025-09-21T02:23:27.796Z
Learnt from: seongwon030
Repo: Moadong/moadong PR: 744
File: frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.tsx:47-48
Timestamp: 2025-09-21T02:23:27.796Z
Learning: ClubApplyButton 컴포넌트에서 ShareButton은 항상 렌더링되어야 하므로 정적 import를 사용하는 것이 적절함. 동적 import는 불필요함.

Applied to files:

  • frontend/src/pages/ClubDetailPage/components/ShareButton/ShareButton.tsx
  • frontend/src/pages/ClubDetailPage/components/ShareButton/ShareButton.styles.ts
📚 Learning: 2025-03-19T05:18:07.818Z
Learnt from: seongwon030
Repo: Moadong/moadong PR: 195
File: frontend/src/pages/AdminPage/AdminPage.tsx:7-7
Timestamp: 2025-03-19T05:18:07.818Z
Learning: AdminPage.tsx에서 현재 하드코딩된 클럽 ID('67d2e3b9b15c136c6acbf20b')는 로그인 기능 구현 후 동적으로 가져오는 방식으로 수정될 예정입니다.

Applied to files:

  • frontend/src/pages/ClubDetailPage/components/ShareButton/ShareButton.tsx
  • frontend/src/components/ClubStateBox/ClubStateBox.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubProfileCard/ClubProfileCard.tsx
  • frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.tsx
  • frontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.tsx
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{ts,tsx,js,jsx} : Break down broad state management into smaller, focused hooks/contexts to reduce coupling

Applied to files:

  • frontend/src/hooks/ScrollToTop.tsx
  • frontend/src/App.tsx
  • frontend/src/components/common/Header/Header.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.tsx
📚 Learning: 2025-07-19T05:05:10.196Z
Learnt from: seongwon030
Repo: Moadong/moadong PR: 548
File: frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx:17-57
Timestamp: 2025-07-19T05:05:10.196Z
Learning: ClubDetailPage.tsx에서 notJoinedClubNames 배열의 하드코딩은 의도적인 설계 결정입니다. 개발자가 명시적으로 하드코딩을 선택했으므로 이에 대한 리팩토링 제안을 하지 않아야 합니다.

Applied to files:

  • frontend/src/components/ClubStateBox/ClubStateBox.tsx
  • frontend/src/styles/clubTags.ts
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{tsx,jsx} : Abstract complex logic/interactions into dedicated components/HOCs

Applied to files:

  • frontend/src/App.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.tsx
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{tsx,jsx} : Colocate simple, localized logic or use inline definitions to reduce context switching

Applied to files:

  • frontend/src/App.tsx
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{tsx,jsx} : Use Component Composition instead of Props Drilling to reduce coupling

Applied to files:

  • frontend/src/App.tsx
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{ts,tsx,js,jsx} : Replace magic numbers with named constants for clarity

Applied to files:

  • frontend/src/styles/Global.styles.ts
  • frontend/src/pages/AdminPage/tabs/RecruitEditTab/components/Calendar/Calendar.styles.ts
  • frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.tsx
  • frontend/src/components/common/InputField/InputField.styles.ts
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{ts,tsx,js,jsx} : Define constants near related logic or ensure names link them clearly to avoid silent failures

Applied to files:

  • frontend/src/styles/Global.styles.ts
  • frontend/src/utils/getDeadLineText.ts
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{tsx,jsx} : Separate significantly different conditional UI/logic into distinct components

Applied to files:

  • frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.tsx
📚 Learning: 2025-09-30T05:26:41.788Z
Learnt from: alsdddk
Repo: Moadong/moadong PR: 765
File: backend/src/main/java/moadong/club/service/ClubApplyService.java:431-435
Timestamp: 2025-09-30T05:26:41.788Z
Learning: In the Moadong codebase's club application feature (backend/src/main/java/moadong/club/), multiple ClubApplicationForm entities can have ACTIVE status for the same clubId, semesterYear, and semesterTerm simultaneously. There is no uniqueness constraint requiring only one ACTIVE form per semester.

Applied to files:

  • frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.tsx
🧬 Code graph analysis (11)
frontend/src/App.tsx (1)
frontend/src/hooks/ScrollToTop.tsx (1)
  • ScrollToTop (4-12)
frontend/src/pages/AdminPage/tabs/RecruitEditTab/components/Calendar/Calendar.styles.ts (1)
frontend/src/styles/theme/colors.ts (1)
  • colors (1-81)
frontend/src/pages/ClubDetailPage/components/ClubDetailFooter/ClubDetailFooter.tsx (2)
frontend/src/types/club.ts (1)
  • RecruitmentStatus (3-7)
frontend/src/utils/recruitmentDateParser.ts (1)
  • recruitmentDateParser (3-18)
frontend/src/styles/clubTags.ts (1)
frontend/src/styles/theme/colors.ts (1)
  • colors (1-81)
frontend/src/pages/ClubDetailPage/components/ShareButton/ShareButton.styles.ts (1)
frontend/src/styles/mediaQuery.ts (1)
  • media (8-14)
frontend/src/components/common/Header/Header.tsx (1)
frontend/src/hooks/useScrollDetection.ts (1)
  • useScrollDetection (3-16)
frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.tsx (2)
frontend/src/types/application.ts (1)
  • ApplicationForm (65-68)
frontend/src/constants/eventName.ts (1)
  • USER_EVENT (1-38)
frontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.styles.ts (1)
frontend/src/styles/theme/colors.ts (1)
  • colors (1-81)
frontend/src/components/common/InputField/InputField.styles.ts (1)
frontend/src/styles/theme/colors.ts (1)
  • colors (1-81)
frontend/src/pages/ClubDetailPage/components/ClubDetailFooter/ClubDetailFooter.styles.ts (1)
frontend/src/styles/mediaQuery.ts (1)
  • media (8-14)
frontend/src/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton.styles.ts (2)
frontend/src/styles/theme/colors.ts (1)
  • colors (1-81)
frontend/src/styles/mediaQuery.ts (1)
  • media (8-14)
🔇 Additional comments (21)
frontend/src/components/common/InputField/InputField.styles.ts (1)

1-1: 테마 기반 스타일링 적용 및 모바일 UX 개선 확인

테마 색상 사용으로 일관성이 향상되었고, placeholder의 font-size: 16px는 iOS Safari에서 포커스 시 자동 확대를 방지하는 좋은 선택입니다.

Also applies to: 39-39, 70-71

frontend/src/styles/Global.styles.ts (1)

9-11: 폼 요소 전반에 일관된 폰트 적용 확인

button, input, select까지 확장하여 모든 폼 컨트롤에 일관된 폰트가 적용되도록 개선되었습니다.

frontend/src/hooks/ScrollToTop.tsx (1)

1-12: 브라우저 뒤로/앞으로 이동 시 스크롤 복원 동작을 확인하세요

모든 경로 변경 시 최상단으로 스크롤하는 구현은 정상적으로 작동하지만, 브라우저의 뒤로/앞으로 버튼 사용 시에도 스크롤 위치가 복원되지 않고 최상단으로 이동합니다.

일반적으로 사용자는 브라우저 네비게이션 시 이전 스크롤 위치가 복원되기를 기대합니다. 이것이 의도된 동작인지 확인하고, 필요하다면 useNavigationType을 활용하여 POP 액션(뒤로/앞으로)일 때는 스크롤하지 않도록 개선할 수 있습니다.

브라우저 네비게이션 시 스크롤 복원을 위한 제안
 import { useEffect } from 'react';
-import { useLocation } from 'react-router-dom';
+import { useLocation, useNavigationType } from 'react-router-dom';

 export const ScrollToTop = () => {
   const { pathname } = useLocation();
+  const navigationType = useNavigationType();

   useEffect(() => {
-    window.scrollTo(0, 0);
+    // POP (뒤로/앞으로 버튼)이 아닐 때만 스크롤
+    if (navigationType !== 'POP') {
+      window.scrollTo(0, 0);
+    }
   }, [pathname]);

   return null;
 };
frontend/src/App.tsx (1)

7-7: ScrollToTop 컴포넌트 통합 확인

BrowserRouter 내부에 적절히 배치되었으며, GlobalStyles 이후에 렌더링하여 전역 라우트 변경 감지가 올바르게 동작합니다.

Also applies to: 29-29

frontend/src/components/ClubStateBox/ClubStateBox.tsx (1)

8-8: 모집예정 상태 지원 추가 확인

새로운 UPCOMING 상태를 지원하여 모집 상태 시스템이 확장되었습니다. STATUS_COLORS의 '모집예정' 매핑과 일관되게 작동합니다.

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

2-2: 디바이스별 아이콘 분기 처리 확인

useDevice 훅을 활용하여 모바일과 데스크톱에 맞는 공유 아이콘을 선택적으로 렌더링하도록 개선되었습니다. 간결하고 명확한 구현입니다.

Also applies to: 6-6, 18-18, 60-63

frontend/src/components/common/Button/Button.tsx (1)

21-21: 버튼 크기 및 폰트 사이즈 조정 확인

높이와 폰트 크기가 조정되어 다른 컴포넌트들과 시각적 일관성이 개선되었습니다. font-size: 16px는 모바일 포커스 시 자동 확대를 방지합니다.

Also applies to: 25-25

frontend/src/pages/ClubDetailPage/components/ShareButton/ShareButton.styles.ts (1)

1-1: 반응형 아이콘 크기 조정 확인

데스크톱에서 60x60, 모바일에서 44x44로 아이콘 크기가 디바이스별로 최적화되었습니다. media 헬퍼를 사용하여 프로젝트의 반응형 스타일 패턴과 일관성을 유지하고 있습니다.

Also applies to: 11-17

frontend/src/components/common/Header/Header.tsx (1)

9-9: LGTM! 훅 이름 변경이 적절합니다.

useScrolluseScrollDetection 리네이밍은 훅의 역할(스크롤 감지)을 더 명확하게 표현합니다. 관련 훅 파일의 변경과 일관성 있게 적용되었습니다.

Also applies to: 18-18

frontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.styles.ts (1)

1-1: LGTM! 테마 색상 적용이 잘 되었습니다.

하드코딩된 색상값을 colors 테마 토큰으로 교체하여 유지보수성과 일관성이 향상되었습니다. colors.primary[800], colors.gray[700] 등 다른 컴포넌트들과 동일한 테마 시스템을 사용하고 있습니다.

Also applies to: 26-28

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

83-87: LGTM! recruitmentStatus prop 추가가 적절합니다.

ClubDetailFooterrecruitmentStatus prop을 전달하여 상태 기반 마감 텍스트 렌더링이 가능해졌습니다. 이는 PR의 모집 상태 시스템 개선 목표와 일치합니다.

frontend/src/styles/clubTags.ts (1)

17-22: 모집중과 모집예정이 동일한 색상을 사용합니다.

모집중모집예정 모두 colors.accent[1][900] (#3DBBFF)을 사용하고 있습니다. 이는 의도된 디자인일 수 있지만, 두 상태를 시각적으로 구분하지 못할 수 있습니다.

디자인 의도가 맞는지 확인해 주세요. 만약 구분이 필요하다면 모집예정에 다른 색상(예: colors.accent[1][800])을 고려해 볼 수 있습니다.

frontend/src/types/club.ts (2)

3-7: LGTM! 타입 안전성이 개선되었습니다.

RecruitmentStatus 유니온 타입 도입으로 모집 상태 처리의 타입 안전성이 향상되었습니다. 'OPEN' | 'CLOSED' | 'UPCOMING' | 'ALWAYS' 리터럴 타입은 컴파일 타임에 유효하지 않은 상태값을 방지합니다.

Also applies to: 15-15


78-83: 참고: ClubApiResponse의 recruitmentStatus는 string으로 유지됩니다.

ClubApiResponse.recruitmentStatusstring으로 남아있고 Club.recruitmentStatusRecruitmentStatus로 변경되었습니다. API 응답을 도메인 모델로 변환하는 과정에서 적절한 타입 매핑이 이루어지는지 확인해 주세요.

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

8-9: LGTM! Mixpanel 추적 통합이 잘 되었습니다.

SNS 링크 클릭 이벤트 추적이 기존 패턴을 따르고 있으며, platformclubName 컨텍스트를 포함하여 분석에 유용한 정보를 제공합니다.

Also applies to: 30-30, 96-101

frontend/src/hooks/useScrollDetection.ts (1)

3-16: LGTM! 훅 리네이밍과 구현이 적절합니다.

useScrollDetection이라는 이름이 훅의 역할을 더 명확하게 표현합니다. 이벤트 리스너 정리(cleanup)가 올바르게 구현되어 있습니다.

frontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.tsx (1)

17-17: LGTM! 날짜 기반 상시모집 판단 로직이 적절합니다.

FAR_FUTURE_YEAR 상수와 isFarFuture 헬퍼 함수를 사용한 상시모집 판단은 코딩 가이드라인(매직 넘버 상수화)을 따르며, handleUpdateClub의 저장 로직과 일관성이 있습니다.

Also applies to: 39-40, 52-52

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

5-22: LGTM!

recruitmentStatus prop이 깔끔하게 추가되었으며, 타입 안전성이 유지되고 있습니다. getDeadlineText 호출이 날짜 기반 계산에서 상태 기반 로직으로 올바르게 업데이트되었습니다.

frontend/src/utils/getDeadLineText.test.ts (1)

3-82: LGTM!

테스트 케이스들이 새로운 recruitmentStatus 파라미터 기반 로직을 포괄적으로 검증하고 있습니다. OPEN, CLOSED, UPCOMING, ALWAYS 상태에 대한 모든 시나리오가 잘 커버되어 있습니다.

frontend/src/pages/AdminPage/tabs/RecruitEditTab/components/Calendar/Calendar.styles.ts (1)

3-222: LGTM!

하드코딩된 컬러 값들을 테마 기반 토큰으로 성공적으로 마이그레이션했습니다. 이는 디자인 시스템의 일관성을 높이고 유지보수성을 향상시킵니다.

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

23-24: LGTM!

코드 리팩터링이 잘 되어 있습니다:

  1. 상태 및 함수 이름이 더 명확하고 설명적으로 변경되었습니다.
  2. 모집 상태 관련 불리언 변수들(Lines 82-85)이 명확하게 명명되어 조건 로직의 의도가 분명합니다.
  3. renderButtonContent 함수가 복잡한 삼항 연산자 대신 if/else를 사용하여 가독성이 향상되었습니다.
  4. Disabled 상태가 적절하게 처리되고 있습니다.

As per coding guidelines, 복잡한 불리언 조건을 명명된 변수에 할당하고 if/else 구조를 사용하여 가독성을 높였습니다.

Also applies to: 28-52, 54-80, 82-103, 105-120

const days = differenceInCalendarDays(recruitmentEnd, today);

if (days > 365) return '상시 모집';
if (days > 365) return RECRUITMENT_STATUS.ALWAYS; // D-day가 의미 없을 정도로 긴 경우 '상시 모집'으로 표시
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 | 🟠 Major

매직 넘버 365를 명명된 상수로 추출하세요.

365일 임계값이 하드코딩되어 있습니다. 이 값을 명명된 상수로 추출하면 의도가 명확해지고 향후 조정이 용이해집니다.

🔎 제안하는 리팩터링
+const ALWAYS_RECRUITING_THRESHOLD_DAYS = 365;
+
 const RECRUITMENT_STATUS = {
   CLOSED: '모집 마감',
   ALWAYS: '상시 모집',
   UPCOMING: '모집 시작',
 };

 const getDeadlineText = (
   recruitmentStart: Date | null,
   recruitmentEnd: Date | null,
   recruitmentStatus: string,
   today: Date = new Date(),
 ): string => {
   console.log(recruitmentStart, recruitmentEnd, recruitmentStatus, today);

   if (recruitmentStatus === 'CLOSED') {
     return RECRUITMENT_STATUS.CLOSED;
   }

   if (recruitmentStatus === 'UPCOMING') {
     if (!recruitmentStart) return RECRUITMENT_STATUS.CLOSED;
     const hour = recruitmentStart.getHours();
     const minute = recruitmentStart.getMinutes();

     let formatStr = 
     hour === 0 && minute === 0 
     ? 'M월 d일'
     : 'M월 d일 HH:mm';
     return `${format(recruitmentStart, formatStr, { locale: ko })} ${RECRUITMENT_STATUS.UPCOMING}`;
   }

   if (!recruitmentEnd) return RECRUITMENT_STATUS.CLOSED;
   const days = differenceInCalendarDays(recruitmentEnd, today);

-  if (days > 365) return RECRUITMENT_STATUS.ALWAYS; // D-day가 의미 없을 정도로 긴 경우 '상시 모집'으로 표시
+  if (days > ALWAYS_RECRUITING_THRESHOLD_DAYS) return RECRUITMENT_STATUS.ALWAYS; // D-day가 의미 없을 정도로 긴 경우 '상시 모집'으로 표시
   return days > 0 ? `D-${days}` : 'D-Day';
 };

Based on learnings, 매직 넘버는 명명된 상수로 교체하여 명확성을 높이고, 로직 근처에 상수를 정의하여 연결이 명확하도록 해야 합니다.

📝 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
if (days > 365) return RECRUITMENT_STATUS.ALWAYS; // D-day가 의미 없을 정도로 긴 경우 '상시 모집'으로 표시
const ALWAYS_RECRUITING_THRESHOLD_DAYS = 365;
const RECRUITMENT_STATUS = {
CLOSED: '모집 마감',
ALWAYS: '상시 모집',
UPCOMING: '모집 시작',
};
const getDeadlineText = (
recruitmentStart: Date | null,
recruitmentEnd: Date | null,
recruitmentStatus: string,
today: Date = new Date(),
): string => {
console.log(recruitmentStart, recruitmentEnd, recruitmentStatus, today);
if (recruitmentStatus === 'CLOSED') {
return RECRUITMENT_STATUS.CLOSED;
}
if (recruitmentStatus === 'UPCOMING') {
if (!recruitmentStart) return RECRUITMENT_STATUS.CLOSED;
const hour = recruitmentStart.getHours();
const minute = recruitmentStart.getMinutes();
let formatStr =
hour === 0 && minute === 0
? 'M월 d일'
: 'M월 d일 HH:mm';
return `${format(recruitmentStart, formatStr, { locale: ko })} ${RECRUITMENT_STATUS.UPCOMING}`;
}
if (!recruitmentEnd) return RECRUITMENT_STATUS.CLOSED;
const days = differenceInCalendarDays(recruitmentEnd, today);
if (days > ALWAYS_RECRUITING_THRESHOLD_DAYS) return RECRUITMENT_STATUS.ALWAYS; // D-day가 의미 없을 정도로 긴 경우 '상시 모집'으로 표시
return days > 0 ? `D-${days}` : 'D-Day';
};
🤖 Prompt for AI Agents
In frontend/src/utils/getDeadLineText.ts around line 37, the literal 365 is a
magic number; extract it into a clearly named constant (e.g., const
ALWAYS_RECRUITMENT_DAYS = 365) defined near the function/logic so its intent is
obvious, replace the hardcoded 365 in the if (days > 365) check with that
constant, and export the constant only if it must be reused elsewhere (otherwise
keep it module-local).

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: 0

♻️ Duplicate comments (1)
frontend/src/utils/getDeadLineText.ts (1)

35-35: 매직 넘버 365를 명명된 상수로 추출하세요.

365일 임계값이 하드코딩되어 있습니다. 이 값을 명명된 상수로 추출하면 의도가 명확해지고 향후 조정이 용이해집니다.

🔎 제안하는 리팩터링
+const ALWAYS_RECRUITING_THRESHOLD_DAYS = 365;
+
 const RECRUITMENT_STATUS = {
   CLOSED: '모집 마감',
   ALWAYS: '상시 모집',
   UPCOMING: '모집 시작',
 };

 const getDeadlineText = (
   recruitmentStart: Date | null,
   recruitmentEnd: Date | null,
   recruitmentStatus: string,
   today: Date = new Date(),
 ): string => {
   if (recruitmentStatus === 'CLOSED') {
     return RECRUITMENT_STATUS.CLOSED;
   }

   if (recruitmentStatus === 'UPCOMING') {
     if (!recruitmentStart) return RECRUITMENT_STATUS.CLOSED;
     const hour = recruitmentStart.getHours();
     const minute = recruitmentStart.getMinutes();

     let formatStr = 
     hour === 0 && minute === 0 
     ? 'M월 d일'
     : 'M월 d일 HH:mm';
     return `${format(recruitmentStart, formatStr, { locale: ko })} ${RECRUITMENT_STATUS.UPCOMING}`;
   }

   if (!recruitmentEnd) return RECRUITMENT_STATUS.CLOSED;
   const days = differenceInCalendarDays(recruitmentEnd, today);

-  if (days > 365) return RECRUITMENT_STATUS.ALWAYS; // D-day가 의미 없을 정도로 긴 경우 '상시 모집'으로 표시
+  if (days > ALWAYS_RECRUITING_THRESHOLD_DAYS) return RECRUITMENT_STATUS.ALWAYS; // D-day가 의미 없을 정도로 긴 경우 '상시 모집'으로 표시
   return days > 0 ? `D-${days}` : 'D-Day';
 };

학습된 내용과 코딩 가이드라인에 따라, 매직 넘버는 명명된 상수로 교체하여 명확성을 높이고, 로직 근처에 상수를 정의하여 연결이 명확하도록 해야 합니다.

🧹 Nitpick comments (2)
frontend/src/utils/getDeadLineText.ts (2)

13-13: 타입 안정성을 위해 RecruitmentStatus 타입을 사용하세요.

recruitmentStatus 매개변수가 string으로 타입되어 있어 타입 안정성이 부족합니다. AI 요약에 따르면 frontend/src/types/club.tsRecruitmentStatus 타입이 정의되어 있으므로, 이를 임포트하여 사용하면 컴파일 타임에 유효하지 않은 상태 값을 감지할 수 있습니다.

🔎 제안하는 리팩터링

파일 상단에 타입 임포트를 추가하세요:

+import type { RecruitmentStatus } from '@/types/club';
 import { format, differenceInCalendarDays } from 'date-fns';
 import { ko } from 'date-fns/locale';

그 다음 함수 시그니처를 업데이트하세요:

 const getDeadlineText = (
   recruitmentStart: Date | null,
   recruitmentEnd: Date | null,
-  recruitmentStatus: string,
+  recruitmentStatus: RecruitmentStatus,
   today: Date = new Date(),
 ): string => {

코딩 가이드라인에 따라, 일관된 타입 사용으로 유사 함수/훅 간 타입 일관성을 유지해야 합니다.


25-28: 가독성을 위해 삼항 연산자를 if/else로 변경하세요.

포맷 문자열을 결정하는 복잡한 삼항 연산자를 if/else 문으로 변경하면 가독성이 향상됩니다.

🔎 제안하는 리팩터링
-    let formatStr = 
-    hour === 0 && minute === 0 
-    ? 'M월 d일'
-    : 'M월 d일 HH:mm';
+    let formatStr: string;
+    if (hour === 0 && minute === 0) {
+      formatStr = 'M월 d일';
+    } else {
+      formatStr = 'M월 d일 HH:mm';
+    }
     return `${format(recruitmentStart, formatStr, { locale: ko })} ${RECRUITMENT_STATUS.UPCOMING}`;

코딩 가이드라인에 따라, 복잡하거나 중첩된 삼항 연산자는 가독성을 위해 if/else로 교체해야 합니다.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a87e2a6 and dad6cbb.

📒 Files selected for processing (1)
  • frontend/src/utils/getDeadLineText.ts
🧰 Additional context used
📓 Path-based instructions (2)
frontend/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (frontend/.cursorrules)

frontend/**/*.{ts,tsx,js,jsx}: Replace magic numbers with named constants for clarity
Replace complex/nested ternaries with if/else or IIFEs for readability
Assign complex boolean conditions to named variables for explicit meaning
Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle)
Use unique and descriptive names for custom wrappers/functions to avoid ambiguity
Define constants near related logic or ensure names link them clearly to avoid silent failures
Break down broad state management into smaller, focused hooks/contexts to reduce coupling

Files:

  • frontend/src/utils/getDeadLineText.ts
frontend/**/*.{ts,tsx}

📄 CodeRabbit inference engine (frontend/.cursorrules)

Use consistent return types for similar functions/hooks

Files:

  • frontend/src/utils/getDeadLineText.ts
🧠 Learnings (3)
📚 Learning: 2025-08-24T17:33:23.092Z
Learnt from: suhyun113
Repo: Moadong/moadong PR: 698
File: frontend/src/hooks/queries/applicants/useDeleteApplicants.ts:10-16
Timestamp: 2025-08-24T17:33:23.092Z
Learning: The codebase has inconsistent console logging patterns across files - mixing console.log/console.error for errors, using both Korean and English messages, and various formatting styles (template literals vs separate arguments, with/without emojis). A unified logging format like `console.error('[ModuleName] Operation failed:', error)` should be established for better debugging consistency.

Applied to files:

  • frontend/src/utils/getDeadLineText.ts
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{ts,tsx,js,jsx} : Define constants near related logic or ensure names link them clearly to avoid silent failures

Applied to files:

  • frontend/src/utils/getDeadLineText.ts
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{ts,tsx,js,jsx} : Replace magic numbers with named constants for clarity

Applied to files:

  • frontend/src/utils/getDeadLineText.ts
🔇 Additional comments (1)
frontend/src/utils/getDeadLineText.ts (1)

1-8: LGTM! 명확한 상수 정의와 적절한 임포트입니다.

date-fns 라이브러리와 한국어 로케일을 사용한 임포트가 적절하며, RECRUITMENT_STATUS 상수 객체를 통해 한글 라벨을 명확하게 정의했습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💻 FE Frontend 📈 release 릴리즈 배포

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants