Skip to content

Feature/#73 page route feat#74

Merged
yiyoonseo merged 7 commits into
developfrom
feature/#73-page_route-feat
May 29, 2026
Merged

Feature/#73 page route feat#74
yiyoonseo merged 7 commits into
developfrom
feature/#73-page_route-feat

Conversation

@yiyoonseo
Copy link
Copy Markdown
Contributor

@yiyoonseo yiyoonseo commented May 29, 2026

🔗 관련 이슈

#73

📝 개요

⌨️ 작업 상세 내용

라우팅 구조 개편

  • /apply/virtual/[id]/.../mockApply/actual/[mockApplyId]/...
  • 결과 페이지 동적 파라미터를 [id][jobPostingId] 로 명확화
    • URL: /mockApply/actual/result/[jobPostingId]?sequence=N&totalCount=N
  • 분석 API를 mockApplyId 기반에서 jobPostingId + sequence 기반으로 변경
    • GET /api/job-postings/{jobPostingId}/analysis?sequence=N
  • Trybar가 applyId 직접 조회 대신 totalCount prop을 받아 렌더링하도록 변경

폴더 구조 정리

  • src/components/apply/src/components/mockApply/
  • src/components/mock-application/src/components/mockApply/
  • src/app/apply/src/app/mockApply/

로그인 방어 로직

  • 액세스 토큰을 localStoragecookie에도 저장
  • middleware.ts 추가 — 비인증 사용자 접근 시 /login?redirect= 로 리다이렉트

버그 수정 / 소소한 개선

  • MockApplicationHomePageClient hydration 에러 수정
  • InputMain height 고정 (h-12)

💡 코드 설명 및 참고사항

📸 스크린샷 (UI 변경 시)

🔍 리뷰 요구사항 (Reviewers)

  • [ ]

⚠️ 로컬 실행 시 유의사항

테스트 체크리스트

  • 로그인 없이 접근 시 로그인 페이지로 리다이렉트되는지
  • 모의 지원 완료 후 결과 페이지(/mockApply/actual/result/{jobPostingId})로 정상 이동하는지
  • Trybar 회차 클릭 시 해당 회차 분석 결과가 표시되는지
  • 홈 카드 클릭 시 최신 회차 결과로 이동하는지
  • 재지원하기 정상 동작하는지

Summary by CodeRabbit

  • New Features

    • Introduced a dedicated "mock apply" flow with a redesigned home experience, progress steps, saved-applications modal, and interactive application cards (resume/delete/retry).
    • App now checks auth on requests and persists access tokens in cookies for smoother sessions.
  • Bug Fixes

    • Fixed input field height rendering.
  • Refactor

    • Reworked routes and navigation to the new mock-apply scheme and updated related UI links and redirects.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1179da62-a772-4eff-94b0-06d62df5e3ad

📥 Commits

Reviewing files that changed from the base of the PR and between 38d1984 and d0da52c.

📒 Files selected for processing (19)
  • jobdri/src/app/mockApply/actual/[mockApplyId]/(jd)/jd-input/JdInputPageClient.tsx
  • jobdri/src/app/mockApply/actual/[mockApplyId]/(jd)/jd-input/page.tsx
  • jobdri/src/app/mockApply/actual/[mockApplyId]/questions/QuestionsPageClient.tsx
  • jobdri/src/app/mockApply/actual/[mockApplyId]/write/WritePageClient.tsx
  • jobdri/src/components/common/lnb/Lnb.tsx
  • jobdri/src/components/mockApply/MockApplicationHomePageClient.tsx
  • jobdri/src/components/mockApply/QuestionGenerationLoading.tsx
  • jobdri/src/components/mockApply/home/ApplicationCardShared.tsx
  • jobdri/src/components/mockApply/home/ApplicationKebabButton.tsx
  • jobdri/src/components/mockApply/home/ApplicationProgressSteps.tsx
  • jobdri/src/components/mockApply/home/EmptyApplicationState.tsx
  • jobdri/src/components/mockApply/home/MockApplicationHomeIntro.tsx
  • jobdri/src/components/mockApply/home/PausedApplicationCard.tsx
  • jobdri/src/components/mockApply/home/ResultApplicationCard.tsx
  • jobdri/src/components/mockApply/home/SavedApplicationsModal.tsx
  • jobdri/src/components/mockApply/home/applicationHomeUtils.ts
  • jobdri/src/components/mockApply/home/homeSteps.ts
  • jobdri/src/components/mockApply/home/index.ts
  • jobdri/src/components/mockApply/home/types.ts

📝 Walkthrough

Walkthrough

Redirect root to /mockApply, move apply flow to /mockApply and /mockApply/actual (rename route params), rewire imports and navigation, add mockApply home UI and utilities, and introduce cookie-backed auth helpers plus Next.js middleware that redirects unauthenticated requests to /login.

Changes

Route Migration to mockApply Structure

Layer / File(s) Summary
Root and Home Page Entry Points
jobdri/src/app/page.tsx, jobdri/src/app/apply/page.tsx, jobdri/src/app/mockApply/page.tsx
Root page redirects to /mockApply, old /apply page removed, new /mockApply page added rendering MockApplicationHomePageClient.
JD input & review flow
jobdri/src/app/mockApply/actual/[mockApplyId]/(jd)/*
JD input/review client and pages migrated to /mockApply/actual/[mockApplyId]/*, route param renamed to mockApplyId, imports switched to mockApply modules, and navigation targets updated.
Questions & Write flow
jobdri/src/app/mockApply/actual/[mockApplyId]/questions/*, jobdri/src/app/mockApply/actual/[mockApplyId]/write/*
Questions and write pages updated to use mockApplyId, imports switched to mockApply versions, and navigation chaining updated to /mockApply/actual/... routes.
Results page & navigation
jobdri/src/app/mockApply/actual/result/[jobPostingId]/*
Result page now expects jobPostingId, uses mockApply result components, and back-navigation routes to /mockApply.
Apply type selection routing
jobdri/src/app/mockApply/apply-type/ApplyTypePageClient.tsx
Apply-type selection now routes real submissions to /mockApply/actual/new/jd-input.
Mock home client routing & wiring
jobdri/src/components/mockApply/MockApplicationHomePageClient.tsx
Home client imports and route builders updated to mockApply versions; result/retry navigation now targets /mockApply/actual/... and “새로운 지원하기” goes to /mockApply/apply-type.
Component import path updates
jobdri/src/components/mockApply/jd/JdReviewMain.tsx, jobdri/src/components/mockApply/result/ApplyResult.tsx
Sub-component imports updated to mockApply module paths.
Route constants & hooks
jobdri/src/config/applySteps.ts, jobdri/src/constants/routes.ts, jobdri/src/hooks/useReApply.ts
APPLY_STEPS, ROUTES, and useReApply updated to reference /mockApply/* paths; some files include BOM/encoding edits on client directives.
Global navigation updates
jobdri/src/components/common/header/Header.tsx, jobdri/src/components/common/lnb/Lnb.tsx
Header and LNB left-action/menu links updated to /mockApply and minor client-directive encoding edits applied.
Small UI layout changes
jobdri/src/components/common/input/InputMain.tsx
InputMain wrapper now enforces fixed height (h-12) and inner flex fills height (h-full).

MockApply Home UI & Utilities

Layer / File(s) Summary
Types, steps, barrel exports
jobdri/src/components/mockApply/home/types.ts, jobdri/src/components/mockApply/home/homeSteps.ts, jobdri/src/components/mockApply/home/index.ts
Adds ApplicationCardData, home INTRO_STEPS/PROGRESS_STEPS/completedStepCountByStatus, and a barrel module exporting home components and types.
Home utilities & session helpers
jobdri/src/components/mockApply/home/applicationHomeUtils.ts
Adds mapping/merging of mock apply items to ApplicationCardData, sessionStorage caching, resume path normalization, result/retry path builders, and JD-review session persistence.
Shared card helpers & kebab menu
jobdri/src/components/mockApply/home/ApplicationCardShared.tsx, .../ApplicationKebabButton.tsx
Adds keyboard activation handler, CreatedAt helper, and ApplicationKebabButton dropdown with outside-click/escape handling and ARIA attributes.
Presentational home components
jobdri/src/components/mockApply/home/*
Adds ApplicationProgressSteps, EmptyApplicationState, MockApplicationHomeIntro, PausedApplicationCard, ResultApplicationCard, and SavedApplicationsModal UI components used on the home.

Authentication and Middleware

Layer / File(s) Summary
Auth cookie helpers
jobdri/src/lib/auth.ts
Adds AUTH_COOKIE_KEYS, persist access token to document.cookie (7-day max-age) in saveAuthTokens, adds clearAuthTokens() to clear cookie and localStorage, and prefers cookie in getAuthHeaders() with localStorage fallback.
Request authentication middleware
jobdri/src/middleware.ts
New Next.js middleware checks for jobdri_accessToken cookie, allows public routes (/login, /oauth2) without auth, and redirects unauthenticated non-public requests to /login?redirect=...; config matcher scopes middleware to application paths excluding static assets.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • minnngo

Poem

🐰 From /apply to /mockApply we hop and steer,
mockApplyId in place, the routes now clear,
Cookies tucked safely for middleware's watchful eye,
Home cards and kebabs dance beneath the sky,
Hooray—the rabbit routes with a cheerful cry!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Feature/#73 page route feat' is vague and generic, using non-descriptive abbreviations and incomplete phrasing that don't clearly convey the main changes (routing restructure, folder reorganization, auth middleware). Use a more descriptive title like 'Restructure routes from /apply to /mockApply with jobPostingId parameterization' or 'Reorganize folder structure and routing for mock apply flow'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/#73-page_route-feat

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

Copy link
Copy Markdown

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
jobdri/src/lib/auth.ts (1)

175-199: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add Secure (and mirror attributes) for the auth access-token cookie; avoid unsafe token parsing assumptions.

  • saveAuthTokens sets jobdri_accessToken without Secure (line 177); this allows the cookie to be sent over non-HTTPS, weakening transport security.
  • clearAuthTokens deletes the cookie without matching attributes like SameSite (and Secure if added) (line 198); mirror the same attributes used when setting.
  • getAuthHeaders extracts the cookie value with .split("=")[1] (line 260), so an access token containing = would be truncated—don’t introduce encoding without also decoding/adjusting extraction.
🤖 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/lib/auth.ts` around lines 175 - 199, saveAuthTokens sets
AUTH_COOKIE_KEYS.accessToken without the Secure flag and without encoding,
clearAuthTokens removes it without mirroring attributes, and getAuthHeaders uses
naive .split("=")[1] which breaks if the token contains "="; fix by (1) when
setting in saveAuthTokens include Secure (and existing SameSite=Lax, path=/,
max-age) and encode the token (e.g., encodeURIComponent) so cookie storage is
safe, (2) in clearAuthTokens delete the cookie using the exact same attributes
(SameSite, path, Secure) and max-age=0 to ensure the browser removes the same
cookie, and (3) in getAuthHeaders stop using split("=")[1] and instead parse
document.cookie to locate AUTH_COOKIE_KEYS.accessToken, then decodeURIComponent
the value so tokens with "=" or other characters are handled correctly.
🧹 Nitpick comments (3)
jobdri/src/components/common/input/InputMain.tsx (1)

82-84: ⚡ Quick win

Fixed height conflicts with existing vertical padding contract.

h-12 is being applied on top of getWrapperClass’s default py-3, which leaves a very small inner content area. This can make the input feel cramped and risks clipping at larger text scaling.

Proposed adjustment
-      <div
-        className={clsx(getWrapperClass(focused, disabled, isError), "h-12")}
-      >
+      <div
+        className={clsx(
+          getWrapperClass(focused, disabled, isError, undefined, "px-4 py-0"),
+          "h-12",
+        )}
+      >
🤖 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/input/InputMain.tsx` around lines 82 - 84, The
div is forcing a fixed height via the "h-12" utility which conflicts with the
wrapper's default vertical padding from getWrapperClass(focused, disabled,
isError); remove the hard-coded "h-12" from the className and either use a fluid
height (e.g., "h-auto") or a minimum height utility (e.g., "min-h-12" or a
px-based min-height) so the wrapper's py-3 has room and text scaling won't clip;
update the className string in InputMain.tsx where getWrapperClass(...) is
combined with "h-12" to remove/replace that token.
jobdri/src/middleware.ts (1)

7-7: ⚡ Quick win

Extract token cookie key to a shared constant to avoid drift.

Line 7 hardcodes "jobdri_accessToken" while jobdri/src/lib/auth.ts defines AUTH_COOKIE_KEYS.accessToken. A shared constants module keeps client and middleware contracts aligned.

🤖 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/middleware.ts` at line 7, Replace the hardcoded cookie key in
middleware.ts with the shared constant: instead of using the literal
"jobdri_accessToken" when calling request.cookies.get (which sets the token
variable), import and use AUTH_COOKIE_KEYS.accessToken from
jobdri/src/lib/auth.ts so the middleware and auth library share the same key;
update the import at the top and change the request.cookies.get call to use
AUTH_COOKIE_KEYS.accessToken.
jobdri/src/lib/auth.ts (1)

258-261: ⚡ Quick win

Make cookie accessToken parsing robust (avoid split("=")[1]) (jobdri/src/lib/auth.ts, lines 258-261)

getAuthHeaders() currently derives the cookie value with ?.split("=")[1], which would truncate if an access token ever contains =. This is probably not an issue today if accessToken is a standard JWT (the file decodes it via split(".") and base64url logic elsewhere), but it’s still fragile. Prefer extracting everything after jobdri_accessToken= (e.g., via slice(...)) rather than splitting on =. Also, the “264-264” part is just the localStorage fallback, not the parsing bug.

🤖 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/lib/auth.ts` around lines 258 - 261, The cookie parsing in
getAuthHeaders (variable cookieToken) uses ?.split("=").[1] which breaks if the
token contains '='; change it to locate the cookie key string
`${AUTH_COOKIE_KEYS.accessToken}=` (e.g., with indexOf or a RegExp) and then
slice the cookie string to extract everything after that '=' to the end of the
cookie value (not splitting on '='), preserving the full token; update the logic
that finds the cookie row (the .find callback and subsequent extraction) to
return the sliced substring instead of using .split("=")[1].
🤖 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/mockApply/actual/`[mockApplyId]/(jd)/jd-input/JdInputPageClient.tsx:
- Around line 69-71: The route param key is wrong: change useParams<{ id: string
}>() to useParams<{ mockApplyId: string }>() and replace usages of id with
mockApplyId (update the const from useParams and all places building
manualJdReviewPath, session/storage keys and any other paths such as the
occurrences around the current lines 162-166 and 182) so paths like
`/mockApply/actual/${id}/...` and storage keys use the correct mockApplyId
value; ensure useRouter usage remains unchanged and only the param name/type and
all references are updated consistently.

In
`@jobdri/src/app/mockApply/actual/`[mockApplyId]/questions/QuestionsPageClient.tsx:
- Line 24: The navigation call router.push(`/mockApply/actual/${id}/write`)
drops search params so WritePageClient loses the jobPostingId; change the push
to include the existing jobPostingId query (e.g., read jobPostingId from search
params or router.query in QuestionsPageClient and call router.push with an
object that preserves query: pathname `/mockApply/actual/${id}/write` and query:
{ jobPostingId: <existingJobPostingId>, ...otherParams } ) so WritePageClient
still receives jobPostingId.

In `@jobdri/src/app/mockApply/actual/`[mockApplyId]/write/WritePageClient.tsx:
- Line 75: The redirect URL currently uses
`/mockApply/actual/result/${jobPostingId}?sequence=${savedSequence}` but the new
result route contract requires both sequence and totalCount; update the URL in
WritePageClient.tsx (the place building the redirect in the WritePageClient
component/function) to include `&totalCount=${totalCount}` (or the existing
variable that holds the total applies, e.g.,
`savedTotalCount`/`selectedApplyCount`) and ensure that `totalCount` is in
scope/passed into this function so the query becomes
`?sequence=${savedSequence}&totalCount=${totalCount}` when navigating.

In `@jobdri/src/components/mockApply/MockApplicationHomePageClient.tsx`:
- Line 707: The CTA's router.push is pointing to the wrong/missing route; update
the onClick handler in MockApplicationHomePageClient (the router.push call
currently using "/mockApply/mockApply-type") to push the migrated path
"/mockApply/apply-type" so the button navigates to the correct page.
- Around line 221-229: The route normalization only matches "/mockApply/virtual"
so already-migrated paths like "/mockApply/actual/..." are rejected; update the
regex used when computing routeMatch to accept both "virtual" and "actual" (e.g.
use /^\/mockApply\/(?:virtual|actual)\/[^/]+\/([^/?#]+)([?#].*)?$/) so
routeSegment is captured for either form, then keep the existing logic that
checks RESUME_ROUTE_SEGMENTS and returns
`/mockApply/actual/${mockApplyId}/${routeSegment}${routeMatch[2] ?? ""}` using
the same routeMatch indices.

In `@jobdri/src/config/applySteps.ts`:
- Around line 14-19: The step definitions for "자소서 입력" and "결과 확인" use top-level
paths ("/mockApply/write", "/mockApply/result") which no longer match the
migrated pages under "/mockApply/actual/..." and can be mis-resolved by the
current startsWith matching; update those step objects so their path values
point to the migrated routes (e.g. "/mockApply/actual/write" and
"/mockApply/actual/result") or alternatively make the route-matching logic use
exact matching for the step list; locate and update the step array entries for
the labels "자소서 입력" and "결과 확인" in applySteps (the step objects with label and
path) accordingly.

In `@jobdri/src/middleware.ts`:
- Line 10: The public-route check in middleware uses pathname.startsWith(route)
(see isPublic and PUBLIC_ROUTES) which allows prefix bypasses; update the
isPublic logic to only treat a route as public when the pathname equals the
route or the route is a parent segment (i.e., pathname === route OR
pathname.startsWith(route + '/') ), or use a regex like ^route(/|$) to match
exact segment boundaries; ensure this logic handles the root route and preserves
existing PUBLIC_ROUTES values so paths like /login-anything no longer bypass
auth.
- Line 14: middleware.ts currently sets loginUrl.searchParams.set("redirect",
pathname) but the login UI (app/login/page.tsx and
components/login/EmailLoginScreen.tsx) never reads that param; either stop
setting it or wire the login flow to consume it. Option A: remove the
loginUrl.searchParams.set("redirect", ...) call in middleware.ts. Option B:
propagate the original next URL by adding request.nextUrl.search (or the
specific pathname) into the login URL in middleware.ts and update
app/login/page.tsx and components/login/EmailLoginScreen.tsx to read
searchParams.get("redirect") and use it after successful login to
navigate/redirect the user. Ensure consistency by choosing one approach and
updating all three symbols (middleware.ts loginUrl.searchParams.set,
app/login/page.tsx, components/login/EmailLoginScreen.tsx).

---

Outside diff comments:
In `@jobdri/src/lib/auth.ts`:
- Around line 175-199: saveAuthTokens sets AUTH_COOKIE_KEYS.accessToken without
the Secure flag and without encoding, clearAuthTokens removes it without
mirroring attributes, and getAuthHeaders uses naive .split("=")[1] which breaks
if the token contains "="; fix by (1) when setting in saveAuthTokens include
Secure (and existing SameSite=Lax, path=/, max-age) and encode the token (e.g.,
encodeURIComponent) so cookie storage is safe, (2) in clearAuthTokens delete the
cookie using the exact same attributes (SameSite, path, Secure) and max-age=0 to
ensure the browser removes the same cookie, and (3) in getAuthHeaders stop using
split("=")[1] and instead parse document.cookie to locate
AUTH_COOKIE_KEYS.accessToken, then decodeURIComponent the value so tokens with
"=" or other characters are handled correctly.

---

Nitpick comments:
In `@jobdri/src/components/common/input/InputMain.tsx`:
- Around line 82-84: The div is forcing a fixed height via the "h-12" utility
which conflicts with the wrapper's default vertical padding from
getWrapperClass(focused, disabled, isError); remove the hard-coded "h-12" from
the className and either use a fluid height (e.g., "h-auto") or a minimum height
utility (e.g., "min-h-12" or a px-based min-height) so the wrapper's py-3 has
room and text scaling won't clip; update the className string in InputMain.tsx
where getWrapperClass(...) is combined with "h-12" to remove/replace that token.

In `@jobdri/src/lib/auth.ts`:
- Around line 258-261: The cookie parsing in getAuthHeaders (variable
cookieToken) uses ?.split("=").[1] which breaks if the token contains '=';
change it to locate the cookie key string `${AUTH_COOKIE_KEYS.accessToken}=`
(e.g., with indexOf or a RegExp) and then slice the cookie string to extract
everything after that '=' to the end of the cookie value (not splitting on '='),
preserving the full token; update the logic that finds the cookie row (the .find
callback and subsequent extraction) to return the sliced substring instead of
using .split("=")[1].

In `@jobdri/src/middleware.ts`:
- Line 7: Replace the hardcoded cookie key in middleware.ts with the shared
constant: instead of using the literal "jobdri_accessToken" when calling
request.cookies.get (which sets the token variable), import and use
AUTH_COOKIE_KEYS.accessToken from jobdri/src/lib/auth.ts so the middleware and
auth library share the same key; update the import at the top and change the
request.cookies.get call to use AUTH_COOKIE_KEYS.accessToken.
🪄 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: 5f033590-8058-4f4c-bf4c-41c45ae5db08

📥 Commits

Reviewing files that changed from the base of the PR and between 7e1cbee and 38d1984.

📒 Files selected for processing (44)
  • jobdri/src/app/apply/page.tsx
  • jobdri/src/app/mockApply/actual/[mockApplyId]/(jd)/jd-input/JdInputPageClient.tsx
  • jobdri/src/app/mockApply/actual/[mockApplyId]/(jd)/jd-input/page.tsx
  • jobdri/src/app/mockApply/actual/[mockApplyId]/(jd)/jd-review/JdReviewPageClient.tsx
  • jobdri/src/app/mockApply/actual/[mockApplyId]/(jd)/jd-review/page.tsx
  • jobdri/src/app/mockApply/actual/[mockApplyId]/(jd)/page.tsx
  • jobdri/src/app/mockApply/actual/[mockApplyId]/questions/QuestionsPageClient.tsx
  • jobdri/src/app/mockApply/actual/[mockApplyId]/questions/page.tsx
  • jobdri/src/app/mockApply/actual/[mockApplyId]/write/WritePageClient.tsx
  • jobdri/src/app/mockApply/actual/[mockApplyId]/write/page.tsx
  • jobdri/src/app/mockApply/actual/result/[jobPostingId]/ResultPageClient.tsx
  • jobdri/src/app/mockApply/actual/result/[jobPostingId]/page.tsx
  • jobdri/src/app/mockApply/apply-type/ApplyTypePageClient.tsx
  • jobdri/src/app/mockApply/apply-type/page.tsx
  • jobdri/src/app/mockApply/page.tsx
  • jobdri/src/app/page.tsx
  • jobdri/src/components/common/header/Header.tsx
  • jobdri/src/components/common/input/InputMain.tsx
  • jobdri/src/components/common/lnb/Lnb.tsx
  • jobdri/src/components/mockApply/AddQuestion.tsx
  • jobdri/src/components/mockApply/InputSection.tsx
  • jobdri/src/components/mockApply/MockApplicationHomePageClient.tsx
  • jobdri/src/components/mockApply/PageLoading.tsx
  • jobdri/src/components/mockApply/QuestionGenerationLoading.tsx
  • jobdri/src/components/mockApply/ResumeAnalysisLoading.tsx
  • jobdri/src/components/mockApply/SelectQuestion.tsx
  • jobdri/src/components/mockApply/jd/JdReviewMain.tsx
  • jobdri/src/components/mockApply/jd/jdReviewSections.ts
  • jobdri/src/components/mockApply/result/Alret.tsx
  • jobdri/src/components/mockApply/result/ApplyResult.tsx
  • jobdri/src/components/mockApply/result/DetailAnotationPannel.tsx
  • jobdri/src/components/mockApply/result/DetailSection.tsx
  • jobdri/src/components/mockApply/result/OverviewSection.tsx
  • jobdri/src/components/mockApply/result/ScoreCircle.tsx
  • jobdri/src/components/mockApply/result/Sidebar.tsx
  • jobdri/src/components/mockApply/result/SidebarItem.tsx
  • jobdri/src/components/mockApply/result/SummaryCard.tsx
  • jobdri/src/components/mockApply/result/Trybar.tsx
  • jobdri/src/components/mockApply/result/highlightStyles.ts
  • jobdri/src/config/applySteps.ts
  • jobdri/src/constants/routes.ts
  • jobdri/src/hooks/useReApply.ts
  • jobdri/src/lib/auth.ts
  • jobdri/src/middleware.ts
💤 Files with no reviewable changes (1)
  • jobdri/src/app/apply/page.tsx

Comment thread jobdri/src/app/mockApply/actual/[mockApplyId]/(jd)/jd-input/JdInputPageClient.tsx Outdated
Comment thread jobdri/src/app/mockApply/actual/[mockApplyId]/questions/QuestionsPageClient.tsx Outdated
shouldKeepLoading = true;
router.push(
`/apply/virtual/${jobPostingId}/result?sequence=${savedSequence}`,
`/mockApply/actual/result/${jobPostingId}?sequence=${savedSequence}`,
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 | 🟠 Major | ⚡ Quick win

Include totalCount in result URL to match the new contract.

Line 75 only sends sequence, but the migrated result route contract expects ?sequence=N&totalCount=N.

Suggested fix
-      router.push(
-        `/mockApply/actual/result/${jobPostingId}?sequence=${savedSequence}`,
-      );
+      router.push(
+        `/mockApply/actual/result/${jobPostingId}?sequence=${savedSequence}&totalCount=${savedSequence}`,
+      );
📝 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
`/mockApply/actual/result/${jobPostingId}?sequence=${savedSequence}`,
`/mockApply/actual/result/${jobPostingId}?sequence=${savedSequence}&totalCount=${savedSequence}`,
🤖 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/actual/`[mockApplyId]/write/WritePageClient.tsx at
line 75, The redirect URL currently uses
`/mockApply/actual/result/${jobPostingId}?sequence=${savedSequence}` but the new
result route contract requires both sequence and totalCount; update the URL in
WritePageClient.tsx (the place building the redirect in the WritePageClient
component/function) to include `&totalCount=${totalCount}` (or the existing
variable that holds the total applies, e.g.,
`savedTotalCount`/`selectedApplyCount`) and ensure that `totalCount` is in
scope/passed into this function so the query becomes
`?sequence=${savedSequence}&totalCount=${totalCount}` when navigating.

Comment on lines +221 to +229
/^\/mockApply\/virtual\/[^/]+\/([^/?#]+)([?#].*)?$/,
);
const routeSegment = routeMatch?.[1];

if (!routeSegment || !RESUME_ROUTE_SEGMENTS.has(routeSegment)) {
return "";
}

return `/apply/virtual/${mockApplyId}/${routeSegment}${routeMatch[2] ?? ""}`;
return `/mockApply/actual/${mockApplyId}/${routeSegment}${routeMatch[2] ?? ""}`;
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 | 🟠 Major | ⚡ Quick win

Resume-path normalization only matches /mockApply/virtual, not current /mockApply/actual.

Line 221 rejects already-migrated resumePath values like /mockApply/actual/{id}/jd-review, so resume can fall back to a wrong default route.

Suggested fix
-  const routeMatch = path.match(
-    /^\/mockApply\/virtual\/[^/]+\/([^/?#]+)([?#].*)?$/,
-  );
+  const routeMatch = path.match(
+    /^\/(?:apply\/virtual|mockApply\/virtual|mockApply\/actual)\/[^/]+\/([^/?#]+)([?#].*)?$/,
+  );
🤖 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/mockApply/MockApplicationHomePageClient.tsx` around
lines 221 - 229, The route normalization only matches "/mockApply/virtual" so
already-migrated paths like "/mockApply/actual/..." are rejected; update the
regex used when computing routeMatch to accept both "virtual" and "actual" (e.g.
use /^\/mockApply\/(?:virtual|actual)\/[^/]+\/([^/?#]+)([?#].*)?$/) so
routeSegment is captured for either form, then keep the existing logic that
checks RESUME_ROUTE_SEGMENTS and returns
`/mockApply/actual/${mockApplyId}/${routeSegment}${routeMatch[2] ?? ""}` using
the same routeMatch indices.

Comment thread jobdri/src/components/mockApply/MockApplicationHomePageClient.tsx Outdated
Comment on lines +14 to +19
{ label: "유형 선택", path: "/mockApply", exact: true },
{ label: "공고 생성", path: "/mockApply/job/create" },
{ label: "공고 확인", path: "/mockApply/job/confirm" },
{ label: "문항 선택", path: "/mockApply/actual" },
{ label: "자소서 입력", path: "/mockApply/write" },
{ label: "결과 확인", path: "/mockApply/result" },
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 | 🟠 Major | 🏗️ Heavy lift

Step-path definitions no longer match migrated dynamic routes.

Line 18-19 still use top-level paths (/mockApply/write, /mockApply/result), but migrated pages are under /mockApply/actual/.... With current startsWith matching, write/result pages can resolve to the wrong step.

Proposed direction
 export const APPLY_STEPS: ApplyStep[] = [
   { label: "유형 선택", path: "/mockApply", exact: true },
   { label: "공고 생성", path: "/mockApply/job/create" },
   { label: "공고 확인", path: "/mockApply/job/confirm" },
-  { label: "문항 선택", path: "/mockApply/actual" },
-  { label: "자소서 입력", path: "/mockApply/write" },
-  { label: "결과 확인", path: "/mockApply/result" },
+  // Dynamic-route flow needs segment-aware matching, not only prefix constants.
+  // e.g. /mockApply/actual/:mockApplyId/questions, /write, /result/:jobPostingId
 ];
🤖 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/config/applySteps.ts` around lines 14 - 19, The step definitions
for "자소서 입력" and "결과 확인" use top-level paths ("/mockApply/write",
"/mockApply/result") which no longer match the migrated pages under
"/mockApply/actual/..." and can be mis-resolved by the current startsWith
matching; update those step objects so their path values point to the migrated
routes (e.g. "/mockApply/actual/write" and "/mockApply/actual/result") or
alternatively make the route-matching logic use exact matching for the step
list; locate and update the step array entries for the labels "자소서 입력" and "결과
확인" in applySteps (the step objects with label and path) accordingly.

Comment thread jobdri/src/middleware.ts
const token = request.cookies.get("jobdri_accessToken")?.value;
const { pathname } = request.nextUrl;

const isPublic = PUBLIC_ROUTES.some((route) => pathname.startsWith(route));
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 | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the file and show relevant sections with line numbers
echo "=== middleware.ts (context around line ~10) ==="
nl -ba jobdri/src/middleware.ts | sed -n '1,160p'

echo
echo "=== Find PUBLIC_ROUTES usage/definition ==="
rg -n "PUBLIC_ROUTES" -S jobdri/src || true

echo
echo "=== Find middleware auth/public logic ==="
rg -n "isPublic|startsWith\\(route\\)|pathname|PUBLIC_ROUTES\\.some" -S jobdri/src/middleware.ts || true

echo
echo "=== Inspect other middleware/auth files if referenced ==="
rg -n "middleware" -S jobdri/src | head -n 50

Repository: JobDri-Developer/FrontEnd

Length of output: 178


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== middleware.ts (first 200 lines with numbers) ==="
cat -n jobdri/src/middleware.ts | sed -n '1,200p'

echo
echo "=== Find PUBLIC_ROUTES definitions/usages ==="
rg -n "PUBLIC_ROUTES" -S jobdri/src || true

echo
echo "=== Inspect auth/public logic ==="
rg -n "isPublic|startsWith\\(route\\)|pathname|PUBLIC_ROUTES\\.some" -S jobdri/src/middleware.ts || true

echo
echo "=== Find any other middleware usage ==="
rg -n "middleware" -S jobdri/src | head -n 50 || true

Repository: JobDri-Developer/FrontEnd

Length of output: 1624


Fix public-route matching in middleware to avoid prefix-based auth bypass

jobdri/src/middleware.ts uses pathname.startsWith(route), so any path beginning with /login or /oauth2 (e.g. /login-anything, /oauth2token) is treated as public and skips the auth redirect.

Suggested patch
-  const isPublic = PUBLIC_ROUTES.some((route) => pathname.startsWith(route));
+  const isPublic = PUBLIC_ROUTES.some(
+    (route) => pathname === route || pathname.startsWith(`${route}/`),
+  );
🤖 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/middleware.ts` at line 10, The public-route check in middleware
uses pathname.startsWith(route) (see isPublic and PUBLIC_ROUTES) which allows
prefix bypasses; update the isPublic logic to only treat a route as public when
the pathname equals the route or the route is a parent segment (i.e., pathname
=== route OR pathname.startsWith(route + '/') ), or use a regex like ^route(/|$)
to match exact segment boundaries; ensure this logic handles the root route and
preserves existing PUBLIC_ROUTES values so paths like /login-anything no longer
bypass auth.

Comment thread jobdri/src/middleware.ts

if (!token && !isPublic) {
const loginUrl = new URL("/login", request.url);
loginUrl.searchParams.set("redirect", pathname);
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 | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Show the relevant middleware code around the reported line
echo "=== middleware.ts (lines near 14) ==="
nl -ba jobdri/src/middleware.ts | sed -n '1,80p'

# 2) Search for where "redirect" is used/read in the codebase
echo
echo "=== occurrences of 'redirect' in jobdri/src ==="
rg -n --hidden --no-ignore-vcs "redirect" jobdri/src || true

# 3) If the login screen exists, inspect it for redirect handling
echo
echo "=== Inspect EmailLoginScreen.tsx (if present) ==="
if [ -f jobdri/src/components/login/EmailLoginScreen.tsx ]; then
  nl -ba jobdri/src/components/login/EmailLoginScreen.tsx | sed -n '1,220p'
else
  echo "File not found: jobdri/src/components/login/EmailLoginScreen.tsx"
fi

# 4) Search for reading redirect from query params (common patterns)
echo
echo "=== occurrences of nextUrl/searchParams/get('redirect' patterns) ==="
rg -n --hidden --no-ignore-vcs "(searchParams|useSearchParams|query|get\\(\"redirect\"\\)|get\\('redirect'\\)|redirect\\s*[:=]|params\\.|param\\.)" jobdri/src/components/jobdri/src jobdri/src || true

Repository: JobDri-Developer/FrontEnd

Length of output: 168


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Print file with line numbers (without nl)
echo "=== middleware.ts (first 120 lines) ==="
awk '{printf "%6d\t%s\n", NR, $0}' jobdri/src/middleware.ts | sed -n '1,120p'

echo
echo "=== occurrences of 'redirect' in jobdri/src ==="
rg -n --hidden --no-ignore-vcs "redirect" jobdri/src || true

echo
echo "=== EmailLoginScreen.tsx (if present) ==="
if [ -f jobdri/src/components/login/EmailLoginScreen.tsx ]; then
  awk '{printf "%6d\t%s\n", NR, $0}' jobdri/src/components/login/EmailLoginScreen.tsx | sed -n '1,260p'
else
  echo "File not found: jobdri/src/components/login/EmailLoginScreen.tsx"
fi

echo
echo "=== occurrences of reading redirect from query/search params ==="
rg -n --hidden --no-ignore-vcs \
  "searchParams\.get\\(\"redirect\"\\)|searchParams\.get\\('redirect'\\)|useSearchParams\\(|nextUrl\\.(search|toString)|get\\(\"redirect\"\\)|get\\('redirect'\\)" \
  jobdri/src || true

Repository: JobDri-Developer/FrontEnd

Length of output: 11662


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Files under src/app related to login ==="
fd -t f "login" jobdri/src/app jobdri/src/components jobdri/src || true

echo
echo "=== occurrences of searchParams.get('redirect') / redirect param access ==="
rg -n --hidden --no-ignore-vcs "searchParams\.get\(\"redirect\"\)|searchParams\.get\('redirect'\)|useSearchParams\(\).*redirect|URLSearchParams\(.+redirect|new URL\\(.+redirect|\\bredirect\\b.*searchParams" jobdri/src || true

echo
echo "=== occurrences of 'redirect=' in strings/URLs ==="
rg -n --hidden --no-ignore-vcs "redirect=" jobdri/src || true

echo
echo "=== Inspect /login route entrypoint(s) ==="
# Try common locations; if they don't exist, the rg below will still help.
for f in \
  jobdri/src/app/login/page.tsx \
  jobdri/src/app/login/layout.tsx \
  jobdri/src/app/login/page.jsx \
  jobdri/src/app/login/page.ts \
  jobdri/src/app/login/route.ts \
  jobdri/src/app/(.*)/login/page.tsx \
  ; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    awk '{printf "%6d\t%s\n", NR, $0}' "$f" | sed -n '1,220p'
  fi
done

# Broader: show any route files whose path includes login
echo
echo "=== route files mentioning '/login' ==="
rg -n --hidden --no-ignore-vcs '"/login"|\'/login\'|PUBLIC_ROUTES|router\.push\(.*login|ROUTES\.LOGIN|app/login' jobdri/src/app jobdri/src/components jobdri/src/constants jobdri/src/lib || true

Repository: JobDri-Developer/FrontEnd

Length of output: 466


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Find login route files/dirs under src/app ==="
# List files whose path contains /login or login in name (case-insensitive)
fd -t f -i "login" jobdri/src/app || true
echo
find jobdri/src/app -maxdepth 6 -type f \( -iname "*login*" \) 2>/dev/null || true

echo
echo "=== List all page.tsx/route.tsx under app/login (if directory exists) ==="
if [ -d jobdri/src/app/login ]; then
  fd -t f "page.tsx" jobdri/src/app/login || true
  fd -t f "route.ts" jobdri/src/app/login || true
  fd -t f -i "login" jobdri/src/app/login || true
else
  echo "jobdri/src/app/login does not exist"
fi

echo
echo "=== Find where EmailLoginScreen is used ==="
rg -n --hidden --no-ignore-vcs "EmailLoginScreen" jobdri/src || true

echo
echo "=== Inspect constants/routes.ts (for login route constant) ==="
if [ -f jobdri/src/constants/routes.ts ]; then
  awk '{printf "%6d\t%s\n", NR, $0}' jobdri/src/constants/routes.ts | sed -n '1,120p'
fi

echo
echo "=== Search for useSearchParams on login-related files ==="
# Look for searchParams usage in any file with "login" in path
rg -n --hidden --no-ignore-vcs "useSearchParams\\(|searchParams\\.get\\(" jobdri/src/components/login jobdri/src/app || true

echo
echo "=== Search for any code reading the 'redirect' query param in all files ==="
rg -n --hidden --no-ignore-vcs "(\"redirect\"|'redirect')\\s*[,)]" jobdri/src/app jobdri/src/components jobdri/src/lib || true

Repository: JobDri-Developer/FrontEnd

Length of output: 3130


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== app/login/page.tsx ==="
awk '{printf "%6d\t%s\n", NR, $0}' jobdri/src/app/login/page.tsx | sed -n '1,120p'

echo
echo "=== Search within EmailLoginScreen.tsx for redirect/search param handling ==="
rg -n --hidden --no-ignore-vcs "(redirect|searchParams|useSearchParams|query\\.|router\\.query)" jobdri/src/components/login/EmailLoginScreen.tsx || true

echo
echo "=== Search within login components for redirect ==="
rg -n --hidden --no-ignore-vcs "redirect" jobdri/src/components/login || true

echo
echo "=== Search within src for redirect= usage in routing to login ==="
rg -n --hidden --no-ignore-vcs "redirect.*ROUTES\\.LOGIN|ROUTES\\.LOGIN.*redirect|/login\\?redirect|\\?redirect=" jobdri/src || true

Repository: JobDri-Developer/FrontEnd

Length of output: 457


Avoid/adjust redirect query-string fix: /login?redirect=... is not consumed in this codebase.
middleware.ts sets loginUrl.searchParams.set("redirect", pathname), but app/login/page.tsx and components/login/EmailLoginScreen.tsx never read a redirect query param (no redirect/searchParams.get("redirect") usages found). Either wire the login flow to use redirect (and then include request.nextUrl.search) or remove/stop setting it.

🤖 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/middleware.ts` at line 14, middleware.ts currently sets
loginUrl.searchParams.set("redirect", pathname) but the login UI
(app/login/page.tsx and components/login/EmailLoginScreen.tsx) never reads that
param; either stop setting it or wire the login flow to consume it. Option A:
remove the loginUrl.searchParams.set("redirect", ...) call in middleware.ts.
Option B: propagate the original next URL by adding request.nextUrl.search (or
the specific pathname) into the login URL in middleware.ts and update
app/login/page.tsx and components/login/EmailLoginScreen.tsx to read
searchParams.get("redirect") and use it after successful login to
navigate/redirect the user. Ensure consistency by choosing one approach and
updating all three symbols (middleware.ts loginUrl.searchParams.set,
app/login/page.tsx, components/login/EmailLoginScreen.tsx).

Copy link
Copy Markdown
Collaborator

@minnngo minnngo left a comment

Choose a reason for hiding this comment

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

충돌 있는거만 해결하면 될듯?? 수고했어요~~👍👍

yiyoonseo and others added 2 commits May 29, 2026 14:08
- JdInputPageClient useParams 키 mockApplyId로 수정
- QuestionsPageClient jobPostingId 폴백 로직 + 새 경로 적용
- MockApplicationHomePageClient develop 리팩토링 버전 반영 (home/ 서브 컴포넌트)
- mock-application/home/ → mockApply/home/ 이동 및 경로 전체 업데이트

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@yiyoonseo yiyoonseo merged commit d9f6bb5 into develop May 29, 2026
1 check was pending
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix: UI 버그 수정 및 코드 개선

2 participants