Skip to content

[feat] 問題集の詳細ページのグレードアイコンから投票できるようにする#3589

Open
river0525 wants to merge 3 commits into
stagingfrom
feature/#3583-workbook-voting
Open

[feat] 問題集の詳細ページのグレードアイコンから投票できるようにする#3589
river0525 wants to merge 3 commits into
stagingfrom
feature/#3583-workbook-voting

Conversation

@river0525
Copy link
Copy Markdown
Collaborator

@river0525 river0525 commented May 25, 2026

Summary

Changes

  • src/routes/workbooks/[slug]/+page.server.ts:
    • getVoteGradeStatistics() を並列取得して voteStatisticsMap を返す
    • isAtCoderVerified: locals.user?.is_validated === true を返す
    • voteAbsoluteGrade アクションを追加(既存の vote_actions.ts を再利用)
  • src/routes/workbooks/[slug]/+page.svelte:
    • GradeLabelVotableGrade に置き換え
    • isAtCoderVerifiedvoteStatisticsMap$derived で取得
    • 未使用になった getTaskGrade 関数と TaskGrade import を削除

Test plan

  • 問題集詳細ページでグレードアイコンをクリックすると投票ドロップダウンが開くことを確認
  • ログイン済み・AtCoder認証済みユーザーが投票でき、グレード表示がリアルタイムで更新されることを確認
  • 未ログインユーザーにはログイン/アカウント作成のドロップダウンが表示されることを確認
  • AtCoder未認証ユーザーには認証を促すドロップダウンが表示されることを確認
  • pnpm format && pnpm check && pnpm test:unit がすべてパスすることを確認

🤖 Generated with Claude Code

Summary by CodeRabbit

リリースノート

  • 新機能

    • 問題のグレード投票機能を追加。AtCoder検証済みユーザーが絶対評価を投票できるようになりました。
  • 改善

    • グレード表示コンポーネントを改善し、投票機能に対応させました。
    • フォーム検証を強化し、不正な投票リクエストを事前に防止するようにしました。

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 25, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: d0d562b1-6dc0-4856-a788-9273019409a9

📥 Commits

Reviewing files that changed from the base of the PR and between 5e05054 and b04ba39.

📒 Files selected for processing (2)
  • src/features/votes/zod/schema.ts
  • src/lib/types/auth_forms.ts

📝 Walkthrough

Walkthrough

投票入力を Zod スキーマで検証し、検証済みデータを vote アクションに渡すよう改築。workbook ページに isAtCoderVerified を追加し、grade 表示を VotableGrade コンポーネントに置き換え。seed 処理や test 型チューニングを併せて実施。

Changes

投票検証スキーマと vote アクション改築

Layer / File(s) Summary
投票スキーマ定義と vote アクション署名変更
src/features/votes/zod/schema.ts, src/features/votes/actions/vote_actions.ts
VoteAbsoluteGradeInput スキーマ新設(taskId 必須、grade は TaskGrade enum、PENDING は拒否)。vote アクションが Request から pre-validated data を受け取るよう変更し、inline validation を廃止。
Route 層でのフォーム検証追加
src/routes/workbooks/[slug]/+page.server.ts, src/routes/problems/+page.server.ts, src/routes/votes/[slug]/+page.server.ts
3 ルート全てで superValidate(request, zod4(voteAbsoluteGradeSchema)) による検証を追加。無効時は fail(BAD_REQUEST, { form })、有効時は form.data を vote アクションに渡す。workbooks ページの load に isAtCoderVerified を追加。
Workbook ページ UI コンポーネント置き換え
src/routes/workbooks/[slug]/+page.svelte
Grade 表示を GradeLabel/RelativeEvaluationBadge から VotableGrade へ切り替え。voteStatisticsMapisAtCoderVerified を derived で準備し、各タスク行に taskResult、ログイン状態、検証状態、推定 grade(統計から、なければ null)を渡す。
支援変更
prisma/seed.ts, src/features/workbooks/stores/replenishment_workbook.test.ts, src/lib/types/auth_forms.ts
Seed の classifyContest null fallback、test の vitest Mock 型修正、auth_forms の SchemaShape 型エイリアス追加。

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes


Possibly related PRs


Suggested reviewers

  • KATO-Hiro

📋 投票の「前さばき」をルートで一元化
スキーマが守り手となり、アクションは検証済みデータのみ信頼
UI も統計データで優雅に
Workbook は VotableGrade で光る✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive prisma/seed.ts の修正は投票機能に関連しないが、src/features/workbooks/stores/replenishment_workbook.test.ts や src/lib/types/auth_forms.ts の変更は全て投票機能関連の要件に基づいている。 prisma/seed.ts の contest_type フォールバック変更とreplenishment_workbook.test.tsのvitestタイプ修正について、本PRの目的との関連性を確認してください。
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed プルリクエストタイトルは、問題集詳細ページのグレードアイコンから投票できるようにするという主要な変更を正確に反映している。
Linked Issues check ✅ Passed Issue #3583の目的である「グレードアイコンから投票可能にする」「投票統計を取得・表示する」「認証状態に応じたUI提供」がすべて実装されている。

✏️ 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 feature/#3583-workbook-voting

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


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
Contributor

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

🤖 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/routes/workbooks/`[slug]/+page.server.ts:
- Around line 41-44: The page is loading global vote stats via
getVoteGradeStatistics(), causing high payload; change to fetch only stats for
tasks in this workbook by replacing the call with a new service that accepts
task IDs (e.g., getVoteGradeStatisticsByTaskIds). Collect the task IDs from
workBook.workBookTasks (map to id strings), call
getVoteGradeStatisticsByTaskIds(taskIds) where getVoteGradeStatistics() was
used, and update imports to use the new function (implement
getVoteGradeStatisticsByTaskIds in
src/features/votes/services/vote_statistics.ts to query votedGradeStatistics
where taskId in taskIds and return a map keyed by taskId).
🪄 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: 1f7da413-3c8e-4a39-8a39-d26527c8ffe1

📥 Commits

Reviewing files that changed from the base of the PR and between 2abae1a and 38b1e67.

📒 Files selected for processing (2)
  • src/routes/workbooks/[slug]/+page.server.ts
  • src/routes/workbooks/[slug]/+page.svelte

Comment thread src/routes/workbooks/[slug]/+page.server.ts
@river0525
Copy link
Copy Markdown
Collaborator Author

river0525 commented May 25, 2026

@KATO-Hiro
本PRの修正は #3588 のマージ後に行います。(リベースが必要なため)
それまではレビューをしていただかなくても問題ございません。

@KATO-Hiro
Copy link
Copy Markdown
Collaborator

@river0525
承知いたしました

先ほど、#3588 をマージいたしました
お手数をおかけしますが、リベースをお願いできますでしょうか?

Replace GradeLabel with VotableGrade so users can vote directly from the
grade icon on the workbook detail page. Fetches vote statistics in parallel
with task results and adds the voteAbsoluteGrade form action.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@river0525 river0525 force-pushed the feature/#3583-workbook-voting branch from 38b1e67 to a05606e Compare May 25, 2026 16:58
Copy link
Copy Markdown
Contributor

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

🤖 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/routes/workbooks/`[slug]/+page.server.ts:
- Around line 61-63: The voteAbsoluteGrade action currently delegates without
Superforms+Zod validation; update +page.server.ts to perform server-side
validation with Superforms and your Zod schema before calling
voteAbsoluteGradeAction: import the Zod schema for the vote form and Superforms'
superValidate, call await superValidate(request, voteAbsoluteGradeSchema) (or
equivalent) to get validated.data, then pass that validated payload into
voteAbsoluteGradeAction (e.g., voteAbsoluteGradeAction({ request, locals, data:
validated.data })), and adjust voteAbsoluteGradeAction signature to accept and
use the validated data instead of raw request parsing.
🪄 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: 3fac380a-ba96-4524-83e0-53203b2f7eb3

📥 Commits

Reviewing files that changed from the base of the PR and between 38b1e67 and a05606e.

📒 Files selected for processing (2)
  • src/routes/workbooks/[slug]/+page.server.ts
  • src/routes/workbooks/[slug]/+page.svelte

Comment thread src/routes/workbooks/[slug]/+page.server.ts
@river0525
Copy link
Copy Markdown
Collaborator Author

river0525 commented May 27, 2026

@KATO-Hiro
リベース及び、AIレビューへの対応が完了いたしました。
ご確認よろしくお願いいたします。

追加のレビューが来たので対応いたします。

Copy link
Copy Markdown
Contributor

@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

🤖 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/features/votes/zod/schema.ts`:
- Line 5: taskId の Zod スキーマは現在 z.string().min(1)
で空白のみが通ってしまうので、src/features/votes/zod/schema.ts の taskId 定義を
z.string().trim().min(1) に変更して前後の空白を除去し空文字を拒否するようにし、既存のバリデーションエラー処理(Zod
のエラーハンドリング)で不正入力を 400 レスポンスに返すことを確認してください。

In `@src/lib/types/auth_forms.ts`:
- Line 22: The current recursive type SchemaShape = { [key: string]: SchemaShape
} forces every node to be an object of the same shape and prevents leaf nodes
like { type: 'string' }; update SchemaShape to allow either a nested map or a
leaf descriptor (e.g., permit objects like { type: string } at leaves) so
form.shape can be typed as { username: { type: 'string' }, password: { type:
'string' } } without casts; change the definition of SchemaShape (and any uses)
to something like a union between a map and a leaf descriptor so callers (and
auth_forms.test.ts) no longer need as unknown casts.

In `@src/lib/utils/auth_forms.ts`:
- Line 167: createBaseAuthForm's fallback `shape: {}` breaks compatibility with
tests expecting a username/password schema; replace the empty fallback shape in
createBaseAuthForm with the expected schema (username and password entries with
type 'string') so the function returns a shape matching { username: { type:
'string' }, password: { type: 'string' } } when no custom shape is provided.
🪄 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: b1713abb-a947-4ce3-96e1-7f436b42a02d

📥 Commits

Reviewing files that changed from the base of the PR and between a05606e and 5e05054.

📒 Files selected for processing (9)
  • prisma/seed.ts
  • src/features/votes/actions/vote_actions.ts
  • src/features/votes/zod/schema.ts
  • src/features/workbooks/stores/replenishment_workbook.test.ts
  • src/lib/types/auth_forms.ts
  • src/lib/utils/auth_forms.ts
  • src/routes/problems/+page.server.ts
  • src/routes/votes/[slug]/+page.server.ts
  • src/routes/workbooks/[slug]/+page.server.ts

Comment thread src/features/votes/zod/schema.ts Outdated
Comment thread src/lib/types/auth_forms.ts Outdated
Comment thread src/lib/utils/auth_forms.ts Outdated
- Add .trim() to taskId in voteAbsoluteGradeSchema to reject whitespace-only strings
- Fix SchemaShape type from recursive self-reference to Record<string, unknown> so leaf values like { type: 'string' } are representable
- Restore shape fallback in createBaseAuthForm to { username: { type: 'string' }, password: { type: 'string' } } — was emptied when recursive type was introduced

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@river0525
Copy link
Copy Markdown
Collaborator Author

@KATO-Hiro
レビューへの対応が完了いたしました。
改めまして、ご確認よろしくお願いいたします。

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