Feat: 모의지원 전체 흐름 연결 및 재도전·삭제 기능 개선 [JDDEV-98]#103
Hidden character warning
Conversation
…ome_retry—api-feat # Conflicts: # jobdri/src/app/mockApply/[mockApplyId]/page.tsx # jobdri/src/components/common/lnb/Lnb.tsx
📝 WalkthroughWalkthroughThe PR updates mock-apply question persistence, retry and deletion flows, result navigation, LNB recent-item and notification handling, ModalNotice layouts, confirmation dialogs, and viewport-based page containers. ChangesMock apply workflow
Sidebar and notification workflows
Modal and viewport UI
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 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: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
jobdri/src/app/mockApply/[mockApplyId]/result/page.tsx (1)
103-121: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winRetry failure produces no user feedback — the
catchis unreachable.
reApply(inuseReApply) swallows errors internally and returnsnullrather than throwing, soawait reApply(...)never rejects and thiscatchnever runs. On a failed retry the modal stays open and no error toast is shown. Gate on the return value instead.🐛 Proposed fix
- try { - await reApply(resolvedMockApplyId, { - getRedirectPath: (result) => - `/mockApply/${result.mockApplyId}?retry=1&sequence=${result.sequence}`, - }); - } catch { - setIsRetryModalOpen(false); - showTopToast("재도전을 시작하지 못했어요. 잠시 후 다시 시도해주세요."); - } + const result = await reApply(resolvedMockApplyId, { + getRedirectPath: (retryResult) => + `/mockApply/${retryResult.mockApplyId}?retry=1&sequence=${retryResult.sequence}`, + }); + + if (!result) { + setIsRetryModalOpen(false); + showTopToast("재도전을 시작하지 못했어요. 잠시 후 다시 시도해주세요."); + }🤖 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 `@jobdri/src/app/mockApply/`[mockApplyId]/result/page.tsx around lines 103 - 121, Update handleRetryConfirm to inspect the value returned by reApply instead of relying on the unreachable catch block. When reApply returns null or another failure result, close the retry modal and show the existing failure toast; preserve the redirect callback and successful retry behavior.
🤖 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 `@jobdri/src/app/credit/page.tsx`:
- Around line 48-49: Update the parent content container’s overflow behavior
near the fixed-width main element to allow horizontal scrolling instead of
clipping. Change the `overflow-x-hidden` behavior on the surrounding `<div>` to
`overflow-x-auto`, while preserving the existing vertical scrolling and `main`
width constraints.
In `@jobdri/src/components/common/lnb/Lnb.tsx`:
- Around line 262-273: Guard newNotification.type in the
subscribeToNotificationStream callback before invoking startsWith, preserving
the loadRecentItems refresh when the type is present and starts with
"ANALYSIS_ASYNC_". Treat missing types as non-matching so the notification is
still mapped and stored without throwing.
- Around line 285-308: Update the handleMockApplyDeleted handler in the Lnb
useEffect to select the first remaining recent item when the deleted item was
selected, matching loadRecentItems’s mappedItems[0]?.id ?? "" fallback; retain
the current selection when a different item is deleted and clear it only when no
items remain.
---
Outside diff comments:
In `@jobdri/src/app/mockApply/`[mockApplyId]/result/page.tsx:
- Around line 103-121: Update handleRetryConfirm to inspect the value returned
by reApply instead of relying on the unreachable catch block. When reApply
returns null or another failure result, close the retry modal and show the
existing failure toast; preserve the redirect callback and successful retry
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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 9f625ec5-14b4-4107-999b-7e98b826d8df
📒 Files selected for processing (25)
jobdri/src/app/credit/page.tsxjobdri/src/app/mockApply/[mockApplyId]/(jd)/jd-review/page.tsxjobdri/src/app/mockApply/[mockApplyId]/page.tsxjobdri/src/app/mockApply/[mockApplyId]/result/page.tsxjobdri/src/app/mockApply/[mockApplyId]/result/resume-analysis-loading/ResumeAnalysisLoadingPageClient.tsxjobdri/src/app/mockApply/job/create/page.tsxjobdri/src/app/mockApply/job/loading/page.tsxjobdri/src/app/mockApply/job/review/page.tsxjobdri/src/app/page.tsxjobdri/src/components/common/MockApplyTemplate.tsxjobdri/src/components/common/lnb/Lnb.tsxjobdri/src/components/common/lnb/LnbFolded.tsxjobdri/src/components/common/lnb/LnbNotification.tsxjobdri/src/components/common/lnb/LnbShared.tsxjobdri/src/components/common/lnb/index.tsjobdri/src/components/common/modal/ModalNotice.tsxjobdri/src/components/common/searchbar/SearchBar.tsxjobdri/src/components/mockApply/ResumeAnalysisLoading.tsxjobdri/src/components/mockApply/home/ResultApplicationCard.tsxjobdri/src/components/mockApply/home/ResultApplicationList.tsxjobdri/src/components/mockApply/home/applicationHomeUtils.tsjobdri/src/hooks/useReApply.tsjobdri/src/lib/api/mockApplies.tsjobdri/src/lib/api/notification.tsjobdri/src/lib/api/questions.ts
| <div className="min-h-0 min-w-0 flex-1 overflow-x-hidden overflow-y-auto"> | ||
| <main className="mx-auto w-full max-w-[1320px] min-w-[1060px] px-18 pt-12 pb-60"> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Allow horizontal scrolling for the fixed-width content.
main remains min-w-[1060px], but its parent uses overflow-x-hidden. When the viewport is narrower than the LNB plus 1060px, the right side of the credit content is clipped and cannot be reached. Use overflow-x-auto or relax the minimum width at smaller breakpoints.
Proposed fix
- <div className="min-h-0 min-w-0 flex-1 overflow-x-hidden overflow-y-auto">
+ <div className="min-h-0 min-w-0 flex-1 overflow-x-auto overflow-y-auto">📝 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.
| <div className="min-h-0 min-w-0 flex-1 overflow-x-hidden overflow-y-auto"> | |
| <main className="mx-auto w-full max-w-[1320px] min-w-[1060px] px-18 pt-12 pb-60"> | |
| <div className="min-h-0 min-w-0 flex-1 overflow-x-auto overflow-y-auto"> | |
| <main className="mx-auto w-full max-w-[1320px] min-w-[1060px] px-18 pt-12 pb-60"> |
🤖 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 `@jobdri/src/app/credit/page.tsx` around lines 48 - 49, Update the parent
content container’s overflow behavior near the fixed-width main element to allow
horizontal scrolling instead of clipping. Change the `overflow-x-hidden`
behavior on the surrounding `<div>` to `overflow-x-auto`, while preserving the
existing vertical scrolling and `main` width constraints.
| void loadInitialNotifications(); | ||
|
|
||
| const unsubscribe = subscribeToNotificationStream( | ||
| (newNotification) => { | ||
| const mappedNewItem = mapApiToLnbItem(newNotification); | ||
| setNotificationItems((prev) => [mappedNewItem, ...prev]); | ||
| setHasNotification(true); | ||
|
|
||
| if (newNotification.type.startsWith("ANALYSIS_ASYNC_")) { | ||
| void loadRecentItems(); | ||
| } | ||
| }, |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
Guard newNotification.type before calling .startsWith.
mapNotificationType and LnbNotificationListItem both treat the notification type/apiType field as potentially absent (apiType?: string, notificationItem.type ?? "normal"), but this call doesn't guard it. If a payload lacks type, this throws inside the onmessage handler in notification.ts, which swallows it and mislogs it as a parse failure — silently skipping the recent-items refresh.
🛡️ Proposed fix
- if (newNotification.type.startsWith("ANALYSIS_ASYNC_")) {
+ if (newNotification.type?.startsWith("ANALYSIS_ASYNC_")) {
void loadRecentItems();
}📝 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.
| void loadInitialNotifications(); | |
| const unsubscribe = subscribeToNotificationStream( | |
| (newNotification) => { | |
| const mappedNewItem = mapApiToLnbItem(newNotification); | |
| setNotificationItems((prev) => [mappedNewItem, ...prev]); | |
| setHasNotification(true); | |
| if (newNotification.type.startsWith("ANALYSIS_ASYNC_")) { | |
| void loadRecentItems(); | |
| } | |
| }, | |
| void loadInitialNotifications(); | |
| const unsubscribe = subscribeToNotificationStream( | |
| (newNotification) => { | |
| const mappedNewItem = mapApiToLnbItem(newNotification); | |
| setNotificationItems((prev) => [mappedNewItem, ...prev]); | |
| setHasNotification(true); | |
| if (newNotification.type?.startsWith("ANALYSIS_ASYNC_")) { | |
| void loadRecentItems(); | |
| } | |
| }, |
🤖 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 `@jobdri/src/components/common/lnb/Lnb.tsx` around lines 262 - 273, Guard
newNotification.type in the subscribeToNotificationStream callback before
invoking startsWith, preserving the loadRecentItems refresh when the type is
present and starts with "ANALYSIS_ASYNC_". Treat missing types as non-matching
so the notification is still mapped and stored without throwing.
| useEffect(() => { | ||
| const handleMockApplyDeleted = (event: Event) => { | ||
| const mockApplyId = (event as CustomEvent<number>).detail; | ||
|
|
||
| setRecentItems((current) => | ||
| current.filter((item) => item.id !== String(mockApplyId)), | ||
| ); | ||
| setSelectedRecentItemId((current) => | ||
| current === String(mockApplyId) ? "" : current, | ||
| ); | ||
| }; | ||
|
|
||
| window.addEventListener( | ||
| MOCK_APPLY_DELETED_EVENT, | ||
| handleMockApplyDeleted, | ||
| ); | ||
|
|
||
| return () => { | ||
| window.removeEventListener( | ||
| MOCK_APPLY_DELETED_EVENT, | ||
| handleMockApplyDeleted, | ||
| ); | ||
| }; | ||
| }, []); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Reselect fallback item after deleting the selected recent item.
Unlike loadRecentItems (which falls back to mappedItems[0]?.id ?? "" when the current selection is invalid), this handler just clears selectedRecentItemId to "" when the deleted item was selected, leaving nothing highlighted until the next full refresh.
♻️ Proposed fix
setRecentItems((current) =>
current.filter((item) => item.id !== String(mockApplyId)),
);
setSelectedRecentItemId((current) =>
- current === String(mockApplyId) ? "" : current,
+ current === String(mockApplyId)
+ ? (recentItems.find((item) => item.id !== String(mockApplyId))?.id ?? "")
+ : current,
);🤖 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 `@jobdri/src/components/common/lnb/Lnb.tsx` around lines 285 - 308, Update the
handleMockApplyDeleted handler in the Lnb useEffect to select the first
remaining recent item when the deleted item was selected, matching
loadRecentItems’s mappedItems[0]?.id ?? "" fallback; retain the current
selection when a different item is deleted and clear it only when no items
remain.
🔗 관련 이슈
📝 개요
⌨️ 작업 상세 내용
sequence기반 지원 회차 표시ModalNotice컴포넌트로 통일💡 코드 설명 및 참고사항
🔍 리뷰 요구사항 (Reviewers)
Summary by CodeRabbit