[FE-16] 지원 상세 화면 — 상태 타임라인 · 면접 회차 · 시트 조립

작업 내용 (설계 의도)

근거 설계: 20260722-공고알림앱-design-fe-web.md — “S-07 지원 상세” 근거 요구: FR-47(전이 이력이 히스토리 조회의 기준 데이터) · FR-46(면접 회차) · FR-43(종료 상태) · FR-42

변경 사항

전이 이력이 이 앱의 핵심 가치입니다(FR-47). 그 이력을 타임라인으로 드러내고, 앞선 wave가 만든 두 시트(FE-14 상태 변경 · FE-15 면접 회차)를 조립하는 화면입니다.

핵심 설계 의도:

  • 타임라인은 최신이 위입니다. 주 목적이 “현재 어디까지 왔나”의 확인이고, 상단 현재 상태 카드와 타임라인 첫 항목이 시각적으로 이어집니다. 시간순 오름차순이면 사용자가 매번 맨 아래로 스크롤해야 합니다.
  • 하단 고정 CTA는 “상태 변경” 하나입니다(토스 Clear CTA). 면접 회차 추가는 해당 섹션 안의 텍스트 버튼으로 두어 주 CTA와 경쟁시키지 않습니다.
  • 종료된 지원에서는 CTA를 렌더하지 않습니다 — disabled로 두지 않고 아예 없애고, 그 자리에 “이 지원은 종료됐어요 (불합격 · 서류전형)” 안내를 둡니다. disabled 버튼은 “왜 못 누르지”라는 질문을 만들고, 없는 버튼은 만들지 않습니다(FR-43 종료 상태 = 전이 불가).
  • 면접 회차 섹션은 독립 empty를 가집니다 — 타임라인은 생성 시 APPLIED 이력이 항상 1건 존재해 empty가 없지만, 면접 회차는 0건이 정상 상태입니다.
  • 공고로 이동하는 링크를 상단에 둡니다 — 지원 상세에서 원 공고 내용을 확인하는 흐름이 자연스럽습니다.
  • 삭제 UI를 만들지 않습니다(NFR-5).
  • P1 확장 지점: 자소서 섹션(FR-49)이 면접 회차 섹션 아래에 들어갈 자리입니다. 1단계에서는 렌더하지 않습니다.

조립 책임: 이 티켓이 시트의 열림 상태(지역 useState)와 트리거를 소유하고, 시트 컴포넌트 자체와 mutation은 FE-14·FE-15가 소유합니다. 시트가 성공하면 이 화면의 상세 쿼리가 무효화되어 타임라인·면접 목록·현재 상태가 함께 갱신됩니다.

범위: src/pages/application/ApplicationDetailPage.tsx(스텁 대체), 전용 컴포넌트(CurrentStatusCard·InterviewSection·StatusTimeline), src/api/application/detail.ts, src/hooks/application/useApplication.ts.

의존

  • FE-14 (TransitStatusSheet), FE-15 (InterviewSheet), FE-05
  • BE 의존: BE-14 (지원 조회·전이), BE-15 (면접 회차)

다이어그램

처리 흐름

sequenceDiagram
    participant U as 사용자
    participant P as ApplicationDetailPage
    participant H as useApplication
    participant T as TransitStatusSheet
    participant Q as Query 캐시
    P->>H: GET /api/applications/{id}
    H-->>P: 지원 + 히스토리 + 면접 회차
    alt 종료 상태
        P-->>U: CTA 미렌더 + "종료됐어요" 안내
    else 진행 중
        P-->>U: 하단 CTA "상태 변경"
        U->>P: CTA 클릭
        P->>T: open=true (currentStatus 전달)
        T->>Q: 전이 성공 시 상세 무효화
        Q-->>P: 재조회
        P-->>U: 타임라인 · 현재 상태 갱신
    end

클래스 의존

flowchart LR
    subgraph Page["pages/application"]
        Detail[ApplicationDetailPage]
        Cur[CurrentStatusCard]
        Iv[InterviewSection]
        TL[StatusTimeline]
    end
    subgraph Sheets["components/application"]
        TS[TransitStatusSheet]
        IS[InterviewSheet]
    end
    subgraph Domain["components/domain"]
        SC[ApplicationStatusChip]
    end
    subgraph Hooks["hooks/application"]
        H[useApplication]
    end
    Detail --> Cur
    Detail --> Iv
    Detail --> TL
    Detail --> TS
    Detail --> IS
    Detail --> H
    Cur --> SC
    TL --> SC

테스트 케이스

  • 회사명·공고명·현재 상태가 상단에 렌더된다
  • 전이 이력이 최신 항목이 위로 정렬되어 렌더된다
  • 각 이력 항목에 전이 시각과 메모가 렌더된다
  • 최초 APPLIED 이력이 타임라인 마지막(가장 아래)에 렌더된다
  • 진행 중 지원에서 하단 “상태 변경” CTA가 렌더된다
  • 종료 상태 지원에서 “상태 변경” CTA가 렌더되지 않는다 (disabled가 아니라 미존재)
  • 종료 상태 지원에 종료 안내와 종료 사유(불합격 · 단계)가 렌더된다
  • 면접 회차가 회차 순으로 일정·결과와 함께 렌더된다
  • 면접 회차가 0건이면 면접 섹션에만 empty와 추가 버튼이 렌더된다
  • “상태 변경” 클릭 시 상태 변경 시트가 열린다
  • 상태 변경 성공 후 현재 상태 카드와 타임라인이 함께 갱신된다
  • 면접 회차 추가 성공 후 면접 섹션이 갱신된다
  • 종료 상태에서는 면접 회차 추가 버튼이 렌더되지 않는다
  • 기존 면접 회차 항목 클릭 시 수정 모드 시트가 열린다
  • 공고 링크 클릭 시 /job-postings/{id}로 이동한다
  • 404 응답 시 “지원 기록을 찾을 수 없어요”와 지원 목록 이동 수단이 렌더된다
  • 로딩 중 현재 상태 카드와 타임라인 스켈레톤이 렌더된다
  • 지원 삭제 버튼이 존재하지 않는다