平均年齢の変遷グラフ画面設計書
最終更新: 2026-09-10 関連 Issue: #1595(平均年齢の変遷グラフ追加)
1. 画面概要
| 項目 | 内容 |
|---|---|
| URL | /average-age |
| レンダリング方式 | SSR(動的)。Server Component(app/average-age/page.tsx)でVercel Blobからメンバーデータを取得し、算出済みの年次データをクライアントコンポーネントに渡す |
| ライブラリ | recharts(LineChart)。本リポジトリでrechartsを使った既存グラフ(DiscographyStatusChart.tsx・GeniusLinksStatusChart.tsx)はいずれもBarChartのみで、LineChartの採用は本画面が初出 |
| 対象データ | 結成年(1997年)から現在までの、毎年の結成日(9月14日)時点における在籍メンバーの平均年齢 |
2. 表示目的
結成から加入・卒業を繰り返すことでグループの平均年齢が上がったり下がったりし、それがグループのカラーの変化に表れているという仮説を、時系列の折れ線グラフとして可視化する。
3. 集計ロジック
3-1. 対象日の算出
結成日(1997-09-14、constants/group.tsのGROUP_FORMATION_DATEとして定数化)を基準に、毎年の「結成記念日」({年}-09-14)を対象日とする。
- 開始年: 1997年
- 終了年: 現在の年。ただし現在の年の結成記念日(
{現在年}-09-14)が未到来の場合(現在日 < 現在年の9/14)は、その年を対象から除外し前年までとする(起こっていない未来時点の値を確定値として表示しないため)
3-2. 在籍メンバーの判定
各対象日について、lib/member-map-utils.tsのgetActiveMemberIdsAtKeyframe(members, targetDate)(レーダーチャート時系列化 #1308 で実装済み)をそのまま転用し、在籍メンバー(joinDate <= 対象日 かつ (gradDate が null または gradDate > 対象日))を判定する。
3-3. 平均年齢の算出
対象日時点の在籍メンバー全員について、profile.dob(生年月日、必須・全メンバー公開)から満年齢を算出し、単純平均を取る。
- 満年齢の算出: 対象日の年 − 生年の年 − (対象日の月日 < 誕生日の月日 の場合は1)
- 在籍メンバーが0人の年(結成前後の理論上のエッジケース)はデータ点として出力しない
4. 画面遷移
4-1. 遷移元
Topページのナビゲーションリンク(メンバー・ユニット・関係性マップ・リリース…の横並び)に「平均年齢」リンクを追加し、/average-ageへ遷移できるようにする。関係性マップと同様、メンバーデータ全体を俯瞰する機能として、ナビゲーション上は「関係性マップ」の直後に配置する。
4-2. 復帰導線
画面上部に「Topに戻る」リンクを設置する(他の主要一覧画面と同様のパターン)。
5. 画面構成
┌───────────────────────────────────────────┐
│ 「Topに戻る」 │
├───────────────────────────────────────────┤
│ 見出し「平均年齢の変遷」+説明文 │
│ (結成から現在まで、毎年の結成記念日時点の │
│ 在籍メンバーの平均年齢の推移です) │
├───────────────────────────────────────────┤
│ │
│ 折れ線グラフ(横軸: 年、縦軸: 平均年齢) │
│ │
└───────────────────────────────────────────┘
- 単一系列の折れ線グラフとして表示する(グループ全体の平均年齢のみ、系列の切り替えUIは設けない)
- 横軸は西暦年(例:
1997,1998, …)、縦軸は平均年齢(歳、小数第1位まで) - グラフ上にカーソルを合わせると、その年の平均年齢をツールチップで表示する(
DiscographyStatusChart.tsxと同様のTooltipスタイルを踏襲)
6. コンポーネント方針
- Server Component(
app/average-age/page.tsx)でgetMembersFromBlob()によりメンバーデータを取得し、lib/average-age-utils.tsのcalculateAverageAgeTimeline()で年次データ({ year: number; averageAge: number }[])に変換してからクライアントコンポーネントに渡す(app/sync-status/page.tsxと同じ「Server Componentで計算 → Client Componentで描画」の分担パターン) - 描画は新規クライアントコンポーネント
components/AverageAgeChart.tsx('use client')で行う。recharts のLineChart・CartesianGrid・XAxis・YAxis・Tooltip・ResponsiveContainerを用い、配色・グリッド線・ツールチップのスタイルはDiscographyStatusChart.tsxを踏襲する
7. ローディング・エラー状態
| 状態 | 表示内容 |
|---|---|
| データ取得エラー(Blob未取得等) | 「メンバーデータが取得できませんでした」等のエラーメッセージ |
| 算出結果が空(理論上発生しない) | グラフの代わりに「表示できるデータがありません」を表示 |
本画面はServer Componentでレンダリング時に同期的にデータを取得するため、クライアント側のローディング状態(スピナー等)は発生しない。
改訂履歴(バージョン降順に記載)
| 版 | 更新日 | 変更内容 |
|---|---|---|
| 1.0 | 2026-09-10 | 初版作成(#1595) |