Skip to content

Feat/413 유저/기업 홈 수정#421

Merged
MrMirror21 merged 17 commits into
devfrom
feat/413
Aug 1, 2025
Merged

Feat/413 유저/기업 홈 수정#421
MrMirror21 merged 17 commits into
devfrom
feat/413

Conversation

@ohofront

@ohofront ohofront commented Jun 24, 2025

Copy link
Copy Markdown
Contributor

Related issue 🛠

Work Description ✏️

  1. 전체 흐름 및 요구사항
  • 홈 화면 Job / Career / Resume 카드 디자인 통일
  • 로그인한 유저 타입(account_type)에 따라 다른 카드 노출
    • 유저(UserType.USER)
      • Trending Job Lists for you (스크랩 수 기준 인기)
      • Trending Career Lists for you (스크랩 수 기준 인기)
      • Bookmarked Job
      • Bookmarked Career
    • 고용주(UserType.OWNER)
      • 요즘 인기있는 인재 (Resume 리스트)
      • 요즘 인기있는 공고 (Job 리스트)
  1. 컴포넌트 분리 및 통일
  • Job 공고 카드 (HomePostCard)
    - 대표 이미지 (representative_img_url)를 backgroundImage로 적용
    - 고정 width, height (w-[9.063rem] h-[6.75rem])
    - 제목, 회사명, 주소, employment_type/visa 태그 표시
  • Career 공고 카드 (HomeCareerPostCard)
    - 기존 Job 카드 디자인과 완전히 동일하게 통일
    - careerData.img_urls[0] 이미지 사용 (없을 경우 No Image 박스 노출)
    - organizer_name, host_name 표시
    - career_category, visa 태그 표시
  • Resume 카드 (고용주 전용) (EmployerEmployeeCardList + EmployerEmployeeCard)
    • 디자인 통일:
      • 이미지 박스 상단 (profile_img_url)
      • 이름, 타이틀, industry/visa 태그 표시
      • 하단 북마크 버튼 + 북마크 수 표시
    • 전체 카드 폭 고정, 태그와 북마크를 같은 라인에 배치
  1. 데이터 요청 방식 분기
  • 유저일 때:
    • useHomeJobPosting / useGetCareerList / useGetPostList 사용
    • 북마크, 스크랩 기능 포함
  • 고용주일 때:
    • useInfiniteGetEmployeeResumeList 사용
    • 북마크 추가/삭제 시 usePutScrapResume 사용

Uncompleted Tasks 😅

  • Task1

To Reviewers 📢

  1. 유저회원
    화면 기록 2025-06-24 오후 9 19 32
  2. 기업회원
    화면 기록 2025-06-24 오후 9 21 29

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • 홈 화면에 커리어 카드 및 커리어 리스트 컴포넌트가 추가되어 커리어 관련 정보를 확인할 수 있습니다.
    • 홈 섹션이 사용자 유형(사업자/일반 사용자)에 따라 트렌딩 이력서, 트렌딩/북마크 채용공고, 커리어 정보를 다르게 보여줍니다.
    • 채용/커리어 카드 리스트, 이력서 카드 리스트에서 타이틀 및 "더보기" 버튼이 지원됩니다.
    • 직원 이력서 카드 컴포넌트와 북마크, 빈 상태 UI 컴포넌트가 새롭게 도입되었습니다.
    • 홈 화면에 개인 맞춤 인사말과 헤드라인을 표시하는 컴포넌트가 추가되었습니다.
    • 홈 배너가 캐러셀 형태로 새롭게 개선되었습니다.
    • 직원 이력서 카드 리스트 컴포넌트가 추가되어 이력서 정보를 가로 스크롤 형태로 제공합니다.
    • 비자 정보 표시를 위한 포맷팅 훅과 관련 유틸리티가 추가되었습니다.
  • 개선사항

    • 이력서 카드 및 리스트, 커리어 카드 리스트의 디자인과 레이아웃이 개선되었습니다.
    • 커리어 검색 섹션이 로그인/비로그인 상태를 구분하여 각각에 맞는 데이터를 보여줍니다.
    • 검색 필터 유틸리티가 사용자/비회원 구분 및 타입 안정성을 강화하도록 개선되었습니다.
    • 홈 메뉴 아이콘과 텍스트가 변경되어 UI가 간결해졌습니다.
    • 채용 카드 및 커리어 카드의 비자 태그 표시 방식이 개선되어 가독성이 향상되었습니다.
    • 일부 컴포넌트의 스타일과 레이아웃이 시맨틱 컬러와 유틸리티 클래스를 활용해 정리되었습니다.
    • 데이터 요청 및 네비게이션 로직이 사용자 유형에 따라 세분화되어 사용자 경험이 향상되었습니다.
  • 버그 수정

    • 일부 리스트에서 데이터가 없거나 로딩 중일 때의 상태 표시가 더 안전하게 처리됩니다.
    • 지역 필터 매핑 시 값이 없을 때도 오류 없이 동작하도록 수정되었습니다.

@ohofront ohofront added this to the 6월 3주차 스프린트 milestone Jun 24, 2025
@ohofront ohofront requested review from MrMirror21 and naarang June 24, 2025 12:10
@ohofront ohofront self-assigned this Jun 24, 2025
@ohofront ohofront added ✨ Feature New feature or request 🎨 Html&CSS Markup & Styles labels Jun 24, 2025
@ohofront ohofront added this to Giggle Jun 24, 2025
@coderabbitai

coderabbitai Bot commented Jun 24, 2025

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

이번 변경에서는 홈 화면의 유저/기업별 맞춤형 포스트, 커리어, 이력서 리스트 구성을 대폭 개편하고, 각 리스트 컴포넌트의 UI 및 props를 확장했습니다. 또한 커리어, 이력서, 공고 검색 필터 포맷터와 데이터 조회 훅이 역할별로 분리 및 강화되었습니다.

Changes

파일/그룹 변경 요약
홈 커리어 카드 및 리스트
src/components/Home/HomeCareerPostCard.tsx, src/components/Home/HomeCareerPostingList.tsx
홈 커리어 카드 및 리스트 컴포넌트 신규 도입, 역할별 커리어 리스트 렌더링 지원
홈 포스트 섹션
src/components/Home/HomeJobPostingSection.tsx
컴포넌트명 HomePostSection으로 변경, 유저/기업별 홈 화면 로직 및 데이터 분기, 여러 리스트/탭 렌더링
고용주 직원 카드 리스트 리팩토링
src/components/Employer/EmployeeSearch/EmployerEmployeeCardList.tsx
카드/리스트 UI 리팩토링, props 확장, 스크롤/레이아웃 개선, 북마크 카운트 표시 등
커리어 카드 리스트 헤더 및 props 확장
src/components/PostSearch/CareerCardList.tsx
리스트 헤더(타이틀/See More) props 추가, 안전한 데이터 매핑 처리
커리어 검색 섹션 로그인 분기 및 필터 포맷터 분리
src/components/PostSearch/CareerSearchSection.tsx
게스트/로그인 유저 분기, 필터 포맷터 및 데이터 훅 분리, 관련 상태명 정비
검색 필터 리스트 안전성 및 className 변경
src/components/PostSearch/PostSearchFilterList.tsx
undefined 안전성 보강 및 className 순서 조정
커리어 리스트 단일 페이지 조회용 API 훅 추가
src/hooks/api/useCareer.ts
커리어 리스트 단일 페이지 조회용 신규 훅 2종 추가 (useGetCareerList, useGetCareerGuestList)
검색 페이지 초기화 로직 개선
src/pages/PostSearch/PostSearchPage.tsx
검색 옵션/탭 초기화에 location.state 안전하게 활용, 초기값 명시적 할당
스크랩된 공고 페이지 필터 초기화 및 요청 파라미터 변경
src/pages/Resume/ScrappedJobPostsPage.tsx
location.state로 필터 탭 초기화, 커리어 요청 파라미터 변경(정렬, 카테고리 필수화)
커리어 타입 확장
src/types/api/career.ts
CareerListItemTypeimg_urls(이미지 배열) 속성 추가
검색 필터 포맷터 분리 및 타입 강화
src/utils/formatSearchFilter.ts
공고/커리어/이력서 필터 포맷터 역할별 분리 및 타입 강화, safeJoin 도입
직원 카드 컴포넌트 및 북마크 UI 신규 도입
src/components/Common/EmployeeCard/*
EmployeeCard, EmployeeCardBookmark, EmployeeCardEmptyState 신규 컴포넌트 도입 및 index 파일로 묶음
고용주 직원 카드 리스트에서 EmployeeCard 컴포넌트 사용으로 리팩토링
src/components/Employer/EmployeeSearch/EmployerEmployeeCardList.tsx
내부 커스텀 카드 제거, 공통 EmployeeCard 컴포넌트 사용, 북마크 및 내비게이션 로직 위임
커스텀 훅 도입: 직원 카드 북마크 및 내비게이션 처리
src/hooks/useEmployeeCard.ts
직원 카드 북마크 토글 및 상세 페이지 이동 함수 제공 훅 추가
비자 정보 포맷팅 훅 추가 및 활용
src/hooks/useFormattedVisa.ts
비자 리스트를 포맷팅하여 대표 비자 문자열 생성하는 훅 추가, 홈 포스트 카드 등에서 활용
홈 배너 컴포넌트 리팩토링 및 이름 변경
src/components/Home/HomeBannerCarousel.tsx
기존 HomeBanner 제거, HomeBannerCarousel로 교체, 불필요한 UI 제거 및 스타일 조정
홈 직원 카드 리스트 신규 도입
src/components/Home/HomeEmployeeCardList.tsx
직원 이력서 카드 리스트 컴포넌트 추가, 로딩/빈 상태 및 가로 스크롤 지원
홈 인사말 섹션 신규 도입
src/components/Home/HomeGreetingSection.tsx
유저 타입별 맞춤 인사말 및 헤드라인 메시지 렌더링 컴포넌트 추가
홈 상단 섹션 신규 도입
src/components/Home/HomeTopSection.tsx
HomeGreetingSection, ResumeHelperBanner, HomeMenu 조합한 상단 섹션 컴포넌트 추가
홈 메뉴 아이콘 및 텍스트 변경, 스타일 조정
src/components/Home/HomeMenu.tsx
메뉴 아이콘 SVG 변경, 텍스트 변경, 버튼 스타일 및 렌더링 조건 수정
홈 포스트 카드 비자 태그 포맷팅 개선
src/components/Home/HomePostCard.tsx
비자 태그 문자열 가공 및 useFormattedVisa 훅 활용, 불필요 마진 클래스 제거
홈 페이지 컴포넌트에서 배너 및 메뉴 컴포넌트 교체
src/pages/Home/HomePage.tsx
HomeBannerHomeMenu 제거, HomeTopSectionHomeBannerCarousel로 교체
검색 페이지 및 기타 UI 개선
src/components/Home/HomeJobPostingList.tsx, src/components/PostSearch/PostSearchFilterList.tsx
UI 스타일링 개선 및 className 순서 변경, 안전성 강화

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant HomePostSection
    participant API
    participant ListComponent

    User->>HomePostSection: 홈 진입
    HomePostSection->>API: (유저/기업별) 트렌딩/북마크 데이터 요청
    API-->>HomePostSection: 데이터 반환
    HomePostSection->>ListComponent: 데이터 전달 (props)
    ListComponent-->>User: 리스트 렌더링 (타이틀/See More/카드 등)
    User->>ListComponent: See More 클릭
    ListComponent->>HomePostSection: onSeeMoreClick 콜백
    HomePostSection->>User: 검색/스크랩 페이지로 이동
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Assessment against linked issues

Objective Addressed Explanation
Trending Job Lists for you (스크랩 수 기준 인기), See More 클릭 시 검색 - 공고/popular활성화 (#413)
Trending Career Lists for you (스크랩 수 기준 커리어), See More 클릭 시 검색 - 커리어/popular활성화 (#413)
Bookmarked Job (북마크 공고), See More 클릭 시 스크랩 - 공고 활성화 (#413)
Bookmarked Career (북마크 커리어), See More 클릭 시 스크랩 - 커리어 활성화 (#413)

Assessment against linked issues: Out-of-scope changes

(해당 없음)

Possibly related PRs

  • #382: EmployerEmployeeCardList 및 관련 API/타입/상수의 최초 도입 PR로, 본 PR의 리팩토링/기능 확장과 직접적으로 연결됨.
  • #392: EmployerEmployeeCard의 북마크 처리 및 prop 기반 상태관리 리팩토링 등, 본 PR의 카드 컴포넌트 변경과 코드 레벨에서 밀접하게 연관됨.

Suggested reviewers

  • ohofront
  • naarang

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3211a61 and 476a685.

📒 Files selected for processing (3)
  • src/components/Home/HomeCareerPostCard.tsx (1 hunks)
  • src/hooks/api/useCareer.ts (1 hunks)
  • src/pages/Resume/ScrappedJobPostsPage.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/hooks/api/useCareer.ts
  • src/components/Home/HomeCareerPostCard.tsx
  • src/pages/Resume/ScrappedJobPostsPage.tsx
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/413

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 generate unit tests to generate unit tests for 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🔭 Outside diff range comments (1)
src/pages/PostSearch/PostSearchPage.tsx (1)

55-59: Performance API 브라우저 호환성 확인 필요

Performance Navigation Timing API가 모든 브라우저에서 지원되지 않을 수 있습니다. 특히 오래된 브라우저에서는 오류가 발생할 수 있습니다.

-const isReload =
-  (
-    performance.getEntriesByType(
-      'navigation',
-    )[0] as PerformanceNavigationTiming
-  )?.type === 'reload';
+let isReload = false;
+try {
+  const navEntry = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming;
+  isReload = navEntry?.type === 'reload';
+} catch (error) {
+  // Fallback for browsers that don't support Performance API
+  console.warn('Performance API not supported');
+}
🧹 Nitpick comments (12)
src/hooks/api/useCareer.ts (1)

203-203: 주석의 번호를 확인해주세요.

주석에 "144"라고 되어있는데, 다른 API 주석들과의 일관성을 위해 "14.4"가 맞는지 확인해주세요.

-// 144 (게스트) 커리어 리스트 일반 조회 훅 (페이징 없이 한번에 호출)
+// 14.4 (게스트) 커리어 리스트 일반 조회 훅 (페이징 없이 한번에 호출)
src/components/Home/HomeCareerPostingList.tsx (2)

51-53: 수평 스크롤 컨테이너의 키보드 접근성 개선 필요

현재 구현은 마우스/터치 스크롤만 지원합니다. 키보드 사용자를 위해 좌우 화살표 키로 스크롤할 수 있도록 구현을 추가하는 것이 좋겠습니다.

-<div className="flex overflow-x-scroll whitespace-nowrap no-scrollbar">
+<div 
+  className="flex overflow-x-scroll whitespace-nowrap no-scrollbar"
+  tabIndex={0}
+  onKeyDown={(e) => {
+    const scrollAmount = 200;
+    if (e.key === 'ArrowLeft') {
+      e.currentTarget.scrollBy({ left: -scrollAmount, behavior: 'smooth' });
+    } else if (e.key === 'ArrowRight') {
+      e.currentTarget.scrollBy({ left: scrollAmount, behavior: 'smooth' });
+    }
+  }}
+>

16-17: 에러 상태 처리 추가 검토

현재 로딩과 빈 데이터 상태만 처리하고 있습니다. API 호출 실패 시 에러 상태도 처리하면 더 나은 사용자 경험을 제공할 수 있습니다.

에러 상태 처리를 위한 props 추가와 UI 구현이 필요하신가요?

src/components/Home/HomeCareerPostCard.tsx (1)

33-35: "No Image" 텍스트 다국어 지원 필요

"No Image" 텍스트가 영어로 하드코딩되어 있습니다. 다른 UI 요소들과 일관성을 위해 번역 상수를 사용하는 것이 좋겠습니다.

-No Image
+{postTranslation.noImage || '이미지 없음'}
src/components/PostSearch/CareerSearchSection.tsx (1)

44-91: 에러 상태 처리 추가 권장

현재 로딩 상태만 처리하고 있으나, API 호출 실패 시 에러 상태도 처리하면 사용자 경험이 개선될 것입니다.

useInfiniteGetCareerListuseInfiniteGetCareerGuestList 훅에서 error 상태도 반환받아 처리하는 것을 고려해보세요.

src/pages/PostSearch/PostSearchPage.tsx (1)

18-25: state 객체 타입 검증 추가 권장

location.state의 타입이 보장되지 않으므로, 런타임 타입 검증을 추가하면 더 안전할 것 같습니다.

타입 가드 함수를 만들어 state 객체의 속성들을 검증하는 것을 고려해보세요. 예를 들어:

const isValidSearchState = (state: any): state is SearchState => {
  return state && 
    (typeof state.searchText === 'string' || state.searchText === undefined) &&
    // ... 다른 필드들 검증
};
src/components/Home/HomeJobPostingSection.tsx (1)

62-89: 네비게이션 state 객체 상수화 권장

네비게이션 함수들이 호출될 때마다 새로운 state 객체가 생성됩니다. 이를 상수로 정의하면 메모리 효율성이 개선됩니다.

+const NAVIGATION_STATES = {
+  JOB_SEARCH: {
+    initialMenu: POST_SEARCH_PAGE_MENU.POST,
+    postSortType: POST_SORTING.POPULAR,
+  },
+  CAREER_SEARCH: {
+    initialMenu: POST_SEARCH_PAGE_MENU.CAREER,
+    careerSortType: POST_SORTING.POPULAR,
+  },
+  RESUME_SEARCH: {
+    initialMenu: POST_SEARCH_PAGE_MENU.CAREER,
+    resumeSortType: POST_SORTING.POPULAR,
+  },
+};

 const goToJobSearch = () => {
-  navigate('/search', {
-    state: {
-      initialMenu: POST_SEARCH_PAGE_MENU.POST,
-      postSortType: POST_SORTING.POPULAR,
-    },
-  });
+  navigate('/search', { state: NAVIGATION_STATES.JOB_SEARCH });
 };
src/components/Employer/EmployeeSearch/EmployerEmployeeCardList.tsx (3)

32-48: 이미지 폴백 디자인을 개선해보세요.

현재 "No Image" 텍스트가 하드코딩되어 있고, 그라디언트 배경색이 다소 강해 보입니다. 브랜드 일관성을 위해 다른 컴포넌트와 유사한 폴백 스타일을 사용하는 것이 좋겠습니다.

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

-          <div className="flex items-center justify-center w-full h-full text-white bg-gradient-to-r from-purple-500 to-pink-500">
-            No Image
+          <div className="flex items-center justify-center w-full h-full text-text-alternative bg-surface-secondary">
+            <EmptyJobIcon className="w-8 h-8" />
           </div>

55-57: 하드코딩된 폴백 텍스트를 상수로 분리하세요.

title이 없을 때 표시되는 텍스트가 하드코딩되어 있습니다. 유지보수성을 위해 상수나 번역 파일로 분리하는 것이 좋겠습니다.

-          {cardData?.title || '친절한 서비스를 고객을 맞게 만들어보아요!'}
+          {cardData?.title || postTranslation.defaultEmployeeTitle.ko}

74-74: 비자 정보 변환 로직을 재사용 가능한 유틸로 분리하세요.

replace(/_/g, '-') 로직이 여러 곳에서 사용될 것 같습니다. 재사용성을 위해 별도 유틸 함수로 분리하는 것을 고려해보세요.

// utils/formatVisa.ts
export const formatVisaForDisplay = (visa: string) => visa.replace(/_/g, '-');
src/utils/formatSearchFilter.ts (2)

127-127: 카테고리 조인 로직에 일관성을 적용하세요.

카테고리 필터링에서 safeJoin 유틸을 사용하지 않고 직접 join을 사용하고 있습니다. 일관성을 위해 safeJoin을 사용하는 것이 좋겠습니다.

-    category: careerCategory.length > 0 ? careerCategory.join(',') : null,
+    category: careerCategory.length > 0 ? safeJoin(careerCategory) : null,

Also applies to: 166-166


195-204: 이력서 검색 필터에도 safeJoin을 적용하세요.

다른 포맷터와 일관성을 위해 safeJoin 유틸을 사용하는 것이 좋겠습니다.

   return {
     size: 5,
     sorting: sortType,
-    visa:
-      filterList[EMPLOYEE_SEARCH_CATEGORY.VISA]
-        ?.join(',')
-        ?.replace(/-/g, '_') ?? null,
-    korean: filterList[EMPLOYEE_SEARCH_CATEGORY.KOREAN]?.join(',') ?? null,
-    major: filterList[EMPLOYEE_SEARCH_CATEGORY.MAJOR]?.join(',') ?? null,
-    nationality:
-      filterList[EMPLOYEE_SEARCH_CATEGORY.NATIONALITY]?.join(',') ?? null,
-    industry: filterList[EMPLOYEE_SEARCH_CATEGORY.INDUSTRY]?.join(',') ?? null,
+    visa: safeJoin(filterList[EMPLOYEE_SEARCH_CATEGORY.VISA])?.replace(/-/g, '_') ?? null,
+    korean: safeJoin(filterList[EMPLOYEE_SEARCH_CATEGORY.KOREAN]) ?? null,
+    major: safeJoin(filterList[EMPLOYEE_SEARCH_CATEGORY.MAJOR]) ?? null,
+    nationality: safeJoin(filterList[EMPLOYEE_SEARCH_CATEGORY.NATIONALITY]) ?? null,
+    industry: safeJoin(filterList[EMPLOYEE_SEARCH_CATEGORY.INDUSTRY]) ?? null,
   };
📜 Review details

Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6182b17 and c64b568.

📒 Files selected for processing (12)
  • src/components/Employer/EmployeeSearch/EmployerEmployeeCardList.tsx (2 hunks)
  • src/components/Home/HomeCareerPostCard.tsx (1 hunks)
  • src/components/Home/HomeCareerPostingList.tsx (1 hunks)
  • src/components/Home/HomeJobPostingSection.tsx (1 hunks)
  • src/components/PostSearch/CareerCardList.tsx (2 hunks)
  • src/components/PostSearch/CareerSearchSection.tsx (4 hunks)
  • src/components/PostSearch/PostSearchFilterList.tsx (2 hunks)
  • src/hooks/api/useCareer.ts (1 hunks)
  • src/pages/PostSearch/PostSearchPage.tsx (4 hunks)
  • src/pages/Resume/ScrappedJobPostsPage.tsx (3 hunks)
  • src/types/api/career.ts (1 hunks)
  • src/utils/formatSearchFilter.ts (1 hunks)
🔇 Additional comments (15)
src/types/api/career.ts (1)

16-16: 타입 확장이 적절합니다.

CareerListItemTypeimg_urls 속성 추가가 잘 되었습니다. 홈 화면의 커리어 카드에서 이미지를 표시하기 위한 기반 작업으로 보이며, 선택적 속성으로 정의되어 기존 코드와의 호환성도 유지됩니다.

src/pages/Resume/ScrappedJobPostsPage.tsx (1)

84-88: 네비게이션 state를 활용한 초기 필터 설정이 좋습니다.

useLocation을 사용하여 네비게이션으로부터 필터 탭의 초기값을 받아오는 로직이 잘 구현되었습니다. 사용자 경험 향상에 도움이 될 것 같습니다.

src/components/PostSearch/PostSearchFilterList.tsx (1)

46-52: 안전한 배열 접근 패턴이 잘 적용되었습니다.

region1Depth?.map(...) ?? []을 사용하여 region1Depth가 undefined일 때의 런타임 에러를 방지했습니다. 방어적 프로그래밍의 좋은 예시입니다.

src/components/PostSearch/CareerCardList.tsx (3)

101-105: 컴포넌트 재사용성이 향상되었습니다.

titleonSeeMoreClick 선택적 props 추가로 컴포넌트의 재사용성이 크게 향상되었습니다. 다양한 컨텍스트에서 활용할 수 있게 되었네요.

Also applies to: 109-113


149-162: 헤더 영역 구현이 깔끔합니다.

조건부 렌더링을 통한 제목과 "See More" 버튼 구현이 잘 되어있습니다. UI 일관성도 유지되고 있습니다.


165-165: 안전한 배열 접근이 적용되었습니다.

careerData?.map으로 optional chaining을 적용하여 undefined 에러를 방지했습니다.

src/hooks/api/useCareer.ts (2)

190-201: 단순 조회 훅 추가가 좋습니다.

무한스크롤이 필요하지 않은 경우를 위한 useGetCareerList 훅 추가가 적절합니다. 홈 화면 등에서 제한된 개수의 데이터만 필요할 때 유용할 것 같습니다.


204-214: 게스트용 단순 조회 훅도 잘 구현되었습니다.

로그인 여부에 따른 API 분리가 일관되게 적용되었고, 구현도 기존 패턴을 잘 따르고 있습니다.

src/components/PostSearch/CareerSearchSection.tsx (1)

52-58: 하드코딩된 페이지네이션 값 검토 필요

page: 1size: 5가 하드코딩되어 있습니다. 이는 무한 스크롤 로직과 맞지 않을 수 있으며, 실제 페이지네이션 상태와 동기화되지 않을 수 있습니다.

무한 스크롤에서 초기 페이지와 사이즈 설정이 올바른지 확인이 필요합니다. useInfiniteGetCareerListuseInfiniteGetCareerGuestList 훅의 구현을 확인해주세요.

Also applies to: 70-77

src/components/Home/HomeJobPostingSection.tsx (1)

99-101: flatMap 사용 시 undefined 처리 개선 필요

pages가 undefined일 경우 flatMap이 예상치 못한 동작을 할 수 있습니다.

-resumeData={
-  trendingResumeData?.pages?.flatMap((page) => page.data.resumes) ??
-  []
-}
+resumeData={
+  trendingResumeData?.pages
+    ? trendingResumeData.pages.flatMap((page) => page.data.resumes)
+    : []
+}

Likely an incorrect or invalid review comment.

src/components/Employer/EmployeeSearch/EmployerEmployeeCardList.tsx (1)

26-28: 다음 스크립트로 전체 코드베이스에서 /employer/search 경로 정의를 다시 검색해 보세요:

#!/bin/bash
# employer/search 경로가 라우터에 정의되어 있는지 전체 코드베이스에서 검색
rg -g '*.ts*' -A 3 -B 3 "employer/search"
src/utils/formatSearchFilter.ts (4)

14-15: 유틸 함수가 잘 구현되었습니다.

safeJoin 함수는 null/undefined 안전성을 제공하고 중복 코드를 줄여주는 좋은 접근입니다.


22-44: TypeScript 타입 정의가 명확합니다.

입력과 출력 타입을 명확히 분리한 것이 코드의 가독성과 타입 안전성을 크게 향상시켰습니다.


111-130: 함수 분리가 적절합니다.

사용자와 게스트용 커리어 검색 필터를 분리한 것이 코드의 명확성과 유지보수성을 향상시켰습니다.


55-65: formatSearchFilter.ts의 전체 로직과 safeJoin 정의를 확인하기 위해 아래 스크립트를 실행해주세요.

#!/bin/bash
# 1. formatSearchFilter 함수 전체 내용 확인
sed -n '1,200p' src/utils/formatSearchFilter.ts

# 2. safeJoin 함수 정의 위치 확인
rg -n "export function safeJoin" -A5 -B5 --glob "*.ts"

Comment thread src/pages/Resume/ScrappedJobPostsPage.tsx Outdated
{/* 주관-주최 */}
<p className="whitespace-normal caption-12-regular text-text-alternative">
{careerData.organizer_name ?? '-'}
<span className="inline-block h-3 mx-1 align-middle border bg-border-alternative"></span>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

구분선 스타일 수정 필요

현재 구분선에 너비가 지정되지 않아 보이지 않을 수 있습니다.

-<span className="inline-block h-3 mx-1 align-middle border bg-border-alternative"></span>
+<span className="inline-block w-[1px] h-3 mx-1 align-middle bg-border-alternative"></span>
🤖 Prompt for AI Agents
In src/components/Home/HomeCareerPostCard.tsx at line 47, the span element used
as a divider lacks a width, causing it to potentially be invisible. Add an
explicit width style or class to the span to ensure the divider is visible, such
as setting a fixed width or using a utility class that defines width.

Comment on lines +20 to +23
<article
className="flex flex-col gap-2 w-[9.063rem] m-1 rounded-lg"
onClick={goToCareerDetailPage}
>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

클릭 가능한 카드에 대한 시각적 피드백과 접근성 개선 필요

article 요소가 클릭 가능하지만 사용자에게 이를 알려주는 시각적 표시가 없고, 키보드 접근성도 부족합니다.

 <article
   className="flex flex-col gap-2 w-[9.063rem] m-1 rounded-lg"
+  role="button"
+  tabIndex={0}
+  style={{ cursor: 'pointer' }}
   onClick={goToCareerDetailPage}
+  onKeyDown={(e) => {
+    if (e.key === 'Enter' || e.key === ' ') {
+      e.preventDefault();
+      goToCareerDetailPage();
+    }
+  }}
 >
📝 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
<article
className="flex flex-col gap-2 w-[9.063rem] m-1 rounded-lg"
onClick={goToCareerDetailPage}
>
<article
className="flex flex-col gap-2 w-[9.063rem] m-1 rounded-lg"
role="button"
tabIndex={0}
style={{ cursor: 'pointer' }}
onClick={goToCareerDetailPage}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
goToCareerDetailPage();
}
}}
>
🤖 Prompt for AI Agents
In src/components/Home/HomeCareerPostCard.tsx around lines 20 to 23, the
clickable article element lacks visual feedback and keyboard accessibility. Add
appropriate focus styles and role="button" to the article element, and handle
keyboard events like onKeyDown to support keyboard navigation. This will improve
both visual indication and accessibility for keyboard users.

Comment on lines +33 to +40
const { data: trendingResumeData, isLoading: trendingResumeLoading } =
useInfiniteGetEmployeeResumeList(
{
size: 5,
sorting: POST_SORTING.POPULAR,
},
isOwner,
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

조건부 데이터 페칭 최적화 필요

현재 구현에서는 조건에 관계없이 모든 훅이 호출되고 있어, 불필요한 API 요청이 발생할 수 있습니다. 특히 고용주 계정에서는 커리어 관련 API가, 일반 유저에서는 이력서 API가 호출될 필요가 없습니다.

각 훅의 enabled 조건을 더 명확히 하여 필요한 경우에만 API를 호출하도록 개선하는 것이 좋겠습니다.

Also applies to: 49-51, 58-59

🤖 Prompt for AI Agents
In src/components/Home/HomeJobPostingSection.tsx around lines 33 to 40, 49 to
51, and 58 to 59, the data fetching hooks are called unconditionally, causing
unnecessary API requests for certain user types. To fix this, add an `enabled`
option to each hook's configuration that checks the user type (e.g., isOwner)
and only enables the hook when the data is needed for that user. This will
prevent irrelevant API calls and optimize data fetching.

Comment on lines 139 to 162
<div className="flex flex-col gap-2">
{title && (
<div className="flex items-center justify-between py-1">
<h3 className="text-black heading-18-semibold">{title}</h3>
{onSeeMoreClick && (
<button
className="caption-12-regular text-[#9397A1]"
onClick={onSeeMoreClick}
>
See More
</button>
)}
</div>
)}

<div className="flex overflow-x-scroll whitespace-nowrap no-scrollbar">
{resumeData.map((value) => (
<EmployerEmployeeCard key={value.id} cardData={value} />
))}
</main>
</div>

{isLoading && <LoadingItem />}
</>
</div>
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

접근성 및 키보드 네비게이션을 개선하세요.

"See More" 버튼에 적절한 aria-label이 없고, 가로 스크롤 컨테이너에 키보드 네비게이션 지원이 부족합니다.

다음과 같이 접근성을 개선할 수 있습니다:

           {onSeeMoreClick && (
             <button
-              className="caption-12-regular text-[#9397A1]"
+              className="caption-12-regular text-[#9397A1]"
+              aria-label={`${title} 목록 더보기`}
               onClick={onSeeMoreClick}
             >
               See More
             </button>
           )}

-      <div className="flex overflow-x-scroll whitespace-nowrap no-scrollbar">
+      <div 
+        className="flex overflow-x-scroll whitespace-nowrap no-scrollbar"
+        role="list"
+        aria-label={title ? `${title} 목록` : '직원 카드 목록'}
+        tabIndex={0}
+      >
📝 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
<div className="flex flex-col gap-2">
{title && (
<div className="flex items-center justify-between py-1">
<h3 className="text-black heading-18-semibold">{title}</h3>
{onSeeMoreClick && (
<button
className="caption-12-regular text-[#9397A1]"
onClick={onSeeMoreClick}
>
See More
</button>
)}
</div>
)}
<div className="flex overflow-x-scroll whitespace-nowrap no-scrollbar">
{resumeData.map((value) => (
<EmployerEmployeeCard key={value.id} cardData={value} />
))}
</main>
</div>
{isLoading && <LoadingItem />}
</>
</div>
);
<div className="flex flex-col gap-2">
{title && (
<div className="flex items-center justify-between py-1">
<h3 className="text-black heading-18-semibold">{title}</h3>
{onSeeMoreClick && (
<button
className="caption-12-regular text-[#9397A1]"
aria-label={`${title} 목록 더보기`}
onClick={onSeeMoreClick}
>
See More
</button>
)}
</div>
)}
<div
className="flex overflow-x-scroll whitespace-nowrap no-scrollbar"
role="list"
aria-label={title ? `${title} 목록` : '직원 카드 목록'}
tabIndex={0}
>
{resumeData.map((value) => (
<EmployerEmployeeCard key={value.id} cardData={value} />
))}
</div>
{isLoading && <LoadingItem />}
</div>
🤖 Prompt for AI Agents
In src/components/Employer/EmployeeSearch/EmployerEmployeeCardList.tsx between
lines 139 and 162, the "See More" button lacks an appropriate aria-label and the
horizontal scroll container does not support keyboard navigation. To fix this,
add a descriptive aria-label to the "See More" button that clearly indicates its
purpose. Also, enhance the scroll container by adding keyboard navigation
support, such as making it focusable with tabIndex and enabling arrow key
scrolling or similar keyboard interactions for better accessibility.

@ohofront ohofront changed the title Feat/413 Feat/413 유저/기업 홈 수정 Jun 24, 2025
Comment thread src/components/Home/HomeCareerPostCard.tsx

@naarang naarang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

변경사항이 많았는데 고생많으셨습니다🙇‍♀️
올려주신 Gif 파일에서 기업회원의 경우에 "see more"와 "더보기"가 혼용되어 나타나는데 "더보기"로 통일되어야 합니다!

Comment thread src/hooks/api/useCareer.ts Outdated
Comment thread src/hooks/api/useCareer.ts Outdated
Comment thread src/pages/Resume/ScrappedJobPostsPage.tsx Outdated
Comment thread src/components/Home/HomeJobPostingSection.tsx Outdated

@naarang naarang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

그리고 기업 회원 화면에서 인재 카드에서 북마크 버튼이 피그마에 정의된 것보다 큰 것 같은데 확인 부탁드립니다!

또한 인재 카드의 경우에 이름은 한 줄, 자기소개는 2줄이고 넘어가면 ... 처리인 것으로 피그마에 되어있어서 반영해주시면 좋을 것 같습니다!

Comment thread src/components/Home/HomeJobPostingSection.tsx
Comment thread src/components/PostSearch/CareerSearchSection.tsx

@naarang naarang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

일반 회원의 경우에 퀵 메뉴의 메뉴명들도 변경되었습니다! 다음의 피그마를 참고해서 반영해주시면 좋을 것 같습니다~

image

Comment thread src/components/Home/HomeJobPostingSection.tsx
- 기존 page 최상위에서 일괄적으로 px-4를 가지고 있었지만 횡스크롤 형 ui들은 px-4에 의해 잘리면 안되므로 해당 ui가 자체적으로 padding을 가지도록 변경함
- 사용자 유형에 따라 퀵메뉴가 존재하지 않음에도 그 container의 padding이 존재, 화면의 불필요한 공백 생성하고 있어 이를 제거함.
- HomePage 내 UI 레이아웃 변경에 따라 인사 문구 등을 출력하는 HomeGreetingSection, 이력서 완성도를 보여주는ResumeHelperBanner, 사용자 유형별 퀵메뉴를 제공하는 HomeMenu를 묶어 HomeTopSection 컴포넌트로 제공
- 기존 광고 배너 캐러셀을 제공했던 HomeBanner를 HomeBannerCarousel로 변경, HomePage에서 단독 호출
- 사용자 유형별로 공고/커리어 카드 내 요구 비자 리스트 문구를 출력하는 로직을 커스텀 훅으로 분리
- 로직 내 삼항 연산자 제거
- 로직과 ui 로직 상 중복되는 부분이 많은 홈/인재 검색에 사용되는 HomeEmployerEmployeeCardList와 EmployerEmployeeCardList에 사용되는 코드를 EmployeeCard로 통합했습니다.
@github-actions

github-actions Bot commented Aug 1, 2025

Copy link
Copy Markdown

✅ Vitest Test Results

**Status:** ALL TESTS PASSED
**Runtime:** 2.39s

### 📊 Test Summary
```
Test Files: 22 files
Total:      177 tests
Passed:     177 tests
Failed:     0 tests
Skipped:    0 tests
```

📉 Coverage Warnings

⚠️ Lines coverage is below 80% (0%)
⚠️ Functions coverage is below 80% (0%)
⚠️ Branches coverage is below 80% (0%)
⚠️ Statements coverage is below 80% (0%)

🎉 All tests passed!

Great job! All 177 tests are working correctly across 22 test files.

🔗 Quick Actions

  • [🧪 Run tests locally](pnpm test)
  • [📊 Run coverage locally](pnpm test:coverage)
  • [🎨 Open Vitest UI](pnpm test:ui)
  • ⚙️ View workflow logs

🤖 Generated by GitHub Actions at 2025-08-01T06:16:34.535Z

@MrMirror21 MrMirror21 self-assigned this Aug 1, 2025
@MrMirror21 MrMirror21 moved this to In Progress in Giggle Aug 1, 2025
@MrMirror21 MrMirror21 added the 🐞 BugFix Something isn't working label Aug 1, 2025

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (2)
src/components/Home/HomeJobPostingSection.tsx (2)

91-91: 섹션 간 간격 확인 필요

이전 리뷰에서 기업회원 화면의 "요즘 인기있는 인재"와 "요즘 인기있는 공고" 사이 간격이 피그마보다 크다는 지적이 있었습니다. 현재 gap-8 클래스를 사용하고 있는데, 디자인 명세와 일치하는지 확인이 필요합니다.

실제 렌더링된 화면에서 섹션 간 간격이 디자인 명세와 일치하는지 확인해 주세요.


80-88: 이력서 검색 네비게이션 경로 수정 필요

이전 리뷰 코멘트에서 지적된 문제가 여전히 남아있습니다. 기업회원의 "요즘 인기있는 인재" 더보기 버튼은 /employer/search (인재검색 페이지)로 이동해야 하는데, 현재는 /search로 이동하고 있습니다.

const goToResumeSearch = () => {
-  navigate('/search', {
-    state: {
-      initialMenu: POST_SEARCH_PAGE_MENU.CAREER,
-      resumeSortType: POST_SORTING.POPULAR,
-    },
-  });
+  navigate('/employer/search');
};
🧹 Nitpick comments (6)
src/components/Home/HomeMenu.tsx (1)

44-44: 메뉴 레이블 단순화가 적절합니다.

메뉴 텍스트가 더 간결하고 모던한 형태로 업데이트되었습니다. 모바일 환경에서 더 나은 사용자 경험을 제공할 것으로 예상됩니다.

단축된 레이블이 사용자에게 명확한 의미를 전달하는지 UX 테스트를 고려해보세요.

Also applies to: 49-49, 54-54, 59-59

src/hooks/useEmployeeCard.ts (1)

6-23: 타입 안전성 개선을 고려해보세요.

현재 cardData.id의 타입이 명시적으로 검증되지 않습니다. API 응답에서 id가 undefined일 가능성을 고려하여 방어적 코딩을 추가할 수 있습니다.

  const handleClickBookmark = (e: MouseEvent) => {
    e.stopPropagation();
+   if (!cardData.id) return;
    mutate(cardData.id);
  };

  const goToResumeDetailPage = () => {
+   if (!cardData.id) return;
    navigate(`/employer/search/${cardData.id}`);
  };
src/components/Home/HomeGreetingSection.tsx (1)

25-34: 접근성 개선을 고려해보세요.

현재 헤드라인이 h2 태그를 사용하고 있는데, 페이지의 전체적인 헤딩 구조를 고려하여 적절한 레벨인지 확인해주세요.

SEO와 접근성을 위해 헤딩 레벨이 올바른지 확인하고, 필요시 h1 또는 다른 레벨로 조정하는 것을 고려해보세요.

src/hooks/useFormattedVisa.ts (1)

10-11: 엣지 케이스 처리를 강화해보세요.

현재 빈 배열이나 undefined에 대한 처리는 적절하지만, 배열의 요소가 빈 문자열인 경우에 대한 처리도 고려해볼 수 있습니다.

  return useMemo(() => {
-   if (!visaData || visaData.length === 0) return '';
+   if (!visaData || visaData.length === 0) return '';
+   const filteredVisaData = visaData.filter(visa => visa && visa.trim());
+   if (filteredVisaData.length === 0) return '';
-   const visaList = visaData.map((visa) => visa.replace(/_/g, '-')).sort();
+   const visaList = filteredVisaData.map((visa) => visa.replace(/_/g, '-')).sort();
src/components/Home/HomeEmployeeCardList.tsx (1)

9-9: 타입 이름 불일치 수정 필요

EmployerEmployeeCardListProps 타입명이 컴포넌트명 HomeEmployeeCardList와 일치하지 않습니다. 일관성을 위해 HomeEmployeeCardListProps로 변경하는 것이 좋겠습니다.

-type EmployerEmployeeCardListProps = {
+type HomeEmployeeCardListProps = {
src/components/Common/EmployeeCard/EmployeeCard.tsx (1)

57-57: 비자 포맷팅 로직 중복 제거 필요

비자 값에서 언더스코어를 하이픈으로 변경하는 로직이 두 variant에서 중복되고 있습니다. 이를 컴포넌트 상단에서 한 번만 처리하거나 별도 유틸 함수로 추출하는 것이 좋겠습니다.

const EmployeeCard = ({ cardData, variant }: EmployeeCardProps) => {
  const { handleClickBookmark, goToResumeDetailPage } =
    useEmployeeCard(cardData);
+  
+  const formattedVisa = cardData?.visa?.replace(/_/g, '-');

  if (variant === 'horizontal') {
    return (
      // ... 기존 코드 ...
          <Tag
-            value={cardData?.visa?.replace(/_/g, '-')}
+            value={formattedVisa}
            // ... 나머지 props ...
          />
      // ... 기존 코드 ...
    );
  }

  // Column 형 카드
  return (
    // ... 기존 코드 ...
              <Tag
-                value={cardData.visa.replace(/_/g, '-')}
+                value={formattedVisa}
                // ... 나머지 props ...
              />
    // ... 기존 코드 ...
  );
};

Also applies to: 103-103

📜 Review details

Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c64b568 and 82e49ed.

⛔ Files ignored due to path filters (7)
  • src/assets/icons/Home/AppliedIcon.svg is excluded by !**/*.svg
  • src/assets/icons/Home/ApplyIcon.svg is excluded by !**/*.svg
  • src/assets/icons/Home/MatchesIcon.svg is excluded by !**/*.svg
  • src/assets/icons/Home/RecommendPostIcon.svg is excluded by !**/*.svg
  • src/assets/icons/Home/ResumeIcon.svg is excluded by !**/*.svg
  • src/assets/icons/Home/SavedIcon.svg is excluded by !**/*.svg
  • src/assets/icons/Home/SavedPostIcon.svg is excluded by !**/*.svg
📒 Files selected for processing (23)
  • src/components/Common/EmployeeCard/EmployeeCard.tsx (1 hunks)
  • src/components/Common/EmployeeCard/EmployeeCardBookmark.tsx (1 hunks)
  • src/components/Common/EmployeeCard/EmployeeCardEmptyState.tsx (1 hunks)
  • src/components/Common/EmployeeCard/index.ts (1 hunks)
  • src/components/Employer/EmployeeSearch/EmployerEmployeeCardList.tsx (2 hunks)
  • src/components/Home/HomeBannerCarousel.tsx (4 hunks)
  • src/components/Home/HomeCareerPostCard.tsx (1 hunks)
  • src/components/Home/HomeCareerPostingList.tsx (1 hunks)
  • src/components/Home/HomeEmployeeCardList.tsx (1 hunks)
  • src/components/Home/HomeGreetingSection.tsx (1 hunks)
  • src/components/Home/HomeJobPostingList.tsx (1 hunks)
  • src/components/Home/HomeJobPostingSection.tsx (1 hunks)
  • src/components/Home/HomeMenu.tsx (3 hunks)
  • src/components/Home/HomePostCard.tsx (3 hunks)
  • src/components/Home/HomeTopSection.tsx (1 hunks)
  • src/components/PostSearch/CareerCardList.tsx (2 hunks)
  • src/components/PostSearch/CareerSearchSection.tsx (3 hunks)
  • src/constants/translation.ts (1 hunks)
  • src/hooks/useEmployeeCard.ts (1 hunks)
  • src/hooks/useFormattedVisa.ts (1 hunks)
  • src/pages/Home/HomePage.tsx (2 hunks)
  • src/pages/PostSearch/PostSearchPage.tsx (3 hunks)
  • src/pages/Resume/ScrappedJobPostsPage.tsx (3 hunks)
✅ Files skipped from review due to trivial changes (6)
  • src/components/Common/EmployeeCard/index.ts
  • src/components/Home/HomeJobPostingList.tsx
  • src/components/Home/HomeTopSection.tsx
  • src/constants/translation.ts
  • src/components/Common/EmployeeCard/EmployeeCardEmptyState.tsx
  • src/pages/Home/HomePage.tsx
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/pages/Resume/ScrappedJobPostsPage.tsx
  • src/components/Employer/EmployeeSearch/EmployerEmployeeCardList.tsx
  • src/pages/PostSearch/PostSearchPage.tsx
  • src/components/PostSearch/CareerSearchSection.tsx
  • src/components/PostSearch/CareerCardList.tsx
  • src/components/Home/HomeCareerPostingList.tsx
  • src/components/Home/HomeCareerPostCard.tsx
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/components/Home/HomeGreetingSection.tsx (1)
src/store/user.ts (1)
  • useUserStore (12-24)
src/components/Home/HomeEmployeeCardList.tsx (2)
src/types/api/resumes.ts (1)
  • EmployeeResumeListItemType (91-102)
src/components/Common/LoadingItem.tsx (1)
  • LoadingItem (3-9)
🔇 Additional comments (19)
src/components/Home/HomeMenu.tsx (2)

1-4: 아이콘 임포트 변경사항이 적절합니다.

새로운 메뉴 레이블과 일치하도록 아이콘 임포트가 업데이트되었습니다. 네이밍 컨벤션이 일관되고 구문적으로 올바릅니다.


73-88: 렌더링 로직과 스타일링 개선이 우수합니다.

조건부 렌더링을 통해 메뉴 아이템이 없을 때 빈 내비게이션이 렌더링되지 않도록 방어적 프로그래밍을 적용했습니다. 버튼 레이아웃과 텍스트 스타일링도 더 일관되고 모던하게 업데이트되었습니다.

src/hooks/useEmployeeCard.ts (2)

10-13: 북마크 처리 로직이 올바르게 구현되었습니다.

이벤트 전파를 중단하고 뮤테이션을 호출하는 로직이 적절합니다. 클릭 이벤트가 상위 컨테이너로 전파되지 않도록 하여 의도치 않은 네비게이션을 방지합니다.


15-17: 경로 확인 완료: /employer/search/:id 라우트가 정의되어 있습니다.

  • src/router.tsx에서 path="/employer/search/:id"로 명시되어 있어,
    navigate(\/employer/search/${cardData.id}`)` 호출은 올바른 상세 페이지 이동입니다.

따라서 코드 수정은 필요하지 않습니다.

src/components/Home/HomeGreetingSection.tsx (1)

19-23: 헤드라인 메시지 로직이 명확합니다.

사용자 타입에 따른 헤드라인 메시지 분기 처리가 적절하게 구현되었습니다. 기업 사용자에게는 한국어, 일반 사용자에게는 영어로 제공하는 것이 합리적입니다.

src/components/Home/HomePostCard.tsx (3)

17-17: 사용자 타입 결정 로직이 명확합니다.

account_type을 기반으로 userType 문자열을 생성하는 로직이 간단하고 이해하기 쉽습니다.


29-34: 비자 처리 로직 개선이 우수합니다.

useMemo를 사용하여 비자 데이터 처리를 최적화하고, useFormattedVisa 훅을 통해 포맷팅 로직을 중앙화한 것이 좋습니다. 이는 코드의 재사용성과 유지보수성을 크게 향상시킵니다.


38-38: UI 레이아웃 검증 필요

HomePostCard는 현재 HomeJobPostingList.tsx에서만 사용되고 있습니다.
article 컨테이너에서 마진 클래스가 제거되며 카드 간 간격이 달라질 수 있으므로, 실제 UI에서 의도한 간격이 유지되는지 확인해주세요.

  • 확인 위치
    • src/components/Home/HomeJobPostingList.tsx (각 <HomePostCard /> 렌더링)
src/hooks/useFormattedVisa.ts (2)

5-18: 비자 포맷팅 훅이 잘 구현되었습니다.

이 훅은 다음과 같은 장점을 가지고 있습니다:

  • useMemo를 통한 성능 최적화
  • 빈 데이터에 대한 적절한 처리
  • 일관된 문자열 정규화 (underscore → hyphen)
  • 다국어 지원을 위한 번역 상수 활용

15-16: 번역 키 확인 완료
visaAdditional 번역 키가 src/constants/translation.ts에 아래와 같이 정의되어 있어 정상 동작합니다:

  • 파일: src/constants/translation.ts
    visaAdditional: {
      ko: ' 외 ',
      en: ' +',
    },
src/components/Home/HomeBannerCarousel.tsx (4)

15-28: 데이터 패칭 로직이 명확하게 개선되었습니다.

게스트와 로그인 사용자에 대한 조건부 데이터 패칭이 잘 구현되었습니다. 각각의 상태에 맞는 훅을 사용하고, 로딩 상태도 적절히 처리하고 있습니다.


29-49: 캐러셀 구현이 견고합니다.

Embla 캐러셀을 사용한 구현이 잘 되어 있습니다:

  • 자동재생과 드래그 프리 옵션 설정
  • 페이지 변경 감지를 위한 적절한 이벤트 핸들링
  • useEffect에서 이벤트 정리까지 포함한 완전한 구현

101-117: 스타일링 변경사항을 확인해주세요.

배너 이미지에서 둥근 모서리가 제거되고(rounded-lg 클래스 삭제), 컨테이너의 스타일링도 변경되었습니다. 이러한 변경이 전체 디자인 시스템과 일치하는지 확인이 필요합니다.

다음을 확인해주세요:

  1. 디자인 가이드라인과의 일치성
  2. 다른 배너 컴포넌트들과의 일관성

82-97: 로딩 및 빈 상태 처리가 적절합니다.

로딩 상태와 빈 데이터 상태에 대한 UI 처리가 잘 구현되어 있습니다. 다국어 지원을 위한 번역 상수 사용도 적절합니다.

src/components/Common/EmployeeCard/EmployeeCardBookmark.tsx (1)

1-44: 북마크 컴포넌트 구현이 깔끔합니다!

컴포넌트가 잘 구조화되어 있고 다음과 같은 장점이 있습니다:

  • 두 가지 variant를 명확하게 구분하여 처리
  • 적절한 TypeScript 타입 정의와 기본값 설정
  • 기존 코드베이스의 북마크 아이콘 패턴과 일관성 유지
  • 단일 책임 원칙을 잘 따르고 있음
src/components/Home/HomeEmployeeCardList.tsx (1)

17-63: 컴포넌트 구현이 잘 되어 있습니다!

다음과 같은 장점들이 있습니다:

  • 로딩, 빈 상태, 데이터 상태를 명확하게 구분하여 처리
  • 적절한 로딩 인디케이터 사용 (초기 로딩과 추가 로딩 구분)
  • 새로운 공통 컴포넌트들과 깔끔한 통합
  • 가로 스크롤 구현이 적절함
src/components/Common/EmployeeCard/EmployeeCard.tsx (1)

11-126: 전반적으로 잘 구현된 컴포넌트입니다!

다음과 같은 장점들이 있습니다:

  • 두 가지 variant를 명확하게 구분하여 처리
  • 커스텀 훅과 공통 컴포넌트들의 적절한 활용
  • 북마크 기능의 깔끔한 통합
  • 프로필 이미지 fallback 처리가 적절함
  • 클릭 핸들러와 네비게이션 로직이 잘 분리됨
src/components/Home/HomeJobPostingSection.tsx (2)

23-58: 데이터 페칭 조건부 최적화가 잘 되었습니다!

이전 리뷰에서 지적된 무조건적인 훅 호출 문제가 해결되었습니다:

  • 각 훅이 적절한 enabled 조건을 가지고 있음
  • 사용자 타입과 로그인 상태에 따라 필요한 데이터만 요청
  • 불필요한 API 호출 방지가 잘 구현됨

92-157: 역할 기반 UI 렌더링이 잘 구현되었습니다!

다음과 같은 개선사항들이 잘 반영되었습니다:

  • 고용주와 일반 사용자에 대한 명확한 컨텐츠 구분
  • 로그인 상태에 따른 북마크 컨텐츠 조건부 렌더링 (게스트 사용자 문제 해결)
  • 적절한 컴포넌트 사용으로 깔끔한 구조

Comment thread src/components/Common/EmployeeCard/EmployeeCard.tsx
Comment on lines +8 to +17
const getGreetingMessage = (accountType?: UserType) => {
switch (accountType) {
case UserType.OWNER:
return `환영해요, ${name.replace(/-/g, ' ')}님!`;
case UserType.USER:
return `Welcome, ${name.replace(/-/g, ' ')}`;
default:
return 'Welcome!';
}
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

코드 중복이 발생했습니다.

getGreetingMessage 함수의 로직이 src/components/Home/HomeBanner.tsx의 기존 구현과 동일합니다. 코드 중복을 피하기 위해 공통 유틸리티 함수로 추출하는 것을 고려해보세요.

공통 유틸리티 함수를 생성하여 중복을 제거할 수 있습니다:

// src/utils/greeting.ts
export const getGreetingMessage = (accountType?: UserType, name: string) => {
  switch (accountType) {
    case UserType.OWNER:
      return `환영해요, ${name.replace(/-/g, ' ')}님!`;
    case UserType.USER:
      return `Welcome, ${name.replace(/-/g, ' ')}`;
    default:
      return 'Welcome!';
  }
};
🤖 Prompt for AI Agents
In src/components/Home/HomeGreetingSection.tsx around lines 8 to 17, the
getGreetingMessage function duplicates logic already implemented in
src/components/Home/HomeBanner.tsx. To fix this, extract getGreetingMessage into
a shared utility file such as src/utils/greeting.ts, passing both accountType
and name as parameters, then import and use this utility function in both
components to eliminate code duplication.

- 커리어 리스트 요청시 기본 카테고리값 설정
- 커리어 api 훅 주석 수정
- 불필요한 store 조작 코드 제거
@MrMirror21 MrMirror21 requested a review from naarang August 1, 2025 06:17
@MrMirror21 MrMirror21 merged commit 913a5dc into dev Aug 1, 2025
3 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Giggle Aug 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🐞 BugFix Something isn't working ✨ Feature New feature or request 🎨 Html&CSS Markup & Styles

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants