Skip to content

feat(fe): make container and file upload component for TCManage page#3579

Open
ojongii wants to merge 6 commits into
mainfrom
t2720-make-container-and-file-upload-component-for-TCManage-page
Open

feat(fe): make container and file upload component for TCManage page#3579
ojongii wants to merge 6 commits into
mainfrom
t2720-make-container-and-file-upload-component-for-TCManage-page

Conversation

@ojongii
Copy link
Copy Markdown
Contributor

@ojongii ojongii commented May 24, 2026

Description

테스트 케이스 관리 탭들의 컨테이너와 파일 업로드 컴포넌트를 만들었습니다.
특수 문제 생성 탭은 /problem/create/?type=special에서 확인할 수 있습니다.

Additional context

closes TAS-2720


Before submitting the PR, please make sure you do the following

@ojongii ojongii requested review from sONg20NOW and woo943 May 24, 2026 02:14
@ojongii ojongii self-assigned this May 24, 2026
@ojongii ojongii added ⛳️ team-frontend 🍊squad-유자차 스쿼드 유자차 작업물입니다 preview 이 라벨이 붙어있어야 프론트엔드 Preview 환경이 생성됩니다 labels May 24, 2026
@ojongii ojongii added this to Codedang May 24, 2026
@github-project-automation github-project-automation Bot moved this to Pending ✋ in Codedang May 24, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the problem creation interface by consolidating several standalone pages into a unified TcManagePage and introducing a reusable FileUpload component. The changes also include adding an 'underline' variant to the shadcn Tabs component. Review feedback highlights several improvement opportunities for the FileUpload component, including enhancing accessibility, ensuring the multiple prop is respected during drag-and-drop, and using more unique keys for file lists. Further suggestions include resetting the active tab state in TcManagePage when the problem type changes and cleaning up unused state in the tab sub-components.

Comment on lines +26 to +33
const handleFiles = (incoming: FileList | null) => {
if (!incoming) {
return
}
const next = Array.from(incoming)
setFiles(next)
onFilesChange(next)
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

onDrop을 통해 여러 파일이 한꺼번에 들어올 수 있으므로, multiple 옵션이 false인 경우에는 첫 번째 파일만 선택되도록 로직을 보강하는 것이 안전합니다.

  const handleFiles = (incoming: FileList | null) => {
    if (!incoming) {
      return
    }
    let next = Array.from(incoming)
    if (!multiple && next.length > 0) {
      next = [next[0]]
    }
    setFiles(next)
    onFilesChange(next)
  }

Comment on lines +36 to +37
<div
onClick={() => inputRef.current?.click()}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

div 요소에 onClick 이벤트를 사용하여 버튼처럼 동작하게 할 때는 웹 접근성(A11y)을 위해 role="button"과 tabIndex={0}, 그리고 키보드 이벤트 핸들러(onKeyDown)를 추가하여 키보드 사용자가 상호작용할 수 있도록 개선하는 것이 좋습니다.

    <div
      role="button"
      tabIndex={0}
      onKeyDown={(e) => {
        if (e.key === 'Enter' || e.key === ' ') {
          e.preventDefault()
          inputRef.current?.click()
        }
      }}
      onClick={() => inputRef.current?.click()}

>
<input
ref={inputRef}
type="file"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

사용자가 올바른 형식의 파일만 선택할 수 있도록 accept 속성을 추가하는 것을 권장합니다. FileUploadProps에 accept 필드를 추가하여 외부에서 제어할 수 있게 하면 더 범용적인 컴포넌트가 됩니다.

<ul className="flex flex-col items-center gap-1">
{files.map((f) => (
<li
key={f.name}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

f.name은 파일 이름이 중복될 경우 React의 key 중복 경고를 발생시킬 수 있습니다. 파일 이름과 크기 등을 조합하여 더 고유한 키를 생성하는 것이 좋습니다.

Suggested change
key={f.name}
key={f.name + "-" + f.size}

Comment on lines +32 to +33
<Tabs
value={activeValue}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

isSpecial 값이 변경될 때 activeValue 상태가 초기화되지 않아 UI상에서 활성화된 탭이 표시되지 않는 문제가 발생할 수 있습니다. Tabs 컴포넌트에 isSpecial을 키로 부여하여 상태를 강제로 리셋하거나, useEffect를 통해 상태를 동기화하는 것이 좋습니다.

Suggested change
<Tabs
value={activeValue}
<Tabs
key={isSpecial ? 'special' : 'general'}
value={activeValue}

Comment on lines +7 to +13
const [, setFiles] = useState<File[]>([])
return (
<FileUpload
multiple
primaryText="업로드 된 테스트 생성 파일이 없습니다."
secondaryText=".in 자동 생성이 필요하면 추가해주세요."
onFilesChange={setFiles}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

TcAutoCard1에서 정의된 files 상태는 컴포넌트 내에서 사용되지 않고 있습니다. FileUpload 내부에서 이미 파일 목록 상태를 관리하고 있으므로, 부모 컴포넌트에서 이 정보가 필요하지 않다면 불필요한 상태 선언입니다.

Suggested change
const [, setFiles] = useState<File[]>([])
return (
<FileUpload
multiple
primaryText="업로드 된 테스트 생성 파일이 없습니다."
secondaryText=".in 자동 생성이 필요하면 추가해주세요."
onFilesChange={setFiles}
return (
<FileUpload
multiple
primaryText="업로드 된 테스트 생성 파일이 없습니다."
secondaryText=".in 자동 생성이 필요하면 추가해주세요."
onFilesChange={() => {}}

handleFiles(e.dataTransfer.files)
}}
className={cn(
'border-color-cool-neutral-80 bg-color-neutral-99 flex cursor-pointer flex-col items-center justify-center rounded-[12px] py-20',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

TC 인풋 자동 생성처럼 border가 먼저 적용되면 피그마 디자인처럼 안 나오는 부분이 있어서 border는 빼고 컴포넌트화 한 뒤에, 사용할 때 border를 필요에 따라 추가해야 할 것 같아요!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

확인 부탁드립니다!

@skkuding-bot
Copy link
Copy Markdown

skkuding-bot Bot commented May 27, 2026

Syncing Preview App Succeeded

Application: frontend
Revision: 01bf392bb27ce20c04c46737850ae8d94a922575
Health Status: Healthy

Open Preview | View in Argo CD

@skkuding-bot
Copy link
Copy Markdown

skkuding-bot Bot commented May 28, 2026

Syncing Preview App Succeeded

Application: frontend
Revision: ad6af10e1ecbdfa2c562fb4f9aefc98e982ee900
Health Status: Healthy

Open Preview | View in Argo CD

))}
</TabsList>
</Tabs>
{active.cards.map((Card, i) => (
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

피그마 디자인을 보면 0번째 카드는 탭과 함께 박스로 묶여야 될 것 같아요~

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

Labels

preview 이 라벨이 붙어있어야 프론트엔드 Preview 환경이 생성됩니다 🍊squad-유자차 스쿼드 유자차 작업물입니다 ⛳️ team-frontend

Projects

Status: Pending ✋

Development

Successfully merging this pull request may close these issues.

2 participants