プロフィール

arismmn timeline blog

← ブログ一覧に戻る

itemフィルタの草グラフ連動とフィルタリング不具合を修正した

機能実装デバッグUI/UX

概要

タイムラインのナビメニューにある「item」タブ(楽天市場商品情報付き投稿の絞り込み)に、2つの不具合があった。

  1. 草グラフが連動しない: itemフィルタを有効にしても、貢献グラフの表示が「全カテゴリ」のまま変わらなかった
  2. フィルタリングが1件しか表示されない: itemフィルタを有効にすると、初回SSRで表示されている1件のみが残り、他の投稿が消えてしまっていた

原因

草グラフ連動しない問題

貢献グラフコンポーネント(ContributionGraph)は、カテゴリ別のカウントマップ(どの日に何件投稿があるか)をサーバー側で計算して渡す仕組みになっている。

graph:filter イベントが発火されると、コンポーネント側で categoryData[filterType] を参照してグラフを再描画する。しかし、categoryData の初期定義に item キーが含まれておらず、undefined として扱われ all(全件)にフォールバックしていた。

また、ContributionGraph コンポーネントに itemDates という Props が存在せず、楽天市場商品情報付き投稿の日付リストがコンポーネントに渡されていなかった。

フィルタリングが1件しか表示されない問題

タイムラインには初回表示(SSR)と無限スクロールによる追加読み込みの2つのルートがある。

  • 初回SSRのHTML: data-has-product="1" 属性が付与されていた(正常)
  • 無限スクロールAPIwebapp/src/pages/api/timeline_feed.astro): data-has-product 属性が付与されていなかった(欠落)

その結果、無限スクロールで追加されたアイテムはすべて data-has-product が未定義(!== '1')と判定され、クライアント側フィルタで非表示にされていた。

修正内容

1. ContributionGraphコンポーネントへ itemDates Propsを追加

// 楽天市場商品情報付きつぶやきの日付リストを受け取るPropsを追加
itemDates?: string[];

受け取ったリストから日付別カウントマップを生成し、categoryDataitem キーとして渡すようにした。

const itemCounts = buildCategoryCountMap(itemDates);
// ...
{
  all: counts,
  blog: blogCounts,
  // ...
  item: itemCounts  // 追加
}

クライアント側の categoryData 初期値にも item: {} を追加した。

2. ページのContributionGraph呼び出しに itemDates を渡す

サーバー側で楽天市場商品情報付き投稿の日付リストがすでに productDatesForGraph として計算されていたが、コンポーネントへ渡されていなかった。これを itemDates={productDatesForGraph} として渡すよう修正した。

3. 無限スクロールAPIのアイテムに data-has-product 属性を追加

無限スクロール用APIのレスポンスHTMLにも、SSR側と同じ data-has-product 属性を付与するよう修正した。

data-has-product={(entry.entryType === 'note' && entry.product_info) ? '1' : undefined}

教訓

タイムラインフィルターは「SSR初回表示」「無限スクロールAPI」「草グラフ」の3層で構成されている。新しいフィルターを追加した際や修正する際は、3層すべてに対応が必要か確認すること。今回はSSR側のみ実装されていた属性が、無限スクロールAPI側に反映されていなかったことが原因だった。

Claude Code
Powered by
Claude Code
(使用モデル Sonnet 4.6)
← ブログ一覧に戻る