Skip to content

#113 feat: 제출 이력 패널 추가#114

Merged
suminb99 merged 11 commits into
developfrom
feat/113-submission-history
May 12, 2026
Merged

#113 feat: 제출 이력 패널 추가#114
suminb99 merged 11 commits into
developfrom
feat/113-submission-history

Conversation

@suminb99
Copy link
Copy Markdown
Contributor

⚙️ Related ISSUE Number

Related #113



📄 Work Description

  • 코드 에디터 상단 "제출이력" 버튼으로 하단 패널을 터미널 ↔ 제출 이력 패널로 전환
  • 제출 이력에서 이전 제출 코드를 에디터로 불러오기 가능 (현재 로드된 코드 하이라이트 표시)
  • 과제 제출 성공 시 제출 이력 자동 갱신 및 에디터에 최신 코드 반영
  • 코드 실행 시 터미널 패널 자동 오픈



📷 Screenshot

Screen Recording 2026-05-11 at 21 57 32



💬 To Reviewers

현재 제출 성공 여부 레이블을 성공 시 '모든 테스트 통과', 실패 시 '테스트 실패'로 지정했는데 살짝 어색한 감이 있어서 변경할 수도 있을 거 같습니다.



🔗 Reference

@suminb99 suminb99 requested a review from JiiminHa May 11, 2026 13:01
@suminb99 suminb99 linked an issue May 11, 2026 that may be closed by this pull request
@suminb99 suminb99 self-assigned this May 11, 2026
@vercel
Copy link
Copy Markdown

vercel Bot commented May 11, 2026

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

Project Deployment Actions Updated (UTC)
snow-code-client Ready Ready Preview, Comment May 12, 2026 4:00am

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 11, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ff5e407c-11b7-41d1-ae55-807aa9330592

📥 Commits

Reviewing files that changed from the base of the PR and between 956d4b3 and ff0a46e.

📒 Files selected for processing (3)
  • src/pages/submit-assignment/AssignmentSubmitPage.tsx
  • src/pages/submit-assignment/ui/CodeEditor.tsx
  • src/pages/submit-assignment/ui/SubmissionHistoryPanel.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/pages/submit-assignment/ui/SubmissionHistoryPanel.tsx
  • src/pages/submit-assignment/AssignmentSubmitPage.tsx

📝 Walkthrough

Summary by CodeRabbit

  • 새로운 기능
    • 과제 제출 이력 조회 추가 — 이전 제출 목록 불러오기
    • 제출 이력 패널 추가 — 성공/실패 상태 및 제출 시간 표시
    • 이전 코드 복원 기능 추가 — 제출 목록에서 코드 불러오기
    • 에디터에 제출 이력 토글 버튼 추가 및 하단 패널에서 터미널/이력 전환 가능
    • 제출 시 현재 코드 식별자 업데이트 및 에디터 재렌더 반영
    • 날짜 표시 개선 — "오늘"/"{n}일 전" 형식 적용

풀이

이 PR은 과제 제출 페이지에 제출 이력 조회 및 표시 기능을 추가합니다. 사용자가 이전 제출 버전을 확인하고 복구할 수 있도록 API, 스키마, 쿼리, 컴포넌트, 페이지 통합을 함께 구현합니다.

변경사항

제출 이력 조회 및 UI 통합

레이어 / 파일 설명
데이터 모델 및 스키마
src/entities/assignment/model/schemas.ts, src/shared/lib/course.ts
assignmentSubmissionHistorySchemaTAssignmentSubmissionHistory 타입을 정의하여 제출 이력의 구조(과제 ID, 제출 목록)를 명시합니다. formatDaysAgo 헬퍼 함수로 제출 시간을 "오늘", "1일 전" 형식으로 포맷팅합니다.
API 함수 및 쿼리 빌더
src/entities/assignment/api/assignmentApi.ts, src/entities/assignment/api/assignmentQueries.ts
기존 제출 히스토리 엔드포인트를 호출하는 getAssignmentSubmissionHistory API 함수를 작성하고 Zod로 검증합니다. 쿼리 빌더에서 스코프가 지정된 캐시 키(['assignments', unitId, assignmentId, 'submissionHistory'])와 함께 쿼리 옵션을 생성하며, 제출 목록을 역순으로 정렬합니다.
제출 훅 업데이트
src/features/assignment/submit-assignment/lib/useAssignmentSubmission.ts
unitId를 명시적 매개변수로 추가하고 선택적 onSubmitSuccess(codeId) 콜백을 구현합니다. 성공 후 전체 과정 쿼리 대신 제출 이력 쿼리를 무효화하고 콜백을 호출하여 페이지가 상태를 갱신하도록 합니다.
제출 이력 패널 컴포넌트
src/pages/submit-assignment/ui/SubmissionHistoryPanel.tsx
제출 목록을 렌더링하는 새 컴포넌트입니다. 각 항목은 성공/실패 상태 표시기, formatDaysAgo로 포맷된 상대 시간, 현재 코드와 일치하면 강조 표시, 복구 버튼을 포함합니다.
코드 에디터 및 터미널 UI
src/pages/submit-assignment/ui/CodeEditor.tsx, src/pages/submit-assignment/ui/Terminal.tsx
CodeEditoronTerminalToggle prop을 추가하고 헤더 레이아웃을 justify-between으로 변경하여 왼쪽에 제출이력 버튼을 배치합니다. Terminal의 루트 div에서 h-full bg-primary-black 스타일 클래스를 제거합니다.
제출 페이지 통합 및 상태 관리
src/pages/submit-assignment/AssignmentSubmitPage.tsx
currentCodeId 상태를 추가하여 현재 표시된 제출 버전을 추적하고, isTerminalOpen 상태로 터미널/이력 패널 가시성을 관리합니다. unitIdcourseDetails.units에서 파생시키고 제출 이력을 로드합니다. onTerminalToggle, handleRunCode, onRetrieve 핸들러를 구성하여 사용자 상호작용을 통합합니다. CodeEditor 키를 currentCodeId로 변경하여 다른 제출 버전 간 전환을 트리거하고, 하단 패널을 조건부로 렌더링(isTerminalOpen ? Terminal : SubmissionHistoryPanel)합니다.
설정 포맷팅
src/shared/config/endpoints.ts
엔드포인트 설정을 여러 줄로 포맷팅하되, 기능 변화는 없습니다.

예상 코드 리뷰 노력

🎯 3 (Moderate) | ⏱️ ~25분

관련 PR

제안 라벨

🧩 feature, 🎨 ui

제안 리뷰어

  • JiiminHa

간단한 팁: Zod 검증 실패 메시지가 사용자 로그에 노출되지 않도록 로깅/에러 처리 경로를 확인하세요. 관련 문서: https://github.com/colinhacks/zod#validation.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed 제목은 PR의 주요 변경사항인 '제출 이력 패널 추가'를 명확하고 간결하게 설명합니다.
Description check ✅ Passed 설명은 작업 내용, 스크린샷, 리뷰어 노트를 포함하여 변경사항과 충분히 관련이 있습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 feat/113-submission-history

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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

🧹 Nitpick comments (5)
src/features/assignment/submit-assignment/lib/useAssignmentSubmission.ts (1)

44-44: ⚡ Quick win

불필요한 non-null assertion 제거 권장

unitId는 필수 파라미터(unitId: number)로 정의되어 있어 undefined가 될 수 없습니다. Non-null assertion 연산자(!)는 불필요하며, 코드를 읽는 사람에게 혼란을 줄 수 있습니다.

🧹 개선 제안
     submit({
-      unitId: unitId!,
+      unitId,
       assignmentId: Number(assignmentId),
       code,
     });

참고: TypeScript의 non-null assertion은 컴파일러에게 "내가 확신하니 타입 체크를 건너뛰어"라고 말하는 것이므로, 타입 시스템이 이미 보장하는 경우에는 사용하지 않는 것이 좋습니다.

🤖 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/assignment/submit-assignment/lib/useAssignmentSubmission.ts` at
line 44, The non-null assertion on unitId is unnecessary; in the
useAssignmentSubmission code (look for the useAssignmentSubmission function and
the object/property where you set unitId: unitId!), remove the trailing "!" so
it reads unitId: unitId, since unitId is already declared as a required number
parameter; this simplifies the code and avoids misleading callers about
potential undefined values.
src/shared/lib/course.ts (1)

82-88: ⚡ Quick win

완전한 날짜 단위 계산을 위해 Math.floor 사용 권장

Math.round 대신 Math.floor를 사용하면 더 예측 가능한 동작을 보장합니다. 현재 코드는 시간대에 따라 결과가 달라질 수 있는데, 예를 들어:

  • 오후 2시에 13시간 전 호출 → 0일 전 (현재 오전 1시점)
  • 오전 10시에 13시간 전 호출 → 1일 전 (어제 오후 9시점)

"며칠 전"을 표현할 때는 완전히 경과한 날짓수만 계산하는 것이 자연스럽습니다. Math.floor는 이 의도를 명확하게 드러냅니다.

더불어, ensureUTC 함수는 타임존 정보를 올바르게 처리하고 있습니다. 기존 타임존 마커(Z 또는 +/-)를 유지하거나, 없을 경우 UTC로 명시적으로 표기하므로 ISO 8601 표준을 잘 따르고 있습니다.

💡 개선 제안
 export const formatDaysAgo = (isoString: string): string => {
   const midnight = (d: Date) => d.setHours(0, 0, 0, 0);
-  const days = Math.round(
+  const days = Math.floor(
     (midnight(new Date()) - midnight(new Date(ensureUTC(isoString)))) / 86400000
   );
   return days === 0 ? '오늘' : `${days}일 전`;
 };
🤖 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/lib/course.ts` around lines 82 - 88, The function formatDaysAgo
currently uses Math.round causing partial days to sometimes round up; change the
days calculation in formatDaysAgo to use Math.floor instead of Math.round so it
counts only fully elapsed days (keep the midnight helper and ensureUTC usage
as-is); update the expression that computes days (the Math.round(...) call) to
Math.floor(...) to ensure consistent "몇일 전" behavior across time zones.
src/pages/submit-assignment/ui/SubmissionHistoryPanel.tsx (3)

18-52: ⚡ Quick win

빈 제출 내역 처리를 추가하면 좋겠습니다.

현재 submissionList가 비어있을 때 빈 <ul> 만 렌더링되어 사용자에게 아무 정보도 제공하지 않습니다. 빈 상태에 대한 안내 메시지를 추가하면 UX가 개선됩니다.

💡 빈 상태 UI 추가 예시
 const SubmissionHistoryPanel = ({
   submissionList,
   currentCodeId,
   onRetrieve,
 }: SubmissionHistoryPanelProps) => {
   return (
     <section aria-label='제출 내역'>
+      {submissionList.length === 0 ? (
+        <div className='py-10 text-center text-gray-400'>
+          제출 내역이 없습니다.
+        </div>
+      ) : (
         <ul className='py-5 px-12.5 flex flex-col gap-5'>
           {submissionList.map((submission, index) => (
             <li
               key={submission.codeId}
               className='flex items-center justify-between text-white font-base font-normal'>
               {/* ... */}
             </li>
           ))}
         </ul>
+      )}
     </section>
   );
 };
🤖 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/submit-assignment/ui/SubmissionHistoryPanel.tsx` around lines 18 -
52, Add a friendly empty-state message when submissionList is empty: inside
SubmissionHistoryPanel (the component rendering submissionList) check
submissionList.length === 0 and render a visually consistent placeholder (e.g.,
a centered list item or div within the same <section> and <ul> markup) that
explains there are no submissions yet and suggests an action; ensure the
placeholder uses the same styling/spacing and accessible text (aria-label or
role) and does not break existing elements that reference currentCodeId,
formatDaysAgo, or onRetrieve.

31-41: ⚡ Quick win

Tailwind v4 패턴 개선을 고려해보세요 (선택사항).

현재 조건부 스타일링이 템플릿 리터럴과 삼항 연산자로 구현되어 있는데, 가독성 측면에서 개선할 수 있습니다. 또한 bg-[#CAC2F7] 같은 임의 색상 값은 디자인 시스템 일관성을 위해 테마 색상으로 정의하는 것이 좋습니다.

♻️ 가독성 개선 예시

CSS에서 테마 색상 정의:

`@theme` {
  --color-highlight-bg: `#CAC2F7`;
}

컴포넌트에서 사용:

               <time
                 dateTime={submission.submittedAt}
-                className={`px-3.5 py-1.5
-                  ${
-                    submission.codeId === currentCodeId
-                      ? 'bg-[`#CAC2F7`] rounded-[35px]'
-                      : 'bg-transparent'
-                  }
-                `}>
+                className={`px-3.5 py-1.5 rounded-[35px] ${
+                  submission.codeId === currentCodeId ? 'bg-highlight-bg' : 'bg-transparent'
+                }`}>
                 {formatDaysAgo(submission.submittedAt)}
               </time>
🤖 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/submit-assignment/ui/SubmissionHistoryPanel.tsx` around lines 31 -
41, Replace the inline conditional template literal on the time element in
SubmissionHistoryPanel.tsx with a clearer Tailwind v4 pattern: use a
classnames/clsx utility or your project's cn helper to compose base classes plus
a conditional class (referencing the time element, submission.submittedAt,
submission.codeId and currentCodeId) and swap the arbitrary color bg-[`#CAC2F7`]
for a design-token class (e.g., bg-highlight or a theme token like
bg-primary-200) defined in your Tailwind/theme so the conditional becomes
cn("px-3.5 py-1.5 rounded-[35px]", submission.codeId === currentCodeId &&
"bg-highlight"). Ensure formatDaysAgo(submission.submittedAt) remains unchanged.

28-28: ⚡ Quick win

상태 메시지를 상수로 분리하는 것을 권장합니다.

현재 하드코딩된 "모든 테스트 통과"와 "테스트 실패" 문자열은 유지보수성과 일관성 측면에서 개선 여지가 있습니다. PR 설명에서 언급하신 것처럼 네이밍 재검토와 함께 상수로 추출하면 좋겠습니다.

♻️ 제안: 상수 분리
+const SUBMISSION_STATUS = {
+  SUCCESS: '모든 테스트 통과',
+  FAILURE: '테스트 실패',
+} as const;
+
 const SubmissionHistoryPanel = ({
   submissionList,
   currentCodeId,
   onRetrieve,
 }: SubmissionHistoryPanelProps) => {
   return (
     <section aria-label='제출 내역'>
       <ul className='py-5 px-12.5 flex flex-col gap-5'>
         {submissionList.map((submission, index) => (
           <li
             key={submission.codeId}
             className='flex items-center justify-between text-white font-base font-normal'>
             <span className='flex items-center gap-6'>
               <StatusCircle
                 variant={submission.isSuccess ? 'PASSED' : 'FAILED'}
               />
-              {`#${submissionList.length - index} ${submission.isSuccess ? '모든 테스트 통과' : '테스트 실패'}`}
+              {`#${submissionList.length - index} ${submission.isSuccess ? SUBMISSION_STATUS.SUCCESS : SUBMISSION_STATUS.FAILURE}`}
             </span>
🤖 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/submit-assignment/ui/SubmissionHistoryPanel.tsx` at line 28,
Extract the hardcoded status strings in SubmissionHistoryPanel (the
`#${submissionList.length - index} ${submission.isSuccess ? '모든 테스트 통과' : '테스트
실패'}` usage) into named constants (e.g., TEST_SUCCESS_LABEL and
TEST_FAILURE_LABEL) placed near the top of the file or in a shared constants
module, then replace the inline literals with those constants (use the constants
inside the ternary for `submission.isSuccess`) to improve maintainability and
consistency.
🤖 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/submit-assignment/AssignmentSubmitPage.tsx`:
- Around line 57-60: The query treats 0 as falsy causing enabled:
!!currentCodeId to skip valid codeId 0; update the useQuery call for
assignmentQueries.getAssignmentCode to avoid defaulting to 0 and use an explicit
nullish check: call getAssignmentCode(Number(currentCodeId)) (or only convert
when present) and set enabled to currentCodeId != null (or currentCodeId !==
undefined && currentCodeId !== null) so a legitimate 0 is allowed while
null/undefined still disables the query; locate the useQuery invocation and the
assignmentQueries.getAssignmentCode reference to apply this change.
- Around line 42-47: The computed unitId from courseDetails.units.find(...) can
be undefined; validate it before converting with Number and before calling
useAssignmentSubmission (or any logic that consumes unitId). Update
AssignmentSubmitPage to check if unitId is present (e.g., guard/early return or
conditional rendering) and only call useAssignmentSubmission or Number(unitId)
when unitId !== undefined, or provide a sensible fallback and surface an
error/loading state so you don't pass NaN into useAssignmentSubmission.

In `@src/pages/submit-assignment/ui/CodeEditor.tsx`:
- Around line 101-107: The Button rendering in CodeEditor uses the optional prop
onTerminalToggle but is always rendered; guard the render to avoid click-time
errors by only rendering the Button when onTerminalToggle is provided (or
alternatively render a disabled Button when it is undefined). Locate the Button
instance in CodeEditor.tsx and wrap it in a conditional check for
onTerminalToggle (or set disabled and no-op handler) so clicks cannot call an
undefined function.

---

Nitpick comments:
In `@src/features/assignment/submit-assignment/lib/useAssignmentSubmission.ts`:
- Line 44: The non-null assertion on unitId is unnecessary; in the
useAssignmentSubmission code (look for the useAssignmentSubmission function and
the object/property where you set unitId: unitId!), remove the trailing "!" so
it reads unitId: unitId, since unitId is already declared as a required number
parameter; this simplifies the code and avoids misleading callers about
potential undefined values.

In `@src/pages/submit-assignment/ui/SubmissionHistoryPanel.tsx`:
- Around line 18-52: Add a friendly empty-state message when submissionList is
empty: inside SubmissionHistoryPanel (the component rendering submissionList)
check submissionList.length === 0 and render a visually consistent placeholder
(e.g., a centered list item or div within the same <section> and <ul> markup)
that explains there are no submissions yet and suggests an action; ensure the
placeholder uses the same styling/spacing and accessible text (aria-label or
role) and does not break existing elements that reference currentCodeId,
formatDaysAgo, or onRetrieve.
- Around line 31-41: Replace the inline conditional template literal on the time
element in SubmissionHistoryPanel.tsx with a clearer Tailwind v4 pattern: use a
classnames/clsx utility or your project's cn helper to compose base classes plus
a conditional class (referencing the time element, submission.submittedAt,
submission.codeId and currentCodeId) and swap the arbitrary color bg-[`#CAC2F7`]
for a design-token class (e.g., bg-highlight or a theme token like
bg-primary-200) defined in your Tailwind/theme so the conditional becomes
cn("px-3.5 py-1.5 rounded-[35px]", submission.codeId === currentCodeId &&
"bg-highlight"). Ensure formatDaysAgo(submission.submittedAt) remains unchanged.
- Line 28: Extract the hardcoded status strings in SubmissionHistoryPanel (the
`#${submissionList.length - index} ${submission.isSuccess ? '모든 테스트 통과' : '테스트
실패'}` usage) into named constants (e.g., TEST_SUCCESS_LABEL and
TEST_FAILURE_LABEL) placed near the top of the file or in a shared constants
module, then replace the inline literals with those constants (use the constants
inside the ternary for `submission.isSuccess`) to improve maintainability and
consistency.

In `@src/shared/lib/course.ts`:
- Around line 82-88: The function formatDaysAgo currently uses Math.round
causing partial days to sometimes round up; change the days calculation in
formatDaysAgo to use Math.floor instead of Math.round so it counts only fully
elapsed days (keep the midnight helper and ensureUTC usage as-is); update the
expression that computes days (the Math.round(...) call) to Math.floor(...) to
ensure consistent "몇일 전" behavior across time zones.
🪄 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

Run ID: 9737464d-f9a5-4da0-a8b5-6c129634005a

📥 Commits

Reviewing files that changed from the base of the PR and between 6766725 and 956d4b3.

⛔ Files ignored due to path filters (1)
  • src/assets/svg/retrieveIcon.svg is excluded by !**/*.svg
📒 Files selected for processing (10)
  • src/entities/assignment/api/assignmentApi.ts
  • src/entities/assignment/api/assignmentQueries.ts
  • src/entities/assignment/model/schemas.ts
  • src/features/assignment/submit-assignment/lib/useAssignmentSubmission.ts
  • src/pages/submit-assignment/AssignmentSubmitPage.tsx
  • src/pages/submit-assignment/ui/CodeEditor.tsx
  • src/pages/submit-assignment/ui/SubmissionHistoryPanel.tsx
  • src/pages/submit-assignment/ui/Terminal.tsx
  • src/shared/config/endpoints.ts
  • src/shared/lib/course.ts

Comment on lines +42 to +47
// unitId 찾기
const unitId = courseDetails.units.find((unit) =>
unit.assignments.some(
(assignment) => assignment.id === Number(assignmentId)
)
)?.id;
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

unitId가 undefined일 수 있는 상황을 처리해야 합니다.

find 메서드는 조건에 맞는 항목이 없을 경우 undefined를 반환합니다. 현재 이 unitId가 66번 라인에서 Number(unitId)로 변환되면 NaN이 되어 useAssignmentSubmission 훅에 전달됩니다. 이는 API 호출이나 로직 처리 시 예상치 못한 오류를 발생시킬 수 있습니다.

🛡️ 제안: unitId 유효성 검증 추가
   // unitId 찾기
   const unitId = courseDetails.units.find((unit) =>
     unit.assignments.some(
       (assignment) => assignment.id === Number(assignmentId)
     )
   )?.id;
+
+  if (!unitId) {
+    // unitId가 없는 경우 처리 (에러 페이지로 리다이렉트 등)
+    throw new Error('Assignment not found in any unit');
+  }

   const {data: submissionList} = useQuery({
     ...assignmentQueries.getAssignmentSubmissionHistory(
       Number(unitId),
       Number(assignmentId)
     ),
-    enabled: !!unitId,
   });

   // ...

   const {onSubmit, result, isSubmitPending, isModalOpen, closeModal} =
     useAssignmentSubmission(
       Number(unitId),
       courseDetails,
       Number(assignmentId),
       setCurrentCodeId
     );

또는 조건부 렌더링으로 처리:

+  if (!unitId) {
+    return <div>과제를 찾을 수 없습니다.</div>;
+  }
+
   const {data: submissionList} = useQuery({
     ...assignmentQueries.getAssignmentSubmissionHistory(
       Number(unitId),
       Number(assignmentId)
     ),
-    enabled: !!unitId,
   });
🤖 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/submit-assignment/AssignmentSubmitPage.tsx` around lines 42 - 47,
The computed unitId from courseDetails.units.find(...) can be undefined;
validate it before converting with Number and before calling
useAssignmentSubmission (or any logic that consumes unitId). Update
AssignmentSubmitPage to check if unitId is present (e.g., guard/early return or
conditional rendering) and only call useAssignmentSubmission or Number(unitId)
when unitId !== undefined, or provide a sensible fallback and surface an
error/loading state so you don't pass NaN into useAssignmentSubmission.

Comment on lines 57 to 60
const {data: assignmentCode} = useQuery({
...assignmentQueries.getAssignmentCode(Number(codeId || 0)),
enabled: !!codeId,
...assignmentQueries.getAssignmentCode(Number(currentCodeId || 0)),
enabled: !!currentCodeId,
});
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

currentCodeId가 0일 때의 엣지 케이스를 확인하세요.

현재 코드에서 currentCodeId || 0은 0을 기본값으로 사용하지만, 59번 라인의 enabled: !!currentCodeIdcurrentCodeId가 0일 때 false가 되어 쿼리가 실행되지 않습니다. 만약 데이터베이스에서 codeId가 0부터 시작한다면 이는 버그가 될 수 있습니다.

🔍 제안: 명시적인 null 체크
   const {data: assignmentCode} = useQuery({
-    ...assignmentQueries.getAssignmentCode(Number(currentCodeId || 0)),
-    enabled: !!currentCodeId,
+    ...assignmentQueries.getAssignmentCode(Number(currentCodeId ?? 0)),
+    enabled: currentCodeId != null,
   });

?? (nullish coalescing)과 != null 체크를 사용하면 0을 유효한 값으로 처리하면서도 undefined/null은 올바르게 필터링할 수 있습니다.

🤖 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/submit-assignment/AssignmentSubmitPage.tsx` around lines 57 - 60,
The query treats 0 as falsy causing enabled: !!currentCodeId to skip valid
codeId 0; update the useQuery call for assignmentQueries.getAssignmentCode to
avoid defaulting to 0 and use an explicit nullish check: call
getAssignmentCode(Number(currentCodeId)) (or only convert when present) and set
enabled to currentCodeId != null (or currentCodeId !== undefined &&
currentCodeId !== null) so a legitimate 0 is allowed while null/undefined still
disables the query; locate the useQuery invocation and the
assignmentQueries.getAssignmentCode reference to apply this change.

Comment thread src/pages/submit-assignment/ui/CodeEditor.tsx
@suminb99 suminb99 merged commit 73e63b3 into develop May 12, 2026
4 checks passed
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.

feat: 코드 제출 내역 창 구현

2 participants