この Build で見せるもの
「検索付き一覧画面を作る」Playbook の設計をそのまま実務ドメインに転用した完成例です。
| 機能 | 概要 |
|---|---|
| キーワード検索 | subject・body・requester を横断してフリーテキスト検索 |
| ステータスフィルタ | 未対応 / 対応中 / 解決済み / クローズ |
| 優先度フィルタ | 高 / 中 / 低 |
| カテゴリフィルタ | バグ / 機能要望 / 使い方 / その他 |
| ソート | 更新が新しい順 / 作成が新しい順 / 優先度が高い順 |
| アクティブチップ | 絞り込み中の条件をチップ表示、個別に解除できる |
| EmptyState | 0 件時に条件の種類に応じた解除ボタンを表示 |
| 詳細復帰 | 詳細から元の絞り込み一覧へ from パラメータで戻れる |
| open redirect 対策 | /contact-requests プレフィックス以外の from は弾く |
ファイル構成
| ファイル | 役割 |
|---|---|
src/app/contact-requests/page.tsx | 一覧ページ(サーバーコンポーネント) |
src/app/contact-requests/[id]/page.tsx | 詳細ページ(from パラメータ対応) |
src/components/contact-requests/ContactFilterPanel.tsx | サイドバーフィルタ(クライアント) |
src/lib/contact-requests/data.ts | データ定義・型・取得関数 |
src/lib/contact-requests/filters.ts | フィルタ・ソート純粋関数 |
src/lib/contact-requests/query.ts | URL クエリのパース・ビルド・open redirect 検証 |
設計のポイント
フィルタ状態は URL クエリで管理しています。ブラウザの戻る・シェア・リロードで同じ絞り込み状態を再現できます。
filterContactRequests と sortContactRequests は UI から完全に分離した純粋関数です。入力・出力が明確で、テストが書きやすい構造になっています。
parseContactReturnHref はサーバー側で from パラメータを検証します。/contact-requests または /contact-requests?... 以外は /contact-requests にフォールバックするため、open redirect になりません。
転用のしかた
他のドメイン(タスク管理・商品一覧・ユーザー一覧)へ転用するときは data.ts の型とデータを差し替えるだけです。filters.ts と query.ts の構造・page.tsx のレイアウトはほぼそのまま使えます。
実装の詳細な手順は関連 Playbook 「検索付き一覧画面を作る」 で段階的に説明しています。