Skip to content

feat(web): 手持ち PDF 経歴書のフォーム流し込み UI と注入機構(ADR-0024 / #524・#528)#539

Merged
yusuke0610 merged 3 commits into
mainfrom
feat/pdf-import-web
Jul 25, 2026
Merged

feat(web): 手持ち PDF 経歴書のフォーム流し込み UI と注入機構(ADR-0024 / #524・#528)#539
yusuke0610 merged 3 commits into
mainfrom
feat/pdf-import-web

Conversation

@yusuke0610

@yusuke0610 yusuke0610 commented Jul 25, 2026

Copy link
Copy Markdown
Owner

概要

ADR-0024 の最終ピース。手持ち PDF 経歴書 → フォーム自動入力の web 一式(#528)と、前提のフォーム注入機構#524)を実装する。#527 の抽出エンドポイント(POST /api/agent/resume-import/pdf)を使い、空フォームの新規ユーザが「アップロード → 抽出 → フォーム反映 → 確認 → 保存」を完走できる。抽出結果はフォーム state に注入するだけでDB は更新しない(ADR-0010)。

変更内容

#524 フォーム注入機構

  • utils/resumeImport.ts: ResumeImportResponse → CareerFormState の決定論変換(TDD
    • 見出し(full_name / career_summary / self_pr)は抽出値が非空のときだけ上書き(欠落は既存値保持)
    • experiences は抽出があればフラット値から構築して置換(深いネストは blank 既定・end_date 空=在籍中)
    • email / github_url / qualifications は抽出対象外のため現状維持

#528 web

  • hooks/useResumeImport.ts: アップロード→抽出の状態管理(TDD: loading/success/error)
  • components/forms/ResumeImportPanel.tsx: ドラッグ&ドロップ/クリック選択・ローディング・
    入力途中データがある場合の上書き確認ダイアログ・成功トースト・クライアント側 PDF 事前チェック
  • CareerResumeForm: 空フォーム時のみフォーム上部にパネルを表示(新規ユーザが最初に目にする位置)
  • api/agent.ts importResumePdf + api/client.tsFormData(multipart) 対応(CSRF/401 リフレッシュ/エラー処理を再利用)
  • messages.tsRESUME_IMPORT_MESSAGES / FALLBACK_MESSAGES.RESUME_IMPORT(リテラル直書きなし)

その他

テスト

  • resumeImport 変換 5 件(TDD)/ useResumeImport 4 件(TDD: 初期/成功/失敗/clearError)
  • E2Eresume-import.spec.ts): 空フォーム→アップロード→氏名反映+成功トースト / スキャン PDF エラー表示
  • make ci green(backend + web lint/test/build + lint-tdd)、E2E は serial(CI 相当 workers=1)で pass

依存

ADR #537 / backend #538 はマージ済み。本 PR で ADR-0024(#526-528 + #524)が完結する。

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added PDF resume import to automatically populate blank career profiles.
    • Supports file selection and drag-and-drop uploads.
    • Prompts for confirmation before replacing existing profile information.
    • Displays progress, success, and localized error messages.
  • Bug Fixes
    • Improved file upload handling for multipart requests.
  • Tests
    • Added coverage for successful imports, validation errors, form updates, and failure handling.

#527 の抽出エンドポイントを使い、空フォームの新規ユーザが PDF から入力を自動作成
できる導線を追加。抽出結果はフォーム state に注入するだけで DB は更新しない(ADR-0010)。

#524 注入機構:
- utils/resumeImport.ts: ResumeImportResponse → CareerFormState の決定論変換(TDD)。
  非空の抽出値のみ上書き(欠落は既存値保持)、experiences はフラット値から構築、
  email/github_url/qualifications は現状維持

#528 web:
- hooks/useResumeImport.ts: アップロード → 抽出の状態管理(TDD: loading/success/error)
- components/forms/ResumeImportPanel.tsx: ドラッグ&ドロップ/選択・ローディング・
  入力途中データがある場合の上書き確認ダイアログ・成功トースト
- CareerResumeForm: 空フォーム時のみフォーム上部にパネルを表示
- api/agent.ts importResumePdf + api/client.ts の FormData(multipart)対応
- messages.ts に RESUME_IMPORT_MESSAGES / FALLBACK 追加

その他:
- #523 の撤去漏れ(stryker mutate の削除済み agentModels.ts)を掃除
- E2E: 空フォーム→アップロード→反映 / スキャン PDF エラー

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added feature 新機能 web フロントエンド (web) labels Jul 25, 2026
@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@yusuke0610, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 16 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 85b3416c-976c-437a-9613-99f4646377a4

📥 Commits

Reviewing files that changed from the base of the PR and between 1a555a8 and 5ceccc2.

⛔ Files ignored due to path filters (1)
  • web/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (6)
  • web/package.json
  • web/scripts/audit-check.mjs
  • web/src/components/forms/CareerResumeForm.tsx
  • web/src/components/forms/ResumeImportPanel.tsx
  • web/src/utils/resumeImport.test.ts
  • web/src/utils/resumeImport.ts
📝 Walkthrough

Walkthrough

Adds a PDF resume import flow with multipart API support, extraction-to-form mapping, an authenticated upload panel for empty career forms, overwrite handling, error states, unit tests, and Playwright coverage.

Changes

PDF resume import

Layer / File(s) Summary
PDF upload API contract
web/src/api/*
Adds the resume-import endpoint and response type, submits PDF files as FormData, and omits the JSON content type for multipart requests.
Extracted resume form mapping
web/src/utils/resumeImport.ts, web/src/utils/resumeImport.test.ts
Maps extracted fields and experiences into career form state while preserving blank or missing existing values.
Import hook and career form UI
web/src/hooks/useResumeImport.ts, web/src/components/forms/*, web/src/constants/messages.ts
Adds upload state and error handling, renders the import panel for empty forms, supports drag-and-drop and overwrite confirmation, and applies successful imports.
Import behavior validation
web/e2e/resume-import.spec.ts, web/src/hooks/useResumeImport.test.ts, web/stryker.conf.json
Tests successful and rejected imports, hook state transitions, and updates mutation-test scope.

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

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant ResumeImportPanel
  participant useResumeImport
  participant ResumeImportAPI
  participant CareerResumeForm
  Browser->>ResumeImportPanel: Select PDF
  ResumeImportPanel->>useResumeImport: importPdf(file)
  useResumeImport->>ResumeImportAPI: POST multipart PDF
  ResumeImportAPI-->>useResumeImport: ResumeImportResponse or error
  useResumeImport-->>ResumeImportPanel: Result
  ResumeImportPanel->>CareerResumeForm: Apply mapped form state
  CareerResumeForm-->>Browser: Updated fields and toast
Loading

Possibly related issues

Possibly related PRs

Suggested labels: documentation, feature, backend, web, test

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PDF経歴書のアップロードUIとフォーム注入機構という変更内容を適切に要約しています。
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/pdf-import-web

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 added the test テスト追加・修正 label Jul 25, 2026

@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 `@web/src/components/forms/CareerResumeForm.tsx`:
- Around line 131-135: Define or reuse one complete form-content predicate
covering every user-editable field, including email, github_url, qualifications,
full_name, career_summary, self-pr, and experience values. Update
CareerResumeForm’s panel-rendering check to use it, and update
ResumeImportPanel’s overwrite-confirmation check to use the same predicate;
apply the changes at web/src/components/forms/CareerResumeForm.tsx lines 131-135
and web/src/components/forms/ResumeImportPanel.tsx lines 22-30.
- Around line 247-255: Update the ResumeImportPanel rendering condition in the
career resume form to require that the existing resume lookup has completed and
no resumeId is present, in addition to isFormEmpty. Keep the import panel hidden
while loadLatest is in progress and for users with an existing resume.

In `@web/src/components/forms/ResumeImportPanel.tsx`:
- Around line 52-60: Guard the ResumeImportPanel import entry points, especially
handleFile and openFileDialog, so they return immediately while an import is
active. Reuse the existing importing state used for aria-disabled, and ensure
both file-picker selection and drop handling cannot start another import until
the current request completes.
🪄 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: 63b7408f-3591-4393-979a-71be0b4e215a

📥 Commits

Reviewing files that changed from the base of the PR and between 6fa5ccd and 1a555a8.

📒 Files selected for processing (14)
  • web/e2e/resume-import.spec.ts
  • web/src/api/agent.ts
  • web/src/api/client.ts
  • web/src/api/paths.ts
  • web/src/api/types.ts
  • web/src/components/forms/CareerResumeForm.tsx
  • web/src/components/forms/ResumeImportPanel.module.css
  • web/src/components/forms/ResumeImportPanel.tsx
  • web/src/constants/messages.ts
  • web/src/hooks/useResumeImport.test.ts
  • web/src/hooks/useResumeImport.ts
  • web/src/utils/resumeImport.test.ts
  • web/src/utils/resumeImport.ts
  • web/stryker.conf.json
💤 Files with no reviewable changes (1)
  • web/stryker.conf.json

Comment thread web/src/components/forms/CareerResumeForm.tsx Outdated
Comment thread web/src/components/forms/CareerResumeForm.tsx
Comment thread web/src/components/forms/ResumeImportPanel.tsx
yusuke0610 and others added 2 commits July 25, 2026 16:13
…it ゲート対応)

main への PR で npm audit ゲートが新規 High advisory 2 件で落ちたため対処。

- brace-expansion(GHSA-mh99-v99m-4gvg / DoS→OOM): overrides で 5.0.8(patched)へ
  統一。openapi-typescript→@Redocly→minimatch 経由の dev 依存。非破壊更新
- react-router(GHSA-qwww-vcr4-c8h2 / RSC mode CSRF バイパス): allowlist で時限許容。
  DevForge は SPA(BrowserRouter のみ)で RSC/framework モードを使わず到達不能。
  react-router-dom 7.x に前進修正版が無く(最新 7.18.1 も脆弱範囲)、修正は v8 メジャー
  or ダウングレードのみで本 CSRF に無関係な破壊的変更のため。reviewBy 2026-10-31

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CodeRabbit 指摘(Functional Correctness)3 件。

- 空フォーム判定を全編集フィールド横断の単一述語 hasCareerFormContent に統一
  (email/github_url/qualifications も見る)。パネル表示と上書き確認で共用(Minor)
- パネル表示を !loading && !resumeId でゲート(Major)。認証ユーザは loadLatest 完了前に
  空フォームが見えるため、既存経歴書との競合(インポートがロード結果で上書きされる/
  既存経歴書に適用される)を防ぐ
- 抽出中の再アップロードを handleFile / openFileDialog で実ガード(Major)。aria-disabled は
  視覚のみで、importing 中もクリック/選択で並行リクエストでき応答の順序逆転で誤反映し得た

hasCareerFormContent の単体テスト(空/任意フィールド/配列中身)を追加。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@yusuke0610

Copy link
Copy Markdown
Owner Author

CodeRabbit 指摘 3 件を対応しました(5ceccc2)。

  • 空フォーム判定の単一述語化(Minor): email/github_url/qualifications を含む全編集フィールドを見る hasCareerFormContent に統一し、パネル表示(CareerResumeForm)と上書き確認(ResumeImportPanel)で共用。単体テストも追加。
  • ロード完了ゲート(Major): パネル表示を !loading && !resumeId && !hasCareerFormContent(form) に。認証ユーザが loadLatest 完了前にインポートして既存経歴書と競合するのを防止。
  • 同時実行ガード(Major): handleFile / openFileDialog で importing 中の再アップロードを実ガード(aria-disabled は視覚のみだった)。応答の順序逆転による誤反映を防止。

make ci green・E2E(serial)pass 済み。

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

Labels

feature 新機能 test テスト追加・修正 web フロントエンド (web)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant