概要
脱React化の一環として、提出物一覧機能をReactから普通のrails viewに移行します。
#9134、#9135 、#9137 が終わってからの着手になります。
対象ファイル
Reactコンポーネント
- app/javascript/components/Products.jsx (削除)
- app/javascript/components/Product.jsx (前提として既に素のJSに移行済み)
ViewテンプレートとAPI
- app/views/products/index.html.slim (全ての提出物一覧)
- app/views/products/unchecked/index.html.slim (未チェック提出物一覧)
- app/views/products/unassigned/index.html.slim (未アサイン提出物一覧)
- app/views/products/self_assigned/index.html.slim (自分の担当提出物一覧)
- app/controllers/api/products_controller.rb (API)
関連コントローラー
- app/controllers/products_controller.rb
- app/controllers/products/unchecked_controller.rb
- app/controllers/products/unassigned_controller.rb
- app/controllers/products/self_assigned_controller.rb
実装内容
現在の実装:
- React + SWRで提出物データを取得(/api/products.json 等)
- 複数の条件による提出物一覧表示(全て、未チェック、未アサイン、自分の担当)
- ページネーション機能(50件/ページ)
- 経過日数別グループ表示(未アサインページ)
- フィルターボタン(全て/未返信)
- 空状態表示
移行後の実装:
- 各コントローラーで提出物データを取得
- Rails viewで提出物一覧をレンダリング
- kaminariでページネーション
- パーシャルで個別提出物表示(Product.jsx → product-card.js を活用)
注意点
- 複数のページで使用されている(4箇所の異なるview)
- 多様なパラメータ対応(selectedTab、checker_id、target等)
- 経過日数別グループ表示:未アサインページでの特殊なレイアウト
- フィルター機能:未返信/全て の切り替え
- ページネーション:React版50件/ページと同じ設定
- 空状態表示:複数パターンの空状態メッセージ
- UnconfirmedLink機能:一括で開くリンク
- elapsedDays.js統合:経過日数表示のサイドナビゲーション
- APIの後方互換性:/api/products.json 等の使用状況
React版の複雑な機能
- selectedTabによる分岐処理(all/unchecked/unassigned/self_assigned)
- 経過日数別グループ化(unassignedタブのみ)
- 動的フィルターURL生成
- productDeadlineDay基準の経過日数計算
- 経過日数サイドナビゲーション(elapsedDays.js使用)
参考資料
チェックリスト
事前調査・準備
- Product.jsx の素のJS移行(product-card.js)完了確認
- 依存コンポーネント(Pagination、UnconfirmedLink、LoadingListPlaceholder)の非React化状況確認
- elapsedDays.js の実装確認
- 各APIエンドポイント(/api/products、/api/products/unchecked等)の使用状況確認
API・コントローラー
- products_controller#index でデータ取得の実装
- products/unchecked_controller#index でデータ取得の実装
- products/unassigned_controller#index でデータ取得の実装(経過日数別グループ化含む)
- products/self_assigned_controller#index でデータ取得の実装
- kaminariによる50件/ページのページネーション実装
- フィルター機能(checker_id、target等)の実装
View実装
- products/index.html.slim からReact部分を削除、Rails標準レンダリングに変更
- products/unchecked/index.html.slim の修正
- products/unassigned/index.html.slim の修正(経過日数別グループ表示含む)
- products/self_assigned/index.html.slim の修正
- 提出物一覧レンダリング(product-card.js使用)の実装
- フィルターボタン(全て/未返信)の実装
- 経過日数ヘッダー表示の実装
- ページネーション表示の実装
- 空状態表示の実装(複数パターン)
JavaScript統合
- elapsedDays.js の統合(サイドナビゲーション)
- product-card.js の初期化
- UnconfirmedLink機能の実装
テスト・確認
- 全ての提出物一覧での表示確認
- 未チェック提出物一覧での表示・フィルタリング確認
- 未アサイン提出物一覧での経過日数別グループ表示確認
- 自分の担当提出物一覧での表示・フィルタリング確認
- ページネーションの動作確認(全ページ)
- 空状態表示の確認(全パターン)
- 経過日数サイドナビゲーションの確認
- 一括で開くリンクの動作確認
段階的クリーンアップ
- 不要なReactコンポーネントファイルを削除(Products.jsx)
- APIエンドポイント(/api/products 等)の削除(移行完了後、別PRでも可)
- 不要なJSライブラリ依存関係の削除(SWR、usePage等)
パフォーマンス・考慮事項
- 経過日数別グループ化でのN+1問題防止
- 50件/ページでのパフォーマンス確認
- フィルター条件でのクエリ最適化
- elapsedDays.js との統合によるJS初期化タイミング
実装の複雑度について
Products.jsx は非常に複雑なコンポーネントです:
- 4つの異なるタブモードの条件分岐
- 経過日数別グループ表示の特殊レイアウト
- 動的なAPIエンドポイント生成
- フィルター機能とURL管理
分割戦略
Phase 1: シンプルなページから開始
Issue 1: Products/index.html.slim(全ての提出物)を非React化
- 対象: app/views/products/index.html.slim のみ
- 特徴: 最もシンプル(経過日数グループなし、基本的なページネーションのみ)
- 依存関係: Product.jsx → product-card.js の前提
Issue 2: Products/unchecked/index.html.slim(未チェック提出物)を非React化
- 対象: app/views/products/unchecked/index.html.slim のみ
- 特徴: フィルターボタン(全て/未返信)追加
- 前提: Issue 1完了
Issue 3: Products/self_assigned/index.html.slim(自分の担当提出物)を非React化
- 対象: app/views/products/self_assigned/index.html.slim のみ
- 特徴: Issue 2と同様のフィルター機能
- 前提: Issue 2完了
Phase 2: 最も複雑なページ
Issue 4: Products/unassigned/index.html.slim(未アサイン提出物)を非React化
- 対象: app/views/products/unassigned/index.html.slim のみ
- 特徴: 経過日数別グループ表示、サイドナビゲーション
- 前提: Issue 1-3完了、elapsedDays.js の理解
Phase 3: クリーンアップ
Issue 5: Products.jsx関連のクリーンアップ
- 対象: APIエンドポイント削除、JSライブラリ依存関係削除
- 前提: Issue 1-4完了
概要
脱React化の一環として、提出物一覧機能をReactから普通のrails viewに移行します。
#9134、#9135 、#9137 が終わってからの着手になります。
対象ファイル
Reactコンポーネント
ViewテンプレートとAPI
関連コントローラー
実装内容
現在の実装:
移行後の実装:
注意点
React版の複雑な機能
参考資料
チェックリスト
事前調査・準備
API・コントローラー
View実装
JavaScript統合
テスト・確認
段階的クリーンアップ
パフォーマンス・考慮事項
実装の複雑度について
Products.jsx は非常に複雑なコンポーネントです:
分割戦略
Phase 1: シンプルなページから開始
Issue 1: Products/index.html.slim(全ての提出物)を非React化
Issue 2: Products/unchecked/index.html.slim(未チェック提出物)を非React化
Issue 3: Products/self_assigned/index.html.slim(自分の担当提出物)を非React化
Phase 2: 最も複雑なページ
Issue 4: Products/unassigned/index.html.slim(未アサイン提出物)を非React化
Phase 3: クリーンアップ
Issue 5: Products.jsx関連のクリーンアップ