Skip to content

[FIX] 지원서 날짜 밀림, 지원서 수정 안됨 버그 수정#408

Open
JangYEhoon00 wants to merge 3 commits into
mainfrom
fix/#407
Open

[FIX] 지원서 날짜 밀림, 지원서 수정 안됨 버그 수정#408
JangYEhoon00 wants to merge 3 commits into
mainfrom
fix/#407

Conversation

@JangYEhoon00

@JangYEhoon00 JangYEhoon00 commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

🔥 연관 이슈

🚀 작업 내용

날짜 밀림 버그

기존 문제는 toISOString()이 항상 UTC 기준 문자열을 만들기 때문에, 한국 시간 2026-07-01 00:00 같은 로컬 날짜가 UTC로는 2026-06-30T15:00:00.000Z가 되면서 날짜가 하루 앞당겨질 수 있었습니다.
이번 수정은: API에서 받은 '2026-07-01' 문자열을 new Date('2026-07-01')로 바로 만들지 않고 year, month, day를 직접 쪼개서
new Date(2026, 6, 1)처럼 로컬 날짜 객체로 만들고 다시 API에 보낼 때도 toISOString()을 쓰지 않고 getFullYear(), getMonth(), getDate()로 YYYY-MM-DD를 직접 조립해서 결과를 리턴했습니다.

지원서 수정 안되는 버그

useFormEdit.ts에는 canEditForm, canEditContent 계산이 들어가 있었습니다.
그런데 FormEditPage.tsx는 여전히 기존 값인 isRecruiting을 쓰고 있었습니다.
FormHeaderSection.tsx도 여전히 readOnly 하나로 제목/설명/모집기간을 같이 잠그고 있었습니다.

🤔 고민했던 내용

지원서 수정이 안되는 버그를 수정하며 값을 명시 시키는게 좋다고 생각하여 handelBasicInfoChange 함수가 길어졌는데 이런 부분이 괜찮을지 궁금합니다.

💬 리뷰 중점사항

제가 이해하고 있는 것으로는 모집일 전, 그리고 모집일 이후 지원서 날짜 변경이 가능한 것으로 알고있습니다.
혹여나 제가 이해하고 있는게 다를 수 있어 피드백 주시면 수정하겠습니다.

Summary by CodeRabbit

  • Bug Fixes

    • 지원서/폼의 날짜 입력과 표시가 로컬 기준으로 처리되어, 날짜가 하루 어긋나 보이던 문제가 개선되었습니다.
    • 편집 가능 여부가 더 세분화되어, 모집 기간과 기본 정보/질문 수정 상태가 더 정확하게 반영됩니다.
  • Documentation

    • 프로젝트 구조, 작업 규칙, 공통 개발 가이드가 추가되어 문서화가 강화되었습니다.

codex가 프로젝트를 이해하는데 가이드 역할을 하는 AGENT.MD파일들을 생성했습니다.
@vercel

vercel Bot commented Jul 1, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
ddingdong-fe Ready Ready Preview, Comment Jul 1, 2026 11:42am

@github-actions github-actions Bot requested review from keemsebin and ujinsim July 1, 2026 11:42
@github-actions github-actions Bot added the fix 에러 픽스 label Jul 1, 2026
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

여러 디렉터리(루트, apps/web/app, apps/web/app/_api, apps/web/app/admin, packages/shared)에 AGENTS.md 문서를 신규 추가했다. 또한 지원서 편집 화면의 편집 가능 범위 계산을 isRecruiting에서 canEditForm/canEditContent로 분리하고, 날짜 포맷팅을 UTC 대신 로컬 타임존 기준(parseLocalDate)으로 변경했다.

Changes

AGENTS.md 문서 추가

Layer / File(s) Summary
AGENTS.md 가이드 신규 작성
AGENTS.md, apps/web/app/AGENTS.md, apps/web/app/_api/AGENTS.md, apps/web/app/admin/AGENTS.md, packages/shared/AGENTS.md
각 디렉터리별 구조, 참고 위치, 작성 컨벤션, 안티패턴, 알려진 이슈를 정리한 문서가 신규 추가된다.

Estimated code review effort: 2 (Simple) | ~10 minutes

지원서 생성/편집 날짜 및 권한 로직 수정

Layer / File(s) Summary
로컬 날짜 파싱 유틸
apps/web/app/admin/apply/new/_utils/format.ts
formatDate가 UTC 기반 대신 새로 추가된 parseLocalDate를 통해 로컬 타임존 기준 YYYY-MM-DD를 산출하도록 변경되었으며, parseLocalDate 내부에 console.log가 추가되었다.
transformFormData 날짜/섹션 로직 변경
apps/web/app/admin/apply/[id]/edit/_utils/transformFormData.ts
기본 정보 변환 시 new Date 대신 parseLocalDate를 사용하며, 섹션 맵 구성 로직이 has+get! 방식에서 get/set 기반으로 변경되었다.
useFormEdit 편집 권한 및 저장 흐름 재구성
apps/web/app/admin/apply/[id]/edit/_hooks/useFormEdit.ts
isRecruiting 계산이 제거되고 canEditForm/canEditContent가 도입되어 기본 정보 반영, 저장 시 검증(validateBasicInfo, validateQuestions), payload 구성 방식이 권한 값에 따라 분기되도록 변경되었다.
FormEditPage 권한 값 연동
apps/web/app/admin/apply/[id]/edit/_pages/FormEditPage.tsx
isRecruiting 대신 canEditForm/canEditContent를 사용해 편집 UI 노출과 섹션 readOnly 여부를 결정하도록 변경되었다.
FormHeaderSection 모집 기간 전용 readOnly
apps/web/app/admin/apply/new/_components/FormHeaderSection.tsx
recruitPeriodReadOnly prop이 추가되어 지원 기간 Datepicker의 disabled 여부를 별도로 제어할 수 있게 되었다.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant FormEditPage
  participant useFormEdit
  participant transformFormData

  User->>FormEditPage: 편집 모드 진입
  FormEditPage->>useFormEdit: canEditForm/canEditContent 조회
  useFormEdit->>useFormEdit: startDate/endDate 기준 권한 계산
  useFormEdit-->>FormEditPage: canEditForm, canEditContent 반환
  FormEditPage->>FormEditPage: readOnly = !isEditing || !canEditContent 적용

  User->>FormEditPage: 저장 클릭
  FormEditPage->>useFormEdit: handleSave 호출
  alt canEditContent true
    useFormEdit->>useFormEdit: validateBasicInfo, validateQuestions
    useFormEdit->>transformFormData: formatFormData(basicInfo, sections, formField)
  else canEditContent false
    useFormEdit->>useFormEdit: startDate/endDate 누락 검증
    useFormEdit->>useFormEdit: formatDate로 모집 기간만 재구성
  end
  useFormEdit-->>FormEditPage: 저장 payload 반환
Loading

Estimated code review effort: 3 (Moderate) | ~25 minutes

Related issues: #407

Suggested labels: documentation, bug

Suggested reviewers: COW-dev 팀 리뷰어

🐰 로컬 시간에 발 맞춰 뛰는 토끼,
날짜 하나 꼬였던 문제 풀어내고,
편집 권한 두 갈래로 나눠 심어,
문서까지 곳곳에 심어놓았네,
당근밭 정리 끝, 폴짝 폴짝 커밋!

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning 기능 수정과 직접 관련 없는 AGENTS.md 문서 추가가 여러 경로에 포함되어 있습니다. 문서 정리는 별도 PR로 분리하거나, 이번 이슈와 직접 관련된 수정만 남겨 범위를 좁히세요.
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.
Description check ⚠️ Warning 연관 이슈·작업 내용·고민·리뷰 중점사항은 있으나, 템플릿이 요구한 [FIX]/[FEAT] 등 제목이 없습니다. 제목을 [FIX] 날짜 밀림 및 지원서 수정 버그 수정처럼 태그 형식으로 추가하고, 필요 시 각 항목을 더 구체화하세요.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 지원서 날짜 밀림과 수정 불가 버그라는 핵심 변경을 잘 요약합니다.
Linked Issues check ✅ Passed 지원서 입력 비활성화와 날짜 지연 문제를 각각 수정하는 변경이 있어 #407의 요구사항을 충족합니다.
✨ 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 fix/#407

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

Update: 2026년 07월 01일 20시 43분 27초
Storybook 미리보기: https://69ca943d51248ba5e1094fac-dtuuzsvjwo.chromatic.com/

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

🤖 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 `@apps/web/app/admin/apply/`[id]/edit/_hooks/useFormEdit.ts:
- Around line 30-53: `useFormEdit`의 `useMemo`가 `formData.startDate`와
`formData.endDate`만 의존해서 자정을 넘겨도 `canEditForm`/`canEditContent`가 갱신되지 않는 문제를
수정하세요. `handleSave()`가 최신 날짜 기준으로 권한을 다시 판단하도록, 현재 날짜를 상태/의존성에 포함해 갱신되게 하거나 저장
시점에 `parseLocalDate`와 `today`를 기준으로 재계산하도록 `useFormEdit`의 권한 계산 로직을 조정하세요.

In `@apps/web/app/admin/apply/new/_utils/format.ts`:
- Around line 10-29: The date helper is currently scoped too narrowly under the
new apply route, but it is now reused by edit-related code as well. Move the
shared formatting logic from parseLocalDate and formatDate into an apply-level
utility location such as apps/web/app/admin/apply/_utils/format.ts, then update
the imports in transformFormData and useFormEdit to reference the new shared
path. Keep the helper within the admin apply domain boundary rather than tying
edit to the new route’s internal _utils folder.
- Line 16: Remove the remaining debug console output from parseLocalDate() in
format.ts by deleting the console.log(date) statement. Keep the function
behavior unchanged so repeated calls from the admin apply flow no longer emit
date values to the browser console.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 88e5fff9-4d19-4518-99bb-1dc4abb7b458

📥 Commits

Reviewing files that changed from the base of the PR and between 51b5387 and 52e2ae6.

📒 Files selected for processing (10)
  • AGENTS.md
  • apps/web/app/AGENTS.md
  • apps/web/app/_api/AGENTS.md
  • apps/web/app/admin/AGENTS.md
  • apps/web/app/admin/apply/[id]/edit/_hooks/useFormEdit.ts
  • apps/web/app/admin/apply/[id]/edit/_pages/FormEditPage.tsx
  • apps/web/app/admin/apply/[id]/edit/_utils/transformFormData.ts
  • apps/web/app/admin/apply/new/_components/FormHeaderSection.tsx
  • apps/web/app/admin/apply/new/_utils/format.ts
  • packages/shared/AGENTS.md

Comment on lines +30 to 53
const { canEditForm, canEditContent } = useMemo(() => {
if (!formData.startDate || !formData.endDate) {
return {
canEditForm: false,
canEditContent: false,
};
}
const today = new Date();
today.setHours(0, 0, 0, 0);
const startDate = new Date(formData.startDate);
const startDate = parseLocalDate(formData.startDate);
startDate.setHours(0, 0, 0, 0);
const endDate = new Date(formData.endDate);
const endDate = parseLocalDate(formData.endDate);
endDate.setHours(0, 0, 0, 0);

return (
const isBeforeRecruiting = today.getTime() < startDate.getTime();
const isRecruiting =
startDate.getTime() <= today.getTime() &&
today.getTime() <= endDate.getTime()
);
today.getTime() <= endDate.getTime();

return {
canEditForm: isBeforeRecruiting || isRecruiting,
canEditContent: isBeforeRecruiting,
};
}, [formData.startDate, formData.endDate]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

권한 계산이 날짜 경계 이후에도 고정됩니다.

canEditForm/canEditContentformData.startDateformData.endDate 변경에만 묶여 있어서, 페이지를 열어 둔 채 모집 시작일/종료일 자정을 넘기면 값이 그대로 남습니다. 그 상태에서 handleSave()도 같은 캐시 값을 사용하므로, 실제로는 수정이 막혀야 하는 시점 이후에도 저장이 통과할 수 있습니다.

제안
+const getEditPermissions = (
+  startDateText?: string | null,
+  endDateText?: string | null,
+) => {
+  if (!startDateText || !endDateText) {
+    return { canEditForm: false, canEditContent: false };
+  }
+
+  const today = new Date();
+  today.setHours(0, 0, 0, 0);
+
+  const startDate = parseLocalDate(startDateText);
+  startDate.setHours(0, 0, 0, 0);
+
+  const endDate = parseLocalDate(endDateText);
+  endDate.setHours(0, 0, 0, 0);
+
+  const isBeforeRecruiting = today.getTime() < startDate.getTime();
+  const isRecruiting =
+    startDate.getTime() <= today.getTime() &&
+    today.getTime() <= endDate.getTime();
+
+  return {
+    canEditForm: isBeforeRecruiting || isRecruiting,
+    canEditContent: isBeforeRecruiting,
+  };
+};
+
-const { canEditForm, canEditContent } = useMemo(() => {
-  ...
-}, [formData.startDate, formData.endDate]);
+const { canEditForm, canEditContent } = getEditPermissions(
+  formData.startDate,
+  formData.endDate,
+);
...
 const handleSave = () => {
-  if (canEditContent && !validateBasicInfo(basicInfo)) {
+  const currentPermissions = getEditPermissions(
+    formData.startDate,
+    formData.endDate,
+  );
+
+  if (!currentPermissions.canEditForm) {
+    toast.error('더 이상 지원서를 수정할 수 없습니다.');
+    return;
+  }
+
+  if (currentPermissions.canEditContent && !validateBasicInfo(basicInfo)) {
     return;
   }

Also applies to: 98-149

🤖 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 `@apps/web/app/admin/apply/`[id]/edit/_hooks/useFormEdit.ts around lines 30 -
53, `useFormEdit`의 `useMemo`가 `formData.startDate`와 `formData.endDate`만 의존해서 자정을
넘겨도 `canEditForm`/`canEditContent`가 갱신되지 않는 문제를 수정하세요. `handleSave()`가 최신 날짜
기준으로 권한을 다시 판단하도록, 현재 날짜를 상태/의존성에 포함해 갱신되게 하거나 저장 시점에 `parseLocalDate`와 `today`를
기준으로 재계산하도록 `useFormEdit`의 권한 계산 로직을 조정하세요.

Comment on lines +10 to +29
export function parseLocalDate(date: string): Date {
const [yearText, monthText, dayText] = date.split('-');

if (!yearText || !monthText || !dayText) {
return new Date(date);
}
console.log(date);

return new Date(Number(yearText), Number(monthText) - 1, Number(dayText));
}

export function formatDate(date: Date | string | null): string {
if (!date) return '';
if (date instanceof Date) return date.toISOString().split('T')[0];
return new Date(date).toISOString().split('T')[0];

const localDate = date instanceof Date ? date : parseLocalDate(date);
const year = localDate.getFullYear();
const month = String(localDate.getMonth() + 1).padStart(2, '0');
const day = String(localDate.getDate()).padStart(2, '0');

return `${year}-${month}-${day}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

이 날짜 유틸은 apply 공용 위치로 올려주세요.

이제 이 파일이 apps/web/app/admin/apply/[id]/edit/_utils/transformFormData.ts:3apps/web/app/admin/apply/[id]/edit/_hooks/useFormEdit.ts:11-15에서도 쓰이므로, /new/_utils에 두면 edit 라우트가 new 라우트 내부 구현에 직접 결합됩니다. apps/web/app/admin/apply/_utils/format.ts 같은 apply 레벨 공용 위치로 승격하는 편이 현재 사용 범위와 경계에 맞습니다.

As per coding guidelines, "Keep admin feature code inside its domain route folder..." and "Do not move admin-only helpers to app-wide _utils just because another admin file imports them; keep the route boundary tight until reused outside admin." Based on learnings, "Keep route-specific code inside the route folder; promote it to app-wide _components, _hooks, _utils, or _constants only when it is reused across multiple routes."

🤖 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 `@apps/web/app/admin/apply/new/_utils/format.ts` around lines 10 - 29, The date
helper is currently scoped too narrowly under the new apply route, but it is now
reused by edit-related code as well. Move the shared formatting logic from
parseLocalDate and formatDate into an apply-level utility location such as
apps/web/app/admin/apply/_utils/format.ts, then update the imports in
transformFormData and useFormEdit to reference the new shared path. Keep the
helper within the admin apply domain boundary rather than tying edit to the new
route’s internal _utils folder.

Sources: Coding guidelines, Learnings

if (!yearText || !monthText || !dayText) {
return new Date(date);
}
console.log(date);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

디버그 로그는 제거해주세요.

parseLocalDate()가 초기 렌더, 권한 계산, 저장 포맷팅에서 반복 호출돼서 날짜값이 운영 브라우저 콘솔에 계속 남습니다.

제안
-  console.log(date);
📝 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
console.log(date);
🤖 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 `@apps/web/app/admin/apply/new/_utils/format.ts` at line 16, Remove the
remaining debug console output from parseLocalDate() in format.ts by deleting
the console.log(date) statement. Keep the function behavior unchanged so
repeated calls from the admin apply flow no longer emit date values to the
browser console.

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

Labels

fix 에러 픽스

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FIX] 지원서 생성 및 편집 기능 수정

1 participant