[feat] 사장님 구인구직 UI 구현 및 API 연동 - #60
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthrough매니저용 공고·지원자 관리 기능이 추가됐다. 커서 페이지네이션 API, 생성·수정·마감 및 지원자 상태 변경 흐름, 목록·상세·폼 화면, 매니저 전용 라우팅과 Docbar 탭, 토스트·공통 입력 UI가 구현됐다. Changes매니저 공고·지원자 관리
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
src/app/App.tsx (1)
33-38: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win신규 매니저 공고 페이지 6종에 lazy loading 미적용.
SignupPage는 이미Suspense+lazy 패턴을 쓰고 있는데, 이번에 추가된 매니저 공고·지원자 페이지 6개(ManagerPostingListPage,ManagerPostingCreatePage,ManagerPostingDetailPage,ManagerPostingEditPage,ManagerApplicationListPage,ManagerApplicationDetailPage)는 정적 import라 초기 번들에 그대로 포함됩니다. 매니저 전용 대규모 기능이므로 코드 스플리팅 대상으로 적합합니다.♻️ 제안: React.lazy + Suspense 적용
-import { ManagerPostingListPage } from '`@/pages/manager/posting-list`' -import { ManagerPostingCreatePage } from '`@/pages/manager/posting-create`' -import { ManagerPostingDetailPage } from '`@/pages/manager/posting-detail`' -import { ManagerPostingEditPage } from '`@/pages/manager/posting-edit`' -import { ManagerApplicationListPage } from '`@/pages/manager/application-list`' -import { ManagerApplicationDetailPage } from '`@/pages/manager/application-detail`' +const ManagerPostingListPage = lazy(() => import('`@/pages/manager/posting-list`')) +const ManagerPostingCreatePage = lazy(() => import('`@/pages/manager/posting-create`')) +const ManagerPostingDetailPage = lazy(() => import('`@/pages/manager/posting-detail`')) +const ManagerPostingEditPage = lazy(() => import('`@/pages/manager/posting-edit`')) +const ManagerApplicationListPage = lazy(() => import('`@/pages/manager/application-list`')) +const ManagerApplicationDetailPage = lazy(() => import('`@/pages/manager/application-detail`'))각
<HomeRouteGuard>내부를<Suspense fallback={null}>로 감싸주세요.As per path instructions,
src/app/**: "라우팅 구조가 lazy loading을 활용하는지 확인" 항목에 따라 지적합니다.Also applies to: 171-211, 256-271
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/App.tsx` around lines 33 - 38, Replace the six static manager page imports with React.lazy imports for ManagerPostingListPage, ManagerPostingCreatePage, ManagerPostingDetailPage, ManagerPostingEditPage, ManagerApplicationListPage, and ManagerApplicationDetailPage, following the existing SignupPage pattern. Wrap each corresponding HomeRouteGuard route element in Suspense with a null fallback, preserving the current route configuration and guards.Source: Path instructions
src/pages/manager/posting-list/index.tsx (1)
50-69: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win무한스크롤 sentinel 로직이 두 페이지에 중복 구현됨.
sentinelRef+IntersectionObserver셋업/해제 로직이 두 파일에서 변수명까지 동일하게 반복됩니다. 근본 원인은 공유 훅 부재이므로 하나로 추출하는 것을 권장합니다.
src/pages/manager/posting-list/index.tsx#L50-L69: 이 블록을useInfiniteScrollSentinel({ hasNextPage, isFetchingNextPage, fetchNextPage, isLoading, count: postings.length })같은 공유 훅으로 추출하고sentinelRef만 반환받아 사용.src/pages/manager/application-list/index.tsx#L56-L75: 동일한 공유 훅을 재사용해 중복 블록 제거(count: applications.length로 전달).♻️ 제안: 공유 훅 추출 예시
// src/shared/lib/useInfiniteScrollSentinel.ts export function useInfiniteScrollSentinel({ hasNextPage, isFetchingNextPage, fetchNextPage, isLoading, count, }: { hasNextPage: boolean isFetchingNextPage: boolean fetchNextPage: () => void isLoading: boolean count: number }) { const sentinelRef = useRef<HTMLDivElement>(null) useEffect(() => { const el = sentinelRef.current if (!el) return const observer = new IntersectionObserver( ([entry]) => { if (entry.isIntersecting && hasNextPage && !isFetchingNextPage) { fetchNextPage() } }, { threshold: 0.1 } ) observer.observe(el) return () => observer.disconnect() }, [hasNextPage, isFetchingNextPage, fetchNextPage, isLoading, count]) return sentinelRef }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/pages/manager/posting-list/index.tsx` around lines 50 - 69, Extract the duplicated sentinelRef and IntersectionObserver setup from src/pages/manager/posting-list/index.tsx lines 50-69 into a shared useInfiniteScrollSentinel hook, accepting hasNextPage, isFetchingNextPage, fetchNextPage, isLoading, and count, then return the ref for rendering. Replace the duplicate block in src/pages/manager/application-list/index.tsx lines 56-75 with the same hook, passing applications.length as count; both sites should otherwise preserve the existing fetch and cleanup behavior.src/shared/ui/common/WheelPicker.tsx (1)
87-129: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win선택값이 스크린리더에 노출되지 않아요.
컨테이너에
role="listbox"만 있고 개별 항목엔role/aria-selected가 없으며, 값 변경 시(ArrowUp/ArrowDown) 포커스나aria-activedescendant갱신도 없습니다. 근무시간처럼 필수 값을 고르는 컨트롤인데, 스크린리더 사용자는 현재 선택값을 전혀 알 수 없어 폼 작성을 완료하기 어렵습니다.listbox대신 값-휠 특성에 맞는slider/spinbutton+aria-valuenow/aria-valuetext패턴이 더 적합합니다.♿ 제안: spinbutton 시맨틱 추가
<div data-vaul-no-drag className={cn( 'relative touch-none select-none overflow-hidden focus:outline-none', className )} style={{ height: itemHeight * visibleCount }} aria-label={ariaLabel} - role="listbox" + role="slider" + aria-valuemin={0} + aria-valuemax={items.length - 1} + aria-valuenow={selectedIndex} + aria-valuetext={items[selectedIndex]} tabIndex={0}
**/*.tsx: "a11y: 서비스를 막는 수준(의미 있는 버튼/폼/이미지, 키보드 트랩 등)만" 지침에 근거해 필수 값-선택 컨트롤의 선택값 미노출을 지적합니다.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/shared/ui/common/WheelPicker.tsx` around lines 87 - 129, Update the WheelPicker container’s accessibility semantics from a bare listbox to a value-selection control such as spinbutton, exposing the current selection through aria-valuenow and aria-valuetext. Ensure handleKeyDown and any pointer-driven value updates keep these attributes synchronized so screen readers announce the selected item, while preserving the existing interaction and visual behavior.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/features/manager/posting/types/dto.ts`:
- Around line 231-240: Update adaptApplicant so a missing dto.gender does not
default to ‘남성’; preserve ‘여성’ for GENDER_FEMALE and map absent gender to the
same placeholder convention used for other missing applicant fields, such as
‘-’.
In `@src/features/manager/posting/ui/PostingFormFields.tsx`:
- Around line 77-88: 공고 제목, 급여, 상세내용 입력 요소에 접근 가능한 이름을 추가하세요. PostingFormFields의
해당 input/textarea 각각에 화면에 표시되는 Section 라벨과 일치하는 aria-label을 지정하고, 기존 값·변경 처리·오류
스타일은 유지하세요.
---
Nitpick comments:
In `@src/app/App.tsx`:
- Around line 33-38: Replace the six static manager page imports with React.lazy
imports for ManagerPostingListPage, ManagerPostingCreatePage,
ManagerPostingDetailPage, ManagerPostingEditPage, ManagerApplicationListPage,
and ManagerApplicationDetailPage, following the existing SignupPage pattern.
Wrap each corresponding HomeRouteGuard route element in Suspense with a null
fallback, preserving the current route configuration and guards.
In `@src/pages/manager/posting-list/index.tsx`:
- Around line 50-69: Extract the duplicated sentinelRef and IntersectionObserver
setup from src/pages/manager/posting-list/index.tsx lines 50-69 into a shared
useInfiniteScrollSentinel hook, accepting hasNextPage, isFetchingNextPage,
fetchNextPage, isLoading, and count, then return the ref for rendering. Replace
the duplicate block in src/pages/manager/application-list/index.tsx lines 56-75
with the same hook, passing applications.length as count; both sites should
otherwise preserve the existing fetch and cleanup behavior.
In `@src/shared/ui/common/WheelPicker.tsx`:
- Around line 87-129: Update the WheelPicker container’s accessibility semantics
from a bare listbox to a value-selection control such as spinbutton, exposing
the current selection through aria-valuenow and aria-valuetext. Ensure
handleKeyDown and any pointer-driven value updates keep these attributes
synchronized so screen readers announce the selected item, while preserving the
existing interaction and visual behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 0826f7f3-5fd7-49f8-8037-ab543b407274
⛔ Files ignored due to path filters (11)
src/assets/icons/doc/Applicant.svgis excluded by!**/*.svgsrc/assets/icons/posting/Alert.svgis excluded by!**/*.svgsrc/assets/icons/posting/Calendar.svgis excluded by!**/*.svgsrc/assets/icons/posting/CheckCircle.svgis excluded by!**/*.svgsrc/assets/icons/posting/ChevronRight.svgis excluded by!**/*.svgsrc/assets/icons/posting/Clock.svgis excluded by!**/*.svgsrc/assets/icons/posting/Close.svgis excluded by!**/*.svgsrc/assets/icons/posting/Lock.svgis excluded by!**/*.svgsrc/assets/icons/posting/Person.svgis excluded by!**/*.svgsrc/assets/icons/posting/Plus.svgis excluded by!**/*.svgsrc/assets/icons/posting/Write.svgis excluded by!**/*.svg
📒 Files selected for processing (67)
src/app/App.tsxsrc/features/manager/api/posting.tssrc/features/manager/home/hooks/useManagedPostingsViewModel.tssrc/features/manager/home/types/posting.tssrc/features/manager/posting/api/application.tssrc/features/manager/posting/api/posting.tssrc/features/manager/posting/hooks/mutation/useClosePostingMutation.tssrc/features/manager/posting/hooks/mutation/useCreatePostingMutation.tssrc/features/manager/posting/hooks/mutation/useUpdateApplicationStatusMutation.tssrc/features/manager/posting/hooks/mutation/useUpdatePostingMutation.tssrc/features/manager/posting/hooks/query/useManagerPostingDetailQuery.tssrc/features/manager/posting/hooks/query/useManagerPostingsQuery.tssrc/features/manager/posting/hooks/query/usePostingApplicationDetailQuery.tssrc/features/manager/posting/hooks/query/usePostingApplicationsQuery.tssrc/features/manager/posting/hooks/query/useWorkspaceFilterOptions.tssrc/features/manager/posting/hooks/useApplicationDetailViewModel.tssrc/features/manager/posting/hooks/useApplicationListViewModel.tssrc/features/manager/posting/hooks/usePostingDetailViewModel.tssrc/features/manager/posting/hooks/usePostingForm.tssrc/features/manager/posting/hooks/usePostingListViewModel.tssrc/features/manager/posting/lib/applicationStatus.tssrc/features/manager/posting/lib/buildPostingRequest.tssrc/features/manager/posting/lib/postingErrorMessage.tssrc/features/manager/posting/lib/postingStatus.tssrc/features/manager/posting/types/dto.tssrc/features/manager/posting/types/posting.tssrc/features/manager/posting/ui/ApplicantCard.tsxsrc/features/manager/posting/ui/FilterBar.tsxsrc/features/manager/posting/ui/HiringActionBar.tsxsrc/features/manager/posting/ui/ManagerApplicationStatusBadge.tsxsrc/features/manager/posting/ui/ManagerPostingStatusBadge.tsxsrc/features/manager/posting/ui/PostingFormFields.tsxsrc/features/manager/posting/ui/PostingListCard.tsxsrc/features/manager/posting/ui/ScheduleEditor.tsxsrc/features/user/home/applied-stores/types/application.tssrc/pages/manager/application-detail/index.tsxsrc/pages/manager/application-list/index.tsxsrc/pages/manager/posting-create/index.tsxsrc/pages/manager/posting-detail/index.tsxsrc/pages/manager/posting-edit/index.tsxsrc/pages/manager/posting-list/index.tsxsrc/pages/manager/worker-schedule/components/FixedScheduleDateSection.tsxsrc/pages/manager/worker-schedule/components/GeneralScheduleDateSection.tsxsrc/pages/manager/worker-schedule/components/WorkTimeRangeField.tsxsrc/shared/constants/payment.tssrc/shared/constants/routes.tssrc/shared/constants/workingDays.tssrc/shared/lib/cursorPage.tssrc/shared/lib/formatKoreanWorkTime.tssrc/shared/lib/formatRelativeTime.tssrc/shared/lib/queryKeys.tssrc/shared/lib/toTimeOfDay.tssrc/shared/stores/useDocStore.tssrc/shared/stores/useToastStore.tssrc/shared/types/applicationStatus.tssrc/shared/types/tab.tssrc/shared/types/workTime.tssrc/shared/ui/common/Docbar.tsxsrc/shared/ui/common/Navbar.tsxsrc/shared/ui/common/SelectDropdown.tsxsrc/shared/ui/common/Skeleton.tsxsrc/shared/ui/common/Toast.tsxsrc/shared/ui/common/ToastViewport.tsxsrc/shared/ui/common/WheelPicker.tsxsrc/shared/ui/common/WorkTimePickerDrawer.tsxstorybook/stories/Docbar.stories.tsxtailwind.config.js
| <Section label="공고 제목" required error={errors.title}> | ||
| <input | ||
| type="text" | ||
| value={values.title} | ||
| placeholder="예: 주말 홀서빙 구합니다" | ||
| onChange={e => form.setTitle(e.target.value)} | ||
| className={cn( | ||
| inputClassName, | ||
| errors.title ? 'border-error' : 'border-line-1 focus:border-main' | ||
| )} | ||
| /> | ||
| </Section> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
필수 입력 필드에 접근성 이름이 없어요.
공고 제목, 급여, 상세내용 섹션의 input/textarea는 Section의 시각적 <h2> 라벨과 프로그램적으로 연결되어 있지 않습니다(htmlFor/id 없음, aria-label도 없음). 스크린리더 사용자는 어떤 값을 입력해야 하는지 알 수 없어 공고 등록/수정을 완료하지 못할 수 있습니다. 반면 업장 선택은 SelectDropdown에 ariaLabel이 있어 문제없습니다.
♿ 최소 수정안 (각 input에 aria-label 추가)
<Section label="공고 제목" required error={errors.title}>
<input
type="text"
+ aria-label="공고 제목"
value={values.title} <input
type="text"
inputMode="numeric"
+ aria-label="급여"
value={ <textarea
value={values.description}
rows={5}
+ aria-label="상세내용"
placeholder="근무 조건, 우대 사항 등을 자유롭게 작성해 주세요"**/*.tsx: "a11y: 서비스를 막는 수준(의미 있는 버튼/폼/이미지, 키보드 트랩 등)만." 지침에 근거해 필수 폼 입력의 이름 부재를 지적합니다.
Also applies to: 116-139, 141-154
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/features/manager/posting/ui/PostingFormFields.tsx` around lines 77 - 88,
공고 제목, 급여, 상세내용 입력 요소에 접근 가능한 이름을 추가하세요. PostingFormFields의 해당 input/textarea
각각에 화면에 표시되는 Section 라벨과 일치하는 aria-label을 지정하고, 기존 값·변경 처리·오류 스타일은 유지하세요.
Source: Path instructions
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/features/manager/posting/ui/ScheduleEditor.tsx (1)
216-229: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win정수가 아닌 모집 인원을 다른 값으로 변환하지 마세요.
type="number"는1.5,1e2,-1같은 값을 입력할 수 있습니다. Line 226의 정규식은 이를 각각15,12,1로 바꿉니다. 사용자가 의도하지 않은positionsNeeded가 폼 상태에 저장됩니다.정수만 허용한다면
type="text"와inputMode="numeric"을 사용하세요. 또는 원본 값을 정수로 검증하고 유효하지 않으면 상태를 갱신하지 마세요.수정 예시
- type="number" - min={1} + type="text" + inputMode="numeric"🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/features/manager/posting/ui/ScheduleEditor.tsx` around lines 216 - 229, Update the positionsNeeded input handler in ScheduleEditor so invalid or non-integer values are not transformed into different numbers and stored in form state. Validate the original input as a non-negative integer, and only call form.updateSchedule when it is valid; preserve the existing empty-display behavior for zero.
🧹 Nitpick comments (3)
src/features/job-lookup-map/test/lib/applyPostingError.test.ts (1)
24-36: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winHTTP 429 분기를 독립적으로 검증하세요.
이 fixture는
status: 429와code: 'E001'을 함께 설정합니다. 두 조건 모두retryable: true를 만들기 때문에 HTTP 429 조건이 제거되어도 테스트가 통과합니다.code를 비재시도 코드로 변경하거나 생략하세요.수정 예시
axiosError(429, { - code: 'E001', + code: 'B001', message: '요청이 너무 많습니다. 잠시 후 다시 시도해주세요.', })🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/features/job-lookup-map/test/lib/applyPostingError.test.ts` around lines 24 - 36, Update the HTTP 429 test for resolveApplyPostingError so its fixture does not also use retryable code E001; omit the code or use a non-retryable code, while preserving status 429 and the expected retryable: true result to verify the HTTP status branch independently.storybook/stories/PostingListCard.stories.tsx (1)
4-5: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win기능 공개 API를 통해 가져오세요.
이 스토리는 feature 외부에 있습니다.
ui/PostingListCard와types/posting을 직접 import하면 내부 경로가 외부 계약이 됩니다.
src/features/manager/posting/index.ts에서 필요한 심볼을 export한 뒤, 이 스토리는 공개 API만 import하세요.수정 예시
-import { PostingListCard } from '../../src/features/manager/posting/ui/PostingListCard' -import type { PostingListItem } from '../../src/features/manager/posting/types/posting' +import { + PostingListCard, + type PostingListItem, +} from '../../src/features/manager/posting'As per path instructions,
src/features/**는 외부에index.ts공개 API를 통해서만 노출해야 합니다.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@storybook/stories/PostingListCard.stories.tsx` around lines 4 - 5, Update the posting feature’s public API in src/features/manager/posting/index.ts to export PostingListCard and PostingListItem, then change the PostingListCard story imports to use that feature entry point instead of ui/PostingListCard and types/posting internal paths.Source: Path instructions
src/pages/manager/posting-create/index.tsx (1)
6-6: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift공고 생성 흐름을 feature의 public API로 이동하세요.
Line 6은 page가 feature 내부
lib모듈을 직접 import하게 합니다. Lines 37-42는 서버 오류를 공고 폼 오류 상태로 변환합니다. 이 작업은 page의 조합 책임을 넘습니다.
useCreatePostingFlow같은 feature hook을 만들고index.ts에서만 노출하세요. 이 hook이 mutation callback,resolvePostingFormError,setServerErrors를 관리하게 하세요. page는 성공 후 이동 처리와 UI 조합만 담당해야 합니다.경로 지침의 “Public API(index.ts)를 통해서만 외부에 노출” 및 “페이지 컴포넌트가 비즈니스 로직 없이 조합(Composition)만 하는지” 규칙을 적용했습니다.
Also applies to: 37-44
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/pages/manager/posting-create/index.tsx` at line 6, Move the posting-creation mutation and server-error handling from the page into a feature hook such as useCreatePostingFlow, including resolvePostingFormError and setServerErrors. Export the hook through the feature’s index.ts public API, remove the page’s direct lib import, and leave the page responsible only for invoking the flow, handling success navigation, and composing the UI.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/pages/manager/posting-create/index.tsx`:
- Around line 37-44: Prevent stale server errors from being applied by updating
the submission flow around the onError handler and form state management: either
keep the confirmation modal and form editing locked until the request completes,
or capture the form version at submission and call
form.setServerErrors(fieldErrors) only when that version still matches the
current form version; preserve showing the resolved error message via showToast.
---
Outside diff comments:
In `@src/features/manager/posting/ui/ScheduleEditor.tsx`:
- Around line 216-229: Update the positionsNeeded input handler in
ScheduleEditor so invalid or non-integer values are not transformed into
different numbers and stored in form state. Validate the original input as a
non-negative integer, and only call form.updateSchedule when it is valid;
preserve the existing empty-display behavior for zero.
---
Nitpick comments:
In `@src/features/job-lookup-map/test/lib/applyPostingError.test.ts`:
- Around line 24-36: Update the HTTP 429 test for resolveApplyPostingError so
its fixture does not also use retryable code E001; omit the code or use a
non-retryable code, while preserving status 429 and the expected retryable: true
result to verify the HTTP status branch independently.
In `@src/pages/manager/posting-create/index.tsx`:
- Line 6: Move the posting-creation mutation and server-error handling from the
page into a feature hook such as useCreatePostingFlow, including
resolvePostingFormError and setServerErrors. Export the hook through the
feature’s index.ts public API, remove the page’s direct lib import, and leave
the page responsible only for invoking the flow, handling success navigation,
and composing the UI.
In `@storybook/stories/PostingListCard.stories.tsx`:
- Around line 4-5: Update the posting feature’s public API in
src/features/manager/posting/index.ts to export PostingListCard and
PostingListItem, then change the PostingListCard story imports to use that
feature entry point instead of ui/PostingListCard and types/posting internal
paths.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: d869e1b9-5b31-4d27-b90c-a5bb87a7e025
📒 Files selected for processing (30)
src/features/job-lookup-map/hooks/useApplyPosting.tssrc/features/job-lookup-map/lib/applyPostingError.tssrc/features/job-lookup-map/test/lib/applyPostingError.test.tssrc/features/manager/posting/api/application.tssrc/features/manager/posting/hooks/mutation/useCreatePostingMutation.tssrc/features/manager/posting/hooks/mutation/useUpdatePostingMutation.tssrc/features/manager/posting/hooks/query/usePostingApplicationsQuery.tssrc/features/manager/posting/hooks/useApplicationListViewModel.tssrc/features/manager/posting/hooks/usePostingForm.tssrc/features/manager/posting/lib/postingErrorMessage.tssrc/features/manager/posting/test/api/application.test.tssrc/features/manager/posting/test/lib/buildPostingRequest.test.tssrc/features/manager/posting/test/lib/postingErrorMessage.test.tssrc/features/manager/posting/test/types/dto.test.tssrc/features/manager/posting/types/dto.tssrc/features/manager/posting/types/posting.tssrc/features/manager/posting/ui/FilterBar.tsxsrc/features/manager/posting/ui/PostingFormFields.tsxsrc/features/manager/posting/ui/PostingListCard.tsxsrc/features/manager/posting/ui/ScheduleEditor.tsxsrc/pages/manager/application-list/index.tsxsrc/pages/manager/posting-create/index.tsxsrc/pages/manager/posting-detail/index.tsxsrc/pages/manager/posting-edit/index.tsxsrc/pages/user/job-lookup-map-apply/index.tsxsrc/shared/lib/queryKeys.tssrc/shared/lib/utils/errorUtils.tssrc/shared/types/common.tsstorybook/stories/PostingListCard.stories.tsxstorybook/stories/ScheduleEditor.stories.tsx
💤 Files with no reviewable changes (2)
- src/features/manager/posting/hooks/mutation/useCreatePostingMutation.ts
- src/features/manager/posting/hooks/mutation/useUpdatePostingMutation.ts
🚧 Files skipped from review as they are similar to previous changes (7)
- src/features/manager/posting/ui/PostingListCard.tsx
- src/pages/manager/posting-edit/index.tsx
- src/features/manager/posting/types/posting.ts
- src/pages/manager/application-list/index.tsx
- src/features/manager/posting/ui/PostingFormFields.tsx
- src/features/manager/posting/types/dto.ts
- src/features/manager/posting/ui/FilterBar.tsx
ID
변경 내용
MANAGER - 업장 관리자 공고 관리 API에 연동 (조회·등록·수정·마감·채용 결정)내 공고/지원자탭 추가 및 라우트 등록구현 사항
화면 · 라우팅
features/manager/posting슬라이스 신규 구성 (api/types/lib/hooks/ui):postingId보다 먼저 매칭되도록 라우트 순서 배치type="time"대신 기존 휠 픽커(WorkTimePickerDrawer)로 통일API 연동
useInfiniteQuery+ IntersectionObserver 커서 무한스크롤createSchedules/updateSchedules/deleteScheduleIds3분할로 변환 (lib/buildPostingRequest.ts)types/dto.ts의 어댑터로 일원화.DescribedEnumDto래퍼(status.value) 해제,contact→phoneNumber·birthday→birthDate·GENDER_MALE→남성·자격증 필드명 매핑 처리queryKeys.posting하위로 통일해, 공고 변경 시 목록·상세·홈 카드를 한 번에 무효화shared 승격 / 버그 수정
CommonApiResponse래핑 여부가 엔드포인트마다 달라, 두 형태를 모두 정규화하는unwrapCursorPage추가HH:mm:ss로 내려주어 화면에07:00:00~12:00:00으로 노출되고 시간 픽커 초기값이 깨지던 문제를toTimeOfDay로 정규화ApplicationApiStatus타입을 shared로 추출해 유저/매니저 양측에서 재사용구현 시연 (필요 시)
480.mov
Summary by CodeRabbit
새로운 기능
개선